Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2] rtl8187: Enable monitor mode to fix multicast reception
From: Nils Holland @ 2017-02-19 23:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: Larry Finger, Kalle Valo

The rtl8187 cards don't seem to receive multicast frames, which,
among other things, makes them fail to receive RAs in IPv6 networks.
The cause seems to be that the RTL818X_RX_CONF_MULTICAST flag doesn't
have the desired effect.

Fix the issue by setting RTL818X_RX_CONF_MONITOR instead, which puts the
card into monitor mode and resolves the problem so that multicast frames
are sucessfully passed to the kernel.

The existence of the problem and the effectiveness of the solution has
originally been confirmed on an 8187B based card with the USB id of
0bda:8197. Subsequent testing by Larry Finger on an 8187L based card,
which follows the second (8187, i.e. "non-b") code path in the driver,
has confirmed that the fix does not cause any noticeable regresssions
there either.

Signed-off-by: Nils Holland <nholland@tisys.org>
---
 drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
index 231f84db9ab0..56a8686cd367 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
@@ -946,8 +946,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 		      (7 << 13 /* RX FIFO threshold NONE */) |
 		      (7 << 10 /* MAX RX DMA */) |
 		      RTL818X_RX_CONF_RX_AUTORESETPHY |
-		      RTL818X_RX_CONF_ONLYERLPKT |
-		      RTL818X_RX_CONF_MULTICAST;
+		      RTL818X_RX_CONF_ONLYERLPKT;
 		priv->rx_conf = reg;
 		rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
 
@@ -1319,12 +1318,11 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
 		priv->rx_conf ^= RTL818X_RX_CONF_FCS;
 	if (changed_flags & FIF_CONTROL)
 		priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
-	if (changed_flags & FIF_OTHER_BSS)
-		priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
-	if (*total_flags & FIF_ALLMULTI || multicast > 0)
-		priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
+	if (*total_flags & FIF_OTHER_BSS ||
+	    *total_flags & FIF_ALLMULTI || multicast > 0)
+		priv->rx_conf |= RTL818X_RX_CONF_MONITOR;
 	else
-		priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
+		priv->rx_conf &= ~RTL818X_RX_CONF_MONITOR;
 
 	*total_flags = 0;
 
@@ -1332,10 +1330,10 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
 		*total_flags |= FIF_FCSFAIL;
 	if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
 		*total_flags |= FIF_CONTROL;
-	if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
+	if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) {
 		*total_flags |= FIF_OTHER_BSS;
-	if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
 		*total_flags |= FIF_ALLMULTI;
+	}
 
 	rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
 }
-- 
2.11.1

^ permalink raw reply related

* Re: [PATCH v2] rtl8187: Enable monitor mode to fix multicast reception
From: Larry Finger @ 2017-02-20  1:17 UTC (permalink / raw)
  To: Nils Holland, linux-wireless; +Cc: Kalle Valo
In-Reply-To: <20170219235919.GA15763@tisys.org>

On 02/19/2017 05:59 PM, Nils Holland wrote:
> The rtl8187 cards don't seem to receive multicast frames, which,
> among other things, makes them fail to receive RAs in IPv6 networks.
> The cause seems to be that the RTL818X_RX_CONF_MULTICAST flag doesn't
> have the desired effect.
>
> Fix the issue by setting RTL818X_RX_CONF_MONITOR instead, which puts the
> card into monitor mode and resolves the problem so that multicast frames
> are sucessfully passed to the kernel.
>
> The existence of the problem and the effectiveness of the solution has
> originally been confirmed on an 8187B based card with the USB id of
> 0bda:8197. Subsequent testing by Larry Finger on an 8187L based card,
> which follows the second (8187, i.e. "non-b") code path in the driver,
> has confirmed that the fix does not cause any noticeable regresssions
> there either.
>
> Signed-off-by: Nils Holland <nholland@tisys.org>

Acked-by: Larry Finger <Larry.Finger@lwfinger.net>

Thanks,

Larry

> ---
>  drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c | 16 +++++++---------
>  1 file changed, 7 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
> index 231f84db9ab0..56a8686cd367 100644
> --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
> +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
> @@ -946,8 +946,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
>  		      (7 << 13 /* RX FIFO threshold NONE */) |
>  		      (7 << 10 /* MAX RX DMA */) |
>  		      RTL818X_RX_CONF_RX_AUTORESETPHY |
> -		      RTL818X_RX_CONF_ONLYERLPKT |
> -		      RTL818X_RX_CONF_MULTICAST;
> +		      RTL818X_RX_CONF_ONLYERLPKT;
>  		priv->rx_conf = reg;
>  		rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
>
> @@ -1319,12 +1318,11 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
>  		priv->rx_conf ^= RTL818X_RX_CONF_FCS;
>  	if (changed_flags & FIF_CONTROL)
>  		priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
> -	if (changed_flags & FIF_OTHER_BSS)
> -		priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
> -	if (*total_flags & FIF_ALLMULTI || multicast > 0)
> -		priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
> +	if (*total_flags & FIF_OTHER_BSS ||
> +	    *total_flags & FIF_ALLMULTI || multicast > 0)
> +		priv->rx_conf |= RTL818X_RX_CONF_MONITOR;
>  	else
> -		priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
> +		priv->rx_conf &= ~RTL818X_RX_CONF_MONITOR;
>
>  	*total_flags = 0;
>
> @@ -1332,10 +1330,10 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
>  		*total_flags |= FIF_FCSFAIL;
>  	if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
>  		*total_flags |= FIF_CONTROL;
> -	if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
> +	if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) {
>  		*total_flags |= FIF_OTHER_BSS;
> -	if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
>  		*total_flags |= FIF_ALLMULTI;
> +	}
>
>  	rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
>  }
>

^ permalink raw reply

* [PATCHv2] ath10k: Update available channel list for 5G radio
From: c_traja @ 2017-02-20  5:06 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Tamizh chelvam

From: Tamizh chelvam <c_traja@qti.qualcomm.com>

If a 5 GHz radio is calibrated for operation in both
the low band (channels 36 to 64) and
high band(channels 100 to 169), hardware allows operations
in all the listed channels. However, if the chip has been
calibrated only for the low/high band and a high/low band
channel is configured, due to lack of calibration there will
be potentially invalid signal on those non calibrated channels.
To avoid this problem this patch introduces ath10k_low_5ghz_channel
and ath10k_high_5ghz_channel lists as separate arrays.
The channel list will be initialized depending on the low_5ghz_chan
and high_5ghz_chan values which we get from target through
wmi service ready event.

Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
---
v2:
  * Addressed Jouni and Kalle's comments

 drivers/net/wireless/ath/ath10k/core.h |    2 ++
 drivers/net/wireless/ath/ath10k/mac.c  |   55 +++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/wmi.c  |    6 ++++
 drivers/net/wireless/ath/ath10k/wmi.h  |    2 ++
 4 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 88d14be..d07d567 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -774,6 +774,8 @@ struct ath10k {
 	u32 vht_cap_info;
 	u32 num_rf_chains;
 	u32 max_spatial_stream;
+	u32 low_5ghz_chan;
+	u32 high_5ghz_chan;
 	/* protected by conf_mutex */
 	bool ani_enabled;
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3029f25..0840efb 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7623,6 +7623,38 @@ static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
 	CHAN2G(14, 2484, 0),
 };
 
+static const struct ieee80211_channel ath10k_low_5ghz_channels[] = {
+	CHAN5G(36, 5180, 0),
+	CHAN5G(40, 5200, 0),
+	CHAN5G(44, 5220, 0),
+	CHAN5G(48, 5240, 0),
+	CHAN5G(52, 5260, 0),
+	CHAN5G(56, 5280, 0),
+	CHAN5G(60, 5300, 0),
+	CHAN5G(64, 5320, 0),
+};
+
+static const struct ieee80211_channel ath10k_high_5ghz_channels[] = {
+	CHAN5G(100, 5500, 0),
+	CHAN5G(104, 5520, 0),
+	CHAN5G(108, 5540, 0),
+	CHAN5G(112, 5560, 0),
+	CHAN5G(116, 5580, 0),
+	CHAN5G(120, 5600, 0),
+	CHAN5G(124, 5620, 0),
+	CHAN5G(128, 5640, 0),
+	CHAN5G(132, 5660, 0),
+	CHAN5G(136, 5680, 0),
+	CHAN5G(140, 5700, 0),
+	CHAN5G(144, 5720, 0),
+	CHAN5G(149, 5745, 0),
+	CHAN5G(153, 5765, 0),
+	CHAN5G(157, 5785, 0),
+	CHAN5G(161, 5805, 0),
+	CHAN5G(165, 5825, 0),
+	CHAN5G(169, 5845, 0),
+};
+
 static const struct ieee80211_channel ath10k_5ghz_channels[] = {
 	CHAN5G(36, 5180, 0),
 	CHAN5G(40, 5200, 0),
@@ -8014,6 +8046,7 @@ int ath10k_mac_register(struct ath10k *ar)
 	};
 	struct ieee80211_supported_band *band;
 	void *channels;
+	int n_channels;
 	int ret;
 
 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
@@ -8049,16 +8082,30 @@ int ath10k_mac_register(struct ath10k *ar)
 	}
 
 	if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
