Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 1/3] ath9k: Add a module parameter to set btcoex duty cycle
From: Valo, Kalle @ 2016-11-25 15:25 UTC (permalink / raw)
  To: miaoqing@codeaurora.org; +Cc: linux-wireless@vger.kernel.org, ath9k-devel
In-Reply-To: <1479970402-13796-1-git-send-email-miaoqing@codeaurora.org>

miaoqing@codeaurora.org writes:

> From: Miaoqing Pan <miaoqing@codeaurora.org>
>
> btcoex duty cyle allows user to balance the performance
> between WLAN and BT.
>
> Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>

[...]

> --- a/drivers/net/wireless/ath/ath9k/init.c
> +++ b/drivers/net/wireless/ath/ath9k/init.c
> @@ -73,6 +73,12 @@ struct ath9k_eeprom_ctx {
> =20
>  #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
> =20
> +#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
> +static int ath9k_btcoex_duty_cycle =3D ATH_BTCOEX_DEF_DUTY_CYCLE;
> +module_param_named(btcoex_duty_cycle, ath9k_btcoex_duty_cycle, int, 0444=
);
> +MODULE_PARM_DESC(btcoex_duty_cycle, "BT coexistence duty cycle");
> +#endif

I don't think module parameters are really meant for providing protocol
settings like this, especially as these would be global for all radios.
nl80211 (if used in production) or debugfs (if used only in testing) are
much better choises.

--=20
Kalle Valo=

^ permalink raw reply

* Re: [PATCH 2/3] ath9k: export configurable parameters of PTA
From: Valo, Kalle @ 2016-11-25 15:28 UTC (permalink / raw)
  To: miaoqing@codeaurora.org; +Cc: linux-wireless@vger.kernel.org, ath9k-devel
In-Reply-To: <1479970402-13796-2-git-send-email-miaoqing@codeaurora.org>

miaoqing@codeaurora.org writes:

> From: Miaoqing Pan <miaoqing@codeaurora.org>
>
> Export time_extend, pritority_time, first_slot_time, wl_active_time
> and wl_qc_time those PTA(aka slotted mode) configurable parameters,
> allow user to change/debug the timing easily.
>
> Also set wl_active_time and wl_qc_time default value to 0, as in this
> period WLAN chip may send out ACK, and it will corrupt the BT(or other)
> received packet in the PTA cycle.
>
> Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>

Please try to always write commit logs so that everyone will understand,
for example spelling out what PTA means would be nice.

> --- a/drivers/net/wireless/ath/ath9k/init.c
> +++ b/drivers/net/wireless/ath/ath9k/init.c
> @@ -77,6 +77,26 @@ struct ath9k_eeprom_ctx {
>  static int ath9k_btcoex_duty_cycle =3D ATH_BTCOEX_DEF_DUTY_CYCLE;
>  module_param_named(btcoex_duty_cycle, ath9k_btcoex_duty_cycle, int, 0444=
);
>  MODULE_PARM_DESC(btcoex_duty_cycle, "BT coexistence duty cycle");
> +
> +static int ath9k_btcoex_time_extend;
> +module_param_named(btcoex_time_extend, ath9k_btcoex_time_extend, int, 04=
44);
> +MODULE_PARM_DESC(btcoex_time_extend, "BT coexistence time extend");
> +
> +static int ath9k_btcoex_priority_time =3D 2;
> +module_param_named(btcoex_priority_time, ath9k_btcoex_priority_time, int=
, 0444);
> +MODULE_PARM_DESC(btcoex_priority_time, "BT coexistence priority time");
> +
> +static int ath9k_btcoex_first_slot_time =3D 5;
> +module_param_named(btcoex_first_slot_time, ath9k_btcoex_first_slot_time,=
 int, 0444);
> +MODULE_PARM_DESC(btcoex_first_slot_time, "BT coexistence first slot time=
");
> +
> +static int ath9k_btcoex_wl_active_time;
> +module_param_named(btcoex_wl_active_time, ath9k_btcoex_wl_active_time, i=
nt, 0444);
> +MODULE_PARM_DESC(btcoex_wl_active_time, "BT coexistence wlan active time=
");
> +
> +static int ath9k_btcoex_wl_qc_time;
> +module_param_named(btcoex_wl_qc_time, ath9k_btcoex_wl_qc_time, int, 0444=
);
> +MODULE_PARM_DESC(btcoex_wl_qc_time, "BT coexistence wlan quiet collision=
 time");
>  #endif

Same as with the previous patch, I don't think these should be set via
module parameters.

--=20
Kalle Valo=

^ permalink raw reply

* Re: [PATCH] mt7601u: wait for clear rxq when stopping mac
From: Jakub Kicinski @ 2016-11-25 17:06 UTC (permalink / raw)
  To: Anthony Romano; +Cc: linux-wireless
In-Reply-To: <20161125111334.31085-1-anthony.romano@coreos.com>

On Fri, 25 Nov 2016 03:13:34 -0800, Anthony Romano wrote:
> mt7601u_mac_stop_hw should stop polling the rxq once it remains empty
> but instead continues polling after the rxq status stays clear; bringing
> down the interface takes about six seconds from this alone.
> 
> Speed up path by exiting rxq loop once status repeatedly polls empty.
> 
> Signed-off-by: Anthony Romano <anthony.romano@coreos.com>

Looks correct, the condition was inverted and we don't have to
msleep() when we see values go to zero.  Thanks!

Reviewed-by: Jakub Kicinski <kubakici@wp.pl>

^ permalink raw reply

* Re: [PATCH v2 0/7] ath9k: EEPROM swapping improvements
From: Martin Blumenstingl @ 2016-11-25 23:49 UTC (permalink / raw)
  To: Valo, Kalle
  Cc: ath9k-devel, linux-wireless@vger.kernel.org,
	ath9k-devel@lists.ath9k.org, devicetree@vger.kernel.org,
	arnd@arndb.de, chunkeey@googlemail.com, nbd@nbd.name
In-Reply-To: <871sxza9al.fsf@kamboji.qca.qualcomm.com>

On Fri, Nov 25, 2016 at 4:06 PM, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> Kalle Valo <kvalo@codeaurora.org> writes:
>
>> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>>
>>> There are two types of swapping the EEPROM data in the ath9k driver.
>>> Before this series one type of swapping could not be used without the
>>> other.
>>>
>>> The first type of swapping looks at the "magic bytes" at the start of
>>> the EEPROM data and performs swab16 on the EEPROM contents if needed.
>>> The second type of swapping is EEPROM format specific and swaps
>>> specific fields within the EEPROM itself (swab16, swab32 - depends on
>>> the EEPROM format).
>>>
>>> With this series the second part now looks at the EEPMISC register
>>> inside the EEPROM, which uses a bit to indicate if the EEPROM data
>>> is Big Endian (this is also done by the FreeBSD kernel).
>>> This has a nice advantage: currently there are some out-of-tree hacks
>>> (in OpenWrt and LEDE) where the EEPROM has a Big Endian header on a
>>> Big Endian system (= no swab16 is performed) but the EEPROM itself
>>> indicates that it's data is Little Endian. Until now the out-of-tree
>>> code simply did a swab16 before passing the data to ath9k, so ath9k
>>> first did the swab16 - this also enabled the format specific swapping.
>>> These out-of-tree hacks are still working with the new logic, but it
>>> is recommended to remove them. This implementation is based on a
>>> discussion with Arnd Bergmann who raised concerns about the
>>> robustness and portability of the swapping logic in the original OF
>>> support patch review, see [0].
>>>
>>> After a second round of patches (= v1 of this series) neither Arnd
>>> Bergmann nor I were really happy with the complexity of the EEPROM
>>> swapping logic. Based on a discussion (see [1] and [2]) we decided
>>> that ath9k should use a defined format (specifying the endianness
>>> of the data - I went with __le16 and __le32) when accessing the
>>> EEPROM fields. A benefit of this is that we enable the EEPMISC based
>>> swapping logic by default, just like the FreeBSD driver, see [3]. On
>>> the devices which I have tested (see below) ath9k now works without
>>> having to specify the "endian_check" field in ath9k_platform_data (or
>>> a similar logic which could provide this via devicetree) as ath9k now
>>> detects the endianness automatically. Only EEPROMs which are mangled
>>> by some out-of-tree code still need the endian_check flag (or one can
>>> simply remove that mangling from the out-of-tree code).
>>>
>>> Testing:
>>> - tested by myself on AR9287 with Big Endian EEPROM
>>> - tested by myself on AR9227 with Little Endian EEPROM
>>> - tested by myself on AR9381 (using the ar9003_eeprom implementation,
>>>   which did not suffer from this whole problem)
>>> - how do we proceed with testing? maybe we could keep this in a
>>>   feature-branch and add these patches to LEDE once we have an ACK to
>>>   get more people to test this
>>>
>>> This series depends on my other series (v7):
>>> "add devicetree support to ath9k" - see [4]
>>
>> I think this looks pretty good. If there's a bug somewhere it should be
>> quite easy to fix so I'm not that worried and would be willing to take
>> these as soon as I have applied the dependency series. IIRC your
>> devicetree patches will have at least one more review round so that will
>> take some time still. In the meantime it would be great if LEDE folks
>> could take a look at these and comment (or test).
>
> So are everyone happy with this? I haven't seen any comments. If I don't
> here anything I'm planning to take these, most likely for 4.11.
after being busy due to <daytime job and other things in life> I'm
currently trying to get the patches into LEDE: [0] (so far there are
no major objections)
once we get this into LEDE we'll see pretty soon if there are any
problems or not -> 4.11 sounds good to me!


Regards,
Martin


[0] http://lists.infradead.org/pipermail/lede-dev/2016-November/004231.html

^ permalink raw reply

* [PATCH] rtl8xxxu: tx rate reported before set
From: Barry Day @ 2016-11-26  2:12 UTC (permalink / raw)
  To: Jes Sorensen; +Cc: linux-wireless, Kalle Valo

Move the dev_info call that attempts to show the rate used before it is set.

Signed-off-by: Barry Day <briselec@gmail.com>
---
 rtl8xxxu_core.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/rtl8xxxu_core.c b/rtl8xxxu_core.c
index 04141e5..a9137ab 100644
--- a/rtl8xxxu_core.c
+++ b/rtl8xxxu_core.c
@@ -4844,16 +4844,16 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
 
 	tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32;
 
-	if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
-		dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
-			 __func__, rate, cpu_to_le16(tx_desc40->pkt_size));
-
 	if (rate_flags & IEEE80211_TX_RC_MCS &&
 	    !ieee80211_is_mgmt(hdr->frame_control))
 		rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
 	else
 		rate = tx_rate->hw_value;
 
+	if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
+		dev_info(dev, "%s: TX rate: %d, pkt size %d\n",
+			 __func__, rate, cpu_to_le16(tx_desc40->pkt_size));
+
 	seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
 
 	tx_desc40->txdw4 = cpu_to_le32(rate);
-- 
2.9.2

^ permalink raw reply related

* Re: wl1251 & mac address & calibration data
From: Pavel Machek @ 2016-11-26 17:17 UTC (permalink / raw)
  To: Aaro Koskinen
  Cc: Pali Rohár, Sebastian Reichel, Michal Kazior, Kalle Valo,
	Ivaylo Dimitrov, Tony Lindgren, linux-wireless,
	Network Development, linux-kernel
In-Reply-To: <20161124184601.wo4al6nyzb6rmiqs@raspberrypi-2.musicnaut.iki.fi>

[-- Attachment #1: Type: text/plain, Size: 908 bytes --]

On Thu 2016-11-24 20:46:01, Aaro Koskinen wrote:
> Hi,
> 
> On Thu, Nov 24, 2016 at 04:20:45PM +0100, Pali Rohár wrote:
> > Proprietary, signed and closed bootloader NOLO does not support DT. So
> > for booting you need to append DTS file to kernel image.
> > 
> > U-Boot is optional and can be used as intermediate bootloader between
> > NOLO and kernel. But still it has problems with reading from nand, so
> > cannot read NVS data nor MAC address.
> 
> You could use kexec to pass the fixed DT.

Yeah. You could also strap desktop PC to a USB GPRS card, and call it
phone. You could also make a pig fly.

But because you could does not mean you should. No, sorry, kexec is
not acceptable. Too hard to set up, slows boot too much.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: wl1251 & mac address & calibration data
From: Pali Rohár @ 2016-11-26 17:20 UTC (permalink / raw)
  To: Aaro Koskinen
  Cc: Sebastian Reichel, Pavel Machek, Michal Kazior, Kalle Valo,
	Ivaylo Dimitrov, Tony Lindgren, linux-wireless,
	Network Development, linux-kernel
In-Reply-To: <20161124184601.wo4al6nyzb6rmiqs@raspberrypi-2.musicnaut.iki.fi>

[-- Attachment #1: Type: Text/Plain, Size: 641 bytes --]

On Thursday 24 November 2016 19:46:01 Aaro Koskinen wrote:
> Hi,
> 
> On Thu, Nov 24, 2016 at 04:20:45PM +0100, Pali Rohár wrote:
> > Proprietary, signed and closed bootloader NOLO does not support DT.
> > So for booting you need to append DTS file to kernel image.
> > 
> > U-Boot is optional and can be used as intermediate bootloader
> > between NOLO and kernel. But still it has problems with reading
> > from nand, so cannot read NVS data nor MAC address.
> 
> You could use kexec to pass the fixed DT.
> 
> A.

IIRC it was broken for N900/omap3, no idea if somebody fixed it.

-- 
Pali Rohár
pali.rohar@gmail.com

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* [PATCH] rtlwifi: Fix enter/exit power_save
From: Larry Finger @ 2016-11-26 20:43 UTC (permalink / raw)
  To: kvalo; +Cc: devel, linux-wireless, Larry Finger, Stable

In commit a5ffbe0a1993 ("rtlwifi: Fix scheduling while atomic bug") and
commit a269913c52ad ("rtlwifi: Rework rtl_lps_leave() and rtl_lps_enter()
to use work queue"), an error was introduced in the power-save routines
due to the fact that leaving PS was delayed by the use of a work queue.

This problem is fixed by detecting if the enter or leave routines are
in interrupt mode. If so, the workqueue is used to place the request.
If in normal mode, the enter or leave routines are called directly.

Fixes: a269913c52ad ("rtlwifi: Rework rtl_lps_leave() and rtl_lps_enter() to use work queue")
Reported-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
---
Kalle,

Please push this patch to 4.10. It fixes a long-standing bug.

Thanks,

Larry
---
 drivers/net/wireless/realtek/rtlwifi/base.c |  8 +++----
 drivers/net/wireless/realtek/rtlwifi/core.c |  9 +++-----
 drivers/net/wireless/realtek/rtlwifi/pci.c  | 14 ++++-------
 drivers/net/wireless/realtek/rtlwifi/ps.c   | 36 ++++++++++++++++++++++-------
 4 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 264466f..4ac928b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc);
 
 static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
 {
+	struct ieee80211_hw *hw = rtlpriv->hw;
+
 	rtlpriv->ra.is_special_data = true;
 	if (rtlpriv->cfg->ops->get_btc_status())
 		rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
 					rtlpriv, 1);
-	rtlpriv->enter_ps = false;
-	schedule_work(&rtlpriv->works.lps_change_work);
+	rtl_lps_leave(hw);
 	ppsc->last_delaylps_stamp_jiffies = jiffies;
 }
 
@@ -1381,8 +1382,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
 
 		if (is_tx) {
 			rtlpriv->ra.is_special_data = true;
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
+			rtl_lps_leave(hw);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 		}
 
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index e89681d..2caa4ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		} else {
 			mstatus = RT_MEDIA_DISCONNECT;
 
-			if (mac->link_state == MAC80211_LINKED) {
-				rtlpriv->enter_ps = false;
-				schedule_work(&rtlpriv->works.lps_change_work);
-			}
+			if (mac->link_state == MAC80211_LINKED)
+				rtl_lps_leave(hw);
 			if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
 				rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 			mac->link_state = MAC80211_NOLINK;
@@ -1431,8 +1429,7 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
 	}
 
 	if (mac->link_state == MAC80211_LINKED) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
+		rtl_lps_leave(hw);
 		mac->link_state = MAC80211_LINKED_SCANNING;
 	} else {
 		rtl_ips_nic_on(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index d044b23..8bfe020 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -659,11 +659,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 	}
 
 	if (((rtlpriv->link_info.num_rx_inperiod +
-		rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
-	}
+	      rtlpriv->link_info.num_tx_inperiod) > 8) ||
+	      (rtlpriv->link_info.num_rx_inperiod > 2))
+		rtl_lps_leave(hw);
 }
 
 static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -914,10 +912,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 		}
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		      (rtlpriv->link_info.num_rx_inperiod > 2)) {
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
-		}
+		      (rtlpriv->link_info.num_rx_inperiod > 2))
+			rtl_lps_leave(hw);
 		skb = new_skb;
 no_new:
 		if (rtlpriv->use_new_trx_flow) {
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c
index 18d979a..d0ffc4d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 	}
 }
 
