Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: NL80211_SCAN_FLAG_RANDOM_ADDR ?
From: Denis Kenzior @ 2019-04-12  1:26 UTC (permalink / raw)
  To: Ben Greear, linux-wireless
In-Reply-To: <fcd9fcc2-86dd-8cd7-1822-efb7df498cf8@candelatech.com>

Hi Ben,

On 04/11/2019 06:20 PM, Ben Greear wrote:
> On 4/11/19 4:19 PM, Ben Greear wrote:
>> On 4/11/19 3:30 PM, Denis Kenzior wrote:
>>> Hi,
>>>
>>> I've been poking around at how this flag is used and I noticed this 
>>> check in net/wireless/nl80211.c:
>>>
>>> nl80211_check_scan_flags()
>>>
>>>          if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
>>>                  int err;
>>>
>>>                  if (!(wiphy->features & randomness_flag) ||
>>>                      (wdev && wdev->current_bss))
>>>                          return -EOPNOTSUPP;
>>>
>>>
>>> The above disallows the use of RANDOM_ADDR for scans while connected. 
>>> The nl80211.h uapi header seems to concur:
>>>
>>>   "@NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports 
>>> using a random MAC address during scan (if the device is unassociated);"
>>>
>>> However, if I create a P2P Device (in addition to the default STA 
>>> device), the kernel happily lets me scan on the wdev while the STA 
>>> interface is connected.
>>>
>>> sudo iw phy0 interface add p2p type __p2pdev
>>> sudo iw wdev 0x2 p2p start
>>> sudo iw wdev 0x2 scan randomize
>>>
>>> So the immediate question I have is, should the RANDOM_ADDR flag 
>>> indeed be limited to unassociated STA interfaces?  It would seem the 
>>> hardware is capable randomizing even when connected? Please educate 
>>> me :)
>>
>> You can be sure that each driver/hardware has its own bugs and 
>> limitations related to this.
>>
>> Ath10k wave 1 and wave 2 that I am aware of would ignore and/or not 
>> ACK probe responses
>> sent back to an MAC address that is not that of the station itself.  
>> And changing the mac of a station
>> would require complete re-association AFAIK.  That is likely just one 
>> of the many issues.

Yes, I understand that some hardware would not support this.  But the 
question is does this check belong at the nl80211 layer (e.g. no 
hardware can do this) vs somewhere at the driver layer + additional 
feature bit as needed.

> 
> I should add:  If you really want to scan in this manner, you could just 
> create a new station vdev with
> random addr and have it do the scanning, then delete it when done?  The 
> original station will continue on
> its way unmolested.
> 

So you mean something like:
sudo iw phy0 interface add sta2 type station
sudo iw dev sta2 scan randomize
command failed: Network is down (-100)
sudo ifconfig sta2 up
SIOCSIFFLAGS: Device or resource busy

I guess I'm running into this:

	valid interface combinations:
		 * #{ managed } <= 1, #{ AP, P2P-client, P2P-GO } <= 1, #{ P2P-device 
} <= 1,
		   total <= 3, #channels <= 2

Or did you mean something else?

Regards,
-Denis

^ permalink raw reply

* Re: NL80211_SCAN_FLAG_RANDOM_ADDR ?
From: Ben Greear @ 2019-04-11 23:20 UTC (permalink / raw)
  To: Denis Kenzior, linux-wireless
In-Reply-To: <913e7464-ea6e-bb22-141a-ab76019bed3f@candelatech.com>

On 4/11/19 4:19 PM, Ben Greear wrote:
> On 4/11/19 3:30 PM, Denis Kenzior wrote:
>> Hi,
>>
>> I've been poking around at how this flag is used and I noticed this check in net/wireless/nl80211.c:
>>
>> nl80211_check_scan_flags()
>>
>>          if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
>>                  int err;
>>
>>                  if (!(wiphy->features & randomness_flag) ||
>>                      (wdev && wdev->current_bss))
>>                          return -EOPNOTSUPP;
>>
>>
>> The above disallows the use of RANDOM_ADDR for scans while connected. The nl80211.h uapi header seems to concur:
>>
>>   "@NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a random MAC address during scan (if the device is unassociated);"
>>
>> However, if I create a P2P Device (in addition to the default STA device), the kernel happily lets me scan on the wdev while the STA interface is connected.
>>
>> sudo iw phy0 interface add p2p type __p2pdev
>> sudo iw wdev 0x2 p2p start
>> sudo iw wdev 0x2 scan randomize
>>
>> So the immediate question I have is, should the RANDOM_ADDR flag indeed be limited to unassociated STA interfaces?  It would seem the hardware is capable 
>> randomizing even when connected? Please educate me :)
> 
> You can be sure that each driver/hardware has its own bugs and limitations related to this.
> 
> Ath10k wave 1 and wave 2 that I am aware of would ignore and/or not ACK probe responses
> sent back to an MAC address that is not that of the station itself.  And changing the mac of a station
> would require complete re-association AFAIK.  That is likely just one of the many issues.

I should add:  If you really want to scan in this manner, you could just create a new station vdev with
random addr and have it do the scanning, then delete it when done?  The original station will continue on
its way unmolested.

Thanks,
Ben


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: NL80211_SCAN_FLAG_RANDOM_ADDR ?
From: Ben Greear @ 2019-04-11 23:19 UTC (permalink / raw)
  To: Denis Kenzior, linux-wireless
In-Reply-To: <e09a9bc7-9774-334b-53e8-13e1d781bee3@gmail.com>

On 4/11/19 3:30 PM, Denis Kenzior wrote:
> Hi,
> 
> I've been poking around at how this flag is used and I noticed this check in net/wireless/nl80211.c:
> 
> nl80211_check_scan_flags()
> 
>          if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
>                  int err;
> 
>                  if (!(wiphy->features & randomness_flag) ||
>                      (wdev && wdev->current_bss))
>                          return -EOPNOTSUPP;
> 
> 
> The above disallows the use of RANDOM_ADDR for scans while connected. The nl80211.h uapi header seems to concur:
> 
>   "@NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a random MAC address during scan (if the device is unassociated);"
> 
> However, if I create a P2P Device (in addition to the default STA device), the kernel happily lets me scan on the wdev while the STA interface is connected.
> 
> sudo iw phy0 interface add p2p type __p2pdev
> sudo iw wdev 0x2 p2p start
> sudo iw wdev 0x2 scan randomize
> 
> So the immediate question I have is, should the RANDOM_ADDR flag indeed be limited to unassociated STA interfaces?  It would seem the hardware is capable 
> randomizing even when connected? Please educate me :)

You can be sure that each driver/hardware has its own bugs and limitations related to this.

Ath10k wave 1 and wave 2 that I am aware of would ignore and/or not ACK probe responses
sent back to an MAC address that is not that of the station itself.  And changing the mac of a station
would require complete re-association AFAIK.  That is likely just one of the many issues.

Thanks,
Ben


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Zero TID queue stats in dump_htt_stats?
From: Joshua Zhao @ 2019-04-11 23:13 UTC (permalink / raw)
  To: linux-wireless, ath10k

Hi,
I'm running ath10k driver on QCA IPQ4019. When I enable htt_stats_mask
by "echo 0x1FFFF >
/sys/kernel/debug/ieee80211/phy0/ath10k/htt_stats_mask" I can see tx
rates / rx rates / etc get updated. But the TID queue related stats
are always 0.
Is this known and expected?  Is there anything related to that now
fq_codel in mac80211 handles txq scheduling?

Thanks,
Joshua

^ permalink raw reply

* NL80211_SCAN_FLAG_RANDOM_ADDR ?
From: Denis Kenzior @ 2019-04-11 22:30 UTC (permalink / raw)
  To: linux-wireless

Hi,

I've been poking around at how this flag is used and I noticed this 
check in net/wireless/nl80211.c:

nl80211_check_scan_flags()

         if (*flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
                 int err;

                 if (!(wiphy->features & randomness_flag) ||
                     (wdev && wdev->current_bss))
                         return -EOPNOTSUPP;


The above disallows the use of RANDOM_ADDR for scans while connected. 
The nl80211.h uapi header seems to concur:

  "@NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports 
using a random MAC address during scan (if the device is unassociated);"

However, if I create a P2P Device (in addition to the default STA 
device), the kernel happily lets me scan on the wdev while the STA 
interface is connected.

sudo iw phy0 interface add p2p type __p2pdev
sudo iw wdev 0x2 p2p start
sudo iw wdev 0x2 scan randomize

So the immediate question I have is, should the RANDOM_ADDR flag indeed 
be limited to unassociated STA interfaces?  It would seem the hardware 
is capable randomizing even when connected? Please educate me :)

Regards,
-Denis

^ permalink raw reply

* iwlwifi: BUG: unable to handle kernel paging request at ffffc90000e1c808
From: Michal Hocko @ 2019-04-11 21:07 UTC (permalink / raw)
  To: Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, linux-wireless
  Cc: LKML

Hi,
I have just encountered the following splat with 5.1-rc4. Is this a
known problem? Greping throug older logs show that "Error sending SCAN_CFG_CMD"
is not new. In older kernels it was followed by "Start IWL Error Log Dump:"
but it oopsed now. I was running 5.0 previously. Let me know if you need
more information.