-		channels = kmemdup(ath10k_5ghz_channels,
-				   sizeof(ath10k_5ghz_channels),
-				   GFP_KERNEL);
+		if (ar->high_5ghz_chan <= 5350) {
+			channels = kmemdup(ath10k_low_5ghz_channels,
+					   sizeof(ath10k_low_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_low_5ghz_channels);
+		} else if (ar->low_5ghz_chan >= 5490 &&
+			   ar->high_5ghz_chan <= 5885) {
+			channels = kmemdup(ath10k_high_5ghz_channels,
+					   sizeof(ath10k_high_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_high_5ghz_channels);
+		} else {
+			channels = kmemdup(ath10k_5ghz_channels,
+					   sizeof(ath10k_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_5ghz_channels);
+		}
 		if (!channels) {
 			ret = -ENOMEM;
 			goto err_free;
 		}
 
 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
-		band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels);
+		band->n_channels = n_channels;
 		band->channels = channels;
 		band->n_bitrates = ath10k_a_rates_size;
 		band->bitrates = ath10k_a_rates;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 2f1743e..b31c4f7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4593,6 +4593,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	arg->phy_capab = ev->phy_capability;
 	arg->num_rf_chains = ev->num_rf_chains;
 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
+	arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
 	arg->num_mem_reqs = ev->num_mem_reqs;
 	arg->service_map = ev->wmi_service_bitmap;
 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
@@ -4629,6 +4631,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	arg->phy_capab = ev->phy_capability;
 	arg->num_rf_chains = ev->num_rf_chains;
 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
+	arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
 	arg->num_mem_reqs = ev->num_mem_reqs;
 	arg->service_map = ev->wmi_service_bitmap;
 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
@@ -4682,6 +4686,8 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
 	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
 	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
 	ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
+	ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
+	ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
 
 	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
 			arg.service_map, arg.service_map_len);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 386aa51..78350d4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6335,6 +6335,8 @@ struct wmi_svc_rdy_ev_arg {
 	__le32 num_rf_chains;
 	__le32 eeprom_rd;
 	__le32 num_mem_reqs;
+	__le32 low_5ghz_chan;
+	__le32 high_5ghz_chan;
 	const __le32 *service_map;
 	size_t service_map_len;
 	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] ath10k: Update available channel list for 5G radio
From: c_traja @ 2017-02-20  5:08 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Tamizh chelvam

From: Tamizh chelvam <c_traja@qti.qualcomm.com>

If a 5 GHz radio is calibrated for operation in both
the low band (channels 36 to 64) and
high band(channels 100 to 169), hardware allows operations
in all the listed channels. However, if the chip has been
calibrated only for the low/high band and a high/low band
channel is configured, due to lack of calibration there will
be potentially invalid signal on those non calibrated channels.
To avoid this problem this patch introduces ath10k_low_5ghz_channel
and ath10k_high_5ghz_channel lists as separate arrays.
The channel list will be initialized depending on the low_5ghz_chan
and high_5ghz_chan values which we get from target through
wmi service ready event.

Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
---
 drivers/net/wireless/ath/ath10k/core.h |    2 ++
 drivers/net/wireless/ath/ath10k/mac.c  |   55 +++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/wmi.c  |    6 ++++
 drivers/net/wireless/ath/ath10k/wmi.h  |    2 ++
 4 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 88d14be..d07d567 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -774,6 +774,8 @@ struct ath10k {
 	u32 vht_cap_info;
 	u32 num_rf_chains;
 	u32 max_spatial_stream;
+	u32 low_5ghz_chan;
+	u32 high_5ghz_chan;
 	/* protected by conf_mutex */
 	bool ani_enabled;
 
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3029f25..0840efb 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7623,6 +7623,38 @@ static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
 	CHAN2G(14, 2484, 0),
 };
 
+static const struct ieee80211_channel ath10k_low_5ghz_channels[] = {
+	CHAN5G(36, 5180, 0),
+	CHAN5G(40, 5200, 0),
+	CHAN5G(44, 5220, 0),
+	CHAN5G(48, 5240, 0),
+	CHAN5G(52, 5260, 0),
+	CHAN5G(56, 5280, 0),
+	CHAN5G(60, 5300, 0),
+	CHAN5G(64, 5320, 0),
+};
+
+static const struct ieee80211_channel ath10k_high_5ghz_channels[] = {
+	CHAN5G(100, 5500, 0),
+	CHAN5G(104, 5520, 0),
+	CHAN5G(108, 5540, 0),
+	CHAN5G(112, 5560, 0),
+	CHAN5G(116, 5580, 0),
+	CHAN5G(120, 5600, 0),
+	CHAN5G(124, 5620, 0),
+	CHAN5G(128, 5640, 0),
+	CHAN5G(132, 5660, 0),
+	CHAN5G(136, 5680, 0),
+	CHAN5G(140, 5700, 0),
+	CHAN5G(144, 5720, 0),
+	CHAN5G(149, 5745, 0),
+	CHAN5G(153, 5765, 0),
+	CHAN5G(157, 5785, 0),
+	CHAN5G(161, 5805, 0),
+	CHAN5G(165, 5825, 0),
+	CHAN5G(169, 5845, 0),
+};
+
 static const struct ieee80211_channel ath10k_5ghz_channels[] = {
 	CHAN5G(36, 5180, 0),
 	CHAN5G(40, 5200, 0),
@@ -8014,6 +8046,7 @@ int ath10k_mac_register(struct ath10k *ar)
 	};
 	struct ieee80211_supported_band *band;
 	void *channels;
+	int n_channels;
 	int ret;
 
 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr);
@@ -8049,16 +8082,30 @@ int ath10k_mac_register(struct ath10k *ar)
 	}
 
 	if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