-/*Enter the leisure power save mode.*/
-void rtl_lps_enter(struct ieee80211_hw *hw)
+/* Interrupt safe routine to enter the leisure power save mode.*/
+static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -444,10 +444,9 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_enter);
 
-/*Leave the leisure power save mode.*/
-void rtl_lps_leave(struct ieee80211_hw *hw)
+/* Interrupt safe routine to leave the leisure power save mode.*/
+static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -477,7 +476,6 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 	}
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_leave);
 
 /* For sw LPS*/
 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
@@ -670,12 +668,34 @@ void rtl_lps_change_work_callback(struct work_struct *work)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	if (rtlpriv->enter_ps)
-		rtl_lps_enter(hw);
+		rtl_lps_enter_core(hw);
 	else
-		rtl_lps_leave(hw);
+		rtl_lps_leave_core(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
 
+void rtl_lps_enter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_enter_core(hw);
+	rtlpriv->enter_ps = true;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_enter);
+
+void rtl_lps_leave(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_leave_core(hw);
+	rtlpriv->enter_ps = false;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_leave);
+
 void rtl_swlps_wq_callback(void *data)
 {
 	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
-- 
2.10.0

^ permalink raw reply related

* Re: [PATCH v2] ath9k: Introduce airtime fairness scheduling between stations
From: Toke Høiland-Jørgensen @ 2016-11-27 15:58 UTC (permalink / raw)
  To: Valo, Kalle; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <87wpfr8u9v.fsf@kamboji.qca.qualcomm.com>

"Valo, Kalle" <kvalo@qca.qualcomm.com> writes:

> (The make-wifi-fast list is annoying as it always spams me when it's on
> CC, so dropped it.)
>
> Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
>
>> This reworks the ath9k driver to schedule transmissions to connected
>> stations in a way that enforces airtime fairness between them. It
>> accomplishes this by measuring the time spent transmitting to or
>> receiving from a station at TX and RX completion, and accounting this to
>> a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
>> deficit scheduler is employed at packet dequeue time, to control which
>> station gets the next transmission opportunity.
>>
>> Airtime fairness can significantly improve the efficiency of the network
>> when station rates vary. The following throughput values are from a
>> simple three-station test scenario, where two stations operate at the
>> highest HT20 rate, and one station at the lowest, and the scheduler is
>> employed at the access point:
>>
>>                   Before   /   After
>> Fast station 1:    19.17   /   25.09 Mbps
>> Fast station 2:    19.83   /   25.21 Mbps
>> Slow station:       2.58   /    1.77 Mbps
>> Total:             41.58   /   52.07 Mbps
>>
>> The benefit of airtime fairness goes up the more stations are present.
>> In a 30-station test with one station artificially limited to 1 Mbps,
>> we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
>>
>> Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>
>
> [...]
>
>> +void ath_acq_lock(struct ath_softc *sc, struct ath_acq *acq)
>> +	__acquires(&acq->lock)
>> +{
>> +	spin_lock_bh(&acq->lock);
>> +}
>> +
>> +void ath_acq_unlock(struct ath_softc *sc, struct ath_acq *acq)
>> +	__releases(&acq->lock)
>> +{
>> +	spin_unlock_bh(&acq->lock);
>> +}
>
> Why these? To me it looks like they just add an extra function jump and
> unneccessary extra layer.

Well, there's already similar functions for the txq lock (ath_txq_lock()
and ath_txq_unlock() in xmit.c), so figured I'd be consistent with
those. And also that the __acquires and __releases macros were probably
useful.