[ 3076.724445] iwlwifi 0000:01:00.0: Error sending SCAN_CFG_CMD: time out after 2000ms.
[ 3076.724449] iwlwifi 0000:01:00.0: Current CMD queue read_ptr 38 write_ptr 39
[ 3076.724468] BUG: unable to handle kernel paging request at ffffc90000e1c808
[ 3076.724469] #PF error: [normal kernel read fault]
[ 3076.724470] PGD 245924067 P4D 245924067 PUD 245925067 PMD 24441e067 PTE 0
[ 3076.724473] Oops: 0000 [#1] PREEMPT SMP PTI
[ 3076.724475] CPU: 2 PID: 10490 Comm: kworker/2:0 Not tainted 5.1.0-rc4-00003-gfd008d1a7a20 #50
[ 3076.724476] Hardware name: Dell Inc. Latitude E7470/0T6HHJ, BIOS 1.5.3 04/18/2016
[ 3076.724500] Workqueue: events iwl_mvm_tcm_work [iwlmvm]
[ 3076.724506] RIP: 0010:iwl_trans_pcie_read32+0xe/0x11 [iwlwifi]
[ 3076.724508] Code: f6 48 03 b7 28 a2 00 00 88 16 c3 0f 1f 44 00 00 89 f6 48 03 b7 28 a2 00 00 89 16 c3 0f 1f 44 00 00 89 f6 48 03 b7 28 a2 00 00 <8b> 06 c3 0f 1f 44 00 00 48 8b 47 10 83 78 48 13 19 c0 25 00 00 10
[ 3076.724509] RSP: 0000:ffffc9000622fcb0 EFLAGS: 00010282
[ 3076.724510] RAX: ffffffffa024ce32 RBX: ffff888243000018 RCX: 0000000000000003
[ 3076.724512] RDX: 0000000008000005 RSI: ffffc90000e1c808 RDI: ffff888243000018
[ 3076.724513] RBP: ffff888243009154 R08: 0000000000000001 R09: ffffffff824e062f
[ 3076.724514] R10: 0000000000000000 R11: ffffc9000622f9e7 R12: 00000001000a97a6
[ 3076.724514] R13: 0000000000000006 R14: ffff888242af4000 R15: ffff88824300a268
[ 3076.724516] FS:  0000000000000000(0000) GS:ffff888245f00000(0000) knlGS:0000000000000000
[ 3076.724517] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3076.724518] CR2: ffffc90000e1c808 CR3: 000000010131c003 CR4: 00000000003606e0
[ 3076.724519] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 3076.724520] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 3076.724521] Call Trace:
[ 3076.724527]  iwl_trans_sync_nmi+0xac/0x18a [iwlwifi]
[ 3076.724533]  iwl_trans_pcie_send_hcmd+0x2e1/0x3b2 [iwlwifi]
[ 3076.724536]  ? wait_woken+0x6d/0x6d
[ 3076.724542]  iwl_trans_send_cmd+0x99/0xb4 [iwlwifi]
[ 3076.724547]  iwl_mvm_send_cmd+0x2a/0x5c [iwlmvm]
[ 3076.724554]  iwl_mvm_config_scan+0x38b/0x3c2 [iwlmvm]
[ 3076.724560]  ? iwl_mvm_update_low_latency+0xbb/0xbb [iwlmvm]
[ 3076.724565]  iwl_mvm_recalc_tcm+0x473/0x48c [iwlmvm]
[ 3076.724569]  process_one_work+0x1e2/0x32b
[ 3076.724571]  ? pwq_unbound_release_workfn+0xc9/0xc9
[ 3076.724573]  worker_thread+0x1d8/0x2a3
[ 3076.724574]  kthread+0x114/0x11c
[ 3076.724576]  ? kthread_park+0x76/0x76
[ 3076.724579]  ret_from_fork+0x3a/0x50
[ 3076.724581] Modules linked in: tun ctr ccm binfmt_misc snd_hda_codec_hdmi arc4 snd_hda_codec_realtek snd_hda_codec_generic i915 i2c_algo_bit iosf_mbi snd_hda_intel iwlmvm drm_kms_helper uvcvideo snd_hda_codec videobuf2_vmalloc cfbfillrect mac80211 videobuf2_memops videobuf2_v4l2 snd_hda_core syscopyarea videobuf2_common cfbimgblt sysfillrect snd_pcm_oss videodev snd_mixer_oss sysimgblt coretemp iwlwifi fb_sys_fops hwmon cfbcopyarea x86_pkg_temp_thermal fb snd_pcm fbdev kvm_intel media drm kvm drm_panel_orientation_quirks snd_timer irqbypass i2c_i801 cfg80211 snd i2c_core video backlight
[ 3076.724596] CR2: ffffc90000e1c808
[ 3076.724598] ---[ end trace da5234017dd6ffd3 ]---
[ 3076.724603] RIP: 0010:iwl_trans_pcie_read32+0xe/0x11 [iwlwifi]
[ 3076.724605] Code: f6 48 03 b7 28 a2 00 00 88 16 c3 0f 1f 44 00 00 89 f6 48 03 b7 28 a2 00 00 89 16 c3 0f 1f 44 00 00 89 f6 48 03 b7 28 a2 00 00 <8b> 06 c3 0f 1f 44 00 00 48 8b 47 10 83 78 48 13 19 c0 25 00 00 10
[ 3076.724606] RSP: 0000:ffffc9000622fcb0 EFLAGS: 00010282
[ 3076.724607] RAX: ffffffffa024ce32 RBX: ffff888243000018 RCX: 0000000000000003
[ 3076.724608] RDX: 0000000008000005 RSI: ffffc90000e1c808 RDI: ffff888243000018
[ 3076.724609] RBP: ffff888243009154 R08: 0000000000000001 R09: ffffffff824e062f
[ 3076.724610] R10: 0000000000000000 R11: ffffc9000622f9e7 R12: 00000001000a97a6
[ 3076.724611] R13: 0000000000000006 R14: ffff888242af4000 R15: ffff88824300a268
[ 3076.724612] FS:  0000000000000000(0000) GS:ffff888245f00000(0000) knlGS:0000000000000000
[ 3076.724613] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3076.724614] CR2: ffffc90000e1c808 CR3: 000000010131c003 CR4: 00000000003606e0
[ 3076.724615] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 3076.724616] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 3077.332767] iwlwifi 0000:01:00.0: Queue 0 is inactive on fifo 2 and stuck for 2500 ms. SW [38, 39] HW [162, 162] FH TRB=0x0a5a5a5a2
[ 3084.756712] iwlwifi 0000:01:00.0: Queue 10 is inactive on fifo 2 and stuck for 10000 ms. SW [81, 89] HW [162, 162] FH TRB=0x0a5a5a5a2
[ 3097.044641] iwlwifi 0000:01:00.0: Queue 11 is inactive on fifo 2 and stuck for 10000 ms. SW [203, 204] HW [162, 162] FH TRB=0x0a5a5a5a2

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* [PATCH v4 3/3] mac80211: probe unexercised mesh links
From: Rajkumar Manoharan @ 2019-04-11 20:47 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Rajkumar Manoharan
In-Reply-To: <1555015646-7655-1-git-send-email-rmanohar@codeaurora.org>

The requirement for mesh link metric refreshing, is that from one
mesh point we be able to send some data frames to other mesh points
which are not currently selected as a primary traffic path, but which
are only 1 hop away. The absence of the primary path to the chosen node
makes it necessary to apply some form of marking on a chosen packet
stream so that the packets can be properly steered to the selected node
for testing, and not by the regular mesh path lookup.

Tested-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
---
v2: fix addr1 for injected frames
v3: bugfix in filling DA

 include/net/mac80211.h     |  2 ++
 net/mac80211/cfg.c         |  1 +
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/mesh_hwmp.c   |  4 ++++
 net/mac80211/tx.c          | 36 ++++++++++++++++++++++++++++++++++++
 5 files changed, 45 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d66fbfe8d55d..76a443f32fc8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -807,6 +807,7 @@ enum mac80211_tx_info_flags {
  * @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
  * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
  * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
+ * @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -816,6 +817,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTRL_RATE_INJECT		= BIT(2),
 	IEEE80211_TX_CTRL_AMSDU			= BIT(3),
 	IEEE80211_TX_CTRL_FAST_XMIT		= BIT(4),
+	IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP	= BIT(5),
 };
 
 /*
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ba6e4080d63d..52e6a091b7e4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4035,4 +4035,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
 	.get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
 	.start_pmsr = ieee80211_start_pmsr,
 	.abort_pmsr = ieee80211_abort_pmsr,
+	.probe_mesh_link = ieee80211_probe_mesh_link,
 };
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8a99bcfe81ec..1cd6a8bb17f2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1780,6 +1780,8 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 			      const u8 *buf, size_t len,
 			      const u8 *dest, __be16 proto, bool unencrypted);
+int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+			      const u8 *buf, size_t len);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 2c5929c0fa62..bf8e13cd5fd1 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1135,6 +1135,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
 	if (ieee80211_is_qos_nullfunc(hdr->frame_control))
 		return 0;
 
+	/* Allow injected packets to bypass mesh routing */
+	if (info->control.flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
+		return 0;
+
 	if (!mesh_nexthop_lookup(sdata, skb))
 		return 0;
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ffe35fc89351..2b16a2527a6a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2607,6 +2607,13 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 			goto free;
 		}
 		band = chanctx_conf->def.chan->band;
+
+		/* For injected frames, fill RA right away as nexthop lookup
+		 * will be skipped.
+		 */
+		if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) &&
+		    is_zero_ether_addr(hdr.addr1))
+			memcpy(hdr.addr1, skb->data, ETH_ALEN);
 		break;
 #endif
 	case NL80211_IFTYPE_STATION:
@@ -5093,3 +5100,32 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 
 	return 0;
 }