-		channels = kmemdup(ath10k_5ghz_channels,
-				   sizeof(ath10k_5ghz_channels),
-				   GFP_KERNEL);
+		if (ar->high_5ghz_chan <= 5350) {
+			channels = kmemdup(ath10k_low_5ghz_channels,
+					   sizeof(ath10k_low_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_low_5ghz_channels);
+		} else if (ar->low_5ghz_chan >= 5490 &&
+			   ar->high_5ghz_chan <= 5885) {
+			channels = kmemdup(ath10k_high_5ghz_channels,
+					   sizeof(ath10k_high_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_high_5ghz_channels);
+		} else {
+			channels = kmemdup(ath10k_5ghz_channels,
+					   sizeof(ath10k_5ghz_channels),
+					   GFP_KERNEL);
+			n_channels = ARRAY_SIZE(ath10k_5ghz_channels);
+		}
 		if (!channels) {
 			ret = -ENOMEM;
 			goto err_free;
 		}
 
 		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
-		band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels);
+		band->n_channels = n_channels;
 		band->channels = channels;
 		band->n_bitrates = ath10k_a_rates_size;
 		band->bitrates = ath10k_a_rates;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 2f1743e..b31c4f7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4593,6 +4593,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	arg->phy_capab = ev->phy_capability;
 	arg->num_rf_chains = ev->num_rf_chains;
 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
+	arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
 	arg->num_mem_reqs = ev->num_mem_reqs;
 	arg->service_map = ev->wmi_service_bitmap;
 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
@@ -4629,6 +4631,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
 	arg->phy_capab = ev->phy_capability;
 	arg->num_rf_chains = ev->num_rf_chains;
 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+	arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
+	arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
 	arg->num_mem_reqs = ev->num_mem_reqs;
 	arg->service_map = ev->wmi_service_bitmap;
 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
@@ -4682,6 +4686,8 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
 	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
 	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
 	ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
+	ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
+	ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
 
 	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
 			arg.service_map, arg.service_map_len);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 386aa51..78350d4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6335,6 +6335,8 @@ struct wmi_svc_rdy_ev_arg {
 	__le32 num_rf_chains;
 	__le32 eeprom_rd;
 	__le32 num_mem_reqs;
+	__le32 low_5ghz_chan;
+	__le32 high_5ghz_chan;
 	const __le32 *service_map;
 	size_t service_map_len;
 	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
-- 
1.7.9.5

^ permalink raw reply related

* RE: [PATCHv2] ath10k: Update available channel list for 5G radio
From: Raja, Tamizh Chelvam @ 2017-02-20  5:07 UTC (permalink / raw)
  To: ath10k@lists.infradead.org; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1487567190-18243-1-git-send-email-c_traja@qti.qualcomm.com>

Please ignore this patch:(

> -----Original Message-----
> From: Raja, Tamizh Chelvam
> Sent: Monday, February 20, 2017 10:37 AM
> To: ath10k@lists.infradead.org
> Cc: linux-wireless@vger.kernel.org; Raja, Tamizh Chelvam
> <c_traja@qti.qualcomm.com>
> Subject: [PATCHv2] ath10k: Update available channel list for 5G radio
>=20
> From: Tamizh chelvam <c_traja@qti.qualcomm.com>
>=20
> If a 5 GHz radio is calibrated for operation in both the low band (channe=
ls 36 to
> 64) and high band(channels 100 to 169), hardware allows operations in all=
 the
> listed channels. However, if the chip has been calibrated only for the lo=
w/high
> band and a high/low band channel is configured, due to lack of calibratio=
n
> there will be potentially invalid signal on those non calibrated channels=
.
> To avoid this problem this patch introduces ath10k_low_5ghz_channel and
> ath10k_high_5ghz_channel lists as separate arrays.
> The channel list will be initialized depending on the low_5ghz_chan and
> high_5ghz_chan values which we get from target through wmi service ready
> event.
>=20
> Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
> ---
> v2:
>   * Addressed Jouni and Kalle's comments
>=20
>  drivers/net/wireless/ath/ath10k/core.h |    2 ++
>  drivers/net/wireless/ath/ath10k/mac.c  |   55
> +++++++++++++++++++++++++++++---
>  drivers/net/wireless/ath/ath10k/wmi.c  |    6 ++++
>  drivers/net/wireless/ath/ath10k/wmi.h  |    2 ++
>  4 files changed, 61 insertions(+), 4 deletions(-)
>=20
> diff --git a/drivers/net/wireless/ath/ath10k/core.h
> b/drivers/net/wireless/ath/ath10k/core.h
> index 88d14be..d07d567 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -774,6 +774,8 @@ struct ath10k {
>  	u32 vht_cap_info;
>  	u32 num_rf_chains;
>  	u32 max_spatial_stream;
> +	u32 low_5ghz_chan;
> +	u32 high_5ghz_chan;
>  	/* protected by conf_mutex */
>  	bool ani_enabled;
>=20
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c
> b/drivers/net/wireless/ath/ath10k/mac.c
> index 3029f25..0840efb 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -7623,6 +7623,38 @@ static void
> ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
>  	CHAN2G(14, 2484, 0),
>  };
>=20
> +static const struct ieee80211_channel ath10k_low_5ghz_channels[] =3D {
> +	CHAN5G(36, 5180, 0),
> +	CHAN5G(40, 5200, 0),
> +	CHAN5G(44, 5220, 0),
> +	CHAN5G(48, 5240, 0),
> +	CHAN5G(52, 5260, 0),
> +	CHAN5G(56, 5280, 0),
> +	CHAN5G(60, 5300, 0),
> +	CHAN5G(64, 5320, 0),
> +};
> +
> +static const struct ieee80211_channel ath10k_high_5ghz_channels[] =3D {
> +	CHAN5G(100, 5500, 0),
> +	CHAN5G(104, 5520, 0),
> +	CHAN5G(108, 5540, 0),
> +	CHAN5G(112, 5560, 0),
> +	CHAN5G(116, 5580, 0),
> +	CHAN5G(120, 5600, 0),
> +	CHAN5G(124, 5620, 0),
> +	CHAN5G(128, 5640, 0),
> +	CHAN5G(132, 5660, 0),
> +	CHAN5G(136, 5680, 0),
> +	CHAN5G(140, 5700, 0),
> +	CHAN5G(144, 5720, 0),
> +	CHAN5G(149, 5745, 0),
> +	CHAN5G(153, 5765, 0),
> +	CHAN5G(157, 5785, 0),
> +	CHAN5G(161, 5805, 0),
> +	CHAN5G(165, 5825, 0),
> +	CHAN5G(169, 5845, 0),
> +};
> +
>  static const struct ieee80211_channel ath10k_5ghz_channels[] =3D {
>  	CHAN5G(36, 5180, 0),
>  	CHAN5G(40, 5200, 0),
> @@ -8014,6 +8046,7 @@ int ath10k_mac_register(struct ath10k *ar)
>  	};
>  	struct ieee80211_supported_band *band;
>  	void *channels;
> +	int n_channels;
>  	int ret;
>=20
>  	SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr); @@ -8049,16
> +8082,30 @@ int ath10k_mac_register(struct ath10k *ar)
>  	}
>=20
>  	if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
> -		channels =3D kmemdup(ath10k_5ghz_channels,
> -				   sizeof(ath10k_5ghz_channels),
> -				   GFP_KERNEL);
> +		if (ar->high_5ghz_chan <=3D 5350) {
> +			channels =3D kmemdup(ath10k_low_5ghz_channels,
> +					   sizeof(ath10k_low_5ghz_channels),
> +					   GFP_KERNEL);
> +			n_channels =3D ARRAY_SIZE(ath10k_low_5ghz_channels);
> +		} else if (ar->low_5ghz_chan >=3D 5490 &&
> +			   ar->high_5ghz_chan <=3D 5885) {
> +			channels =3D kmemdup(ath10k_high_5ghz_channels,
> +					   sizeof(ath10k_high_5ghz_channels),
> +					   GFP_KERNEL);
> +			n_channels =3D
> ARRAY_SIZE(ath10k_high_5ghz_channels);
> +		} else {
> +			channels =3D kmemdup(ath10k_5ghz_channels,
> +					   sizeof(ath10k_5ghz_channels),
> +					   GFP_KERNEL);
> +			n_channels =3D ARRAY_SIZE(ath10k_5ghz_channels);
> +		}
>  		if (!channels) {
>  			ret =3D -ENOMEM;
>  			goto err_free;
>  		}
>=20
>  		band =3D &ar->mac.sbands[NL80211_BAND_5GHZ];
> -		band->n_channels =3D ARRAY_SIZE(ath10k_5ghz_channels);
> +		band->n_channels =3D n_channels;
>  		band->channels =3D channels;
>  		band->n_bitrates =3D ath10k_a_rates_size;
>  		band->bitrates =3D ath10k_a_rates;
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c
> b/drivers/net/wireless/ath/ath10k/wmi.c
> index 2f1743e..b31c4f7 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -4593,6 +4593,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k
> *ar, u32 req_id,
>  	arg->phy_capab =3D ev->phy_capability;
>  	arg->num_rf_chains =3D ev->num_rf_chains;
>  	arg->eeprom_rd =3D ev->hal_reg_capabilities.eeprom_rd;
> +	arg->low_5ghz_chan =3D ev->hal_reg_capabilities.low_5ghz_chan;
> +	arg->high_5ghz_chan =3D ev->hal_reg_capabilities.high_5ghz_chan;
>  	arg->num_mem_reqs =3D ev->num_mem_reqs;
>  	arg->service_map =3D ev->wmi_service_bitmap;
>  	arg->service_map_len =3D sizeof(ev->wmi_service_bitmap); @@ -4629,6
> +4631,8 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32
> req_id,
>  	arg->phy_capab =3D ev->phy_capability;
>  	arg->num_rf_chains =3D ev->num_rf_chains;
>  	arg->eeprom_rd =3D ev->hal_reg_capabilities.eeprom_rd;
> +	arg->low_5ghz_chan =3D ev->hal_reg_capabilities.low_5ghz_chan;
> +	arg->high_5ghz_chan =3D ev->hal_reg_capabilities.high_5ghz_chan;
>  	arg->num_mem_reqs =3D ev->num_mem_reqs;
>  	arg->service_map =3D ev->wmi_service_bitmap;
>  	arg->service_map_len =3D sizeof(ev->wmi_service_bitmap); @@ -4682,6
> +4686,8 @@ static void ath10k_wmi_event_service_ready_work(struct
> work_struct *work)
>  	ar->phy_capability =3D __le32_to_cpu(arg.phy_capab);
>  	ar->num_rf_chains =3D __le32_to_cpu(arg.num_rf_chains);
>  	ar->hw_eeprom_rd =3D __le32_to_cpu(arg.eeprom_rd);
> +	ar->low_5ghz_chan =3D __le32_to_cpu(arg.low_5ghz_chan);
> +	ar->high_5ghz_chan =3D __le32_to_cpu(arg.high_5ghz_chan);
>=20
>  	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
>  			arg.service_map, arg.service_map_len); diff --git
> a/drivers/net/wireless/ath/ath10k/wmi.h
> b/drivers/net/wireless/ath/ath10k/wmi.h
> index 386aa51..78350d4 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.h
> +++ b/drivers/net/wireless/ath/ath10k/wmi.h
> @@ -6335,6 +6335,8 @@ struct wmi_svc_rdy_ev_arg {
>  	__le32 num_rf_chains;
>  	__le32 eeprom_rd;
>  	__le32 num_mem_reqs;
> +	__le32 low_5ghz_chan;
> +	__le32 high_5ghz_chan;
>  	const __le32 *service_map;
>  	size_t service_map_len;
>  	const struct wlan_host_mem_req
> *mem_reqs[WMI_MAX_MEM_REQS];
> --
> 1.7.9.5

^ permalink raw reply

* Re: [PATCH] Make EN2 pin optional in the TRF7970A driver
From: Heiko Schocher @ 2017-02-20  5:19 UTC (permalink / raw)
  To: netdev
  Cc: Rob Herring, Guan Ben, Mark Jonas, devicetree@vger.kernel.org,
	linux-wireless, linux-kernel@vger.kernel.org, Samuel Ortiz,
	Lauro Ramos Venancio, Aloisio Almeida Jr, Mark Rutland
In-Reply-To: <CAL_JsqKM4fEcfPekYkt-+TVNXE3nMF1AEfSHWW+3wAgdYDMXEg@mail.gmail.com>

Hello all,

Am 13.02.2017 um 22:31 schrieb Rob Herring:
> On Mon, Feb 13, 2017 at 12:38 AM, Heiko Schocher <hs@denx.de> wrote:
>> Hello Rob,
>>
>>
>> Am 10.02.2017 um 16:51 schrieb Rob Herring:
>>>
>>> On Tue, Feb 07, 2017 at 06:22:04AM +0100, Heiko Schocher wrote:
>>>>
>>>> From: Guan Ben <ben.guan@cn.bosch.com>
>>>>
>>>> Make the EN2 pin optional. This is useful for boards,
>>>> which have this pin fix wired, for example to ground.
>>>>
>>>> Signed-off-by: Guan Ben <ben.guan@cn.bosch.com>
>>>> Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
>>>> Signed-off-by: Heiko Schocher <hs@denx.de>
>>>>
>>>> ---
>>>>
>>>>    .../devicetree/bindings/net/nfc/trf7970a.txt       |  4 ++--
>>>>    drivers/nfc/trf7970a.c                             | 26
>>>> ++++++++++++----------
>>>>    2 files changed, 16 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>> b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>> index 32b35a0..5889a3d 100644
>>>> --- a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>> +++ b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt
>>>> @@ -5,8 +5,8 @@ Required properties:
>>>>    - spi-max-frequency: Maximum SPI frequency (<= 2000000).
>>>>    - interrupt-parent: phandle of parent interrupt handler.
>>>>    - interrupts: A single interrupt specifier.
>>>> -- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the
>>>> -  TRF7970A.
>>>> +- ti,enable-gpios: One or two GPIO entries used for 'EN' and 'EN2' pins
>>>> on the
>>>> +  TRF7970A. EN2 is optional.
>>>
>>>
>>> Could EN ever be optional/fixed? If so, perhaps deprecate this property
>>> and do 2 properties, one for each pin.
>>
>>
>> The hardware I have has the EN2 pin fix connected to ground. Looking
>> into http://www.ti.com/lit/ds/slos743k/slos743k.pdf page 19 table 6-3
>> and 6-4 the EN2 pin is a don;t core if EN = 1. If EN = 0 EN2 pin
>> selects between Power Down and Sleep Mode ... I see no reason why
>> this is not possible/allowed ...
>>
>> Hmm.. I do not like the idea of deprecating the "ti,enable-gpios"
>> property into 2 seperate properties ... but if this would be a reason
>> for not accepting this patch, I can do this ... How should I name
>> the 2 new properties?
>
> I guess if this ever happens, then we just add "ti,enable2-gpios" and
> ti,enable-gpios continues to point to EN. We don't need to deprecate
> anything (or maybe just deprecate having both GPIOs on single
> property).
>
> In that case,
>
> Acked-by: Rob Herring <robh@kernel.org>

gentle ping.

Are there any more comments to this patch? Is it acceptable as it
is?

Thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* Re: [PATCH] ath10k: Update available channel list for 5G radio
From: Adrian Chadd @ 2017-02-20  6:12 UTC (permalink / raw)
  To: c_traja; +Cc: ath10k@lists.infradead.org, linux-wireless@vger.kernel.org
In-Reply-To: <1487567326-18346-1-git-send-email-c_traja@qti.qualcomm.com>

hiya,

we're working on something similar to this, but based on bmi-id.

Why'd you withdraw this patch for now?


-a

^ permalink raw reply

* Re: [PATCH] ath10k: Update available channel list for 5G radio
From: Rafał Miłecki @ 2017-02-20  6:25 UTC (permalink / raw)
  To: c_traja, ath10k; +Cc: linux-wireless
In-Reply-To: <1487567326-18346-1-git-send-email-c_traja@qti.qualcomm.com>

On 02/20/2017 06:08 AM, c_traja@qti.qualcomm.com wrote:
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
> index 3029f25..0840efb 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -7623,6 +7623,38 @@ static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
>  	CHAN2G(14, 2484, 0),
>  };
>
> +static const struct ieee80211_channel ath10k_low_5ghz_channels[] = {
> +	CHAN5G(36, 5180, 0),
> +	CHAN5G(40, 5200, 0),
> +	CHAN5G(44, 5220, 0),
> +	CHAN5G(48, 5240, 0),
> +	CHAN5G(52, 5260, 0),
> +	CHAN5G(56, 5280, 0),
> +	CHAN5G(60, 5300, 0),
> +	CHAN5G(64, 5320, 0),
> +};
> +
> +static const struct ieee80211_channel ath10k_high_5ghz_channels[] = {
> +	CHAN5G(100, 5500, 0),
> +	CHAN5G(104, 5520, 0),
> +	CHAN5G(108, 5540, 0),
> +	CHAN5G(112, 5560, 0),
> +	CHAN5G(116, 5580, 0),
> +	CHAN5G(120, 5600, 0),
> +	CHAN5G(124, 5620, 0),
> +	CHAN5G(128, 5640, 0),
> +	CHAN5G(132, 5660, 0),
> +	CHAN5G(136, 5680, 0),
> +	CHAN5G(140, 5700, 0),
> +	CHAN5G(144, 5720, 0),
> +	CHAN5G(149, 5745, 0),
> +	CHAN5G(153, 5765, 0),
> +	CHAN5G(157, 5785, 0),
> +	CHAN5G(161, 5805, 0),
> +	CHAN5G(165, 5825, 0),
> +	CHAN5G(169, 5845, 0),
> +};