Also, won't the compiler automatically inline them?

-Toke

^ permalink raw reply

* [PATCH] wireless: ath: ath9k: constify ath_bus_ops structure
From: Bhumika Goyal @ 2016-11-27 17:03 UTC (permalink / raw)
  To: julia.lawall, ath9k-devel, kvalo, linux-wireless, ath9k-devel,
	netdev, linux-kernel
  Cc: Bhumika Goyal

Declare the structure ath_bus_ops as const as it is only passed as an
argument to the function ath9k_init_device. This argument is of type
const struct ath_bus_ops *, so ath_bus_ops structures with this property
can be declared as const.
Done using Coccinelle:
@r1 disable optional_qualifier @
identifier i;
position p;
@@
static struct ath_bus_ops i@p = {...};

@ok1@
identifier r1.i;
position p;
expression e1,e2;
@@
ath9k_init_device(e1,e2,&i@p)

@bad@
position p!={r1.p,ok1.p};
identifier r1.i;
@@
i@p

@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
static
+const
struct ath_bus_ops i={...};

@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
+const
struct ath_bus_ops i;

File size before:
   text	   data	    bss	    dec	    hex	filename
   1295	    232	      0	   1527	    5f7	ath/ath9k/ahb.o

File size after:
   text	   data	    bss	    dec	    hex	filename
   1359	    176	      0	   1535	    5ff	ath/ath9k/ahb.o

Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
 drivers/net/wireless/ath/ath9k/ahb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index bea6186..2bd982c 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -62,7 +62,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 	return false;
 }
 