+
+int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+			      const u8 *buf, size_t len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + len +
+			    30 + /* header size */
+			    18); /* 11s header size */
+	if (!skb)
+		return -ENOMEM;
+
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+	skb_put_data(skb, buf, len);
+
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_802_3);
+	skb_reset_network_header(skb);
+	skb_reset_mac_header(skb);
+
+	local_bh_disable();
+	__ieee80211_subif_start_xmit(skb, skb->dev, 0,
+				     IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP);
+	local_bh_enable();
+
+	return 0;
+}
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 2/3] mac80211: add option for setting control flags
From: Rajkumar Manoharan @ 2019-04-11 20:47 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Rajkumar Manoharan
In-Reply-To: <1555015646-7655-1-git-send-email-rmanohar@codeaurora.org>

Allows setting of control flags of skb cb - if needed -
when calling ieee80211_subif_start_xmit().

Tested-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
---
 net/mac80211/ieee80211_i.h |  3 ++-
 net/mac80211/tdls.c        |  2 +-
 net/mac80211/tx.c          | 18 +++++++++++-------
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 861bf8312177..8a99bcfe81ec 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1762,7 +1762,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev);
 void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev,
-				  u32 info_flags);
+				  u32 info_flags,
+				  u32 ctrl_flags);
 void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
 			      struct sk_buff_head *skbs);
 struct sk_buff *
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index d30690d79a58..24c37f91ca46 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1056,7 +1056,7 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
 
 	/* disable bottom halves when entering the Tx path */
 	local_bh_disable();
-	__ieee80211_subif_start_xmit(skb, dev, flags);
+	__ieee80211_subif_start_xmit(skb, dev, flags, 0);
 	local_bh_enable();
 
 	return ret;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1e82ba7c34e3..ffe35fc89351 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2432,6 +2432,7 @@ static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
  * @sdata: virtual interface to build the header for
  * @skb: the skb to build the header in
  * @info_flags: skb flags to set
+ * @ctrl_flags: info control flags to set
  *
  * This function takes the skb with 802.3 header and reformats the header to
  * the appropriate IEEE 802.11 header based on which interface the packet is
@@ -2447,7 +2448,7 @@ static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
  */
 static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 					   struct sk_buff *skb, u32 info_flags,
-					   struct sta_info *sta)
+					   struct sta_info *sta, u32 ctrl_flags)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_info *info;
@@ -2824,6 +2825,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 	info->flags = info_flags;
 	info->ack_frame_id = info_id;
 	info->band = band;
+	info->control.flags = ctrl_flags;
 
 	return skb;
  free:
@@ -3805,7 +3807,8 @@ void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
 
 void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev,
-				  u32 info_flags)
+				  u32 info_flags,
+				  u32 ctrl_flags)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
@@ -3879,7 +3882,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 		skb->prev = NULL;
 		skb->next = NULL;
 
-		skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
+		skb = ieee80211_build_hdr(sdata, skb, info_flags,
+					  sta, ctrl_flags);
 		if (IS_ERR(skb))
 			goto out;
 
@@ -4019,9 +4023,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 		__skb_queue_head_init(&queue);
 		ieee80211_convert_to_unicast(skb, dev, &queue);
 		while ((skb = __skb_dequeue(&queue)))
-			__ieee80211_subif_start_xmit(skb, dev, 0);
+			__ieee80211_subif_start_xmit(skb, dev, 0, 0);
 	} else {
-		__ieee80211_subif_start_xmit(skb, dev, 0);
+		__ieee80211_subif_start_xmit(skb, dev, 0, 0);
 	}
 
 	return NETDEV_TX_OK;
@@ -4046,7 +4050,7 @@ struct sk_buff *
 		goto out;
 	}
 
-	skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
+	skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0);
 	if (IS_ERR(skb))
 		goto out;
 
@@ -5084,7 +5088,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 	skb_reset_mac_header(skb);
 
 	local_bh_disable();
-	__ieee80211_subif_start_xmit(skb, skb->dev, flags);
+	__ieee80211_subif_start_xmit(skb, skb->dev, flags, 0);
 	local_bh_enable();
 
 	return 0;
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 1/3] cfg80211: add support to probe unexercised mesh link
From: Rajkumar Manoharan @ 2019-04-11 20:47 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Rajkumar Manoharan
In-Reply-To: <1555015646-7655-1-git-send-email-rmanohar@codeaurora.org>

Adding support to allow mesh HWMP to measure link metrics on unexercised
direct mesh path by sending some data frames to other mesh points which
are not currently selected as a primary traffic path but only 1 hop away.
The absence of the primary path to the chosen node makes it necessary to
apply some form of marking on a chosen packet stream so that the packets
can be properly steered to the selected node for testing, and not by the
regular mesh path lookup.

Tested-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
---
v4: Rebased and fixed compile warnings

 include/net/cfg80211.h       |  5 +++++
 include/uapi/linux/nl80211.h | 17 ++++++++++++++
 net/wireless/nl80211.c       | 53 ++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/rdev-ops.h      | 13 +++++++++++
 net/wireless/trace.h         | 18 +++++++++++++++
 5 files changed, 106 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 944de1802210..298301525f9f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3501,6 +3501,9 @@ struct cfg80211_update_owe_info {
  * @update_owe_info: Provide updated OWE info to driver. Driver implementing SME
  *	but offloading OWE processing to the user space will get the updated
  *	DH IE through this interface.
+ *
+ * @probe_mesh_link: Probe direct Mesh peer's link quality by sending data frame
+ *	and overrule HWMP path selection algorithm.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3817,6 +3820,8 @@ struct cfg80211_ops {
 			      struct cfg80211_pmsr_request *request);
 	int	(*update_owe_info)(struct wiphy *wiphy, struct net_device *dev,
 				   struct cfg80211_update_owe_info *owe_info);
+	int	(*probe_mesh_link)(struct wiphy *wiphy, struct net_device *dev,
+				   const u8 *buf, size_t len);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 25f70dd2b583..6f09d1500960 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1070,6 +1070,21 @@
  *	OWE AKM by the host drivers that implement SME but rely
  *	on the user space for the cryptographic/DH IE processing in AP mode.
  *
+ * @NL80211_CMD_PROBE_MESH_LINK: The requirement for mesh link metric
+ *	refreshing, is that from one mesh point we be able to send some data
+ *	frames to other mesh points which are not currently selected as a
+ *	primary traffic path, but which are only 1 hop away. The absence of
+ *	the primary path to the chosen node makes it necessary to apply some
+ *	form of marking on a chosen packet stream so that the packets can be
+ *	properly steered to the selected node for testing, and not by the
+ *	regular mesh path lookup. Further, the packets must be of type data
+ *	so that the rate control (often embedded in firmware) is used for
+ *	rate selection.
+ *
+ *	Here attribute %NL80211_ATTR_MAC is used to specify connected mesh
+ *	peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame
+ *	content. The frame is ethernet data.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1292,6 +1307,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_UPDATE_OWE_INFO,
 
+	NL80211_CMD_PROBE_MESH_LINK,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 846d25d2dc82..2cdc1a55d724 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13405,6 +13405,52 @@ static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
 	return rdev_update_owe_info(rdev, dev, &owe_info);
 }
 
+static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct station_info sinfo = {};
+	const u8 *buf;
+	size_t len;
+	u8 *dest;
+	int err;
+
+	if (!rdev->ops->probe_mesh_link || !rdev->ops->get_station)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_MAC] ||
+	    !info->attrs[NL80211_ATTR_FRAME]) {
+		GENL_SET_ERR_MSG(info, "Frame or MAC missing");
+		return -EINVAL;
+	}
+
+	wdev_lock(wdev);
+	if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
+		wdev_unlock(wdev);
+		err = -EOPNOTSUPP;
+		return err;
+	}
+	wdev_unlock(wdev);
+
+	dest = nla_data(info->attrs[NL80211_ATTR_MAC]);
+	buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+	len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+
+	if (len < sizeof(struct ethhdr))
+		return -EINVAL;
+
+	if (!ether_addr_equal(buf, dest) || is_multicast_ether_addr(buf) ||
+	    !ether_addr_equal(buf + ETH_ALEN, dev->dev_addr))
+		return -EINVAL;
+
+	err = rdev_get_station(rdev, dev, dest, &sinfo);
+	if (err)
+		return err;
+
+	return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -14242,6 +14288,13 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_PROBE_MESH_LINK,
+		.doit = nl80211_probe_mesh_link,
+		.flags = GENL_UNS_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_family nl80211_fam __ro_after_init = {
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 18437a9deb54..e853a4fe6f97 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1286,4 +1286,17 @@ static inline int rdev_update_owe_info(struct cfg80211_registered_device *rdev,
 	return ret;
 }
 
+static inline int
+rdev_probe_mesh_link(struct cfg80211_registered_device *rdev,
+		     struct net_device *dev, const u8 *dest,
+		     const void *buf, size_t len)
+{
+	int ret;
+
+	trace_rdev_probe_mesh_link(&rdev->wiphy, dev, dest, buf, len);
+	ret = rdev->ops->probe_mesh_link(&rdev->wiphy, dev, buf, len);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 488ef2ce8231..2abfff925aac 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3421,6 +3421,24 @@
 		      WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
 );
 
+TRACE_EVENT(rdev_probe_mesh_link,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 const u8 *dest, const u8 *buf, size_t len),
+	TP_ARGS(wiphy, netdev, dest, buf, len),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		MAC_ENTRY(dest)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		MAC_ASSIGN(dest, dest);
+	),
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
+		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(dest))
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 0/3]  wireless: Add support to probe unexercised mesh link
From: Rajkumar Manoharan @ 2019-04-11 20:47 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Rajkumar Manoharan