This isn't too flexible. What if one day you'll see hardware that supports
channels 100-144 only?

It should be much better idea to just disable unavailable channels, see what we
did in wiphy_freq_limits_apply (net-next).

^ permalink raw reply

* Re: [PATCH v2] rtl8187: Enable monitor mode to fix multicast reception
From: Rafał Miłecki @ 2017-02-20  6:35 UTC (permalink / raw)
  To: Nils Holland, linux-wireless; +Cc: Larry Finger, Kalle Valo
In-Reply-To: <20170219235919.GA15763@tisys.org>

On 02/20/2017 12:59 AM, Nils Holland wrote:
> The rtl8187 cards don't seem to receive multicast frames, which,
> among other things, makes them fail to receive RAs in IPv6 networks.
> The cause seems to be that the RTL818X_RX_CONF_MULTICAST flag doesn't
> have the desired effect.

AFAIU you have RTL8187B chipset card only, but above message describes this as
generic issue (including RTL8187 and RTL8187L).

Larry: were you able to reproduce this problem using RTL8187L? Is this
workaround needed for that chipset as well? I couldn't find clear statement.

^ permalink raw reply

* Re: [RFC V2 0/3] Pre-CAC and sharing DFS state across multiple radios
From: Johannes Berg @ 2017-02-20  9:15 UTC (permalink / raw)
  To: Vasanthakumar Thiagarajan; +Cc: linux-wireless
In-Reply-To: <1487262275-14654-1-git-send-email-vthiagar@qti.qualcomm.com>

On Thu, 2017-02-16 at 21:54 +0530, Vasanthakumar Thiagarajan wrote:
> Currently irrespective of dfs domain and radar detection activity
> pre-CAC results for a wiphy are retained till the wiphy is detroyed.
> This may not be preferred in non-ETSI dfs domain where pre-CAC is not
> explicitly mentioned in the respective DFS requirement spec. This
> patch
> set modifies the current behaviour of pre-CAC for non-ETSI domain by
> giving 2 seconds grace period for dfs master interface to start
> operating
> on the CAC completed channel.
> 
> This patch set also adds support to share dfs channel state across
> multiple radios of the same regulatory configuration.
> 

Looks fine to me - please resend as PATCH.

johannes

^ permalink raw reply

* Re: [RFC V3 0/5] cfg80211: support multiple scheduled scans
From: Johannes Berg @ 2017-02-20  9:19 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless
In-Reply-To: <1487155049-1892-1-git-send-email-arend.vanspriel@broadcom.com>

On Wed, 2017-02-15 at 10:37 +0000, Arend van Spriel wrote:
> Another review round for multiple scheduled scan support in nl80211.
> 


Looks fine to me. Not sure I see much value in splitting patches 4/5,
but whichever you prefer is fine with me.

Maybe some of the commit messages ("It mainly illustrates ...") could
use some rewording :)

johannes

^ permalink raw reply

* [PATCH 0/3] Pre-CAC and sharing DFS state across multiple radios
From: Vasanthakumar Thiagarajan @ 2017-02-20 10:39 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Vasanthakumar Thiagarajan

Currently irrespective of dfs domain and radar detection activity
pre-CAC results for a wiphy are retained till the wiphy is detroyed.
This may not be preferred in non-ETSI dfs domain where pre-CAC is not
explicitly mentioned in the respective DFS requirement spec. This patch
set modifies the current behaviour of pre-CAC for non-ETSI domain by
giving 2 seconds grace period for dfs master interface to start operating
on the CAC completed channel.

This patch set also adds support to share dfs channel state across
multiple radios of the same regulatory configuration.