-static struct ath_bus_ops ath_ahb_bus_ops  = {
+static const struct ath_bus_ops ath_ahb_bus_ops  = {
 	.ath_bus_type = ATH_AHB,
 	.read_cachesize = ath_ahb_read_cachesize,
 	.eeprom_read = ath_ahb_eeprom_read,
-- 
1.9.1

^ permalink raw reply related

* [PATCH] rtlwifi: Add updates for RTL8723BE and RTL8821AE
From: Larry Finger @ 2016-11-27 19:28 UTC (permalink / raw)
  To: linux-firmware; +Cc: linux-wireless, Larry Finger, netdev

The new versions will only work with new versions of the drivers. For
that reason, they are given new names and the old versions are retained.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 WHENCE                     |   4 ++++
 rtlwifi/rtl8723befw_36.bin | Bin 0 -> 31762 bytes
 rtlwifi/rtl8821aefw_29.bin | Bin 0 -> 28348 bytes
 3 files changed, 4 insertions(+)
 create mode 100644 rtlwifi/rtl8723befw_36.bin
 create mode 100644 rtlwifi/rtl8821aefw_29.bin

diff --git a/WHENCE b/WHENCE
index 90d6e4d..c31fe15 100644
--- a/WHENCE
+++ b/WHENCE
@@ -2329,6 +2329,8 @@ Driver: rtl8723be - Realtek 802.11n WLAN driver for RTL8723BE
 
 Info: From Vendor's realtek/rtlwifi_linux_mac80211_0019.0320.2014V628 driver
 File: rtlwifi/rtl8723befw.bin
+Info: Update to version 36 - Sent by Realtek
+File: rtlwifi/rtl8723befw_36.bin
 
 Licence: Redistributable. See LICENCE.rtlwifi_firmware.txt for details.
 
@@ -2370,6 +2372,8 @@ Driver: rtl8821ae - Realtek 802.11n WLAN driver for RTL8821AE
 Info: From Vendor's realtek/rtlwifi_linux_mac80211_0019.0320.2014V628 driver
 File: rtlwifi/rtl8821aefw.bin
 File: rtlwifi/rtl8821aefw_wowlan.bin
+Info: Update to version 29 - Sent by Realtek
+File: rtlwifi/rtl8821aefw_29.bin
 
 Licence: Redistributable. See LICENCE.rtlwifi_firmware.txt for details.
 
diff --git a/rtlwifi/rtl8723befw_36.bin b/rtlwifi/rtl8723befw_36.bin
new file mode 100644
index 0000000000000000000000000000000000000000..1bb9b9c8cea95689a0d27f9d7c264ad63728dde1
GIT binary patch
literal 31762
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
M8dR)JhVGZ{SDBkI`Tzg`

literal 0
HcmV?d00001

diff --git a/rtlwifi/rtl8821aefw_29.bin b/rtlwifi/rtl8821aefw_29.bin
new file mode 100644
index 0000000000000000000000000000000000000000..f0acde46948149dd6c49d203814e2dc417b07e91
GIT binary patch
literal 28348
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
Ow{ZbD-Q0C;TmLUs$&o4m

literal 0
HcmV?d00001

-- 
2.10.0

^ permalink raw reply related

* [PATCH] ath10k: fix TLV set regdomain command
From: Erik Stromdahl @ 2016-11-27 19:37 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl

There is a typo bug in the current implementation of
ath10k_wmi_tlv_op_gen_pdev_set_rd.
The conformance test limits are not set up properly.

The two arguments ctl2g and ctl5g were not used at all.
Instead, the regdomain arguments rd2g and rd5g were used
for the ctl settings as well.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/wmi-tlv.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 97b536e..f304f66 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1313,8 +1313,8 @@ static int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
 	cmd->regd = __cpu_to_le32(rd);
 	cmd->regd_2ghz = __cpu_to_le32(rd2g);
 	cmd->regd_5ghz = __cpu_to_le32(rd5g);
-	cmd->conform_limit_2ghz = __cpu_to_le32(rd2g);
-	cmd->conform_limit_5ghz = __cpu_to_le32(rd5g);
+	cmd->conform_limit_2ghz = __cpu_to_le32(ctl2g);
+	cmd->conform_limit_5ghz = __cpu_to_le32(ctl5g);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
 	return skb;
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH 2/2] cfg80211: Add support to sched scan to report better BSSs
From: Arend Van Spriel @ 2016-11-27 20:51 UTC (permalink / raw)
  To: Jouni Malinen, Johannes Berg; +Cc: linux-wireless, vamsi krishna
In-Reply-To: <1479938857-1788-2-git-send-email-jouni@qca.qualcomm.com>

On 23-11-2016 23:07, Jouni Malinen wrote:
> From: vamsi krishna <vamsin@qti.qualcomm.com>
> 
> Enhance sched scan to support option of finding a better BSS while in
> connected state. Firmware scans the medium and reports when it finds a
> known BSS which has a significantly better RSSI than the current
> connected BSS.

I suppose the intent here is to be notified about roaming candidates and
hence the "connected state" prerequisite. It seems there has already
been taken a shot at this which may be used/extended [1].

Regards,
Arend

[1] http://lxr.free-electrons.com/source/include/uapi/linux/nl80211.h#L2945
[2] http://lxr.free-electrons.com/source/include/uapi/linux/nl80211.h#L4826

> Signed-off-by: vamsi krishna <vamsin@qti.qualcomm.com>
> Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
> ---
>  include/net/cfg80211.h       | 17 +++++++++++++++++
>  include/uapi/linux/nl80211.h | 17 +++++++++++++++++
>  net/wireless/nl80211.c       | 32 ++++++++++++++++++++++++++++++--
>  3 files changed, 64 insertions(+), 2 deletions(-)
> 
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index ef42749..c62c42a 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -1626,6 +1626,20 @@ struct cfg80211_sched_scan_plan {
>   *	cycle.  The driver may ignore this parameter and start
>   *	immediately (or at any other time), if this feature is not
>   *	supported.
> + * @relative_rssi: Relative RSSI threshold to restrict scan result reporting in
> + *	connected state to cases where a matching BSS is determined to have a
> + *	significantly better RSSI than the current connected BSS.
> + * @relative_rssi_5g_pref: The amount of RSSI preference that is given to a
> + *	5 GHz BSS over 2.4 GHz BSS while looking for better BSSs in connected
> + *	state.
> + *	If the current connected BSS is in the 2.4 GHz band, other BSSs in the
> + *	2.4 GHz band to be reported should have better RSSI by @relative_rssi
> + *	and other BSSs in the 5 GHz band to be reported should have better RSSI
> + *	by (@relative_rssi - @relative_rssi_5g_pref).
> + *	If the current connected BSS is in the 5 GHz band, other BSSs in the
> + *	2.4 GHz band to be reported should have better RSSI by
> + *	(@relative_rssi + @relative_rssi_5g_pref) and other BSSs in the 5 GHz
> + *	band to be reported should have better RSSI by by @relative_rssi.
>   */
>  struct cfg80211_sched_scan_request {
>  	struct cfg80211_ssid *ssids;
> @@ -1645,6 +1659,9 @@ struct cfg80211_sched_scan_request {
>  	u8 mac_addr[ETH_ALEN] __aligned(2);
>  	u8 mac_addr_mask[ETH_ALEN] __aligned(2);
>  
> +	int relative_rssi;
> +	int relative_rssi_5g_pref;

I suppose s8 would be sufficient here, right?

>  	/* internal */
>  	struct wiphy *wiphy;
>  	struct net_device *dev;
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 984a35ac..34b16a4 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -1981,6 +1981,16 @@ enum nl80211_commands {
>   *	%NL80211_ATTR_MAC has also been used in various commands/events for
>   *	specifying the BSSID.
>   *
> + * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which
> + *	other BSSs has to be better than the current connected BSS so that they
> + *	get reported to user space. This will give an opportunity to userspace
> + *	to consider connecting to other matching BSSs which have better RSSI
> + *	than the current connected BSS.
> + *
> + * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF: The amount of RSSI preference
> + *	to be given to 5 GHz APs over 2.4 GHz APs while searching for better
> + *	BSSs than the current connected BSS.
> + *
>   * @NUM_NL80211_ATTR: total number of nl80211_attrs available
>   * @NL80211_ATTR_MAX: highest attribute number currently defined
>   * @__NL80211_ATTR_AFTER_LAST: internal use
> @@ -2387,6 +2397,9 @@ enum nl80211_attrs {
>  
>  	NL80211_ATTR_BSSID,
>  
> +	NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
> +	NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF,
> +
>  	/* add attributes here, update the policy in nl80211.c */
>  
>  	__NL80211_ATTR_AFTER_LAST,
> @@ -4698,6 +4711,9 @@ enum nl80211_feature_flags {
>   *	configuration (AP/mesh) with VHT rates.
>   * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup
>   *	with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
> + * @NL80211_EXT_FEATURE_SCHED_SCAN_BETTER_BSS: The driver supports sched_scan
> + *	for reporting BSSs with better RSSI than the current connected BSS
> + *	(%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI).
>   *
>   * @NUM_NL80211_EXT_FEATURES: number of extended features.
>   * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
> @@ -4713,6 +4729,7 @@ enum nl80211_ext_feature_index {
>  	NL80211_EXT_FEATURE_BEACON_RATE_HT,
>  	NL80211_EXT_FEATURE_BEACON_RATE_VHT,
>  	NL80211_EXT_FEATURE_FILS_STA,
> +	NL80211_EXT_FEATURE_SCHED_SCAN_BETTER_BSS,
>  
>  	/* add new features before the definition below */
>  	NUM_NL80211_EXT_FEATURES,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 8db5cb1..af018a5 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -405,6 +405,8 @@ enum nl80211_multicast_groups {
>  	[NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
>  	[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
>  	[NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
> +	[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_U32 },
> +	[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF] = { .type = NLA_U32 },

Related to earlier comment this could be NLA_U8.

>  };
>  
>  /* policy for the key attributes */
> @@ -6856,6 +6858,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
>  	size_t ie_len;
>  	struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
>  	s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
> +	int bbr;
>  
>  	if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
>  		return ERR_PTR(-EINVAL);
> @@ -6950,6 +6953,13 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
>  	if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
>  		return ERR_PTR(-EINVAL);
>  
> +	bbr = wiphy_ext_feature_isset(
> +		wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_BETTER_BSS);
> +	if (!bbr &&
> +	    (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
> +	     attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF]))
> +		return ERR_PTR(-EINVAL);
> +
>  	request = kzalloc(sizeof(*request)
>  			+ sizeof(*request->ssids) * n_ssids
>  			+ sizeof(*request->match_sets) * n_match_sets
> @@ -7156,6 +7166,14 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
>  		request->delay =
>  			nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
>  
> +	if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI])
> +		request->relative_rssi = nla_get_s32(
> +			attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
> +
> +	if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF])
> +		request->relative_rssi_5g_pref = nla_get_s32(
> +			attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF]);
> +
>  	err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
>  	if (err)
>  		goto out_free;
> @@ -9649,7 +9667,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
>  	return 0;
>  }
>  
> -static int nl80211_send_wowlan_nd(struct sk_buff *msg,
> +static int nl80211_send_wowlan_nd(struct wiphy *wiphy,
> +				  struct sk_buff *msg,
>  				  struct cfg80211_sched_scan_request *req)
>  {
>  	struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
> @@ -9670,6 +9689,15 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
>  	if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
>  		return -ENOBUFS;
>  
> +	if (wiphy_ext_feature_isset(
> +		    wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_BETTER_BSS) &&
> +	    (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
> +			 req->relative_rssi) ||
> +	     nla_put_u32(msg,
> +			 NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI_5G_PREF,
> +			 req->relative_rssi_5g_pref)))
> +		return -ENOBUFS;
> +
>  	freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
>  	if (!freqs)
>  		return -ENOBUFS;
> @@ -9783,7 +9811,7 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
>  			goto nla_put_failure;
>  
>  		if (nl80211_send_wowlan_nd(
> -			    msg,
> +			    &rdev->wiphy, msg,
>  			    rdev->wiphy.wowlan_config->nd_config))
>  			goto nla_put_failure;
>  
> 

^ permalink raw reply

* linux-next: build warning after merge of the wireless-drivers-next tree
From: Stephen Rothwell @ 2016-11-28  0:58 UTC (permalink / raw)
  To: Kalle Valo, Wireless; +Cc: linux-next, linux-kernel, Jes Sorensen

Hi all,

After merging the wireless-drivers-next tree, today's linux-next build
(x86_64 allmodconfig) produced this warning:

In file included from include/linux/usb/ch9.h:35:0,
                 from include/linux/usb.h:5,
                 from drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:32:
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c: In function 'rtl8xxxu_fill_txdesc_v2':
include/linux/device.h:1214:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
 #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
                                    ^
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:4841:6: note: 'rate' was declared here
  u32 rate;
      ^

Introduced by commit

  b4c3d9cfb607 ("rtl8xxxu: Pass tx_info to fill_txdesc in order to have access to retry count")

This is a correct diagnosis.

-- 
Cheers,
Stephen Rothwell

^ permalink raw reply

* Re: pull-request: wireless-drivers-next 2016-11-25
From: David Miller @ 2016-11-28  1:27 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <8760nbaoey.fsf@kamboji.qca.qualcomm.com>

From: Kalle Valo <kvalo@codeaurora.org>
Date: Fri, 25 Nov 2016 11:39:49 +0200

> here's a pull request for 4.10. ath9k has now been converted to use
> mac80211 intermediate software queues to fix bufferbloat problems. rsi
> has become active again and latevy mwifiex has been getting a _lot_ of
> love.
> 
> I'm not expecting to see any problems with this pull request. When you
> pull git will do lots of automerging but at least I didn't see any
> conflicts. Please let me know if you have any problems.

Pulled, thanks Kalle.

^ permalink raw reply

* [PATCH] ath9k_htc: don't use HZ for usb msg timeouts
From: Anthony Romano @ 2016-11-28  4:27 UTC (permalink / raw)
  To: linux-wireless, ath9k-devel; +Cc: ath9k-devel

The usb_*_msg() functions expect a timeout in msecs but are given HZ,
which is ticks per second. If HZ=100, firmware download often times out
when there is modest USB utilization and the device fails to initialize.

Replaces HZ in usb_*_msg timeouts with 1000 msec since HZ is one second
for timeouts in jiffies.

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
---
 drivers/net/wireless/ath/ath9k/hif_usb.c | 9 +++++----
 drivers/net/wireless/ath/ath9k/hif_usb.h | 2 ++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index e1c338cb9cb5..de2d212f39ec 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -997,7 +997,8 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
 		err = usb_control_msg(hif_dev->udev,
 				      usb_sndctrlpipe(hif_dev->udev, 0),
 				      FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
-				      addr >> 8, 0, buf, transfer, HZ);
+				      addr >> 8, 0, buf, transfer,
+				      USB_MSG_TIMEOUT);
 		if (err < 0) {
 			kfree(buf);
 			return err;
@@ -1020,7 +1021,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
 	err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
 			      FIRMWARE_DOWNLOAD_COMP,
 			      0x40 | USB_DIR_OUT,
-			      firm_offset >> 8, 0, NULL, 0, HZ);
+			      firm_offset >> 8, 0, NULL, 0, USB_MSG_TIMEOUT);
 	if (err)
 		return -EIO;
 
@@ -1249,7 +1250,7 @@ static int send_eject_command(struct usb_interface *interface)
 
 	dev_info(&udev->dev, "Ejecting storage device...\n");
 	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
-		cmd, 31, NULL, 2000);
+		cmd, 31, NULL, 2 * USB_MSG_TIMEOUT);
 	kfree(cmd);
 	if (r)
 		return r;
@@ -1314,7 +1315,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev)
 		return;
 
 	ret = usb_interrupt_msg(udev, usb_sndintpipe(udev, USB_REG_OUT_PIPE),
-			   buf, 4, NULL, HZ);
+			   buf, 4, NULL, USB_MSG_TIMEOUT);
 	if (ret)
 		dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
 
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 7c2ef7ecd98b..7846916aa01d 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -71,6 +71,8 @@ extern int htc_use_dev_fw;
 #define USB_REG_IN_PIPE   3
 #define USB_REG_OUT_PIPE  4
 
+#define USB_MSG_TIMEOUT 1000 /* (ms) */
+
 #define HIF_USB_MAX_RXPIPES 2
 #define HIF_USB_MAX_TXPIPES 4
 
-- 
2.11.0.rc2

^ permalink raw reply related

* Re: [PATCH 1/5] rsi: Device configuration bootup parameters updated
From: Kalle Valo @ 2016-11-28  7:21 UTC (permalink / raw)
  To: Prameela Rani Garnepudi
  Cc: Prameela Rani Garnepudi, linux-wireless, johannes.berg, hofrat,
	xypron.glpk
In-Reply-To: <e2acef96-6d2f-e5ad-aa74-5916ebb7e0bf@redpinesignals.com>

Prameela Rani Garnepudi <prameela.garnepudi@redpinesignals.com> writes:

> On 11/14/2016 05:45 PM, Prameela Rani Garnepudi wrote: 
>> Switch clock info values are changed in the firmware for both 20MHZ 
>> and 40MHZ modes. Hence these values which are configured through boot 
>> parameters request frame are updated. Also three other power save 
>> related parameters are added to boot up parameters. 
>> 
>> Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com> 

(Removed over hundred lines of unnecessary quotes, please edit your
quotes.)

> Can you please tell me, what modifications need to be done for this  
> patch. I already modified the code as per your previous suggestions. 

Like always, please check the patchwork before sending any emails. The
patch in question is here:

https://patchwork.kernel.org/patch/9427401/

It's in state "Changes Requested" which means that one of patches in the
patchset should have some comments. After looking at the other patches I
see my comment in patch 2:

https://patchwork.kernel.org/patch/9427419/

        "Based on Documentation/kernel-documentation.rst this doesn't
         look to be valid kernel-doc format. But AFAICS you got the
         format correct in patch 3.

         Also this function uses negative error codes (as preferred),
         it's not just -1 on failure. You should fix that in the comment
         (similar problems also elsewhere in this patchset)."

-- 
Kalle Valo

^ permalink raw reply

* Re: linux-next: build warning after merge of the wireless-drivers-next tree
From: Kalle Valo @ 2016-11-28  7:25 UTC (permalink / raw)
  To: Stephen Rothwell, Jes Sorensen; +Cc: Wireless, linux-next, linux-kernel
In-Reply-To: <20161128115814.2cabf139@canb.auug.org.au>

Stephen Rothwell <sfr@canb.auug.org.au> writes:

> Hi all,
>
> After merging the wireless-drivers-next tree, today's linux-next build
> (x86_64 allmodconfig) produced this warning:
>
> In file included from include/linux/usb/ch9.h:35:0,
>                  from include/linux/usb.h:5,
>                  from drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:32:
> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c: In function 'rtl8xxxu_fill_txdesc_v2':
> include/linux/device.h:1214:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
>  #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
>                                     ^
> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:4841:6: note: 'rate' was declared here
>   u32 rate;
>       ^
>
> Introduced by commit
>
>   b4c3d9cfb607 ("rtl8xxxu: Pass tx_info to fill_txdesc in order to have access to retry count")
>
> This is a correct diagnosis.

Thanks for the report. Jes, can you send a patch to fix this? (Unless
someone else beats to it.)

-- 
Kalle Valo

^ permalink raw reply

* [PATCH] bcma: add Dell Inspiron 3148
From: Jiri Slaby @ 2016-11-28  7:57 UTC (permalink / raw)
  To: zajec5; +Cc: linux-wireless, linux-kernel, Jiri Slaby

This is what is in the laptop:
01:00.0 Network controller [0280]: Broadcom Limited BCM43142 802.11b/g/n [14e4:4365] (rev 01)
        Subsystem: Dell Device [1028:0018]
        Flags: bus master, fast devsel, latency 0, IRQ 18
        Memory at b0400000 (64-bit, non-prefetchable) [size=32K]
        Capabilities: [40] Power Management version 3
        Capabilities: [58] Vendor Specific Information: Len=78 <?>
        Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
        Capabilities: [d0] Express Endpoint, MSI 00
        Capabilities: [100] Advanced Error Reporting
        Capabilities: [13c] Virtual Channel
        Capabilities: [160] Device Serial Number 00-00-9a-ff-ff-f3-40-b8
        Capabilities: [16c] Power Budgeting <?>

With the patch, I can see:
bcma: bus0: Found chip with id 43142, rev 0x01 and package 0x08
bcma: bus0: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x28, class 0x0)
bcma: bus0: Core 1 found: IEEE 802.11 (manuf 0x4BF, id 0x812, rev 0x21, class 0x0)
bcma: bus0: Core 2 found: PCIe (manuf 0x4BF, id 0x820, rev 0x16, class 0x0)
bcma: bus0: Core 3 found: UNKNOWN (manuf 0x43B, id 0x368, rev 0x00, class 0x0)
bcma: bus0: Bus registered

The wifi is not currently supported by brcmsmac yet:
brcmsmac bcma1:1: mfg 4bf core 812 rev 33 class 0 irq 18
brcmsmac: unknown device id 4365

So don't expect a working wifi from this patch :).

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Rafał Miłecki <zajec5@gmail.com>
Cc: <linux-wireless@vger.kernel.org>
---
 drivers/bcma/host_pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index bd46569e0e52..925842996986 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -295,6 +295,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
-- 
2.10.2

^ permalink raw reply related

* Re: linux-next: build warning after merge of the wireless-drivers-next tree
From: Barry Day @ 2016-11-28  8:16 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Stephen Rothwell, Jes Sorensen, Wireless, linux-next,
	linux-kernel
In-Reply-To: <87d1hg83rp.fsf@kamboji.qca.qualcomm.com>

On Mon, Nov 28, 2016 at 09:25:30AM +0200, Kalle Valo wrote:
> Stephen Rothwell <sfr@canb.auug.org.au> writes:
> 
> > Hi all,
> >
> > After merging the wireless-drivers-next tree, today's linux-next build
> > (x86_64 allmodconfig) produced this warning:
> >
> > In file included from include/linux/usb/ch9.h:35:0,
> >                  from include/linux/usb.h:5,
> >                  from drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:32:
> > drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c: In function 'rtl8xxxu_fill_txdesc_v2':
> > include/linux/device.h:1214:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
> >  #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
> >                                     ^
> > drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c:4841:6: note: 'rate' was declared here
> >   u32 rate;
> >       ^
> >
> > Introduced by commit
> >
> >   b4c3d9cfb607 ("rtl8xxxu: Pass tx_info to fill_txdesc in order to have access to retry count")
> >
> > This is a correct diagnosis.
> 
> Thanks for the report. Jes, can you send a patch to fix this? (Unless
> someone else beats to it.)
> 
> -- 
> Kalle Valo

I posted a patch on the 26th that fixes this

Barry

^ permalink raw reply

* Re: [PATCH v2] ath9k: Introduce airtime fairness scheduling between stations
From: Felix Fietkau @ 2016-11-28  9:34 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, Valo, Kalle
  Cc: linux-wireless@vger.kernel.org
In-Reply-To: <87inr8q5iq.fsf@toke.dk>

On 2016-11-27 16:58, Toke Høiland-Jørgensen wrote:
> "Valo, Kalle" <kvalo@qca.qualcomm.com> writes:
> 
>> (The make-wifi-fast list is annoying as it always spams me when it's on
>> CC, so dropped it.)
>>
>> Toke Høiland-Jørgensen <toke@toke.dk> writes:
>>
>>> This reworks the ath9k driver to schedule transmissions to connected
>>> stations in a way that enforces airtime fairness between them. It
>>> accomplishes this by measuring the time spent transmitting to or
>>> receiving from a station at TX and RX completion, and accounting this to
>>> a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
>>> deficit scheduler is employed at packet dequeue time, to control which
>>> station gets the next transmission opportunity.
>>>
>>> Airtime fairness can significantly improve the efficiency of the network
>>> when station rates vary. The following throughput values are from a
>>> simple three-station test scenario, where two stations operate at the
>>> highest HT20 rate, and one station at the lowest, and the scheduler is
>>> employed at the access point:
>>>
>>>                   Before   /   After
>>> Fast station 1:    19.17   /   25.09 Mbps
>>> Fast station 2:    19.83   /   25.21 Mbps
>>> Slow station:       2.58   /    1.77 Mbps
>>> Total:             41.58   /   52.07 Mbps
>>>
>>> The benefit of airtime fairness goes up the more stations are present.
>>> In a 30-station test with one station artificially limited to 1 Mbps,
>>> we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
>>>
>>> Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
>>
>> [...]
>>
>>> +void ath_acq_lock(struct ath_softc *sc, struct ath_acq *acq)
>>> +	__acquires(&acq->lock)
>>> +{
>>> +	spin_lock_bh(&acq->lock);
>>> +}
>>> +
>>> +void ath_acq_unlock(struct ath_softc *sc, struct ath_acq *acq)
>>> +	__releases(&acq->lock)
>>> +{
>>> +	spin_unlock_bh(&acq->lock);
>>> +}
>>
>> Why these? To me it looks like they just add an extra function jump and
>> unneccessary extra layer.
> 
> Well, there's already similar functions for the txq lock (ath_txq_lock()
> and ath_txq_unlock() in xmit.c), so figured I'd be consistent with
> those. And also that the __acquires and __releases macros were probably
> useful.
> 
> Also, won't the compiler automatically inline them?
Not necessarily, these functions are not static. I think it would be a
good idea to turn the ath_txq_lock/unlock functions into static inline
functions as well.