Consider below mesh topology.

        MP1
       /    \
      /      \
     MP2 --- MP3

Assume that even though MP1 & MP3 have direct mesh links, the path was
established via MP2. (MP1 <-> MP2 <-> MP3). The 1-hop mesh link MP1 <-> MP3
never be excercised till the current path is terminated. As of now, there
is no option to send data frame to pick other than primary path. So mesh
link metric between MP1 & MP3 never be updated. This series allows user
to send data to 1-hop mesh peers through unexercised mesh path.

-Rajkumar

v4: Rebased on mac80211-next top and fixed compile errors
v3: Rebased the changes on TOT

Rajkumar Manoharan (3):
  cfg80211: add support to probe unexercised mesh link
  mac80211: add option for setting control flags
  mac80211: probe unexercised mesh links

 include/net/cfg80211.h       |  5 ++++
 include/net/mac80211.h       |  2 ++
 include/uapi/linux/nl80211.h | 16 +++++++++++++
 net/mac80211/cfg.c           |  1 +
 net/mac80211/ieee80211_i.h   |  5 +++-
 net/mac80211/mesh_hwmp.c     |  4 ++++
 net/mac80211/tdls.c          |  2 +-
 net/mac80211/tx.c            | 54 ++++++++++++++++++++++++++++++++++++++------
 net/wireless/nl80211.c       | 53 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/rdev-ops.h      | 13 +++++++++++
 net/wireless/trace.h         | 18 +++++++++++++++
 11 files changed, 164 insertions(+), 9 deletions(-)

-- 
1.9.1


^ permalink raw reply

* Re: [RFC V4 2/2] ath10k: add tx hw 802.11 encapusaltion offloading support
From: John Crispin @ 2019-04-11 18:36 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Johannes Berg, linux-wireless, Srini Kode, Rajkumar Manoharan,
	Shashidhar Lakkavalli, Vasanthakumar Thiagarajan
In-Reply-To: <87ef69yizo.fsf@purkki.adurom.net>


On 10/04/2019 17:31, Kalle Valo wrote:
> John Crispin <john@phrozen.org> writes:
>
>> From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
>>
>> This patch adds support for ethernet rxtx mode to the driver. The feature
>> is enabled via a new module parameter. If enabled to driver will enable
>> the feature on a per vif basis if all other requirements were met.
>>
>> Testing on a IPQ4019 based hardware shows a increase in TCP throughput
>> of ~20% when the feature is enabled.
>>
>> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
>> Signed-off-by: John Crispin <john@phrozen.org>
> Looks good to me.
>
> BTW, for ath10k patches (patchsets including ath10k patches) please try
> to CC also the ath10k list. Easier to find ath10k patches that way.
>
Hi,

Thanks Kalle, I'll be sending a V5 tomorrow with a small improvement on 
the hw crypto part, that unbreaks wpa3. can I add your Acked-by on the 
ath10k part ?

     John


^ permalink raw reply

* [PATCH] mwl8k: Fix rate_idx underflow
From: Petr Štetiar @ 2019-04-11 18:13 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalle Valo, Lennert Buytenhek, Petr Štetiar, stable

It was reported on OpenWrt bug tracking system[1], that several users
are affected by the endless reboot of their routers if they configure
5GHz interface with channel 44 or 48.

The reboot loop is caused by the following excessive number of WARN_ON
messages:

 WARNING: CPU: 0 PID: 0 at backports-4.19.23-1/net/mac80211/rx.c:4516
                             ieee80211_rx_napi+0x1fc/0xa54 [mac80211]

as the messages are being correctly emitted by the following guard:

 case RX_ENC_LEGACY:
      if (WARN_ON(status->rate_idx >= sband->n_bitrates))

as the rate_idx is in this case erroneously set to 251 (0xfb). This fix
simply converts previously used magic number to proper constant and
guards against substraction which is leading to the currently observed
underflow.

1. https://bugs.openwrt.org/index.php?do=details&task_id=2218

Fixes: 854783444bab ("mwl8k: properly set receive status rate index on 5 GHz receive")
Cc: <stable@vger.kernel.org>
Tested-by: Eubert Bao <bunnier@gmail.com>
Reported-by: Eubert Bao <bunnier@gmail.com>
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
 drivers/net/wireless/marvell/mwl8k.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
index 8e4e9b6..ffc565a 100644
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
@@ -441,6 +441,9 @@ struct mwl8k_sta {
 #define MWL8K_CMD_UPDATE_STADB		0x1123
 #define MWL8K_CMD_BASTREAM		0x1125
 
+#define MWL8K_LEGACY_5G_RATE_OFFSET \
+	(ARRAY_SIZE(mwl8k_rates_24) - ARRAY_SIZE(mwl8k_rates_50))
+
 static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
 {
 	u16 command = le16_to_cpu(cmd);
@@ -1016,8 +1019,9 @@ static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len)
 
 	if (rxd->channel > 14) {
 		status->band = NL80211_BAND_5GHZ;
-		if (!(status->encoding == RX_ENC_HT))
-			status->rate_idx -= 5;
+		if (!(status->encoding == RX_ENC_HT) &&
+		    status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
+			status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
 	} else {
 		status->band = NL80211_BAND_2GHZ;
 	}
@@ -1124,8 +1128,9 @@ static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
 
 	if (rxd->channel > 14) {
 		status->band = NL80211_BAND_5GHZ;
-		if (!(status->encoding == RX_ENC_HT))
-			status->rate_idx -= 5;
+		if (!(status->encoding == RX_ENC_HT) &&
+		    status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
+			status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
 	} else {
 		status->band = NL80211_BAND_2GHZ;
 	}
-- 
1.9.1


^ permalink raw reply related

* Re: question: crda timeout in cfg80211
From: Sergey Matyukevich @ 2019-04-11 12:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org, Igor Mitsyanko
In-Reply-To: <f6b699b051cd1625da57b224e7cd1a8ac6916e72.camel@sipsolutions.net>

> > Indeed, it is PI. I should have known. But instead I spent some time
> > digging through 802.11 specs :)
> 
> Oops :)
> 
> > Well, as I mentioned in my question, regulatory update/reset operations
> > shall be completed in ~pi seconds for _all_ the wireless cards in the
> > system. In our case, regulatory reset operation may be fairly costly.
> > As a result, we end up with recurring reset timeout, when more than one
> > qtn card is installed in a single pcie host. One option for us is to
> > optimize regulatory reset operations in firmware.
> >
> > But what do you think about converting crda_timeout into a per-wiphy
> > timeout in the case when all wiphy-s are being processed, e.g.
> > in update_all_wiphy_regulatory.
> 
> Maybe we should parallelize it? But I don't know how easy that would be.
> 
> I'm a little worried just making it longer will cause users to really be
> wondering what's going on?

Hello Johannes,

Calling regulatory notifiers in parallel sounds like a good idea.
But I haven't yet looked into the details as well. Before fixing
the timeout issue, I was trying to figure out why that regulatory
reset was needed at all.

Here is a simple usecase: Linux distro sets regulatory region to US,
STA is connected to AP. Any STA disconnect (including an attempt to
reconnect to another AP) leads to regulatory reset cycle: US -> 00 -> US.
This reset cycle is not supposed to be done for the wireless cards that
specify REGULATORY_COUNTRY_IE_IGNORE flag. However regulatory reset will
be applied anyway if at least one card in the system does not specify
that flag.

Hence two questions:
Do we really need this kind of reset when we remain
in the same regulatory domain ? 

Does it make sense to track when restore_regulatory_settings performs
reset, and to skip reset for the cards that specify
REGULATORY_COUNTRY_IE_IGNORE ?

Regards,
Sergey

^ permalink raw reply

* Re: [PATCH v3 07/11] drm: sun4i: Add support for enabling DDC I2C bus power to dw_hdmi glue
From: Maxime Ripard @ 2019-04-11 12:25 UTC (permalink / raw)
  To: megous
  Cc: linux-sunxi, Chen-Yu Tsai, Rob Herring, Linus Walleij,
	David Airlie, Daniel Vetter, Mark Rutland, Giuseppe Cavallaro,
	Alexandre Torgue, Jose Abreu, David S. Miller, Maxime Coquelin,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Kalle Valo, Naveen Gupta, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, netdev, linux-stm32,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	linux-gpio
In-Reply-To: <20190411101951.30223-8-megous@megous.com>

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

On Thu, Apr 11, 2019 at 12:19:47PM +0200, megous@megous.com wrote:
> From: Ondrej Jirman <megous@megous.com>
>
> Orange Pi 3 board requires enabling DDC I2C bus via some GPIO connected
> transistors, before the bus can be used.
>
> Model this as a power supply for DDC bus on the HDMI connector connected
> to the output port (port 1) of the HDMI controller.
>
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> ---
>  drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 60 ++++++++++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h |  2 +
>  2 files changed, 60 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
> index 39d8509d96a0..1b6ffba41177 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
> @@ -98,6 +98,30 @@ static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,
>  	return crtcs;
>  }
>
> +static int sun8i_dw_hdmi_find_connector_pdev(struct device *dev,
> +					     struct platform_device **pdev_out)
> +{
> +	struct platform_device* pdev;

This doesn't respect the guidelines.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v3 04/11] pinctrl: sunxi: Support I/O bias voltage setting on H6
From: Maxime Ripard @ 2019-04-11 12:22 UTC (permalink / raw)
  To: megous
  Cc: linux-sunxi, Chen-Yu Tsai, Rob Herring, Linus Walleij,
	David Airlie, Daniel Vetter, Mark Rutland, Giuseppe Cavallaro,
	Alexandre Torgue, Jose Abreu, David S. Miller, Maxime Coquelin,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Kalle Valo, Naveen Gupta, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, netdev, linux-stm32,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	linux-gpio
In-Reply-To: <20190411101951.30223-5-megous@megous.com>

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

Hi,

On Thu, Apr 11, 2019 at 12:19:44PM +0200, megous@megous.com wrote:
> From: Ondrej Jirman <megous@megous.com>
>
> H6 SoC has a "pio group withstand voltage mode" register (datasheet
> description), that needs to be used to select either 1.8V or 3.3V I/O mode,
> based on what voltage is powering the respective pin banks and is thus used
> for I/O signals.
>
> Add support for configuring this register according to the voltage of the
> pin bank regulator (if enabled).
>
> This is similar to the support for I/O bias voltage setting patch for A80
> and the same concerns apply. See:
>
>   commit 402bfb3c1352 ("Support I/O bias voltage setting on A80")
>
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> ---
>  drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c |  1 +
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     | 11 +++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |  5 +++++
>  3 files changed, 17 insertions(+)
>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
> index ef4268cc6227..3cc1121589c9 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
> @@ -591,6 +591,7 @@ static const struct sunxi_pinctrl_desc h6_pinctrl_data = {
>  	.irq_banks = 4,
>  	.irq_bank_map = h6_irq_bank_map,
>  	.irq_read_needs_mux = true,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>  };
>
>  static int h6_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 98c4de5f4019..0cbca30b75dc 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -614,6 +614,8 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
>  					 unsigned pin,
>  					 struct regulator *supply)
>  {
> +	unsigned short bank = pin / PINS_PER_BANK;
> +	unsigned long flags;
>  	u32 val, reg;
>  	int uV;
>
> @@ -651,6 +653,15 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
>  		reg &= ~IO_BIAS_MASK;
>  		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
>  		return 0;
> +	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
> +		val = uV <= 1800000 ? 1 : 0;
> +
> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> +		reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
> +		reg &= ~(1 << bank);
> +		writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +		return 0;
>  	default:
>  		return -EINVAL;
>  	}
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index 4bfc8a6d9dce..36186906f0a7 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -95,11 +95,16 @@
>  #define PINCTRL_SUN7I_A20	BIT(7)
>  #define PINCTRL_SUN8I_R40	BIT(8)
>
> +#define PIO_POW_MOD_SEL_REG	0x340
> +
>  enum sunxi_desc_bias_voltage {
>  	BIAS_VOLTAGE_NONE,
>  	/* Bias voltage configuration is done through
>  	 * Pn_GRP_CONFIG registers, as seen on A80 SoC. */
>  	BIAS_VOLTAGE_GRP_CONFIG,
> +	/* Bias voltage is set through PIO_POW_MOD_SEL_REG
> +	 * register, as seen on H6 SoC, for example. */

That's not the proper comment style.

Once fixed, this patch and the previous is
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [RFC 5/5] mt7603: init mcu_restart function pointer
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <cover.1554982661.git.lorenzo@kernel.org>

Use common function wrapper in mt7603_mcu_exit since the code is shared
with mt7615 driver

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
index c52ae301062c..7ebfcb021d40 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -161,9 +161,9 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
 }
 
 static int