Vasanthakumar Thiagarajan (3):
  cfg80211: Make pre-CAC results valid only for ETSI domain
  cfg80211: Disallow moving out of operating DFS channel in non-ETSI
  cfg80211: Share Channel DFS state across wiphys of same DFS domain

 include/uapi/linux/nl80211.h |   5 ++
 net/wireless/ap.c            |   5 ++
 net/wireless/chan.c          | 117 ++++++++++++++++++++++++++++++++++
 net/wireless/core.c          |  37 +++++++++++
 net/wireless/core.h          |  16 +++++
 net/wireless/ibss.c          |   1 +
 net/wireless/mesh.c          |   1 +
 net/wireless/mlme.c          |  50 ++++++++++++---
 net/wireless/nl80211.c       |  52 ++++++++++++++++
 net/wireless/reg.c           | 145 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/reg.h           |  36 +++++++++++
 11 files changed, 456 insertions(+), 9 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain
From: Vasanthakumar Thiagarajan @ 2017-02-20 10:39 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Vasanthakumar Thiagarajan
In-Reply-To: <1487587155-30487-1-git-send-email-vthiagar@qti.qualcomm.com>

DFS requirement for ETSI domain (section 4.7.1.4 in
ETSI EN 301 893 V1.8.1) is the only one which explicitly
states that once DFS channel is marked as available afer
the CAC, this channel will remain in available state even
moving to a different operating channel. But the same is
not explicitly stated in FCC DFS requirement. Also, Pre-CAC
requriements are not explicitly mentioned in FCC requirement.
Current implementation in keeping DFS channel in available
state is same as described in ETSI domain.

For ETSI DFS domain, this patch gives a grace period of 2 seconds
since the completion of successful CAC before moving the channel's
DFS state to 'usable' from 'available' state. The same grace period
is checked against the channel's dfs_state_entered timestamp while
deciding if a DFS channel is available for operation. There is a new
radar event, NL80211_RADAR_PRE_CAC_EXPIRED, reported when DFS channel
is moved from available to usable state after the grace period. Also
make sure the DFS channel state is reset to usable once the beaconing
operation on that channel is brought down (like stop_ap, leave_ibss
and leave_mesh) in non-ETSI domain.

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
---
 include/uapi/linux/nl80211.h |   5 +++
 net/wireless/ap.c            |   5 +++
 net/wireless/chan.c          | 101 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/core.h          |  10 +++++
 net/wireless/ibss.c          |   1 +
 net/wireless/mesh.c          |   1 +
 net/wireless/mlme.c          |  40 +++++++++++++----
 net/wireless/reg.c           |  28 ++++++++++++
 net/wireless/reg.h           |  14 ++++++
 9 files changed, 196 insertions(+), 9 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9a499b1..cd4dfef 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4913,12 +4913,17 @@ enum nl80211_smps_mode {
  *	change to the channel status.
  * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is
  *	over, channel becomes usable.
+ * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this
+ *	non-operating channel is expired and no longer valid. New CAC must
+ *	be done on this channel before starting the operation. This is not
+ *	applicable for ETSI dfs domain where pre-CAC is valid for ever.
  */
 enum nl80211_radar_event {
 	NL80211_RADAR_DETECTED,
 	NL80211_RADAR_CAC_FINISHED,
 	NL80211_RADAR_CAC_ABORTED,
 	NL80211_RADAR_NOP_FINISHED,
+	NL80211_RADAR_PRE_CAC_EXPIRED,
 };
 
 /**
diff --git a/net/wireless/ap.c b/net/wireless/ap.c
index bdad1f9..25666d3 100644
--- a/net/wireless/ap.c
+++ b/net/wireless/ap.c
@@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
 		rdev_set_qos_map(rdev, dev, NULL);
 		if (notify)
 			nl80211_send_ap_stopped(wdev);
+
+		/* Should we apply the grace period during beaconing interface
+		 * shutdown also?
+		 */
+		cfg80211_sched_dfs_chan_update(rdev);
 	}
 
 	return err;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 5497d022..099f13c 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -456,6 +456,107 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
 	return (r1 + r2 > 0);
 }
 
+/*
+ * Checks if center frequency of chan falls with in the bandwidth
+ * range of chandef.
+ */
+bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef,
+			  struct ieee80211_channel *chan)
+{
+	int width;
+	u32 cf_offset, freq;
+
+	if (chandef->chan->center_freq == chan->center_freq)
+		return true;
+
+	width = cfg80211_chandef_get_width(chandef);
+	if (width <= 20)
+		return false;
+
+	cf_offset = width / 2 - 10;
+
+	for (freq = chandef->center_freq1 - width / 2 + 10;
+	     freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) {
+		if (chan->center_freq == freq)
+			return true;
+	}
+
+	if (!chandef->center_freq2)
+		return false;
+
+	for (freq = chandef->center_freq2 - width / 2 + 10;
+	     freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) {
+		if (chan->center_freq == freq)
+			return true;
+	}
+
+	return false;
+}
+
+bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
+{
+	bool active = false;
+
+	ASSERT_WDEV_LOCK(wdev);
+
+	if (!wdev->chandef.chan)
+		return false;
+
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
+		active = wdev->beacon_interval != 0;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		active = wdev->ssid_len != 0;
+		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		active = wdev->mesh_id_len != 0;
+		break;
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_OCB:
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_P2P_DEVICE:
+	/* Can NAN type be considered as beaconing interface? */
+	case NL80211_IFTYPE_NAN:
+		break;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	case NUM_NL80211_IFTYPES:
+		WARN_ON(1);
+	}
+
+	return active;
+}
+
+bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
+				  struct ieee80211_channel *chan)
+{
+	struct wireless_dev *wdev;
+
+	ASSERT_RTNL();
+
+	if (!(chan->flags & IEEE80211_CHAN_RADAR))
+		return false;
+
+	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
+		wdev_lock(wdev);
+		if (!cfg80211_beaconing_iface_active(wdev)) {
+			wdev_unlock(wdev);
+			continue;
+		}
+
+		if (cfg80211_is_sub_chan(&wdev->chandef, chan)) {
+			wdev_unlock(wdev);
+			return true;
+		}
+		wdev_unlock(wdev);
+	}
+
+	return false;
+}
 
 static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
 					     u32 center_freq,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index efa690a..519a29e 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -466,6 +466,16 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
 cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
 			      const struct cfg80211_chan_def *chandef);
 
+void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
+
+bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
+				  struct ieee80211_channel *chan);
+
+bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev);
+
+bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef,
+			  struct ieee80211_channel *chan);
+
 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
 {
 	unsigned long end = jiffies;
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 364f900..10bf040 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -190,6 +190,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
 	if (!nowext)
 		wdev->wext.ibss.ssid_len = 0;
 #endif
+	cfg80211_sched_dfs_chan_update(rdev);
 }
 
 void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 2d8518a..ec0b1c2 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -262,6 +262,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
 		wdev->beacon_interval = 0;
 		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 		rdev_set_qos_map(rdev, dev, NULL);
+		cfg80211_sched_dfs_chan_update(rdev);
 	}
 
 	return err;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 22b3d99..cd29366 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -745,6 +745,12 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 }
 EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
+void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev)
+{
+	cancel_delayed_work(&rdev->dfs_update_channels_wk);
+	queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, 0);
+}
+
 void cfg80211_dfs_channels_update_work(struct work_struct *work)
 {
 	struct delayed_work *delayed_work = to_delayed_work(work);
@@ -755,6 +761,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 	struct wiphy *wiphy;
 	bool check_again = false;
 	unsigned long timeout, next_time = 0;
+	unsigned long time_dfs_update;
+	enum nl80211_radar_event radar_event;
 	int bandid, i;
 
 	rdev = container_of(delayed_work, struct cfg80211_registered_device,
@@ -770,11 +778,27 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 		for (i = 0; i < sband->n_channels; i++) {
 			c = &sband->channels[i];
 
-			if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
+			if (!(c->flags & IEEE80211_CHAN_RADAR))
+				continue;
+
+			if (c->dfs_state != NL80211_DFS_UNAVAILABLE &&
+			    c->dfs_state != NL80211_DFS_AVAILABLE)
 				continue;
 
-			timeout = c->dfs_state_entered + msecs_to_jiffies(
-					IEEE80211_DFS_MIN_NOP_TIME_MS);
+			if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
+				time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
+				radar_event = NL80211_RADAR_NOP_FINISHED;
+			} else {
+				if (regulatory_pre_cac_allowed(wiphy) ||
+				    cfg80211_any_wiphy_oper_chan(wiphy, c))
+					continue;
+
+				time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
+				radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
+			}
+
+			timeout = c->dfs_state_entered +
+				  msecs_to_jiffies(time_dfs_update);
 
 			if (time_after_eq(jiffies, timeout)) {
 				c->dfs_state = NL80211_DFS_USABLE;
@@ -784,8 +808,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 							NL80211_CHAN_NO_HT);
 
 				nl80211_radar_notify(rdev, &chandef,
-						     NL80211_RADAR_NOP_FINISHED,
-						     NULL, GFP_ATOMIC);
+						     radar_event, NULL,
+						     GFP_ATOMIC);
 				continue;
 			}
 
@@ -810,7 +834,6 @@ void cfg80211_radar_event(struct wiphy *wiphy,
 			  gfp_t gfp)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-	unsigned long timeout;
 
 	trace_cfg80211_radar_event(wiphy, chandef);
 
@@ -820,9 +843,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
 	 */
 	cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
 
-	timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
-	queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
-			   timeout);
+	cfg80211_sched_dfs_chan_update(rdev);
 
 	nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
 }
