From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from smtp.codeaurora.org ([198.145.29.96]) by bombadil.infradead.org with esmtps (Exim 4.92.2 #3 (Red Hat Linux)) id 1iBuHk-0007Gw-Lq for ath10k@lists.infradead.org; Sun, 22 Sep 2019 05:19:52 +0000 MIME-Version: 1.0 Date: Sun, 22 Sep 2019 13:19:43 +0800 From: Yibo Zhao Subject: Re: [PATCH 2/4] mac80211: defer txqs removal from rbtree In-Reply-To: <874l157nrt.fsf@toke.dk> References: <1568639388-27291-1-git-send-email-yiboz@codeaurora.org> <1568639388-27291-2-git-send-email-yiboz@codeaurora.org> <87pnjyiq7o.fsf@toke.dk> <87sgothmpy.fsf@toke.dk> <8cdece5c030fd95817fb099021c38613@codeaurora.org> <87tv98fu6l.fsf@toke.dk> <1b4ab006d9b5c88035845aaac193ef48@codeaurora.org> <8736gre3bm.fsf@toke.dk> <198124204167325252fcfcd65e3f2733@codeaurora.org> <87ftkp7uuz.fsf@toke.dk> <4574cce4079f8dab2b2bf223431a6eae@codeaurora.org> <877e617qg2.fsf@toke.dk> <910d9bb5f9016b29fb2aaeb0b89bac38@codeaurora.org> <874l157nrt.fsf@toke.dk> Message-ID: <2935b00bf3e29ad8b2738fe98dc24a76@codeaurora.org> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "ath10k" Errors-To: ath10k-bounces+kvalo=adurom.com@lists.infradead.org To: =?UTF-8?Q?Toke_H=C3=B8iland-J=C3=B8rgensen?= Cc: linux-wireless-owner@vger.kernel.org, linux-wireless@vger.kernel.org, ath10k@lists.infradead.org T24gMjAxOS0wOS0yMSAyMjowMCwgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+IFlp Ym8gWmhhbyA8eWlib3pAY29kZWF1cm9yYS5vcmc+IHdyaXRlczoKPiAKPj4gT24gMjAxOS0wOS0y MSAyMTowMiwgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+Pj4gWWlibyBaaGFvIDx5 aWJvekBjb2RlYXVyb3JhLm9yZz4gd3JpdGVzOgo+Pj4gCj4+Pj4gT24gMjAxOS0wOS0yMSAxOToy NywgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+Pj4+PiBZaWJvIFpoYW8gPHlpYm96 QGNvZGVhdXJvcmEub3JnPiB3cml0ZXM6Cj4+Pj4+IAo+Pj4+Pj4gT24gMjAxOS0wOS0yMCAxNzox NSwgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+Pj4+Pj4+IFlpYm8gWmhhbyA8eWli b3pAY29kZWF1cm9yYS5vcmc+IHdyaXRlczoKPj4+Pj4+PiAKPj4+Pj4+Pj4gT24gMjAxOS0wOS0x OSAxODozNywgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+Pj4+Pj4+Pj4gWWlibyBa aGFvIDx5aWJvekBjb2RlYXVyb3JhLm9yZz4gd3JpdGVzOgo+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4g T24gMjAxOS0wOS0xOCAxOToyMywgVG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIHdyb3RlOgo+Pj4+ Pj4+Pj4+PiBZaWJvIFpoYW8gPHlpYm96QGNvZGVhdXJvcmEub3JnPiB3cml0ZXM6Cj4+Pj4+Pj4+ Pj4+IAo+Pj4+Pj4+Pj4+Pj4gT24gMjAxOS0wOS0xOCAwNToxMCwgVG9rZSBIw7hpbGFuZC1Kw7hy Z2Vuc2VuIHdyb3RlOgo+Pj4+Pj4+Pj4+Pj4+IFlpYm8gWmhhbyA8eWlib3pAY29kZWF1cm9yYS5v cmc+IHdyaXRlczoKPj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gSW4gYSBsb29wIHR4cXMg ZGVxdWV1ZSBzY2VuYXJpbywgaWYgdGhlIGZpcnN0IHR4cSBpbiB0aGUKPj4+Pj4+Pj4+Pj4+Pj4g cmJ0cmVlCj4+Pj4+Pj4+Pj4+Pj4+IGdldHMKPj4+Pj4+Pj4+Pj4+Pj4gcmVtb3ZlZCBmcm9tIHJi dHJlZSBpbW1lZGlhdGVseSBpbiB0aGUKPj4+Pj4+Pj4+Pj4+Pj4gaWVlZTgwMjExX3JldHVybl90 eHEoKSwKPj4+Pj4+Pj4+Pj4+Pj4gdGhlCj4+Pj4+Pj4+Pj4+Pj4+IGxvb3Agd2lsbCBicmVhayBz b29uIGluIHRoZSBpZWVlODAyMTFfbmV4dF90eHEoKSBkdWUgdG8KPj4+Pj4+Pj4+Pj4+Pj4gc2No ZWR1bGVfcG9zCj4+Pj4+Pj4+Pj4+Pj4+IG5vdCBsZWFkaW5nIHRvIHRoZSBzZWNvbmQgdHhxIGlu IHRoZSByYnRyZWUuIFRodXMsIAo+Pj4+Pj4+Pj4+Pj4+PiBkZWZlcmluZwo+Pj4+Pj4+Pj4+Pj4+ PiB0aGUKPj4+Pj4+Pj4+Pj4+Pj4gcmVtb3ZhbCByaWdodCBiZWZvcmUgdGhlIGVuZCBvZiB0aGlz IHNjaGVkdWxlIHJvdW5kLgo+Pj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gQ28tZGV2ZWxv cGVkLWJ5OiBZaWJvIFpoYW8gPHlpYm96QGNvZGVhdXJvcmEub3JnPgo+Pj4+Pj4+Pj4+Pj4+PiBT aWduZWQtb2ZmLWJ5OiBZaWJvIFpoYW8gPHlpYm96QGNvZGVhdXJvcmEub3JnPgo+Pj4+Pj4+Pj4+ Pj4+PiBTaWduZWQtb2ZmLWJ5OiBUb2tlIEjDuGlsYW5kLUrDuHJnZW5zZW4gPHRva2VAdG9rZS5k az4KPj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+PiBJIGRpZG4ndCB3cml0ZSB0aGlzIHBhdGNo LCBzbyBwbGVhc2UgZG9uJ3QgdXNlIG15IHNpZ24tb2ZmLgo+Pj4+Pj4+Pj4+Pj4+IEknbGwKPj4+ Pj4+Pj4+Pj4+PiBhZGQKPj4+Pj4+Pj4+Pj4+PiBhY2sgb3IgcmV2aWV3IHRhZ3MgYXMgYXBwcm9w cmlhdGUgaW4gcmVwbHk7IGJ1dCBhIGZldwo+Pj4+Pj4+Pj4+Pj4+IGNvbW1lbnRzCj4+Pj4+Pj4+ Pj4+Pj4gZmlyc3Q6Cj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+IC0tLQo+Pj4+Pj4+Pj4+ Pj4+PiAgaW5jbHVkZS9uZXQvbWFjODAyMTEuaCAgICAgfCAxNiArKysrKysrKysrLS0KPj4+Pj4+ Pj4+Pj4+Pj4gIG5ldC9tYWM4MDIxMS9pZWVlODAyMTFfaS5oIHwgIDMgKysrCj4+Pj4+Pj4+Pj4+ Pj4+ICBuZXQvbWFjODAyMTEvbWFpbi5jICAgICAgICB8ICA2ICsrKysrCj4+Pj4+Pj4+Pj4+Pj4+ ICBuZXQvbWFjODAyMTEvdHguYyAgICAgICAgICB8IDYzCj4+Pj4+Pj4+Pj4+Pj4+ICsrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKystLS0KPj4+Pj4+Pj4+Pj4+Pj4gIDQg ZmlsZXMgY2hhbmdlZCwgODMgaW5zZXJ0aW9ucygrKSwgNSBkZWxldGlvbnMoLSkKPj4+Pj4+Pj4+ Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+IGRpZmYgLS1naXQgYS9pbmNsdWRlL25ldC9tYWM4MDIxMS5o IAo+Pj4+Pj4+Pj4+Pj4+PiBiL2luY2x1ZGUvbmV0L21hYzgwMjExLmgKPj4+Pj4+Pj4+Pj4+Pj4g aW5kZXggYWMyZWQ4ZS4uYmE1YTM0NSAxMDA2NDQKPj4+Pj4+Pj4+Pj4+Pj4gLS0tIGEvaW5jbHVk ZS9uZXQvbWFjODAyMTEuaAo+Pj4+Pj4+Pj4+Pj4+PiArKysgYi9pbmNsdWRlL25ldC9tYWM4MDIx MS5oCj4+Pj4+Pj4+Pj4+Pj4+IEBAIC05MjUsNiArOTI1LDggQEAgc3RydWN0IGllZWU4MDIxMV90 eF9yYXRlIHsKPj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+ICAjZGVmaW5lIElFRUU4MDIx MV9NQVhfVFhfUkVUUlkJCTMxCj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiArI2RlZmlu ZSBJRUVFODAyMTFfQUlSVElNRV9UWFFfUk1fQ0hLX0lOVFZfSU5fTVMgMTAwCj4+Pj4+Pj4+Pj4+ Pj4+ICsKPj4+Pj4+Pj4+Pj4+Pj4gIHN0YXRpYyBpbmxpbmUgdm9pZCBpZWVlODAyMTFfcmF0ZV9z ZXRfdmh0KHN0cnVjdAo+Pj4+Pj4+Pj4+Pj4+PiBpZWVlODAyMTFfdHhfcmF0ZQo+Pj4+Pj4+Pj4+ Pj4+PiAqcmF0ZSwKPj4+Pj4+Pj4+Pj4+Pj4gIAkJCQkJICB1OCBtY3MsIHU4IG5zcykKPj4+Pj4+ Pj4+Pj4+Pj4gIHsKPj4+Pj4+Pj4+Pj4+Pj4gQEAgLTYyMzIsNyArNjIzNCw4IEBAIHN0cnVjdCBz a19idWZmCj4+Pj4+Pj4+Pj4+Pj4+ICppZWVlODAyMTFfdHhfZGVxdWV1ZShzdHJ1Y3QKPj4+Pj4+ Pj4+Pj4+Pj4gaWVlZTgwMjExX2h3ICpodywKPj4+Pj4+Pj4+Pj4+Pj4gICAqIEBhYzogQUMgbnVt YmVyIHRvIHJldHVybiBwYWNrZXRzIGZyb20uCj4+Pj4+Pj4+Pj4+Pj4+ICAgKgo+Pj4+Pj4+Pj4+ Pj4+PiAgICogU2hvdWxkIG9ubHkgYmUgY2FsbGVkIGJldHdlZW4gY2FsbHMgdG8KPj4+Pj4+Pj4+ Pj4+Pj4gaWVlZTgwMjExX3R4cV9zY2hlZHVsZV9zdGFydCgpCj4+Pj4+Pj4+Pj4+Pj4+IC0gKiBh bmQgaWVlZTgwMjExX3R4cV9zY2hlZHVsZV9lbmQoKS4KPj4+Pj4+Pj4+Pj4+Pj4gKyAqIGFuZCBp ZWVlODAyMTFfdHhxX3NjaGVkdWxlX2VuZCgpLiBJZiB0aGUgdHhxIGlzIGVtcHR5LAo+Pj4+Pj4+ Pj4+Pj4+PiBpdAo+Pj4+Pj4+Pj4+Pj4+PiB3aWxsCj4+Pj4+Pj4+Pj4+Pj4+IGJlCj4+Pj4+Pj4+ Pj4+Pj4+IGFkZGVkCj4+Pj4+Pj4+Pj4+Pj4+ICsgKiB0byBhIHJlbW92ZSBsaXN0IGFuZCBnZXQg cmVtb3ZlZCBsYXRlci4KPj4+Pj4+Pj4+Pj4+Pj4gICAqIFJldHVybnMgdGhlIG5leHQgdHhxIGlm IHN1Y2Nlc3NmdWwsICVOVUxMIGlmIG5vIHF1ZXVlIAo+Pj4+Pj4+Pj4+Pj4+PiBpcwo+Pj4+Pj4+ Pj4+Pj4+PiBlbGlnaWJsZS4KPj4+Pj4+Pj4+Pj4+Pj4gSWYgYSB0eHEKPj4+Pj4+Pj4+Pj4+Pj4g ICAqIGlzIHJldHVybmVkLCBpdCBzaG91bGQgYmUgcmV0dXJuZWQgd2l0aAo+Pj4+Pj4+Pj4+Pj4+ PiBpZWVlODAyMTFfcmV0dXJuX3R4cSgpCj4+Pj4+Pj4+Pj4+Pj4+IGFmdGVyIHRoZQo+Pj4+Pj4+ Pj4+Pj4+PiAgICogZHJpdmVyIGhhcyBmaW5pc2hlZCBzY2hlZHVsaW5nIGl0Lgo+Pj4+Pj4+Pj4+ Pj4+PiBAQCAtNjI2OCw3ICs2MjcxLDggQEAgdm9pZAo+Pj4+Pj4+Pj4+Pj4+PiBpZWVlODAyMTFf dHhxX3NjaGVkdWxlX3N0YXJ0KHN0cnVjdAo+Pj4+Pj4+Pj4+Pj4+PiBpZWVlODAyMTFfaHcgKmh3 LCB1OCBhYykKPj4+Pj4+Pj4+Pj4+Pj4gICAqIEBodzogcG9pbnRlciBhcyBvYnRhaW5lZCBmcm9t IGllZWU4MDIxMV9hbGxvY19odygpCj4+Pj4+Pj4+Pj4+Pj4+ICAgKiBAYWM6IEFDIG51bWJlciB0 byBhY3F1aXJlIGxvY2tzIGZvcgo+Pj4+Pj4+Pj4+Pj4+PiAgICoKPj4+Pj4+Pj4+Pj4+Pj4gLSAq IFJlbGVhc2UgbG9ja3MgcHJldmlvdXNseSBhY3F1aXJlZCBieQo+Pj4+Pj4+Pj4+Pj4+PiBpZWVl ODAyMTFfdHhxX3NjaGVkdWxlX2VuZCgpLgo+Pj4+Pj4+Pj4+Pj4+PiArICogUmVsZWFzZSBsb2Nr cyBwcmV2aW91c2x5IGFjcXVpcmVkIGJ5Cj4+Pj4+Pj4+Pj4+Pj4+IGllZWU4MDIxMV90eHFfc2No ZWR1bGVfZW5kKCkuCj4+Pj4+Pj4+Pj4+Pj4+IENoZWNrCj4+Pj4+Pj4+Pj4+Pj4+ICsgKiBhbmQg cmVtb3ZlIHRoZSBlbXB0eSB0eHEgZnJvbSByYi10cmVlLgo+Pj4+Pj4+Pj4+Pj4+PiAgICovCj4+ Pj4+Pj4+Pj4+Pj4+ICB2b2lkIGllZWU4MDIxMV90eHFfc2NoZWR1bGVfZW5kKHN0cnVjdCBpZWVl ODAyMTFfaHcgKmh3LCAKPj4+Pj4+Pj4+Pj4+Pj4gdTgKPj4+Pj4+Pj4+Pj4+Pj4gYWMpCj4+Pj4+ Pj4+Pj4+Pj4+ICAJX19yZWxlYXNlcyh0eHFfbG9jayk7Cj4+Pj4+Pj4+Pj4+Pj4+IEBAIC02Mjg3 LDYgKzYyOTEsMTQgQEAgdm9pZCBpZWVlODAyMTFfc2NoZWR1bGVfdHhxKHN0cnVjdAo+Pj4+Pj4+ Pj4+Pj4+PiBpZWVlODAyMTFfaHcKPj4+Pj4+Pj4+Pj4+Pj4gKmh3LCBzdHJ1Y3QgaWVlZTgwMjEx X3R4cSAqdHhxKQo+Pj4+Pj4+Pj4+Pj4+PiAgCV9fYWNxdWlyZXModHhxX2xvY2spIF9fcmVsZWFz ZXModHhxX2xvY2spOwo+Pj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gIC8qKgo+Pj4+Pj4+ Pj4+Pj4+PiArICogaWVlZTgwMjExX3R4cXNfY2hlY2sgLSBDaGVjayB0eHFzIHdhaXRpbmcgZm9y IHJlbW92YWwKPj4+Pj4+Pj4+Pj4+Pj4gKyAqCj4+Pj4+Pj4+Pj4+Pj4+ICsgKiBAdG1yOiBwb2lu dGVyIGFzIG9idGFpbmVkIGZyb20gbG9jYWwKPj4+Pj4+Pj4+Pj4+Pj4gKyAqCj4+Pj4+Pj4+Pj4+ Pj4+ICsgKi8KPj4+Pj4+Pj4+Pj4+Pj4gK3ZvaWQgaWVlZTgwMjExX3R4cXNfY2hlY2soc3RydWN0 IHRpbWVyX2xpc3QgKnRtcik7Cj4+Pj4+Pj4+Pj4+Pj4+ICsKPj4+Pj4+Pj4+Pj4+Pj4gKy8qKgo+ Pj4+Pj4+Pj4+Pj4+PiAgICogaWVlZTgwMjExX3R4cV9tYXlfdHJhbnNtaXQgLSBjaGVjayB3aGV0 aGVyIFRYUSBpcwo+Pj4+Pj4+Pj4+Pj4+PiBhbGxvd2VkCj4+Pj4+Pj4+Pj4+Pj4+IHRvCj4+Pj4+ Pj4+Pj4+Pj4+IHRyYW5zbWl0Cj4+Pj4+Pj4+Pj4+Pj4+ICAgKgo+Pj4+Pj4+Pj4+Pj4+PiAgICog VGhpcyBmdW5jdGlvbiBpcyB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgZ2l2ZW4gdHhxIGlzCj4+Pj4+ Pj4+Pj4+Pj4+IGFsbG93ZWQKPj4+Pj4+Pj4+Pj4+Pj4gdG8KPj4+Pj4+Pj4+Pj4+Pj4gdHJhbnNt aXQgYnkKPj4+Pj4+Pj4+Pj4+Pj4gZGlmZiAtLWdpdCBhL25ldC9tYWM4MDIxMS9pZWVlODAyMTFf aS5oCj4+Pj4+Pj4+Pj4+Pj4+IGIvbmV0L21hYzgwMjExL2llZWU4MDIxMV9pLmgKPj4+Pj4+Pj4+ Pj4+Pj4gaW5kZXggYTQ1NTZmOS4uNDlhYTE0M2UgMTAwNjQ0Cj4+Pj4+Pj4+Pj4+Pj4+IC0tLSBh L25ldC9tYWM4MDIxMS9pZWVlODAyMTFfaS5oCj4+Pj4+Pj4+Pj4+Pj4+ICsrKyBiL25ldC9tYWM4 MDIxMS9pZWVlODAyMTFfaS5oCj4+Pj4+Pj4+Pj4+Pj4+IEBAIC04NDcsNiArODQ3LDcgQEAgc3Ry dWN0IHR4cV9pbmZvIHsKPj4+Pj4+Pj4+Pj4+Pj4gIAlzdHJ1Y3QgY29kZWxfc3RhdHMgY3N0YXRz Owo+Pj4+Pj4+Pj4+Pj4+PiAgCXN0cnVjdCBza19idWZmX2hlYWQgZnJhZ3M7Cj4+Pj4+Pj4+Pj4+ Pj4+ICAJc3RydWN0IHJiX25vZGUgc2NoZWR1bGVfb3JkZXI7Cj4+Pj4+Pj4+Pj4+Pj4+ICsJc3Ry dWN0IGxpc3RfaGVhZCBjYW5kaWRhdGU7Cj4+Pj4+Pj4+Pj4+Pj4+ICAJdW5zaWduZWQgbG9uZyBm bGFnczsKPj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+ICAJLyoga2VlcCBsYXN0ISAqLwo+ Pj4+Pj4+Pj4+Pj4+PiBAQCAtMTE0NSw2ICsxMTQ2LDggQEAgc3RydWN0IGllZWU4MDIxMV9sb2Nh bCB7Cj4+Pj4+Pj4+Pj4+Pj4+ICAJdTY0IGFpcnRpbWVfdl90W0lFRUU4MDIxMV9OVU1fQUNTXTsK Pj4+Pj4+Pj4+Pj4+Pj4gIAl1NjQgYWlydGltZV93ZWlnaHRfc3VtW0lFRUU4MDIxMV9OVU1fQUNT XTsKPj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+ICsJc3RydWN0IGxpc3RfaGVhZCByZW1v dmVfbGlzdFtJRUVFODAyMTFfTlVNX0FDU107Cj4+Pj4+Pj4+Pj4+Pj4+ICsJc3RydWN0IHRpbWVy X2xpc3QgcmVtb3ZlX3RpbWVyOwo+Pj4+Pj4+Pj4+Pj4+PiAgCXUxNiBhaXJ0aW1lX2ZsYWdzOwo+ Pj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gIAljb25zdCBzdHJ1Y3QgaWVlZTgwMjExX29w cyAqb3BzOwo+Pj4+Pj4+Pj4+Pj4+PiBkaWZmIC0tZ2l0IGEvbmV0L21hYzgwMjExL21haW4uYyBi L25ldC9tYWM4MDIxMS9tYWluLmMKPj4+Pj4+Pj4+Pj4+Pj4gaW5kZXggZTlmZmE4ZS4uNzhmZTI0 YSAxMDA2NDQKPj4+Pj4+Pj4+Pj4+Pj4gLS0tIGEvbmV0L21hYzgwMjExL21haW4uYwo+Pj4+Pj4+ Pj4+Pj4+PiArKysgYi9uZXQvbWFjODAyMTEvbWFpbi5jCj4+Pj4+Pj4+Pj4+Pj4+IEBAIC02Njcs MTAgKzY2NywxNSBAQCBzdHJ1Y3QgaWVlZTgwMjExX2h3Cj4+Pj4+Pj4+Pj4+Pj4+ICppZWVlODAy MTFfYWxsb2NfaHdfbm0oc2l6ZV90IHByaXZfZGF0YV9sZW4sCj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+ Pj4+Pj4+Pj4+PiAgCWZvciAoaSA9IDA7IGkgPCBJRUVFODAyMTFfTlVNX0FDUzsgaSsrKSB7Cj4+ Pj4+Pj4+Pj4+Pj4+ICAJCWxvY2FsLT5hY3RpdmVfdHhxc1tpXSA9IFJCX1JPT1RfQ0FDSEVEOwo+ Pj4+Pj4+Pj4+Pj4+PiArCQlJTklUX0xJU1RfSEVBRCgmbG9jYWwtPnJlbW92ZV9saXN0W2ldKTsK Pj4+Pj4+Pj4+Pj4+Pj4gIAkJc3Bpbl9sb2NrX2luaXQoJmxvY2FsLT5hY3RpdmVfdHhxX2xvY2tb aV0pOwo+Pj4+Pj4+Pj4+Pj4+PiAgCX0KPj4+Pj4+Pj4+Pj4+Pj4gIAlsb2NhbC0+YWlydGltZV9m bGFncyA9IEFJUlRJTUVfVVNFX1RYIHwgQUlSVElNRV9VU0VfUlg7Cj4+Pj4+Pj4+Pj4+Pj4+IAo+ Pj4+Pj4+Pj4+Pj4+PiArCXRpbWVyX3NldHVwKCZsb2NhbC0+cmVtb3ZlX3RpbWVyLCBpZWVlODAy MTFfdHhxc19jaGVjaywKPj4+Pj4+Pj4+Pj4+Pj4gMCk7Cj4+Pj4+Pj4+Pj4+Pj4+ICsJbW9kX3Rp bWVyKCZsb2NhbC0+cmVtb3ZlX3RpbWVyLAo+Pj4+Pj4+Pj4+Pj4+PiArCQkgIGppZmZpZXMgKwo+ Pj4+Pj4+Pj4+Pj4+PiBtc2Vjc190b19qaWZmaWVzKElFRUU4MDIxMV9BSVJUSU1FX1RYUV9STV9D SEtfSU5UVl9JTl9NUykpOwo+Pj4+Pj4+Pj4+Pj4+PiArCj4+Pj4+Pj4+Pj4+Pj4+ICAJSU5JVF9M SVNUX0hFQUQoJmxvY2FsLT5jaGFuY3R4X2xpc3QpOwo+Pj4+Pj4+Pj4+Pj4+PiAgCW11dGV4X2lu aXQoJmxvY2FsLT5jaGFuY3R4X210eCk7Cj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiBA QCAtMTMwNSw2ICsxMzEwLDcgQEAgdm9pZCBpZWVlODAyMTFfdW5yZWdpc3Rlcl9odyhzdHJ1Y3QK Pj4+Pj4+Pj4+Pj4+Pj4gaWVlZTgwMjExX2h3Cj4+Pj4+Pj4+Pj4+Pj4+ICpodykKPj4+Pj4+Pj4+ Pj4+Pj4gIAl0YXNrbGV0X2tpbGwoJmxvY2FsLT50eF9wZW5kaW5nX3Rhc2tsZXQpOwo+Pj4+Pj4+ Pj4+Pj4+PiAgCXRhc2tsZXRfa2lsbCgmbG9jYWwtPnRhc2tsZXQpOwo+Pj4+Pj4+Pj4+Pj4+PiAK Pj4+Pj4+Pj4+Pj4+Pj4gKwlkZWxfdGltZXJfc3luYygmbG9jYWwtPnJlbW92ZV90aW1lcik7Cj4+ Pj4+Pj4+Pj4+Pj4+ICAjaWZkZWYgQ09ORklHX0lORVQKPj4+Pj4+Pj4+Pj4+Pj4gIAl1bnJlZ2lz dGVyX2luZXRhZGRyX25vdGlmaWVyKCZsb2NhbC0+aWZhX25vdGlmaWVyKTsKPj4+Pj4+Pj4+Pj4+ Pj4gICNlbmRpZgo+Pj4+Pj4+Pj4+Pj4+PiBkaWZmIC0tZ2l0IGEvbmV0L21hYzgwMjExL3R4LmMg Yi9uZXQvbWFjODAyMTEvdHguYwo+Pj4+Pj4+Pj4+Pj4+PiBpbmRleCBkMDBiYWFhLi40MmNhMDEw IDEwMDY0NAo+Pj4+Pj4+Pj4+Pj4+PiAtLS0gYS9uZXQvbWFjODAyMTEvdHguYwo+Pj4+Pj4+Pj4+ Pj4+PiArKysgYi9uZXQvbWFjODAyMTEvdHguYwo+Pj4+Pj4+Pj4+Pj4+PiBAQCAtMTQ1MCw2ICsx NDUwLDcgQEAgdm9pZCBpZWVlODAyMTFfdHhxX2luaXQoc3RydWN0Cj4+Pj4+Pj4+Pj4+Pj4+IGll ZWU4MDIxMV9zdWJfaWZfZGF0YSAqc2RhdGEsCj4+Pj4+Pj4+Pj4+Pj4+ICAJY29kZWxfc3RhdHNf aW5pdCgmdHhxaS0+Y3N0YXRzKTsKPj4+Pj4+Pj4+Pj4+Pj4gIAlfX3NrYl9xdWV1ZV9oZWFkX2lu aXQoJnR4cWktPmZyYWdzKTsKPj4+Pj4+Pj4+Pj4+Pj4gIAlSQl9DTEVBUl9OT0RFKCZ0eHFpLT5z Y2hlZHVsZV9vcmRlcik7Cj4+Pj4+Pj4+Pj4+Pj4+ICsJSU5JVF9MSVNUX0hFQUQoJnR4cWktPmNh bmRpZGF0ZSk7Cj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiAgCXR4cWktPnR4cS52aWYg PSAmc2RhdGEtPnZpZjsKPj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+Pj4+IEBAIC0zNzI0LDYg KzM3MjUsOSBAQCB2b2lkIGllZWU4MDIxMV9zY2hlZHVsZV90eHEoc3RydWN0Cj4+Pj4+Pj4+Pj4+ Pj4+IGllZWU4MDIxMV9odwo+Pj4+Pj4+Pj4+Pj4+PiAqaHcsCj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+ Pj4+Pj4+Pj4+PiAgCXNwaW5fbG9ja19iaCgmbG9jYWwtPmFjdGl2ZV90eHFfbG9ja1thY10pOwo+ Pj4+Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gKwlpZiAoIWxpc3RfZW1wdHkoJnR4cWktPmNh bmRpZGF0ZSkpCj4+Pj4+Pj4+Pj4+Pj4+ICsJCWxpc3RfZGVsX2luaXQoJnR4cWktPmNhbmRpZGF0 ZSk7Cj4+Pj4+Pj4+Pj4+Pj4+ICsKPj4+Pj4+Pj4+Pj4+Pj4gIAlpZiAoIVJCX0VNUFRZX05PREUo JnR4cWktPnNjaGVkdWxlX29yZGVyKSkKPj4+Pj4+Pj4+Pj4+Pj4gIAkJZ290byBvdXQ7Cj4+Pj4+ Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiBAQCAtMzc4Myw2ICszNzg3LDIwIEBAIHN0YXRpYyB2 b2lkCj4+Pj4+Pj4+Pj4+Pj4+IF9faWVlZTgwMjExX3Vuc2NoZWR1bGVfdHhxKHN0cnVjdAo+Pj4+ Pj4+Pj4+Pj4+PiBpZWVlODAyMTFfaHcgKmh3LAo+Pj4+Pj4+Pj4+Pj4+PiAgCVJCX0NMRUFSX05P REUoJnR4cWktPnNjaGVkdWxlX29yZGVyKTsKPj4+Pj4+Pj4+Pj4+Pj4gIH0KPj4+Pj4+Pj4+Pj4+ Pj4gCj4+Pj4+Pj4+Pj4+Pj4+ICt2b2lkIGllZWU4MDIxMV9yZW1vdmVfdHhxKHN0cnVjdCBpZWVl ODAyMTFfaHcgKmh3LAo+Pj4+Pj4+Pj4+Pj4+PiArCQkJICBzdHJ1Y3QgaWVlZTgwMjExX3R4cSAq dHhxKQo+Pj4+Pj4+Pj4+Pj4+PiArewo+Pj4+Pj4+Pj4+Pj4+PiArCXN0cnVjdCBpZWVlODAyMTFf bG9jYWwgKmxvY2FsID0gaHdfdG9fbG9jYWwoaHcpOwo+Pj4+Pj4+Pj4+Pj4+PiArCXN0cnVjdCB0 eHFfaW5mbyAqdHhxaSA9IHRvX3R4cV9pbmZvKHR4cSk7Cj4+Pj4+Pj4+Pj4+Pj4+ICsKPj4+Pj4+ Pj4+Pj4+Pj4gKwlsb2NrZGVwX2Fzc2VydF9oZWxkKCZsb2NhbC0+YWN0aXZlX3R4cV9sb2NrW3R4 cS0+YWNdKTsKPj4+Pj4+Pj4+Pj4+Pj4gKwo+Pj4+Pj4+Pj4+Pj4+PiArCWlmICghUkJfRU1QVFlf Tk9ERSgmdHhxaS0+c2NoZWR1bGVfb3JkZXIpKSB7Cj4+Pj4+Pj4+Pj4+Pj4+ICsJCV9faWVlZTgw MjExX3Vuc2NoZWR1bGVfdHhxKGh3LCB0eHEpOwo+Pj4+Pj4+Pj4+Pj4+PiArCQlsaXN0X2RlbF9p bml0KCZ0eHFpLT5jYW5kaWRhdGUpOwo+Pj4+Pj4+Pj4+Pj4+PiArCX0KPj4+Pj4+Pj4+Pj4+Pj4g K30KPj4+Pj4+Pj4+Pj4+Pj4gKwo+Pj4+Pj4+Pj4+Pj4+PiAgdm9pZCBpZWVlODAyMTFfdW5zY2hl ZHVsZV90eHEoc3RydWN0IGllZWU4MDIxMV9odyAqaHcsCj4+Pj4+Pj4+Pj4+Pj4+ICAJCQkgICAg ICBzdHJ1Y3QgaWVlZTgwMjExX3R4cSAqdHhxKQo+Pj4+Pj4+Pj4+Pj4+PiAgCV9fYWNxdWlyZXMo dHhxX2xvY2spIF9fcmVsZWFzZXModHhxX2xvY2spCj4+Pj4+Pj4+Pj4+Pj4+IEBAIC0zNzkwLDcg KzM4MDgsNyBAQCB2b2lkIGllZWU4MDIxMV91bnNjaGVkdWxlX3R4cShzdHJ1Y3QKPj4+Pj4+Pj4+ Pj4+Pj4gaWVlZTgwMjExX2h3ICpodywKPj4+Pj4+Pj4+Pj4+Pj4gIAlzdHJ1Y3QgaWVlZTgwMjEx X2xvY2FsICpsb2NhbCA9IGh3X3RvX2xvY2FsKGh3KTsKPj4+Pj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+ Pj4+Pj4+ICAJc3Bpbl9sb2NrX2JoKCZsb2NhbC0+YWN0aXZlX3R4cV9sb2NrW3R4cS0+YWNdKTsK Pj4+Pj4+Pj4+Pj4+Pj4gLQlfX2llZWU4MDIxMV91bnNjaGVkdWxlX3R4cShodywgdHhxKTsKPj4+ Pj4+Pj4+Pj4+Pj4gKwlpZWVlODAyMTFfcmVtb3ZlX3R4cShodywgdHhxKTsKPj4+Pj4+Pj4+Pj4+ Pj4gIAlzcGluX3VubG9ja19iaCgmbG9jYWwtPmFjdGl2ZV90eHFfbG9ja1t0eHEtPmFjXSk7Cj4+ Pj4+Pj4+Pj4+Pj4+ICB9Cj4+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiBAQCAtMzgwMywx MSArMzgyMSw0OCBAQCB2b2lkIGllZWU4MDIxMV9yZXR1cm5fdHhxKHN0cnVjdAo+Pj4+Pj4+Pj4+ Pj4+PiBpZWVlODAyMTFfaHcKPj4+Pj4+Pj4+Pj4+Pj4gKmh3LAo+Pj4+Pj4+Pj4+Pj4+PiAgCWxv Y2tkZXBfYXNzZXJ0X2hlbGQoJmxvY2FsLT5hY3RpdmVfdHhxX2xvY2tbdHhxLT5hY10pOwo+Pj4+ Pj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+Pj4+Pj4gIAlpZiAoIVJCX0VNUFRZX05PREUoJnR4cWktPnNj aGVkdWxlX29yZGVyKSAmJgo+Pj4+Pj4+Pj4+Pj4+PiAtCSAgICAoc2tiX3F1ZXVlX2VtcHR5KCZ0 eHFpLT5mcmFncykgJiYKPj4+Pj4+Pj4+Pj4+Pj4gIXR4cWktPnRpbi5iYWNrbG9nX3BhY2tldHMp KQo+Pj4+Pj4+Pj4+Pj4+PiAtCQlfX2llZWU4MDIxMV91bnNjaGVkdWxlX3R4cShodywgdHhxKTsK Pj4+Pj4+Pj4+Pj4+Pj4gKwkJIXR4cV9oYXNfcXVldWUoJnR4cWktPnR4cSkgJiYKPj4+Pj4+Pj4+ Pj4+Pj4gKwkJbGlzdF9lbXB0eSgmdHhxaS0+Y2FuZGlkYXRlKSkKPj4+Pj4+Pj4+Pj4+Pj4gKwkJ bGlzdF9hZGRfdGFpbCgmdHhxaS0+Y2FuZGlkYXRlLAo+Pj4+Pj4+Pj4+Pj4+PiAmbG9jYWwtPnJl bW92ZV9saXN0W3R4cS0+YWNdKTsKPj4+Pj4+Pj4+Pj4+Pj4gKwo+Pj4+Pj4+Pj4+Pj4+PiAgfQo+ Pj4+Pj4+Pj4+Pj4+PiAgRVhQT1JUX1NZTUJPTChpZWVlODAyMTFfcmV0dXJuX3R4cSk7Cj4+Pj4+ Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+PiArdm9pZCBfX2llZWU4MDIxMV9jaGVja190eHFzKHN0 cnVjdCBpZWVlODAyMTFfbG9jYWwgCj4+Pj4+Pj4+Pj4+Pj4+ICpsb2NhbCwKPj4+Pj4+Pj4+Pj4+ Pj4gaW50Cj4+Pj4+Pj4+Pj4+Pj4+IGFjKQo+Pj4+Pj4+Pj4+Pj4+PiArewo+Pj4+Pj4+Pj4+Pj4+ PiArCXN0cnVjdCB0eHFfaW5mbyAqaXRlciwgKnRtcDsKPj4+Pj4+Pj4+Pj4+Pj4gKwlzdHJ1Y3Qg c3RhX2luZm8gKnN0YTsKPj4+Pj4+Pj4+Pj4+Pj4gKwo+Pj4+Pj4+Pj4+Pj4+PiArCWxvY2tkZXBf YXNzZXJ0X2hlbGQoJmxvY2FsLT5hY3RpdmVfdHhxX2xvY2tbYWNdKTsKPj4+Pj4+Pj4+Pj4+Pj4g Kwo+Pj4+Pj4+Pj4+Pj4+PiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShpdGVyLCB0bXAsCj4+ Pj4+Pj4+Pj4+Pj4+ICZsb2NhbC0+cmVtb3ZlX2xpc3RbYWNdLAo+Pj4+Pj4+Pj4+Pj4+PiArCQkJ CSBjYW5kaWRhdGUpIHsKPj4+Pj4+Pj4+Pj4+Pj4gKwkJc3RhID0gY29udGFpbmVyX29mKGl0ZXIt PnR4cS5zdGEsIHN0cnVjdCBzdGFfaW5mbywgCj4+Pj4+Pj4+Pj4+Pj4+IHN0YSk7Cj4+Pj4+Pj4+ Pj4+Pj4+ICsKPj4+Pj4+Pj4+Pj4+Pj4gKwkJaWYgKHR4cV9oYXNfcXVldWUoJml0ZXItPnR4cSkp Cj4+Pj4+Pj4+Pj4+Pj4+ICsJCQlsaXN0X2RlbF9pbml0KCZpdGVyLT5jYW5kaWRhdGUpOwo+Pj4+ Pj4+Pj4+Pj4+PiArCQllbHNlCj4+Pj4+Pj4+Pj4+Pj4+ICsJCQlpZWVlODAyMTFfcmVtb3ZlX3R4 cSgmbG9jYWwtPmh3LCAmaXRlci0+dHhxKTsKPj4+Pj4+Pj4+Pj4+Pj4gKwl9Cj4+Pj4+Pj4+Pj4+ Pj4+ICt9Cj4+Pj4+Pj4+Pj4+Pj4+ICsKPj4+Pj4+Pj4+Pj4+Pj4gK3ZvaWQgaWVlZTgwMjExX3R4 cXNfY2hlY2soc3RydWN0IHRpbWVyX2xpc3QgKnQpCj4+Pj4+Pj4+Pj4+Pj4+ICt7Cj4+Pj4+Pj4+ Pj4+Pj4+ICsJc3RydWN0IGllZWU4MDIxMV9sb2NhbCAqbG9jYWwgPSBmcm9tX3RpbWVyKGxvY2Fs LCB0LAo+Pj4+Pj4+Pj4+Pj4+PiByZW1vdmVfdGltZXIpOwo+Pj4+Pj4+Pj4+Pj4+PiArCXN0cnVj dCB0eHFfaW5mbyAqaXRlciwgKnRtcDsKPj4+Pj4+Pj4+Pj4+Pj4gKwlzdHJ1Y3Qgc3RhX2luZm8g KnN0YTsKPj4+Pj4+Pj4+Pj4+Pj4gKwlpbnQgYWM7Cj4+Pj4+Pj4+Pj4+Pj4+ICsKPj4+Pj4+Pj4+ Pj4+Pj4gKwlmb3IgKGFjID0gMDsgYWMgPCBJRUVFODAyMTFfTlVNX0FDUzsgYWMrKykgewo+Pj4+ Pj4+Pj4+Pj4+PiArCQlzcGluX2xvY2tfYmgoJmxvY2FsLT5hY3RpdmVfdHhxX2xvY2tbYWNdKTsK Pj4+Pj4+Pj4+Pj4+Pj4gKwkJX19pZWVlODAyMTFfY2hlY2tfdHhxcyhsb2NhbCwgYWMpOwo+Pj4+ Pj4+Pj4+Pj4+PiArCQlzcGluX3VubG9ja19iaCgmbG9jYWwtPmFjdGl2ZV90eHFfbG9ja1thY10p Owo+Pj4+Pj4+Pj4+Pj4+PiArCX0KPj4+Pj4+Pj4+Pj4+Pj4gKwo+Pj4+Pj4+Pj4+Pj4+PiArCW1v ZF90aW1lcigmbG9jYWwtPnJlbW92ZV90aW1lciwKPj4+Pj4+Pj4+Pj4+Pj4gKwkJICBqaWZmaWVz ICsKPj4+Pj4+Pj4+Pj4+Pj4gbXNlY3NfdG9famlmZmllcyhJRUVFODAyMTFfQUlSVElNRV9UWFFf Uk1fQ0hLX0lOVFZfSU5fTVMpKTsKPj4+Pj4+Pj4+Pj4+Pj4gK30KPj4+Pj4+Pj4+Pj4+PiAKPj4+ Pj4+Pj4+Pj4+PiBJJ2xsIGFzayB0aGUgc2FtZSBhcyBJIGRpZCBsYXN0IHRpbWUgKHdoZXJlIHlv dSB0b2xkIG1lIHRvCj4+Pj4+Pj4+Pj4+Pj4gaG9sZAo+Pj4+Pj4+Pj4+Pj4+IG9mZgo+Pj4+Pj4+ Pj4+Pj4+IHVudGlsIHRoaXMgcm91bmQpOgo+Pj4+Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+Pj4+IFdo eSBkbyB5b3UgbmVlZCB0aGUgdGltZXIgYW5kIHRoZSBwZXJpb2RpYyBjaGVjaz8gSWYgVFhRcyAK Pj4+Pj4+Pj4+Pj4+PiBhcmUKPj4+Pj4+Pj4+Pj4+PiBhZGRlZAo+Pj4+Pj4+Pj4+Pj4+IHRvCj4+ Pj4+Pj4+Pj4+Pj4gdGhlIHJlbW92ZSBsaXN0IGR1cmluZyB0aGUgc2NoZWR1bGluZyBydW4sIGFu ZAo+Pj4+Pj4+Pj4+Pj4+IF9faWVlZTgwMjExX2NoZWNrX3R4cXMoKQo+Pj4+Pj4+Pj4+Pj4+IGlz IHJ1biBmcm9tIHNjaGVkdWxlX2VuZCgpLCBpc24ndCB0aGF0IHN1ZmZpY2llbnQgdG8gY2xlYXIK Pj4+Pj4+Pj4+Pj4+PiB0aGUKPj4+Pj4+Pj4+Pj4+PiBsaXN0Pwo+Pj4+Pj4+Pj4+Pj4gSXMgaXQg cG9zc2libGUgdGhhdCBhIHR4cSBpcyBub3QgYWRkZWQgdG8gdGhlIHJlbW92ZSBsaXN0IAo+Pj4+ Pj4+Pj4+Pj4gYnV0Cj4+Pj4+Pj4+Pj4+PiB0aGVuCj4+Pj4+Pj4+Pj4+PiBwYWNrZXRzIGluIGl0 IGFyZSBkcm9wcGVkIGJ5IGZxX2NvZGVsIGFsZ28/IExpa2UgdGhlIHN0YXRpb24KPj4+Pj4+Pj4+ Pj4+IGRpc2Nvbm5lY3RzCj4+Pj4+Pj4+Pj4+PiB3aXRob3V0IGFueSBub3RpZmljYXRpb24uCj4+ Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+PiBXZWxsIGFzIGxvbmcgYXMgYWxsIHRoZSBvdGhlciBjbGVh bnVwIHBhdGhzIGNhbGwgZGlyZWN0bHkgCj4+Pj4+Pj4+Pj4+IGludG8KPj4+Pj4+Pj4+Pj4gX191 bnNjaGVkdWxlX3R4cSgpLCB0aGF0IHNob3VsZCByZW1vdmUgc3RhdGlvbnMgZnJvbSB0aGUKPj4+ Pj4+Pj4+Pj4gc2NoZWR1bGVyCj4+Pj4+Pj4+Pj4+IHdoZW4KPj4+Pj4+Pj4+Pj4gdGhleSBkaXNj b25uZWN0IGV0Yy4KPj4+Pj4+Pj4+PiBZZXMsIHRoZSBkaXNjb25uZWN0IHNjZW5hcmlvIGlzIGEg YmFkIGV4YW1wbGUuIE15IGNvbmNlcm4gaXMsCj4+Pj4+Pj4+Pj4gc2F5LAo+Pj4+Pj4+Pj4+IHdl Cj4+Pj4+Pj4+Pj4gaGF2ZSAxMCBzdGF0aW9ucyBhbmQgb25seSBvbmUgb2YgdGhlbSBpcyBhc3Np Z25lZCBhIHZlcnkgc21hbGwKPj4+Pj4+Pj4+PiB3ZWlnaHQKPj4+Pj4+Pj4+PiBjb21wYXJlZCB3 aXRoIHRoYXQgb2Ygb3RoZXJzLiBTdXBwb3NlLCBhZnRlciBpdHMgY2hhbmNlIG9mIFR4LAo+Pj4+ Pj4+Pj4+IGl0Cj4+Pj4+Pj4+Pj4gaXMKPj4+Pj4+Pj4+PiBtb3N0IGxpa2VseSB0byBiZSBwbGFj ZWQgaW4gdGhlIHJpZ2h0bW9zdChzdGlsbCBoYXMgc29tZSAKPj4+Pj4+Pj4+PiBwYWNrZXRzCj4+ Pj4+Pj4+Pj4gaW4KPj4+Pj4+Pj4+PiB0aGUKPj4+Pj4+Pj4+PiB0eHEpIGFuZCBubyBtb3JlIGlu Y29taW5nIGRhdGEgZm9yIGl0LiBUaGUgcmVtYWluaW5nIHBhY2tldHMgCj4+Pj4+Pj4+Pj4gaW4K Pj4+Pj4+Pj4+PiB0eHEKPj4+Pj4+Pj4+PiB3aWxsCj4+Pj4+Pj4+Pj4gYmUgZHJvcHBlZCBkdWUg dG8gdGltZW91dCBhbGdvIGluIGNvZGVsKGNvcnJlY3QgbWUgaWYgSSBhbQo+Pj4+Pj4+Pj4+IHdy b25nKQo+Pj4+Pj4+Pj4+IGJ1dAo+Pj4+Pj4+Pj4+IHRoaXMgZW1wdHkgdHhxIHdpbGwgc3RheSBv biB0aGUgcmJ0cmVlIHVudGlsIG90aGVyIHR4cXMgZ2V0Cj4+Pj4+Pj4+Pj4gZHJhaW5lZAo+Pj4+ Pj4+Pj4+IG9yCj4+Pj4+Pj4+Pj4gZ2xvYmFsIHZ0IGNhdGNoIHVwIHdpdGggaXRzIHZ0LiBUaGUg c3RheWluZyB0aW1lIGNvdWxkIGJlIGxvbmcKPj4+Pj4+Pj4+PiBpZgo+Pj4+Pj4+Pj4+IHdlaWdo dAo+Pj4+Pj4+Pj4+IGlzIGV4dHJlbWVseSBzbWFsbC4gVGhlbiBkbyB3ZSBuZWVkIHRpbWVyIHRv IGNoZWNrIG9yIGFueSAKPj4+Pj4+Pj4+PiBvdGhlcgo+Pj4+Pj4+Pj4+IGJldHRlcgo+Pj4+Pj4+ Pj4+IHNvbHV0aW9uPwo+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+PiBBaCwgSSBzZWUgd2hhdCB5b3UgbWVh bi4gTm8sIEkgZG9uJ3QgdGhpbmsgdGhpcyB3aWxsIGJlIGEKPj4+Pj4+Pj4+IHByb2JsZW07Cj4+ Pj4+Pj4+PiB0aGUKPj4+Pj4+Pj4+IHNjZW5hcmlvIHlvdSdyZSBkZXNjcmliaW5nIHdvdWxkIHBs YXkgb3V0IGxpa2UgdGhpczoKPj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4gMS4gU3RhdGlvbiBlbmRzIHRy YW5zbWl0dGluZywgc3RpbGwgaGFzIGEgc2luZ2xlIHBhY2tldCBxdWV1ZWQsCj4+Pj4+Pj4+PiBn ZXRzCj4+Pj4+Pj4+PiAgICBtb3ZlZCB0byB0aGUgZW5kIG9mIHRoZSByYnRyZWUgKGFuZCBzdGF5 cyB0aGVyZSBmb3IgYSAKPj4+Pj4+Pj4+IHdoaWxlKS4KPj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4gMi4g V2hlbiB3ZSBmaW5hbGx5IGdldCB0byB0aGUgcG9pbnQgd2hlcmUgdGhpcyBzdGF0aW9uIGdldHMK Pj4+Pj4+Pj4+IGFub3RoZXIKPj4+Pj4+Pj4+ICAgIGNoYW5jZSB0byB0cmFuc21pdCwgdGhlIENv RGVsIGRyb3AgdGltZXIgdHJpZ2dlcnMgYW5kIHRoZSAKPj4+Pj4+Pj4+IGxhc3QKPj4+Pj4+Pj4+ IHBhY2tldAo+Pj4+Pj4+Pj4gICAgaXMgZHJvcHBlZFswXS4gVGhpcyBtZWFucyB0aGF0IHRoZSBx dWV1ZSB3aWxsIGp1c3QgYmUgZW1wdHkKPj4+Pj4+Pj4+ICAgIChhbmQgaWVlZTgwMjExX3R4X2Rl cXVldWUoKSB3aWxsIHJldHVybiBOVUxMKS4KPj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4gMy4gQmVjYXVz ZSB0aGUgcXVldWUgaXMgZW1wdHksIGllZWU4MDIxMV9yZXR1cm5fdHhxKCkgd2lsbCBub3QKPj4+ Pj4+Pj4+IHB1dAo+Pj4+Pj4+Pj4gaXQKPj4+Pj4+Pj4+ICAgIGJhY2sgb24gdGhlIHJidHJlZS4K Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4gQ3J1Y2lhbGx5LCBpbiAyLiB0aGUgQ29EZWwgYWxnb3JpdGht IGRvZXNuJ3Qga2ljayBpbiB1bnRpbCB0aGUKPj4+Pj4+Pj4+IHBvaW50Cj4+Pj4+Pj4+PiBvZgo+ Pj4+Pj4+Pj4gcGFja2V0IGRlcXVldWUuIEJ1dCBldmVuIGlmIGFuIGVtcHR5IHF1ZXVlIHN0YXlz IG9uIHRoZSByYnRyZWUKPj4+Pj4+Pj4+IGZvcgo+Pj4+Pj4+Pj4gYQo+Pj4+Pj4+Pj4gd2hpbGUs IHRoZXJlIGlzIG5vIGhhcm0gaW4gdGhhdDogZXZlbnR1YWxseSBpdCB3aWxsIGdldCBpdHMgCj4+ Pj4+Pj4+PiB0dXJuLAo+Pj4+Pj4+Pj4gaXQKPj4+Pj4+Pj4+IHdpbGwgdHVybiBvdXQgdG8gYmUg ZW1wdHksIGFuZCBqdXN0IGJlIHNraXBwZWQgb3Zlci4KPj4+Pj4+Pj4gVGhlbiB0aGF0IHdpbGwg YmUgZmluZS4gVGhhbmtzIGZvciB0aGUgZXhwbGFuYXRpb24gb2YgdGhlIAo+Pj4+Pj4+PiBkcm9w cGluZwo+Pj4+Pj4+PiBwYXJ0Cj4+Pj4+Pj4+IGluIENvRGVsIGFsZ29yaXRobS4KPj4+Pj4+PiAK Pj4+Pj4+PiBZdXAsIHRoaW5rIHNvLiBBbmQgeW91J3JlIHdlbGNvbWUgOikKPj4+Pj4+PiAKPj4+ Pj4+Pj4+IFRoZSBpc3N1ZSB3ZSBuZWVkIHRvIGJlIGNvbmNlcm5lZCBhYm91dCBpcyB0aGUgb3Bw b3NpdGU6IElmIHdlCj4+Pj4+Pj4+PiBoYXZlCj4+Pj4+Pj4+PiBhCj4+Pj4+Pj4+PiBxdWV1ZSB0 aGF0ICpkb2VzKiBoYXZlIHBhY2tldHMgcXVldWVkLCBidXQgd2hpY2ggaXMgKm5vdCoKPj4+Pj4+ Pj4+IHNjaGVkdWxlZAo+Pj4+Pj4+Pj4gZm9yCj4+Pj4+Pj4+PiB0cmFuc21pc3Npb24sIHRoYXQg d2lsbCBzdGFsbCBUWC4KPj4+Pj4+Pj4gSXMgaXQgYnkgZGVzaWduIHNpbmNlIGl0cyB2dCBpcyBt b3JlIHRoYW4gZ2xvYmFsIHZ0LCByaWdodD8gVGhlCj4+Pj4+Pj4+IGxhdHRlbmN5Cj4+Pj4+Pj4+ IG1heSBzb21laG93IGdldCBpbXBhY3RlZCB0aG91Z2guCj4+Pj4+Pj4gCj4+Pj4+Pj4gV2VsbCwg aXQgc2hvdWxkIHN0aWxsIHN0YXkgb24gdGhlIHJidHJlZSBhcyBsb25nIGFzIGl0IGhhcyAKPj4+ Pj4+PiBwYWNrZXRzCj4+Pj4+Pj4gcXVldWVkLiBXZSBkb24ndCBoYXZlIGEgY2hlY2sgYW55d2hl cmUgdGhhdCByZXNjaGVkdWxlcyBUWFFzIAo+Pj4+Pj4+IHdob3NlCj4+Pj4+Pj4gdl90Cj4+Pj4+ Pj4gZHJvcHMgYmVsb3cgZ2xvYmFsIHZfdC4uLgo+Pj4+Pj4+IAo+Pj4+Pj4+Pj4gWzBdIENvRGVs IGluIG1vc3QgY2FzZXMgb25seSBkcm9wcyBhIHNpbmdsZSBwYWNrZXQgYXQgYSB0aW1lLCAKPj4+ Pj4+Pj4+IHNvCj4+Pj4+Pj4+PiBpdAo+Pj4+Pj4+Pj4gd2lsbAo+Pj4+Pj4+Pj4gbm90IGNsZWFy IG91dCBhbiBlbnRpcmUgcXVldWUgd2l0aCBtdWx0aXBsZSBwYWNrZXRzIGluIG9uZSBnby4KPj4+ Pj4+Pj4+IEJ1dAo+Pj4+Pj4+Pj4geW91Cj4+Pj4+Pj4+PiBhcmUgcmlnaHQgdGhhdCBpdCBjb3Vs ZCBjb25jZWl2YWJseSBkcm9wIHRoZSBsYXN0IHBhY2tldCBpbiBhCj4+Pj4+Pj4+PiBxdWV1ZS4K Pj4+Pj4+Pj4+IAo+Pj4+Pj4+Pj4+PiBXZSBvbmx5IG5lZWQgdG8gZGVmZXIgcmVtb3ZhbCBpbnNp ZGUgYSBzaW5nbGUgInNjaGVkdWxpbmcKPj4+Pj4+Pj4+Pj4gcm91bmQiCj4+Pj4+Pj4+Pj4+IChp LmUuLAo+Pj4+Pj4+Pj4+PiBiZXR3ZWVuIGEgcGFpciBvZiBpZWVlODAyMTFfdHhxX3NjaGVkdWxl X3N0YXJ0L2VuZC4gU28gaWYgd2UKPj4+Pj4+Pj4+Pj4ganVzdAo+Pj4+Pj4+Pj4+PiB3YWxrCj4+ Pj4+Pj4+Pj4+IHRoZSByZW1vdmUgbGlzdCBpbiBzY2hlZHVsZV9lbmQoKSB3ZSBzaG91bGQgYmUg ZW5vdWdoLCBubz8KPj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+IEhtbSwgb3IgbWF5YmUgYSBzaW1w bGVyIHdheSB0byBmaXggdGhlIG9yaWdpbmFsIGlzc3VlIGlzIGp1c3QKPj4+Pj4+Pj4+Pj4gdG8K Pj4+Pj4+Pj4+Pj4gaGF2ZQo+Pj4+Pj4+Pj4+PiB1bnNjaGVkdWxlX3R4cSgpIHVwZGF0ZSB0aGUg c2NoZWR1bGVfcG9zKCkgcG9pbnRlcj8KPj4+Pj4+Pj4+Pj4gCj4+Pj4+Pj4+Pj4+IEkuZS4sIHVu c2NoZWR1bGVfdHhxIGNoZWNrcyBpZiB0aGUgdHhxIGJlaW5nIHJlbW92ZWQgaXMKPj4+Pj4+Pj4+ Pj4gY3VycmVudGx5Cj4+Pj4+Pj4+Pj4+IGJlaW5nCj4+Pj4+Pj4+Pj4+IHBvaW50ZWQgdG8gYnkg c2NoZWR1bGVfcG9zW2FjXSwgYW5kIGlmIGl0IGlzLCBpdCB1cGRhdGVzCj4+Pj4+Pj4+Pj4+IHNj aGVkdWxlX3Bvcwo+Pj4+Pj4+Pj4+PiB0bwo+Pj4+Pj4+Pj4+PiBiZSB0aGUgcmJfbmV4dCBvZiB0 aGUgY3VycmVudCB2YWx1ZT8KPj4+Pj4+Pj4+PiBBY3R1YWxseSwgaWYgc2NoZWR1bGVfcG9zIGlz IHVwZGF0ZWQgdG8gcmJfbmV4dCBvZiB0aGUgY3VycmVudAo+Pj4+Pj4+Pj4+IHZhbHVlLAo+Pj4+ Pj4+Pj4+IHRoZW4gaW4gdGhlIG5leHRfdHhxKCkgd2hlcmUgd2UgYXJlIGdvaW5nIHRvIHVzZSBy Yl9uZXh0IGFnYWluCj4+Pj4+Pj4+Pj4gYW5kCj4+Pj4+Pj4+Pj4gZmluYWxseSBwaWNrIHRoZSBu ZXh0IG5vZGUgb2YgdGhlIG5vZGUgd2UgcmVhbGx5IHdhbnQuIElzIGl0Cj4+Pj4+Pj4+Pj4gZmlu ZQo+Pj4+Pj4+Pj4+IHRvCj4+Pj4+Pj4+Pj4gdXBkYXRlIHNjaGVkdWxlX3BvcyB0byBOVUxMPwo+ Pj4+Pj4+Pj4gCj4+Pj4+Pj4+PiBIbW0sIHllYWgsIGdvb2QgcG9pbnQuCj4+Pj4+Pj4+PiAKPj4+ Pj4+Pj4+IElmIHdlIGRvIGVuZCB1cCBzZXR0aW5nIHNjaGVkdWxlX3BvcyB0byBOVUxMIGluIHRo ZSBtaWRkbGUgb2YgYQo+Pj4+Pj4+Pj4gc2NoZWR1bGluZyByb3VuZCwgdGhhdCB3aWxsIG1ha2Ug bmV4dF90eHEoKSAic3RhcnQgb3ZlciIsIGFuZCAKPj4+Pj4+Pj4+IGRvCj4+Pj4+Pj4+PiBhbm90 aGVyCj4+Pj4+Pj4+PiBsb29wIHRocm91Z2ggdGhlIHdob2xlIHRoaW5nLiBJIGd1ZXNzIHdlIG1h eSBiZSBhYmxlIGhpdCBhIGNhc2UKPj4+Pj4+Pj4+IHdoZXJlCj4+Pj4+Pj4+PiB0aGluZ3MgY2Fu IG9zY2lsbGF0ZSBiYWNrIGFuZCBmb3J0aCBiZXR3ZWVuIGFkZGl0aW9uIGFuZCAKPj4+Pj4+Pj4+ IHJlbW92YWwKPj4+Pj4+Pj4+IHJlc3VsdGluZyBpbiBhbiBpbmZpbml0ZSBsb29wPyBOb3Qgc3Vy ZSwgYnV0IGF0IGxlYXN0IEkgY2FuJ3QKPj4+Pj4+Pj4+IHNlZW0KPj4+Pj4+Pj4+IHRvCj4+Pj4+ Pj4+PiBjb252aW5jZSBteXNlbGYgdGhhdCB0aGlzIGNhbid0IGhhcHBlbi4KPj4+Pj4+Pj4gCj4+ Pj4+Pj4+IEFzIHRoZSBsb29wIG9mIG5leHRfdHhxIHVuZGVyIGxvY2sgcHJvdGVjdGlvbiBhcyBi ZWxvdywKPj4+Pj4+Pj4gCj4+Pj4+Pj4+IHR4cV9zY2hlZHVsZV9zdGFydCgpOwo+Pj4+Pj4+PiB3 aGlsZSh0eHE9bmV4dF90eHEoKSl7Cj4+Pj4+Pj4+IC4uLgo+Pj4+Pj4+PiByZXR1cm5fdHhxKHR4 cSk7Cj4+Pj4+Pj4+IH0KPj4+Pj4+Pj4gdHhxX3NjaGVkdWxlX2VuZCgpOwo+Pj4+Pj4+PiAKPj4+ Pj4+Pj4gSSBkbyBub3Qgc2VlIGFueSBjaGFuY2Ugb2YgYWRkaXRpb24sIG5vPwo+Pj4+Pj4+IAo+ Pj4+Pj4+IEFzIHlvdSBub3RlZCBpbiB5b3VyIG90aGVyIGVtYWlsLCBGZWxpeCByZWR1Y2VkIHRo ZSBsb2NraW5nLiBBbmQKPj4+Pj4+PiB5ZWFoLAo+Pj4+Pj4+IHdlIG5lZWQgdG8gcmViYXNlIHRo aXMgc2VyaWVzIHRvIGFsc28gaW5jb3Jwb3JhdGUgdGhhdC4gSSBmaWd1cmUgCj4+Pj4+Pj4gSQo+ Pj4+Pj4+IGNhbgo+Pj4+Pj4+IHNlbmQgYW4gdXBkYXRlZCB2ZXJzaW9uIG9mIHRoZSBmaXJzdCBw YXRjaCBpbiB0aGUgc2VyaWVzIG9uY2UgCj4+Pj4+Pj4gd2UndmUKPj4+Pj4+PiB3b3JrZWQgb3V0 IHRoZSByZW1haW5pbmcgaXNzdWVzIHdpdGggeW91ciBmb2xsb3ctdXAgcGF0Y2hlcy4KPj4+Pj4+ PiAKPj4+Pj4+IE9oLCBJIHdhcyB0aGlua2luZyB3ZSB3ZXJlIGRpc2N1c3Npbmcgd2l0aG91dCBs b2NraW5nIHJlZHVjZWQuIAo+Pj4+Pj4gWWVzLAo+Pj4+Pj4gSQo+Pj4+Pj4gYWxzbyBhZ3JlZSB0 aGVyZSBtaWdodCBiZSBhIGNhc2UgY2F1c2luZyBpbmZpbml0ZSBsb29wLiBXaXRoIAo+Pj4+Pj4g bG9ja2luZwo+Pj4+Pj4gcmVkdWNlZCwgdGhlIHRyZWUgY2FuIGJlIGFkanVzdGVkIGJldHdlZW4g bmV4dF90eHEoKSBhbmQKPj4+Pj4+IHJldHVybl90eHEoKQo+Pj4+Pj4gaW4KPj4+Pj4+IHRoZSBs b29wIHNpdHVhdGlvbi4gRm9yIGZ1cnRoZXIgZGlzY3Vzc2lvbiwgbGV0ICdzIGNvbnNpZGVyLAo+ Pj4+Pj4gMSkgdGhlIHRyZWUgc3RhcnRzIGxpa2U6Cj4+Pj4+PiAgICAgICAgIEEtPkItPkMtPkQt PkUKPj4+Pj4+IDIpIHRoZW4gbmV4dF90eHEoKSByZXR1cm5zIEEgZm9yIGRlcXVldWluZwo+Pj4+ Pj4gMykgZHJpdmVyIGRlcXVldWVzIEEgYW5kIGRyYWluZXMgQSB3aXRob3V0IGFueSBhY3RpdmUg dHhxIGxvY2tlZAo+Pj4+Pj4gbWVhbmluZwo+Pj4+Pj4gdGhlIHRyZWUgY291bGQgYmUgY2hhbmdl ZCB1cG9uIFR4IGNvbXBlbGV0aW9uLgo+Pj4+Pj4gNCkgdGhlbiBpbiByZXR1cm5fdHhxKCksIHRo ZSB0cmVlIGNvdWxkIGJlLAo+Pj4+Pj4gICAgICAgICBpICAgQS0+Qi0+Qy0+RC0+RSDvvIhBIGlz IGVtcHR5LCBhbmQgbWF5YmUgc29vbiBiZSBhZGRlZCAKPj4+Pj4+IGJhY2sKPj4+Pj4+IGJlZm9y ZSB0aGUgbG9vcCBlbmTvvIkKPj4+Pj4+ICAgICAgICAgaWkgIEItPkMtPkEtPkQtPkUg77yIQSBp cyBlbXB0eSwgYW5kIG1heWJlIHNvb24gYmUgYWRkZWQgCj4+Pj4+PiBiYWNrCj4+Pj4+PiBiZWZv cmUgdGhlIGxvb3AgZW5k77yJCj4+Pj4+PiAgICAgICAgIGlpaSBCLT5DLT5ELT5FLT5BIO+8iEEg aXMgZW1wdHksIGFuZCBtYXliZSBzb29uIGJlIGFkZGVkIAo+Pj4+Pj4gYmFjawo+Pj4+Pj4gYmVm b3JlIHRoZSBsb29wIGVuZCkKPj4+Pj4+IAo+Pj4+Pj4gd2l0aCB0aGlzIGNoYW5nZToKPj4+Pj4+ ICAgbG9jYWwtPnNjaGVkdWxlX3Bvc1thY10gPSByYl9uZXh0KG5vZGUpID86IHJiX3ByZXYobm9k ZSk7Cj4+Pj4+PiAKPj4+Pj4+IGZvciBjYXNlIGksIGxvY2FsLT5zY2hlZHVsZV9wb3NbYWNdIGlz IHJiX25leHQoQSkgd2hpY2ggaXMgQiwgYW5kIAo+Pj4+Pj4gaW4KPj4+Pj4+IG5leHRfdHhxKCks IHJiX25leHQoQikgaXMgd2hhdCB3ZSByZXR1cm5zIHdoaWNoIGFjdHVhbGx5IGlzIEMgYW5kIAo+ Pj4+Pj4gQgo+Pj4+Pj4gaXMKPj4+Pj4+IHNraXBwZWQsIG5vPwo+Pj4+Pj4gCj4+Pj4+PiBTaW1p bGlhciBmb3IgY2FzZSBpaSwgd2Ugc2tpcCBCLCBDLCBELgo+Pj4+PiAKPj4+Pj4gWXVwLCBJIHRo aW5rIHlvdSdyZSByaWdodC4gQnV0IGlmIHdlIGNhbiBmaXggdGhpcyBieSBtYWtpbmcKPj4+Pj4g aWVlZTgwMjExX3Jlc29ydF90eHEoKSBhd2FyZSBvZiB0aGUgc2NoZWR1bGVfcG9zIGFzIHdlbGws IG5vPyBJLmUuLAo+Pj4+PiBpZgo+Pj4+PiByZXNvcnRfdHhxKCkgYWN0cyBvbiB0aGUgdHhxIHRo YXQncyBjdXJyZW50bHkgaW4gc2NoZWR1bGVfcG9zLCBpdAo+Pj4+PiB3aWxsCj4+Pj4+IHVwZGF0 ZSBzY2hlZHVsZSBwb3Mgd2l0aCB0aGUgc2FtZSByYl9uZXh0KG5vZGUpID86IHJiX3ByZXYobm9k ZSk7Cj4+Pj4+IChvcHRpb25hbGx5IGFmdGVyIGNoZWNraW5nIHRoYXQgdGhlIHBvc2l0aW9uIG9m IHRoZSBub2RlIGlzIAo+Pj4+PiBhY3R1YWxseQo+Pj4+PiBnb2luZyB0byBjaGFuZ2UpLgo+Pj4+ IFNvcnJ5LCBwbGVhc2UgaWdvcmUgbGFzdCBlbWFpbCBzZW50IGJ5IG1pc3Rha2UuCj4+Pj4gCj4+ Pj4gSSBkb24ndCB0aGluayBpdCBtYWtlcyBhbnkgZGlmZmVyZW5jZSB3aXRoIHRoYXQgaW4gdW5z Y2hlZHVsZV90eHEoKS4KPj4+PiBGb3IKPj4+PiBjYXNlIGksIGl0IGZpbmFsbHkgcGlja3MgQyBh cyB3ZWxsIGluIG5leHRfdHhxKCkuIEZvciBuZXh0X3R4cSgpLAo+Pj4+IHNjaGVkdWxlX3BvcyBt ZWFucyBwcmV2aW91cyBjYW5kaWRhdGUgbm9kZSB3aGVyZWFzIHdpdGggeW91ciBjaGFuZ2UsCj4+ Pj4gaXQKPj4+PiBsb29rcyBsaWtlIHNjaGVkdWxlX3BvcyBpcyBjdXJyZW50IGNhbmRpZGF0ZSBu b2RlIGluc3RlYWQuCj4+PiAKPj4+IEhtbSwgdGhhdCB3YXMgbm90IGFjdHVhbGx5IHdoYXQgSSB3 YXMgdGhpbmtpbmcsIGJ1dCB5ZWFoIEkgdGhpbmsgCj4+PiB5b3UncmUKPj4+IHJpZ2h0IHRoYXQg aXQgd291bGQgYmUgZWFzaWVyIHRvIGp1c3QgY2hhbmdlIGl0IHNvIHNjaGVkdWxlX3BvcyBpcwo+ Pj4gcG9pbnRpbmcgdG8gdGhlIG5leHQgYW5kIG5vdCB0aGUgY3VycmVudCB0eHEgd2Ugd2FudCB0 byBzY2hlZHVsZS4KPj4gU28gZG8geW91IG1lYW4gd2UgY2FuIGNoYW5nZSBuZXh0X3R4cSBsaWtl IHRoaXMsCj4+IAo+PiAgIHN0cnVjdCBpZWVlODAyMTFfdHhxICppZWVlODAyMTFfbmV4dF90eHEo c3RydWN0IGllZWU4MDIxMV9odyAqaHcsIHU4Cj4+IGFjKQo+PiAgIHsKPj4gICAJc3RydWN0IGll ZWU4MDIxMV9sb2NhbCAqbG9jYWwgPSBod190b19sb2NhbChodyk7Cj4+IAlzdHJ1Y3QgcmJfbm9k ZSAqbm9kZSA9IGxvY2FsLT5zY2hlZHVsZV9wb3NbYWNdOwo+PiAgIAlzdHJ1Y3QgdHhxX2luZm8g KnR4cWkgPSBOVUxMOwo+PiAJYm9vbCBmaXJzdCA9IGZhbHNlOwo+PiAKPj4gICAJbG9ja2RlcF9h c3NlcnRfaGVsZCgmbG9jYWwtPmFjdGl2ZV90eHFfbG9ja1thY10pOwo+PiAKPj4gCWlmICghbm9k ZSkgewo+PiAJICAgICAgICBub2RlID0gcmJfZmlyc3RfY2FjaGVkKCZsb2NhbC0+YWN0aXZlX3R4 cXNbYWNdKTsKPj4gCQlmaXJzdCA9IHRydWU7Cj4+IC0JfSBlbHNlCj4+IC0JCW5vZGUgPSByYl9u ZXh0KG5vZGUpOwo+PiArICAgICAgIH0KPj4gKwo+PiAJaWYgKCFub2RlKQo+PiAgIAkJcmV0dXJu IE5VTEw7Cj4gCj4gQWgsIG5vLCBub3cgSSByZW1lbWJlciB3aHkgdGhpcyBkaWRuJ3Qgd29yayBh bmQgSSB3ZW50IHdpdGggdGhlIG90aGVyCj4gYXBwcm9hY2g6IElmIHlvdSBtYWtlIHRoaXMgY2hh bmdlLCB5b3UgYWxzbyBoYXZlIHRvIGhhdmUgdGhpcyBhdCB0aGUKPiBlbmQ6Cj4gCj4gbG9jYWwt PnNjaGVkdWxlX3Bvc1thY10gPSByYl9uZXh0KG5vZGUpOwo+IAo+IAo+IEJ1dCB0aGlzIG1lYW5z IHdlIGNhbiBubyBsb25nZXIgZGlzdGluZ3Vpc2ggYmV0d2VlbiBoYXZpbmcgZ29uZSB0aHJvdWdo Cj4gdGhlIHdob2xlIHRoaW5nIChzbyByYl9uZXh0KCkgcmV0dXJucyBOVUxMKSwgb3Igc3RhcnRp bmcgb3V0IHdpdGgKPiBub3RoaW5nLgo+IAo+IFNvLCBpbnN0ZWFkIHdlIG5lZWQgdG8ga2VlcCBu ZXh0X3R4cSgpIHRoZSB3YXkgaXQgaXMsIGFuZCBqdXN0IGFkZAoKUmlnaHQsIHNob3VsZCBrZWVw IG5leHRfdHhxKCkgdGhlIHdheSBpdCBpcy4KCj4gCj4gbG9jYWwtPnNjaGVkdWxlX3Bvc1thY10g PSByYl9wcmV2KG5vZGUpOwo+IAo+IHdoZW5ldmVyIHdlIHJlbW92ZSBhIG5vZGUgKGJvdGggaW4g cmV0dXJuX3R4cSgpIGFuZCByZXNvcnRfdHhxKCkpLgoKQWdyZWUsIGFuZCBhbHNvIHdlIG1heSBu ZWVkIHRvIGNvbnNpZGVyIGNhc2UgbGlrZSBBIGlzIHJlbW92ZWQgYW5kIHNvb24gCmJlIGFkZGVk IGJhY2sganVzdCB0aGUgc2FtZSBhcyBpaSksCiAgICAgICAgQi0+Qy0+QS0+RC0+RQp0aGVuIEIg aXMgc2NoZWR1bGUsIHJlbW92ZWQgYW5kIHNvb24gYWRkZWQgYmFjaywKICAgICAgICBDLT5BLT5C LT5ELT5FCkEgYW5kIEIgd2lsbCBoYXZlIGEgc2Vjb25kIGNoYW5jZSB0byBiZSBzY2hlZHVsZWQg YW5kIHRoaXMgbWF5IGhhcHBlbiB0byAKb3RoZXJzIGFzIHdlbGwgbGVhZGluZyB0byB0aGUgaW5m aW5pdGUgbG9vcCBhcyB5b3UgaGF2ZSBtZW50aW9uZWQgCnByZXZpb3VzbHksIHNvIGRvIHdlIG5l ZWQgdG8gbWFpbnRhaW4gYSBzY2hlZHVsZV9yb3VuZCBsaWtlIHdlIGRvIGluIApEUlI/IExpa2Us CiAgICAgLSBJZiB0aGUgbm9kZSBpcyBpbiB0aGUgc2FtZSByb3VuZCwgYnkgcGFzcyBzY2hlZHVs ZSwgZ28gdG8gCnJiX25leHQoKSwgZWl0aGVyIGNvbnRpbnVlIGxvb3AgdGhpcyByb3VuZCBvciBl bmQgdGhpcyByb3VuZC4KICAgICAtIEluY3JlYXNlIHRoZSBzY2hlZHVsZV9yb3VuZCBhdCB0aGUg c2NoZWR1bGVfc3RhcnQoKSBvbmx5IHdoZW4gdGhlIApzY2hlZHVsZV9wb3MgaXMgTlVMTC4KCj4g Cj4+PiAKPj4+IFdlJ2Qgc3RpbGwgbmVlZCBhIGNoZWNrIGluIHJlc29ydF90eHEoKSB0aGVuLCBi dXQgaXQgd291bGQgbWFrZSBpdCAKPj4+IHNhZmUKPj4+IHRvIHVuc2NoZWR1bGUgaW4gcmV0dXJu X3R4cSgpLi4uCj4+IFllcywgYWdyZWUgd2l0aCB0aGF0Lgo+PiAKPj4gCj4+PiAKPj4+Pj4+IEFs c28gSSBhbSB3b25kZXJpbmcgaWYgdGhlcmUgd2lsbCBiZSBzb21lIFNNUCBpc3N1ZXMgcmVsYXRp bmcgd2l0aAo+Pj4+Pj4gbG9jYWwtPnNjaGVkdWxlX3Bvc1thY10uCj4+Pj4+IAo+Pj4+PiBOb3Qg c3VyZSB3aGF0IHlvdSBtZWFuIGJ5IHRoaXM/Cj4+Pj4gTXkgYmFkLiBQbGVhc2UgaWdub3JlIHRo aXMuCj4+Pj4gCj4+Pj4gCj4+Pj4+IAo+Pj4+Pj4+PiBJbiBhdGgxMGssIHdlIHdpbGwgdXN1YWxs eSBwdXNoIHBhY2tldHMgb2YgZmlyc3QgdHhxIGFzIG1hbnkgYXMgCj4+Pj4+Pj4+IHdlCj4+Pj4+ Pj4+IGNhbgo+Pj4+Pj4+PiB1bnRpbCBpdCBpcyBkcmFpbmVkIGFuZCB0aGVuIG1vdmUgdG8gdGhl IG5leHQgb25lLiBTbyBpZiBhIHR4cQo+Pj4+Pj4+PiBnZXRzCj4+Pj4+Pj4+IHJlbW92ZWQgaW4g dGhlIHJldHVybl90eHEsIGl0IHNob3VsZCBhbHdheXMgYmUgdGhlIGxlZnRtb3N0LiBBbmQKPj4+ Pj4+Pj4gZHVyaW5nIHRoaXMgcGVyaW9kLCBuZWl0aGVyIHZ0IG9mIGFueSBzdGF0aW9uIG9yIGds b2JhbCB2dCBjYW4gCj4+Pj4+Pj4+IGJlCj4+Pj4+Pj4+IHVwZGF0ZWQgZHVlIHRvIGxvY2sgcHJv dGVjdGlvbi4KPj4+Pj4+Pj4gCj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+IEJ1dCBpbiB0aGF0IGNhc2Us IHdlIGNvdWxkIGZpeCBpdCBieSBqdXN0IGNvbmRpdGlvbmFsbHkgCj4+Pj4+Pj4+PiBhc3NpZ25p bmcKPj4+Pj4+Pj4+IGVpdGhlcgo+Pj4+Pj4+Pj4gcmJfbmV4dCBvciByYl9wcmV2IHRvIHRoZSBz Y2hlZHVsZV9wb3MgaW4gdW5zY2hlZHVsZV90eHEoKT8gCj4+Pj4+Pj4+PiBJLmUuLAo+Pj4+Pj4+ Pj4gc29tZXRoaW5nIGxpa2U6Cj4+Pj4+Pj4+PiAKPj4+Pj4+Pj4+IGxvY2FsLT5zY2hlZHVsZV9w b3NbYWNdID0gcmJfbmV4dChub2RlKSA/OiByYl9wcmV2KG5vZGUpOwo+Pj4+Pj4+PiBJIGFtIG5v dCBzdXJlIEkgYW0gZ2V0dGluZyB5b3VyIHBvaW50LiBTdGlsbCBpbiBuZXh0X3R4cSwKPj4+Pj4+ Pj4gc2NoZWR1bGVfcG9zW2FjXSB3aWxsIGxlYWQgdXMgdG8gdGhlIG5leHQgbm9kZSBvZiB0aGUg b25lIHdlIAo+Pj4+Pj4+PiB3YW50Lgo+Pj4+Pj4+IAo+Pj4+Pj4+IFRoZSBsb2dpYyBpbiBuZXh0 X3R4cSBpcyBkaWZmZXJlbnQgd2hlbiBzY2hlZHVsZV9wb3NbYWNdIGlzIE5VTEwsCj4+Pj4+Pj4g dnMKPj4+Pj4+PiB3aGVuIHJiX25leHQoc2NoZWR1bGVfcG9zW2FjXSkgaXMgTlVMTC4gVGhlIGZv cm1lciByZXN0YXJ0cyBhIG5ldwo+Pj4+Pj4+IHNjaGVkdWxpbmcgcm91bmQsIHdoaWxlIHRoZSBs YXR0ZXIgZW5kcyB0aGUgY3VycmVudCByb3VuZC4KPj4+Pj4+PiAKPj4+Pj4+PiAtVG9rZQo+Pj4+ Pj4gCj4+Pj4+PiAtLQo+Pj4+Pj4gWWlibwo+Pj4+IAo+Pj4+IC0tCj4+Pj4gWWlibwo+PiAKPj4g LS0KPj4gWWlibwoKLS0gCllpYm8KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fCmF0aDEwayBtYWlsaW5nIGxpc3QKYXRoMTBrQGxpc3RzLmluZnJhZGVhZC5v cmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9hdGgxMGsK From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C3ACC3A5A2 for ; Sun, 22 Sep 2019 05:22:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 389B020830 for ; Sun, 22 Sep 2019 05:22:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="dgo8lGwL"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="b/bTq2v2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726495AbfIVFTt (ORCPT ); Sun, 22 Sep 2019 01:19:49 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:51954 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725829AbfIVFTt (ORCPT ); Sun, 22 Sep 2019 01:19:49 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 7ABE8611FA; Sun, 22 Sep 2019 05:19:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1569129586; bh=jvsfzcjb1o+zxlPLJYU2hoMjSOsTUXKiOHw3VBPXGws=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=dgo8lGwLyRXm61sQ1bCVXzRFN0cWUFnaN9fG/HnGMq2i24YiolgbTZgbu7LVZXKv8 qptqdwk5xeo2BJB1Y3cNQyCmuatK282gEcCUgisqIQbGIExgmFUKZGF+utYxErIOkA E+F0S3ZZjllv4Bk+YS4yHRnb8ords239DAkF4X34= Received: from mail.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id B065960740; Sun, 22 Sep 2019 05:19:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1569129583; bh=jvsfzcjb1o+zxlPLJYU2hoMjSOsTUXKiOHw3VBPXGws=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=b/bTq2v2ByhBTC0UanSGNs1vdtvf0x5WoIXBg/3cUQhetGF7xUp51hx6HMZSoSNaR bl+ubZiexyZRBVUJab+V6FN70P0H/DhD32hxLASRflQblW2lRsI/HRRa2pv/YXXGH3 lMkYVxxz9n9KBViu0os6FzRNVwBlxGQfo4yHL1ds= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Date: Sun, 22 Sep 2019 13:19:43 +0800 From: Yibo Zhao To: =?UTF-8?Q?Toke_H=C3=B8iland-J=C3=B8rgensen?= Cc: ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, linux-wireless-owner@vger.kernel.org Subject: Re: [PATCH 2/4] mac80211: defer txqs removal from rbtree In-Reply-To: <874l157nrt.fsf@toke.dk> References: <1568639388-27291-1-git-send-email-yiboz@codeaurora.org> <1568639388-27291-2-git-send-email-yiboz@codeaurora.org> <87pnjyiq7o.fsf@toke.dk> <87sgothmpy.fsf@toke.dk> <8cdece5c030fd95817fb099021c38613@codeaurora.org> <87tv98fu6l.fsf@toke.dk> <1b4ab006d9b5c88035845aaac193ef48@codeaurora.org> <8736gre3bm.fsf@toke.dk> <198124204167325252fcfcd65e3f2733@codeaurora.org> <87ftkp7uuz.fsf@toke.dk> <4574cce4079f8dab2b2bf223431a6eae@codeaurora.org> <877e617qg2.fsf@toke.dk> <910d9bb5f9016b29fb2aaeb0b89bac38@codeaurora.org> <874l157nrt.fsf@toke.dk> Message-ID: <2935b00bf3e29ad8b2738fe98dc24a76@codeaurora.org> X-Sender: yiboz@codeaurora.org User-Agent: Roundcube Webmail/1.2.5 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org On 2019-09-21 22:00, Toke Høiland-Jørgensen wrote: > Yibo Zhao writes: > >> On 2019-09-21 21:02, Toke Høiland-Jørgensen wrote: >>> Yibo Zhao writes: >>> >>>> On 2019-09-21 19:27, Toke Høiland-Jørgensen wrote: >>>>> Yibo Zhao writes: >>>>> >>>>>> On 2019-09-20 17:15, Toke Høiland-Jørgensen wrote: >>>>>>> Yibo Zhao writes: >>>>>>> >>>>>>>> On 2019-09-19 18:37, Toke Høiland-Jørgensen wrote: >>>>>>>>> Yibo Zhao writes: >>>>>>>>> >>>>>>>>>> On 2019-09-18 19:23, Toke Høiland-Jørgensen wrote: >>>>>>>>>>> Yibo Zhao writes: >>>>>>>>>>> >>>>>>>>>>>> On 2019-09-18 05:10, Toke Høiland-Jørgensen wrote: >>>>>>>>>>>>> Yibo Zhao writes: >>>>>>>>>>>>> >>>>>>>>>>>>>> In a loop txqs dequeue scenario, if the first txq in the >>>>>>>>>>>>>> rbtree >>>>>>>>>>>>>> gets >>>>>>>>>>>>>> removed from rbtree immediately in the >>>>>>>>>>>>>> ieee80211_return_txq(), >>>>>>>>>>>>>> the >>>>>>>>>>>>>> loop will break soon in the ieee80211_next_txq() due to >>>>>>>>>>>>>> schedule_pos >>>>>>>>>>>>>> not leading to the second txq in the rbtree. Thus, >>>>>>>>>>>>>> defering >>>>>>>>>>>>>> the >>>>>>>>>>>>>> removal right before the end of this schedule round. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Co-developed-by: Yibo Zhao >>>>>>>>>>>>>> Signed-off-by: Yibo Zhao >>>>>>>>>>>>>> Signed-off-by: Toke Høiland-Jørgensen >>>>>>>>>>>>> >>>>>>>>>>>>> I didn't write this patch, so please don't use my sign-off. >>>>>>>>>>>>> I'll >>>>>>>>>>>>> add >>>>>>>>>>>>> ack or review tags as appropriate in reply; but a few >>>>>>>>>>>>> comments >>>>>>>>>>>>> first: >>>>>>>>>>>>> >>>>>>>>>>>>>> --- >>>>>>>>>>>>>> include/net/mac80211.h | 16 ++++++++++-- >>>>>>>>>>>>>> net/mac80211/ieee80211_i.h | 3 +++ >>>>>>>>>>>>>> net/mac80211/main.c | 6 +++++ >>>>>>>>>>>>>> net/mac80211/tx.c | 63 >>>>>>>>>>>>>> +++++++++++++++++++++++++++++++++++++++++++--- >>>>>>>>>>>>>> 4 files changed, 83 insertions(+), 5 deletions(-) >>>>>>>>>>>>>> >>>>>>>>>>>>>> diff --git a/include/net/mac80211.h >>>>>>>>>>>>>> b/include/net/mac80211.h >>>>>>>>>>>>>> index ac2ed8e..ba5a345 100644 >>>>>>>>>>>>>> --- a/include/net/mac80211.h >>>>>>>>>>>>>> +++ b/include/net/mac80211.h >>>>>>>>>>>>>> @@ -925,6 +925,8 @@ struct ieee80211_tx_rate { >>>>>>>>>>>>>> >>>>>>>>>>>>>> #define IEEE80211_MAX_TX_RETRY 31 >>>>>>>>>>>>>> >>>>>>>>>>>>>> +#define IEEE80211_AIRTIME_TXQ_RM_CHK_INTV_IN_MS 100 >>>>>>>>>>>>>> + >>>>>>>>>>>>>> static inline void ieee80211_rate_set_vht(struct >>>>>>>>>>>>>> ieee80211_tx_rate >>>>>>>>>>>>>> *rate, >>>>>>>>>>>>>> u8 mcs, u8 nss) >>>>>>>>>>>>>> { >>>>>>>>>>>>>> @@ -6232,7 +6234,8 @@ struct sk_buff >>>>>>>>>>>>>> *ieee80211_tx_dequeue(struct >>>>>>>>>>>>>> ieee80211_hw *hw, >>>>>>>>>>>>>> * @ac: AC number to return packets from. >>>>>>>>>>>>>> * >>>>>>>>>>>>>> * Should only be called between calls to >>>>>>>>>>>>>> ieee80211_txq_schedule_start() >>>>>>>>>>>>>> - * and ieee80211_txq_schedule_end(). >>>>>>>>>>>>>> + * and ieee80211_txq_schedule_end(). If the txq is empty, >>>>>>>>>>>>>> it >>>>>>>>>>>>>> will >>>>>>>>>>>>>> be >>>>>>>>>>>>>> added >>>>>>>>>>>>>> + * to a remove list and get removed later. >>>>>>>>>>>>>> * Returns the next txq if successful, %NULL if no queue >>>>>>>>>>>>>> is >>>>>>>>>>>>>> eligible. >>>>>>>>>>>>>> If a txq >>>>>>>>>>>>>> * is returned, it should be returned with >>>>>>>>>>>>>> ieee80211_return_txq() >>>>>>>>>>>>>> after the >>>>>>>>>>>>>> * driver has finished scheduling it. >>>>>>>>>>>>>> @@ -6268,7 +6271,8 @@ void >>>>>>>>>>>>>> ieee80211_txq_schedule_start(struct >>>>>>>>>>>>>> ieee80211_hw *hw, u8 ac) >>>>>>>>>>>>>> * @hw: pointer as obtained from ieee80211_alloc_hw() >>>>>>>>>>>>>> * @ac: AC number to acquire locks for >>>>>>>>>>>>>> * >>>>>>>>>>>>>> - * Release locks previously acquired by >>>>>>>>>>>>>> ieee80211_txq_schedule_end(). >>>>>>>>>>>>>> + * Release locks previously acquired by >>>>>>>>>>>>>> ieee80211_txq_schedule_end(). >>>>>>>>>>>>>> Check >>>>>>>>>>>>>> + * and remove the empty txq from rb-tree. >>>>>>>>>>>>>> */ >>>>>>>>>>>>>> void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, >>>>>>>>>>>>>> u8 >>>>>>>>>>>>>> ac) >>>>>>>>>>>>>> __releases(txq_lock); >>>>>>>>>>>>>> @@ -6287,6 +6291,14 @@ void ieee80211_schedule_txq(struct >>>>>>>>>>>>>> ieee80211_hw >>>>>>>>>>>>>> *hw, struct ieee80211_txq *txq) >>>>>>>>>>>>>> __acquires(txq_lock) __releases(txq_lock); >>>>>>>>>>>>>> >>>>>>>>>>>>>> /** >>>>>>>>>>>>>> + * ieee80211_txqs_check - Check txqs waiting for removal >>>>>>>>>>>>>> + * >>>>>>>>>>>>>> + * @tmr: pointer as obtained from local >>>>>>>>>>>>>> + * >>>>>>>>>>>>>> + */ >>>>>>>>>>>>>> +void ieee80211_txqs_check(struct timer_list *tmr); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> +/** >>>>>>>>>>>>>> * ieee80211_txq_may_transmit - check whether TXQ is >>>>>>>>>>>>>> allowed >>>>>>>>>>>>>> to >>>>>>>>>>>>>> transmit >>>>>>>>>>>>>> * >>>>>>>>>>>>>> * This function is used to check whether given txq is >>>>>>>>>>>>>> allowed >>>>>>>>>>>>>> to >>>>>>>>>>>>>> transmit by >>>>>>>>>>>>>> diff --git a/net/mac80211/ieee80211_i.h >>>>>>>>>>>>>> b/net/mac80211/ieee80211_i.h >>>>>>>>>>>>>> index a4556f9..49aa143e 100644 >>>>>>>>>>>>>> --- a/net/mac80211/ieee80211_i.h >>>>>>>>>>>>>> +++ b/net/mac80211/ieee80211_i.h >>>>>>>>>>>>>> @@ -847,6 +847,7 @@ struct txq_info { >>>>>>>>>>>>>> struct codel_stats cstats; >>>>>>>>>>>>>> struct sk_buff_head frags; >>>>>>>>>>>>>> struct rb_node schedule_order; >>>>>>>>>>>>>> + struct list_head candidate; >>>>>>>>>>>>>> unsigned long flags; >>>>>>>>>>>>>> >>>>>>>>>>>>>> /* keep last! */ >>>>>>>>>>>>>> @@ -1145,6 +1146,8 @@ struct ieee80211_local { >>>>>>>>>>>>>> u64 airtime_v_t[IEEE80211_NUM_ACS]; >>>>>>>>>>>>>> u64 airtime_weight_sum[IEEE80211_NUM_ACS]; >>>>>>>>>>>>>> >>>>>>>>>>>>>> + struct list_head remove_list[IEEE80211_NUM_ACS]; >>>>>>>>>>>>>> + struct timer_list remove_timer; >>>>>>>>>>>>>> u16 airtime_flags; >>>>>>>>>>>>>> >>>>>>>>>>>>>> const struct ieee80211_ops *ops; >>>>>>>>>>>>>> diff --git a/net/mac80211/main.c b/net/mac80211/main.c >>>>>>>>>>>>>> index e9ffa8e..78fe24a 100644 >>>>>>>>>>>>>> --- a/net/mac80211/main.c >>>>>>>>>>>>>> +++ b/net/mac80211/main.c >>>>>>>>>>>>>> @@ -667,10 +667,15 @@ struct ieee80211_hw >>>>>>>>>>>>>> *ieee80211_alloc_hw_nm(size_t priv_data_len, >>>>>>>>>>>>>> >>>>>>>>>>>>>> for (i = 0; i < IEEE80211_NUM_ACS; i++) { >>>>>>>>>>>>>> local->active_txqs[i] = RB_ROOT_CACHED; >>>>>>>>>>>>>> + INIT_LIST_HEAD(&local->remove_list[i]); >>>>>>>>>>>>>> spin_lock_init(&local->active_txq_lock[i]); >>>>>>>>>>>>>> } >>>>>>>>>>>>>> local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX; >>>>>>>>>>>>>> >>>>>>>>>>>>>> + timer_setup(&local->remove_timer, ieee80211_txqs_check, >>>>>>>>>>>>>> 0); >>>>>>>>>>>>>> + mod_timer(&local->remove_timer, >>>>>>>>>>>>>> + jiffies + >>>>>>>>>>>>>> msecs_to_jiffies(IEEE80211_AIRTIME_TXQ_RM_CHK_INTV_IN_MS)); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> INIT_LIST_HEAD(&local->chanctx_list); >>>>>>>>>>>>>> mutex_init(&local->chanctx_mtx); >>>>>>>>>>>>>> >>>>>>>>>>>>>> @@ -1305,6 +1310,7 @@ void ieee80211_unregister_hw(struct >>>>>>>>>>>>>> ieee80211_hw >>>>>>>>>>>>>> *hw) >>>>>>>>>>>>>> tasklet_kill(&local->tx_pending_tasklet); >>>>>>>>>>>>>> tasklet_kill(&local->tasklet); >>>>>>>>>>>>>> >>>>>>>>>>>>>> + del_timer_sync(&local->remove_timer); >>>>>>>>>>>>>> #ifdef CONFIG_INET >>>>>>>>>>>>>> unregister_inetaddr_notifier(&local->ifa_notifier); >>>>>>>>>>>>>> #endif >>>>>>>>>>>>>> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c >>>>>>>>>>>>>> index d00baaa..42ca010 100644 >>>>>>>>>>>>>> --- a/net/mac80211/tx.c >>>>>>>>>>>>>> +++ b/net/mac80211/tx.c >>>>>>>>>>>>>> @@ -1450,6 +1450,7 @@ void ieee80211_txq_init(struct >>>>>>>>>>>>>> ieee80211_sub_if_data *sdata, >>>>>>>>>>>>>> codel_stats_init(&txqi->cstats); >>>>>>>>>>>>>> __skb_queue_head_init(&txqi->frags); >>>>>>>>>>>>>> RB_CLEAR_NODE(&txqi->schedule_order); >>>>>>>>>>>>>> + INIT_LIST_HEAD(&txqi->candidate); >>>>>>>>>>>>>> >>>>>>>>>>>>>> txqi->txq.vif = &sdata->vif; >>>>>>>>>>>>>> >>>>>>>>>>>>>> @@ -3724,6 +3725,9 @@ void ieee80211_schedule_txq(struct >>>>>>>>>>>>>> ieee80211_hw >>>>>>>>>>>>>> *hw, >>>>>>>>>>>>>> >>>>>>>>>>>>>> spin_lock_bh(&local->active_txq_lock[ac]); >>>>>>>>>>>>>> >>>>>>>>>>>>>> + if (!list_empty(&txqi->candidate)) >>>>>>>>>>>>>> + list_del_init(&txqi->candidate); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> if (!RB_EMPTY_NODE(&txqi->schedule_order)) >>>>>>>>>>>>>> goto out; >>>>>>>>>>>>>> >>>>>>>>>>>>>> @@ -3783,6 +3787,20 @@ static void >>>>>>>>>>>>>> __ieee80211_unschedule_txq(struct >>>>>>>>>>>>>> ieee80211_hw *hw, >>>>>>>>>>>>>> RB_CLEAR_NODE(&txqi->schedule_order); >>>>>>>>>>>>>> } >>>>>>>>>>>>>> >>>>>>>>>>>>>> +void ieee80211_remove_txq(struct ieee80211_hw *hw, >>>>>>>>>>>>>> + struct ieee80211_txq *txq) >>>>>>>>>>>>>> +{ >>>>>>>>>>>>>> + struct ieee80211_local *local = hw_to_local(hw); >>>>>>>>>>>>>> + struct txq_info *txqi = to_txq_info(txq); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + lockdep_assert_held(&local->active_txq_lock[txq->ac]); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + if (!RB_EMPTY_NODE(&txqi->schedule_order)) { >>>>>>>>>>>>>> + __ieee80211_unschedule_txq(hw, txq); >>>>>>>>>>>>>> + list_del_init(&txqi->candidate); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> +} >>>>>>>>>>>>>> + >>>>>>>>>>>>>> void ieee80211_unschedule_txq(struct ieee80211_hw *hw, >>>>>>>>>>>>>> struct ieee80211_txq *txq) >>>>>>>>>>>>>> __acquires(txq_lock) __releases(txq_lock) >>>>>>>>>>>>>> @@ -3790,7 +3808,7 @@ void ieee80211_unschedule_txq(struct >>>>>>>>>>>>>> ieee80211_hw *hw, >>>>>>>>>>>>>> struct ieee80211_local *local = hw_to_local(hw); >>>>>>>>>>>>>> >>>>>>>>>>>>>> spin_lock_bh(&local->active_txq_lock[txq->ac]); >>>>>>>>>>>>>> - __ieee80211_unschedule_txq(hw, txq); >>>>>>>>>>>>>> + ieee80211_remove_txq(hw, txq); >>>>>>>>>>>>>> spin_unlock_bh(&local->active_txq_lock[txq->ac]); >>>>>>>>>>>>>> } >>>>>>>>>>>>>> >>>>>>>>>>>>>> @@ -3803,11 +3821,48 @@ void ieee80211_return_txq(struct >>>>>>>>>>>>>> ieee80211_hw >>>>>>>>>>>>>> *hw, >>>>>>>>>>>>>> lockdep_assert_held(&local->active_txq_lock[txq->ac]); >>>>>>>>>>>>>> >>>>>>>>>>>>>> if (!RB_EMPTY_NODE(&txqi->schedule_order) && >>>>>>>>>>>>>> - (skb_queue_empty(&txqi->frags) && >>>>>>>>>>>>>> !txqi->tin.backlog_packets)) >>>>>>>>>>>>>> - __ieee80211_unschedule_txq(hw, txq); >>>>>>>>>>>>>> + !txq_has_queue(&txqi->txq) && >>>>>>>>>>>>>> + list_empty(&txqi->candidate)) >>>>>>>>>>>>>> + list_add_tail(&txqi->candidate, >>>>>>>>>>>>>> &local->remove_list[txq->ac]); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> } >>>>>>>>>>>>>> EXPORT_SYMBOL(ieee80211_return_txq); >>>>>>>>>>>>>> >>>>>>>>>>>>>> +void __ieee80211_check_txqs(struct ieee80211_local >>>>>>>>>>>>>> *local, >>>>>>>>>>>>>> int >>>>>>>>>>>>>> ac) >>>>>>>>>>>>>> +{ >>>>>>>>>>>>>> + struct txq_info *iter, *tmp; >>>>>>>>>>>>>> + struct sta_info *sta; >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + lockdep_assert_held(&local->active_txq_lock[ac]); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + list_for_each_entry_safe(iter, tmp, >>>>>>>>>>>>>> &local->remove_list[ac], >>>>>>>>>>>>>> + candidate) { >>>>>>>>>>>>>> + sta = container_of(iter->txq.sta, struct sta_info, >>>>>>>>>>>>>> sta); >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + if (txq_has_queue(&iter->txq)) >>>>>>>>>>>>>> + list_del_init(&iter->candidate); >>>>>>>>>>>>>> + else >>>>>>>>>>>>>> + ieee80211_remove_txq(&local->hw, &iter->txq); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> +} >>>>>>>>>>>>>> + >>>>>>>>>>>>>> +void ieee80211_txqs_check(struct timer_list *t) >>>>>>>>>>>>>> +{ >>>>>>>>>>>>>> + struct ieee80211_local *local = from_timer(local, t, >>>>>>>>>>>>>> remove_timer); >>>>>>>>>>>>>> + struct txq_info *iter, *tmp; >>>>>>>>>>>>>> + struct sta_info *sta; >>>>>>>>>>>>>> + int ac; >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { >>>>>>>>>>>>>> + spin_lock_bh(&local->active_txq_lock[ac]); >>>>>>>>>>>>>> + __ieee80211_check_txqs(local, ac); >>>>>>>>>>>>>> + spin_unlock_bh(&local->active_txq_lock[ac]); >>>>>>>>>>>>>> + } >>>>>>>>>>>>>> + >>>>>>>>>>>>>> + mod_timer(&local->remove_timer, >>>>>>>>>>>>>> + jiffies + >>>>>>>>>>>>>> msecs_to_jiffies(IEEE80211_AIRTIME_TXQ_RM_CHK_INTV_IN_MS)); >>>>>>>>>>>>>> +} >>>>>>>>>>>>> >>>>>>>>>>>>> I'll ask the same as I did last time (where you told me to >>>>>>>>>>>>> hold >>>>>>>>>>>>> off >>>>>>>>>>>>> until this round): >>>>>>>>>>>>> >>>>>>>>>>>>> Why do you need the timer and the periodic check? If TXQs >>>>>>>>>>>>> are >>>>>>>>>>>>> added >>>>>>>>>>>>> to >>>>>>>>>>>>> the remove list during the scheduling run, and >>>>>>>>>>>>> __ieee80211_check_txqs() >>>>>>>>>>>>> is run from schedule_end(), isn't that sufficient to clear >>>>>>>>>>>>> the >>>>>>>>>>>>> list? >>>>>>>>>>>> Is it possible that a txq is not added to the remove list >>>>>>>>>>>> but >>>>>>>>>>>> then >>>>>>>>>>>> packets in it are dropped by fq_codel algo? Like the station >>>>>>>>>>>> disconnects >>>>>>>>>>>> without any notification. >>>>>>>>>>> >>>>>>>>>>> Well as long as all the other cleanup paths call directly >>>>>>>>>>> into >>>>>>>>>>> __unschedule_txq(), that should remove stations from the >>>>>>>>>>> scheduler >>>>>>>>>>> when >>>>>>>>>>> they disconnect etc. >>>>>>>>>> Yes, the disconnect scenario is a bad example. My concern is, >>>>>>>>>> say, >>>>>>>>>> we >>>>>>>>>> have 10 stations and only one of them is assigned a very small >>>>>>>>>> weight >>>>>>>>>> compared with that of others. Suppose, after its chance of Tx, >>>>>>>>>> it >>>>>>>>>> is >>>>>>>>>> most likely to be placed in the rightmost(still has some >>>>>>>>>> packets >>>>>>>>>> in >>>>>>>>>> the >>>>>>>>>> txq) and no more incoming data for it. The remaining packets >>>>>>>>>> in >>>>>>>>>> txq >>>>>>>>>> will >>>>>>>>>> be dropped due to timeout algo in codel(correct me if I am >>>>>>>>>> wrong) >>>>>>>>>> but >>>>>>>>>> this empty txq will stay on the rbtree until other txqs get >>>>>>>>>> drained >>>>>>>>>> or >>>>>>>>>> global vt catch up with its vt. The staying time could be long >>>>>>>>>> if >>>>>>>>>> weight >>>>>>>>>> is extremely small. Then do we need timer to check or any >>>>>>>>>> other >>>>>>>>>> better >>>>>>>>>> solution? >>>>>>>>> >>>>>>>>> Ah, I see what you mean. No, I don't think this will be a >>>>>>>>> problem; >>>>>>>>> the >>>>>>>>> scenario you're describing would play out like this: >>>>>>>>> >>>>>>>>> 1. Station ends transmitting, still has a single packet queued, >>>>>>>>> gets >>>>>>>>> moved to the end of the rbtree (and stays there for a >>>>>>>>> while). >>>>>>>>> >>>>>>>>> 2. When we finally get to the point where this station gets >>>>>>>>> another >>>>>>>>> chance to transmit, the CoDel drop timer triggers and the >>>>>>>>> last >>>>>>>>> packet >>>>>>>>> is dropped[0]. This means that the queue will just be empty >>>>>>>>> (and ieee80211_tx_dequeue() will return NULL). >>>>>>>>> >>>>>>>>> 3. Because the queue is empty, ieee80211_return_txq() will not >>>>>>>>> put >>>>>>>>> it >>>>>>>>> back on the rbtree. >>>>>>>>> >>>>>>>>> Crucially, in 2. the CoDel algorithm doesn't kick in until the >>>>>>>>> point >>>>>>>>> of >>>>>>>>> packet dequeue. But even if an empty queue stays on the rbtree >>>>>>>>> for >>>>>>>>> a >>>>>>>>> while, there is no harm in that: eventually it will get its >>>>>>>>> turn, >>>>>>>>> it >>>>>>>>> will turn out to be empty, and just be skipped over. >>>>>>>> Then that will be fine. Thanks for the explanation of the >>>>>>>> dropping >>>>>>>> part >>>>>>>> in CoDel algorithm. >>>>>>> >>>>>>> Yup, think so. And you're welcome :) >>>>>>> >>>>>>>>> The issue we need to be concerned about is the opposite: If we >>>>>>>>> have >>>>>>>>> a >>>>>>>>> queue that *does* have packets queued, but which is *not* >>>>>>>>> scheduled >>>>>>>>> for >>>>>>>>> transmission, that will stall TX. >>>>>>>> Is it by design since its vt is more than global vt, right? The >>>>>>>> lattency >>>>>>>> may somehow get impacted though. >>>>>>> >>>>>>> Well, it should still stay on the rbtree as long as it has >>>>>>> packets >>>>>>> queued. We don't have a check anywhere that reschedules TXQs >>>>>>> whose >>>>>>> v_t >>>>>>> drops below global v_t... >>>>>>> >>>>>>>>> [0] CoDel in most cases only drops a single packet at a time, >>>>>>>>> so >>>>>>>>> it >>>>>>>>> will >>>>>>>>> not clear out an entire queue with multiple packets in one go. >>>>>>>>> But >>>>>>>>> you >>>>>>>>> are right that it could conceivably drop the last packet in a >>>>>>>>> queue. >>>>>>>>> >>>>>>>>>>> We only need to defer removal inside a single "scheduling >>>>>>>>>>> round" >>>>>>>>>>> (i.e., >>>>>>>>>>> between a pair of ieee80211_txq_schedule_start/end. So if we >>>>>>>>>>> just >>>>>>>>>>> walk >>>>>>>>>>> the remove list in schedule_end() we should be enough, no? >>>>>>>>>>> >>>>>>>>>>> Hmm, or maybe a simpler way to fix the original issue is just >>>>>>>>>>> to >>>>>>>>>>> have >>>>>>>>>>> unschedule_txq() update the schedule_pos() pointer? >>>>>>>>>>> >>>>>>>>>>> I.e., unschedule_txq checks if the txq being removed is >>>>>>>>>>> currently >>>>>>>>>>> being >>>>>>>>>>> pointed to by schedule_pos[ac], and if it is, it updates >>>>>>>>>>> schedule_pos >>>>>>>>>>> to >>>>>>>>>>> be the rb_next of the current value? >>>>>>>>>> Actually, if schedule_pos is updated to rb_next of the current >>>>>>>>>> value, >>>>>>>>>> then in the next_txq() where we are going to use rb_next again >>>>>>>>>> and >>>>>>>>>> finally pick the next node of the node we really want. Is it >>>>>>>>>> fine >>>>>>>>>> to >>>>>>>>>> update schedule_pos to NULL? >>>>>>>>> >>>>>>>>> Hmm, yeah, good point. >>>>>>>>> >>>>>>>>> If we do end up setting schedule_pos to NULL in the middle of a >>>>>>>>> scheduling round, that will make next_txq() "start over", and >>>>>>>>> do >>>>>>>>> another >>>>>>>>> loop through the whole thing. I guess we may be able hit a case >>>>>>>>> where >>>>>>>>> things can oscillate back and forth between addition and >>>>>>>>> removal >>>>>>>>> resulting in an infinite loop? Not sure, but at least I can't >>>>>>>>> seem >>>>>>>>> to >>>>>>>>> convince myself that this can't happen. >>>>>>>> >>>>>>>> As the loop of next_txq under lock protection as below, >>>>>>>> >>>>>>>> txq_schedule_start(); >>>>>>>> while(txq=next_txq()){ >>>>>>>> ... >>>>>>>> return_txq(txq); >>>>>>>> } >>>>>>>> txq_schedule_end(); >>>>>>>> >>>>>>>> I do not see any chance of addition, no? >>>>>>> >>>>>>> As you noted in your other email, Felix reduced the locking. And >>>>>>> yeah, >>>>>>> we need to rebase this series to also incorporate that. I figure >>>>>>> I >>>>>>> can >>>>>>> send an updated version of the first patch in the series once >>>>>>> we've >>>>>>> worked out the remaining issues with your follow-up patches. >>>>>>> >>>>>> Oh, I was thinking we were discussing without locking reduced. >>>>>> Yes, >>>>>> I >>>>>> also agree there might be a case causing infinite loop. With >>>>>> locking >>>>>> reduced, the tree can be adjusted between next_txq() and >>>>>> return_txq() >>>>>> in >>>>>> the loop situation. For further discussion, let 's consider, >>>>>> 1) the tree starts like: >>>>>> A->B->C->D->E >>>>>> 2) then next_txq() returns A for dequeuing >>>>>> 3) driver dequeues A and draines A without any active txq locked >>>>>> meaning >>>>>> the tree could be changed upon Tx compeletion. >>>>>> 4) then in return_txq(), the tree could be, >>>>>> i A->B->C->D->E (A is empty, and maybe soon be added >>>>>> back >>>>>> before the loop end) >>>>>> ii B->C->A->D->E (A is empty, and maybe soon be added >>>>>> back >>>>>> before the loop end) >>>>>> iii B->C->D->E->A (A is empty, and maybe soon be added >>>>>> back >>>>>> before the loop end) >>>>>> >>>>>> with this change: >>>>>> local->schedule_pos[ac] = rb_next(node) ?: rb_prev(node); >>>>>> >>>>>> for case i, local->schedule_pos[ac] is rb_next(A) which is B, and >>>>>> in >>>>>> next_txq(), rb_next(B) is what we returns which actually is C and >>>>>> B >>>>>> is >>>>>> skipped, no? >>>>>> >>>>>> Similiar for case ii, we skip B, C, D. >>>>> >>>>> Yup, I think you're right. But if we can fix this by making >>>>> ieee80211_resort_txq() aware of the schedule_pos as well, no? I.e., >>>>> if >>>>> resort_txq() acts on the txq that's currently in schedule_pos, it >>>>> will >>>>> update schedule pos with the same rb_next(node) ?: rb_prev(node); >>>>> (optionally after checking that the position of the node is >>>>> actually >>>>> going to change). >>>> Sorry, please igore last email sent by mistake. >>>> >>>> I don't think it makes any difference with that in unschedule_txq(). >>>> For >>>> case i, it finally picks C as well in next_txq(). For next_txq(), >>>> schedule_pos means previous candidate node whereas with your change, >>>> it >>>> looks like schedule_pos is current candidate node instead. >>> >>> Hmm, that was not actually what I was thinking, but yeah I think >>> you're >>> right that it would be easier to just change it so schedule_pos is >>> pointing to the next and not the current txq we want to schedule. >> So do you mean we can change next_txq like this, >> >> 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]); >> >> if (!node) { >> node = rb_first_cached(&local->active_txqs[ac]); >> first = true; >> - } else >> - node = rb_next(node); >> + } >> + >> if (!node) >> return NULL; > > Ah, no, now I remember why this didn't work and I went with the other > approach: If you make this change, you also have to have this at the > end: > > local->schedule_pos[ac] = rb_next(node); > > > But this means we can no longer distinguish between having gone through > the whole thing (so rb_next() returns NULL), or starting out with > nothing. > > So, instead we need to keep next_txq() the way it is, and just add Right, should keep next_txq() the way it is. > > local->schedule_pos[ac] = rb_prev(node); > > whenever we remove a node (both in return_txq() and resort_txq()). Agree, and also we may need to consider case like A is removed and soon be added back just the same as ii), B->C->A->D->E then B is schedule, removed and soon added back, C->A->B->D->E A and B will have a second chance to be scheduled and this may happen to others as well leading to the infinite loop as you have mentioned previously, so do we need to maintain a schedule_round like we do in DRR? Like, - If the node is in the same round, by pass schedule, go to rb_next(), either continue loop this round or end this round. - Increase the schedule_round at the schedule_start() only when the schedule_pos is NULL. > >>> >>> We'd still need a check in resort_txq() then, but it would make it >>> safe >>> to unschedule in return_txq()... >> Yes, agree with that. >> >> >>> >>>>>> Also I am wondering if there will be some SMP issues relating with >>>>>> local->schedule_pos[ac]. >>>>> >>>>> Not sure what you mean by this? >>>> My bad. Please ignore this. >>>> >>>> >>>>> >>>>>>>> In ath10k, we will usually push packets of first txq as many as >>>>>>>> we >>>>>>>> can >>>>>>>> until it is drained and then move to the next one. So if a txq >>>>>>>> gets >>>>>>>> removed in the return_txq, it should always be the leftmost. And >>>>>>>> during this period, neither vt of any station or global vt can >>>>>>>> be >>>>>>>> updated due to lock protection. >>>>>>>> >>>>>>>>> >>>>>>>>> But in that case, we could fix it by just conditionally >>>>>>>>> assigning >>>>>>>>> either >>>>>>>>> rb_next or rb_prev to the schedule_pos in unschedule_txq()? >>>>>>>>> I.e., >>>>>>>>> something like: >>>>>>>>> >>>>>>>>> local->schedule_pos[ac] = rb_next(node) ?: rb_prev(node); >>>>>>>> I am not sure I am getting your point. Still in next_txq, >>>>>>>> schedule_pos[ac] will lead us to the next node of the one we >>>>>>>> want. >>>>>>> >>>>>>> The logic in next_txq is different when schedule_pos[ac] is NULL, >>>>>>> vs >>>>>>> when rb_next(schedule_pos[ac]) is NULL. The former restarts a new >>>>>>> scheduling round, while the latter ends the current round. >>>>>>> >>>>>>> -Toke >>>>>> >>>>>> -- >>>>>> Yibo >>>> >>>> -- >>>> Yibo >> >> -- >> Yibo -- Yibo