Please don't blindly repeat patterns that are already there, some of
them might just not make any sense at all ;)

- Felix

^ permalink raw reply

* Re: [PATCH v2] ath9k: Introduce airtime fairness scheduling between stations
From: Toke Høiland-Jørgensen @ 2016-11-28 10:00 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: Valo, Kalle, linux-wireless@vger.kernel.org
In-Reply-To: <4533523f-deb5-69f6-aeb7-f5312285b49e@nbd.name>

Felix Fietkau <nbd@nbd.name> writes:

> On 2016-11-27 16:58, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>> "Valo, Kalle" <kvalo@qca.qualcomm.com> writes:
>>=20
>>> (The make-wifi-fast list is annoying as it always spams me when it's on
>>> CC, so dropped it.)
>>>
>>> Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
>>>
>>>> This reworks the ath9k driver to schedule transmissions to connected
>>>> stations in a way that enforces airtime fairness between them. It
>>>> accomplishes this by measuring the time spent transmitting to or
>>>> receiving from a station at TX and RX completion, and accounting this =
to
>>>> a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
>>>> deficit scheduler is employed at packet dequeue time, to control which
>>>> station gets the next transmission opportunity.
>>>>
>>>> Airtime fairness can significantly improve the efficiency of the netwo=
rk
>>>> when station rates vary. The following throughput values are from a
>>>> simple three-station test scenario, where two stations operate at the
>>>> highest HT20 rate, and one station at the lowest, and the scheduler is
>>>> employed at the access point:
>>>>
>>>>                   Before   /   After
>>>> Fast station 1:    19.17   /   25.09 Mbps
>>>> Fast station 2:    19.83   /   25.21 Mbps
>>>> Slow station:       2.58   /    1.77 Mbps
>>>> Total:             41.58   /   52.07 Mbps
>>>>
>>>> The benefit of airtime fairness goes up the more stations are present.
>>>> In a 30-station test with one station artificially limited to 1 Mbps,
>>>> we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
>>>>
>>>> Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk>
>>>
>>> [...]
>>>
>>>> +void ath_acq_lock(struct ath_softc *sc, struct ath_acq *acq)
>>>> +	__acquires(&acq->lock)
>>>> +{
>>>> +	spin_lock_bh(&acq->lock);
>>>> +}
>>>> +
>>>> +void ath_acq_unlock(struct ath_softc *sc, struct ath_acq *acq)
>>>> +	__releases(&acq->lock)
>>>> +{
>>>> +	spin_unlock_bh(&acq->lock);
>>>> +}
>>>
>>> Why these? To me it looks like they just add an extra function jump and
>>> unneccessary extra layer.
>>=20
>> Well, there's already similar functions for the txq lock (ath_txq_lock()
>> and ath_txq_unlock() in xmit.c), so figured I'd be consistent with
>> those. And also that the __acquires and __releases macros were probably
>> useful.
>>=20
>> Also, won't the compiler automatically inline them?
> Not necessarily, these functions are not static. I think it would be a
> good idea to turn the ath_txq_lock/unlock functions into static inline
> functions as well.