-mt7603_mcu_restart(struct mt7603_dev *dev)
+mt7603_mcu_restart(struct mt76_dev *dev)
 {
-	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_RESTART_DL_REQ,
+	return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ,
 				   NULL, 0, true);
 }
 
@@ -269,6 +269,7 @@ int mt7603_mcu_init(struct mt7603_dev *dev)
 {
 	static const struct mt76_mcu_ops mt7603_mcu_ops = {
 		.mcu_send_msg = mt7603_mcu_msg_send,
+		.mcu_restart = mt7603_mcu_restart,
 	};
 
 	dev->mt76.mcu_ops = &mt7603_mcu_ops;
@@ -277,7 +278,7 @@ int mt7603_mcu_init(struct mt7603_dev *dev)
 
 void mt7603_mcu_exit(struct mt7603_dev *dev)
 {
-	mt7603_mcu_restart(dev);
+	__mt76_mcu_restart(&dev->mt76);
 	skb_queue_purge(&dev->mt76.mmio.mcu.res_q);
 }
 
-- 
2.20.1


^ permalink raw reply related

* [RFC 4/5] mt76: introduce mt76_mcu_restart macro
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <cover.1554982661.git.lorenzo@kernel.org>

Use common function wrapper in mt76x02_watchdog_reset

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h         | 2 ++
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index a23ec92fae97..def76af77cd8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -537,6 +537,8 @@ struct mt76_rx_status {
 
 #define mt76_mcu_send_msg(dev, ...)	(dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__)
 #define __mt76_mcu_send_msg(dev, ...)	(dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__)
+#define mt76_mcu_restart(dev, ...)	(dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76))
+#define __mt76_mcu_restart(dev, ...)	(dev)->mcu_ops->mcu_restart((dev))
 
 #define mt76_set(dev, offset, val)	mt76_rmw(dev, offset, 0, val)
 #define mt76_clear(dev, offset, val)	mt76_rmw(dev, offset, val, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index ca8320711bc2..f2d2c4112e80 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -454,7 +454,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
 	mt76_set(dev, 0x734, 0x3);
 
 	if (restart)
-		dev->mt76.mcu_ops->mcu_restart(&dev->mt76);
+		mt76_mcu_restart(dev);
 
 	for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++)
 		mt76_queue_tx_cleanup(dev, i, true);
-- 
2.20.1


^ permalink raw reply related

* [RFC 3/5] mt7603: initialize mt76_mcu_ops data structure
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <cover.1554982661.git.lorenzo@kernel.org>

Use __mt76_mcu_send_msg wrapper instead of mt7603_mcu_msg_send.
This is a preliminary patch for mt7615-mt7603 mcu code unification

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  1 +
 .../net/wireless/mediatek/mt76/mt7603/init.c  |  2 +-
 .../net/wireless/mediatek/mt76/mt7603/mcu.c   | 28 +++++++++++++------
 .../wireless/mediatek/mt76/mt7603/mt7603.h    |  2 +-
 4 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index b432da3f55c7..a23ec92fae97 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -536,6 +536,7 @@ struct mt76_rx_status {
 #define mt76_rd_rp(dev, ...)	(dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__)
 
 #define mt76_mcu_send_msg(dev, ...)	(dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__)
+#define __mt76_mcu_send_msg(dev, ...)	(dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__)
 
 #define mt76_set(dev, offset, val)	mt76_rmw(dev, offset, 0, val)
 #define mt76_clear(dev, offset, val)	mt76_rmw(dev, offset, val, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index e17b6b89dfe2..d54dda67d036 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -282,7 +282,7 @@ mt7603_init_hardware(struct mt7603_dev *dev)
 		mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
 	}
 
-	ret = mt7603_load_firmware(dev);
+	ret = mt7603_mcu_init(dev);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
index a978305cc969..c52ae301062c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -54,10 +54,10 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,
 }
 
 static int
-mt7603_mcu_msg_send(struct mt7603_dev *dev, int cmd, const void *data,
+mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
 		    int len, bool wait_resp)
 {
-	struct mt76_dev *mdev = &dev->mt76;
+	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
 	unsigned long expires = jiffies + 3 * HZ;
 	struct mt7603_mcu_rxd *rxd;
 	struct sk_buff *skb;
@@ -115,7 +115,7 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
 		.mode = cpu_to_le32(BIT(31)),
 	};
 
-	return mt7603_mcu_msg_send(dev, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
+	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
 				   &req, sizeof(req), true);
 }
 
@@ -156,18 +156,18 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
 		.addr = cpu_to_le32(addr),
 	};
 
-	return mt7603_mcu_msg_send(dev, -MCU_CMD_FW_START_REQ,
+	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ,
 				   &req, sizeof(req), true);
 }
 
 static int
 mt7603_mcu_restart(struct mt7603_dev *dev)
 {
-	return mt7603_mcu_msg_send(dev, -MCU_CMD_RESTART_DL_REQ,
+	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_RESTART_DL_REQ,
 				   NULL, 0, true);
 }
 
-int mt7603_load_firmware(struct mt7603_dev *dev)
+static int mt7603_load_firmware(struct mt7603_dev *dev)
 {
 	const struct firmware *fw;
 	const struct mt7603_fw_trailer *hdr;
@@ -265,6 +265,16 @@ int mt7603_load_firmware(struct mt7603_dev *dev)
 	return ret;
 }
 
+int mt7603_mcu_init(struct mt7603_dev *dev)
+{
+	static const struct mt76_mcu_ops mt7603_mcu_ops = {
+		.mcu_send_msg = mt7603_mcu_msg_send,
+	};
+
+	dev->mt76.mcu_ops = &mt7603_mcu_ops;
+	return mt7603_load_firmware(dev);
+}
+
 void mt7603_mcu_exit(struct mt7603_dev *dev)
 {
 	mt7603_mcu_restart(dev);
@@ -361,7 +371,7 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
 		req.data[i].pad = 0;
 	}
 
-	return mt7603_mcu_msg_send(dev, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
+	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
 				   &req, sizeof(req), true);
 }
 
@@ -405,7 +415,7 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
 	memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7,
 	       sizeof(req.temp_comp_power));
 
-	return mt7603_mcu_msg_send(dev, MCU_EXT_CMD_SET_TX_POWER_CTRL,
+	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL,
 				   &req, sizeof(req), true);
 }
 
@@ -451,7 +461,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
 	for (i = 0; i < ARRAY_SIZE(req.txpower); i++)
 		req.txpower[i] = tx_power;
 