@@ -851,6 +872,7 @@ void cfg80211_cac_event(struct net_device *netdev,
 			  msecs_to_jiffies(wdev->cac_time_ms);
 		WARN_ON(!time_after_eq(jiffies, timeout));
 		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+		cfg80211_sched_dfs_chan_update(rdev);
 		break;
 	case NL80211_RADAR_CAC_ABORTED:
 		break;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 753efcd..e59b192 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3120,6 +3120,34 @@ bool regulatory_indoor_allowed(void)
 	return reg_is_indoor;
 }
 
+bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
+{
+	const struct ieee80211_regdomain *regd = NULL;
+	const struct ieee80211_regdomain *wiphy_regd = NULL;
+	bool pre_cac_allowed = false;
+
+	rcu_read_lock();
+
+	regd = rcu_dereference(cfg80211_regdomain);
+	wiphy_regd = rcu_dereference(wiphy->regd);
+	if (!wiphy_regd) {
+		if (regd->dfs_region == NL80211_DFS_ETSI)
+			pre_cac_allowed = true;
+
+		rcu_read_unlock();
+
+		return pre_cac_allowed;
+	}
+
+	if (regd->dfs_region == wiphy_regd->dfs_region &&
+	    wiphy_regd->dfs_region == NL80211_DFS_ETSI)
+		pre_cac_allowed = true;
+
+	rcu_read_unlock();
+
+	return pre_cac_allowed;
+}
+
 int __init regulatory_init(void)
 {
 	int err = 0;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index f6ced31..ff078f0 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -143,4 +143,18 @@ void regulatory_hint_country_ie(struct wiphy *wiphy,
  */
 bool regulatory_indoor_allowed(void);
 
+/*
+ * Grace period to timeout pre-CAC results on the dfs channels. This timeout
+ * value is used for Non-ETSI domain.
+ * TODO: May be make this timeout available through regdb?
+ */
+#define REG_PRE_CAC_EXPIRY_GRACE_MS 2000
+
+/**
+ * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain
+ * @wiphy: wiphy for which pre-CAC capability is checked.
+
+ * Pre-CAC is allowed only in ETSI domain.
+ */
+bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
 #endif  /* __NET_WIRELESS_REG_H */
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/3] cfg80211: Disallow moving out of operating DFS channel in non-ETSI
From: Vasanthakumar Thiagarajan @ 2017-02-20 10:39 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Vasanthakumar Thiagarajan
In-Reply-To: <1487587155-30487-1-git-send-email-vthiagar@qti.qualcomm.com>

For non-ETSI regulatory domain, CAC result on DFS channel
may not be valid once moving out of that channel (as done
during remain-on-channel, scannning and off-channel tx).
Running CAC on an operating DFS channel after every off-channel
operation will only add complexity and disturb the current
link. Better do not allow any off-channel switch from a DFS
operating channel in non-ETSI domain.

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
---
 net/wireless/nl80211.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d516527..b15903b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6556,6 +6556,19 @@ static int nl80211_parse_random_mac(struct nlattr **attrs,
 	return 0;
 }
 
+static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev)
+{
+	ASSERT_WDEV_LOCK(wdev);
+
+	if (!cfg80211_beaconing_iface_active(wdev))
+		return true;
+
+	if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR))
+		return true;
+
+	return regulatory_pre_cac_allowed(wdev->wiphy);
+}
+
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6681,6 +6694,25 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 
 	request->n_channels = i;
 
+	wdev_lock(wdev);
+	if (!cfg80211_off_channel_oper_allowed(wdev)) {
+		struct ieee80211_channel *chan;
+
+		if (request->n_channels != 1) {
+			wdev_unlock(wdev);
+			err = -EBUSY;
+			goto out_free;
+		}
+
+		chan = request->channels[0];
+		if (chan->center_freq != wdev->chandef.chan->center_freq) {
+			wdev_unlock(wdev);
+			err = -EBUSY;
+			goto out_free;
+		}
+	}
+	wdev_unlock(wdev);
+
 	i = 0;
 	if (n_ssids) {
 		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
@@ -9103,6 +9135,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 	struct wireless_dev *wdev = info->user_ptr[1];
 	struct cfg80211_chan_def chandef;
+	const struct cfg80211_chan_def *compat_chandef;
 	struct sk_buff *msg;
 	void *hdr;
 	u64 cookie;
@@ -9131,6 +9164,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
 	if (err)
 		return err;
 
+	wdev_lock(wdev);
+	if (!cfg80211_off_channel_oper_allowed(wdev) &&
+	    !cfg80211_chandef_identical(&wdev->chandef, &chandef)) {
+		compat_chandef = cfg80211_chandef_compatible(&wdev->chandef,
+							     &chandef);
+		if (compat_chandef != &chandef) {
+			wdev_unlock(wdev);
+			return -EBUSY;
+		}
+	}
+	wdev_unlock(wdev);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
 		return -ENOMEM;
@@ -9306,6 +9351,13 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 	if (!chandef.chan && params.offchan)
 		return -EINVAL;
 
+	wdev_lock(wdev);
+	if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) {
+		wdev_unlock(wdev);
+		return -EBUSY;
+	}
+	wdev_unlock(wdev);
+
 	params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
 	params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain
From: Vasanthakumar Thiagarajan @ 2017-02-20 10:39 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Vasanthakumar Thiagarajan
In-Reply-To: <1487587155-30487-1-git-send-email-vthiagar@qti.qualcomm.com>

Sharing DFS channel state across multiple wiphys (radios) could
be useful with multiple radios on the system. When one radio
completes CAC and markes the channel available another radio
can use this information and start beaconing without really doing
CAC.

Whenever there is a state change in dfs channel associated to
a particular wiphy the the same state change is propagated to
other wiphys having the same DFS reg domain configuration.
Also when a new wiphy is created the dfs channel state of
other existing wiphys of same DFS domain is copied.

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
---
 net/wireless/chan.c |  30 ++++++++++----
 net/wireless/core.c |  37 +++++++++++++++++
 net/wireless/core.h |   6 +++
 net/wireless/mlme.c |  10 +++++
 net/wireless/reg.c  | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/reg.h  |  22 ++++++++++
 6 files changed, 215 insertions(+), 7 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 099f13c..b8aa5a7 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -531,16 +531,11 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
 	return active;
 }
 
-bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
-				  struct ieee80211_channel *chan)
+static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy,
+					struct ieee80211_channel *chan)
 {
 	struct wireless_dev *wdev;
 
-	ASSERT_RTNL();
-
-	if (!(chan->flags & IEEE80211_CHAN_RADAR))
-		return false;
-
 	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
 		wdev_lock(wdev);
 		if (!cfg80211_beaconing_iface_active(wdev)) {
@@ -558,6 +553,27 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
 	return false;
 }
 
+bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
+				  struct ieee80211_channel *chan)
+{
+	struct cfg80211_registered_device *rdev;
+
+	ASSERT_RTNL();
+
+	if (!(chan->flags & IEEE80211_CHAN_RADAR))
+		return false;
+
+	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+		if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
+			continue;
+
+		if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan))
+			return true;
+	}
+
+	return false;
+}
+
 static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
 					     u32 center_freq,
 					     u32 bandwidth)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 04143df..a5630e9 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
 	rtnl_unlock();
 }
 
+static void cfg80211_propagate_radar_detect_wk(struct work_struct *work)
+{
+	struct cfg80211_registered_device *rdev;
+
+	rdev = container_of(work, struct cfg80211_registered_device,
+			    propagate_radar_detect_wk);
+
+	rtnl_lock();
+
+	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->radar_chandef,
+				       NL80211_DFS_UNAVAILABLE,
+				       NL80211_RADAR_DETECTED);
+
+	rtnl_unlock();
+}
+
+static void cfg80211_propagate_cac_done_wk(struct work_struct *work)
+{
+	struct cfg80211_registered_device *rdev;
+
+	rdev = container_of(work, struct cfg80211_registered_device,
+			    propagate_cac_done_wk);
+
+	rtnl_lock();
+
+	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->cac_done_chandef,
+				       NL80211_DFS_AVAILABLE,
+				       NL80211_RADAR_CAC_FINISHED);
+
+	rtnl_unlock();
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
@@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
 	spin_lock_init(&rdev->destroy_list_lock);
 	INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
 	INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
+	INIT_WORK(&rdev->propagate_radar_detect_wk,
+		  cfg80211_propagate_radar_detect_wk);
+	INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
 
 #ifdef CONFIG_CFG80211_DEFAULT_PS
 	rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -915,6 +950,8 @@ void wiphy_unregister(struct wiphy *wiphy)
 	flush_work(&rdev->destroy_work);
 	flush_work(&rdev->sched_scan_stop_wk);
 	flush_work(&rdev->mlme_unreg_wk);