Right, I'll re-send with these functions fixed, and send a separate
patch to fix ath_txq_lock*

> Please don't blindly repeat patterns that are already there, some of
> them might just not make any sense at all ;)

But that would imply that kernel developers are not infallible. Surely
that can't be right? ;)

-Toke

^ permalink raw reply

* [PATCH v3] ath9k: Introduce airtime fairness scheduling between stations
From: Toke Høiland-Jørgensen @ 2016-11-28 10:12 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20160617090929.31606-1-toke@toke.dk>

This reworks the ath9k driver to schedule transmissions to connected
stations in a way that enforces airtime fairness between them. It
accomplishes this by measuring the time spent transmitting to or
receiving from a station at TX and RX completion, and accounting this to
a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
deficit scheduler is employed at packet dequeue time, to control which
station gets the next transmission opportunity.

Airtime fairness can significantly improve the efficiency of the network
when station rates vary. The following throughput values are from a
simple three-station test scenario, where two stations operate at the
highest HT20 rate, and one station at the lowest, and the scheduler is
employed at the access point:

                  Before   /   After
Fast station 1:    19.17   /   25.09 Mbps
Fast station 2:    19.83   /   25.21 Mbps
Slow station:       2.58   /    1.77 Mbps
Total:             41.58   /   52.07 Mbps

The benefit of airtime fairness goes up the more stations are present.
In a 30-station test with one station artificially limited to 1 Mbps,
we have seen aggregate throughput go from 2.14 to 17.76 Mbps.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
Changes since v2:
  - Just call spin_*lock_bh() instead of introducing ath_acq_*lock()
    functions.
    
 drivers/net/wireless/ath/ath9k/ath9k.h     |  25 +++-
 drivers/net/wireless/ath/ath9k/channel.c   |  14 ++-
 drivers/net/wireless/ath/ath9k/debug.c     |   3 +
 drivers/net/wireless/ath/ath9k/debug.h     |  13 +++
 drivers/net/wireless/ath/ath9k/debug_sta.c |  54 +++++++++
 drivers/net/wireless/ath/ath9k/init.c      |   2 +
 drivers/net/wireless/ath/ath9k/main.c      |   6 +-
 drivers/net/wireless/ath/ath9k/recv.c      |  65 +++++++++++
 drivers/net/wireless/ath/ath9k/xmit.c      | 177 +++++++++++++++++++++--------
 9 files changed, 303 insertions(+), 56 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 378d345..79e4b71 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 #define ATH_TXFIFO_DEPTH           8
 #define ATH_TX_ERROR               0x01
 
+#define ATH_AIRTIME_QUANTUM        300 /* usec */
+
 /* Stop tx traffic 1ms before the GO goes away */
 #define ATH_P2P_PS_STOP_TIME       1000
 
@@ -247,6 +249,9 @@ struct ath_atx_tid {
 	bool has_queued;
 };
 
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
+
 struct ath_node {
 	struct ath_softc *sc;
 	struct ieee80211_sta *sta; /* station struct we're part of */
@@ -258,9 +263,12 @@ struct ath_node {
 
 	bool sleeping;
 	bool no_ps_filter;
+	s64 airtime_deficit[IEEE80211_NUM_ACS];
+	u32 airtime_rx_start;
 
 #ifdef CONFIG_ATH9K_STATION_STATISTICS
 	struct ath_rx_rate_stats rx_rate_stats;
+	struct ath_airtime_stats airtime_stats;
 #endif
 	u8 key_idx[4];
 
@@ -317,10 +325,16 @@ struct ath_rx {
 /* Channel Context */
 /*******************/
 
+struct ath_acq {
+	struct list_head acq_new;
+	struct list_head acq_old;
+	spinlock_t lock;
+};
+
 struct ath_chanctx {
 	struct cfg80211_chan_def chandef;
 	struct list_head vifs;
-	struct list_head acq[IEEE80211_NUM_ACS];
+	struct ath_acq acq[IEEE80211_NUM_ACS];
 	int hw_queue_base;
 
 	/* do not dereference, use for comparison only */
@@ -575,6 +589,8 @@ void ath_txq_schedule_all(struct ath_softc *sc);
 int ath_tx_init(struct ath_softc *sc, int nbufs);
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *q);
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+		     int width, int half_gi, bool shortPreamble);
 void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
 void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
 int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
@@ -963,6 +979,11 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
 
 #define ATH9K_NUM_CHANCTX  2 /* supports 2 operating channels */
 
+#define AIRTIME_USE_TX		BIT(0)
+#define AIRTIME_USE_RX		BIT(1)
+#define AIRTIME_USE_NEW_QUEUES	BIT(2)
+#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
+
 struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
@@ -1005,6 +1026,8 @@ struct ath_softc {
 	short nbcnvifs;
 	unsigned long ps_usecount;
 
+	u16 airtime_flags; /* AIRTIME_* */
+
 	struct ath_rx rx;
 	struct ath_tx tx;
 	struct ath_beacon beacon;
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 929dd70..b84539d 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *sc)
 		INIT_LIST_HEAD(&ctx->vifs);
 		ctx->txpower = ATH_TXPOWER_MAX;
 		ctx->flush_timeout = HZ / 5; /* 200ms */
-		for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
-			INIT_LIST_HEAD(&ctx->acq[j]);
+		for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
+			INIT_LIST_HEAD(&ctx->acq[j].acq_new);
+			INIT_LIST_HEAD(&ctx->acq[j].acq_old);
+			spin_lock_init(&ctx->acq[j].lock);
+		}
 	}
 }
 