-	ret = mt7603_mcu_msg_send(dev, MCU_EXT_CMD_CHANNEL_SWITCH,
+	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH,
 				  &req, sizeof(req), true);
 	if (ret)
 		return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 9cc8ca7a4d1c..f414ff2a5279 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -176,7 +176,7 @@ void mt7603_unregister_device(struct mt7603_dev *dev);
 int mt7603_eeprom_init(struct mt7603_dev *dev);
 int mt7603_dma_init(struct mt7603_dev *dev);
 void mt7603_dma_cleanup(struct mt7603_dev *dev);
-int mt7603_load_firmware(struct mt7603_dev *dev);
+int mt7603_mcu_init(struct mt7603_dev *dev);
 void mt7603_init_debugfs(struct mt7603_dev *dev);
 
 static inline void mt7603_irq_enable(struct mt7603_dev *dev, u32 mask)
-- 
2.20.1


^ permalink raw reply related

* [RFC 2/5] mt7603: use standard signature for mt7603_mcu_msg_send
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <cover.1554982661.git.lorenzo@kernel.org>

Use mt76 common signature for mt7603_mcu_msg_send. Move skb allocation
in mt7603_mcu_msg_send and remove duplicated code. This is a preliminary
patch for mt7615-mt7603 mcu code unification

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7603/mcu.c   | 61 ++++++++-----------
 1 file changed, 27 insertions(+), 34 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
index 868a4b601a6f..a978305cc969 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -22,9 +22,6 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,
 	struct mt7603_mcu_txd *txd;
 	u8 seq;
 
-	if (!skb)
-		return -EINVAL;
-
 	seq = ++mdev->mmio.mcu.msg_seq & 0xf;
 	if (!seq)
 		seq = ++mdev->mmio.mcu.msg_seq & 0xf;
@@ -57,20 +54,26 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,
 }
 
 static int
-mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd)
+mt7603_mcu_msg_send(struct mt7603_dev *dev, int cmd, const void *data,
+		    int len, bool wait_resp)
 {
 	struct mt76_dev *mdev = &dev->mt76;
 	unsigned long expires = jiffies + 3 * HZ;
 	struct mt7603_mcu_rxd *rxd;
+	struct sk_buff *skb;
 	int ret, seq;
 
+	skb = mt7603_mcu_msg_alloc(data, len);
+	if (!skb)
+		return -ENOMEM;
+
 	mutex_lock(&mdev->mmio.mcu.mutex);
 
 	ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq);
 	if (ret)
 		goto out;
 
-	while (1) {
+	while (wait_resp) {
 		bool check_seq = false;
 
 		skb = mt76_mcu_get_response(&dev->mt76, expires);
@@ -111,9 +114,9 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
 		.len = cpu_to_le32(len),
 		.mode = cpu_to_le32(BIT(31)),
 	};
-	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
 
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ);
+	return mt7603_mcu_msg_send(dev, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
+				   &req, sizeof(req), true);
 }
 
 static int
@@ -152,17 +155,16 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
 		.override = cpu_to_le32(addr ? 1 : 0),
 		.addr = cpu_to_le32(addr),
 	};
-	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
 
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ);
+	return mt7603_mcu_msg_send(dev, -MCU_CMD_FW_START_REQ,
+				   &req, sizeof(req), true);
 }
 
 static int
 mt7603_mcu_restart(struct mt7603_dev *dev)
 {
-	struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0);
-
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ);
+	return mt7603_mcu_msg_send(dev, -MCU_CMD_RESTART_DL_REQ,
+				   NULL, 0, true);
 }
 
 int mt7603_load_firmware(struct mt7603_dev *dev)
@@ -343,30 +345,24 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
 		u8 buffer_mode;
 		u8 len;
 		u8 pad[2];
-	} req_hdr = {
+		struct req_data data[255];
+	} req = {
 		.buffer_mode = 1,
 		.len = ARRAY_SIZE(req_fields) - 1,
 	};
-	struct sk_buff *skb;
-	struct req_data *data;
-	const int size = 0xff * sizeof(struct req_data);
 	u8 *eep = (u8 *)dev->mt76.eeprom.data;
 	int i;
 
-	BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size);
-
-	skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr));
-	memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr));
-	data = (struct req_data *)skb_put(skb, size);
-	memset(data, 0, size);
+	BUILD_BUG_ON(ARRAY_SIZE(req_fields) > ARRAY_SIZE(req.data));
 
 	for (i = 0; i < ARRAY_SIZE(req_fields); i++) {
-		data[i].addr = cpu_to_le16(req_fields[i]);
-		data[i].val = eep[req_fields[i]];
-		data[i].pad = 0;
+		req.data[i].addr = cpu_to_le16(req_fields[i]);
+		req.data[i].val = eep[req_fields[i]];
+		req.data[i].pad = 0;
 	}
 
-	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE);
+	return mt7603_mcu_msg_send(dev, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
+				   &req, sizeof(req), true);
 }
 
 static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
@@ -401,7 +397,6 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
 		},
 #undef EEP_VAL
 	};
-	struct sk_buff *skb;
 	u8 *eep = (u8 *)dev->mt76.eeprom.data;
 
 	memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK,
@@ -410,8 +405,8 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
 	memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7,
 	       sizeof(req.temp_comp_power));
 
-	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
-	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL);
+	return mt7603_mcu_msg_send(dev, MCU_EXT_CMD_SET_TX_POWER_CTRL,
+				   &req, sizeof(req), true);
 }
 
 int mt7603_mcu_set_channel(struct mt7603_dev *dev)
@@ -435,10 +430,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
 		.tx_streams = n_chains,
 		.rx_streams = n_chains,
 	};
-	struct sk_buff *skb;
 	s8 tx_power;
-	int ret;
-	int i;
+	int i, ret;
 
 	if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) {
 		req.bw = MT_BW_40;
@@ -458,8 +451,8 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
 	for (i = 0; i < ARRAY_SIZE(req.txpower); i++)
 		req.txpower[i] = tx_power;
 
-	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
-	ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH);
+	ret = mt7603_mcu_msg_send(dev, MCU_EXT_CMD_CHANNEL_SWITCH,
+				  &req, sizeof(req), true);
 	if (ret)
 		return ret;
 
-- 
2.20.1


^ permalink raw reply related

* [RFC 1/5] mt7603: remove query from mt7603_mcu_msg_send signature
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless
In-Reply-To: <cover.1554982661.git.lorenzo@kernel.org>

Remove query parameter from mt7603_mcu_msg_send/__mt7603_mcu_msg_send
routine signature since it can be obtained from cmd value. This is a
preliminary patch for mcu code unification between mt7615 and mt7603
drivers

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 .../net/wireless/mediatek/mt76/mt7603/mcu.c   | 36 ++++++++-----------
 1 file changed, 14 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
index 57481012ee47..868a4b601a6f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c
@@ -14,8 +14,8 @@ struct mt7603_fw_trailer {
 } __packed;
 
 static int
-__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
-		      int query, int *wait_seq)
+__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,
+		      int cmd, int *wait_seq)
 {
 	int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12;
 	struct mt76_dev *mdev = &dev->mt76;
@@ -42,15 +42,14 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
 
 	if (cmd < 0) {
 		txd->cid = -cmd;
+		txd->set_query = MCU_Q_NA;
 	} else {
 		txd->cid = MCU_CMD_EXT_CID;
 		txd->ext_cid = cmd;
-		if (query != MCU_Q_NA)
-			txd->ext_cid_ack = 1;
+		txd->set_query = MCU_Q_SET;
+		txd->ext_cid_ack = 1;
 	}
 
-	txd->set_query = query;
-
 	if (wait_seq)
 		*wait_seq = seq;
 
@@ -58,8 +57,7 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
 }
 
 static int
-mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
-		    int query)
+mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd)
 {
 	struct mt76_dev *mdev = &dev->mt76;
 	unsigned long expires = jiffies + 3 * HZ;
@@ -68,7 +66,7 @@ mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
 
 	mutex_lock(&mdev->mmio.mcu.mutex);
 
-	ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq);
+	ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq);
 	if (ret)
 		goto out;
 
@@ -115,8 +113,7 @@ mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
 	};
 	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
 
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
-				   MCU_Q_NA);
+	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ);
 }
 
 static int
@@ -134,7 +131,7 @@ mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len)
 			return -ENOMEM;
 
 		ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER,
-					    MCU_Q_NA, NULL);
+					    NULL);
 		if (ret)
 			break;
 
@@ -157,8 +154,7 @@ mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
 	};
 	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
 
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ,
-				   MCU_Q_NA);
+	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ);
 }
 
 static int
@@ -166,8 +162,7 @@ mt7603_mcu_restart(struct mt7603_dev *dev)
 {
 	struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0);
 
-	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ,
-				   MCU_Q_NA);
+	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ);
 }
 
 int mt7603_load_firmware(struct mt7603_dev *dev)
@@ -371,8 +366,7 @@ int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
 		data[i].pad = 0;
 	}
 
-	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
-				   MCU_Q_SET);
+	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE);
 }
 
 static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
@@ -417,8 +411,7 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
 	       sizeof(req.temp_comp_power));
 
 	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
-	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL,
-				   MCU_Q_SET);
+	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL);
 }
 
 int mt7603_mcu_set_channel(struct mt7603_dev *dev)
@@ -466,8 +459,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev)
 		req.txpower[i] = tx_power;
 
 	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
-	ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH,
-				  MCU_Q_SET);
+	ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH);
 	if (ret)
 		return ret;
 
-- 
2.20.1


^ permalink raw reply related

* [RFC 0/5] use standard signature for mt7603 mcu api
From: Lorenzo Bianconi @ 2019-04-11 11:52 UTC (permalink / raw)
  To: nbd; +Cc: lorenzo.bianconi, linux-wireless

Introduce mt76_mcu_ops data structure in mt7603 mcu code in order to
unify mcu code between mt7603 and mt7615 drivers

Lorenzo Bianconi (5):
  mt7603: remove query from mt7603_mcu_msg_send signature
  mt7603: use standard signature for mt7603_mcu_msg_send
  mt7603: initialize mt76_mcu_ops data structure
  mt76: introduce mt76_mcu_restart macro
  mt7603: init mcu_restart function pointer

 drivers/net/wireless/mediatek/mt76/mt76.h     |   3 +
 .../net/wireless/mediatek/mt76/mt7603/init.c  |   2 +-
 .../net/wireless/mediatek/mt76/mt7603/mcu.c   | 102 +++++++++---------
 .../wireless/mediatek/mt76/mt7603/mt7603.h    |   2 +-
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c |   2 +-
 5 files changed, 55 insertions(+), 56 deletions(-)

-- 
2.20.1


^ permalink raw reply

* Re: [RFC/RFT] mac80211: Switch to a virtual time-based airtime scheduler
From: Toke Høiland-Jørgensen @ 2019-04-11 11:24 UTC (permalink / raw)
  To: Yibo Zhao
  Cc: make-wifi-fast, linux-wireless, Felix Fietkau, Rajkumar Manoharan,
	Kan Yan, linux-wireless-owner
In-Reply-To: <73077ba7cda566d5eeb2395978b3524c@codeaurora.org>

Yibo Zhao <yiboz@codeaurora.org> writes:

> On 2019-04-10 18:40, Toke Høiland-Jørgensen wrote:
>> Yibo Zhao <yiboz@codeaurora.org> writes:
>> 
>>> On 2019-04-10 04:41, Toke Høiland-Jørgensen wrote:
>>>> Yibo Zhao <yiboz@codeaurora.org> writes:
>>>> 
>>>>> On 2019-04-04 16:31, Toke Høiland-Jørgensen wrote:
>>>>>> Yibo Zhao <yiboz@codeaurora.org> writes:
>>>>>> 
>>>>>>> On 2019-02-16 01:05, Toke Høiland-Jørgensen wrote:
>>>>>>>> This switches the airtime scheduler in mac80211 to use a virtual
>>>>>>>> time-based
>>>>>>>> scheduler instead of the round-robin scheduler used before. This
>>>>>>>> has
>>>>>>>> a
>>>>>>>> couple of advantages:
>>>>>>>> 
>>>>>>>> - No need to sync up the round-robin scheduler in 
>>>>>>>> firmware/hardware
>>>>>>>> with
>>>>>>>>   the round-robin airtime scheduler.
>>>>>>>> 
>>>>>>>> - If several stations are eligible for transmission we can 
>>>>>>>> schedule
>>>>>>>> both of
>>>>>>>>   them; no need to hard-block the scheduling rotation until the
>>>>>>>> head
>>>>>>>> of
>>>>>>>> the
>>>>>>>>   queue has used up its quantum.
>>>>>>>> 
>>>>>>>> - The check of whether a station is eligible for transmission
>>>>>>>> becomes
>>>>>>>>   simpler (in ieee80211_txq_may_transmit()).
>>>>>>>> 
>>>>>>>> The drawback is that scheduling becomes slightly more expensive, 
>>>>>>>> as
>>>>>>>> we
>>>>>>>> need
>>>>>>>> to maintain an rbtree of TXQs sorted by virtual time. This means
>>>>>>>> that
>>>>>>>> ieee80211_register_airtime() becomes O(logN) in the number of
>>>>>>>> currently
>>>>>>>> scheduled TXQs. However, hopefully this number rarely grows too 
>>>>>>>> big
>>>>>>>> (it's
>>>>>>>> only TXQs currently backlogged, not all associated stations), so 
>>>>>>>> it
>>>>>>>> shouldn't be too big of an issue.
>>>>>>>> 
>>>>>>>> @@ -1831,18 +1830,32 @@ void 
>>>>>>>> ieee80211_sta_register_airtime(struct
>>>>>>>> ieee80211_sta *pubsta, u8 tid,
>>>>>>>>  {
>>>>>>>>  	struct sta_info *sta = container_of(pubsta, struct sta_info,
>>>>>>>> sta);
>>>>>>>>  	struct ieee80211_local *local = sta->sdata->local;
>>>>>>>> +	struct ieee80211_txq *txq = sta->sta.txq[tid];
>>>>>>>>  	u8 ac = ieee80211_ac_from_tid(tid);
>>>>>>>> -	u32 airtime = 0;
>>>>>>>> +	u64 airtime = 0, weight_sum;
>>>>>>>> +
>>>>>>>> +	if (!txq)
>>>>>>>> +		return;
>>>>>>>> 
>>>>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_TX)
>>>>>>>>  		airtime += tx_airtime;
>>>>>>>>  	if (sta->local->airtime_flags & AIRTIME_USE_RX)
>>>>>>>>  		airtime += rx_airtime;
>>>>>>>> 
>>>>>>>> +	/* Weights scale so the unit weight is 256 */
>>>>>>>> +	airtime <<= 8;
>>>>>>>> +
>>>>>>>>  	spin_lock_bh(&local->active_txq_lock[ac]);
>>>>>>>> +
>>>>>>>>  	sta->airtime[ac].tx_airtime += tx_airtime;
>>>>>>>>  	sta->airtime[ac].rx_airtime += rx_airtime;
>>>>>>>> -	sta->airtime[ac].deficit -= airtime;
>>>>>>>> +
>>>>>>>> +	weight_sum = local->airtime_weight_sum[ac] ?:
>>>>>>>> sta->airtime_weight;
>>>>>>>> +
>>>>>>>> +	local->airtime_v_t[ac] += airtime / weight_sum;
>>>>>>> Hi Toke,
>>>>>>> 
>>>>>>> Please ignore the previous two broken emails regarding this new
>>>>>>> proposal
>>>>>>> from me.
>>>>>>> 
>>>>>>> It looks like local->airtime_v_t acts like a Tx criteria. Only the
>>>>>>> stations with less airtime than that are valid for Tx. That means
>>>>>>> there
>>>>>>> are situations, like 50 clients, that some of the stations can be
>>>>>>> used
>>>>>>> to Tx when putting next_txq in the loop. Am I right?
>>>>>> 
>>>>>> I'm not sure what you mean here. Are you referring to the case 
>>>>>> where
>>>>>> new
>>>>>> stations appear with a very low (zero) airtime_v_t? That is handled
>>>>>> when
>>>>>> the station is enqueued.
>>>>> Hi Toke,
>>>>> 
>>>>> Sorry for the confusion. I am not referring to the case that you
>>>>> mentioned though it can be solved by your subtle design, max(local 
>>>>> vt,
>>>>> sta vt). :-)
>>>>> 
>>>>> Actually, my concern is situation about putting next_txq in the 
>>>>> loop.
>>>>> Let me explain a little more and see below.
>>>>> 
>>>>>> @@ -3640,126 +3638,191 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue);
>>>>>>  struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, 
>>>>>> u8
>>>>>> ac)
>>>>>>  {
>>>>>>  	struct ieee80211_local *local = hw_to_local(hw);
>>>>>> +	struct rb_node *node = local->schedule_pos[ac];
>>>>>>  	struct txq_info *txqi = NULL;
>>>>>> +	bool first = false;
>>>>>> 
>>>>>>  	lockdep_assert_held(&local->active_txq_lock[ac]);
>>>>>> 
>>>>>> - begin:
>>>>>> -	txqi = list_first_entry_or_null(&local->active_txqs[ac],
>>>>>> -					struct txq_info,
>>>>>> -					schedule_order);
>>>>>> -	if (!txqi)
>>>>>> +	if (!node) {
>>>>>> +		node = rb_first_cached(&local->active_txqs[ac]);
>>>>>> +		first = true;
>>>>>> +	} else
>>>>>> +		node = rb_next(node);
>>>>> 
>>>>> Consider below piece of code from ath10k_mac_schedule_txq:
>>>>> 
>>>>>          ieee80211_txq_schedule_start(hw, ac);
>>>>>          while ((txq = ieee80211_next_txq(hw, ac))) {
>>>>>                  while (ath10k_mac_tx_can_push(hw, txq)) {
>>>>>                          ret = ath10k_mac_tx_push_txq(hw, txq);
>>>>>                          if (ret < 0)
>>>>>                                  break;
>>>>>                  }
>>>>>                  ieee80211_return_txq(hw, txq);
>>>>>                  ath10k_htt_tx_txq_update(hw, txq);
>>>>>                  if (ret == -EBUSY)
>>>>>                          break;
>>>>>          }
>>>>>          ieee80211_txq_schedule_end(hw, ac);
>>>>> 
>>>>> If my understanding is right, local->schedule_pos is used to record
>>>>> the
>>>>> last scheduled node and used for traversal rbtree for valid txq. 
>>>>> There
>>>>> is chance that an empty txq is feeded to return_txq and got removed
>>>>> from
>>>>> rbtree. The empty txq will always be the rb_first node. Then in the
>>>>> following next_txq, local->schedule_pos becomes meaningless since 
>>>>> its
>>>>> rb_next will return NULL and the loop break. Only rb_first get
>>>>> dequeued
>>>>> during this loop.
>>>>> 
>>>>> 	if (!node || RB_EMPTY_NODE(node)) {
>>>>> 		node = rb_first_cached(&local->active_txqs[ac]);
>>>>> 		first = true;
>>>>> 	} else
>>>>> 		node = rb_next(node);
>>>> 
>>>> Ah, I see what you mean. Yes, that would indeed be a problem - nice
>>>> catch! :)
>>>> 
>>>>> How about this? The nodes on the rbtree will be dequeued and removed
>>>>> from rbtree one by one until HW is busy. Please note local vt and 
>>>>> sta
>>>>> vt will not be updated since txq lock is held during this time.
>>>> 
>>>> Insertion and removal from the rbtree are relatively expensive, so 
>>>> I'd
>>>> rather not do that for every txq. I think a better way to solve this
>>>> is to just defer the actual removal from the tree until
>>>> ieee80211_txq_schedule_end()... Will fix that when I submit this 
>>>> again.
>>> 
>>> Do you mean we keep the empty txqs in the rbtree until loop finishes 
>>> and
>>> remove them in ieee80211_txq_schedule_end(may be put return_txq in 
>>> it)?
>>> If it is the case, I suppose a list is needed to store the empty txqs 
>>> so
>>> as to dequeue them in ieee80211_txq_schedule_end.
>> 
>> Yeah, return_txq() would just put "to be removed" TXQs on a list, and
>> schedule_end() would do the actual removal (after checking whether a 
>> new
>> packet showed up in the meantime).
>
> SGTM
>
>> 
>>> And one more thing,
>>> 
>>>> +               if (sta->airtime[ac].v_t > local->airtime_v_t[ac]) {
>>>> +                       if (first)
>>>> +                               local->airtime_v_t[ac] =
>>>> sta->airtime[ac].v_t;
>>>> +                       else
>>>> +                               return NULL;
>>> 
>>> As local->airtime_v_t will not be updated during loop, we don't need 
>>> to
>>> return NULL.
>> 
>> Yes we do; this is actually the break condition. I.e., stations whose
>> virtual time are higher than the global time (in local->airtime_v_t) 
>> are
>> not allowed to transmit. And since we are traversing them in order, 
>> when
>> we find the first such station, we are done and can break out of the
>> scheduling loop entirely (which is what we do by returning NULL). The
>> other branch in the inner if() is just for the case where no stations
>> are currently eligible to transmit according to this rule; here we 
>> don't
>> want to stall, so we advance the global timer so the first station
>> becomes eligible...
>
> Yes,the inner if() make sure first node always get scheduled no matter 
> its vt.
>
> To detail my concern, let's assume only two nodes in the tree and
> empty nodes will be in tree until schedule_end(). In the loop and in
> case hw is not busy, ath10k will drain every node next_txq returned
> before asking for another txq again. Then as we are traversing to next
> rb node, it is highly possible the second node is not allowed to
> transmit since the global time has not been updated yet as the active
> txq lock is held. At this time, only second node on the tree has data
> and hw is capable of sending more data. I don't think the second node
> is not valid for transmission in this situation.
>
> With more nodes in the tree in this situation, I think same thing
> happens that all nodes except the first node are not allowed to
> transmit since none of their vts are less than the global time which
> is not updated in time. The loop breaks when we are checking the
> second node.

Yeah, in many cases we will end up throttling all but the first (couple
of) node(s). This is by design; otherwise we can't ensure fairness. As
long as we are making forward progress that is fine, though...

-Toke

^ permalink raw reply

* Re: [linux-sunxi] [PATCH v3 03/11] pinctrl: sunxi: Prepare for alternative bias voltage setting methods
From: Ondřej Jirman @ 2019-04-11 10:44 UTC (permalink / raw)
  To: Julian Calaby
  Cc: linux-sunxi, Maxime Ripard, Chen-Yu Tsai, Rob Herring,
	Linus Walleij, David Airlie, Daniel Vetter, Mark Rutland,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, David S. Miller,
	Maxime Coquelin, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, Naveen Gupta, dri-devel,
	devicetree, Mailing List, Arm, linux-kernel, netdev, linux-stm32,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	linux-gpio
In-Reply-To: <CAGRGNgUhPC+G+H_zYSi7KFx-K10uPOXRsPqPFcirGaWScw59dQ@mail.gmail.com>

On Thu, Apr 11, 2019 at 08:34:33PM +1000, Julian Calaby wrote:
> Hi Ondrej
> 
> On Thu, Apr 11, 2019 at 8:19 PM megous via linux-sunxi
> <linux-sunxi@googlegroups.com> wrote:
> >
> > From: Ondrej Jirman <megous@megous.com>
> >
> > H6 has a different I/O voltage bias setting method than A80. Prepare
> > existing code for using alternative bias voltage setting methods.
> >
> > Signed-off-by: Ondrej Jirman <megous@megous.com>
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > index ee15ab067b5f..4bfc8a6d9dce 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > @@ -95,6 +95,13 @@
> >  #define PINCTRL_SUN7I_A20      BIT(7)
> >  #define PINCTRL_SUN8I_R40      BIT(8)
> >
> > +enum sunxi_desc_bias_voltage {
> > +       BIAS_VOLTAGE_NONE,
> > +       /* Bias voltage configuration is done through
> > +        * Pn_GRP_CONFIG registers, as seen on A80 SoC. */
> > +       BIAS_VOLTAGE_GRP_CONFIG,
> > +};
> > +
> >  struct sunxi_desc_function {
> >         unsigned long   variant;
> >         const char      *name;
> > @@ -117,7 +124,7 @@ struct sunxi_pinctrl_desc {
> >         const unsigned int              *irq_bank_map;
> >         bool                            irq_read_needs_mux;
> >         bool                            disable_strict_mode;
> > -       bool                            has_io_bias_cfg;
> > +       int                             io_bias_cfg_variant;
> 
> Shouldn't we be defining this field using the enum rather than as an int?

Yes, thank you, I fixed it for v4.

regards,
  	o.

> Thanks,
> 
> -- 
> Julian Calaby
> 
> Email: julian.calaby@gmail.com
> Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply

* Re: [linux-sunxi] [PATCH v3 03/11] pinctrl: sunxi: Prepare for alternative bias voltage setting methods
From: Julian Calaby @ 2019-04-11 10:34 UTC (permalink / raw)
  To: megous
  Cc: linux-sunxi, Maxime Ripard, Chen-Yu Tsai, Rob Herring,
	Linus Walleij, David Airlie, Daniel Vetter, Mark Rutland,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, David S. Miller,
	Maxime Coquelin, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, Naveen Gupta, dri-devel,
	devicetree, Mailing List, Arm, linux-kernel, netdev, linux-stm32,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	linux-gpio
In-Reply-To: <20190411101951.30223-4-megous@megous.com>

Hi Ondrej

On Thu, Apr 11, 2019 at 8:19 PM megous via linux-sunxi
<linux-sunxi@googlegroups.com> wrote:
>
> From: Ondrej Jirman <megous@megous.com>
>
> H6 has a different I/O voltage bias setting method than A80. Prepare
> existing code for using alternative bias voltage setting methods.
>
> Signed-off-by: Ondrej Jirman <megous@megous.com>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index ee15ab067b5f..4bfc8a6d9dce 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -95,6 +95,13 @@
>  #define PINCTRL_SUN7I_A20      BIT(7)
>  #define PINCTRL_SUN8I_R40      BIT(8)
>
> +enum sunxi_desc_bias_voltage {
> +       BIAS_VOLTAGE_NONE,
> +       /* Bias voltage configuration is done through
> +        * Pn_GRP_CONFIG registers, as seen on A80 SoC. */
> +       BIAS_VOLTAGE_GRP_CONFIG,
> +};
> +
>  struct sunxi_desc_function {
>         unsigned long   variant;
>         const char      *name;
> @@ -117,7 +124,7 @@ struct sunxi_pinctrl_desc {
>         const unsigned int              *irq_bank_map;
>         bool                            irq_read_needs_mux;
>         bool                            disable_strict_mode;
> -       bool                            has_io_bias_cfg;
> +       int                             io_bias_cfg_variant;

Shouldn't we be defining this field using the enum rather than as an int?

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply

* [PATCH v3 02/11] net: stmmac: sun8i: force select external PHY when no internal one
From: megous @ 2019-04-11 10:19 UTC (permalink / raw)
  To: linux-sunxi, Maxime Ripard, Chen-Yu Tsai, Rob Herring,
	Linus Walleij
  Cc: Icenowy Zheng, David Airlie, Daniel Vetter, Mark Rutland,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, David S. Miller,
	Maxime Coquelin, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, Naveen Gupta, dri-devel,
	devicetree, linux-arm-kernel, linux-kernel, netdev, linux-stm32,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	linux-gpio, Ondrej Jirman
In-Reply-To: <20190411101951.30223-1-megous@megous.com>

From: Icenowy Zheng <icenowy@aosc.io>

The PHY selection bit also exists on SoCs without an internal PHY; if it's
set to 1 (internal PHY, default value) then the MAC will not make use of
any PHY such SoCs.

This problem appears when adapting for H6, which has no real internal PHY
(the "internal PHY" on H6 is not on-die, but on a co-packaged AC200 chip,
connected via RMII interface at GPIO bank A).

Force the PHY selection bit to 0 when the SOC doesn't have an internal PHY,
to address the problem of a wrong default value.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 20c19afb8316..cb7e7f53be7d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -907,6 +907,11 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
 		 * address. No need to mask it again.
 		 */
 		reg |= 1 << H3_EPHY_ADDR_SHIFT;
+	} else {
+		/* For SoCs without internal PHY the PHY selection bit should be
+		 * set to 0 (external PHY).
+		 */
+		reg &= ~H3_EPHY_SELECT;
 	}
 
 	if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) {
-- 
2.21.0


^ 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