+	flush_work(&rdev->propagate_radar_detect_wk);
+	flush_work(&rdev->propagate_cac_done_wk);
 
 #ifdef CONFIG_PM
 	if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 519a29e..a2fe8fc 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -97,6 +97,12 @@ struct cfg80211_registered_device {
 
 	struct work_struct sched_scan_stop_wk;
 
+	struct cfg80211_chan_def radar_chandef;
+	struct work_struct propagate_radar_detect_wk;
+
+	struct cfg80211_chan_def cac_done_chandef;
+	struct work_struct propagate_cac_done_wk;
+
 	/* must be last because of the way we do wiphy_priv(),
 	 * and it should at least be aligned to NETDEV_ALIGN */
 	struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index cd29366..01ce4a6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -810,6 +810,10 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 				nl80211_radar_notify(rdev, &chandef,
 						     radar_event, NULL,
 						     GFP_ATOMIC);
+
+				regulatory_propagate_dfs_state(wiphy, &chandef,
+							       c->dfs_state,
+							       radar_event);
 				continue;
 			}
 
@@ -846,6 +850,9 @@ void cfg80211_radar_event(struct wiphy *wiphy,
 	cfg80211_sched_dfs_chan_update(rdev);
 
 	nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
+
+	memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def));
+	queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
 }
 EXPORT_SYMBOL(cfg80211_radar_event);
 
@@ -872,6 +879,9 @@ void cfg80211_cac_event(struct net_device *netdev,
 			  msecs_to_jiffies(wdev->cac_time_ms);
 		WARN_ON(!time_after_eq(jiffies, timeout));
 		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+		memcpy(&rdev->cac_done_chandef, chandef,
+		       sizeof(struct cfg80211_chan_def));
+		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
 		cfg80211_sched_dfs_chan_update(rdev);
 		break;
 	case NL80211_RADAR_CAC_ABORTED:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e59b192..2ad5de0 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2067,6 +2067,88 @@ static void reg_set_request_processed(void)
 	return REG_REQ_IGNORE;
 }
 
+bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2)
+{
+	const struct ieee80211_regdomain *wiphy1_regd = NULL;
+	const struct ieee80211_regdomain *wiphy2_regd = NULL;
+	const struct ieee80211_regdomain *cfg80211_regd = NULL;
+	bool dfs_domain_same;
+
+	rcu_read_lock();
+
+	cfg80211_regd = rcu_dereference(cfg80211_regdomain);
+	wiphy1_regd = rcu_dereference(wiphy1->regd);
+	if (!wiphy1_regd)
+		wiphy1_regd = cfg80211_regd;
+
+	wiphy2_regd = rcu_dereference(wiphy2->regd);
+	if (!wiphy2_regd)
+		wiphy2_regd = cfg80211_regd;
+
+	dfs_domain_same = wiphy1_regd->dfs_region == wiphy2_regd->dfs_region;
+
+	rcu_read_unlock();
+
+	return dfs_domain_same;
+}
+
+static void reg_copy_dfs_chan_state(struct ieee80211_channel *dst_chan,
+				    struct ieee80211_channel *src_chan)
+{
+	if (!(dst_chan->flags & IEEE80211_CHAN_RADAR) ||
+	    !(src_chan->flags & IEEE80211_CHAN_RADAR))
+		return;
+
+	if (dst_chan->flags & IEEE80211_CHAN_DISABLED ||
+	    src_chan->flags & IEEE80211_CHAN_DISABLED)
+		return;
+
+	if (src_chan->center_freq == dst_chan->center_freq &&
+	    dst_chan->dfs_state == NL80211_DFS_USABLE) {
+		dst_chan->dfs_state = src_chan->dfs_state;
+		dst_chan->dfs_state_entered = src_chan->dfs_state_entered;
+	}
+}
+
+static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy,
+				       struct wiphy *src_wiphy)
+{
+	struct ieee80211_supported_band *src_sband, *dst_sband;
+	struct ieee80211_channel *src_chan, *dst_chan;
+	int i, j, band;
+
+	if (!reg_dfs_domain_same(dst_wiphy, src_wiphy))
+		return;
+
+	for (band = 0; band < NUM_NL80211_BANDS; band++) {
+		dst_sband = dst_wiphy->bands[band];
+		src_sband = src_wiphy->bands[band];
+		if (!dst_sband || !src_sband)
+			continue;
+
+		for (i = 0; i < dst_sband->n_channels; i++) {
+			dst_chan = &dst_sband->channels[i];
+			for (j = 0; j < src_sband->n_channels; j++) {
+				src_chan = &src_sband->channels[j];
+				reg_copy_dfs_chan_state(dst_chan, src_chan);
+			}
+		}
+	}
+}
+
+static void wiphy_all_share_dfs_chan_state(struct wiphy *wiphy)
+{
+	struct cfg80211_registered_device *rdev;
+
+	ASSERT_RTNL();
+
+	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+		if (wiphy == &rdev->wiphy)
+			continue;
+		wiphy_share_dfs_chan_state(wiphy, &rdev->wiphy);
+	}
+}
+
 /* This processes *all* regulatory hints */
 static void reg_process_hint(struct regulatory_request *reg_request)
 {
@@ -2110,6 +2192,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
 	if (treatment == REG_REQ_ALREADY_SET && wiphy &&
 	    wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
 		wiphy_update_regulatory(wiphy, reg_request->initiator);
+		wiphy_all_share_dfs_chan_state(wiphy);
 		reg_check_channels();
 	}
 
@@ -3061,6 +3144,7 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
 
 	lr = get_last_request();
 	wiphy_update_regulatory(wiphy, lr->initiator);
+	wiphy_all_share_dfs_chan_state(wiphy);
 }
 
 void wiphy_regulatory_deregister(struct wiphy *wiphy)
@@ -3148,6 +3232,39 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
 	return pre_cac_allowed;
 }
 
+void regulatory_propagate_dfs_state(struct wiphy *wiphy,
+				    struct cfg80211_chan_def *chandef,
+				    enum nl80211_dfs_state dfs_state,
+				    enum nl80211_radar_event event)
+{
+	struct cfg80211_registered_device *rdev;
+
+	ASSERT_RTNL();
+
+	if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR)))
+		return;
+
+	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+		if (wiphy == &rdev->wiphy)
+			continue;
+
+		if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
+			continue;
+
+		if (!ieee80211_get_channel(&rdev->wiphy,
+					   chandef->chan->center_freq))
+			continue;
+
+		cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
+
+		if (event == NL80211_RADAR_DETECTED ||
+		    event == NL80211_RADAR_CAC_FINISHED)
+			cfg80211_sched_dfs_chan_update(rdev);
+
+		nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
+	}
+}
+
 int __init regulatory_init(void)
 {
 	int err = 0;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index ff078f0..ca7fedf 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -157,4 +157,26 @@ void regulatory_hint_country_ie(struct wiphy *wiphy,
  * Pre-CAC is allowed only in ETSI domain.
  */
 bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
+
+/**
+ * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys
+ * @wiphy - wiphy on which radar is detected and the event will be propagated
+ *	to other available wiphys having the same DFS domain
+ * @chandef - Channel definition of radar detected channel
+ * @dfs_state - DFS channel state to be set
+ * @event - Type of radar event which triggered this DFS state change
+ *
+ * This function should be called with rtnl lock held.
+ */
+void regulatory_propagate_dfs_state(struct wiphy *wiphy,
+				    struct cfg80211_chan_def *chandef,
+				    enum nl80211_dfs_state dfs_state,
+				    enum nl80211_radar_event event);
+
+/**
+ * reg_dfs_domain_same - Checks if both wiphy have same DFS domain configured
+ * @wiphy1 - wiphy it's dfs_region to be checked against that of wiphy2
+ * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1
+ */
+bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
 #endif  /* __NET_WIRELESS_REG_H */
-- 
1.9.1

^ permalink raw reply related

* Re: [RFC V3 0/5] cfg80211: support multiple scheduled scans
From: Arend Van Spriel @ 2017-02-20 10:55 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1487582393.5474.2.camel@sipsolutions.net>

On 20-2-2017 10:19, Johannes Berg wrote:
> On Wed, 2017-02-15 at 10:37 +0000, Arend van Spriel wrote:
>> Another review round for multiple scheduled scan support in nl80211.
>>
> 
> 
> Looks fine to me. Not sure I see much value in splitting patches 4/5,
> but whichever you prefer is fine with me.

I was a bit in doubt on granularity of the patches. Let's see what I
make of it when submitting a formal patch ;-)

> Maybe some of the commit messages ("It mainly illustrates ...") could
> use some rewording :)

Will do.

Thanks,
Arend

^ permalink raw reply

* [PATCH] mac80211: fix packet statistics for fast-RX
From: Johannes Berg @ 2017-02-20 13:17 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

When adding per-CPU statistics, which added statistics back
to mac80211 for the fast-RX path, I evidently forgot to add
the "stats->packets++" line. The reason for that is likely
that I didn't see it since it's done in defragmentation for
the regular RX path.

Add the missing line to properly count received packets in
the fast-RX case.

Fixes: c9c5962b56c1 ("mac80211: enable collecting station statistics per-CPU")
Reported-by: Oren Givon <oren.givon@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 50ca3828b124..a8443d8bc233 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3880,6 +3880,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
 	stats->last_rate = sta_stats_encode_rate(status);
 
 	stats->fragments++;
+	stats->packets++;
 
 	if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
 		stats->last_signal = status->signal;
-- 
2.9.3

^ permalink raw reply related