@@ -1345,8 +1348,11 @@ void ath9k_offchannel_init(struct ath_softc *sc)
 	ctx->txpower = ATH_TXPOWER_MAX;
 	cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
 
-	for (i = 0; i < ARRAY_SIZE(ctx->acq); i++)
-		INIT_LIST_HEAD(&ctx->acq[i]);
+	for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
+		INIT_LIST_HEAD(&ctx->acq[i].acq_new);
+		INIT_LIST_HEAD(&ctx->acq[i].acq_old);
+		spin_lock_init(&ctx->acq[i].lock);
+	}
 
 	sc->offchannel.chan.offchannel = true;
 }
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 89a94dd..43930c3 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah)
 	debugfs_create_file("tpc", S_IRUSR | S_IWUSR,
 			    sc->debug.debugfs_phy, sc, &fops_tpc);
 
+	debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR,
+			   sc->debug.debugfs_phy, &sc->airtime_flags);
+
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index a078cdd..249f814 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -221,6 +221,11 @@ struct ath_rx_rate_stats {
 	} cck_stats[4];
 };
 
+struct ath_airtime_stats {
+	u32 rx_airtime;
+	u32 tx_airtime;
+};
+
 #define ANT_MAIN 0
 #define ANT_ALT  1
 
@@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
 void ath_debug_rate_stats(struct ath_softc *sc,
 			  struct ath_rx_status *rs,
 			  struct sk_buff *skb);
+void ath_debug_airtime(struct ath_softc *sc,
+		       struct ath_node *an,
+		       u32 rx, u32 tx);
 #else
 static inline void ath_debug_rate_stats(struct ath_softc *sc,
 					struct ath_rx_status *rs,
 					struct sk_buff *skb)
 {
 }
+static inline void ath_debug_airtime(struct ath_softc *sc,
+			      struct ath_node *an,
+			      u32 rx, u32 tx)
+{
+}
 #endif /* CONFIG_ATH9K_STATION_STATISTICS */
 
 #endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index 2a3a3c4..524cbf13 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -242,6 +242,59 @@ static const struct file_operations fops_node_recv = {
 	.llseek = default_llseek,
 };
 
+void ath_debug_airtime(struct ath_softc *sc,
+		struct ath_node *an,
+		u32 rx,
+		u32 tx)
+{
+	struct ath_airtime_stats *astats = &an->airtime_stats;
+
+	astats->rx_airtime += rx;
+	astats->tx_airtime += tx;
+}
+
+static ssize_t read_airtime(struct file *file, char __user *user_buf,
+			size_t count, loff_t *ppos)
+{
+	struct ath_node *an = file->private_data;
+	struct ath_airtime_stats *astats;
+	static const char *qname[4] = {
+		"VO", "VI", "BE", "BK"
+	};
+	u32 len = 0, size = 256;
+	char *buf;
+	size_t retval;
+	int i;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	astats = &an->airtime_stats;
+
+	len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
+	len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
+	len += scnprintf(buf + len, size - len, "Deficit: ");
+	for (i = 0; i < 4; i++)
+		len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
+	if (len < size)
+		buf[len++] = '\n';
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+
+static const struct file_operations fops_airtime = {
+	.read = read_airtime,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+
 void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
 			   struct ieee80211_vif *vif,
 			   struct ieee80211_sta *sta,
@@ -251,4 +304,5 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
 
 	debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr);
 	debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
+	debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime);
 }
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c0c8bf0..5aa665f 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 
 	/* Will be cleared in ath9k_start() */
 	set_bit(ATH_OP_INVALID, &common->op_flags);
+	sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
+			     AIRTIME_USE_NEW_QUEUES);
 
 	sc->sc_ah = ah;
 	sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 59e3bd0..58f06ce 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
 		goto out;
 
 	if (txq->mac80211_qnum >= 0) {
-		struct list_head *list;
+		struct ath_acq *acq;
 
-		list = &sc->cur_chan->acq[txq->mac80211_qnum];
-		if (!list_empty(list))
+		acq = &sc->cur_chan->acq[txq->mac80211_qnum];
+		if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old))
 			pending = true;
 	}
 out:
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 6697342..6cc36a8 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -991,6 +991,70 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,
 	}
 }
 
+static void ath_rx_count_airtime(struct ath_softc *sc,
+				 struct ath_rx_status *rs,
+				 struct sk_buff *skb)
+{
+	struct ath_node *an;
+	struct ath_acq *acq;
+	struct ath_vif *avp;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_sta *sta;
+	struct ieee80211_rx_status *rxs;
+	const struct ieee80211_rate *rate;
+	bool is_sgi, is_40, is_sp;
+	int phy;
+	u16 len = rs->rs_datalen;
+	u32 airtime = 0;
+	u8 tidno, acno;
+
+	if (!ieee80211_is_data(hdr->frame_control))
+		return;
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
+	if (!sta)
+		goto exit;
+	an = (struct ath_node *) sta->drv_priv;
+	avp = (struct ath_vif *) an->vif->drv_priv;
+	tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+	acno = TID_TO_WME_AC(tidno);
+	acq = &avp->chanctx->acq[acno];
+
+	rxs = IEEE80211_SKB_RXCB(skb);
+
+	is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI);
+	is_40 = !!(rxs->flag & RX_FLAG_40MHZ);
+	is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE);
+
+	if (!!(rxs->flag & RX_FLAG_HT)) {
+		/* MCS rates */
+
+		airtime += ath_pkt_duration(sc, rxs->rate_idx, len,
+					is_40, is_sgi, is_sp);
+	} else {
+
+		phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM;
+		rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx];
+		airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100,
+						len, rxs->rate_idx, is_sp);
+	}
+
+ 	if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
+		spin_lock_bh(&acq->lock);
+		an->airtime_deficit[acno] -= airtime;
+		if (an->airtime_deficit[acno] <= 0)
+			__ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
+		spin_unlock_bh(&acq->lock);
+	}
+	ath_debug_airtime(sc, an, airtime, 0);
+exit:
+	rcu_read_unlock();
+}
+
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 {
 	struct ath_rxbuf *bf;
@@ -1137,6 +1201,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		ath9k_antenna_check(sc, &rs);
 		ath9k_apply_ampdu_details(sc, &rs, rxs);
 		ath_debug_rate_stats(sc, &rs, skb);
+		ath_rx_count_airtime(sc, &rs, skb);
 
 		hdr = (struct ieee80211_hdr *)skb->data;
 		if (ieee80211_is_ack(hdr->frame_control))
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 486afa9..80d4793 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -124,21 +124,44 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
 		ath_tx_status(hw, skb);
 }
 
-static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
-			     struct ath_atx_tid *tid)
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
-	struct list_head *list;
 	struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
 	struct ath_chanctx *ctx = avp->chanctx;
+	struct ath_acq *acq;
+	struct list_head *tid_list;
+	u8 acno = TID_TO_WME_AC(tid->tidno);
 
-	if (!ctx)
+	if (!ctx || !list_empty(&tid->list))
 		return;
 
-	list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
-	if (list_empty(&tid->list))
-		list_add_tail(&tid->list, list);
+
+	acq = &ctx->acq[acno];
+	if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) &&
+	    tid->an->airtime_deficit[acno] > 0)
+		tid_list = &acq->acq_new;
+	else
+		tid_list = &acq->acq_old;
+
+	list_add_tail(&tid->list, tid_list);
 }
 
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+	struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
+	struct ath_chanctx *ctx = avp->chanctx;
+	struct ath_acq *acq;
+
+	if (!ctx || !list_empty(&tid->list))
+		return;
+
+	acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
+	spin_lock_bh(&acq->lock);
+	__ath_tx_queue_tid(sc, tid);
+	spin_unlock_bh(&acq->lock);
+}
+
+
 void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
 {
 	struct ath_softc *sc = hw->priv;
@@ -153,7 +176,7 @@ void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
 	ath_txq_lock(sc, txq);
 
 	tid->has_queued = true;
-	ath_tx_queue_tid(sc, txq, tid);
+	ath_tx_queue_tid(sc, tid);
 	ath_txq_schedule(sc, txq);
 
 	ath_txq_unlock(sc, txq);
@@ -660,7 +683,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 		skb_queue_splice_tail(&bf_pending, &tid->retry_q);
 		if (!an->sleeping) {
-			ath_tx_queue_tid(sc, txq, tid);
+			ath_tx_queue_tid(sc, tid);
 
 			if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
 				tid->clear_ps_filter = true;
@@ -688,6 +711,53 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
     return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
 }
 
+static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq,
+				 struct ath_buf *bf, struct ath_tx_status *ts)
+{
+	struct ath_node *an;
+	struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum];
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_tx_rate rates[4];
+	struct ieee80211_sta *sta;
+	int i;
+	u32 airtime = 0;
+
+	skb = bf->bf_mpdu;
+	if(!skb)
+		return;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	memcpy(rates, bf->rates, sizeof(rates));
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+	if(!sta)
+		goto exit;
+
+
+	an = (struct ath_node *) sta->drv_priv;
+
+	airtime += ts->duration * (ts->ts_longretry + 1);
+
+	for(i=0; i < ts->ts_rateindex; i++)
+		airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count;
+
+	if (!!(sc->airtime_flags & AIRTIME_USE_TX)) {
+		spin_lock_bh(&acq->lock);
+		an->airtime_deficit[txq->mac80211_qnum] -= airtime;
+		if (an->airtime_deficit[txq->mac80211_qnum] <= 0)
+			__ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb));
+		spin_unlock_bh(&acq->lock);
+	}
+	ath_debug_airtime(sc, an, 0, airtime);
+
+exit:
+	rcu_read_unlock();
+}
+
 static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
 				  struct ath_tx_status *ts, struct ath_buf *bf,
 				  struct list_head *bf_head)
@@ -709,6 +779,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
 
 	ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
 					     ts->ts_rateindex);
+	ath_tx_count_airtime(sc, txq, bf, ts);
 
 	hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
 	sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
@@ -1068,8 +1139,8 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
  * width  - 0 for 20 MHz, 1 for 40 MHz
  * half_gi - to use 4us v/s 3.6 us for symbol time
  */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
-			    int width, int half_gi, bool shortPreamble)
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
+		     int width, int half_gi, bool shortPreamble)
 {
 	u32 nbits, nsymbits, duration, nsymbols;
 	int streams;
@@ -1467,7 +1538,7 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
 }
 
 static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
-			      struct ath_atx_tid *tid, bool *stop)
+			      struct ath_atx_tid *tid)
 {
 	struct ath_buf *bf;
 	struct ieee80211_tx_info *tx_info;
@@ -1489,7 +1560,6 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
 	    (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
 		__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
-		*stop = true;
 		return false;
 	}
 
@@ -1613,7 +1683,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
 		ath_txq_lock(sc, txq);
 		tid->clear_ps_filter = true;
 		if (ath_tid_has_buffered(tid)) {
-			ath_tx_queue_tid(sc, txq, tid);
+			ath_tx_queue_tid(sc, tid);
 			ath_txq_schedule(sc, txq);
 		}
 		ath_txq_unlock_complete(sc, txq);
@@ -1912,9 +1982,10 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_atx_tid *tid, *last_tid;
+	struct ath_atx_tid *tid;
 	struct list_head *tid_list;
-	bool sent = false;
+	struct ath_acq *acq;
+	bool active = AIRTIME_ACTIVE(sc->airtime_flags);
 
 	if (txq->mac80211_qnum < 0)
 		return;
@@ -1923,48 +1994,55 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 		return;
 
 	spin_lock_bh(&sc->chan_lock);
-	tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
-
-	if (list_empty(tid_list)) {
-		spin_unlock_bh(&sc->chan_lock);
-		return;
-	}
-
 	rcu_read_lock();
+	acq = &sc->cur_chan->acq[txq->mac80211_qnum];
 
-	last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
-	while (!list_empty(tid_list)) {
-		bool stop = false;
-
-		if (sc->cur_chan->stopped)
-			break;
-
-		tid = list_first_entry(tid_list, struct ath_atx_tid, list);
-		list_del_init(&tid->list);
+	if (sc->cur_chan->stopped)
+		goto out;
 
-		if (ath_tx_sched_aggr(sc, txq, tid, &stop))
-			sent = true;
+begin:
+	tid_list = &acq->acq_new;
+	if (list_empty(tid_list)) {
+		tid_list = &acq->acq_old;
+		if (list_empty(tid_list))
+			goto out;
+	}
+	tid = list_first_entry(tid_list, struct ath_atx_tid, list);
 
-		/*
-		 * add tid to round-robin queue if more frames
-		 * are pending for the tid
-		 */
-		if (ath_tid_has_buffered(tid))
-			ath_tx_queue_tid(sc, txq, tid);
+	if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
+		spin_lock_bh(&acq->lock);
+		tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM;
+		list_move_tail(&tid->list, &acq->acq_old);
+		spin_unlock_bh(&acq->lock);
+		goto begin;
+	}
 
-		if (stop)
-			break;
+	if (!ath_tid_has_buffered(tid)) {
+		spin_lock_bh(&acq->lock);
+		if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old))
+			list_move_tail(&tid->list, &acq->acq_old);
+		else {
+			list_del_init(&tid->list);
+		}
+		spin_unlock_bh(&acq->lock);
+		goto begin;
+	}
 
-		if (tid == last_tid) {
-			if (!sent)
-				break;
 
-			sent = false;
-			last_tid = list_entry(tid_list->prev,
-					      struct ath_atx_tid, list);
+	/*
+	 * If we succeed in scheduling something, immediately restart to make
+	 * sure we keep the HW busy.
+	 */
+	if(ath_tx_sched_aggr(sc, txq, tid)) {
+		if (!active) {
+			spin_lock_bh(&acq->lock);
+			list_move_tail(&tid->list, &acq->acq_old);
+			spin_unlock_bh(&acq->lock);
 		}
+		goto begin;
 	}
 
+out:
 	rcu_read_unlock();
 	spin_unlock_bh(&sc->chan_lock);
 }
@@ -2818,6 +2896,9 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 	struct ath_atx_tid *tid;
 	int tidno, acno;
 
+	for (acno = 0; acno < IEEE80211_NUM_ACS; acno++)
+		an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM;
+
 	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
 		tid = ath_node_to_tid(an, tidno);
 		tid->an        = an;

base-commit: 705d7aa062203226c8df73f18622664e30bd8a61
-- 
2.10.2

^ permalink raw reply related

* [PATCH] ath9k: Turn ath_txq_lock/unlock() into static inlines.
From: Toke Høiland-Jørgensen @ 2016-11-28 10:20 UTC (permalink / raw)
  To: linux-wireless; +Cc: Toke Høiland-Jørgensen

These are one-line functions that just call spin_lock/unlock_bh(); turn
them into static inlines to avoid the function call overhead.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 drivers/net/wireless/ath/ath9k/ath9k.h | 11 +++++++++--
 drivers/net/wireless/ath/ath9k/xmit.c  | 12 ------------
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 378d345..dca4aaa3 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -555,6 +555,15 @@ static inline void ath_chanctx_check_active(struct ath_softc *sc,
 
 #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
 
+static inline void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
+{
+	spin_lock_bh(&txq->axq_lock);
+}
+static inline void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
+{
+	spin_unlock_bh(&txq->axq_lock);
+}
+
 void ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
@@ -562,8 +571,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs);
 void ath_rx_cleanup(struct ath_softc *sc);
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq);
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq);
 void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 bool ath_drain_all_txq(struct ath_softc *sc);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 486afa9..e5c0829 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -97,18 +97,6 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	dev_kfree_skb(skb);
 }
 
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
-	__acquires(&txq->axq_lock)
-{
-	spin_lock_bh(&txq->axq_lock);
-}
-
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
-	__releases(&txq->axq_lock)
-{
-	spin_unlock_bh(&txq->axq_lock);
-}
-
 void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
 	__releases(&txq->axq_lock)
 {

base-commit: 705d7aa062203226c8df73f18622664e30bd8a61
-- 
2.10.2

^ permalink raw reply related

* Re: [PATCH] bcma: add Dell Inspiron 3148
From: Rafał Miłecki @ 2016-11-28 11:26 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-wireless@vger.kernel.org, Linux Kernel Mailing List
In-Reply-To: <20161128075712.10785-1-jslaby@suse.cz>

On 28 November 2016 at 08:57, Jiri Slaby <jslaby@suse.cz> wrote:
> This is what is in the laptop:
> 01:00.0 Network controller [0280]: Broadcom Limited BCM43142 802.11b/g/n =
[14e4:4365] (rev 01)
>         Subsystem: Dell Device [1028:0018]
>         Flags: bus master, fast devsel, latency 0, IRQ 18
>         Memory at b0400000 (64-bit, non-prefetchable) [size=3D32K]
>         Capabilities: [40] Power Management version 3
>         Capabilities: [58] Vendor Specific Information: Len=3D78 <?>
>         Capabilities: [48] MSI: Enable- Count=3D1/1 Maskable- 64bit+
>         Capabilities: [d0] Express Endpoint, MSI 00
>         Capabilities: [100] Advanced Error Reporting
>         Capabilities: [13c] Virtual Channel
>         Capabilities: [160] Device Serial Number 00-00-9a-ff-ff-f3-40-b8
>         Capabilities: [16c] Power Budgeting <?>
>
> With the patch, I can see:
> bcma: bus0: Found chip with id 43142, rev 0x01 and package 0x08
> bcma: bus0: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x28, cl=
ass 0x0)
> bcma: bus0: Core 1 found: IEEE 802.11 (manuf 0x4BF, id 0x812, rev 0x21, c=
lass 0x0)
> bcma: bus0: Core 2 found: PCIe (manuf 0x4BF, id 0x820, rev 0x16, class 0x=
0)
> bcma: bus0: Core 3 found: UNKNOWN (manuf 0x43B, id 0x368, rev 0x00, class=
 0x0)
> bcma: bus0: Bus registered
>
> The wifi is not currently supported by brcmsmac yet:
> brcmsmac bcma1:1: mfg 4bf core 812 rev 33 class 0 irq 18
> brcmsmac: unknown device id 4365
>
> So don't expect a working wifi from this patch :).
>
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: Rafa=C5=82 Mi=C5=82ecki <zajec5@gmail.com>
> Cc: <linux-wireless@vger.kernel.org>

Looks good, thanks.

--=20
Rafa=C5=82

^ permalink raw reply


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