* ANNOUNCE: Netdev 2.1 update Feb 20
From: Jamal Hadi Salim @ 2017-02-20 13:18 UTC (permalink / raw)
  To: netdev@vger.kernel.org
  Cc: netfilter-devel, netfilter, info, linux-wireless, tech-committee,
	David Miller, Stephen Jaworski, lwn, people, Brenda Butler



A few announcements:
-Registration is open. Register early so we can plan better.
https://onlineregistrations.ca/netdev21/

hotel (If you can get the hotel cheaper online than conference
rates please send us email, dont book ):
http://www.netdevconf.org/2.1/hotel.html

- We are pleased to announce our first Gold sponsor! We welcome back
Redhat as sponsors and thank them for their commitment to the netdev
community!

- We are pleased to announce our first Platinum sponsor: Cumulus
Networks. Cumulus has always been there for the netdev Community from
our very first conference.  Thank you Cumulus!

- Our hard working tech committee has accepted another proposal. This
time veteran netdever Stephen Hemminger digs into the semantics of
names. Names have consequences he says.

Title: What's in a name?
---
Network device names have existed from the earliest days of Unix
networking and their usage has evolved. This talk is a look at some of
the issues with network device names. kernel developers often think the
problem is a userspace issue and nothing can be done but the names are
a key part of the existing ABI.

In the talk, I will cover how the choice of naming policy interacts
with applications and cloud environments, what current expectations
are, and how this interacts with cloud infrastructure. There is no
solution but there are several things that can be done to improve
the user experience. Will also give examples including Amazon, Azure,
Google Compute as well as other non-Linux environments.
-----

Please note that The Call for Proposals is still open, submit early
to avoid the hazards of last minute traffic. Refer to:
http://netdevconf.org/2.1/submit-proposal.html

cheers,
jamal

^ permalink raw reply

* [PATCH 3/6] mac80211: fix power saving clients handling in iwlwifi
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <20170220132439.16064-1-johannes@sipsolutions.net>

From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>

iwlwifi now supports RSS and can't let mac80211 track the
PS state based on the Rx frames since they can come out of
order. iwlwifi is now advertising AP_LINK_PS, and uses
explicit notifications to teach mac80211 about the PS state
of the stations and the PS poll / uAPSD trigger frames
coming our way from the peers.

Because of that, the TIM stopped being maintained in
mac80211. I tried to fix this in commit c68df2e7be0c
("mac80211: allow using AP_LINK_PS with mac80211-generated TIM IE")
but that was later reverted by Felix in commit 6c18a6b4e799
("Revert "mac80211: allow using AP_LINK_PS with mac80211-generated TIM IE")
since it broke drivers that do not implement set_tim.

Since none of the drivers that set AP_LINK_PS have the
set_tim() handler set besides iwlwifi, I can bail out in
__sta_info_recalc_tim if AP_LINK_PS AND .set_tim is not
implemented.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4774e663a411..8bb99d299cda 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
 	}
 
 	/* No need to do anything if the driver does all */
-	if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
+	if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim)
 		return;
 
 	if (sta->dead)
-- 
2.9.3

^ permalink raw reply related

* [PATCH 1/6] cfg80211: combine two nested ifs into a single condition
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Combine two instances of having two nested if statements
into a single one with a combined condition to reduce the
indentation.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/core.c | 12 ++++++------
 net/wireless/util.c | 10 +++++-----
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/net/wireless/core.c b/net/wireless/core.c
index 04143df20f7f..76e664144c8e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1216,12 +1216,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 		 */
 		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
 		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
-		    rdev->ops->set_power_mgmt)
-			if (rdev_set_power_mgmt(rdev, dev, wdev->ps,
-						wdev->ps_timeout)) {
-				/* assume this means it's off */
-				wdev->ps = false;
-			}
+		    rdev->ops->set_power_mgmt &&
+		    rdev_set_power_mgmt(rdev, dev, wdev->ps,
+					wdev->ps_timeout)) {
+			/* assume this means it's off */
+			wdev->ps = false;
+		}
 		break;
 	case NETDEV_UNREGISTER:
 		/*
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 68e5f2ecee1a..daef500a7b64 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -914,11 +914,11 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
 			netdev_err(dev, "failed to set key %d\n", i);
 			continue;
 		}
-		if (wdev->connect_keys->def == i)
-			if (rdev_set_default_key(rdev, dev, i, true, true)) {
-				netdev_err(dev, "failed to set defkey %d\n", i);
-				continue;
-			}
+		if (wdev->connect_keys->def == i &&
+		    rdev_set_default_key(rdev, dev, i, true, true)) {
+			netdev_err(dev, "failed to set defkey %d\n", i);
+			continue;
+		}
 	}
 
 	kzfree(wdev->connect_keys);
-- 
2.9.3

^ permalink raw reply related

* [PATCH 2/6] ieee80211: add FT-PSK AKM suite selector
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Avraham Stern
In-Reply-To: <20170220132439.16064-1-johannes@sipsolutions.net>

From: Avraham Stern <avraham.stern@intel.com>

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 0dd9498c694f..6ea381c98aae 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2347,6 +2347,7 @@ enum ieee80211_sa_query_action {
 /* AKM suite selectors */
 #define WLAN_AKM_SUITE_8021X		SUITE(0x000FAC, 1)
 #define WLAN_AKM_SUITE_PSK		SUITE(0x000FAC, 2)
+#define WLAN_AKM_SUITE_FT_PSK		SUITE(0x000FAC, 4)
 #define WLAN_AKM_SUITE_8021X_SHA256	SUITE(0x000FAC, 5)
 #define WLAN_AKM_SUITE_PSK_SHA256	SUITE(0x000FAC, 6)
 #define WLAN_AKM_SUITE_TDLS		SUITE(0x000FAC, 7)
-- 
2.9.3

^ permalink raw reply related

* [PATCH 5/6] mac80211: fix typo in debug print
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Sara Sharon
In-Reply-To: <20170220132439.16064-1-johannes@sipsolutions.net>

From: Sara Sharon <sara.sharon@intel.com>

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 3b5fd4188f2a..4463c61d068e 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -85,7 +85,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 	ht_dbg(sta->sdata,
 	       "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
 	       sta->sta.addr, tid,
-	       initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
+	       initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
 	       (int)reason);
 
 	if (drv_ampdu_action(local, sta->sdata, &params))
-- 
2.9.3

^ permalink raw reply related

* [PATCH 4/6] mac80211: flush delayed work when enter suspend
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Matt Chen
In-Reply-To: <20170220132439.16064-1-johannes@sipsolutions.net>

From: Matt Chen <matt.chen@intel.com>

The issue was found when entering suspend and resume.
It triggers a warning in:
mac80211/key.c: ieee80211_enable_keys()
...
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
             sdata->crypto_tx_tailroom_pending_dec);
...

It points out sdata->crypto_tx_tailroom_pending_dec isn't cleaned up successfully
in a delayed_work during suspend. Add a flush_delayed_work to fix it.

type=bugfix
fixes=unknown
bug=chrome-os-partner:62283

Change-Id: Iad6b1c86c8792aae81934e7c205f44add10f062b
Signed-off-by: Matt Chen <matt.chen@intel.com>
Reviewed-on: https://git-amr-3.devtools.intel.com/gerrit/88500
Tested-by: ec ger unix iil jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
Reviewed-by: Coelho, Luciano <luciano.coelho@intel.com>
---
 net/mac80211/pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 28a3a0957c9e..76a8bcd8ef11 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -168,6 +168,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			break;
 		}
 
+		flush_delayed_work(&sdata->dec_tailroom_needed_wk);
 		drv_remove_interface(local, sdata);
 	}
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH 1/2] mac80211: flush delayed work when entering suspend
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Matt Chen

From: Matt Chen <matt.chen@intel.com>

The issue was found when entering suspend and resume.
It triggers a warning in:
mac80211/key.c: ieee80211_enable_keys()
...
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
             sdata->crypto_tx_tailroom_pending_dec);
...

It points out sdata->crypto_tx_tailroom_pending_dec isn't cleaned up successfully
in a delayed_work during suspend. Add a flush_delayed_work to fix it.

Cc: stable@vger.kernel.org
Signed-off-by: Matt Chen <matt.chen@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 28a3a0957c9e..76a8bcd8ef11 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -168,6 +168,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 			break;
 		}
 
+		flush_delayed_work(&sdata->dec_tailroom_needed_wk);
 		drv_remove_interface(local, sdata);
 	}
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH 6/6] mac80211: shorten debug message
From: Johannes Berg @ 2017-02-20 13:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Sara Sharon
In-Reply-To: <20170220132439.16064-1-johannes@sipsolutions.net>

From: Sara Sharon <sara.sharon@intel.com>

Tracing is limited to 100 characters and this message passes
the limit when there are a few buffered frames. Shorten it.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 8bb99d299cda..3323a2fb289b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1264,7 +1264,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 	sta_info_recalc_tim(sta);
 
 	ps_dbg(sdata,
-	       "STA %pM aid %d sending %d filtered/%d PS frames since STA not sleeping anymore\n",
+	       "STA %pM aid %d sending %d filtered/%d PS frames since STA woke up\n",
 	       sta->sta.addr, sta->sta.aid, filtered, buffered);
 
 	ieee80211_check_fast_xmit(sta);
-- 
2.9.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox