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=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MIME_BASE64_TEXT,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, URIBL_BLOCKED,USER_AGENT_GIT 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 88A2BC2BA2B for ; Fri, 10 Apr 2020 08:56:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CEFBC20787 for ; Fri, 10 Apr 2020 08:56:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="tWNWjZdS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725975AbgDJI4Q (ORCPT ); Fri, 10 Apr 2020 04:56:16 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:49894 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726671AbgDJI4Q (ORCPT ); Fri, 10 Apr 2020 04:56:16 -0400 X-UUID: 898b870ceca949d6a38eedd00fa65163-20200410 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=Gw113brImNWXUUgWmPAzgFFc8mZhDULwKevqZGI9c0I=; b=tWNWjZdS0E//XpMrINcjfF4HiObrf73wBSI3rJFPf2vcp6YCqQBT+xC8KvNpm2uAX1/mZ8HpmGCORQgNX54qLkV3mnUtPb1U0S9STxeRPHVaiammauzeHb4SPVC2pY+ElmW7WXxSF8xAfLMjN9sIMJerzXN/UovUBFukpDyo+TA=; X-UUID: 898b870ceca949d6a38eedd00fa65163-20200410 Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 740987200; Fri, 10 Apr 2020 16:55:06 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 10 Apr 2020 16:54:56 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 10 Apr 2020 16:54:56 +0800 From: Ryder Lee To: Felix Fietkau , Lorenzo Bianconi CC: Shayne Chen , YF Luo , Yiwei Chung , Chih-Min Chen , Evelyn Tsai , Sean Wang , , , Ryder Lee Subject: [PATCH 06/16] mt76: add mac80211 driver for MT7915 PCIe-based chipsets Date: Fri, 10 Apr 2020 16:54:43 +0800 Message-ID: <3d9a74111aaadde7be00ec7c8c53d095daf4f9d2.1586507878.git.ryder.lee@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-MTK: N Content-Transfer-Encoding: base64 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org QWRkIHN1cHBvcnQgZm9yIHRoZSBNZWRpYVRlayBsYXRlc3QgZ2VuZXJhdGlvbiBJRUVFIDgwMi4x MWF4IDR4NA0KZGV2aWNlIE1UNzkxNUUsIHdoaWNoIHN1cHBvcnRzIGNvbmN1cnJlbnQgZHVhbC1i YW5kIG9wZXJhdGlvbiBhdA0KYm90aCA1R0h6IGFuZCAyLjRHSHouDQoNCk5vdGUgdGhhdCB0aGlz IHBhdGNoIGp1c3QgYWRkIGJhc2ljIHBhcnQgYW5kIHdpbGwgYWRkIG1vcmUgSEUNCmNhcGFiaWxp dGllcyBzdXBwb3J0IGluIHRoZSBmdXJ0aGVyIHBhdGNoZXMuDQoNClRoZSBkcml2ZXIgc3VwcG9y dHMgQVAsIFN0YXRpb24sIE1lc2ggYW5kIG1vbml0b3IgbW9kZS4NCg0KU2lnbmVkLW9mZi1ieTog UnlkZXIgTGVlIDxyeWRlci5sZWVAbWVkaWF0ZWsuY29tPg0KU2lnbmVkLW9mZi1ieTogU2hheW5l IENoZW4gPHNoYXluZS5jaGVuQG1lZGlhdGVrLmNvbT4NClNpZ25lZC1vZmYtYnk6IENoaWgtTWlu IENoZW4gPGNoaWgtbWluLmNoZW5AbWVkaWF0ZWsuY29tPg0KVGVzdGVkLWJ5OiBFdmVseW4gVHNh aSA8ZXZlbHluLnRzYWlAbWVkaWF0ZWsuY29tPg0KQWNrZWQtYnk6IFlpd2VpIENodW5nIDx5aXdl aS5jaHVuZ0BtZWRpYXRlay5jb20+DQpBY2tlZC1ieTogWUYgTHVvIDx5Zi5sdW9AbWVkaWF0ZWsu Y29tPg0KLS0tDQogZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9LY29uZmlnICAg IHwgICAgMSArDQogZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9NYWtlZmlsZSAg IHwgICAgMSArDQogLi4uL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9LY29uZmln IHwgICAxMyArDQogLi4uL3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L01ha2VmaWxlICAg IHwgICAgNiArDQogLi4uL3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L2RlYnVnZnMuYyAg IHwgIDI0NSArKw0KIC4uLi9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZG1hLmMg ICB8ICAyODMgKysNCiAuLi4vd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZWVwcm9tLmMg ICAgfCAgMTI1ICsNCiAuLi4vd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZWVwcm9tLmgg ICAgfCAgIDc4ICsNCiAuLi4vbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L2luaXQu YyAgfCAgMzkyICsrKw0KIC4uLi9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFj LmMgICB8IDEzMTAgKysrKysrKysrKw0KIC4uLi9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9t dDc5MTUvbWFjLmggICB8ICAzMzAgKysrDQogLi4uL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2 L210NzkxNS9tYWluLmMgIHwgIDc0MyArKysrKysNCiAuLi4vbmV0L3dpcmVsZXNzL21lZGlhdGVr L210NzYvbXQ3OTE1L21jdS5jICAgfCAyMzE5ICsrKysrKysrKysrKysrKysrDQogLi4uL25ldC93 aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9tY3UuaCAgIHwgIDgzNyArKysrKysNCiAuLi4v d2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbXQ3OTE1LmggICAgfCAgNDQyICsrKysNCiAu Li4vbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L3BjaS5jICAgfCAgMTY1ICsrDQog Li4uL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9yZWdzLmggIHwgIDM0NCArKysN CiAxNyBmaWxlcyBjaGFuZ2VkLCA3NjM0IGluc2VydGlvbnMoKykNCiBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvS2NvbmZpZw0KIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210Nzkx NS9NYWtlZmlsZQ0KIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRp YXRlay9tdDc2L210NzkxNS9kZWJ1Z2ZzLmMNCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9u ZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZG1hLmMNCiBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZWVwcm9tLmMNCiBj cmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5 MTUvZWVwcm9tLmgNCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVk aWF0ZWsvbXQ3Ni9tdDc5MTUvaW5pdC5jDQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbmV0 L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21hYy5jDQogY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21hYy5oDQogY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21h aW4uYw0KIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9t dDc2L210NzkxNS9tY3UuYw0KIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVz cy9tZWRpYXRlay9tdDc2L210NzkxNS9tY3UuaA0KIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJz L25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9tdDc5MTUuaA0KIGNyZWF0ZSBtb2Rl IDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9wY2kuYw0K IGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210 NzkxNS9yZWdzLmgNCg0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVr L210NzYvS2NvbmZpZyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvS2NvbmZp Zw0KaW5kZXggY2JjMmQ4YTVkMzU0Li40MTUzM2EwZTE3MjAgMTAwNjQ0DQotLS0gYS9kcml2ZXJz L25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L0tjb25maWcNCisrKyBiL2RyaXZlcnMvbmV0L3dp cmVsZXNzL21lZGlhdGVrL210NzYvS2NvbmZpZw0KQEAgLTI0LDMgKzI0LDQgQEAgc291cmNlICJk cml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzZ4MC9LY29uZmlnIg0KIHNvdXJj ZSAiZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc2eDIvS2NvbmZpZyINCiBz b3VyY2UgImRyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3NjAzL0tjb25maWci DQogc291cmNlICJkcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzYxNS9LY29u ZmlnIg0KK3NvdXJjZSAiZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUv S2NvbmZpZyINCmRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2 L01ha2VmaWxlIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9NYWtlZmlsZQ0K aW5kZXggZDdhMWRkYzllNDA3Li4xZGYwNDE1NmY5N2YgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL25l dC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L01ha2VmaWxlDQorKysgYi9kcml2ZXJzL25ldC93aXJl bGVzcy9tZWRpYXRlay9tdDc2L01ha2VmaWxlDQpAQCAtMjcsMyArMjcsNCBAQCBvYmotJChDT05G SUdfTVQ3NngwX0NPTU1PTikgKz0gbXQ3NngwLw0KIG9iai0kKENPTkZJR19NVDc2eDJfQ09NTU9O KSArPSBtdDc2eDIvDQogb2JqLSQoQ09ORklHX01UNzYwM0UpICs9IG10NzYwMy8NCiBvYmotJChD T05GSUdfTVQ3NjE1RSkgKz0gbXQ3NjE1Lw0KK29iai0kKENPTkZJR19NVDc5MTVFKSArPSBtdDc5 MTUvDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5 MTUvS2NvbmZpZyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L0tj b25maWcNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAwMDAwMDAwMDAwMDAuLjE3MzdmYjJi NGFkYw0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsv bXQ3Ni9tdDc5MTUvS2NvbmZpZw0KQEAgLTAsMCArMSwxMyBAQA0KKyMgU1BEWC1MaWNlbnNlLUlk ZW50aWZpZXI6IEdQTC0yLjAtb25seQ0KK2NvbmZpZyBNVDc5MTVFDQorCXRyaXN0YXRlICJNZWRp YVRlayBNVDc5MTVFIChQQ0llKSBzdXBwb3J0Ig0KKwlzZWxlY3QgTVQ3Nl9DT1JFDQorCWRlcGVu ZHMgb24gTUFDODAyMTENCisJZGVwZW5kcyBvbiBQQ0kNCisJaGVscA0KKwkgIFRoaXMgYWRkcyBz dXBwb3J0IGZvciBNVDc5MTUtYmFzZWQgd2lyZWxlc3MgUENJZSBkZXZpY2VzLA0KKwkgIHdoaWNo IHN1cHBvcnQgY29uY3VycmVudCBkdWFsLWJhbmQgb3BlcmF0aW9uIGF0IGJvdGggNUdIeg0KKwkg IGFuZCAyLjRHSHogSUVFRSA4MDIuMTFheCA0eDQ6NFNTIDEwMjQtUUFNLCAxNjBNSHogY2hhbm5l bHMsDQorCSAgT0ZETUEsIHNwYXRpYWwgcmV1c2UgYW5kIGR1YWwgY2FycmllciBtb2R1bGF0aW9u Lg0KKw0KKwkgIFRvIGNvbXBpbGUgdGhpcyBkcml2ZXIgYXMgYSBtb2R1bGUsIGNob29zZSBNIGhl cmUuDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5 MTUvTWFrZWZpbGUgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9N YWtlZmlsZQ0KbmV3IGZpbGUgbW9kZSAxMDA2NDQNCmluZGV4IDAwMDAwMDAwMDAwMC4uNTdmZTcy NmNjMzhiDQotLS0gL2Rldi9udWxsDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRl ay9tdDc2L210NzkxNS9NYWtlZmlsZQ0KQEAgLTAsMCArMSw2IEBADQorI1NQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBJU0MNCisNCitvYmotJChDT05GSUdfTVQ3OTE1RSkgKz0gbXQ3OTE1ZS5vDQor DQorbXQ3OTE1ZS15IDo9IHBjaS5vIGluaXQubyBkbWEubyBlZXByb20ubyBtYWluLm8gbWN1Lm8g bWFjLm8gXA0KKwkgICAgIGRlYnVnZnMubw0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVs ZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L2RlYnVnZnMuYyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNz L21lZGlhdGVrL210NzYvbXQ3OTE1L2RlYnVnZnMuYw0KbmV3IGZpbGUgbW9kZSAxMDA2NDQNCmlu ZGV4IDAwMDAwMDAwMDAwMC4uMTUyYWUwNjE3ZjNkDQotLS0gL2Rldi9udWxsDQorKysgYi9kcml2 ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9kZWJ1Z2ZzLmMNCkBAIC0wLDAg KzEsMjQ1IEBADQorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IElTQw0KKy8qIENvcHlyaWdo dCAoQykgMjAyMCBNZWRpYVRlayBJbmMuICovDQorDQorI2luY2x1ZGUgIm10NzkxNS5oIg0KKyNp bmNsdWRlICJlZXByb20uaCINCisNCisvKiogZ2xvYmFsIGRlYnVnZnMgKiovDQorDQorLyogdGVz dCBrbm9iIG9mIHN5c3RlbSBsYXllciAxLzIgZXJyb3IgcmVjb3ZlcnkgKi8NCitzdGF0aWMgaW50 IG10NzkxNV9zZXJfdHJpZ2dlcl9zZXQodm9pZCAqZGF0YSwgdTY0IHZhbCkNCit7DQorCWVudW0g ew0KKwkJU0VSX1NFVF9SRUNPVkVSX0wxID0gMSwNCisJCVNFUl9TRVRfUkVDT1ZFUl9MMiwNCisJ CVNFUl9FTkFCTEUgPSAyLA0KKwkJU0VSX1JFQ09WRVINCisJfTsNCisJc3RydWN0IG10NzkxNV9k ZXYgKmRldiA9IGRhdGE7DQorCWludCByZXQgPSAwOw0KKw0KKwlzd2l0Y2ggKHZhbCkgew0KKwlj YXNlIFNFUl9TRVRfUkVDT1ZFUl9MMToNCisJY2FzZSBTRVJfU0VUX1JFQ09WRVJfTDI6DQorCQkv KiBmYWxsIHRocm91Z2ggKi8NCisJCXJldCA9IG10NzkxNV9tY3Vfc2V0X3NlcihkZXYsIFNFUl9F TkFCTEUsIEJJVCh2YWwpLCAwKTsNCisJCWlmIChyZXQpDQorCQkJcmV0dXJuIHJldDsNCisNCisJ CXJldHVybiBtdDc5MTVfbWN1X3NldF9zZXIoZGV2LCBTRVJfUkVDT1ZFUiwgdmFsLCAwKTsNCisJ ZGVmYXVsdDoNCisJCWJyZWFrOw0KKwl9DQorDQorCXJldHVybiByZXQ7DQorfQ0KKw0KK0RFRklO RV9ERUJVR0ZTX0FUVFJJQlVURShmb3BzX3Nlcl90cmlnZ2VyLCBOVUxMLA0KKwkJCSBtdDc5MTVf c2VyX3RyaWdnZXJfc2V0LCAiJWxsZFxuIik7DQorDQorc3RhdGljIGludA0KK210NzkxNV9yYWRh cl90cmlnZ2VyKHZvaWQgKmRhdGEsIHU2NCB2YWwpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAq ZGV2ID0gZGF0YTsNCisNCisJcmV0dXJuIG10NzkxNV9tY3VfcmRkX2NtZChkZXYsIFJERF9SQURB Ul9FTVVMQVRFLCAxLCAwLCAwKTsNCit9DQorDQorREVGSU5FX0RFQlVHRlNfQVRUUklCVVRFKGZv cHNfcmFkYXJfdHJpZ2dlciwgTlVMTCwNCisJCQkgbXQ3OTE1X3JhZGFyX3RyaWdnZXIsICIlbGxk XG4iKTsNCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X2RiZGNfc2V0KHZvaWQgKmRhdGEsIHU2NCB2 YWwpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gZGF0YTsNCisNCisJaWYgKHZhbCkN CisJCW10NzkxNV9yZWdpc3Rlcl9leHRfcGh5KGRldik7DQorCWVsc2UNCisJCW10NzkxNV91bnJl Z2lzdGVyX2V4dF9waHkoZGV2KTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRpYyBpbnQN CittdDc5MTVfZGJkY19nZXQodm9pZCAqZGF0YSwgdTY0ICp2YWwpDQorew0KKwlzdHJ1Y3QgbXQ3 OTE1X2RldiAqZGV2ID0gZGF0YTsNCisNCisJKnZhbCA9ICEhbXQ3OTE1X2V4dF9waHkoZGV2KTsN CisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK0RFRklORV9ERUJVR0ZTX0FUVFJJQlVURShmb3BzX2Ri ZGMsIG10NzkxNV9kYmRjX2dldCwNCisJCQkgbXQ3OTE1X2RiZGNfc2V0LCAiJWxsZFxuIik7DQor DQorc3RhdGljIHZvaWQNCittdDc5MTVfYW1wZHVfc3RhdF9yZWFkX3BoeShzdHJ1Y3QgbXQ3OTE1 X3BoeSAqcGh5LA0KKwkJCSAgIHN0cnVjdCBzZXFfZmlsZSAqZmlsZSkNCit7DQorCXN0cnVjdCBt dDc5MTVfZGV2ICpkZXYgPSBmaWxlLT5wcml2YXRlOw0KKwlib29sIGV4dF9waHkgPSBwaHkgIT0g JmRldi0+cGh5Ow0KKwlpbnQgYm91bmRbMTVdLCByYW5nZVs0XSwgaSwgbjsNCisNCisJaWYgKCFw aHkpDQorCQlyZXR1cm47DQorDQorCS8qIFR4IGFtcGR1IHN0YXQgKi8NCisJZm9yIChpID0gMDsg aSA8IEFSUkFZX1NJWkUocmFuZ2UpOyBpKyspDQorCQlyYW5nZVtpXSA9IG10NzZfcnIoZGV2LCBN VF9NSUJfQVJORyhleHRfcGh5LCBpKSk7DQorDQorCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpF KGJvdW5kKTsgaSsrKQ0KKwkJYm91bmRbaV0gPSBNVF9NSUJfQVJOQ1JfUkFOR0UocmFuZ2VbaSAv IDRdLCBpKSArIDE7DQorDQorCXNlcV9wcmludGYoZmlsZSwgIlxuUGh5ICVkXG4iLCBleHRfcGh5 KTsNCisNCisJc2VxX3ByaW50ZihmaWxlLCAiTGVuZ3RoOiAlOGQgfCAiLCBib3VuZFswXSk7DQor CWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKGJvdW5kKSAtIDE7IGkrKykNCisJCXNlcV9wcmlu dGYoZmlsZSwgIiUzZCAtJTNkIHwgIiwNCisJCQkgICBib3VuZFtpXSArIDEsIGJvdW5kW2kgKyAx XSk7DQorDQorCXNlcV9wdXRzKGZpbGUsICJcbkNvdW50OiAgIik7DQorCW4gPSBleHRfcGh5ID8g QVJSQVlfU0laRShkZXYtPm10NzYuYWdncl9zdGF0cykgLyAyIDogMDsNCisJZm9yIChpID0gMDsg aSA8IEFSUkFZX1NJWkUoYm91bmQpOyBpKyspDQorCQlzZXFfcHJpbnRmKGZpbGUsICIlOGQgfCAi LCBkZXYtPm10NzYuYWdncl9zdGF0c1tpICsgbl0pOw0KKwlzZXFfcHV0cyhmaWxlLCAiXG4iKTsN CisNCisJc2VxX3ByaW50ZihmaWxlLCAiQkEgbWlzcyBjb3VudDogJWRcbiIsIHBoeS0+bWliLmJh X21pc3NfY250KTsNCit9DQorDQorc3RhdGljIGludA0KK210NzkxNV90eF9zdGF0c19yZWFkKHN0 cnVjdCBzZXFfZmlsZSAqZmlsZSwgdm9pZCAqZGF0YSkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2 ICpkZXYgPSBmaWxlLT5wcml2YXRlOw0KKwlpbnQgc3RhdFs4XSwgaSwgbjsNCisNCisJbXQ3OTE1 X2FtcGR1X3N0YXRfcmVhZF9waHkoJmRldi0+cGh5LCBmaWxlKTsNCisJbXQ3OTE1X2FtcGR1X3N0 YXRfcmVhZF9waHkobXQ3OTE1X2V4dF9waHkoZGV2KSwgZmlsZSk7DQorDQorCS8qIFR4IGFtc2R1 IGluZm8gKi8NCisJc2VxX3B1dHMoZmlsZSwgIlR4IE1TRFUgc3RhdDpcbiIpOw0KKwlmb3IgKGkg PSAwLCBuID0gMDsgaSA8IEFSUkFZX1NJWkUoc3RhdCk7IGkrKykgew0KKwkJc3RhdFtpXSA9IG10 NzZfcnIoZGV2LCAgTVRfUExFX0FNU0RVX1BBQ0tfTVNEVV9DTlQoaSkpOw0KKwkJbiArPSBzdGF0 W2ldOw0KKwl9DQorDQorCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKHN0YXQpOyBpKyspIHsN CisJCXNlcV9wcmludGYoZmlsZSwgIkFNU0RVIHBhY2sgY291bnQgb2YgJWQgTVNEVSBpbiBUWEQ6 IDB4JXggIiwNCisJCQkgICBpICsgMSwgc3RhdFtpXSk7DQorCQlpZiAobiAhPSAwKQ0KKwkJCXNl cV9wcmludGYoZmlsZSwgIiglZCUlKVxuIiwgc3RhdFtpXSAqIDEwMCAvIG4pOw0KKwkJZWxzZQ0K KwkJCXNlcV9wdXRzKGZpbGUsICJcbiIpOw0KKwl9DQorDQorCXJldHVybiAwOw0KK30NCisNCitz dGF0aWMgaW50DQorbXQ3OTE1X3R4X3N0YXRzX29wZW4oc3RydWN0IGlub2RlICppbm9kZSwgc3Ry dWN0IGZpbGUgKmYpDQorew0KKwlyZXR1cm4gc2luZ2xlX29wZW4oZiwgbXQ3OTE1X3R4X3N0YXRz X3JlYWQsIGlub2RlLT5pX3ByaXZhdGUpOw0KK30NCisNCitzdGF0aWMgY29uc3Qgc3RydWN0IGZp bGVfb3BlcmF0aW9ucyBmb3BzX3R4X3N0YXRzID0gew0KKwkub3BlbiA9IG10NzkxNV90eF9zdGF0 c19vcGVuLA0KKwkucmVhZCA9IHNlcV9yZWFkLA0KKwkubGxzZWVrID0gc2VxX2xzZWVrLA0KKwku cmVsZWFzZSA9IHNpbmdsZV9yZWxlYXNlLA0KK307DQorDQorc3RhdGljIGludCBtdDc5MTVfcmVh ZF90ZW1wZXJhdHVyZShzdHJ1Y3Qgc2VxX2ZpbGUgKnMsIHZvaWQgKmRhdGEpDQorew0KKwlzdHJ1 Y3QgbXQ3OTE1X2RldiAqZGV2ID0gZGV2X2dldF9kcnZkYXRhKHMtPnByaXZhdGUpOw0KKwlpbnQg dGVtcDsNCisNCisJLyogY3B1ICovDQorCXRlbXAgPSBtdDc5MTVfbWN1X2dldF90ZW1wZXJhdHVy ZShkZXYsIDApOw0KKwlzZXFfcHJpbnRmKHMsICJUZW1wZXJhdHVyZTogJWRcbiIsIHRlbXApOw0K Kw0KKwlyZXR1cm4gMDsNCit9DQorDQorc3RhdGljIGludA0KK210NzkxNV9xdWV1ZXNfYWNxKHN0 cnVjdCBzZXFfZmlsZSAqcywgdm9pZCAqZGF0YSkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpk ZXYgPSBkZXZfZ2V0X2RydmRhdGEocy0+cHJpdmF0ZSk7DQorCWludCBpOw0KKw0KKwlmb3IgKGkg PSAwOyBpIDwgMTY7IGkrKykgew0KKwkJaW50IGosIGFjcyA9IGkgLyA0LCBpbmRleCA9IGkgJSA0 Ow0KKwkJdTMyIGN0cmwsIHZhbCwgcWxlbiA9IDA7DQorDQorCQl2YWwgPSBtdDc2X3JyKGRldiwg TVRfUExFX0FDX1FFTVBUWShhY3MsIGluZGV4KSk7DQorCQljdHJsID0gQklUKDMxKSB8IEJJVCgx NSkgfCAoYWNzIDw8IDgpOw0KKw0KKwkJZm9yIChqID0gMDsgaiA8IDMyOyBqKyspIHsNCisJCQlp ZiAodmFsICYgQklUKGopKQ0KKwkJCQljb250aW51ZTsNCisNCisJCQltdDc2X3dyKGRldiwgTVRf UExFX0ZMX1EwX0NUUkwsDQorCQkJCWN0cmwgfCAoaiArIChpbmRleCA8PCA1KSkpOw0KKwkJCXFs ZW4gKz0gbXQ3Nl9nZXRfZmllbGQoZGV2LCBNVF9QTEVfRkxfUTNfQ1RSTCwNCisJCQkJCSAgICAg ICBHRU5NQVNLKDExLCAwKSk7DQorCQl9DQorCQlzZXFfcHJpbnRmKHMsICJBQyVkJWQ6IHF1ZXVl ZD0lZFxuIiwgYWNzLCBpbmRleCwgcWxlbik7DQorCX0NCisNCisJcmV0dXJuIDA7DQorfQ0KKw0K K3N0YXRpYyBpbnQNCittdDc5MTVfcXVldWVzX3JlYWQoc3RydWN0IHNlcV9maWxlICpzLCB2b2lk ICpkYXRhKQ0KK3sNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IGRldl9nZXRfZHJ2ZGF0YShz LT5wcml2YXRlKTsNCisJc3RhdGljIGNvbnN0IHN0cnVjdCB7DQorCQljaGFyICpxdWV1ZTsNCisJ CWludCBpZDsNCisJfSBxdWV1ZV9tYXBbXSA9IHsNCisJCXsgIldGRE1BMCIsIE1UX1RYUV9CRSB9 LA0KKwkJeyAiTUNVV00iLCBNVF9UWFFfTUNVIH0sDQorCQl7ICJNQ1VXQSIsIE1UX1RYUV9NQ1Vf V0EgfSwNCisJCXsgIk1DVUZXUSIsIE1UX1RYUV9GV0RMIH0sDQorCX07DQorCWludCBpOw0KKw0K Kwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShxdWV1ZV9tYXApOyBpKyspIHsNCisJCXN0cnVj dCBtdDc2X3N3X3F1ZXVlICpxID0gJmRldi0+bXQ3Ni5xX3R4W3F1ZXVlX21hcFtpXS5pZF07DQor DQorCQlpZiAoIXEtPnEpDQorCQkJY29udGludWU7DQorDQorCQlzZXFfcHJpbnRmKHMsDQorCQkJ ICAgIiVzOglxdWV1ZWQ9JWQgaGVhZD0lZCB0YWlsPSVkXG4iLA0KKwkJCSAgIHF1ZXVlX21hcFtp XS5xdWV1ZSwgcS0+cS0+cXVldWVkLCBxLT5xLT5oZWFkLA0KKwkJCSAgIHEtPnEtPnRhaWwpOw0K Kwl9DQorDQorCXJldHVybiAwOw0KK30NCisNCitpbnQgbXQ3OTE1X2luaXRfZGVidWdmcyhzdHJ1 Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJc3RydWN0IGRlbnRyeSAqZGlyOw0KKw0KKwlkaXIg PSBtdDc2X3JlZ2lzdGVyX2RlYnVnZnMoJmRldi0+bXQ3Nik7DQorCWlmICghZGlyKQ0KKwkJcmV0 dXJuIC1FTk9NRU07DQorDQorCWRlYnVnZnNfY3JlYXRlX2Rldm1fc2VxZmlsZShkZXYtPm10NzYu ZGV2LCAicXVldWVzIiwgZGlyLA0KKwkJCQkgICAgbXQ3OTE1X3F1ZXVlc19yZWFkKTsNCisJZGVi dWdmc19jcmVhdGVfZGV2bV9zZXFmaWxlKGRldi0+bXQ3Ni5kZXYsICJhY3EiLCBkaXIsDQorCQkJ CSAgICBtdDc5MTVfcXVldWVzX2FjcSk7DQorCWRlYnVnZnNfY3JlYXRlX2ZpbGUoInR4X3N0YXRz IiwgMDQwMCwgZGlyLCBkZXYsICZmb3BzX3R4X3N0YXRzKTsNCisJZGVidWdmc19jcmVhdGVfZmls ZSgiZGJkYyIsIDA2MDAsIGRpciwgZGV2LCAmZm9wc19kYmRjKTsNCisJZGVidWdmc19jcmVhdGVf dTMyKCJkZnNfaHdfcGF0dGVybiIsIDA0MDAsIGRpciwgJmRldi0+aHdfcGF0dGVybik7DQorCS8q IHRlc3Qga25vYnMgKi8NCisJZGVidWdmc19jcmVhdGVfZmlsZSgicmFkYXJfdHJpZ2dlciIsIDAy MDAsIGRpciwgZGV2LA0KKwkJCSAgICAmZm9wc19yYWRhcl90cmlnZ2VyKTsNCisJZGVidWdmc19j cmVhdGVfZmlsZSgic2VyX3RyaWdnZXIiLCAwMjAwLCBkaXIsIGRldiwgJmZvcHNfc2VyX3RyaWdn ZXIpOw0KKwlkZWJ1Z2ZzX2NyZWF0ZV9kZXZtX3NlcWZpbGUoZGV2LT5tdDc2LmRldiwgInRlbXBl cmF0dXJlIiwgZGlyLA0KKwkJCQkgICAgbXQ3OTE1X3JlYWRfdGVtcGVyYXR1cmUpOw0KKw0KKwly ZXR1cm4gMDsNCit9DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsv bXQ3Ni9tdDc5MTUvZG1hLmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210 NzkxNS9kbWEuYw0KbmV3IGZpbGUgbW9kZSAxMDA2NDQNCmluZGV4IDAwMDAwMDAwMDAwMC4uMDE1 NmU2ZTU5MzNhDQotLS0gL2Rldi9udWxsDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRp YXRlay9tdDc2L210NzkxNS9kbWEuYw0KQEAgLTAsMCArMSwyODMgQEANCisvLyBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogSVNDDQorLyogQ29weXJpZ2h0IChDKSAyMDIwIE1lZGlhVGVrIEluYy4g Ki8NCisNCisjaW5jbHVkZSAibXQ3OTE1LmgiDQorI2luY2x1ZGUgIi4uL2RtYS5oIg0KKyNpbmNs dWRlICJtYWMuaCINCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X2luaXRfdHhfcXVldWVzKHN0cnVj dCBtdDc5MTVfZGV2ICpkZXYsIGludCBuX2Rlc2MpDQorew0KKwlzdHJ1Y3QgbXQ3Nl9zd19xdWV1 ZSAqcTsNCisJc3RydWN0IG10NzZfcXVldWUgKmh3cTsNCisJaW50IGVyciwgaTsNCisNCisJaHdx ID0gZGV2bV9remFsbG9jKGRldi0+bXQ3Ni5kZXYsIHNpemVvZigqaHdxKSwgR0ZQX0tFUk5FTCk7 DQorCWlmICghaHdxKQ0KKwkJcmV0dXJuIC1FTk9NRU07DQorDQorCWVyciA9IG10NzZfcXVldWVf YWxsb2MoZGV2LCBod3EsIE1UNzkxNV9UWFFfQkFORDAsIG5fZGVzYywgMCwNCisJCQkgICAgICAg TVRfVFhfUklOR19CQVNFKTsNCisJaWYgKGVyciA8IDApDQorCQlyZXR1cm4gZXJyOw0KKw0KKwlm b3IgKGkgPSAwOyBpIDwgTVRfVFhRX01DVTsgaSsrKSB7DQorCQlxID0gJmRldi0+bXQ3Ni5xX3R4 W2ldOw0KKwkJSU5JVF9MSVNUX0hFQUQoJnEtPnN3cSk7DQorCQlxLT5xID0gaHdxOw0KKwl9DQor DQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X2luaXRfbWN1X3F1ZXVl KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBtdDc2X3N3X3F1ZXVlICpxLA0KKwkJICAg ICAgaW50IGlkeCwgaW50IG5fZGVzYykNCit7DQorCXN0cnVjdCBtdDc2X3F1ZXVlICpod3E7DQor CWludCBlcnI7DQorDQorCWh3cSA9IGRldm1fa3phbGxvYyhkZXYtPm10NzYuZGV2LCBzaXplb2Yo Kmh3cSksIEdGUF9LRVJORUwpOw0KKwlpZiAoIWh3cSkNCisJCXJldHVybiAtRU5PTUVNOw0KKw0K KwllcnIgPSBtdDc2X3F1ZXVlX2FsbG9jKGRldiwgaHdxLCBpZHgsIG5fZGVzYywgMCwgTVRfVFhf UklOR19CQVNFKTsNCisJaWYgKGVyciA8IDApDQorCQlyZXR1cm4gZXJyOw0KKw0KKwlJTklUX0xJ U1RfSEVBRCgmcS0+c3dxKTsNCisJcS0+cSA9IGh3cTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0K K3ZvaWQgbXQ3OTE1X3F1ZXVlX3J4X3NrYihzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYsIGVudW0gbXQ3 Nl9yeHFfaWQgcSwNCisJCQkgc3RydWN0IHNrX2J1ZmYgKnNrYikNCit7DQorCXN0cnVjdCBtdDc5 MTVfZGV2ICpkZXYgPSBjb250YWluZXJfb2YobWRldiwgc3RydWN0IG10NzkxNV9kZXYsIG10NzYp Ow0KKwlfX2xlMzIgKnJ4ZCA9IChfX2xlMzIgKilza2ItPmRhdGE7DQorCWVudW0gcnhfcGt0X3R5 cGUgdHlwZTsNCisNCisJdHlwZSA9IEZJRUxEX0dFVChNVF9SWEQwX1BLVF9UWVBFLCBsZTMyX3Rv X2NwdShyeGRbMF0pKTsNCisNCisJc3dpdGNoICh0eXBlKSB7DQorCWNhc2UgUEtUX1RZUEVfVFhS WF9OT1RJRlk6DQorCQltdDc5MTVfbWFjX3R4X2ZyZWUoZGV2LCBza2IpOw0KKwkJYnJlYWs7DQor CWNhc2UgUEtUX1RZUEVfUlhfRVZFTlQ6DQorCQltdDc5MTVfbWN1X3J4X2V2ZW50KGRldiwgc2ti KTsNCisJCWJyZWFrOw0KKwljYXNlIFBLVF9UWVBFX05PUk1BTDoNCisJCWlmICghbXQ3OTE1X21h Y19maWxsX3J4KGRldiwgc2tiKSkgew0KKwkJCW10NzZfcngoJmRldi0+bXQ3NiwgcSwgc2tiKTsN CisJCQlyZXR1cm47DQorCQl9DQorCQkvKiBmYWxsIHRocm91Z2ggKi8NCisJZGVmYXVsdDoNCisJ CWRldl9rZnJlZV9za2Ioc2tiKTsNCisJCWJyZWFrOw0KKwl9DQorfQ0KKw0KK3N0YXRpYyBpbnQg bXQ3OTE1X3BvbGxfdHgoc3RydWN0IG5hcGlfc3RydWN0ICpuYXBpLCBpbnQgYnVkZ2V0KQ0KK3sN CisJc3RhdGljIGNvbnN0IHU4IHF1ZXVlX21hcFtdID0gew0KKwkJTVRfVFhRX01DVSwNCisJCU1U X1RYUV9NQ1VfV0EsDQorCQlNVF9UWFFfQkUNCisJfTsNCisJc3RydWN0IG10NzkxNV9kZXYgKmRl djsNCisJaW50IGk7DQorDQorCWRldiA9IGNvbnRhaW5lcl9vZihuYXBpLCBzdHJ1Y3QgbXQ3OTE1 X2RldiwgbXQ3Ni50eF9uYXBpKTsNCisNCisJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUocXVl dWVfbWFwKTsgaSsrKQ0KKwkJbXQ3Nl9xdWV1ZV90eF9jbGVhbnVwKGRldiwgcXVldWVfbWFwW2ld LCBmYWxzZSk7DQorDQorCWlmIChuYXBpX2NvbXBsZXRlX2RvbmUobmFwaSwgMCkpDQorCQltdDc5 MTVfaXJxX2VuYWJsZShkZXYsIE1UX0lOVF9UWF9ET05FX0FMTCk7DQorDQorCWZvciAoaSA9IDA7 IGkgPCBBUlJBWV9TSVpFKHF1ZXVlX21hcCk7IGkrKykNCisJCW10NzZfcXVldWVfdHhfY2xlYW51 cChkZXYsIHF1ZXVlX21hcFtpXSwgZmFsc2UpOw0KKw0KKwltdDc5MTVfbWFjX3N0YV9wb2xsKGRl dik7DQorDQorCXRhc2tsZXRfc2NoZWR1bGUoJmRldi0+bXQ3Ni50eF90YXNrbGV0KTsNCisNCisJ cmV0dXJuIDA7DQorfQ0KKw0KK3ZvaWQgbXQ3OTE1X2RtYV9wcmVmZXRjaChzdHJ1Y3QgbXQ3OTE1 X2RldiAqZGV2KQ0KK3sNCisjZGVmaW5lIFBSRUZFVENIKGJhc2UsIGRlcHRoKQkoKGJhc2UpIDw8 IDE2IHwgKGRlcHRoKSkNCisNCisJbXQ3Nl93cihkZXYsIE1UX1dGRE1BMF9SWF9SSU5HMF9FWFRf Q1RSTCwgUFJFRkVUQ0goMHgwLCAweDQpKTsNCisJbXQ3Nl93cihkZXYsIE1UX1dGRE1BMF9SWF9S SU5HMV9FWFRfQ1RSTCwgUFJFRkVUQ0goMHg0MCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9X RkRNQTBfUlhfUklORzJfRVhUX0NUUkwsIFBSRUZFVENIKDB4ODAsIDB4MCkpOw0KKw0KKwltdDc2 X3dyKGRldiwgTVRfV0ZETUExX1RYX1JJTkcwX0VYVF9DVFJMLCBQUkVGRVRDSCgweDgwLCAweDQp KTsNCisJbXQ3Nl93cihkZXYsIE1UX1dGRE1BMV9UWF9SSU5HMV9FWFRfQ1RSTCwgUFJFRkVUQ0go MHhjMCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfVFhfUklORzJfRVhUX0NUUkws IFBSRUZFVENIKDB4MTAwLCAweDQpKTsNCisJbXQ3Nl93cihkZXYsIE1UX1dGRE1BMV9UWF9SSU5H M19FWFRfQ1RSTCwgUFJFRkVUQ0goMHgxNDAsIDB4NCkpOw0KKwltdDc2X3dyKGRldiwgTVRfV0ZE TUExX1RYX1JJTkc0X0VYVF9DVFJMLCBQUkVGRVRDSCgweDE4MCwgMHg0KSk7DQorCW10NzZfd3Io ZGV2LCBNVF9XRkRNQTFfVFhfUklORzVfRVhUX0NUUkwsIFBSRUZFVENIKDB4MWMwLCAweDQpKTsN CisJbXQ3Nl93cihkZXYsIE1UX1dGRE1BMV9UWF9SSU5HNl9FWFRfQ1RSTCwgUFJFRkVUQ0goMHgy MDAsIDB4NCkpOw0KKwltdDc2X3dyKGRldiwgTVRfV0ZETUExX1RYX1JJTkc3X0VYVF9DVFJMLCBQ UkVGRVRDSCgweDI0MCwgMHg0KSk7DQorDQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfVFhfUklO RzE2X0VYVF9DVFJMLCBQUkVGRVRDSCgweDI4MCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9X RkRNQTFfVFhfUklORzE3X0VYVF9DVFJMLCBQUkVGRVRDSCgweDJjMCwgMHg0KSk7DQorCW10NzZf d3IoZGV2LCBNVF9XRkRNQTFfVFhfUklORzE4X0VYVF9DVFJMLCBQUkVGRVRDSCgweDMwMCwgMHg0 KSk7DQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfVFhfUklORzE5X0VYVF9DVFJMLCBQUkVGRVRD SCgweDM0MCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfVFhfUklORzIwX0VYVF9D VFJMLCBQUkVGRVRDSCgweDM4MCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfVFhf UklORzIxX0VYVF9DVFJMLCBQUkVGRVRDSCgweDNjMCwgMHgwKSk7DQorDQorCW10NzZfd3IoZGV2 LCBNVF9XRkRNQTFfUlhfUklORzBfRVhUX0NUUkwsIFBSRUZFVENIKDB4M2MwLCAweDQpKTsNCisJ bXQ3Nl93cihkZXYsIE1UX1dGRE1BMV9SWF9SSU5HMV9FWFRfQ1RSTCwgUFJFRkVUQ0goMHg0MDAs IDB4NCkpOw0KKwltdDc2X3dyKGRldiwgTVRfV0ZETUExX1JYX1JJTkcyX0VYVF9DVFJMLCBQUkVG RVRDSCgweDQ0MCwgMHg0KSk7DQorCW10NzZfd3IoZGV2LCBNVF9XRkRNQTFfUlhfUklORzNfRVhU X0NUUkwsIFBSRUZFVENIKDB4NDgwLCAweDApKTsNCit9DQorDQoraW50IG10NzkxNV9kbWFfaW5p dChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJaW50IHJldDsNCisNCisJbXQ3Nl9kbWFf YXR0YWNoKCZkZXYtPm10NzYpOw0KKw0KKwkvKiBjb25maWd1cmUgZ2xvYmFsIHNldHRpbmcgKi8N CisJbXQ3Nl9zZXQoZGV2LCBNVF9XRkRNQTFfR0xPX0NGRywNCisJCSBNVF9XRkRNQTFfR0xPX0NG R19PTUlUX1RYX0lORk8gfA0KKwkJIE1UX1dGRE1BMV9HTE9fQ0ZHX09NSVRfUlhfSU5GTyk7DQor DQorCS8qIGNvbmZpZ3VyZSBwZXJmZXRjaCBzZXR0aW5ncyAqLw0KKwltdDc5MTVfZG1hX3ByZWZl dGNoKGRldik7DQorDQorCS8qIHJlc2V0IGRtYSBpZHggKi8NCisJbXQ3Nl93cihkZXYsIE1UX1dG RE1BMF9SU1RfRFRYX1BUUiwgfjApOw0KKwltdDc2X3dyKGRldiwgTVRfV0ZETUExX1JTVF9EVFhf UFRSLCB+MCk7DQorDQorCS8qIGNvbmZpZ3VyZSBkZWxheSBpbnRlcnJ1cHQgKi8NCisJbXQ3Nl93 cihkZXYsIE1UX1dGRE1BMF9QUklfRExZX0lOVF9DRkcwLCAwKTsNCisJbXQ3Nl93cihkZXYsIE1U X1dGRE1BMV9QUklfRExZX0lOVF9DRkcwLCAwKTsNCisNCisJLyogaW5pdCB0eCBxdWV1ZSAqLw0K KwlyZXQgPSBtdDc5MTVfaW5pdF90eF9xdWV1ZXMoZGV2LCBNVDc5MTVfVFhfUklOR19TSVpFKTsN CisJaWYgKHJldCkNCisJCXJldHVybiByZXQ7DQorDQorCS8qIGNvbW1hbmQgdG8gV00gKi8NCisJ cmV0ID0gbXQ3OTE1X2luaXRfbWN1X3F1ZXVlKGRldiwgJmRldi0+bXQ3Ni5xX3R4W01UX1RYUV9N Q1VdLA0KKwkJCQkgICAgTVQ3OTE1X1RYUV9NQ1VfV00sDQorCQkJCSAgICBNVDc5MTVfVFhfTUNV X1JJTkdfU0laRSk7DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0Ow0KKw0KKwkvKiBjb21tYW5k IHRvIFdBICovDQorCXJldCA9IG10NzkxNV9pbml0X21jdV9xdWV1ZShkZXYsICZkZXYtPm10NzYu cV90eFtNVF9UWFFfTUNVX1dBXSwNCisJCQkJICAgIE1UNzkxNV9UWFFfTUNVX1dBLA0KKwkJCQkg ICAgTVQ3OTE1X1RYX01DVV9SSU5HX1NJWkUpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsN CisNCisJLyogZmlybXdhcmUgZG93bmxvYWQgKi8NCisJcmV0ID0gbXQ3OTE1X2luaXRfbWN1X3F1 ZXVlKGRldiwgJmRldi0+bXQ3Ni5xX3R4W01UX1RYUV9GV0RMXSwNCisJCQkJICAgIE1UNzkxNV9U WFFfRldETCwNCisJCQkJICAgIE1UNzkxNV9UWF9GV0RMX1JJTkdfU0laRSk7DQorCWlmIChyZXQp DQorCQlyZXR1cm4gcmV0Ow0KKw0KKwkvKiBldmVudCBmcm9tIFdNICovDQorCXJldCA9IG10NzZf cXVldWVfYWxsb2MoZGV2LCAmZGV2LT5tdDc2LnFfcnhbTVRfUlhRX01DVV0sDQorCQkJICAgICAg IE1UNzkxNV9SWFFfTUNVX1dNLCBNVDc5MTVfUlhfTUNVX1JJTkdfU0laRSwNCisJCQkgICAgICAg TVRfUlhfQlVGX1NJWkUsIE1UX1JYX0VWRU5UX1JJTkdfQkFTRSk7DQorCWlmIChyZXQpDQorCQly ZXR1cm4gcmV0Ow0KKw0KKwkvKiBldmVudCBmcm9tIFdBICovDQorCXJldCA9IG10NzZfcXVldWVf YWxsb2MoZGV2LCAmZGV2LT5tdDc2LnFfcnhbTVRfUlhRX01DVV9XQV0sDQorCQkJICAgICAgIE1U NzkxNV9SWFFfTUNVX1dBLCBNVDc5MTVfUlhfTUNVX1JJTkdfU0laRSwNCisJCQkgICAgICAgTVRf UlhfQlVGX1NJWkUsIE1UX1JYX0VWRU5UX1JJTkdfQkFTRSk7DQorCWlmIChyZXQpDQorCQlyZXR1 cm4gcmV0Ow0KKw0KKwkvKiByeCBkYXRhICovDQorCXJldCA9IG10NzZfcXVldWVfYWxsb2MoZGV2 LCAmZGV2LT5tdDc2LnFfcnhbTVRfUlhRX01BSU5dLCAwLA0KKwkJCSAgICAgICBNVDc5MTVfUlhf UklOR19TSVpFLCBNVF9SWF9CVUZfU0laRSwNCisJCQkgICAgICAgTVRfUlhfREFUQV9SSU5HX0JB U0UpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsNCisNCisJcmV0ID0gbXQ3Nl9pbml0X3F1 ZXVlcyhkZXYpOw0KKwlpZiAocmV0IDwgMCkNCisJCXJldHVybiByZXQ7DQorDQorCW5ldGlmX3R4 X25hcGlfYWRkKCZkZXYtPm10NzYubmFwaV9kZXYsICZkZXYtPm10NzYudHhfbmFwaSwNCisJCQkg IG10NzkxNV9wb2xsX3R4LCBOQVBJX1BPTExfV0VJR0hUKTsNCisJbmFwaV9lbmFibGUoJmRldi0+ bXQ3Ni50eF9uYXBpKTsNCisNCisJLyogaGlmIHdhaXQgV0ZETUEgaWRsZSAqLw0KKwltdDc2X3Nl dChkZXYsIE1UX1dGRE1BMF9CVVNZX0VOQSwNCisJCSBNVF9XRkRNQTBfQlVTWV9FTkFfVFhfRklG TzAgfA0KKwkJIE1UX1dGRE1BMF9CVVNZX0VOQV9UWF9GSUZPMSB8DQorCQkgTVRfV0ZETUEwX0JV U1lfRU5BX1JYX0ZJRk8pOw0KKw0KKwltdDc2X3NldChkZXYsIE1UX1dGRE1BMV9CVVNZX0VOQSwN CisJCSBNVF9XRkRNQTFfQlVTWV9FTkFfVFhfRklGTzAgfA0KKwkJIE1UX1dGRE1BMV9CVVNZX0VO QV9UWF9GSUZPMSB8DQorCQkgTVRfV0ZETUExX0JVU1lfRU5BX1JYX0ZJRk8pOw0KKw0KKwltdDc2 X3NldChkZXYsIE1UX1dGRE1BMF9QQ0lFMV9CVVNZX0VOQSwNCisJCSBNVF9XRkRNQTBfUENJRTFf QlVTWV9FTkFfVFhfRklGTzAgfA0KKwkJIE1UX1dGRE1BMF9QQ0lFMV9CVVNZX0VOQV9UWF9GSUZP MSB8DQorCQkgTVRfV0ZETUEwX1BDSUUxX0JVU1lfRU5BX1JYX0ZJRk8pOw0KKw0KKwltdDc2X3Nl dChkZXYsIE1UX1dGRE1BMV9QQ0lFMV9CVVNZX0VOQSwNCisJCSBNVF9XRkRNQTFfUENJRTFfQlVT WV9FTkFfVFhfRklGTzAgfA0KKwkJIE1UX1dGRE1BMV9QQ0lFMV9CVVNZX0VOQV9UWF9GSUZPMSB8 DQorCQkgTVRfV0ZETUExX1BDSUUxX0JVU1lfRU5BX1JYX0ZJRk8pOw0KKw0KKwltdDc2X3BvbGwo ZGV2LCBNVF9XRkRNQV9FWFRfQ1NSX0hJRl9NSVNDLA0KKwkJICBNVF9XRkRNQV9FWFRfQ1NSX0hJ Rl9NSVNDX0JVU1ksIDAsIDEwMDApOw0KKw0KKwkvKiBzZXQgV0ZETUEgVHgvUnggKi8NCisJbXQ3 Nl9zZXQoZGV2LCBNVF9XRkRNQTBfR0xPX0NGRywNCisJCSBNVF9XRkRNQTBfR0xPX0NGR19UWF9E TUFfRU4gfCBNVF9XRkRNQTBfR0xPX0NGR19SWF9ETUFfRU4pOw0KKwltdDc2X3NldChkZXYsIE1U X1dGRE1BMV9HTE9fQ0ZHLA0KKwkJIE1UX1dGRE1BMV9HTE9fQ0ZHX1RYX0RNQV9FTiB8IE1UX1dG RE1BMV9HTE9fQ0ZHX1JYX0RNQV9FTik7DQorDQorCS8qIGVuYWJsZSBpbnRlcnJ1cHRzIGZvciBU WC9SWCByaW5ncyAqLw0KKwltdDc5MTVfaXJxX2VuYWJsZShkZXYsIE1UX0lOVF9SWF9ET05FX0FM TCB8IE1UX0lOVF9UWF9ET05FX0FMTCB8DQorCQkJICBNVF9JTlRfTUNVX0NNRCk7DQorDQorCXJl dHVybiAwOw0KK30NCisNCit2b2lkIG10NzkxNV9kbWFfY2xlYW51cChzdHJ1Y3QgbXQ3OTE1X2Rl diAqZGV2KQ0KK3sNCisJLyogZGlzYWJsZSAqLw0KKwltdDc2X2NsZWFyKGRldiwgTVRfV0ZETUEw X0dMT19DRkcsDQorCQkgICBNVF9XRkRNQTBfR0xPX0NGR19UWF9ETUFfRU4gfA0KKwkJICAgTVRf V0ZETUEwX0dMT19DRkdfUlhfRE1BX0VOKTsNCisJbXQ3Nl9jbGVhcihkZXYsIE1UX1dGRE1BMV9H TE9fQ0ZHLA0KKwkJICAgTVRfV0ZETUExX0dMT19DRkdfVFhfRE1BX0VOIHwNCisJCSAgIE1UX1dG RE1BMV9HTE9fQ0ZHX1JYX0RNQV9FTik7DQorDQorCS8qIHJlc2V0ICovDQorCW10NzZfY2xlYXIo ZGV2LCBNVF9XRkRNQTFfUlNULA0KKwkJICAgTVRfV0ZETUExX1JTVF9ETUFTSERMX0FMTF9SU1Qg fA0KKwkJICAgTVRfV0ZETUExX1JTVF9MT0dJQ19SU1QpOw0KKw0KKwltdDc2X3NldChkZXYsIE1U X1dGRE1BMV9SU1QsDQorCQkgTVRfV0ZETUExX1JTVF9ETUFTSERMX0FMTF9SU1QgfA0KKwkJIE1U X1dGRE1BMV9SU1RfTE9HSUNfUlNUKTsNCisNCisJbXQ3Nl9jbGVhcihkZXYsIE1UX1dGRE1BMF9S U1QsDQorCQkgICBNVF9XRkRNQTBfUlNUX0RNQVNIRExfQUxMX1JTVCB8DQorCQkgICBNVF9XRkRN QTBfUlNUX0xPR0lDX1JTVCk7DQorDQorCW10NzZfc2V0KGRldiwgTVRfV0ZETUEwX1JTVCwNCisJ CSBNVF9XRkRNQTBfUlNUX0RNQVNIRExfQUxMX1JTVCB8DQorCQkgTVRfV0ZETUEwX1JTVF9MT0dJ Q19SU1QpOw0KKw0KKwl0YXNrbGV0X2tpbGwoJmRldi0+bXQ3Ni50eF90YXNrbGV0KTsNCisJbXQ3 Nl9kbWFfY2xlYW51cCgmZGV2LT5tdDc2KTsNCit9DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQv d2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvZWVwcm9tLmMgYi9kcml2ZXJzL25ldC93aXJl bGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9lZXByb20uYw0KbmV3IGZpbGUgbW9kZSAxMDA2NDQN CmluZGV4IDAwMDAwMDAwMDAwMC4uMjA5OWRkNDA1MzBmDQotLS0gL2Rldi9udWxsDQorKysgYi9k cml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9lZXByb20uYw0KQEAgLTAs MCArMSwxMjUgQEANCisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogSVNDDQorLyogQ29weXJp Z2h0IChDKSAyMDIwIE1lZGlhVGVrIEluYy4gKi8NCisNCisjaW5jbHVkZSAibXQ3OTE1LmgiDQor I2luY2x1ZGUgImVlcHJvbS5oIg0KKw0KK3N0YXRpYyBpbmxpbmUgYm9vbCBtdDc5MTVfZWZ1c2Vf dmFsaWQodTggdmFsKQ0KK3sNCisJcmV0dXJuICEodmFsID09IDB4ZmYpOw0KK30NCisNCit1MzIg bXQ3OTE1X2VlcHJvbV9yZWFkKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBvZmZzZXQpDQor ew0KKwl1OCAqZGF0YSA9IGRldi0+bXQ3Ni5lZXByb20uZGF0YTsNCisNCisJaWYgKCFtdDc5MTVf ZWZ1c2VfdmFsaWQoZGF0YVtvZmZzZXRdKSkNCisJCW10NzkxNV9tY3VfZ2V0X2VlcHJvbShkZXYs IG9mZnNldCk7DQorDQorCXJldHVybiBkYXRhW29mZnNldF07DQorfQ0KKw0KK3N0YXRpYyBpbnQg bXQ3OTE1X2VlcHJvbV9sb2FkKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlpbnQgcmV0 Ow0KKw0KKwlyZXQgPSBtdDc2X2VlcHJvbV9pbml0KCZkZXYtPm10NzYsIE1UNzkxNV9FRVBST01f U0laRSk7DQorCWlmIChyZXQgPCAwKQ0KKwkJcmV0dXJuIHJldDsNCisNCisJbWVtc2V0KGRldi0+ bXQ3Ni5lZXByb20uZGF0YSwgLTEsIE1UNzkxNV9FRVBST01fU0laRSk7DQorDQorCXJldHVybiAw Ow0KK30NCisNCitzdGF0aWMgaW50IG10NzkxNV9jaGVja19lZXByb20oc3RydWN0IG10NzkxNV9k ZXYgKmRldikNCit7DQorCXUxNiB2YWw7DQorCXU4ICplZXByb20gPSBkZXYtPm10NzYuZWVwcm9t LmRhdGE7DQorDQorCW10NzkxNV9lZXByb21fcmVhZChkZXYsIDApOw0KKwl2YWwgPSBnZXRfdW5h bGlnbmVkX2xlMTYoZWVwcm9tKTsNCisNCisJc3dpdGNoICh2YWwpIHsNCisJY2FzZSAweDc5MTU6 DQorCQlyZXR1cm4gMDsNCisJZGVmYXVsdDoNCisJCXJldHVybiAtRUlOVkFMOw0KKwl9DQorfQ0K Kw0KK3N0YXRpYyB2b2lkIG10NzkxNV9lZXByb21fcGFyc2VfaHdfY2FwKHN0cnVjdCBtdDc5MTVf ZGV2ICpkZXYpDQorew0KKwl1OCAqZWVwcm9tID0gZGV2LT5tdDc2LmVlcHJvbS5kYXRhOw0KKwl1 OCB0eF9tYXNrLCBtYXhfbnNzID0gNDsNCisJdTMyIHZhbCA9IG10NzkxNV9lZXByb21fcmVhZChk ZXYsIE1UX0VFX1dJRklfQ09ORik7DQorDQorCXZhbCA9IEZJRUxEX0dFVChNVF9FRV9XSUZJX0NP TkZfQkFORF9TRUwsIHZhbCk7DQorCXN3aXRjaCAodmFsKSB7DQorCWNhc2UgTVRfRUVfNUdIWjoN CisJCWRldi0+bXQ3Ni5jYXAuaGFzXzVnaHogPSB0cnVlOw0KKwkJYnJlYWs7DQorCWNhc2UgTVRf RUVfMkdIWjoNCisJCWRldi0+bXQ3Ni5jYXAuaGFzXzJnaHogPSB0cnVlOw0KKwkJYnJlYWs7DQor CWRlZmF1bHQ6DQorCQlkZXYtPm10NzYuY2FwLmhhc18yZ2h6ID0gdHJ1ZTsNCisJCWRldi0+bXQ3 Ni5jYXAuaGFzXzVnaHogPSB0cnVlOw0KKwkJYnJlYWs7DQorCX0NCisNCisJLyogcmVhZCB0eCBt YXNrIGZyb20gZWVwcm9tICovDQorCXR4X21hc2sgPSAgRklFTERfR0VUKE1UX0VFX1dJRklfQ09O Rl9UWF9NQVNLLA0KKwkJCSAgICAgZWVwcm9tW01UX0VFX1dJRklfQ09ORl0pOw0KKwlpZiAoIXR4 X21hc2sgfHwgdHhfbWFzayA+IG1heF9uc3MpDQorCQl0eF9tYXNrID0gbWF4X25zczsNCisNCisJ ZGV2LT5jaGFpbm1hc2sgPSBCSVQodHhfbWFzaykgLSAxOw0KKwlkZXYtPm1waHkuYW50ZW5uYV9t YXNrID0gZGV2LT5jaGFpbm1hc2s7DQorCWRldi0+cGh5LmNoYWlubWFzayA9IGRldi0+Y2hhaW5t YXNrOw0KK30NCisNCitpbnQgbXQ3OTE1X2VlcHJvbV9pbml0KHN0cnVjdCBtdDc5MTVfZGV2ICpk ZXYpDQorew0KKwlpbnQgcmV0Ow0KKw0KKwlyZXQgPSBtdDc5MTVfZWVwcm9tX2xvYWQoZGV2KTsN CisJaWYgKHJldCA8IDApDQorCQlyZXR1cm4gcmV0Ow0KKw0KKwlyZXQgPSBtdDc5MTVfY2hlY2tf ZWVwcm9tKGRldik7DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0Ow0KKw0KKwltdDc5MTVfZWVw cm9tX3BhcnNlX2h3X2NhcChkZXYpOw0KKwltZW1jcHkoZGV2LT5tdDc2Lm1hY2FkZHIsIGRldi0+ bXQ3Ni5lZXByb20uZGF0YSArIE1UX0VFX01BQ19BRERSLA0KKwkgICAgICAgRVRIX0FMRU4pOw0K Kw0KKwltdDc2X2VlcHJvbV9vdmVycmlkZSgmZGV2LT5tdDc2KTsNCisNCisJcmV0dXJuIDA7DQor fQ0KKw0KK2ludCBtdDc5MTVfZWVwcm9tX2dldF90YXJnZXRfcG93ZXIoc3RydWN0IG10NzkxNV9k ZXYgKmRldiwNCisJCQkJICAgc3RydWN0IGllZWU4MDIxMV9jaGFubmVsICpjaGFuLA0KKwkJCQkg ICB1OCBjaGFpbl9pZHgpDQorew0KKwlpbnQgaW5kZXg7DQorCWJvb2wgdHNzaV9vbjsNCisNCisJ aWYgKGNoYWluX2lkeCA+IDMpDQorCQlyZXR1cm4gLUVJTlZBTDsNCisNCisJdHNzaV9vbiA9IG10 NzkxNV90c3NpX2VuYWJsZWQoZGV2LCBjaGFuLT5iYW5kKTsNCisNCisJaWYgKGNoYW4tPmJhbmQg PT0gTkw4MDIxMV9CQU5EXzJHSFopIHsNCisJCWluZGV4ID0gTVRfRUVfVFgwX1BPV0VSXzJHICsg Y2hhaW5faWR4ICogMyArICF0c3NpX29uOw0KKwl9IGVsc2Ugew0KKwkJaW50IGdyb3VwID0gdHNz aV9vbiA/DQorCQkJICAgIG10NzkxNV9nZXRfY2hhbm5lbF9ncm91cChjaGFuLT5od192YWx1ZSkg OiA4Ow0KKw0KKwkJaW5kZXggPSBNVF9FRV9UWDBfUE9XRVJfNUcgKyBjaGFpbl9pZHggKiAxMiAr IGdyb3VwOw0KKwl9DQorDQorCXJldHVybiBtdDc5MTVfZWVwcm9tX3JlYWQoZGV2LCBpbmRleCk7 DQorfQ0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3 OTE1L2VlcHJvbS5oIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUv ZWVwcm9tLmgNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAwMDAwMDAwMDAwMDAuLjMwZmM2 MDdlNDY2ZA0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0 ZWsvbXQ3Ni9tdDc5MTUvZWVwcm9tLmgNCkBAIC0wLDAgKzEsNzggQEANCisvKiBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogSVNDICovDQorLyogQ29weXJpZ2h0IChDKSAyMDIwIE1lZGlhVGVrIElu Yy4gKi8NCisNCisjaWZuZGVmIF9fTVQ3OTE1X0VFUFJPTV9IDQorI2RlZmluZSBfX01UNzkxNV9F RVBST01fSA0KKw0KKyNpbmNsdWRlICJtdDc5MTUuaCINCisNCitzdHJ1Y3QgY2FsX2RhdGEgew0K Kwl1OCBjb3VudDsNCisJdTE2IG9mZnNldFs2MF07DQorfTsNCisNCitlbnVtIG10NzkxNV9lZXBy b21fZmllbGQgew0KKwlNVF9FRV9DSElQX0lEID0JCTB4MDAwLA0KKwlNVF9FRV9WRVJTSU9OID0J CTB4MDAyLA0KKwlNVF9FRV9NQUNfQUREUiA9CTB4MDA0LA0KKwlNVF9FRV9ERElFX0ZUX1ZFUlNJ T04gPQkweDA1MCwNCisJTVRfRUVfV0lGSV9DT05GID0JMHgxOTAsDQorCU1UX0VFX1RYMF9QT1dF Ul8yRyA9CTB4MmZjLA0KKwlNVF9FRV9UWDBfUE9XRVJfNUcgPQkweDM0YiwNCisJTVRfRUVfQURJ RV9GVF9WRVJTSU9OID0JMHg5YTAsDQorDQorCV9fTVRfRUVfTUFYID0JCTB4ZTAwDQorfTsNCisN CisjZGVmaW5lIE1UX0VFX1dJRklfQ09ORl9UWF9NQVNLCQkJR0VOTUFTSygyLCAwKQ0KKyNkZWZp bmUgTVRfRUVfV0lGSV9DT05GX0JBTkRfU0VMCQlHRU5NQVNLKDcsIDYpDQorI2RlZmluZSBNVF9F RV9XSUZJX0NPTkZfVFNTSTBfMkcJCUJJVCgwKQ0KKyNkZWZpbmUgTVRfRUVfV0lGSV9DT05GX1RT U0kwXzVHCQlCSVQoMikNCisjZGVmaW5lIE1UX0VFX1dJRklfQ09ORl9UU1NJMV81RwkJQklUKDQp DQorDQorZW51bSBtdDc5MTVfZWVwcm9tX2JhbmQgew0KKwlNVF9FRV9EVUFMX0JBTkQsDQorCU1U X0VFXzVHSFosDQorCU1UX0VFXzJHSFosDQorCU1UX0VFX0RCREMsDQorfTsNCisNCitzdHJ1Y3Qg c2t1X2dyb3VwIHsNCisJdTggbGVuOw0KKwl1MTYgb2Zmc2V0WzJdOw0KKwljb25zdCB1OCAqZGVs dGFfbWFwOw0KK307DQorDQorc3RhdGljIGlubGluZSBpbnQNCittdDc5MTVfZ2V0X2NoYW5uZWxf Z3JvdXAoaW50IGNoYW5uZWwpDQorew0KKwlpZiAoY2hhbm5lbCA+PSAxODQgJiYgY2hhbm5lbCA8 PSAxOTYpDQorCQlyZXR1cm4gMDsNCisJaWYgKGNoYW5uZWwgPD0gNDgpDQorCQlyZXR1cm4gMTsN CisJaWYgKGNoYW5uZWwgPD0gNjQpDQorCQlyZXR1cm4gMjsNCisJaWYgKGNoYW5uZWwgPD0gOTYp DQorCQlyZXR1cm4gMzsNCisJaWYgKGNoYW5uZWwgPD0gMTEyKQ0KKwkJcmV0dXJuIDQ7DQorCWlm IChjaGFubmVsIDw9IDEyOCkNCisJCXJldHVybiA1Ow0KKwlpZiAoY2hhbm5lbCA8PSAxNDQpDQor CQlyZXR1cm4gNjsNCisJcmV0dXJuIDc7DQorfQ0KKw0KK3N0YXRpYyBpbmxpbmUgYm9vbA0KK210 NzkxNV90c3NpX2VuYWJsZWQoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgZW51bSBubDgwMjExX2Jh bmQgYmFuZCkNCit7DQorCXU4ICplZXAgPSBkZXYtPm10NzYuZWVwcm9tLmRhdGE7DQorDQorCS8q IFRPRE86IERCREMgKi8NCisJaWYgKGJhbmQgPT0gTkw4MDIxMV9CQU5EXzVHSFopDQorCQlyZXR1 cm4gZWVwW01UX0VFX1dJRklfQ09ORiArIDddICYgTVRfRUVfV0lGSV9DT05GX1RTU0kwXzVHOw0K KwllbHNlDQorCQlyZXR1cm4gZWVwW01UX0VFX1dJRklfQ09ORiArIDddICYgTVRfRUVfV0lGSV9D T05GX1RTU0kwXzJHOw0KK30NCisNCisjZW5kaWYNCmRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93 aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9pbml0LmMgYi9kcml2ZXJzL25ldC93aXJlbGVz cy9tZWRpYXRlay9tdDc2L210NzkxNS9pbml0LmMNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRl eCAwMDAwMDAwMDAwMDAuLjBlM2U2YjE1NDdiMw0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvaW5pdC5jDQpAQCAtMCwwICsxLDM5 MiBAQA0KKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBJU0MNCisvKiBDb3B5cmlnaHQgKEMp IDIwMjAgTWVkaWFUZWsgSW5jLiAqLw0KKw0KKyNpbmNsdWRlIDxsaW51eC9ldGhlcmRldmljZS5o Pg0KKyNpbmNsdWRlICJtdDc5MTUuaCINCisjaW5jbHVkZSAibWFjLmgiDQorI2luY2x1ZGUgImVl cHJvbS5oIg0KKw0KK3N0YXRpYyB2b2lkDQorbXQ3OTE1X21hY19pbml0X2JhbmQoc3RydWN0IG10 NzkxNV9kZXYgKmRldiwgdTggYmFuZCkNCit7DQorCXUzMiBtYXNrLCBzZXQ7DQorDQorCW10NzZf cm13X2ZpZWxkKGRldiwgTVRfVE1BQ19DVENSMChiYW5kKSwNCisJCSAgICAgICBNVF9UTUFDX0NU Q1IwX0lOU19ERExNVF9SRUZUSU1FLCAweDNmKTsNCisJbXQ3Nl9zZXQoZGV2LCBNVF9UTUFDX0NU Q1IwKGJhbmQpLA0KKwkJIE1UX1RNQUNfQ1RDUjBfSU5TX0RETE1UX1ZIVF9TTVBEVV9FTiB8DQor CQkgTVRfVE1BQ19DVENSMF9JTlNfRERMTVRfRU4pOw0KKw0KKwltYXNrID0gTVRfTURQX1JDRlIw X01DVV9SWF9NR01UIHwNCisJICAgICAgIE1UX01EUF9SQ0ZSMF9NQ1VfUlhfQ1RMX05PTl9CQVIg fA0KKwkgICAgICAgTVRfTURQX1JDRlIwX01DVV9SWF9DVExfQkFSOw0KKwlzZXQgPSBGSUVMRF9Q UkVQKE1UX01EUF9SQ0ZSMF9NQ1VfUlhfTUdNVCwgTVRfTURQX1RPX0hJRikgfA0KKwkgICAgICBG SUVMRF9QUkVQKE1UX01EUF9SQ0ZSMF9NQ1VfUlhfQ1RMX05PTl9CQVIsIE1UX01EUF9UT19ISUYp IHwNCisJICAgICAgRklFTERfUFJFUChNVF9NRFBfUkNGUjBfTUNVX1JYX0NUTF9CQVIsIE1UX01E UF9UT19ISUYpOw0KKwltdDc2X3JtdyhkZXYsIE1UX01EUF9CTlJDRlIwKGJhbmQpLCBtYXNrLCBz ZXQpOw0KKw0KKwltYXNrID0gTVRfTURQX1JDRlIxX01DVV9SWF9CWVBBU1MgfA0KKwkgICAgICAg TVRfTURQX1JDRlIxX1JYX0RST1BQRURfVUNBU1QgfA0KKwkgICAgICAgTVRfTURQX1JDRlIxX1JY X0RST1BQRURfTUNBU1Q7DQorCXNldCA9IEZJRUxEX1BSRVAoTVRfTURQX1JDRlIxX01DVV9SWF9C WVBBU1MsIE1UX01EUF9UT19ISUYpIHwNCisJICAgICAgRklFTERfUFJFUChNVF9NRFBfUkNGUjFf UlhfRFJPUFBFRF9VQ0FTVCwgTVRfTURQX1RPX0hJRikgfA0KKwkgICAgICBGSUVMRF9QUkVQKE1U X01EUF9SQ0ZSMV9SWF9EUk9QUEVEX01DQVNULCBNVF9NRFBfVE9fSElGKTsNCisJbXQ3Nl9ybXco ZGV2LCBNVF9NRFBfQk5SQ0ZSMShiYW5kKSwgbWFzaywgc2V0KTsNCisNCisJbXQ3Nl9zZXQoZGV2 LCBNVF9XRl9STUFDX01JQl9USU1FMChiYW5kKSwgTVRfV0ZfUk1BQ19NSUJfUlhUSU1FX0VOKTsN CisJbXQ3Nl9zZXQoZGV2LCBNVF9XRl9STUFDX01JQl9BSVJUSU1FMChiYW5kKSwgTVRfV0ZfUk1B Q19NSUJfUlhUSU1FX0VOKTsNCit9DQorDQorc3RhdGljIHZvaWQgbXQ3OTE1X21hY19pbml0KHN0 cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlpbnQgaTsNCisNCisJbXQ3Nl9ybXdfZmllbGQo ZGV2LCBNVF9ETUFfRENSMCwgTVRfRE1BX0RDUjBfTUFYX1JYX0xFTiwgMTUzNik7DQorCW10NzZf cm13X2ZpZWxkKGRldiwgTVRfTURQX0RDUjEsIE1UX01EUF9EQ1IxX01BWF9SWF9MRU4sIDE1MzYp Ow0KKwkvKiBlbmFibGUgcnggcmF0ZSByZXBvcnQgKi8NCisJbXQ3Nl9zZXQoZGV2LCBNVF9ETUFf RENSMCwgTVRfRE1BX0RDUjBfUlhEX0c1X0VOKTsNCisJLyogZGlzYWJsZSBoYXJkd2FyZSBkZS1h Z2cgKi8NCisJbXQ3Nl9jbGVhcihkZXYsIE1UX01EUF9EQ1IwLCBNVF9NRFBfRENSMF9EQU1TRFVf RU4pOw0KKw0KKwlmb3IgKGkgPSAwOyBpIDwgTVQ3OTE1X1dUQkxfU0laRTsgaSsrKQ0KKwkJbXQ3 OTE1X21hY193dGJsX3VwZGF0ZShkZXYsIGksDQorCQkJCSAgICAgICBNVF9XVEJMX1VQREFURV9B RE1fQ09VTlRfQ0xFQVIpOw0KKw0KKwltdDc5MTVfbWFjX2luaXRfYmFuZChkZXYsIDApOw0KKwlt dDc5MTVfbWFjX2luaXRfYmFuZChkZXYsIDEpOw0KKwltdDc5MTVfbWN1X3NldF9ydHNfdGhyZXNo KCZkZXYtPnBoeSwgMHg5MmIpOw0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9pbml0X3R4 cG93ZXJfYmFuZChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LA0KKwkJCSBzdHJ1Y3QgaWVlZTgwMjEx X3N1cHBvcnRlZF9iYW5kICpzYmFuZCkNCit7DQorCWludCBpLCBuX2NoYWlucyA9IGh3ZWlnaHQ4 KGRldi0+bXBoeS5hbnRlbm5hX21hc2spOw0KKw0KKwlmb3IgKGkgPSAwOyBpIDwgc2JhbmQtPm5f Y2hhbm5lbHM7IGkrKykgew0KKwkJc3RydWN0IGllZWU4MDIxMV9jaGFubmVsICpjaGFuID0gJnNi YW5kLT5jaGFubmVsc1tpXTsNCisJCXUzMiB0YXJnZXRfcG93ZXIgPSAwOw0KKwkJaW50IGo7DQor DQorCQlmb3IgKGogPSAwOyBqIDwgbl9jaGFpbnM7IGorKykgew0KKwkJCXUzMiB2YWw7DQorDQor CQkJdmFsID0gbXQ3OTE1X2VlcHJvbV9nZXRfdGFyZ2V0X3Bvd2VyKGRldiwgY2hhbiwgaik7DQor CQkJdGFyZ2V0X3Bvd2VyID0gbWF4KHRhcmdldF9wb3dlciwgdmFsKTsNCisJCX0NCisNCisJCWNo YW4tPm1heF9wb3dlciA9IG1pbl90KGludCwgY2hhbi0+bWF4X3JlZ19wb3dlciwNCisJCQkJCXRh cmdldF9wb3dlciAvIDIpOw0KKwkJY2hhbi0+b3JpZ19tcHdyID0gdGFyZ2V0X3Bvd2VyIC8gMjsN CisJfQ0KK30NCisNCitzdGF0aWMgdm9pZCBtdDc5MTVfaW5pdF90eHBvd2VyKHN0cnVjdCBtdDc5 MTVfZGV2ICpkZXYpDQorew0KKwltdDc5MTVfaW5pdF90eHBvd2VyX2JhbmQoZGV2LCAmZGV2LT5t cGh5LnNiYW5kXzJnLnNiYW5kKTsNCisJbXQ3OTE1X2luaXRfdHhwb3dlcl9iYW5kKGRldiwgJmRl di0+bXBoeS5zYmFuZF81Zy5zYmFuZCk7DQorfQ0KKw0KK3N0YXRpYyB2b2lkIG10NzkxNV9pbml0 X3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KK3sNCisJc3RydWN0IG10NzkxNV9kZXYg KmRldiA9IGNvbnRhaW5lcl9vZih3b3JrLCBzdHJ1Y3QgbXQ3OTE1X2RldiwNCisJCQkJIGluaXRf d29yayk7DQorDQorCW10NzkxNV9tY3Vfc2V0X2VlcHJvbShkZXYpOw0KKwltdDc5MTVfbWFjX2lu aXQoZGV2KTsNCisJbXQ3OTE1X2luaXRfdHhwb3dlcihkZXYpOw0KK30NCisNCitzdGF0aWMgaW50 IG10NzkxNV9pbml0X2hhcmR3YXJlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlpbnQg cmV0LCBpZHg7DQorDQorCW10NzZfd3IoZGV2LCBNVF9JTlRfU09VUkNFX0NTUiwgfjApOw0KKw0K KwlJTklUX1dPUksoJmRldi0+aW5pdF93b3JrLCBtdDc5MTVfaW5pdF93b3JrKTsNCisJc3Bpbl9s b2NrX2luaXQoJmRldi0+dG9rZW5fbG9jayk7DQorCWlkcl9pbml0KCZkZXYtPnRva2VuKTsNCisN CisJcmV0ID0gbXQ3OTE1X2RtYV9pbml0KGRldik7DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0 Ow0KKw0KKwlzZXRfYml0KE1UNzZfU1RBVEVfSU5JVElBTElaRUQsICZkZXYtPm1waHkuc3RhdGUp Ow0KKw0KKwlyZXQgPSBtdDc5MTVfbWN1X2luaXQoZGV2KTsNCisJaWYgKHJldCkNCisJCXJldHVy biByZXQ7DQorDQorCXJldCA9IG10NzkxNV9lZXByb21faW5pdChkZXYpOw0KKwlpZiAocmV0IDwg MCkNCisJCXJldHVybiByZXQ7DQorDQorCS8qIEJlYWNvbiBhbmQgbWdtdCBmcmFtZXMgc2hvdWxk IG9jY3VweSB3Y2lkIDAgKi8NCisJaWR4ID0gbXQ3Nl93Y2lkX2FsbG9jKGRldi0+bXQ3Ni53Y2lk X21hc2ssIE1UNzkxNV9XVEJMX1NUQSAtIDEpOw0KKwlpZiAoaWR4KQ0KKwkJcmV0dXJuIC1FTk9T UEM7DQorDQorCWRldi0+bXQ3Ni5nbG9iYWxfd2NpZC5pZHggPSBpZHg7DQorCWRldi0+bXQ3Ni5n bG9iYWxfd2NpZC5od19rZXlfaWR4ID0gLTE7DQorCWRldi0+bXQ3Ni5nbG9iYWxfd2NpZC50eF9p bmZvIHw9IE1UX1dDSURfVFhfSU5GT19TRVQ7DQorCXJjdV9hc3NpZ25fcG9pbnRlcihkZXYtPm10 NzYud2NpZFtpZHhdLCAmZGV2LT5tdDc2Lmdsb2JhbF93Y2lkKTsNCisNCisJcmV0dXJuIDA7DQor fQ0KKw0KKyNkZWZpbmUgQ0NLX1JBVEUoX2lkeCwgX3JhdGUpIHsJCQkJCQlcDQorCS5iaXRyYXRl ID0gX3JhdGUsCQkJCQkJXA0KKwkuZmxhZ3MgPSBJRUVFODAyMTFfUkFURV9TSE9SVF9QUkVBTUJM RSwJCQkJXA0KKwkuaHdfdmFsdWUgPSAoTVRfUEhZX1RZUEVfQ0NLIDw8IDgpIHwgKF9pZHgpLAkJ CVwNCisJLmh3X3ZhbHVlX3Nob3J0ID0gKE1UX1BIWV9UWVBFX0NDSyA8PCA4KSB8ICg0ICsgKF9p ZHgpKSwJXA0KK30NCisNCisjZGVmaW5lIE9GRE1fUkFURShfaWR4LCBfcmF0ZSkgewkJCQkJXA0K KwkuYml0cmF0ZSA9IF9yYXRlLAkJCQkJCVwNCisJLmh3X3ZhbHVlID0gKE1UX1BIWV9UWVBFX09G RE0gPDwgOCkgfCAoX2lkeCksCQkJXA0KKwkuaHdfdmFsdWVfc2hvcnQgPSAoTVRfUEhZX1RZUEVf T0ZETSA8PCA4KSB8IChfaWR4KSwJCVwNCit9DQorDQorc3RhdGljIHN0cnVjdCBpZWVlODAyMTFf cmF0ZSBtdDc5MTVfcmF0ZXNbXSA9IHsNCisJQ0NLX1JBVEUoMCwgMTApLA0KKwlDQ0tfUkFURSgx LCAyMCksDQorCUNDS19SQVRFKDIsIDU1KSwNCisJQ0NLX1JBVEUoMywgMTEwKSwNCisJT0ZETV9S QVRFKDExLCA2MCksDQorCU9GRE1fUkFURSgxNSwgOTApLA0KKwlPRkRNX1JBVEUoMTAsIDEyMCks DQorCU9GRE1fUkFURSgxNCwgMTgwKSwNCisJT0ZETV9SQVRFKDksICAyNDApLA0KKwlPRkRNX1JB VEUoMTMsIDM2MCksDQorCU9GRE1fUkFURSg4LCAgNDgwKSwNCisJT0ZETV9SQVRFKDEyLCA1NDAp LA0KK307DQorDQorc3RhdGljIGNvbnN0IHN0cnVjdCBpZWVlODAyMTFfaWZhY2VfbGltaXQgaWZf bGltaXRzW10gPSB7DQorCXsNCisJCS5tYXggPSAxLA0KKwkJLnR5cGVzID0gQklUKE5MODAyMTFf SUZUWVBFX0FESE9DKQ0KKwl9LCB7DQorCQkubWF4ID0gTVQ3OTE1X01BWF9JTlRFUkZBQ0VTLA0K KwkJLnR5cGVzID0gQklUKE5MODAyMTFfSUZUWVBFX0FQKSB8DQorI2lmZGVmIENPTkZJR19NQUM4 MDIxMV9NRVNIDQorCQkJIEJJVChOTDgwMjExX0lGVFlQRV9NRVNIX1BPSU5UKSB8DQorI2VuZGlm DQorCQkJIEJJVChOTDgwMjExX0lGVFlQRV9TVEFUSU9OKQ0KKwl9DQorfTsNCisNCitzdGF0aWMg Y29uc3Qgc3RydWN0IGllZWU4MDIxMV9pZmFjZV9jb21iaW5hdGlvbiBpZl9jb21iW10gPSB7DQor CXsNCisJCS5saW1pdHMgPSBpZl9saW1pdHMsDQorCQkubl9saW1pdHMgPSBBUlJBWV9TSVpFKGlm X2xpbWl0cyksDQorCQkubWF4X2ludGVyZmFjZXMgPSA0LA0KKwkJLm51bV9kaWZmZXJlbnRfY2hh bm5lbHMgPSAxLA0KKwkJLmJlYWNvbl9pbnRfaW5mcmFfbWF0Y2ggPSB0cnVlLA0KKwkJLnJhZGFy X2RldGVjdF93aWR0aHMgPSBCSVQoTkw4MDIxMV9DSEFOX1dJRFRIXzIwX05PSFQpIHwNCisJCQkJ ICAgICAgIEJJVChOTDgwMjExX0NIQU5fV0lEVEhfMjApIHwNCisJCQkJICAgICAgIEJJVChOTDgw MjExX0NIQU5fV0lEVEhfNDApIHwNCisJCQkJICAgICAgIEJJVChOTDgwMjExX0NIQU5fV0lEVEhf ODApIHwNCisJCQkJICAgICAgIEJJVChOTDgwMjExX0NIQU5fV0lEVEhfMTYwKSB8DQorCQkJCSAg ICAgICBCSVQoTkw4MDIxMV9DSEFOX1dJRFRIXzgwUDgwKSwNCisJfQ0KK307DQorDQorc3RhdGlj IHZvaWQNCittdDc5MTVfcmVnZF9ub3RpZmllcihzdHJ1Y3Qgd2lwaHkgKndpcGh5LA0KKwkJICAg ICBzdHJ1Y3QgcmVndWxhdG9yeV9yZXF1ZXN0ICpyZXF1ZXN0KQ0KK3sNCisJc3RydWN0IGllZWU4 MDIxMV9odyAqaHcgPSB3aXBoeV90b19pZWVlODAyMTFfaHcod2lwaHkpOw0KKwlzdHJ1Y3QgbXQ3 OTE1X2RldiAqZGV2ID0gbXQ3OTE1X2h3X2Rldihodyk7DQorCXN0cnVjdCBtdDc2X3BoeSAqbXBo eSA9IGh3LT5wcml2Ow0KKwlzdHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5ID0gbXBoeS0+cHJpdjsNCisJ c3RydWN0IGNmZzgwMjExX2NoYW5fZGVmICpjaGFuZGVmID0gJm1waHktPmNoYW5kZWY7DQorDQor CWRldi0+bXQ3Ni5yZWdpb24gPSByZXF1ZXN0LT5kZnNfcmVnaW9uOw0KKw0KKwlpZiAoIShjaGFu ZGVmLT5jaGFuLT5mbGFncyAmIElFRUU4MDIxMV9DSEFOX1JBREFSKSkNCisJCXJldHVybjsNCisN CisJbXQ3OTE1X2Rmc19pbml0X3JhZGFyX2RldGVjdG9yKHBoeSk7DQorfQ0KKw0KK3N0YXRpYyB2 b2lkDQorbXQ3OTE1X2luaXRfd2lwaHkoc3RydWN0IGllZWU4MDIxMV9odyAqaHcpDQorew0KKwlz dHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5ID0gbXQ3OTE1X2h3X3BoeShodyk7DQorCXN0cnVjdCB3aXBo eSAqd2lwaHkgPSBody0+d2lwaHk7DQorDQorCWh3LT5xdWV1ZXMgPSA0Ow0KKwlody0+bWF4X3J4 X2FnZ3JlZ2F0aW9uX3N1YmZyYW1lcyA9IElFRUU4MDIxMV9NQVhfQU1QRFVfQlVGOw0KKwlody0+ bWF4X3R4X2FnZ3JlZ2F0aW9uX3N1YmZyYW1lcyA9IElFRUU4MDIxMV9NQVhfQU1QRFVfQlVGOw0K Kw0KKwlwaHktPnNsb3R0aW1lID0gOTsNCisNCisJaHctPnN0YV9kYXRhX3NpemUgPSBzaXplb2Yo c3RydWN0IG10NzkxNV9zdGEpOw0KKwlody0+dmlmX2RhdGFfc2l6ZSA9IHNpemVvZihzdHJ1Y3Qg bXQ3OTE1X3ZpZik7DQorDQorCXdpcGh5LT5pZmFjZV9jb21iaW5hdGlvbnMgPSBpZl9jb21iOw0K Kwl3aXBoeS0+bl9pZmFjZV9jb21iaW5hdGlvbnMgPSBBUlJBWV9TSVpFKGlmX2NvbWIpOw0KKwl3 aXBoeS0+cmVnX25vdGlmaWVyID0gbXQ3OTE1X3JlZ2Rfbm90aWZpZXI7DQorCXdpcGh5LT5mbGFn cyB8PSBXSVBIWV9GTEFHX0hBU19DSEFOTkVMX1NXSVRDSDsNCisNCisJd2lwaHlfZXh0X2ZlYXR1 cmVfc2V0KHdpcGh5LCBOTDgwMjExX0VYVF9GRUFUVVJFX1ZIVF9JQlNTKTsNCisNCisJaWVlZTgw MjExX2h3X3NldChodywgSEFTX1JBVEVfQ09OVFJPTCk7DQorDQorCWh3LT5tYXhfdHhfZnJhZ21l bnRzID0gNDsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfY2FwX2RiZGNfZW5hYmxlKHN0 cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlkZXYtPm1waHkuc2JhbmRfNWcuc2JhbmQudmh0 X2NhcC5jYXAgJj0NCisJCQl+KElFRUU4MDIxMV9WSFRfQ0FQX1NIT1JUX0dJXzE2MCB8DQorCQkJ ICBJRUVFODAyMTFfVkhUX0NBUF9TVVBQX0NIQU5fV0lEVEhfMTYwXzgwUExVUzgwTUhaKTsNCisN CisJaWYgKGRldi0+Y2hhaW5tYXNrID09IDB4ZikNCisJCWRldi0+bXBoeS5hbnRlbm5hX21hc2sg PSBkZXYtPmNoYWlubWFzayA+PiAyOw0KKwllbHNlDQorCQlkZXYtPm1waHkuYW50ZW5uYV9tYXNr ID0gZGV2LT5jaGFpbm1hc2sgPj4gMTsNCisNCisJZGV2LT5waHkuY2hhaW5tYXNrID0gZGV2LT5t cGh5LmFudGVubmFfbWFzazsNCisJZGV2LT5tcGh5Lmh3LT53aXBoeS0+YXZhaWxhYmxlX2FudGVu bmFzX3J4ID0gZGV2LT5waHkuY2hhaW5tYXNrOw0KKwlkZXYtPm1waHkuaHctPndpcGh5LT5hdmFp bGFibGVfYW50ZW5uYXNfdHggPSBkZXYtPnBoeS5jaGFpbm1hc2s7DQorDQorCW10NzZfc2V0X3N0 cmVhbV9jYXBzKCZkZXYtPm10NzYsIHRydWUpOw0KK30NCisNCitzdGF0aWMgdm9pZA0KK210Nzkx NV9jYXBfZGJkY19kaXNhYmxlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlkZXYtPm1w aHkuc2JhbmRfNWcuc2JhbmQudmh0X2NhcC5jYXAgfD0NCisJCQlJRUVFODAyMTFfVkhUX0NBUF9T SE9SVF9HSV8xNjAgfA0KKwkJCUlFRUU4MDIxMV9WSFRfQ0FQX1NVUFBfQ0hBTl9XSURUSF8xNjBf ODBQTFVTODBNSFo7DQorDQorCWRldi0+bXBoeS5hbnRlbm5hX21hc2sgPSBkZXYtPmNoYWlubWFz azsNCisJZGV2LT5waHkuY2hhaW5tYXNrID0gZGV2LT5jaGFpbm1hc2s7DQorCWRldi0+bXBoeS5o dy0+d2lwaHktPmF2YWlsYWJsZV9hbnRlbm5hc19yeCA9IGRldi0+Y2hhaW5tYXNrOw0KKwlkZXYt Pm1waHkuaHctPndpcGh5LT5hdmFpbGFibGVfYW50ZW5uYXNfdHggPSBkZXYtPmNoYWlubWFzazsN CisNCisJbXQ3Nl9zZXRfc3RyZWFtX2NhcHMoJmRldi0+bXQ3NiwgdHJ1ZSk7DQorfQ0KKw0KK2lu dCBtdDc5MTVfcmVnaXN0ZXJfZXh0X3BoeShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJ c3RydWN0IG10NzkxNV9waHkgKnBoeSA9IG10NzkxNV9leHRfcGh5KGRldik7DQorCXN0cnVjdCBt dDc2X3BoeSAqbXBoeTsNCisJaW50IHJldDsNCisJYm9vbCBib3VuZDsNCisNCisJYm91bmQgPSBt dDc5MTVfbDFfcnIoZGV2LCBNVF9IV19CT1VORCkgJiBCSVQoNSk7DQorCWlmICghYm91bmQpDQor CQlyZXR1cm4gLUVJTlZBTDsNCisNCisJaWYgKHRlc3RfYml0KE1UNzZfU1RBVEVfUlVOTklORywg JmRldi0+bXBoeS5zdGF0ZSkpDQorCQlyZXR1cm4gLUVJTlZBTDsNCisNCisJaWYgKHBoeSkNCisJ CXJldHVybiAwOw0KKw0KKwltdDc5MTVfY2FwX2RiZGNfZW5hYmxlKGRldik7DQorCW1waHkgPSBt dDc2X2FsbG9jX3BoeSgmZGV2LT5tdDc2LCBzaXplb2YoKnBoeSksICZtdDc5MTVfb3BzKTsNCisJ aWYgKCFtcGh5KQ0KKwkJcmV0dXJuIC1FTk9NRU07DQorDQorCXBoeSA9IG1waHktPnByaXY7DQor CXBoeS0+ZGV2ID0gZGV2Ow0KKwlwaHktPm10NzYgPSBtcGh5Ow0KKwlwaHktPmNoYWlubWFzayA9 IGRldi0+Y2hhaW5tYXNrICYgfmRldi0+cGh5LmNoYWlubWFzazsNCisJbXBoeS0+YW50ZW5uYV9t YXNrID0gQklUKGh3ZWlnaHQ4KHBoeS0+Y2hhaW5tYXNrKSkgLSAxOw0KKwltdDc5MTVfaW5pdF93 aXBoeShtcGh5LT5odyk7DQorDQorCS8qDQorCSAqIE1ha2UgdGhlIHNlY29uZGFyeSBQSFkgTUFD IGFkZHJlc3MgbG9jYWwgd2l0aG91dCBvdmVybGFwcGluZyB3aXRoDQorCSAqIHRoZSB1c3VhbCBN QUMgYWRkcmVzcyBhbGxvY2F0aW9uIHNjaGVtZSBvbiBtdWx0aXBsZSB2aXJ0dWFsIGludGVyZmFj ZXMNCisJICovDQorCW1waHktPmh3LT53aXBoeS0+cGVybV9hZGRyWzBdIHw9IDI7DQorCW1waHkt Pmh3LT53aXBoeS0+cGVybV9hZGRyWzBdIF49IEJJVCg3KTsNCisNCisJLyogVGhlIHNlY29uZCBp bnRlcmZhY2UgZG9lcyBub3QgZ2V0IGFueSBwYWNrZXRzIHVubGVzcyBpdCBoYXMgYSB2aWYgKi8N CisJaWVlZTgwMjExX2h3X3NldChtcGh5LT5odywgV0FOVF9NT05JVE9SX1ZJRik7DQorDQorCXJl dCA9IG10NzZfcmVnaXN0ZXJfcGh5KG1waHkpOw0KKwlpZiAocmV0KQ0KKwkJaWVlZTgwMjExX2Zy ZWVfaHcobXBoeS0+aHcpOw0KKw0KKwlyZXR1cm4gcmV0Ow0KK30NCisNCit2b2lkIG10NzkxNV91 bnJlZ2lzdGVyX2V4dF9waHkoc3RydWN0IG10NzkxNV9kZXYgKmRldikNCit7DQorCXN0cnVjdCBt dDc5MTVfcGh5ICpwaHkgPSBtdDc5MTVfZXh0X3BoeShkZXYpOw0KKwlzdHJ1Y3QgbXQ3Nl9waHkg Km1waHkgPSBkZXYtPm10NzYucGh5MjsNCisNCisJaWYgKCFwaHkpDQorCQlyZXR1cm47DQorDQor CW10NzkxNV9jYXBfZGJkY19kaXNhYmxlKGRldik7DQorCW10NzZfdW5yZWdpc3Rlcl9waHkobXBo eSk7DQorCWllZWU4MDIxMV9mcmVlX2h3KG1waHktPmh3KTsNCit9DQorDQoraW50IG10NzkxNV9y ZWdpc3Rlcl9kZXZpY2Uoc3RydWN0IG10NzkxNV9kZXYgKmRldikNCit7DQorCXN0cnVjdCBpZWVl ODAyMTFfaHcgKmh3ID0gbXQ3Nl9odyhkZXYpOw0KKwlpbnQgcmV0Ow0KKw0KKwlkZXYtPnBoeS5k ZXYgPSBkZXY7DQorCWRldi0+cGh5Lm10NzYgPSAmZGV2LT5tdDc2LnBoeTsNCisJZGV2LT5tdDc2 LnBoeS5wcml2ID0gJmRldi0+cGh5Ow0KKwlJTklUX0RFTEFZRURfV09SSygmZGV2LT5tdDc2Lm1h Y193b3JrLCBtdDc5MTVfbWFjX3dvcmspOw0KKwlJTklUX0xJU1RfSEVBRCgmZGV2LT5zdGFfcG9s bF9saXN0KTsNCisJc3Bpbl9sb2NrX2luaXQoJmRldi0+c3RhX3BvbGxfbG9jayk7DQorDQorCWlu aXRfd2FpdHF1ZXVlX2hlYWQoJmRldi0+cmVzZXRfd2FpdCk7DQorCUlOSVRfV09SSygmZGV2LT5y ZXNldF93b3JrLCBtdDc5MTVfbWFjX3Jlc2V0X3dvcmspOw0KKw0KKwlyZXQgPSBtdDc5MTVfaW5p dF9oYXJkd2FyZShkZXYpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsNCisNCisJbXQ3OTE1 X2luaXRfd2lwaHkoaHcpOw0KKwlkZXYtPm1waHkuc2JhbmRfMmcuc2JhbmQuaHRfY2FwLmNhcCB8 PSBJRUVFODAyMTFfSFRfQ0FQX0xEUENfQ09ESU5HOw0KKwlkZXYtPm1waHkuc2JhbmRfNWcuc2Jh bmQuaHRfY2FwLmNhcCB8PSBJRUVFODAyMTFfSFRfQ0FQX0xEUENfQ09ESU5HOw0KKwlkZXYtPm1w aHkuc2JhbmRfNWcuc2JhbmQudmh0X2NhcC5jYXAgfD0NCisJCQlJRUVFODAyMTFfVkhUX0NBUF9N QVhfTVBEVV9MRU5HVEhfNzk5MSB8DQorCQkJSUVFRTgwMjExX1ZIVF9DQVBfTUFYX0FfTVBEVV9M RU5HVEhfRVhQT05FTlRfTUFTSzsNCisJbXQ3OTE1X2NhcF9kYmRjX2Rpc2FibGUoZGV2KTsNCisJ ZGV2LT5waHkuZGZzX3N0YXRlID0gLTE7DQorDQorCXJldCA9IG10NzZfcmVnaXN0ZXJfZGV2aWNl KCZkZXYtPm10NzYsIHRydWUsIG10NzkxNV9yYXRlcywNCisJCQkJICAgQVJSQVlfU0laRShtdDc5 MTVfcmF0ZXMpKTsNCisJaWYgKHJldCkNCisJCXJldHVybiByZXQ7DQorDQorCWllZWU4MDIxMV9x dWV1ZV93b3JrKG10NzZfaHcoZGV2KSwgJmRldi0+aW5pdF93b3JrKTsNCisNCisJcmV0dXJuIG10 NzkxNV9pbml0X2RlYnVnZnMoZGV2KTsNCit9DQorDQordm9pZCBtdDc5MTVfdW5yZWdpc3Rlcl9k ZXZpY2Uoc3RydWN0IG10NzkxNV9kZXYgKmRldikNCit7DQorCXN0cnVjdCBtdDc2X3R4d2lfY2Fj aGUgKnR4d2k7DQorCWludCBpZDsNCisNCisJbXQ3OTE1X3VucmVnaXN0ZXJfZXh0X3BoeShkZXYp Ow0KKwltdDc2X3VucmVnaXN0ZXJfZGV2aWNlKCZkZXYtPm10NzYpOw0KKwltdDc5MTVfbWN1X2V4 aXQoZGV2KTsNCisJbXQ3OTE1X2RtYV9jbGVhbnVwKGRldik7DQorDQorCXNwaW5fbG9ja19iaCgm ZGV2LT50b2tlbl9sb2NrKTsNCisJaWRyX2Zvcl9lYWNoX2VudHJ5KCZkZXYtPnRva2VuLCB0eHdp LCBpZCkgew0KKwkJbXQ3OTE1X3R4cF9za2JfdW5tYXAoJmRldi0+bXQ3NiwgdHh3aSk7DQorCQlp ZiAodHh3aS0+c2tiKQ0KKwkJCWRldl9rZnJlZV9za2JfYW55KHR4d2ktPnNrYik7DQorCQltdDc2 X3B1dF90eHdpKCZkZXYtPm10NzYsIHR4d2kpOw0KKwl9DQorCXNwaW5fdW5sb2NrX2JoKCZkZXYt PnRva2VuX2xvY2spOw0KKwlpZHJfZGVzdHJveSgmZGV2LT50b2tlbik7DQorDQorCW10NzZfZnJl ZV9kZXZpY2UoJmRldi0+bXQ3Nik7DQorfQ0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVs ZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21hYy5jIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVk aWF0ZWsvbXQ3Ni9tdDc5MTUvbWFjLmMNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAwMDAw MDAwMDAwMDAuLjM0OTIxNWRkNDE3Yw0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVycy9uZXQv d2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFjLmMNCkBAIC0wLDAgKzEsMTMxMCBAQA0K Ky8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBJU0MNCisvKiBDb3B5cmlnaHQgKEMpIDIwMjAg TWVkaWFUZWsgSW5jLiAqLw0KKw0KKyNpbmNsdWRlIDxsaW51eC9ldGhlcmRldmljZS5oPg0KKyNp bmNsdWRlIDxsaW51eC90aW1la2VlcGluZy5oPg0KKyNpbmNsdWRlICJtdDc5MTUuaCINCisjaW5j bHVkZSAiLi4vZG1hLmgiDQorI2luY2x1ZGUgIm1hYy5oIg0KKw0KKyNkZWZpbmUgdG9fcnNzaShm aWVsZCwgcnh2KQkoKEZJRUxEX0dFVChmaWVsZCwgcnh2KSAtIDIyMCkgLyAyKQ0KKw0KK3N0YXRp YyBjb25zdCBzdHJ1Y3QgbXQ3OTE1X2Rmc19yYWRhcl9zcGVjIGV0c2lfcmFkYXJfc3BlY3MgPSB7 DQorCS5wdWxzZV90aCA9IHsgMTEwLCAtMTAsIC04MCwgNDAsIDUyMDAsIDEyOCwgNTIwMCB9LA0K KwkucmFkYXJfcGF0dGVybiA9IHsNCisJCVs1XSA9ICB7IDEsIDAsICA2LCAzMiwgMjgsIDAsICA5 OTAsIDUwMTAsIDE3LCAxLCAxIH0sDQorCQlbNl0gPSAgeyAxLCAwLCAgOSwgMzIsIDI4LCAwLCAg NjE1LCA1MDEwLCAyNywgMSwgMSB9LA0KKwkJWzddID0gIHsgMSwgMCwgMTUsIDMyLCAyOCwgMCwg IDI0MCwgIDQ0NSwgMjcsIDEsIDEgfSwNCisJCVs4XSA9ICB7IDEsIDAsIDEyLCAzMiwgMjgsIDAs ICAyNDAsICA1MTAsIDQyLCAxLCAxIH0sDQorCQlbOV0gPSAgeyAxLCAxLCAgMCwgIDAsICAwLCAw LCAyNDkwLCAzMzQzLCAxNCwgMCwgMCwgMTIsIDMyLCAyOCwgeyB9LCAxMjYgfSwNCisJCVsxMF0g PSB7IDEsIDEsICAwLCAgMCwgIDAsIDAsIDI0OTAsIDMzNDMsIDE0LCAwLCAwLCAxNSwgMzIsIDI0 LCB7IH0sIDEyNiB9LA0KKwkJWzExXSA9IHsgMSwgMSwgIDAsICAwLCAgMCwgMCwgIDgyMywgMjUx MCwgMTQsIDAsIDAsIDE4LCAzMiwgMjgsIHsgfSwgIDU0IH0sDQorCQlbMTJdID0geyAxLCAxLCAg MCwgIDAsICAwLCAwLCAgODIzLCAyNTEwLCAxNCwgMCwgMCwgMjcsIDMyLCAyNCwgeyB9LCAgNTQg fSwNCisJfSwNCit9Ow0KKw0KK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbXQ3OTE1X2Rmc19yYWRhcl9z cGVjIGZjY19yYWRhcl9zcGVjcyA9IHsNCisJLnB1bHNlX3RoID0geyAxMTAsIC0xMCwgLTgwLCA0 MCwgNTIwMCwgMTI4LCA1MjAwIH0sDQorCS5yYWRhcl9wYXR0ZXJuID0gew0KKwkJWzBdID0geyAx LCAwLCAgOCwgIDMyLCAyOCwgMCwgNTA4LCAzMDc2LCAxMywgMSwgIDEgfSwNCisJCVsxXSA9IHsg MSwgMCwgMTIsICAzMiwgMjgsIDAsIDE0MCwgIDI0MCwgMTcsIDEsICAxIH0sDQorCQlbMl0gPSB7 IDEsIDAsICA4LCAgMzIsIDI4LCAwLCAxOTAsICA1MTAsIDIyLCAxLCAgMSB9LA0KKwkJWzNdID0g eyAxLCAwLCAgNiwgIDMyLCAyOCwgMCwgMTkwLCAgNTEwLCAzMiwgMSwgIDEgfSwNCisJCVs0XSA9 IHsgMSwgMCwgIDksIDI1NSwgMjgsIDAsIDMyMywgIDM0MywgMTMsIDEsIDMyIH0sDQorCX0sDQor fTsNCisNCitzdGF0aWMgY29uc3Qgc3RydWN0IG10NzkxNV9kZnNfcmFkYXJfc3BlYyBqcF9yYWRh cl9zcGVjcyA9IHsNCisJLnB1bHNlX3RoID0geyAxMTAsIC0xMCwgLTgwLCA0MCwgNTIwMCwgMTI4 LCA1MjAwIH0sDQorCS5yYWRhcl9wYXR0ZXJuID0gew0KKwkJWzBdID0gIHsgMSwgMCwgIDgsICAz MiwgMjgsIDAsICA1MDgsIDMwNzYsICAxMywgMSwgIDEgfSwNCisJCVsxXSA9ICB7IDEsIDAsIDEy LCAgMzIsIDI4LCAwLCAgMTQwLCAgMjQwLCAgMTcsIDEsICAxIH0sDQorCQlbMl0gPSAgeyAxLCAw LCAgOCwgIDMyLCAyOCwgMCwgIDE5MCwgIDUxMCwgIDIyLCAxLCAgMSB9LA0KKwkJWzNdID0gIHsg MSwgMCwgIDYsICAzMiwgMjgsIDAsICAxOTAsICA1MTAsICAzMiwgMSwgIDEgfSwNCisJCVs0XSA9 ICB7IDEsIDAsICA5LCAyNTUsIDI4LCAwLCAgMzIzLCAgMzQzLCAgMTMsIDEsIDMyIH0sDQorCQlb MTNdID0geyAxLCAwLCAgNywgIDMyLCAyOCwgMCwgMzgzNiwgMzg1NiwgIDE0LCAxLCAgMSB9LA0K KwkJWzE0XSA9IHsgMSwgMCwgIDYsICAzMiwgMjgsIDAsICA2MTUsIDUwMTAsIDExMCwgMSwgIDEg fSwNCisJCVsxNV0gPSB7IDEsIDEsICAwLCAgIDAsICAwLCAwLCAgIDE1LCA1MDEwLCAxMTAsIDAs ICAwLCAxMiwgMzIsIDI4IH0sDQorCX0sDQorfTsNCisNCitzdGF0aWMgc3RydWN0IG10NzZfd2Np ZCAqbXQ3OTE1X3J4X2dldF93Y2lkKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsDQorCQkJCQkgICAg dTE2IGlkeCwgYm9vbCB1bmljYXN0KQ0KK3sNCisJc3RydWN0IG10NzkxNV9zdGEgKnN0YTsNCisJ c3RydWN0IG10NzZfd2NpZCAqd2NpZDsNCisNCisJaWYgKGlkeCA+PSBBUlJBWV9TSVpFKGRldi0+ bXQ3Ni53Y2lkKSkNCisJCXJldHVybiBOVUxMOw0KKw0KKwl3Y2lkID0gcmN1X2RlcmVmZXJlbmNl KGRldi0+bXQ3Ni53Y2lkW2lkeF0pOw0KKwlpZiAodW5pY2FzdCB8fCAhd2NpZCkNCisJCXJldHVy biB3Y2lkOw0KKw0KKwlpZiAoIXdjaWQtPnN0YSkNCisJCXJldHVybiBOVUxMOw0KKw0KKwlzdGEg PSBjb250YWluZXJfb2Yod2NpZCwgc3RydWN0IG10NzkxNV9zdGEsIHdjaWQpOw0KKwlpZiAoIXN0 YS0+dmlmKQ0KKwkJcmV0dXJuIE5VTEw7DQorDQorCXJldHVybiAmc3RhLT52aWYtPnN0YS53Y2lk Ow0KK30NCisNCit2b2lkIG10NzkxNV9zdGFfcHMoc3RydWN0IG10NzZfZGV2ICptZGV2LCBzdHJ1 Y3QgaWVlZTgwMjExX3N0YSAqc3RhLCBib29sIHBzKQ0KK3sNCit9DQorDQorYm9vbCBtdDc5MTVf bWFjX3d0YmxfdXBkYXRlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIGludCBpZHgsIHUzMiBtYXNr KQ0KK3sNCisJbXQ3Nl9ybXcoZGV2LCBNVF9XVEJMX1VQREFURSwgTVRfV1RCTF9VUERBVEVfV0xB Tl9JRFgsDQorCQkgRklFTERfUFJFUChNVF9XVEJMX1VQREFURV9XTEFOX0lEWCwgaWR4KSB8IG1h c2spOw0KKw0KKwlyZXR1cm4gbXQ3Nl9wb2xsKGRldiwgTVRfV1RCTF9VUERBVEUsIE1UX1dUQkxf VVBEQVRFX0JVU1ksDQorCQkJIDAsIDUwMDApOw0KK30NCisNCitzdGF0aWMgdTMyIG10NzkxNV9t YWNfd3RibF9sbWFjX3JlYWQoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgdTE2IHdjaWQsDQorCQkJ CSAgICAgdTE2IGFkZHIpDQorew0KKwltdDc2X3dyKGRldiwgTVRfV1RCTE9OX1RPUF9XRFVDUiwN CisJCUZJRUxEX1BSRVAoTVRfV1RCTE9OX1RPUF9XRFVDUl9HUk9VUCwgKHdjaWQgPj4gNykpKTsN CisNCisJcmV0dXJuIG10NzZfcnIoZGV2LCBNVF9XVEJMX0xNQUNfT0ZGUyh3Y2lkLCBhZGRyKSk7 DQorfQ0KKw0KK3ZvaWQgbXQ3OTE1X21hY19zdGFfcG9sbChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2 KQ0KK3sNCisJc3RhdGljIGNvbnN0IHU4IGFjX3RvX3RpZFtdID0gew0KKwkJW0lFRUU4MDIxMV9B Q19CRV0gPSAwLA0KKwkJW0lFRUU4MDIxMV9BQ19CS10gPSAxLA0KKwkJW0lFRUU4MDIxMV9BQ19W SV0gPSA0LA0KKwkJW0lFRUU4MDIxMV9BQ19WT10gPSA2DQorCX07DQorCXN0YXRpYyBjb25zdCB1 OCBod19xdWV1ZV9tYXBbXSA9IHsNCisJCVtJRUVFODAyMTFfQUNfQktdID0gMCwNCisJCVtJRUVF ODAyMTFfQUNfQkVdID0gMSwNCisJCVtJRUVFODAyMTFfQUNfVkldID0gMiwNCisJCVtJRUVFODAy MTFfQUNfVk9dID0gMywNCisJfTsNCisJc3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YTsNCisJc3Ry dWN0IG10NzkxNV9zdGEgKm1zdGE7DQorCXUzMiB0eF90aW1lW0lFRUU4MDIxMV9OVU1fQUNTXSwg cnhfdGltZVtJRUVFODAyMTFfTlVNX0FDU107DQorCWludCBpOw0KKw0KKwlyY3VfcmVhZF9sb2Nr KCk7DQorDQorCXdoaWxlICh0cnVlKSB7DQorCQlib29sIGNsZWFyID0gZmFsc2U7DQorCQl1MTYg aWR4Ow0KKw0KKwkJc3Bpbl9sb2NrX2JoKCZkZXYtPnN0YV9wb2xsX2xvY2spOw0KKwkJaWYgKGxp c3RfZW1wdHkoJmRldi0+c3RhX3BvbGxfbGlzdCkpIHsNCisJCQlzcGluX3VubG9ja19iaCgmZGV2 LT5zdGFfcG9sbF9sb2NrKTsNCisJCQlicmVhazsNCisJCX0NCisJCW1zdGEgPSBsaXN0X2ZpcnN0 X2VudHJ5KCZkZXYtPnN0YV9wb2xsX2xpc3QsDQorCQkJCQlzdHJ1Y3QgbXQ3OTE1X3N0YSwgcG9s bF9saXN0KTsNCisJCWxpc3RfZGVsX2luaXQoJm1zdGEtPnBvbGxfbGlzdCk7DQorCQlzcGluX3Vu bG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2NrKTsNCisNCisJCWZvciAoaSA9IDAsIGlkeCA9IG1z dGEtPndjaWQuaWR4OyBpIDwgSUVFRTgwMjExX05VTV9BQ1M7IGkrKykgew0KKwkJCXUzMiB0eF9s YXN0ID0gbXN0YS0+YWlydGltZV9hY1tpXTsNCisJCQl1MzIgcnhfbGFzdCA9IG1zdGEtPmFpcnRp bWVfYWNbaSArIElFRUU4MDIxMV9OVU1fQUNTXTsNCisNCisJCQltc3RhLT5haXJ0aW1lX2FjW2ld ID0NCisJCQkJbXQ3OTE1X21hY193dGJsX2xtYWNfcmVhZChkZXYsIGlkeCwgMjAgKyBpKTsNCisJ CQltc3RhLT5haXJ0aW1lX2FjW2kgKyBJRUVFODAyMTFfTlVNX0FDU10gPQ0KKwkJCQltdDc5MTVf bWFjX3d0YmxfbG1hY19yZWFkKGRldiwgaWR4LCAyMSArIGkpOw0KKwkJCXR4X3RpbWVbaV0gPSBt c3RhLT5haXJ0aW1lX2FjW2ldIC0gdHhfbGFzdDsNCisJCQlyeF90aW1lW2ldID0gbXN0YS0+YWly dGltZV9hY1tpICsgSUVFRTgwMjExX05VTV9BQ1NdIC0NCisJCQkJICAgICByeF9sYXN0Ow0KKw0K KwkJCWlmICgodHhfbGFzdCB8IHJ4X2xhc3QpICYgQklUKDMwKSkNCisJCQkJY2xlYXIgPSB0cnVl Ow0KKwkJfQ0KKw0KKwkJaWYgKGNsZWFyKSB7DQorCQkJbXQ3OTE1X21hY193dGJsX3VwZGF0ZShk ZXYsIGlkeCwNCisJCQkJCSAgICAgICBNVF9XVEJMX1VQREFURV9BRE1fQ09VTlRfQ0xFQVIpOw0K KwkJCW1lbXNldChtc3RhLT5haXJ0aW1lX2FjLCAwLCBzaXplb2YobXN0YS0+YWlydGltZV9hYykp Ow0KKwkJfQ0KKw0KKwkJaWYgKCFtc3RhLT53Y2lkLnN0YSkNCisJCQljb250aW51ZTsNCisNCisJ CXN0YSA9IGNvbnRhaW5lcl9vZigodm9pZCAqKW1zdGEsIHN0cnVjdCBpZWVlODAyMTFfc3RhLA0K KwkJCQkgICBkcnZfcHJpdik7DQorCQlmb3IgKGkgPSAwOyBpIDwgSUVFRTgwMjExX05VTV9BQ1M7 IGkrKykgew0KKwkJCXUzMiB0eF9jdXIgPSB0eF90aW1lW2ldOw0KKwkJCXUzMiByeF9jdXIgPSBy eF90aW1lW2h3X3F1ZXVlX21hcFtpXV07DQorCQkJdTggdGlkID0gYWNfdG9fdGlkW2ldOw0KKw0K KwkJCWlmICghdHhfY3VyICYmICFyeF9jdXIpDQorCQkJCWNvbnRpbnVlOw0KKw0KKwkJCWllZWU4 MDIxMV9zdGFfcmVnaXN0ZXJfYWlydGltZShzdGEsIHRpZCwgdHhfY3VyLA0KKwkJCQkJCSAgICAg ICByeF9jdXIpOw0KKwkJfQ0KKwl9DQorDQorCXJjdV9yZWFkX3VubG9jaygpOw0KK30NCisNCitp bnQgbXQ3OTE1X21hY19maWxsX3J4KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBza19i dWZmICpza2IpDQorew0KKwlzdHJ1Y3QgbXQ3Nl9yeF9zdGF0dXMgKnN0YXR1cyA9IChzdHJ1Y3Qg bXQ3Nl9yeF9zdGF0dXMgKilza2ItPmNiOw0KKwlzdHJ1Y3QgbXQ3Nl9waHkgKm1waHkgPSAmZGV2 LT5tdDc2LnBoeTsNCisJc3RydWN0IG10NzkxNV9waHkgKnBoeSA9ICZkZXYtPnBoeTsNCisJc3Ry dWN0IGllZWU4MDIxMV9zdXBwb3J0ZWRfYmFuZCAqc2JhbmQ7DQorCXN0cnVjdCBpZWVlODAyMTFf aGRyICpoZHI7DQorCXN0cnVjdCBtdDc5MTVfcnh2IHJ4diA9IHt9Ow0KKwlfX2xlMzIgKnJ4ZCA9 IChfX2xlMzIgKilza2ItPmRhdGE7DQorCXUzMiByeGQxID0gbGUzMl90b19jcHUocnhkWzFdKTsN CisJdTMyIHJ4ZDIgPSBsZTMyX3RvX2NwdShyeGRbMl0pOw0KKwl1MzIgcnhkMyA9IGxlMzJfdG9f Y3B1KHJ4ZFszXSk7DQorCWJvb2wgdW5pY2FzdCwgaW5zZXJ0X2NjbXBfaGRyID0gZmFsc2U7DQor CXU4IHJlbW92ZV9wYWQ7DQorCWludCBpLCBpZHg7DQorDQorCW1lbXNldChzdGF0dXMsIDAsIHNp emVvZigqc3RhdHVzKSk7DQorDQorCWlmIChyeGQxICYgTVRfUlhEMV9OT1JNQUxfQkFORF9JRFgp IHsNCisJCW1waHkgPSBkZXYtPm10NzYucGh5MjsNCisJCWlmICghbXBoeSkNCisJCQlyZXR1cm4g LUVJTlZBTDsNCisNCisJCXBoeSA9IG1waHktPnByaXY7DQorCQlzdGF0dXMtPmV4dF9waHkgPSB0 cnVlOw0KKwl9DQorDQorCWlmICghdGVzdF9iaXQoTVQ3Nl9TVEFURV9SVU5OSU5HLCAmbXBoeS0+ c3RhdGUpKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCXVuaWNhc3QgPSBGSUVMRF9HRVQoTVRf UlhEM19OT1JNQUxfQUREUl9UWVBFLCByeGQzKSA9PSBNVF9SWEQzX05PUk1BTF9VMk07DQorCWlk eCA9IEZJRUxEX0dFVChNVF9SWEQxX05PUk1BTF9XTEFOX0lEWCwgcnhkMSk7DQorCXN0YXR1cy0+ d2NpZCA9IG10NzkxNV9yeF9nZXRfd2NpZChkZXYsIGlkeCwgdW5pY2FzdCk7DQorDQorCWlmIChz dGF0dXMtPndjaWQpIHsNCisJCXN0cnVjdCBtdDc5MTVfc3RhICptc3RhOw0KKw0KKwkJbXN0YSA9 IGNvbnRhaW5lcl9vZihzdGF0dXMtPndjaWQsIHN0cnVjdCBtdDc5MTVfc3RhLCB3Y2lkKTsNCisJ CXNwaW5fbG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2NrKTsNCisJCWlmIChsaXN0X2VtcHR5KCZt c3RhLT5wb2xsX2xpc3QpKQ0KKwkJCWxpc3RfYWRkX3RhaWwoJm1zdGEtPnBvbGxfbGlzdCwgJmRl di0+c3RhX3BvbGxfbGlzdCk7DQorCQlzcGluX3VubG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2Nr KTsNCisJfQ0KKw0KKwlzdGF0dXMtPmZyZXEgPSBtcGh5LT5jaGFuZGVmLmNoYW4tPmNlbnRlcl9m cmVxOw0KKwlzdGF0dXMtPmJhbmQgPSBtcGh5LT5jaGFuZGVmLmNoYW4tPmJhbmQ7DQorCWlmIChz dGF0dXMtPmJhbmQgPT0gTkw4MDIxMV9CQU5EXzVHSFopDQorCQlzYmFuZCA9ICZtcGh5LT5zYmFu ZF81Zy5zYmFuZDsNCisJZWxzZQ0KKwkJc2JhbmQgPSAmbXBoeS0+c2JhbmRfMmcuc2JhbmQ7DQor DQorCWlmICghc2JhbmQtPmNoYW5uZWxzKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCWlmIChy eGQxICYgTVRfUlhEMV9OT1JNQUxfRkNTX0VSUikNCisJCXN0YXR1cy0+ZmxhZyB8PSBSWF9GTEFH X0ZBSUxFRF9GQ1NfQ1JDOw0KKw0KKwlpZiAocnhkMSAmIE1UX1JYRDFfTk9STUFMX1RLSVBfTUlD X0VSUikNCisJCXN0YXR1cy0+ZmxhZyB8PSBSWF9GTEFHX01NSUNfRVJST1I7DQorDQorCWlmIChG SUVMRF9HRVQoTVRfUlhEMV9OT1JNQUxfU0VDX01PREUsIHJ4ZDEpICE9IDAgJiYNCisJICAgICEo cnhkMSAmIChNVF9SWEQxX05PUk1BTF9DTE0gfCBNVF9SWEQxX05PUk1BTF9DTSkpKSB7DQorCQlz dGF0dXMtPmZsYWcgfD0gUlhfRkxBR19ERUNSWVBURUQ7DQorCQlzdGF0dXMtPmZsYWcgfD0gUlhf RkxBR19JVl9TVFJJUFBFRDsNCisJCXN0YXR1cy0+ZmxhZyB8PSBSWF9GTEFHX01NSUNfU1RSSVBQ RUQgfCBSWF9GTEFHX01JQ19TVFJJUFBFRDsNCisJfQ0KKw0KKwlpZiAoIShyeGQyICYgTVRfUlhE Ml9OT1JNQUxfTk9OX0FNUERVKSkgew0KKwkJc3RhdHVzLT5mbGFnIHw9IFJYX0ZMQUdfQU1QRFVf REVUQUlMUzsNCisNCisJCS8qIGFsbCBzdWJmcmFtZXMgb2YgYW4gQS1NUERVIGhhdmUgdGhlIHNh bWUgdGltZXN0YW1wICovDQorCQlpZiAocGh5LT5yeF9hbXBkdV90cyAhPSByeGRbMTRdKSB7DQor CQkJaWYgKCErK3BoeS0+YW1wZHVfcmVmKQ0KKwkJCQlwaHktPmFtcGR1X3JlZisrOw0KKwkJfQ0K KwkJcGh5LT5yeF9hbXBkdV90cyA9IHJ4ZFsxNF07DQorDQorCQlzdGF0dXMtPmFtcGR1X3JlZiA9 IHBoeS0+YW1wZHVfcmVmOw0KKwl9DQorDQorCXJlbW92ZV9wYWQgPSBGSUVMRF9HRVQoTVRfUlhE Ml9OT1JNQUxfSERSX09GRlNFVCwgcnhkMik7DQorDQorCWlmIChyeGQyICYgTVRfUlhEMl9OT1JN QUxfTUFYX0xFTl9FUlJPUikNCisJCXJldHVybiAtRUlOVkFMOw0KKw0KKwlyeGQgKz0gNjsNCisJ aWYgKHJ4ZDEgJiBNVF9SWEQxX05PUk1BTF9HUk9VUF80KSB7DQorCQlyeGQgKz0gNDsNCisJCWlm ICgodTggKilyeGQgLSBza2ItPmRhdGEgPj0gc2tiLT5sZW4pDQorCQkJcmV0dXJuIC1FSU5WQUw7 DQorCX0NCisNCisJaWYgKHJ4ZDEgJiBNVF9SWEQxX05PUk1BTF9HUk9VUF8xKSB7DQorCQl1OCAq ZGF0YSA9ICh1OCAqKXJ4ZDsNCisNCisJCWlmIChzdGF0dXMtPmZsYWcgJiBSWF9GTEFHX0RFQ1JZ UFRFRCkgew0KKwkJCXN0YXR1cy0+aXZbMF0gPSBkYXRhWzVdOw0KKwkJCXN0YXR1cy0+aXZbMV0g PSBkYXRhWzRdOw0KKwkJCXN0YXR1cy0+aXZbMl0gPSBkYXRhWzNdOw0KKwkJCXN0YXR1cy0+aXZb M10gPSBkYXRhWzJdOw0KKwkJCXN0YXR1cy0+aXZbNF0gPSBkYXRhWzFdOw0KKwkJCXN0YXR1cy0+ aXZbNV0gPSBkYXRhWzBdOw0KKw0KKwkJCWluc2VydF9jY21wX2hkciA9IEZJRUxEX0dFVChNVF9S WEQyX05PUk1BTF9GUkFHLCByeGQyKTsNCisJCX0NCisJCXJ4ZCArPSA0Ow0KKwkJaWYgKCh1OCAq KXJ4ZCAtIHNrYi0+ZGF0YSA+PSBza2ItPmxlbikNCisJCQlyZXR1cm4gLUVJTlZBTDsNCisJfQ0K Kw0KKwlpZiAocnhkMSAmIE1UX1JYRDFfTk9STUFMX0dST1VQXzIpIHsNCisJCXJ4ZCArPSAyOw0K KwkJaWYgKCh1OCAqKXJ4ZCAtIHNrYi0+ZGF0YSA+PSBza2ItPmxlbikNCisJCQlyZXR1cm4gLUVJ TlZBTDsNCisJfQ0KKw0KKwkvKiBSWEQgR3JvdXAgMyAtIFAtUlhWICovDQorCWlmIChyeGQxICYg TVRfUlhEMV9OT1JNQUxfR1JPVVBfMykgew0KKwkJbWVtY3B5KHJ4di52LCByeGQsIHNpemVvZihy eHYudikpOw0KKw0KKwkJcnhkICs9IDI7DQorCQlpZiAoKHU4ICopcnhkIC0gc2tiLT5kYXRhID49 IHNrYi0+bGVuKQ0KKwkJCXJldHVybiAtRUlOVkFMOw0KKw0KKwkJaWYgKHJ4di52WzBdICYgTVRf UFJYVl9IVF9BRF9DT0RFKQ0KKwkJCXN0YXR1cy0+ZW5jX2ZsYWdzIHw9IFJYX0VOQ19GTEFHX0xE UEM7DQorDQorCQlzdGF0dXMtPmNoYWlucyA9IG1waHktPmFudGVubmFfbWFzazsNCisJCXN0YXR1 cy0+Y2hhaW5fc2lnbmFsWzBdID0gdG9fcnNzaShNVF9QUlhWX1JDUEkwLCByeHYudlsxXSk7DQor CQlzdGF0dXMtPmNoYWluX3NpZ25hbFsxXSA9IHRvX3Jzc2koTVRfUFJYVl9SQ1BJMSwgcnh2LnZb MV0pOw0KKwkJc3RhdHVzLT5jaGFpbl9zaWduYWxbMl0gPSB0b19yc3NpKE1UX1BSWFZfUkNQSTIs IHJ4di52WzFdKTsNCisJCXN0YXR1cy0+Y2hhaW5fc2lnbmFsWzNdID0gdG9fcnNzaShNVF9QUlhW X1JDUEkzLCByeHYudlsxXSk7DQorCQlzdGF0dXMtPnNpZ25hbCA9IHN0YXR1cy0+Y2hhaW5fc2ln bmFsWzBdOw0KKw0KKwkJZm9yIChpID0gMTsgaSA8IGh3ZWlnaHQ4KG1waHktPmFudGVubmFfbWFz ayk7IGkrKykgew0KKwkJCWlmICghKHN0YXR1cy0+Y2hhaW5zICYgQklUKGkpKSkNCisJCQkJY29u dGludWU7DQorDQorCQkJc3RhdHVzLT5zaWduYWwgPSBtYXgoc3RhdHVzLT5zaWduYWwsDQorCQkJ CQkgICAgIHN0YXR1cy0+Y2hhaW5fc2lnbmFsW2ldKTsNCisJCX0NCisNCisJCS8qIFJYRCBHcm91 cCA1IC0gQy1SWFYgKi8NCisJCWlmIChyeGQxICYgTVRfUlhEMV9OT1JNQUxfR1JPVVBfNSkgew0K KwkJCXU4IHN0YmMgPSBGSUVMRF9HRVQoTVRfQ1JYVl9IVF9TVEJDLCByeHYudlsyXSk7DQorCQkJ dTggZ2kgPSBGSUVMRF9HRVQoTVRfQ1JYVl9IVF9TSE9SVF9HSSwgcnh2LnZbMl0pOw0KKwkJCWJv b2wgY2NrID0gZmFsc2U7DQorDQorCQkJcnhkICs9IDE4Ow0KKwkJCWlmICgodTggKilyeGQgLSBz a2ItPmRhdGEgPj0gc2tiLT5sZW4pDQorCQkJCXJldHVybiAtRUlOVkFMOw0KKw0KKwkJCWlkeCA9 IGkgPSBGSUVMRF9HRVQoTVRfUFJYVl9UWF9SQVRFLCByeHYudlswXSk7DQorCQkJcnh2LnBoeSA9 IEZJRUxEX0dFVChNVF9DUlhWX1RYX01PREUsIHJ4di52WzJdKTsNCisNCisJCQlzd2l0Y2ggKHJ4 di5waHkpIHsNCisJCQljYXNlIE1UX1BIWV9UWVBFX0NDSzoNCisJCQkJY2NrID0gdHJ1ZTsNCisJ CQkJLyogZmFsbCB0aHJvdWdoICovDQorCQkJY2FzZSBNVF9QSFlfVFlQRV9PRkRNOg0KKwkJCQlp ID0gbXQ3Nl9nZXRfcmF0ZSgmZGV2LT5tdDc2LCBzYmFuZCwgaSwgY2NrKTsNCisJCQkJYnJlYWs7 DQorCQkJY2FzZSBNVF9QSFlfVFlQRV9IVF9HRjoNCisJCQljYXNlIE1UX1BIWV9UWVBFX0hUOg0K KwkJCQlzdGF0dXMtPmVuY29kaW5nID0gUlhfRU5DX0hUOw0KKwkJCQlpZiAoaSA+IDMxKQ0KKwkJ CQkJcmV0dXJuIC1FSU5WQUw7DQorCQkJCWJyZWFrOw0KKwkJCWNhc2UgTVRfUEhZX1RZUEVfVkhU Og0KKwkJCQlzdGF0dXMtPm5zcyA9DQorCQkJCQlGSUVMRF9HRVQoTVRfUFJYVl9OU1RTLCByeHYu dlswXSkgKyAxOw0KKwkJCQlzdGF0dXMtPmVuY29kaW5nID0gUlhfRU5DX1ZIVDsNCisJCQkJaWYg KGkgPiA5KQ0KKwkJCQkJcmV0dXJuIC1FSU5WQUw7DQorCQkJCWJyZWFrOw0KKwkJCWNhc2UgTVRf UEhZX1RZUEVfSEVfTVU6DQorCQkJCS8qIGZhbGwgdGhyb3VnaCAqLw0KKwkJCWNhc2UgTVRfUEhZ X1RZUEVfSEVfU1U6DQorCQkJY2FzZSBNVF9QSFlfVFlQRV9IRV9FWFRfU1U6DQorCQkJY2FzZSBN VF9QSFlfVFlQRV9IRV9UQjoNCisJCQkJc3RhdHVzLT5uc3MgPQ0KKwkJCQkJRklFTERfR0VUKE1U X1BSWFZfTlNUUywgcnh2LnZbMF0pICsgMTsNCisJCQkJc3RhdHVzLT5lbmNvZGluZyA9IFJYX0VO Q19IRTsNCisJCQkJaSAmPSBHRU5NQVNLKDMsIDApOw0KKw0KKwkJCQlpZiAoZ2kgPD0gTkw4MDIx MV9SQVRFX0lORk9fSEVfR0lfM18yKQ0KKwkJCQkJc3RhdHVzLT5oZV9naSA9IGdpOw0KKw0KKwkJ CQlpZiAoaWR4ICYgTVRfUFJYVl9UWF9EQ00pDQorCQkJCQlzdGF0dXMtPmhlX2RjbSA9IHRydWU7 DQorCQkJCWJyZWFrOw0KKwkJCWRlZmF1bHQ6DQorCQkJCXJldHVybiAtRUlOVkFMOw0KKwkJCX0N CisJCQlzdGF0dXMtPnJhdGVfaWR4ID0gaTsNCisNCisJCQlzd2l0Y2ggKEZJRUxEX0dFVChNVF9D UlhWX0ZSQU1FX01PREUsIHJ4di52WzJdKSkgew0KKwkJCWNhc2UgSUVFRTgwMjExX1NUQV9SWF9C V18yMDoNCisJCQkJYnJlYWs7DQorCQkJY2FzZSBJRUVFODAyMTFfU1RBX1JYX0JXXzQwOg0KKwkJ CQlpZiAocnh2LnBoeSAmIE1UX1BIWV9UWVBFX0hFX0VYVF9TVSAmJg0KKwkJCQkgICAgKGlkeCAm IE1UX1BSWFZfVFhfRVJfU1VfMTA2VCkpIHsNCisJCQkJCXN0YXR1cy0+YncgPSBSQVRFX0lORk9f QldfSEVfUlU7DQorCQkJCQlzdGF0dXMtPmhlX3J1ID0NCisJCQkJCQlOTDgwMjExX1JBVEVfSU5G T19IRV9SVV9BTExPQ18xMDY7DQorCQkJCX0gZWxzZSB7DQorCQkJCQlzdGF0dXMtPmJ3ID0gUkFU RV9JTkZPX0JXXzQwOw0KKwkJCQl9DQorCQkJCWJyZWFrOw0KKwkJCWNhc2UgSUVFRTgwMjExX1NU QV9SWF9CV184MDoNCisJCQkJc3RhdHVzLT5idyA9IFJBVEVfSU5GT19CV184MDsNCisJCQkJYnJl YWs7DQorCQkJY2FzZSBJRUVFODAyMTFfU1RBX1JYX0JXXzE2MDoNCisJCQkJc3RhdHVzLT5idyA9 IFJBVEVfSU5GT19CV18xNjA7DQorCQkJCWJyZWFrOw0KKwkJCWRlZmF1bHQ6DQorCQkJCXJldHVy biAtRUlOVkFMOw0KKwkJCX0NCisNCisJCQlzdGF0dXMtPmVuY19mbGFncyB8PSBSWF9FTkNfRkxB R19TVEJDX01BU0sgKiBzdGJjOw0KKwkJCWlmIChyeHYucGh5IDwgTVRfUEhZX1RZUEVfSEVfU1Ug JiYgZ2kpDQorCQkJCXN0YXR1cy0+ZW5jX2ZsYWdzIHw9IFJYX0VOQ19GTEFHX1NIT1JUX0dJOw0K KwkJfQ0KKwl9DQorDQorCXNrYl9wdWxsKHNrYiwgKHU4ICopcnhkIC0gc2tiLT5kYXRhICsgMiAq IHJlbW92ZV9wYWQpOw0KKw0KKwlpZiAoaW5zZXJ0X2NjbXBfaGRyKSB7DQorCQl1OCBrZXlfaWQg PSBGSUVMRF9HRVQoTVRfUlhEMV9OT1JNQUxfS0VZX0lELCByeGQxKTsNCisNCisJCW10NzZfaW5z ZXJ0X2NjbXBfaGRyKHNrYiwga2V5X2lkKTsNCisJfQ0KKw0KKwloZHIgPSBtdDc2X3NrYl9nZXRf aGRyKHNrYik7DQorCWlmICghc3RhdHVzLT53Y2lkIHx8ICFpZWVlODAyMTFfaXNfZGF0YV9xb3Mo aGRyLT5mcmFtZV9jb250cm9sKSkNCisJCXJldHVybiAwOw0KKw0KKwlzdGF0dXMtPmFnZ3IgPSB1 bmljYXN0ICYmDQorCQkgICAgICAgIWllZWU4MDIxMV9pc19xb3NfbnVsbGZ1bmMoaGRyLT5mcmFt ZV9jb250cm9sKTsNCisJc3RhdHVzLT50aWQgPSAqaWVlZTgwMjExX2dldF9xb3NfY3RsKGhkcikg JiBJRUVFODAyMTFfUU9TX0NUTF9USURfTUFTSzsNCisJc3RhdHVzLT5zZXFubyA9IElFRUU4MDIx MV9TRVFfVE9fU04obGUxNl90b19jcHUoaGRyLT5zZXFfY3RybCkpOw0KKw0KKwlyZXR1cm4gMDsN Cit9DQorDQordm9pZCBtdDc5MTVfbWFjX3dyaXRlX3R4d2koc3RydWN0IG10NzkxNV9kZXYgKmRl diwgX19sZTMyICp0eHdpLA0KKwkJCSAgIHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBtdDc2 X3djaWQgKndjaWQsDQorCQkJICAgc3RydWN0IGllZWU4MDIxMV9rZXlfY29uZiAqa2V5LCBib29s IGJlYWNvbikNCit7DQorCXN0cnVjdCBpZWVlODAyMTFfdHhfaW5mbyAqaW5mbyA9IElFRUU4MDIx MV9TS0JfQ0Ioc2tiKTsNCisJc3RydWN0IGllZWU4MDIxMV9oZHIgKmhkciA9IChzdHJ1Y3QgaWVl ZTgwMjExX2hkciAqKXNrYi0+ZGF0YTsNCisJYm9vbCBtdWx0aWNhc3QgPSBpc19tdWx0aWNhc3Rf ZXRoZXJfYWRkcihoZHItPmFkZHIxKTsNCisJc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiA9IGlu Zm8tPmNvbnRyb2wudmlmOw0KKwlzdHJ1Y3QgbXQ3Nl9waHkgKm1waHkgPSAmZGV2LT5tcGh5Ow0K Kwlib29sIGV4dF9waHkgPSBpbmZvLT5od19xdWV1ZSAmIE1UX1RYX0hXX1FVRVVFX0VYVF9QSFk7 DQorCXU4IGZjX3R5cGUsIGZjX3N0eXBlLCBwX2ZtdCwgcV9pZHgsIG9tYWNfaWR4ID0gMCwgd21t X2lkeCA9IDA7DQorCV9fbGUxNiBmYyA9IGhkci0+ZnJhbWVfY29udHJvbDsNCisJdTE2IHR4X2Nv dW50ID0gNCwgc2Vxbm8gPSAwOw0KKwl1MzIgdmFsOw0KKw0KKwlpZiAodmlmKSB7DQorCQlzdHJ1 Y3QgbXQ3OTE1X3ZpZiAqbXZpZiA9IChzdHJ1Y3QgbXQ3OTE1X3ZpZiAqKXZpZi0+ZHJ2X3ByaXY7 DQorDQorCQlvbWFjX2lkeCA9IG12aWYtPm9tYWNfaWR4Ow0KKwkJd21tX2lkeCA9IG12aWYtPndt bV9pZHg7DQorCX0NCisNCisJaWYgKGV4dF9waHkgJiYgZGV2LT5tdDc2LnBoeTIpDQorCQltcGh5 ID0gZGV2LT5tdDc2LnBoeTI7DQorDQorCWZjX3R5cGUgPSAobGUxNl90b19jcHUoZmMpICYgSUVF RTgwMjExX0ZDVExfRlRZUEUpID4+IDI7DQorCWZjX3N0eXBlID0gKGxlMTZfdG9fY3B1KGZjKSAm IElFRUU4MDIxMV9GQ1RMX1NUWVBFKSA+PiA0Ow0KKw0KKwlpZiAoaWVlZTgwMjExX2lzX2RhdGEo ZmMpIHx8IGllZWU4MDIxMV9pc19idWZmZXJhYmxlX21tcGR1KGZjKSkgew0KKwkJcV9pZHggPSB3 bW1faWR4ICogTVQ3OTE1X01BWF9XTU1fU0VUUyArDQorCQkJc2tiX2dldF9xdWV1ZV9tYXBwaW5n KHNrYik7DQorCQlwX2ZtdCA9IE1UX1RYX1RZUEVfQ1Q7DQorCX0gZWxzZSBpZiAoYmVhY29uKSB7 DQorCQlxX2lkeCA9IE1UX0xNQUNfQkNOMDsNCisJCXBfZm10ID0gTVRfVFhfVFlQRV9GVzsNCisJ fSBlbHNlIHsNCisJCXFfaWR4ID0gTVRfTE1BQ19BTFRYMDsNCisJCXBfZm10ID0gTVRfVFhfVFlQ RV9DVDsNCisJfQ0KKw0KKwl2YWwgPSBGSUVMRF9QUkVQKE1UX1RYRDBfVFhfQllURVMsIHNrYi0+ bGVuICsgTVRfVFhEX1NJWkUpIHwNCisJICAgICAgRklFTERfUFJFUChNVF9UWEQwX1BLVF9GTVQs IHBfZm10KSB8DQorCSAgICAgIEZJRUxEX1BSRVAoTVRfVFhEMF9RX0lEWCwgcV9pZHgpOw0KKwl0 eHdpWzBdID0gY3B1X3RvX2xlMzIodmFsKTsNCisNCisJdmFsID0gTVRfVFhEMV9MT05HX0ZPUk1B VCB8DQorCSAgICAgIEZJRUxEX1BSRVAoTVRfVFhEMV9XTEFOX0lEWCwgd2NpZC0+aWR4KSB8DQor CSAgICAgIEZJRUxEX1BSRVAoTVRfVFhEMV9IRFJfRk9STUFULCBNVF9IRFJfRk9STUFUXzgwMl8x MSkgfA0KKwkgICAgICBGSUVMRF9QUkVQKE1UX1RYRDFfSERSX0lORk8sDQorCQkJIGllZWU4MDIx MV9nZXRfaGRybGVuX2Zyb21fc2tiKHNrYikgLyAyKSB8DQorCSAgICAgIEZJRUxEX1BSRVAoTVRf VFhEMV9USUQsDQorCQkJIHNrYi0+cHJpb3JpdHkgJiBJRUVFODAyMTFfUU9TX0NUTF9USURfTUFT SykgfA0KKwkgICAgICBGSUVMRF9QUkVQKE1UX1RYRDFfT1dOX01BQywgb21hY19pZHgpOw0KKwlp ZiAoZXh0X3BoeSAmJiBxX2lkeCA+PSBNVF9MTUFDX0FMVFgwICYmIHFfaWR4IDw9IE1UX0xNQUNf QkNOMCkNCisJCXZhbCB8PSBjcHVfdG9fbGUzMihNVF9UWEQxX1RHSUQpOw0KKw0KKwl0eHdpWzFd ID0gY3B1X3RvX2xlMzIodmFsKTsNCisNCisJdmFsID0gRklFTERfUFJFUChNVF9UWEQyX0ZSQU1F X1RZUEUsIGZjX3R5cGUpIHwNCisJICAgICAgRklFTERfUFJFUChNVF9UWEQyX1NVQl9UWVBFLCBm Y19zdHlwZSkgfA0KKwkgICAgICBGSUVMRF9QUkVQKE1UX1RYRDJfTVVMVElDQVNULCBtdWx0aWNh c3QpOw0KKwlpZiAoa2V5KSB7DQorCQlpZiAobXVsdGljYXN0ICYmIGllZWU4MDIxMV9pc19yb2J1 c3RfbWdtdF9mcmFtZShza2IpICYmDQorCQkgICAga2V5LT5jaXBoZXIgPT0gV0xBTl9DSVBIRVJf U1VJVEVfQUVTX0NNQUMpIHsNCisJCQl2YWwgfD0gTVRfVFhEMl9CSVA7DQorCQkJdHh3aVszXSA9 IDA7DQorCQl9IGVsc2Ugew0KKwkJCXR4d2lbM10gPSBjcHVfdG9fbGUzMihNVF9UWEQzX1BST1RF Q1RfRlJBTUUpOw0KKwkJfQ0KKwl9IGVsc2Ugew0KKwkJdHh3aVszXSA9IDA7DQorCX0NCisJdHh3 aVsyXSA9IGNwdV90b19sZTMyKHZhbCk7DQorDQorCXR4d2lbNF0gPSAwOw0KKwl0eHdpWzVdID0g MDsNCisJdHh3aVs2XSA9IDA7DQorDQorCWlmICghaWVlZTgwMjExX2lzX2RhdGEoZmMpIHx8IG11 bHRpY2FzdCkgew0KKwkJdTE2IHJhdGU7DQorDQorCQkvKiBoYXJkd2FyZSB3b24ndCBhZGQgSFRD IGZvciBtZ210L2N0cmwgZnJhbWUgKi8NCisJCXR4d2lbMl0gfD0gY3B1X3RvX2xlMzIoTVRfVFhE Ml9GSVhfUkFURSB8IE1UX1RYRDJfSFRDX1ZMRCk7DQorDQorCQlpZiAobXBoeS0+Y2hhbmRlZi5j aGFuLT5iYW5kID09IE5MODAyMTFfQkFORF81R0haKQ0KKwkJCXJhdGUgPSBNVDc5MTVfNUdfUkFU RV9ERUZBVUxUOw0KKwkJZWxzZQ0KKwkJCXJhdGUgPSBNVDc5MTVfMkdfUkFURV9ERUZBVUxUOw0K Kw0KKwkJdmFsID0gTVRfVFhENl9GSVhFRF9CVyB8DQorCQkgICAgICBGSUVMRF9QUkVQKE1UX1RY RDZfVFhfUkFURSwgcmF0ZSk7DQorCQl0eHdpWzZdIHw9IGNwdV90b19sZTMyKHZhbCk7DQorCQl0 eHdpWzNdIHw9IGNwdV90b19sZTMyKE1UX1RYRDNfQkFfRElTQUJMRSk7DQorCX0NCisNCisJaWYg KCFpZWVlODAyMTFfaXNfYmVhY29uKGZjKSkNCisJCXR4d2lbM10gfD0gY3B1X3RvX2xlMzIoTVRf VFhEM19TV19QT1dFUl9NR01UKTsNCisJZWxzZQ0KKwkJdHhfY291bnQgPSAweDFmOw0KKw0KKwlp ZiAoaW5mby0+ZmxhZ3MgJiBJRUVFODAyMTFfVFhfQ1RMX05PX0FDSykNCisJCXR4d2lbM10gfD0g Y3B1X3RvX2xlMzIoTVRfVFhEM19OT19BQ0spOw0KKw0KKwl2YWwgPSBGSUVMRF9QUkVQKE1UX1RY RDdfVFlQRSwgZmNfdHlwZSkgfA0KKwkgICAgICBGSUVMRF9QUkVQKE1UX1RYRDdfU1VCX1RZUEUs IGZjX3N0eXBlKTsNCisJdHh3aVs3XSA9IGNwdV90b19sZTMyKHZhbCk7DQorDQorCXZhbCA9IEZJ RUxEX1BSRVAoTVRfVFhEM19SRU1fVFhfQ09VTlQsIHR4X2NvdW50KTsNCisJaWYgKGllZWU4MDIx MV9pc19kYXRhX3FvcyhmYykpIHsNCisJCXNlcW5vID0gSUVFRTgwMjExX1NFUV9UT19TTihsZTE2 X3RvX2NwdShoZHItPnNlcV9jdHJsKSk7DQorCQl2YWwgfD0gTVRfVFhEM19TTl9WQUxJRDsNCisJ fSBlbHNlIGlmIChpZWVlODAyMTFfaXNfYmFja19yZXEoZmMpKSB7DQorCQlzdHJ1Y3QgaWVlZTgw MjExX2JhciAqYmFyOw0KKw0KKwkJYmFyID0gKHN0cnVjdCBpZWVlODAyMTFfYmFyICopc2tiLT5k YXRhOw0KKwkJc2Vxbm8gPSBJRUVFODAyMTFfU0VRX1RPX1NOKGxlMTZfdG9fY3B1KGJhci0+c3Rh cnRfc2VxX251bSkpOw0KKwkJdmFsIHw9IE1UX1RYRDNfU05fVkFMSUQ7DQorCX0NCisJdmFsIHw9 IEZJRUxEX1BSRVAoTVRfVFhEM19TRVEsIHNlcW5vKTsNCisJdHh3aVszXSB8PSBjcHVfdG9fbGUz Mih2YWwpOw0KK30NCisNCitpbnQgbXQ3OTE1X3R4X3ByZXBhcmVfc2tiKHN0cnVjdCBtdDc2X2Rl diAqbWRldiwgdm9pZCAqdHh3aV9wdHIsDQorCQkJICBlbnVtIG10NzZfdHhxX2lkIHFpZCwgc3Ry dWN0IG10NzZfd2NpZCAqd2NpZCwNCisJCQkgIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEsDQor CQkJICBzdHJ1Y3QgbXQ3Nl90eF9pbmZvICp0eF9pbmZvKQ0KK3sNCisJc3RydWN0IGllZWU4MDIx MV9oZHIgKmhkciA9IChzdHJ1Y3QgaWVlZTgwMjExX2hkciAqKXR4X2luZm8tPnNrYi0+ZGF0YTsN CisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IGNvbnRhaW5lcl9vZihtZGV2LCBzdHJ1Y3QgbXQ3 OTE1X2RldiwgbXQ3Nik7DQorCXN0cnVjdCBpZWVlODAyMTFfdHhfaW5mbyAqaW5mbyA9IElFRUU4 MDIxMV9TS0JfQ0IodHhfaW5mby0+c2tiKTsNCisJc3RydWN0IGllZWU4MDIxMV9rZXlfY29uZiAq a2V5ID0gaW5mby0+Y29udHJvbC5od19rZXk7DQorCXN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYg PSBpbmZvLT5jb250cm9sLnZpZjsNCisJc3RydWN0IG10NzZfdHhfY2IgKmNiID0gbXQ3Nl90eF9z a2JfY2IodHhfaW5mby0+c2tiKTsNCisJc3RydWN0IG10NzZfdHh3aV9jYWNoZSAqdDsNCisJc3Ry dWN0IG10NzkxNV90eHAgKnR4cDsNCisJaW50IGlkLCBpLCBuYnVmID0gdHhfaW5mby0+bmJ1ZiAt IDE7DQorCXU4ICp0eHdpID0gKHU4ICopdHh3aV9wdHI7DQorDQorCWlmICghd2NpZCkNCisJCXdj aWQgPSAmZGV2LT5tdDc2Lmdsb2JhbF93Y2lkOw0KKw0KKwljYi0+d2NpZCA9IHdjaWQtPmlkeDsN CisNCisJbXQ3OTE1X21hY193cml0ZV90eHdpKGRldiwgdHh3aV9wdHIsIHR4X2luZm8tPnNrYiwg d2NpZCwga2V5LA0KKwkJCSAgICAgIGZhbHNlKTsNCisNCisJdHhwID0gKHN0cnVjdCBtdDc5MTVf dHhwICopKHR4d2kgKyBNVF9UWERfU0laRSk7DQorCWZvciAoaSA9IDA7IGkgPCBuYnVmOyBpKysp IHsNCisJCXR4cC0+YnVmW2ldID0gY3B1X3RvX2xlMzIodHhfaW5mby0+YnVmW2kgKyAxXS5hZGRy KTsNCisJCXR4cC0+bGVuW2ldID0gY3B1X3RvX2xlMTYodHhfaW5mby0+YnVmW2kgKyAxXS5sZW4p Ow0KKwl9DQorCXR4cC0+bmJ1ZiA9IG5idWY7DQorDQorCS8qIHBhc3MgcGFydGlhbCBza2IgaGVh ZGVyIHRvIGZ3ICovDQorCXR4X2luZm8tPmJ1ZlsxXS5sZW4gPSBNVF9DVF9QQVJTRV9MRU47DQor CXR4X2luZm8tPm5idWYgPSBNVF9DVF9ETUFfQlVGX05VTTsNCisNCisJdHhwLT5mbGFncyA9IGNw dV90b19sZTE2KE1UX0NUX0lORk9fQVBQTFlfVFhEKTsNCisNCisJaWYgKCFrZXkpDQorCQl0eHAt PmZsYWdzIHw9IGNwdV90b19sZTE2KE1UX0NUX0lORk9fTk9ORV9DSVBIRVJfRlJBTUUpOw0KKw0K KwlpZiAoaWVlZTgwMjExX2lzX21nbXQoaGRyLT5mcmFtZV9jb250cm9sKSkNCisJCXR4cC0+Zmxh Z3MgfD0gY3B1X3RvX2xlMTYoTVRfQ1RfSU5GT19NR01UX0ZSQU1FKTsNCisNCisJaWYgKHZpZikg ew0KKwkJc3RydWN0IG10NzkxNV92aWYgKm12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYt PmRydl9wcml2Ow0KKw0KKwkJdHhwLT5ic3NfaWR4ID0gbXZpZi0+aWR4Ow0KKwl9DQorDQorCXQg PSAoc3RydWN0IG10NzZfdHh3aV9jYWNoZSAqKSh0eHdpICsgbWRldi0+ZHJ2LT50eHdpX3NpemUp Ow0KKwl0LT5za2IgPSB0eF9pbmZvLT5za2I7DQorDQorCXNwaW5fbG9ja19iaCgmZGV2LT50b2tl bl9sb2NrKTsNCisJaWQgPSBpZHJfYWxsb2MoJmRldi0+dG9rZW4sIHQsIDAsIE1UNzkxNV9UT0tF Tl9TSVpFLCBHRlBfQVRPTUlDKTsNCisJc3Bpbl91bmxvY2tfYmgoJmRldi0+dG9rZW5fbG9jayk7 DQorCWlmIChpZCA8IDApDQorCQlyZXR1cm4gaWQ7DQorDQorCXR4cC0+dG9rZW4gPSBjcHVfdG9f bGUxNihpZCk7DQorCXR4cC0+cmVwdF93ZHNfd2NpZCA9IDB4ZmY7DQorCXR4X2luZm8tPnNrYiA9 IERNQV9EVU1NWV9EQVRBOw0KKw0KKwlyZXR1cm4gMDsNCit9DQorDQorc3RhdGljIGlubGluZSBi b29sDQorbXQ3OTE1X3R4X2NoZWNrX2FnZ3JfdGlkKHN0cnVjdCBtdDc5MTVfc3RhICptc3RhLCB1 OCB0aWQpDQorew0KKwlib29sIHJldCA9IGZhbHNlOw0KKw0KKwlzcGluX2xvY2tfYmgoJm1zdGEt PmFtcGR1X2xvY2spOw0KKwlpZiAobXN0YS0+YW1wZHVfc3RhdGVbdGlkXSA9PSBNVDc5MTVfQUdH Ul9TVE9QKQ0KKwkJcmV0ID0gdHJ1ZTsNCisJc3Bpbl91bmxvY2tfYmgoJm1zdGEtPmFtcGR1X2xv Y2spOw0KKw0KKwlyZXR1cm4gcmV0Ow0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV90eF9j aGVja19hZ2dyKHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEsIHN0cnVjdCBza19idWZmICpza2Ip DQorew0KKwlzdHJ1Y3QgaWVlZTgwMjExX2hkciAqaGRyID0gKHN0cnVjdCBpZWVlODAyMTFfaGRy ICopc2tiLT5kYXRhOw0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAqbXN0YTsNCisJdTE2IHRpZDsNCisN CisJaWYgKCFzdGEtPmh0X2NhcC5odF9zdXBwb3J0ZWQpDQorCQlyZXR1cm47DQorDQorCWlmIChz a2JfZ2V0X3F1ZXVlX21hcHBpbmcoc2tiKSA9PSBJRUVFODAyMTFfQUNfVk8pDQorCQlyZXR1cm47 DQorDQorCWlmICh1bmxpa2VseSghaWVlZTgwMjExX2lzX2RhdGFfcW9zKGhkci0+ZnJhbWVfY29u dHJvbCkpKQ0KKwkJcmV0dXJuOw0KKw0KKwlpZiAodW5saWtlbHkoc2tiLT5wcm90b2NvbCA9PSBj cHVfdG9fYmUxNihFVEhfUF9QQUUpKSkNCisJCXJldHVybjsNCisNCisJbXN0YSA9IChzdHJ1Y3Qg bXQ3OTE1X3N0YSAqKXN0YS0+ZHJ2X3ByaXY7DQorCXRpZCA9IGllZWU4MDIxMV9nZXRfdGlkKGhk cik7DQorDQorCWlmIChtdDc5MTVfdHhfY2hlY2tfYWdncl90aWQobXN0YSwgdGlkKSkgew0KKwkJ aWVlZTgwMjExX3N0YXJ0X3R4X2JhX3Nlc3Npb24oc3RhLCB0aWQsIDApOw0KKwkJbXQ3OTE1X3Nl dF9hZ2dyX3N0YXRlKG1zdGEsIHRpZCwgTVQ3OTE1X0FHR1JfUFJPR1JFU1MpOw0KKwl9DQorfQ0K Kw0KK3N0YXRpYyBpbmxpbmUgdm9pZA0KK210NzkxNV90eF9zdGF0dXMoc3RydWN0IGllZWU4MDIx MV9zdGEgKnN0YSwgc3RydWN0IGllZWU4MDIxMV9odyAqaHcsDQorCQkgc3RydWN0IGllZWU4MDIx MV90eF9pbmZvICppbmZvLCBzdHJ1Y3Qgc2tfYnVmZiAqc2tiKQ0KK3sNCisJc3RydWN0IGllZWU4 MDIxMV90eF9zdGF0dXMgc3RhdHVzID0gew0KKwkJLnN0YSA9IHN0YSwNCisJCS5pbmZvID0gaW5m bywNCisJfTsNCisNCisJaWYgKHNrYikNCisJCXN0YXR1cy5za2IgPSBza2I7DQorDQorCWlmIChz dGEpIHsNCisJCXN0cnVjdCBtdDc5MTVfc3RhICptc3RhOw0KKw0KKwkJbXN0YSA9IChzdHJ1Y3Qg bXQ3OTE1X3N0YSAqKXN0YS0+ZHJ2X3ByaXY7DQorCQlzdGF0dXMucmF0ZSA9ICZtc3RhLT5zdGF0 cy50eF9yYXRlOw0KKwl9DQorDQorCWllZWU4MDIxMV90eF9zdGF0dXNfZXh0KGh3LCAmc3RhdHVz KTsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfdHhfY29tcGxldGVfc3RhdHVzKHN0cnVj dCBtdDc2X2RldiAqbWRldiwgc3RydWN0IHNrX2J1ZmYgKnNrYiwNCisJCQkgIHN0cnVjdCBpZWVl ODAyMTFfc3RhICpzdGEsIHU4IHN0YXQpDQorew0KKwlzdHJ1Y3QgaWVlZTgwMjExX3R4X2luZm8g KmluZm8gPSBJRUVFODAyMTFfU0tCX0NCKHNrYik7DQorCXN0cnVjdCBpZWVlODAyMTFfaHcgKmh3 Ow0KKw0KKwlodyA9IG10NzZfdHhfc3RhdHVzX2dldF9odyhtZGV2LCBza2IpOw0KKw0KKwlpZiAo aW5mby0+ZmxhZ3MgJiBJRUVFODAyMTFfVFhfQ1RMX0FNUERVKQ0KKwkJaW5mby0+ZmxhZ3MgfD0g SUVFRTgwMjExX1RYX1NUQVRfQU1QRFU7DQorCWVsc2UgaWYgKHN0YSkNCisJCW10NzkxNV90eF9j aGVja19hZ2dyKHN0YSwgc2tiKTsNCisNCisJaWYgKHN0YXQpDQorCQlpZWVlODAyMTFfdHhfaW5m b19jbGVhcl9zdGF0dXMoaW5mbyk7DQorDQorCWlmICghKGluZm8tPmZsYWdzICYgSUVFRTgwMjEx X1RYX0NUTF9OT19BQ0spKQ0KKwkJaW5mby0+ZmxhZ3MgfD0gSUVFRTgwMjExX1RYX1NUQVRfQUNL Ow0KKw0KKwlpbmZvLT5zdGF0dXMudHhfdGltZSA9IDA7DQorDQorCWlmIChpbmZvLT5mbGFncyAm IElFRUU4MDIxMV9UWF9DVExfUkVRX1RYX1NUQVRVUykgew0KKwkJbXQ3OTE1X3R4X3N0YXR1cyhz dGEsIGh3LCBpbmZvLCBza2IpOw0KKwkJcmV0dXJuOw0KKwl9DQorDQorCWlmIChzdGEgfHwgIShp bmZvLT5mbGFncyAmIElFRUU4MDIxMV9UWF9DVExfTk9fQUNLKSkNCisJCW10NzkxNV90eF9zdGF0 dXMoc3RhLCBodywgaW5mbywgTlVMTCk7DQorDQorCWRldl9rZnJlZV9za2Ioc2tiKTsNCit9DQor DQordm9pZCBtdDc5MTVfdHhwX3NrYl91bm1hcChzdHJ1Y3QgbXQ3Nl9kZXYgKmRldiwNCisJCQkg IHN0cnVjdCBtdDc2X3R4d2lfY2FjaGUgKnQpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X3R4cCAqdHhw Ow0KKwlpbnQgaTsNCisNCisJdHhwID0gbXQ3OTE1X3R4d2lfdG9fdHhwKGRldiwgdCk7DQorCWZv ciAoaSA9IDE7IGkgPCB0eHAtPm5idWY7IGkrKykNCisJCWRtYV91bm1hcF9zaW5nbGUoZGV2LT5k ZXYsIGxlMzJfdG9fY3B1KHR4cC0+YnVmW2ldKSwNCisJCQkJIGxlMTZfdG9fY3B1KHR4cC0+bGVu W2ldKSwgRE1BX1RPX0RFVklDRSk7DQorfQ0KKw0KK3ZvaWQgbXQ3OTE1X21hY190eF9mcmVlKHN0 cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBza19idWZmICpza2IpDQorew0KKwlzdHJ1Y3Qg bXQ3OTE1X3R4X2ZyZWUgKmZyZWUgPSAoc3RydWN0IG10NzkxNV90eF9mcmVlICopc2tiLT5kYXRh Ow0KKwlzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYgPSAmZGV2LT5tdDc2Ow0KKwlzdHJ1Y3QgbXQ3Nl90 eHdpX2NhY2hlICp0eHdpOw0KKwlzdHJ1Y3QgaWVlZTgwMjExX3N0YSAqc3RhID0gTlVMTDsNCisJ dTggaSwgY291bnQ7DQorDQorCS8qDQorCSAqIFRPRE86IE1UX1RYX0ZSRUVfTEFURU5DWSBpcyBt c2R1IHRpbWUgZnJvbSB0aGUgVFhEIGlzIHF1ZXVlZCBpbnRvIFBMRSwNCisJICogdG8gdGhlIHRp bWUgYWNrIGlzIHJlY2VpdmVkIG9yIGRyb3BwZWQgYnkgaHcgKGFpciArIGh3IHF1ZXVlIHRpbWUp Lg0KKwkgKiBTaG91bGQgYXZvaWQgYWNjZXNzaW5nIFdUQkwgdG8gZ2V0IFR4IGFpcnRpbWUsIGFu ZCB1c2UgaXQgaW5zdGVhZC4NCisJICovDQorCWNvdW50ID0gRklFTERfR0VUKE1UX1RYX0ZSRUVf TVNEVV9DTlQsIGxlMTZfdG9fY3B1KGZyZWUtPmN0cmwpKTsNCisJZm9yIChpID0gMDsgaSA8IGNv dW50OyBpKyspIHsNCisJCXUzMiBtc2R1LCBpbmZvID0gbGUzMl90b19jcHUoZnJlZS0+aW5mb1tp XSk7DQorCQl1OCBzdGF0Ow0KKw0KKwkJLyoNCisJCSAqIDEnYjE6IG5ldyB3Y2lkIHBhaXIuDQor CQkgKiAxJ2IwOiBtc2R1X2lkIHdpdGggdGhlIHNhbWUgJ3djaWQgcGFpcicgYXMgYWJvdmUuDQor CQkgKi8NCisJCWlmIChpbmZvICYgTVRfVFhfRlJFRV9QQUlSKSB7DQorCQkJc3RydWN0IG10Nzkx NV9zdGEgKm1zdGE7DQorCQkJc3RydWN0IG10NzZfd2NpZCAqd2NpZDsNCisJCQl1MTYgaWR4Ow0K Kw0KKwkJCWNvdW50Kys7DQorCQkJaWR4ID0gRklFTERfR0VUKE1UX1RYX0ZSRUVfV0xBTl9JRCwg aW5mbyk7DQorCQkJd2NpZCA9IHJjdV9kZXJlZmVyZW5jZShkZXYtPm10NzYud2NpZFtpZHhdKTsN CisJCQlzdGEgPSB3Y2lkX3RvX3N0YSh3Y2lkKTsNCisJCQlpZiAoIXN0YSkNCisJCQkJY29udGlu dWU7DQorDQorCQkJbXN0YSA9IGNvbnRhaW5lcl9vZih3Y2lkLCBzdHJ1Y3QgbXQ3OTE1X3N0YSwg d2NpZCk7DQorCQkJaWVlZTgwMjExX3F1ZXVlX3dvcmsobXQ3Nl9odyhkZXYpLCAmbXN0YS0+c3Rh dHNfd29yayk7DQorCQkJY29udGludWU7DQorCQl9DQorDQorCQltc2R1ID0gRklFTERfR0VUKE1U X1RYX0ZSRUVfTVNEVV9JRCwgaW5mbyk7DQorCQlzdGF0ID0gRklFTERfR0VUKE1UX1RYX0ZSRUVf U1RBVFVTLCBpbmZvKTsNCisNCisJCXNwaW5fbG9ja19iaCgmZGV2LT50b2tlbl9sb2NrKTsNCisJ CXR4d2kgPSBpZHJfcmVtb3ZlKCZkZXYtPnRva2VuLCBtc2R1KTsNCisJCXNwaW5fdW5sb2NrX2Jo KCZkZXYtPnRva2VuX2xvY2spOw0KKw0KKwkJaWYgKCF0eHdpKQ0KKwkJCWNvbnRpbnVlOw0KKw0K KwkJbXQ3OTE1X3R4cF9za2JfdW5tYXAobWRldiwgdHh3aSk7DQorCQlpZiAodHh3aS0+c2tiKSB7 DQorCQkJbXQ3OTE1X3R4X2NvbXBsZXRlX3N0YXR1cyhtZGV2LCB0eHdpLT5za2IsIHN0YSwgc3Rh dCk7DQorCQkJdHh3aS0+c2tiID0gTlVMTDsNCisJCX0NCisNCisJCW10NzZfcHV0X3R4d2kobWRl diwgdHh3aSk7DQorCX0NCisJZGV2X2tmcmVlX3NrYihza2IpOw0KK30NCisNCit2b2lkIG10Nzkx NV90eF9jb21wbGV0ZV9za2Ioc3RydWN0IG10NzZfZGV2ICptZGV2LCBlbnVtIG10NzZfdHhxX2lk IHFpZCwNCisJCQkgICAgc3RydWN0IG10NzZfcXVldWVfZW50cnkgKmUpDQorew0KKwlzdHJ1Y3Qg bXQ3OTE1X2RldiAqZGV2Ow0KKw0KKwlpZiAoIWUtPnR4d2kpIHsNCisJCWRldl9rZnJlZV9za2Jf YW55KGUtPnNrYik7DQorCQlyZXR1cm47DQorCX0NCisNCisJZGV2ID0gY29udGFpbmVyX29mKG1k ZXYsIHN0cnVjdCBtdDc5MTVfZGV2LCBtdDc2KTsNCisNCisJLyogZXJyb3IgcGF0aCAqLw0KKwlp ZiAoZS0+c2tiID09IERNQV9EVU1NWV9EQVRBKSB7DQorCQlzdHJ1Y3QgbXQ3Nl90eHdpX2NhY2hl ICp0Ow0KKwkJc3RydWN0IG10NzkxNV90eHAgKnR4cDsNCisNCisJCXR4cCA9IG10NzkxNV90eHdp X3RvX3R4cChtZGV2LCBlLT50eHdpKTsNCisNCisJCXNwaW5fbG9ja19iaCgmZGV2LT50b2tlbl9s b2NrKTsNCisJCXQgPSBpZHJfcmVtb3ZlKCZkZXYtPnRva2VuLCBsZTE2X3RvX2NwdSh0eHAtPnRv a2VuKSk7DQorCQlzcGluX3VubG9ja19iaCgmZGV2LT50b2tlbl9sb2NrKTsNCisJCWUtPnNrYiA9 IHQgPyB0LT5za2IgOiBOVUxMOw0KKwl9DQorDQorCWlmIChlLT5za2IpIHsNCisJCXN0cnVjdCBt dDc2X3R4X2NiICpjYiA9IG10NzZfdHhfc2tiX2NiKGUtPnNrYik7DQorCQlzdHJ1Y3QgbXQ3Nl93 Y2lkICp3Y2lkOw0KKw0KKwkJd2NpZCA9IHJjdV9kZXJlZmVyZW5jZShkZXYtPm10NzYud2NpZFtj Yi0+d2NpZF0pOw0KKw0KKwkJbXQ3OTE1X3R4X2NvbXBsZXRlX3N0YXR1cyhtZGV2LCBlLT5za2Is IHdjaWRfdG9fc3RhKHdjaWQpLCAwKTsNCisJfQ0KK30NCisNCit2b2lkIG10NzkxNV9tYWNfY2Nh X3N0YXRzX3Jlc2V0KHN0cnVjdCBtdDc5MTVfcGh5ICpwaHkpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1 X2RldiAqZGV2ID0gcGh5LT5kZXY7DQorCWJvb2wgZXh0X3BoeSA9IHBoeSAhPSAmZGV2LT5waHk7 DQorCXUzMiByZWcgPSBNVF9XRl9QSFlfUlhfQ1RSTDEoZXh0X3BoeSk7DQorDQorCW10NzkxNV9s Ml9jbGVhcihkZXYsIHJlZywgTVRfV0ZfUEhZX1JYX0NUUkwxX1NUU0NOVF9FTik7DQorCW10Nzkx NV9sMl9zZXQoZGV2LCByZWcsIEJJVCgxMSkgfCBCSVQoOSkpOw0KK30NCisNCit2b2lkIG10Nzkx NV9tYWNfcmVzZXRfY291bnRlcnMoc3RydWN0IG10NzkxNV9waHkgKnBoeSkNCit7DQorCXN0cnVj dCBtdDc5MTVfZGV2ICpkZXYgPSBwaHktPmRldjsNCisJYm9vbCBleHRfcGh5ID0gcGh5ICE9ICZk ZXYtPnBoeTsNCisJaW50IGk7DQorDQorCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHsNCisJCW10 NzZfcnIoZGV2LCBNVF9UWF9BR0dfQ05UKGV4dF9waHksIGkpKTsNCisJCW10NzZfcnIoZGV2LCBN VF9UWF9BR0dfQ05UMihleHRfcGh5LCBpKSk7DQorCX0NCisNCisJaWYgKGV4dF9waHkpIHsNCisJ CWRldi0+bXQ3Ni5waHkyLT5zdXJ2ZXlfdGltZSA9IGt0aW1lX2dldF9ib290dGltZSgpOw0KKwkJ aSA9IEFSUkFZX1NJWkUoZGV2LT5tdDc2LmFnZ3Jfc3RhdHMpIC8gMjsNCisJfSBlbHNlIHsNCisJ CWRldi0+bXQ3Ni5waHkuc3VydmV5X3RpbWUgPSBrdGltZV9nZXRfYm9vdHRpbWUoKTsNCisJCWkg PSAwOw0KKwl9DQorCW1lbXNldCgmZGV2LT5tdDc2LmFnZ3Jfc3RhdHNbaV0sIDAsIHNpemVvZihk ZXYtPm10NzYuYWdncl9zdGF0cykgLyAyKTsNCisNCisJLyogcmVzZXQgYWlydGltZSBjb3VudGVy cyAqLw0KKwltdDc2X3JyKGRldiwgTVRfTUlCX1NEUjkoZXh0X3BoeSkpOw0KKwltdDc2X3JyKGRl diwgTVRfTUlCX1NEUjM2KGV4dF9waHkpKTsNCisJbXQ3Nl9ycihkZXYsIE1UX01JQl9TRFIzNyhl eHRfcGh5KSk7DQorDQorCW10NzZfc2V0KGRldiwgTVRfV0ZfUk1BQ19NSUJfVElNRTAoZXh0X3Bo eSksDQorCQkgTVRfV0ZfUk1BQ19NSUJfUlhUSU1FX0NMUik7DQorCW10NzZfc2V0KGRldiwgTVRf V0ZfUk1BQ19NSUJfQUlSVElNRTAoZXh0X3BoeSksDQorCQkgTVRfV0ZfUk1BQ19NSUJfUlhUSU1F X0NMUik7DQorfQ0KKw0KK3ZvaWQgbXQ3OTE1X21hY19zZXRfdGltaW5nKHN0cnVjdCBtdDc5MTVf cGh5ICpwaHkpDQorew0KKwlzMTYgY292ZXJhZ2VfY2xhc3MgPSBwaHktPmNvdmVyYWdlX2NsYXNz Ow0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gcGh5LT5kZXY7DQorCWJvb2wgZXh0X3BoeSA9 IHBoeSAhPSAmZGV2LT5waHk7DQorCXUzMiB2YWwsIHJlZ19vZmZzZXQ7DQorCXUzMiBjY2sgPSBG SUVMRF9QUkVQKE1UX1RJTUVPVVRfVkFMX1BMQ1AsIDIzMSkgfA0KKwkJICBGSUVMRF9QUkVQKE1U X1RJTUVPVVRfVkFMX0NDQSwgNDgpOw0KKwl1MzIgb2ZkbSA9IEZJRUxEX1BSRVAoTVRfVElNRU9V VF9WQUxfUExDUCwgNjApIHwNCisJCSAgIEZJRUxEX1BSRVAoTVRfVElNRU9VVF9WQUxfQ0NBLCAy NCk7DQorCWludCBzaWZzLCBvZmZzZXQ7DQorDQorCWlmIChwaHktPm10NzYtPmNoYW5kZWYuY2hh bi0+YmFuZCA9PSBOTDgwMjExX0JBTkRfNUdIWikNCisJCXNpZnMgPSAxNjsNCisJZWxzZQ0KKwkJ c2lmcyA9IDEwOw0KKw0KKwlpZiAoZXh0X3BoeSkgew0KKwkJY292ZXJhZ2VfY2xhc3MgPSBtYXhf dChzMTYsIGRldi0+cGh5LmNvdmVyYWdlX2NsYXNzLA0KKwkJCQkgICAgICAgY292ZXJhZ2VfY2xh c3MpOw0KKwl9IGVsc2Ugew0KKwkJc3RydWN0IG10NzkxNV9waHkgKnBoeV9leHQgPSBtdDc5MTVf ZXh0X3BoeShkZXYpOw0KKw0KKwkJaWYgKHBoeV9leHQpDQorCQkJY292ZXJhZ2VfY2xhc3MgPSBt YXhfdChzMTYsIHBoeV9leHQtPmNvdmVyYWdlX2NsYXNzLA0KKwkJCQkJICAgICAgIGNvdmVyYWdl X2NsYXNzKTsNCisJfQ0KKwltdDc2X3NldChkZXYsIE1UX0FSQl9TQ1IoZXh0X3BoeSksDQorCQkg TVRfQVJCX1NDUl9UWF9ESVNBQkxFIHwgTVRfQVJCX1NDUl9SWF9ESVNBQkxFKTsNCisJdWRlbGF5 KDEpOw0KKw0KKwlvZmZzZXQgPSAzICogY292ZXJhZ2VfY2xhc3M7DQorCXJlZ19vZmZzZXQgPSBG SUVMRF9QUkVQKE1UX1RJTUVPVVRfVkFMX1BMQ1AsIG9mZnNldCkgfA0KKwkJICAgICBGSUVMRF9Q UkVQKE1UX1RJTUVPVVRfVkFMX0NDQSwgb2Zmc2V0KTsNCisNCisJbXQ3Nl93cihkZXYsIE1UX1RN QUNfQ0RUUihleHRfcGh5KSwgY2NrICsgcmVnX29mZnNldCk7DQorCW10NzZfd3IoZGV2LCBNVF9U TUFDX09EVFIoZXh0X3BoeSksIG9mZG0gKyByZWdfb2Zmc2V0KTsNCisJbXQ3Nl93cihkZXYsIE1U X1RNQUNfSUNSMChleHRfcGh5KSwNCisJCUZJRUxEX1BSRVAoTVRfSUZTX0VJRlMsIDM2MCkgfA0K KwkJRklFTERfUFJFUChNVF9JRlNfUklGUywgMikgfA0KKwkJRklFTERfUFJFUChNVF9JRlNfU0lG Uywgc2lmcykgfA0KKwkJRklFTERfUFJFUChNVF9JRlNfU0xPVCwgcGh5LT5zbG90dGltZSkpOw0K Kw0KKwlpZiAocGh5LT5zbG90dGltZSA8IDIwKQ0KKwkJdmFsID0gTVQ3OTE1X0NGRU5EX1JBVEVf REVGQVVMVDsNCisJZWxzZQ0KKwkJdmFsID0gTVQ3OTE1X0NGRU5EX1JBVEVfMTFCOw0KKw0KKwlt dDc2X3Jtd19maWVsZChkZXYsIE1UX0FHR19BQ1IwKGV4dF9waHkpLCBNVF9BR0dfQUNSX0NGRU5E X1JBVEUsIHZhbCk7DQorCW10NzZfY2xlYXIoZGV2LCBNVF9BUkJfU0NSKGV4dF9waHkpLA0KKwkJ ICAgTVRfQVJCX1NDUl9UWF9ESVNBQkxFIHwgTVRfQVJCX1NDUl9SWF9ESVNBQkxFKTsNCit9DQor DQorc3RhdGljIHZvaWQNCittdDc5MTVfcGh5X3VwZGF0ZV9jaGFubmVsKHN0cnVjdCBtdDc2X3Bo eSAqbXBoeSwgaW50IGlkeCkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBjb250YWlu ZXJfb2YobXBoeS0+ZGV2LCBzdHJ1Y3QgbXQ3OTE1X2RldiwgbXQ3Nik7DQorCXN0cnVjdCBtdDc2 X2NoYW5uZWxfc3RhdGUgKnN0YXRlOw0KKwl1NjQgYnVzeV90aW1lLCB0eF90aW1lLCByeF90aW1l LCBvYnNzX3RpbWU7DQorDQorCWJ1c3lfdGltZSA9IG10NzZfZ2V0X2ZpZWxkKGRldiwgTVRfTUlC X1NEUjkoaWR4KSwNCisJCQkJICAgTVRfTUlCX1NEUjlfQlVTWV9NQVNLKTsNCisJdHhfdGltZSA9 IG10NzZfZ2V0X2ZpZWxkKGRldiwgTVRfTUlCX1NEUjM2KGlkeCksDQorCQkJCSBNVF9NSUJfU0RS MzZfVFhUSU1FX01BU0spOw0KKwlyeF90aW1lID0gbXQ3Nl9nZXRfZmllbGQoZGV2LCBNVF9NSUJf U0RSMzcoaWR4KSwNCisJCQkJIE1UX01JQl9TRFIzN19SWFRJTUVfTUFTSyk7DQorCW9ic3NfdGlt ZSA9IG10NzZfZ2V0X2ZpZWxkKGRldiwgTVRfV0ZfUk1BQ19NSUJfQUlSVElNRTE0KGlkeCksDQor CQkJCSAgIE1UX01JQl9PQlNTVElNRV9NQVNLKTsNCisNCisJLyogVE9ETzogc3RhdGUtPm5vaXNl ICovDQorCXN0YXRlID0gbXBoeS0+Y2hhbl9zdGF0ZTsNCisJc3RhdGUtPmNjX2J1c3kgKz0gYnVz eV90aW1lOw0KKwlzdGF0ZS0+Y2NfdHggKz0gdHhfdGltZTsNCisJc3RhdGUtPmNjX3J4ICs9IHJ4 X3RpbWUgKyBvYnNzX3RpbWU7DQorCXN0YXRlLT5jY19ic3NfcnggKz0gcnhfdGltZTsNCit9DQor DQordm9pZCBtdDc5MTVfdXBkYXRlX2NoYW5uZWwoc3RydWN0IG10NzZfZGV2ICptZGV2KQ0KK3sN CisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IGNvbnRhaW5lcl9vZihtZGV2LCBzdHJ1Y3QgbXQ3 OTE1X2RldiwgbXQ3Nik7DQorDQorCW10NzkxNV9waHlfdXBkYXRlX2NoYW5uZWwoJm1kZXYtPnBo eSwgMCk7DQorCWlmIChtZGV2LT5waHkyKQ0KKwkJbXQ3OTE1X3BoeV91cGRhdGVfY2hhbm5lbCht ZGV2LT5waHkyLCAxKTsNCisNCisJLyogcmVzZXQgb2JzcyBhaXJ0aW1lICovDQorCW10NzZfc2V0 KGRldiwgTVRfV0ZfUk1BQ19NSUJfVElNRTAoMCksIE1UX1dGX1JNQUNfTUlCX1JYVElNRV9DTFIp Ow0KKwlpZiAobWRldi0+cGh5MikNCisJCW10NzZfc2V0KGRldiwgTVRfV0ZfUk1BQ19NSUJfVElN RTAoMSksDQorCQkJIE1UX1dGX1JNQUNfTUlCX1JYVElNRV9DTFIpOw0KK30NCisNCitzdGF0aWMg Ym9vbA0KK210NzkxNV93YWl0X3Jlc2V0X3N0YXRlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUz MiBzdGF0ZSkNCit7DQorCWJvb2wgcmV0Ow0KKw0KKwlyZXQgPSB3YWl0X2V2ZW50X3RpbWVvdXQo ZGV2LT5yZXNldF93YWl0LA0KKwkJCQkgKFJFQURfT05DRShkZXYtPnJlc2V0X3N0YXRlKSAmIHN0 YXRlKSwNCisJCQkJIE1UNzkxNV9SRVNFVF9USU1FT1VUKTsNCisNCisJV0FSTighcmV0LCAiVGlt ZW91dCB3YWl0aW5nIGZvciBNQ1UgcmVzZXQgc3RhdGUgJXhcbiIsIHN0YXRlKTsNCisJcmV0dXJu IHJldDsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfdXBkYXRlX3ZpZl9iZWFjb24odm9p ZCAqcHJpdiwgdTggKm1hYywgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZikNCit7DQorCXN0cnVj dCBpZWVlODAyMTFfaHcgKmh3ID0gcHJpdjsNCisNCisJbXQ3OTE1X21jdV9hZGRfYmVhY29uKGh3 LCB2aWYsIHZpZi0+YnNzX2NvbmYuZW5hYmxlX2JlYWNvbik7DQorfQ0KKw0KK3N0YXRpYyB2b2lk DQorbXQ3OTE1X3VwZGF0ZV9iZWFjb25zKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlp ZWVlODAyMTFfaXRlcmF0ZV9hY3RpdmVfaW50ZXJmYWNlcyhkZXYtPm10NzYuaHcsDQorCQlJRUVF ODAyMTFfSUZBQ0VfSVRFUl9SRVNVTUVfQUxMLA0KKwkJbXQ3OTE1X3VwZGF0ZV92aWZfYmVhY29u LCBkZXYtPm10NzYuaHcpOw0KKw0KKwlpZiAoIWRldi0+bXQ3Ni5waHkyKQ0KKwkJcmV0dXJuOw0K Kw0KKwlpZWVlODAyMTFfaXRlcmF0ZV9hY3RpdmVfaW50ZXJmYWNlcyhkZXYtPm10NzYucGh5Mi0+ aHcsDQorCQlJRUVFODAyMTFfSUZBQ0VfSVRFUl9SRVNVTUVfQUxMLA0KKwkJbXQ3OTE1X3VwZGF0 ZV92aWZfYmVhY29uLCBkZXYtPm10NzYucGh5Mi0+aHcpOw0KK30NCisNCitzdGF0aWMgdm9pZA0K K210NzkxNV9kbWFfcmVzZXQoc3RydWN0IG10NzkxNV9kZXYgKmRldikNCit7DQorCWludCBpOw0K Kw0KKwltdDc2X2NsZWFyKGRldiwgTVRfV0ZETUEwX0dMT19DRkcsDQorCQkgICBNVF9XRkRNQTBf R0xPX0NGR19UWF9ETUFfRU4gfCBNVF9XRkRNQTBfR0xPX0NGR19SWF9ETUFfRU4pOw0KKwltdDc2 X2NsZWFyKGRldiwgTVRfV0ZETUExX0dMT19DRkcsDQorCQkgICBNVF9XRkRNQTFfR0xPX0NGR19U WF9ETUFfRU4gfCBNVF9XRkRNQTFfR0xPX0NGR19SWF9ETUFfRU4pOw0KKwl1c2xlZXBfcmFuZ2Uo MTAwMCwgMjAwMCk7DQorDQorCWZvciAoaSA9IDA7IGkgPCBfX01UX1RYUV9NQVg7IGkrKykNCisJ CW10NzZfcXVldWVfdHhfY2xlYW51cChkZXYsIGksIHRydWUpOw0KKw0KKwlmb3IgKGkgPSAwOyBp IDwgQVJSQVlfU0laRShkZXYtPm10NzYucV9yeCk7IGkrKykNCisJCW10NzZfcXVldWVfcnhfcmVz ZXQoZGV2LCBpKTsNCisNCisJLyogcmUtaW5pdCBwcmVmZXRjaCBzZXR0aW5ncyBhZnRlciByZXNl dCAqLw0KKwltdDc5MTVfZG1hX3ByZWZldGNoKGRldik7DQorDQorCW10NzZfc2V0KGRldiwgTVRf V0ZETUEwX0dMT19DRkcsDQorCQkgTVRfV0ZETUEwX0dMT19DRkdfVFhfRE1BX0VOIHwgTVRfV0ZE TUEwX0dMT19DRkdfUlhfRE1BX0VOKTsNCisJbXQ3Nl9zZXQoZGV2LCBNVF9XRkRNQTFfR0xPX0NG RywNCisJCSBNVF9XRkRNQTFfR0xPX0NGR19UWF9ETUFfRU4gfCBNVF9XRkRNQTFfR0xPX0NGR19S WF9ETUFfRU4pOw0KK30NCisNCisvKiBzeXN0ZW0gZXJyb3IgcmVjb3ZlcnkgKi8NCit2b2lkIG10 NzkxNV9tYWNfcmVzZXRfd29yayhzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQorew0KKwlzdHJ1 Y3QgbXQ3OTE1X2RldiAqZGV2Ow0KKw0KKwlkZXYgPSBjb250YWluZXJfb2Yod29yaywgc3RydWN0 IG10NzkxNV9kZXYsIHJlc2V0X3dvcmspOw0KKw0KKwlpZiAoIShSRUFEX09OQ0UoZGV2LT5yZXNl dF9zdGF0ZSkgJiBNVF9NQ1VfQ01EX1NUT1BfRE1BKSkNCisJCXJldHVybjsNCisNCisJaWVlZTgw MjExX3N0b3BfcXVldWVzKG10NzZfaHcoZGV2KSk7DQorCWlmIChkZXYtPm10NzYucGh5MikNCisJ CWllZWU4MDIxMV9zdG9wX3F1ZXVlcyhkZXYtPm10NzYucGh5Mi0+aHcpOw0KKw0KKwlzZXRfYml0 KE1UNzZfUkVTRVQsICZkZXYtPm1waHkuc3RhdGUpOw0KKwlzZXRfYml0KE1UNzZfTUNVX1JFU0VU LCAmZGV2LT5tcGh5LnN0YXRlKTsNCisJd2FrZV91cCgmZGV2LT5tdDc2Lm1jdS53YWl0KTsNCisJ Y2FuY2VsX2RlbGF5ZWRfd29ya19zeW5jKCZkZXYtPm10NzYubWFjX3dvcmspOw0KKw0KKwkvKiBs b2NrL3VubG9jayBhbGwgcXVldWVzIHRvIGVuc3VyZSB0aGF0IG5vIHR4IGlzIHBlbmRpbmcgKi8N CisJbXQ3Nl90eHFfc2NoZWR1bGVfYWxsKCZkZXYtPm1waHkpOw0KKwlpZiAoZGV2LT5tdDc2LnBo eTIpDQorCQltdDc2X3R4cV9zY2hlZHVsZV9hbGwoZGV2LT5tdDc2LnBoeTIpOw0KKw0KKwl0YXNr bGV0X2Rpc2FibGUoJmRldi0+bXQ3Ni50eF90YXNrbGV0KTsNCisJbmFwaV9kaXNhYmxlKCZkZXYt Pm10NzYubmFwaVswXSk7DQorCW5hcGlfZGlzYWJsZSgmZGV2LT5tdDc2Lm5hcGlbMV0pOw0KKwlu YXBpX2Rpc2FibGUoJmRldi0+bXQ3Ni5uYXBpWzJdKTsNCisJbmFwaV9kaXNhYmxlKCZkZXYtPm10 NzYudHhfbmFwaSk7DQorDQorCW11dGV4X2xvY2soJmRldi0+bXQ3Ni5tdXRleCk7DQorDQorCW10 NzZfd3IoZGV2LCBNVF9NQ1VfSU5UX0VWRU5ULCBNVF9NQ1VfSU5UX0VWRU5UX0RNQV9TVE9QUEVE KTsNCisNCisJaWYgKG10NzkxNV93YWl0X3Jlc2V0X3N0YXRlKGRldiwgTVRfTUNVX0NNRF9SRVNF VF9ET05FKSkgew0KKwkJbXQ3OTE1X2RtYV9yZXNldChkZXYpOw0KKw0KKwkJbXQ3Nl93cihkZXYs IE1UX01DVV9JTlRfRVZFTlQsIE1UX01DVV9JTlRfRVZFTlRfRE1BX0lOSVQpOw0KKwkJbXQ3OTE1 X3dhaXRfcmVzZXRfc3RhdGUoZGV2LCBNVF9NQ1VfQ01EX1JFQ09WRVJZX0RPTkUpOw0KKwl9DQor DQorCWNsZWFyX2JpdChNVDc2X01DVV9SRVNFVCwgJmRldi0+bXBoeS5zdGF0ZSk7DQorCWNsZWFy X2JpdChNVDc2X1JFU0VULCAmZGV2LT5tcGh5LnN0YXRlKTsNCisNCisJdGFza2xldF9lbmFibGUo JmRldi0+bXQ3Ni50eF90YXNrbGV0KTsNCisJbmFwaV9lbmFibGUoJmRldi0+bXQ3Ni50eF9uYXBp KTsNCisJbmFwaV9zY2hlZHVsZSgmZGV2LT5tdDc2LnR4X25hcGkpOw0KKw0KKwluYXBpX2VuYWJs ZSgmZGV2LT5tdDc2Lm5hcGlbMF0pOw0KKwluYXBpX3NjaGVkdWxlKCZkZXYtPm10NzYubmFwaVsw XSk7DQorDQorCW5hcGlfZW5hYmxlKCZkZXYtPm10NzYubmFwaVsxXSk7DQorCW5hcGlfc2NoZWR1 bGUoJmRldi0+bXQ3Ni5uYXBpWzFdKTsNCisNCisJbmFwaV9lbmFibGUoJmRldi0+bXQ3Ni5uYXBp WzJdKTsNCisJbmFwaV9zY2hlZHVsZSgmZGV2LT5tdDc2Lm5hcGlbMl0pOw0KKw0KKwlpZWVlODAy MTFfd2FrZV9xdWV1ZXMobXQ3Nl9odyhkZXYpKTsNCisJaWYgKGRldi0+bXQ3Ni5waHkyKQ0KKwkJ aWVlZTgwMjExX3dha2VfcXVldWVzKGRldi0+bXQ3Ni5waHkyLT5odyk7DQorDQorCW10NzZfd3Io ZGV2LCBNVF9NQ1VfSU5UX0VWRU5ULCBNVF9NQ1VfSU5UX0VWRU5UX1JFU0VUX0RPTkUpOw0KKwlt dDc5MTVfd2FpdF9yZXNldF9zdGF0ZShkZXYsIE1UX01DVV9DTURfTk9STUFMX1NUQVRFKTsNCisN CisJbXV0ZXhfdW5sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKw0KKwltdDc5MTVfdXBkYXRlX2Jl YWNvbnMoZGV2KTsNCisNCisJaWVlZTgwMjExX3F1ZXVlX2RlbGF5ZWRfd29yayhtdDc2X2h3KGRl diksICZkZXYtPm10NzYubWFjX3dvcmssDQorCQkJCSAgICAgTVQ3OTE1X1dBVENIRE9HX1RJTUUp Ow0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9tYWNfdXBkYXRlX21pYl9zdGF0cyhzdHJ1 Y3QgbXQ3OTE1X3BoeSAqcGh5KQ0KK3sNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IHBoeS0+ ZGV2Ow0KKwlzdHJ1Y3QgbWliX3N0YXRzICptaWIgPSAmcGh5LT5taWI7DQorCWJvb2wgZXh0X3Bo eSA9IHBoeSAhPSAmZGV2LT5waHk7DQorCWludCBpLCBhZ2dyMCwgYWdncjE7DQorDQorCW1lbXNl dChtaWIsIDAsIHNpemVvZigqbWliKSk7DQorDQorCW1pYi0+ZmNzX2Vycl9jbnQgPSBtdDc2X2dl dF9maWVsZChkZXYsIE1UX01JQl9TRFIzKGV4dF9waHkpLA0KKwkJCQkJICBNVF9NSUJfU0RSM19G Q1NfRVJSX01BU0spOw0KKw0KKwlhZ2dyMCA9IGV4dF9waHkgPyBBUlJBWV9TSVpFKGRldi0+bXQ3 Ni5hZ2dyX3N0YXRzKSAvIDIgOiAwOw0KKwlmb3IgKGkgPSAwLCBhZ2dyMSA9IGFnZ3IwICsgNDsg aSA8IDQ7IGkrKykgew0KKwkJdTMyIHZhbCwgdmFsMjsNCisNCisJCXZhbCA9IG10NzZfcnIoZGV2 LCBNVF9NSUJfTUJfU0RSMShleHRfcGh5LCBpKSk7DQorDQorCQl2YWwyID0gRklFTERfR0VUKE1U X01JQl9BQ0tfRkFJTF9DT1VOVF9NQVNLLCB2YWwpOw0KKwkJaWYgKHZhbDIgPiBtaWItPmFja19m YWlsX2NudCkNCisJCQltaWItPmFja19mYWlsX2NudCA9IHZhbDI7DQorDQorCQl2YWwyID0gRklF TERfR0VUKE1UX01JQl9CQV9NSVNTX0NPVU5UX01BU0ssIHZhbCk7DQorCQlpZiAodmFsMiA+IG1p Yi0+YmFfbWlzc19jbnQpDQorCQkJbWliLT5iYV9taXNzX2NudCA9IHZhbDI7DQorDQorCQl2YWwg PSBtdDc2X3JyKGRldiwgTVRfTUlCX01CX1NEUjAoZXh0X3BoeSwgaSkpOw0KKwkJdmFsMiA9IEZJ RUxEX0dFVChNVF9NSUJfUlRTX1JFVFJJRVNfQ09VTlRfTUFTSywgdmFsKTsNCisJCWlmICh2YWwy ID4gbWliLT5ydHNfcmV0cmllc19jbnQpIHsNCisJCQltaWItPnJ0c19jbnQgPSBGSUVMRF9HRVQo TVRfTUlCX1JUU19DT1VOVF9NQVNLLCB2YWwpOw0KKwkJCW1pYi0+cnRzX3JldHJpZXNfY250ID0g dmFsMjsNCisJCX0NCisNCisJCXZhbCA9IG10NzZfcnIoZGV2LCBNVF9UWF9BR0dfQ05UKGV4dF9w aHksIGkpKTsNCisJCXZhbDIgPSBtdDc2X3JyKGRldiwgTVRfVFhfQUdHX0NOVDIoZXh0X3BoeSwg aSkpOw0KKw0KKwkJZGV2LT5tdDc2LmFnZ3Jfc3RhdHNbYWdncjArK10gKz0gdmFsICYgMHhmZmZm Ow0KKwkJZGV2LT5tdDc2LmFnZ3Jfc3RhdHNbYWdncjArK10gKz0gdmFsID4+IDE2Ow0KKwkJZGV2 LT5tdDc2LmFnZ3Jfc3RhdHNbYWdncjErK10gKz0gdmFsMiAmIDB4ZmZmZjsNCisJCWRldi0+bXQ3 Ni5hZ2dyX3N0YXRzW2FnZ3IxKytdICs9IHZhbDIgPj4gMTY7DQorCX0NCit9DQorDQordm9pZCBt dDc5MTVfbWFjX3N0YV9zdGF0c193b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykNCit7DQor CXN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGE7DQorCXN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWY7 DQorCXN0cnVjdCBtdDc5MTVfc3RhX3N0YXRzICpzdGF0czsNCisJc3RydWN0IG10NzkxNV9zdGEg Km1zdGE7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXY7DQorDQorCW1zdGEgPSBjb250YWluZXJf b2Yod29yaywgc3RydWN0IG10NzkxNV9zdGEsIHN0YXRzX3dvcmspOw0KKwlzdGEgPSBjb250YWlu ZXJfb2YoKHZvaWQgKiltc3RhLCBzdHJ1Y3QgaWVlZTgwMjExX3N0YSwgZHJ2X3ByaXYpOw0KKwl2 aWYgPSBjb250YWluZXJfb2YoKHZvaWQgKiltc3RhLT52aWYsIHN0cnVjdCBpZWVlODAyMTFfdmlm LCBkcnZfcHJpdik7DQorCWRldiA9IG1zdGEtPnZpZi0+ZGV2Ow0KKwlzdGF0cyA9ICZtc3RhLT5z dGF0czsNCisNCisJLyogdXNlIE1UX1RYX0ZSRUVfUkFURSB0byByZXBvcnQgVHggcmF0ZSBmb3Ig ZnVydGhlciBkZXZpY2VzICovDQorCWlmICh0aW1lX2FmdGVyKGppZmZpZXMsIHN0YXRzLT5qaWZm aWVzICsgSFopKSB7DQorCQltdDc5MTVfbWN1X2dldF9yYXRlX2luZm8oZGV2LCBSQVRFX0NUUkxf UlVfSU5GTywNCisJCQkJCSBtc3RhLT53Y2lkLmlkeCk7DQorDQorCQlzdGF0cy0+amlmZmllcyA9 IGppZmZpZXM7DQorCX0NCisNCisJaWYgKHRlc3RfYW5kX2NsZWFyX2JpdChJRUVFODAyMTFfUkNf U1VQUF9SQVRFU19DSEFOR0VEIHwNCisJCQkgICAgICAgSUVFRTgwMjExX1JDX05TU19DSEFOR0VE IHwNCisJCQkgICAgICAgSUVFRTgwMjExX1JDX0JXX0NIQU5HRUQsICZzdGF0cy0+Y2hhbmdlZCkp DQorCQltdDc5MTVfbWN1X2FkZF9yYXRlX2N0cmwoZGV2LCB2aWYsIHN0YSk7DQorDQorCWlmICh0 ZXN0X2FuZF9jbGVhcl9iaXQoSUVFRTgwMjExX1JDX1NNUFNfQ0hBTkdFRCwgJnN0YXRzLT5jaGFu Z2VkKSkNCisJCW10NzkxNV9tY3VfYWRkX3NtcHMoZGV2LCB2aWYsIHN0YSk7DQorDQorCXNwaW5f bG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2NrKTsNCisJaWYgKGxpc3RfZW1wdHkoJm1zdGEtPnBv bGxfbGlzdCkpDQorCQlsaXN0X2FkZF90YWlsKCZtc3RhLT5wb2xsX2xpc3QsICZkZXYtPnN0YV9w b2xsX2xpc3QpOw0KKwlzcGluX3VubG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2NrKTsNCit9DQor DQordm9pZCBtdDc5MTVfbWFjX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KK3sNCisJ c3RydWN0IG10NzkxNV9kZXYgKmRldjsNCisNCisJZGV2ID0gKHN0cnVjdCBtdDc5MTVfZGV2ICop Y29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBtdDc2X2RldiwNCisJCQkJCQltYWNfd29yay53b3Jr KTsNCisNCisJbXV0ZXhfbG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisJbXQ3Nl91cGRhdGVfc3Vy dmV5KCZkZXYtPm10NzYpOw0KKwlpZiAoKytkZXYtPm1hY193b3JrX2NvdW50ID09IDUpIHsNCisJ CXN0cnVjdCBtdDc5MTVfcGh5ICpleHRfcGh5ID0gbXQ3OTE1X2V4dF9waHkoZGV2KTsNCisNCisJ CW10NzkxNV9tYWNfdXBkYXRlX21pYl9zdGF0cygmZGV2LT5waHkpOw0KKwkJaWYgKGV4dF9waHkp DQorCQkJbXQ3OTE1X21hY191cGRhdGVfbWliX3N0YXRzKGV4dF9waHkpOw0KKw0KKwkJZGV2LT5t YWNfd29ya19jb3VudCA9IDA7DQorCX0NCisJbXV0ZXhfdW5sb2NrKCZkZXYtPm10NzYubXV0ZXgp Ow0KKw0KKwlpZWVlODAyMTFfcXVldWVfZGVsYXllZF93b3JrKG10NzZfaHcoZGV2KSwgJmRldi0+ bXQ3Ni5tYWNfd29yaywNCisJCQkJICAgICBNVDc5MTVfV0FUQ0hET0dfVElNRSk7DQorfQ0KKw0K K3N0YXRpYyB2b2lkIG10NzkxNV9kZnNfc3RvcF9yYWRhcl9kZXRlY3RvcihzdHJ1Y3QgbXQ3OTE1 X3BoeSAqcGh5KQ0KK3sNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IHBoeS0+ZGV2Ow0KKw0K KwlpZiAocGh5LT5yZGRfc3RhdGUgJiBCSVQoMCkpDQorCQltdDc5MTVfbWN1X3JkZF9jbWQoZGV2 LCBSRERfU1RPUCwgMCwgTVRfUlhfU0VMMCwgMCk7DQorCWlmIChwaHktPnJkZF9zdGF0ZSAmIEJJ VCgxKSkNCisJCW10NzkxNV9tY3VfcmRkX2NtZChkZXYsIFJERF9TVE9QLCAxLCBNVF9SWF9TRUww LCAwKTsNCit9DQorDQorc3RhdGljIGludCBtdDc5MTVfZGZzX3N0YXJ0X3JkZChzdHJ1Y3QgbXQ3 OTE1X2RldiAqZGV2LCBpbnQgY2hhaW4pDQorew0KKwlpbnQgZXJyOw0KKw0KKwllcnIgPSBtdDc5 MTVfbWN1X3JkZF9jbWQoZGV2LCBSRERfU1RBUlQsIGNoYWluLCBNVF9SWF9TRUwwLCAwKTsNCisJ aWYgKGVyciA8IDApDQorCQlyZXR1cm4gZXJyOw0KKw0KKwlyZXR1cm4gbXQ3OTE1X21jdV9yZGRf Y21kKGRldiwgUkREX0RFVF9NT0RFLCBjaGFpbiwgTVRfUlhfU0VMMCwgMSk7DQorfQ0KKw0KK3N0 YXRpYyBpbnQgbXQ3OTE1X2Rmc19zdGFydF9yYWRhcl9kZXRlY3RvcihzdHJ1Y3QgbXQ3OTE1X3Bo eSAqcGh5KQ0KK3sNCisJc3RydWN0IGNmZzgwMjExX2NoYW5fZGVmICpjaGFuZGVmID0gJnBoeS0+ bXQ3Ni0+Y2hhbmRlZjsNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IHBoeS0+ZGV2Ow0KKwli b29sIGV4dF9waHkgPSBwaHkgIT0gJmRldi0+cGh5Ow0KKwlpbnQgZXJyOw0KKw0KKwkvKiBzdGFy dCBDQUMgKi8NCisJZXJyID0gbXQ3OTE1X21jdV9yZGRfY21kKGRldiwgUkREX0NBQ19TVEFSVCwg ZXh0X3BoeSwgTVRfUlhfU0VMMCwgMCk7DQorCWlmIChlcnIgPCAwKQ0KKwkJcmV0dXJuIGVycjsN CisNCisJZXJyID0gbXQ3OTE1X2Rmc19zdGFydF9yZGQoZGV2LCBleHRfcGh5KTsNCisJaWYgKGVy ciA8IDApDQorCQlyZXR1cm4gZXJyOw0KKw0KKwlwaHktPnJkZF9zdGF0ZSB8PSBCSVQoZXh0X3Bo eSk7DQorDQorCWlmIChjaGFuZGVmLT53aWR0aCA9PSBOTDgwMjExX0NIQU5fV0lEVEhfMTYwIHx8 DQorCSAgICBjaGFuZGVmLT53aWR0aCA9PSBOTDgwMjExX0NIQU5fV0lEVEhfODBQODApIHsNCisJ CWVyciA9IG10NzkxNV9kZnNfc3RhcnRfcmRkKGRldiwgMSk7DQorCQlpZiAoZXJyIDwgMCkNCisJ CQlyZXR1cm4gZXJyOw0KKw0KKwkJcGh5LT5yZGRfc3RhdGUgfD0gQklUKDEpOw0KKwl9DQorDQor CXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X2Rmc19pbml0X3JhZGFyX3Nw ZWNzKHN0cnVjdCBtdDc5MTVfcGh5ICpwaHkpDQorew0KKwljb25zdCBzdHJ1Y3QgbXQ3OTE1X2Rm c19yYWRhcl9zcGVjICpyYWRhcl9zcGVjczsNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IHBo eS0+ZGV2Ow0KKwlpbnQgZXJyLCBpOw0KKw0KKwlzd2l0Y2ggKGRldi0+bXQ3Ni5yZWdpb24pIHsN CisJY2FzZSBOTDgwMjExX0RGU19GQ0M6DQorCQlyYWRhcl9zcGVjcyA9ICZmY2NfcmFkYXJfc3Bl Y3M7DQorCQllcnIgPSBtdDc5MTVfbWN1X3NldF9mY2M1X2xwbihkZXYsIDgpOw0KKwkJaWYgKGVy ciA8IDApDQorCQkJcmV0dXJuIGVycjsNCisJCWJyZWFrOw0KKwljYXNlIE5MODAyMTFfREZTX0VU U0k6DQorCQlyYWRhcl9zcGVjcyA9ICZldHNpX3JhZGFyX3NwZWNzOw0KKwkJYnJlYWs7DQorCWNh c2UgTkw4MDIxMV9ERlNfSlA6DQorCQlyYWRhcl9zcGVjcyA9ICZqcF9yYWRhcl9zcGVjczsNCisJ CWJyZWFrOw0KKwlkZWZhdWx0Og0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJZm9yIChp ID0gMDsgaSA8IEFSUkFZX1NJWkUocmFkYXJfc3BlY3MtPnJhZGFyX3BhdHRlcm4pOyBpKyspIHsN CisJCWVyciA9IG10NzkxNV9tY3Vfc2V0X3JhZGFyX3RoKGRldiwgaSwNCisJCQkJCSAgICAgICZy YWRhcl9zcGVjcy0+cmFkYXJfcGF0dGVybltpXSk7DQorCQlpZiAoZXJyIDwgMCkNCisJCQlyZXR1 cm4gZXJyOw0KKwl9DQorDQorCXJldHVybiBtdDc5MTVfbWN1X3NldF9wdWxzZV90aChkZXYsICZy YWRhcl9zcGVjcy0+cHVsc2VfdGgpOw0KK30NCisNCitpbnQgbXQ3OTE1X2Rmc19pbml0X3JhZGFy X2RldGVjdG9yKHN0cnVjdCBtdDc5MTVfcGh5ICpwaHkpDQorew0KKwlzdHJ1Y3QgY2ZnODAyMTFf Y2hhbl9kZWYgKmNoYW5kZWYgPSAmcGh5LT5tdDc2LT5jaGFuZGVmOw0KKwlzdHJ1Y3QgbXQ3OTE1 X2RldiAqZGV2ID0gcGh5LT5kZXY7DQorCWJvb2wgZXh0X3BoeSA9IHBoeSAhPSAmZGV2LT5waHk7 DQorCWludCBlcnI7DQorDQorCWlmIChkZXYtPm10NzYucmVnaW9uID09IE5MODAyMTFfREZTX1VO U0VUKSB7DQorCQlwaHktPmRmc19zdGF0ZSA9IC0xOw0KKwkJaWYgKHBoeS0+cmRkX3N0YXRlKQ0K KwkJCWdvdG8gc3RvcDsNCisNCisJCXJldHVybiAwOw0KKwl9DQorDQorCWlmICh0ZXN0X2JpdChN VDc2X1NDQU5OSU5HLCAmcGh5LT5tdDc2LT5zdGF0ZSkpDQorCQlyZXR1cm4gMDsNCisNCisJaWYg KHBoeS0+ZGZzX3N0YXRlID09IGNoYW5kZWYtPmNoYW4tPmRmc19zdGF0ZSkNCisJCXJldHVybiAw Ow0KKw0KKwllcnIgPSBtdDc5MTVfZGZzX2luaXRfcmFkYXJfc3BlY3MocGh5KTsNCisJaWYgKGVy ciA8IDApIHsNCisJCXBoeS0+ZGZzX3N0YXRlID0gLTE7DQorCQlnb3RvIHN0b3A7DQorCX0NCisN CisJcGh5LT5kZnNfc3RhdGUgPSBjaGFuZGVmLT5jaGFuLT5kZnNfc3RhdGU7DQorDQorCWlmIChj aGFuZGVmLT5jaGFuLT5mbGFncyAmIElFRUU4MDIxMV9DSEFOX1JBREFSKSB7DQorCQlpZiAoY2hh bmRlZi0+Y2hhbi0+ZGZzX3N0YXRlICE9IE5MODAyMTFfREZTX0FWQUlMQUJMRSkNCisJCQlyZXR1 cm4gbXQ3OTE1X2Rmc19zdGFydF9yYWRhcl9kZXRlY3RvcihwaHkpOw0KKw0KKwkJcmV0dXJuIG10 NzkxNV9tY3VfcmRkX2NtZChkZXYsIFJERF9DQUNfRU5ELCBleHRfcGh5LA0KKwkJCQkJICBNVF9S WF9TRUwwLCAwKTsNCisJfQ0KKw0KK3N0b3A6DQorCWVyciA9IG10NzkxNV9tY3VfcmRkX2NtZChk ZXYsIFJERF9OT1JNQUxfU1RBUlQsIGV4dF9waHksDQorCQkJCSBNVF9SWF9TRUwwLCAwKTsNCisJ aWYgKGVyciA8IDApDQorCQlyZXR1cm4gZXJyOw0KKw0KKwltdDc5MTVfZGZzX3N0b3BfcmFkYXJf ZGV0ZWN0b3IocGh5KTsNCisJcmV0dXJuIDA7DQorfQ0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0 L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21hYy5oIGIvZHJpdmVycy9uZXQvd2lyZWxl c3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFjLmgNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRl eCAwMDAwMDAwMDAwMDAuLjcxMjc1MzQ4NGFlZQ0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFjLmgNCkBAIC0wLDAgKzEsMzMw IEBADQorLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IElTQyAqLw0KKy8qIENvcHlyaWdodCAo QykgMjAyMCBNZWRpYVRlayBJbmMuICovDQorDQorI2lmbmRlZiBfX01UNzkxNV9NQUNfSA0KKyNk ZWZpbmUgX19NVDc5MTVfTUFDX0gNCisNCisjZGVmaW5lIE1UX0NUX1BBUlNFX0xFTgkJCTcyDQor I2RlZmluZSBNVF9DVF9ETUFfQlVGX05VTQkJMg0KKw0KKyNkZWZpbmUgTVRfUlhEMF9MRU5HVEgJ CQlHRU5NQVNLKDE1LCAwKQ0KKyNkZWZpbmUgTVRfUlhEMF9QS1RfVFlQRQkJR0VOTUFTSygzMSwg MjcpDQorDQorI2RlZmluZSBNVF9SWEQwX05PUk1BTF9FVEhfVFlQRV9PRlMJR0VOTUFTSygyMiwg MTYpDQorI2RlZmluZSBNVF9SWEQwX05PUk1BTF9JUF9TVU0JCUJJVCgyMykNCisjZGVmaW5lIE1U X1JYRDBfTk9STUFMX1VEUF9UQ1BfU1VNCUJJVCgyNCkNCisNCitlbnVtIHJ4X3BrdF90eXBlIHsN CisJUEtUX1RZUEVfVFhTLA0KKwlQS1RfVFlQRV9UWFJYViwNCisJUEtUX1RZUEVfTk9STUFMLA0K KwlQS1RfVFlQRV9SWF9EVVBfUkZCLA0KKwlQS1RfVFlQRV9SWF9UTVIsDQorCVBLVF9UWVBFX1JF VFJJRVZFLA0KKwlQS1RfVFlQRV9UWFJYX05PVElGWSwNCisJUEtUX1RZUEVfUlhfRVZFTlQsDQor fTsNCisNCisvKiBSWEQgRFcxICovDQorI2RlZmluZSBNVF9SWEQxX05PUk1BTF9XTEFOX0lEWAkJ R0VOTUFTSyg5LCAwKQ0KKyNkZWZpbmUgTVRfUlhEMV9OT1JNQUxfR1JPVVBfMQkJQklUKDExKQ0K KyNkZWZpbmUgTVRfUlhEMV9OT1JNQUxfR1JPVVBfMgkJQklUKDEyKQ0KKyNkZWZpbmUgTVRfUlhE MV9OT1JNQUxfR1JPVVBfMwkJQklUKDEzKQ0KKyNkZWZpbmUgTVRfUlhEMV9OT1JNQUxfR1JPVVBf NAkJQklUKDE0KQ0KKyNkZWZpbmUgTVRfUlhEMV9OT1JNQUxfR1JPVVBfNQkJQklUKDE1KQ0KKyNk ZWZpbmUgTVRfUlhEMV9OT1JNQUxfU0VDX01PREUJCUdFTk1BU0soMjAsIDE2KQ0KKyNkZWZpbmUg TVRfUlhEMV9OT1JNQUxfS0VZX0lECQlHRU5NQVNLKDIyLCAyMSkNCisjZGVmaW5lIE1UX1JYRDFf Tk9STUFMX0NNCQlCSVQoMjMpDQorI2RlZmluZSBNVF9SWEQxX05PUk1BTF9DTE0JCUJJVCgyNCkN CisjZGVmaW5lIE1UX1JYRDFfTk9STUFMX0lDVl9FUlIJCUJJVCgyNSkNCisjZGVmaW5lIE1UX1JY RDFfTk9STUFMX1RLSVBfTUlDX0VSUglCSVQoMjYpDQorI2RlZmluZSBNVF9SWEQxX05PUk1BTF9G Q1NfRVJSCQlCSVQoMjcpDQorI2RlZmluZSBNVF9SWEQxX05PUk1BTF9CQU5EX0lEWAkJQklUKDI4 KQ0KKyNkZWZpbmUgTVRfUlhEMV9OT1JNQUxfU1BQX0VOCQlCSVQoMjkpDQorI2RlZmluZSBNVF9S WEQxX05PUk1BTF9BRERfT00JCUJJVCgzMCkNCisjZGVmaW5lIE1UX1JYRDFfTk9STUFMX1NFQ19E T05FCQlCSVQoMzEpDQorDQorLyogUlhEIERXMiAqLw0KKyNkZWZpbmUgTVRfUlhEMl9OT1JNQUxf QlNTSUQJCUdFTk1BU0soNSwgMCkNCisjZGVmaW5lIE1UX1JYRDJfTk9STUFMX0NPX0FOVAkJQklU KDYpDQorI2RlZmluZSBNVF9SWEQyX05PUk1BTF9CRl9DUUkJCUJJVCg3KQ0KKyNkZWZpbmUgTVRf UlhEMl9OT1JNQUxfTUFDX0hEUl9MRU4JR0VOTUFTSygxMiwgOCkNCisjZGVmaW5lIE1UX1JYRDJf Tk9STUFMX0hEUl9UUkFOUwlCSVQoMTMpDQorI2RlZmluZSBNVF9SWEQyX05PUk1BTF9IRFJfT0ZG U0VUCUdFTk1BU0soMTUsIDE0KQ0KKyNkZWZpbmUgTVRfUlhEMl9OT1JNQUxfVElECQlHRU5NQVNL KDE5LCAxNikNCisjZGVmaW5lIE1UX1JYRDJfTk9STUFMX01VX0JBUgkJQklUKDIxKQ0KKyNkZWZp bmUgTVRfUlhEMl9OT1JNQUxfU1dfQklUCQlCSVQoMjIpDQorI2RlZmluZSBNVF9SWEQyX05PUk1B TF9BTVNEVV9FUlIJQklUKDIzKQ0KKyNkZWZpbmUgTVRfUlhEMl9OT1JNQUxfTUFYX0xFTl9FUlJP UglCSVQoMjQpDQorI2RlZmluZSBNVF9SWEQyX05PUk1BTF9IRFJfVFJBTlNfRVJST1IJQklUKDI1 KQ0KKyNkZWZpbmUgTVRfUlhEMl9OT1JNQUxfSU5UX0ZSQU1FCUJJVCgyNikNCisjZGVmaW5lIE1U X1JYRDJfTk9STUFMX0ZSQUcJCUJJVCgyNykNCisjZGVmaW5lIE1UX1JYRDJfTk9STUFMX05VTExf RlJBTUUJQklUKDI4KQ0KKyNkZWZpbmUgTVRfUlhEMl9OT1JNQUxfTkRBVEEJCUJJVCgyOSkNCisj ZGVmaW5lIE1UX1JYRDJfTk9STUFMX05PTl9BTVBEVQlCSVQoMzApDQorI2RlZmluZSBNVF9SWEQy X05PUk1BTF9CRl9SRVBPUlQJQklUKDMxKQ0KKw0KKy8qIFJYRCBEVzMgKi8NCisjZGVmaW5lIE1U X1JYRDNfTk9STUFMX1JYVl9TRVEJCUdFTk1BU0soNywgMCkNCisjZGVmaW5lIE1UX1JYRDNfTk9S TUFMX0NIX0ZSRVEJCUdFTk1BU0soMTUsIDgpDQorI2RlZmluZSBNVF9SWEQzX05PUk1BTF9BRERS X1RZUEUJR0VOTUFTSygxNywgMTYpDQorI2RlZmluZSBNVF9SWEQzX05PUk1BTF9VMk0JCUJJVCgw KQ0KKyNkZWZpbmUgTVRfUlhEM19OT1JNQUxfSFRDX1ZMRAkJQklUKDApDQorI2RlZmluZSBNVF9S WEQzX05PUk1BTF9UU0ZfQ09NUEFSRV9MT1NTCUJJVCgxOSkNCisjZGVmaW5lIE1UX1JYRDNfTk9S TUFMX0JFQUNPTl9NQwlCSVQoMjApDQorI2RlZmluZSBNVF9SWEQzX05PUk1BTF9CRUFDT05fVUMJ QklUKDIxKQ0KKyNkZWZpbmUgTVRfUlhEM19OT1JNQUxfQU1TRFUJCUJJVCgyMikNCisjZGVmaW5l IE1UX1JYRDNfTk9STUFMX01FU0gJCUJJVCgyMykNCisjZGVmaW5lIE1UX1JYRDNfTk9STUFMX01I Q1AJCUJJVCgyNCkNCisjZGVmaW5lIE1UX1JYRDNfTk9STUFMX05PX0lORk9fV0IJQklUKDI1KQ0K KyNkZWZpbmUgTVRfUlhEM19OT1JNQUxfRElTQUJMRV9SWF9IRFJfVFJBTlMJQklUKDI2KQ0KKyNk ZWZpbmUgTVRfUlhEM19OT1JNQUxfUE9XRVJfU0FWRV9TVEFUCUJJVCgyNykNCisjZGVmaW5lIE1U X1JYRDNfTk9STUFMX01PUkUJCUJJVCgyOCkNCisjZGVmaW5lIE1UX1JYRDNfTk9STUFMX1VOV0FO VAkJQklUKDI5KQ0KKyNkZWZpbmUgTVRfUlhEM19OT1JNQUxfUlhfRFJPUAkJQklUKDMwKQ0KKyNk ZWZpbmUgTVRfUlhEM19OT1JNQUxfVkxBTjJFVEgJCUJJVCgzMSkNCisNCisvKiBSWEQgRFc0ICov DQorI2RlZmluZSBNVF9SWEQ0X05PUk1BTF9QQVlMT0FEX0ZPUk1BVAlHRU5NQVNLKDEsIDApDQor I2RlZmluZSBNVF9SWEQ0X05PUk1BTF9QQVRURVJOX0RST1AJQklUKDkpDQorI2RlZmluZSBNVF9S WEQ0X05PUk1BTF9DTFMJCUJJVCgxMCkNCisjZGVmaW5lIE1UX1JYRDRfTk9STUFMX09GTEQJCUdF Tk1BU0soMTIsIDExKQ0KKyNkZWZpbmUgTVRfUlhENF9OT1JNQUxfTUFHSUNfUEtUCUJJVCgxMykN CisjZGVmaW5lIE1UX1JYRDRfTk9STUFMX1dPTAkJR0VOTUFTSygxOCwgMTQpDQorI2RlZmluZSBN VF9SWEQ0X05PUk1BTF9DTFNfQklUTUFQCUdFTk1BU0soMjgsIDE5KQ0KKyNkZWZpbmUgTVRfUlhE M19OT1JNQUxfUEZfTU9ERQkJQklUKDI5KQ0KKyNkZWZpbmUgTVRfUlhEM19OT1JNQUxfUEZfU1RT CQlHRU5NQVNLKDMxLCAzMCkNCisNCisvKiBQLVJYViAqLw0KKyNkZWZpbmUgTVRfUFJYVl9UWF9S QVRFCQkJR0VOTUFTSyg2LCAwKQ0KKyNkZWZpbmUgTVRfUFJYVl9UWF9EQ00JCQlCSVQoNCkNCisj ZGVmaW5lIE1UX1BSWFZfVFhfRVJfU1VfMTA2VAkJQklUKDUpDQorI2RlZmluZSBNVF9QUlhWX05T VFMJCQlHRU5NQVNLKDksIDcpDQorI2RlZmluZSBNVF9QUlhWX0hUX0FEX0NPREUJCUJJVCgxMSkN CisjZGVmaW5lIE1UX1BSWFZfUkNQSTMJCQlHRU5NQVNLKDMxLCAyNCkNCisjZGVmaW5lIE1UX1BS WFZfUkNQSTIJCQlHRU5NQVNLKDIzLCAxNikNCisjZGVmaW5lIE1UX1BSWFZfUkNQSTEJCQlHRU5N QVNLKDE1LCA4KQ0KKyNkZWZpbmUgTVRfUFJYVl9SQ1BJMAkJCUdFTk1BU0soNywgMCkNCisNCisv KiBDLVJYViAqLw0KKyNkZWZpbmUgTVRfQ1JYVl9IVF9TVEJDCQkJR0VOTUFTSygxLCAwKQ0KKyNk ZWZpbmUgTVRfQ1JYVl9UWF9NT0RFCQkJR0VOTUFTSyg3LCA0KQ0KKyNkZWZpbmUgTVRfQ1JYVl9G UkFNRV9NT0RFCQlHRU5NQVNLKDEwLCA4KQ0KKyNkZWZpbmUgTVRfQ1JYVl9IVF9TSE9SVF9HSQkJ R0VOTUFTSygxNCwgMTMpDQorDQorc3RydWN0IG10NzkxNV9yeHYgew0KKwl1MzIgcGh5Ow0KKw0K KwkvKiBQLVJYVjogYml0IDB+MSwgQy1SWFY6IGJpdCAyfjE5ICovDQorCV9fbGUzMiB2WzIwXTsN Cit9Ow0KKw0KK2VudW0gdHhfaGVhZGVyX2Zvcm1hdCB7DQorCU1UX0hEUl9GT1JNQVRfODAyXzMs DQorCU1UX0hEUl9GT1JNQVRfQ01ELA0KKwlNVF9IRFJfRk9STUFUXzgwMl8xMSwNCisJTVRfSERS X0ZPUk1BVF84MDJfMTFfRVhULA0KK307DQorDQorZW51bSB0eF9wa3RfdHlwZSB7DQorCU1UX1RY X1RZUEVfQ1QsDQorCU1UX1RYX1RZUEVfU0YsDQorCU1UX1RYX1RZUEVfQ01ELA0KKwlNVF9UWF9U WVBFX0ZXLA0KK307DQorDQorZW51bSB0eF9wa3RfcXVldWVfaWR4IHsNCisJTVRfTE1BQ19BQzAw LA0KKwlNVF9MTUFDX0FDMDEsDQorCU1UX0xNQUNfQUMwMiwNCisJTVRfTE1BQ19BQzAzLA0KKwlN VF9MTUFDX0FMVFgwID0gMHgxMCwNCisJTVRfTE1BQ19CTUMwID0gMHgxMCwNCisJTVRfTE1BQ19C Q04wID0gMHgxMiwNCit9Ow0KKw0KK2VudW0gdHhfcG9ydF9pZHggew0KKwlNVF9UWF9QT1JUX0lE WF9MTUFDLA0KKwlNVF9UWF9QT1JUX0lEWF9NQ1UNCit9Ow0KKw0KK2VudW0gdHhfbWN1X3BvcnRf cV9pZHggew0KKwlNVF9UWF9NQ1VfUE9SVF9SWF9RMCA9IDB4MjAsDQorCU1UX1RYX01DVV9QT1JU X1JYX1ExLA0KKwlNVF9UWF9NQ1VfUE9SVF9SWF9RMiwNCisJTVRfVFhfTUNVX1BPUlRfUlhfUTMs DQorCU1UX1RYX01DVV9QT1JUX1JYX0ZXREwgPSAweDNlDQorfTsNCisNCisjZGVmaW5lIE1UX0NU X0lORk9fQVBQTFlfVFhECQlCSVQoMCkNCisjZGVmaW5lIE1UX0NUX0lORk9fQ09QWV9IT1NUX1RY RF9BTEwJQklUKDEpDQorI2RlZmluZSBNVF9DVF9JTkZPX01HTVRfRlJBTUUJCUJJVCgyKQ0KKyNk ZWZpbmUgTVRfQ1RfSU5GT19OT05FX0NJUEhFUl9GUkFNRQlCSVQoMykNCisjZGVmaW5lIE1UX0NU X0lORk9fSFNSMl9UWAkJQklUKDQpDQorDQorI2RlZmluZSBNVF9UWERfU0laRQkJCSg4ICogNCkN CisNCisjZGVmaW5lIE1UX1RYRDBfUV9JRFgJCQlHRU5NQVNLKDMxLCAyNSkNCisjZGVmaW5lIE1U X1RYRDBfUEtUX0ZNVAkJCUdFTk1BU0soMjQsIDIzKQ0KKyNkZWZpbmUgTVRfVFhEMF9FVEhfVFlQ RV9PRkZTRVQJCUdFTk1BU0soMjIsIDE2KQ0KKyNkZWZpbmUgTVRfVFhEMF9UWF9CWVRFUwkJR0VO TUFTSygxNSwgMCkNCisNCisjZGVmaW5lIE1UX1RYRDFfTE9OR19GT1JNQVQJCUJJVCgzMSkNCisj ZGVmaW5lIE1UX1RYRDFfVEdJRAkJCUJJVCgzMCkNCisjZGVmaW5lIE1UX1RYRDFfT1dOX01BQwkJ CUdFTk1BU0soMjksIDI0KQ0KKyNkZWZpbmUgTVRfVFhEMV9BTVNEVQkJCUJJVCgyMykNCisjZGVm aW5lIE1UX1RYRDFfVElECQkJR0VOTUFTSygyMiwgMjApDQorI2RlZmluZSBNVF9UWEQxX0hEUl9Q QUQJCQlHRU5NQVNLKDE5LCAxOCkNCisjZGVmaW5lIE1UX1RYRDFfSERSX0ZPUk1BVAkJR0VOTUFT SygxNywgMTYpDQorI2RlZmluZSBNVF9UWEQxX0hEUl9JTkZPCQlHRU5NQVNLKDE1LCAxMSkNCisj ZGVmaW5lIE1UX1RYRDFfVlRBCQkJQklUKDEwKQ0KKyNkZWZpbmUgTVRfVFhEMV9XTEFOX0lEWAkJ R0VOTUFTSyg5LCAwKQ0KKw0KKyNkZWZpbmUgTVRfVFhEMl9GSVhfUkFURQkJQklUKDMxKQ0KKyNk ZWZpbmUgTVRfVFhEMl9GSVhFRF9SQVRFCQlCSVQoMzApDQorI2RlZmluZSBNVF9UWEQyX1BPV0VS X09GRlNFVAkJR0VOTUFTSygyOSwgMjQpDQorI2RlZmluZSBNVF9UWEQyX01BWF9UWF9USU1FCQlH RU5NQVNLKDIzLCAxNikNCisjZGVmaW5lIE1UX1RYRDJfRlJBRwkJCUdFTk1BU0soMTUsIDE0KQ0K KyNkZWZpbmUgTVRfVFhEMl9IVENfVkxECQkJQklUKDEzKQ0KKyNkZWZpbmUgTVRfVFhEMl9EVVJB VElPTgkJQklUKDEyKQ0KKyNkZWZpbmUgTVRfVFhEMl9CSVAJCQlCSVQoMTEpDQorI2RlZmluZSBN VF9UWEQyX01VTFRJQ0FTVAkJQklUKDEwKQ0KKyNkZWZpbmUgTVRfVFhEMl9SVFMJCQlCSVQoOSkN CisjZGVmaW5lIE1UX1RYRDJfU09VTkRJTkcJCUJJVCg4KQ0KKyNkZWZpbmUgTVRfVFhEMl9ORFBB CQkJQklUKDcpDQorI2RlZmluZSBNVF9UWEQyX05EUAkJCUJJVCg2KQ0KKyNkZWZpbmUgTVRfVFhE Ml9GUkFNRV9UWVBFCQlHRU5NQVNLKDUsIDQpDQorI2RlZmluZSBNVF9UWEQyX1NVQl9UWVBFCQlH RU5NQVNLKDMsIDApDQorDQorI2RlZmluZSBNVF9UWEQzX1NOX1ZBTElECQlCSVQoMzEpDQorI2Rl ZmluZSBNVF9UWEQzX1BOX1ZBTElECQlCSVQoMzApDQorI2RlZmluZSBNVF9UWEQzX1NXX1BPV0VS X01HTVQJCUJJVCgyOSkNCisjZGVmaW5lIE1UX1RYRDNfQkFfRElTQUJMRQkJQklUKDI4KQ0KKyNk ZWZpbmUgTVRfVFhEM19TRVEJCQlHRU5NQVNLKDI3LCAxNikNCisjZGVmaW5lIE1UX1RYRDNfUkVN X1RYX0NPVU5UCQlHRU5NQVNLKDE1LCAxMSkNCisjZGVmaW5lIE1UX1RYRDNfVFhfQ09VTlQJCUdF Tk1BU0soMTAsIDYpDQorI2RlZmluZSBNVF9UWEQzX1RJTUlOR19NRUFTVVJFCQlCSVQoNSkNCisj ZGVmaW5lIE1UX1RYRDNfREFTCQkJQklUKDQpDQorI2RlZmluZSBNVF9UWEQzX0VFT1NQCQkJQklU KDMpDQorI2RlZmluZSBNVF9UWEQzX0VNUkQJCQlCSVQoMikNCisjZGVmaW5lIE1UX1RYRDNfUFJP VEVDVF9GUkFNRQkJQklUKDEpDQorI2RlZmluZSBNVF9UWEQzX05PX0FDSwkJCUJJVCgwKQ0KKw0K KyNkZWZpbmUgTVRfVFhENF9QTl9MT1cJCQlHRU5NQVNLKDMxLCAwKQ0KKw0KKyNkZWZpbmUgTVRf VFhENV9QTl9ISUdICQkJR0VOTUFTSygzMSwgMTYpDQorI2RlZmluZSBNVF9UWEQ1X01ECQkJQklU KDE1KQ0KKyNkZWZpbmUgTVRfVFhENV9BRERfQkEJCQlCSVQoMTQpDQorI2RlZmluZSBNVF9UWEQ1 X1RYX1NUQVRVU19IT1NUCQlCSVQoMTApDQorI2RlZmluZSBNVF9UWEQ1X1RYX1NUQVRVU19NQ1UJ CUJJVCg5KQ0KKyNkZWZpbmUgTVRfVFhENV9UWF9TVEFUVVNfRk1UCQlCSVQoOCkNCisjZGVmaW5l IE1UX1RYRDVfUElECQkJR0VOTUFTSyg3LCAwKQ0KKw0KKyNkZWZpbmUgTVRfVFhENl9UWF9JQkYJ CQlCSVQoMzEpDQorI2RlZmluZSBNVF9UWEQ2X1RYX0VCRgkJCUJJVCgzMCkNCisjZGVmaW5lIE1U X1RYRDZfVFhfUkFURQkJCUdFTk1BU0soMjksIDE2KQ0KKyNkZWZpbmUgTVRfVFhENl9TR0kJCQlH RU5NQVNLKDE1LCAxNCkNCisjZGVmaW5lIE1UX1RYRDZfSEVMVEYJCQlHRU5NQVNLKDEzLCAxMikN CisjZGVmaW5lIE1UX1RYRDZfTERQQwkJCUJJVCgxMSkNCisjZGVmaW5lIE1UX1RYRDZfU1BFX0lE X0lEWAkJQklUKDEwKQ0KKyNkZWZpbmUgTVRfVFhENl9BTlRfSUQJCQlHRU5NQVNLKDcsIDQpDQor I2RlZmluZSBNVF9UWEQ2X0RZTl9CVwkJCUJJVCgzKQ0KKyNkZWZpbmUgTVRfVFhENl9GSVhFRF9C VwkJQklUKDIpDQorI2RlZmluZSBNVF9UWEQ2X0JXCQkJR0VOTUFTSygyLCAwKQ0KKw0KKyNkZWZp bmUgTVRfVFhEN19UWERfTEVOCQkJR0VOTUFTSygzMSwgMzApDQorI2RlZmluZSBNVF9UWEQ3X1VE UF9UQ1BfU1VNCQlCSVQoMjkpDQorI2RlZmluZSBNVF9UWEQ3X0lQX1NVTQkJCUJJVCgyOCkNCisN CisjZGVmaW5lIE1UX1RYRDdfVFlQRQkJCUdFTk1BU0soMjEsIDIwKQ0KKyNkZWZpbmUgTVRfVFhE N19TVUJfVFlQRQkJR0VOTUFTSygxOSwgMTYpDQorDQorI2RlZmluZSBNVF9UWEQ3X1BTRV9GSUQJ CQlHRU5NQVNLKDI3LCAxNikNCisjZGVmaW5lIE1UX1RYRDdfU1BFX0lEWAkJCUdFTk1BU0soMTUs IDExKQ0KKyNkZWZpbmUgTVRfVFhEN19IV19BTVNEVQkJQklUKDEwKQ0KKyNkZWZpbmUgTVRfVFhE N19UWF9USU1FCQkJR0VOTUFTSyg5LCAwKQ0KKw0KKyNkZWZpbmUgTVRfVFhfUkFURV9TVEJDCQkJ QklUKDEzKQ0KKyNkZWZpbmUgTVRfVFhfUkFURV9OU1MJCQlHRU5NQVNLKDEyLCAxMCkNCisjZGVm aW5lIE1UX1RYX1JBVEVfTU9ERQkJCUdFTk1BU0soOSwgNikNCisjZGVmaW5lIE1UX1RYX1JBVEVf SURYCQkJR0VOTUFTSyg1LCAwKQ0KKw0KKyNkZWZpbmUgTVRfVFhQX01BWF9CVUZfTlVNCQk2DQor DQorc3RydWN0IG10NzkxNV90eHAgew0KKwlfX2xlMTYgZmxhZ3M7DQorCV9fbGUxNiB0b2tlbjsN CisJdTggYnNzX2lkeDsNCisJdTggcmVwdF93ZHNfd2NpZDsNCisJdTggcnN2Ow0KKwl1OCBuYnVm Ow0KKwlfX2xlMzIgYnVmW01UX1RYUF9NQVhfQlVGX05VTV07DQorCV9fbGUxNiBsZW5bTVRfVFhQ X01BWF9CVUZfTlVNXTsNCit9IF9fcGFja2VkIF9fYWxpZ25lZCg0KTsNCisNCitzdHJ1Y3QgbXQ3 OTE1X3R4X2ZyZWUgew0KKwlfX2xlMTYgcnhfYnl0ZV9jbnQ7DQorCV9fbGUxNiBjdHJsOw0KKwl1 OCB0eGRfY250Ow0KKwl1OCByc3ZbM107DQorCV9fbGUzMiBpbmZvW107DQorfSBfX3BhY2tlZCBf X2FsaWduZWQoNCk7DQorDQorI2RlZmluZSBNVF9UWF9GUkVFX01TRFVfQ05UCQlHRU5NQVNLKDks IDApDQorI2RlZmluZSBNVF9UWF9GUkVFX1dMQU5fSUQJCUdFTk1BU0soMjMsIDE0KQ0KKyNkZWZp bmUgTVRfVFhfRlJFRV9MQVRFTkNZCQlHRU5NQVNLKDEyLCAwKQ0KKy8qIDA6IHN1Y2Nlc3MsIG90 aGVyczogZHJvcHBlZCAqLw0KKyNkZWZpbmUgTVRfVFhfRlJFRV9TVEFUVVMJCUdFTk1BU0soMTQs IDEzKQ0KKyNkZWZpbmUgTVRfVFhfRlJFRV9NU0RVX0lECQlHRU5NQVNLKDMwLCAxNikNCisjZGVm aW5lIE1UX1RYX0ZSRUVfUEFJUgkJCUJJVCgzMSkNCisvKiB3aWxsIHN1cHBvcnQgdGhpcyBmaWVs ZCBpbiBmdXJ0aGVyIHJldmlzaW9uICovDQorI2RlZmluZSBNVF9UWF9GUkVFX1JBVEUJCQlHRU5N QVNLKDEzLCAwKQ0KKw0KK3N0cnVjdCBtdDc5MTVfZGZzX3B1bHNlIHsNCisJdTMyIG1heF93aWR0 aDsJCS8qIHVzICovDQorCWludCBtYXhfcHdyOwkJLyogZGJtICovDQorCWludCBtaW5fcHdyOwkJ LyogZGJtICovDQorCXUzMiBtaW5fc3Rncl9wcmk7CS8qIHVzICovDQorCXUzMiBtYXhfc3Rncl9w cmk7CS8qIHVzICovDQorCXUzMiBtaW5fY3JfcHJpOwkJLyogdXMgKi8NCisJdTMyIG1heF9jcl9w cmk7CQkvKiB1cyAqLw0KK307DQorDQorc3RydWN0IG10NzkxNV9kZnNfcGF0dGVybiB7DQorCXU4 IGVuYjsNCisJdTggc3RncjsNCisJdTggbWluX2NycG47DQorCXU4IG1heF9jcnBuOw0KKwl1OCBt aW5fY3JwcjsNCisJdTggbWluX3B3Ow0KKwl1MzIgbWluX3ByaTsNCisJdTMyIG1heF9wcmk7DQor CXU4IG1heF9wdzsNCisJdTggbWluX2NyYm47DQorCXU4IG1heF9jcmJuOw0KKwl1OCBtaW5fc3Rn cG47DQorCXU4IG1heF9zdGdwbjsNCisJdTggbWluX3N0Z3ByOw0KKwl1OCByc3ZbMl07DQorCXUz MiBtaW5fc3RncHJfZGlmZjsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBtdDc5MTVfZGZzX3Jh ZGFyX3NwZWMgew0KKwlzdHJ1Y3QgbXQ3OTE1X2Rmc19wdWxzZSBwdWxzZV90aDsNCisJc3RydWN0 IG10NzkxNV9kZnNfcGF0dGVybiByYWRhcl9wYXR0ZXJuWzE2XTsNCit9Ow0KKw0KK3N0YXRpYyBp bmxpbmUgc3RydWN0IG10NzkxNV90eHAgKg0KK210NzkxNV90eHdpX3RvX3R4cChzdHJ1Y3QgbXQ3 Nl9kZXYgKmRldiwgc3RydWN0IG10NzZfdHh3aV9jYWNoZSAqdCkNCit7DQorCXU4ICp0eHdpOw0K Kw0KKwlpZiAoIXQpDQorCQlyZXR1cm4gTlVMTDsNCisNCisJdHh3aSA9IG10NzZfZ2V0X3R4d2lf cHRyKGRldiwgdCk7DQorDQorCXJldHVybiAoc3RydWN0IG10NzkxNV90eHAgKikodHh3aSArIE1U X1RYRF9TSVpFKTsNCit9DQorDQorI2VuZGlmDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFpbi5jIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv bWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWFpbi5jDQpuZXcgZmlsZSBtb2RlIDEwMDY0NA0KaW5kZXgg MDAwMDAwMDAwMDAwLi5lOWU5ZTdlMjEzODgNCi0tLSAvZGV2L251bGwNCisrKyBiL2RyaXZlcnMv bmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21haW4uYw0KQEAgLTAsMCArMSw3NDMg QEANCisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogSVNDDQorLyogQ29weXJpZ2h0IChDKSAy MDIwIE1lZGlhVGVrIEluYy4gKi8NCisNCisjaW5jbHVkZSA8bGludXgvZXRoZXJkZXZpY2UuaD4N CisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+DQorI2luY2x1ZGUgPGxpbnV4L3Bj aS5oPg0KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4NCisjaW5jbHVkZSAibXQ3OTE1LmgiDQor I2luY2x1ZGUgIm1jdS5oIg0KKw0KK3N0YXRpYyBib29sIG10NzkxNV9kZXZfcnVubmluZyhzdHJ1 Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJc3RydWN0IG10NzkxNV9waHkgKnBoeTsNCisNCisJ aWYgKHRlc3RfYml0KE1UNzZfU1RBVEVfUlVOTklORywgJmRldi0+bXBoeS5zdGF0ZSkpDQorCQly ZXR1cm4gdHJ1ZTsNCisNCisJcGh5ID0gbXQ3OTE1X2V4dF9waHkoZGV2KTsNCisNCisJcmV0dXJu IHBoeSAmJiB0ZXN0X2JpdChNVDc2X1NUQVRFX1JVTk5JTkcsICZwaHktPm10NzYtPnN0YXRlKTsN Cit9DQorDQorc3RhdGljIGludCBtdDc5MTVfc3RhcnQoc3RydWN0IGllZWU4MDIxMV9odyAqaHcp DQorew0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gbXQ3OTE1X2h3X2Rldihodyk7DQorCXN0 cnVjdCBtdDc5MTVfcGh5ICpwaHkgPSBtdDc5MTVfaHdfcGh5KGh3KTsNCisJYm9vbCBydW5uaW5n Ow0KKw0KKwltdXRleF9sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKw0KKwlydW5uaW5nID0gbXQ3 OTE1X2Rldl9ydW5uaW5nKGRldik7DQorDQorCWlmICghcnVubmluZykgew0KKwkJbXQ3OTE1X21j dV9zZXRfcG0oZGV2LCAwLCAwKTsNCisJCW10NzkxNV9tY3Vfc2V0X21hYyhkZXYsIDAsIHRydWUs IGZhbHNlKTsNCisJCW10NzkxNV9tY3Vfc2V0X3NjcyhkZXYsIDAsIHRydWUpOw0KKwl9DQorDQor CWlmIChwaHkgIT0gJmRldi0+cGh5KSB7DQorCQltdDc5MTVfbWN1X3NldF9wbShkZXYsIDEsIDAp Ow0KKwkJbXQ3OTE1X21jdV9zZXRfbWFjKGRldiwgMSwgdHJ1ZSwgZmFsc2UpOw0KKwkJbXQ3OTE1 X21jdV9zZXRfc2NzKGRldiwgMSwgdHJ1ZSk7DQorCX0NCisNCisJbXQ3OTE1X21jdV9zZXRfY2hh bl9pbmZvKHBoeSwgTUNVX0VYVF9DTURfU0VUX1JYX1BBVEgpOw0KKw0KKwlzZXRfYml0KE1UNzZf U1RBVEVfUlVOTklORywgJnBoeS0+bXQ3Ni0+c3RhdGUpOw0KKw0KKwlpZiAocnVubmluZykNCisJ CWdvdG8gb3V0Ow0KKw0KKwltdDc5MTVfbWFjX3Jlc2V0X2NvdW50ZXJzKHBoeSk7DQorDQorCWll ZWU4MDIxMV9xdWV1ZV9kZWxheWVkX3dvcmsobXQ3Nl9odyhkZXYpLCAmZGV2LT5tdDc2Lm1hY193 b3JrLA0KKwkJCQkgICAgIE1UNzkxNV9XQVRDSERPR19USU1FKTsNCitvdXQ6DQorCW11dGV4X3Vu bG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRpYyB2 b2lkIG10NzkxNV9zdG9wKHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3KQ0KK3sNCisJc3RydWN0IG10 NzkxNV9kZXYgKmRldiA9IG10NzkxNV9od19kZXYoaHcpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3BoeSAq cGh5ID0gbXQ3OTE1X2h3X3BoeShodyk7DQorDQorCW11dGV4X2xvY2soJmRldi0+bXQ3Ni5tdXRl eCk7DQorDQorCWNsZWFyX2JpdChNVDc2X1NUQVRFX1JVTk5JTkcsICZwaHktPm10NzYtPnN0YXRl KTsNCisNCisJaWYgKHBoeSAhPSAmZGV2LT5waHkpIHsNCisJCW10NzkxNV9tY3Vfc2V0X3BtKGRl diwgMSwgMSk7DQorCQltdDc5MTVfbWN1X3NldF9tYWMoZGV2LCAxLCBmYWxzZSwgZmFsc2UpOw0K Kwl9DQorDQorCWlmICghbXQ3OTE1X2Rldl9ydW5uaW5nKGRldikpIHsNCisJCWNhbmNlbF9kZWxh eWVkX3dvcmtfc3luYygmZGV2LT5tdDc2Lm1hY193b3JrKTsNCisNCisJCW10NzkxNV9tY3Vfc2V0 X3BtKGRldiwgMCwgMSk7DQorCQltdDc5MTVfbWN1X3NldF9tYWMoZGV2LCAwLCBmYWxzZSwgZmFs c2UpOw0KKwl9DQorDQorCW11dGV4X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCit9DQorDQor c3RhdGljIGludCBnZXRfb21hY19pZHgoZW51bSBubDgwMjExX2lmdHlwZSB0eXBlLCB1MzIgbWFz aykNCit7DQorCWludCBpOw0KKw0KKwlzd2l0Y2ggKHR5cGUpIHsNCisJY2FzZSBOTDgwMjExX0lG VFlQRV9NT05JVE9SOg0KKwljYXNlIE5MODAyMTFfSUZUWVBFX0FQOg0KKwljYXNlIE5MODAyMTFf SUZUWVBFX01FU0hfUE9JTlQ6DQorCWNhc2UgTkw4MDIxMV9JRlRZUEVfQURIT0M6DQorCQkvKiBh cCB1c2VzIGh3IGJzc2lkIDAgYW5kIGV4dCBic3NpZCAqLw0KKwkJaWYgKH5tYXNrICYgQklUKEhX X0JTU0lEXzApKQ0KKwkJCXJldHVybiBIV19CU1NJRF8wOw0KKw0KKwkJZm9yIChpID0gRVhUX0JT U0lEXzE7IGkgPCBFWFRfQlNTSURfRU5EOyBpKyspDQorCQkJaWYgKH5tYXNrICYgQklUKGkpKQ0K KwkJCQlyZXR1cm4gaTsNCisJCWJyZWFrOw0KKwljYXNlIE5MODAyMTFfSUZUWVBFX1NUQVRJT046 DQorCQkvKiBzdGF0aW9uIHVzZXMgaHcgYnNzaWQgb3RoZXIgdGhhbiAwICovDQorCQlmb3IgKGkg PSBIV19CU1NJRF8xOyBpIDwgSFdfQlNTSURfTUFYOyBpKyspDQorCQkJaWYgKH5tYXNrICYgQklU KGkpKQ0KKwkJCQlyZXR1cm4gaTsNCisJCWJyZWFrOw0KKwlkZWZhdWx0Og0KKwkJV0FSTl9PTigx KTsNCisJCWJyZWFrOw0KKwl9DQorDQorCXJldHVybiAtMTsNCit9DQorDQorc3RhdGljIGludCBt dDc5MTVfYWRkX2ludGVyZmFjZShzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywNCisJCQkJc3RydWN0 IGllZWU4MDIxMV92aWYgKnZpZikNCit7DQorCXN0cnVjdCBtdDc5MTVfdmlmICptdmlmID0gKHN0 cnVjdCBtdDc5MTVfdmlmICopdmlmLT5kcnZfcHJpdjsNCisJc3RydWN0IG10NzkxNV9kZXYgKmRl diA9IG10NzkxNV9od19kZXYoaHcpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5ID0gbXQ3OTE1 X2h3X3BoeShodyk7DQorCXN0cnVjdCBtdDc2X3R4cSAqbXR4cTsNCisJYm9vbCBleHRfcGh5ID0g cGh5ICE9ICZkZXYtPnBoeTsNCisJaW50IGlkeCwgcmV0ID0gMDsNCisNCisJbXV0ZXhfbG9jaygm ZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJbXZpZi0+aWR4ID0gZmZzKH5kZXYtPnZpZl9tYXNrKSAt IDE7DQorCWlmIChtdmlmLT5pZHggPj0gTVQ3OTE1X01BWF9JTlRFUkZBQ0VTKSB7DQorCQlyZXQg PSAtRU5PU1BDOw0KKwkJZ290byBvdXQ7DQorCX0NCisNCisJaWR4ID0gZ2V0X29tYWNfaWR4KHZp Zi0+dHlwZSwgZGV2LT5vbWFjX21hc2spOw0KKwlpZiAoaWR4IDwgMCkgew0KKwkJcmV0ID0gLUVO T1NQQzsNCisJCWdvdG8gb3V0Ow0KKwl9DQorCW12aWYtPm9tYWNfaWR4ID0gaWR4Ow0KKwltdmlm LT5kZXYgPSBkZXY7DQorDQorCW12aWYtPmJhbmRfaWR4ID0gZXh0X3BoeTsNCisJaWYgKG10Nzkx NV9leHRfcGh5KGRldikpDQorCQltdmlmLT53bW1faWR4ID0gZXh0X3BoeSAqIChNVDc5MTVfTUFY X1dNTV9TRVRTIC8gMikgKw0KKwkJCQltdmlmLT5pZHggJSAoTVQ3OTE1X01BWF9XTU1fU0VUUyAv IDIpOw0KKwllbHNlDQorCQltdmlmLT53bW1faWR4ID0gbXZpZi0+aWR4ICUgTVQ3OTE1X01BWF9X TU1fU0VUUzsNCisNCisJcmV0ID0gbXQ3OTE1X21jdV9hZGRfZGV2X2luZm8oZGV2LCB2aWYsIHRy dWUpOw0KKwlpZiAocmV0KQ0KKwkJZ290byBvdXQ7DQorDQorCWRldi0+dmlmX21hc2sgfD0gQklU KG12aWYtPmlkeCk7DQorCWRldi0+b21hY19tYXNrIHw9IEJJVChtdmlmLT5vbWFjX2lkeCk7DQor CXBoeS0+b21hY19tYXNrIHw9IEJJVChtdmlmLT5vbWFjX2lkeCk7DQorDQorCWlkeCA9IE1UNzkx NV9XVEJMX1JFU0VSVkVEIC0gbXZpZi0+aWR4Ow0KKw0KKwlJTklUX0xJU1RfSEVBRCgmbXZpZi0+ c3RhLnBvbGxfbGlzdCk7DQorCW12aWYtPnN0YS53Y2lkLmlkeCA9IGlkeDsNCisJbXZpZi0+c3Rh LndjaWQuZXh0X3BoeSA9IG12aWYtPmJhbmRfaWR4Ow0KKwltdmlmLT5zdGEud2NpZC5od19rZXlf aWR4ID0gLTE7DQorCW12aWYtPnN0YS53Y2lkLnR4X2luZm8gfD0gTVRfV0NJRF9UWF9JTkZPX1NF VDsNCisJbXQ3OTE1X21hY193dGJsX3VwZGF0ZShkZXYsIGlkeCwNCisJCQkgICAgICAgTVRfV1RC TF9VUERBVEVfQURNX0NPVU5UX0NMRUFSKTsNCisNCisJcmN1X2Fzc2lnbl9wb2ludGVyKGRldi0+ bXQ3Ni53Y2lkW2lkeF0sICZtdmlmLT5zdGEud2NpZCk7DQorCWlmICh2aWYtPnR4cSkgew0KKwkJ bXR4cSA9IChzdHJ1Y3QgbXQ3Nl90eHEgKil2aWYtPnR4cS0+ZHJ2X3ByaXY7DQorCQltdHhxLT53 Y2lkID0gJm12aWYtPnN0YS53Y2lkOw0KKwkJbXQ3Nl90eHFfaW5pdCgmZGV2LT5tdDc2LCB2aWYt PnR4cSk7DQorCX0NCisNCitvdXQ6DQorCW11dGV4X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsN CisNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIHZvaWQgbXQ3OTE1X3JlbW92ZV9pbnRl cmZhY2Uoc3RydWN0IGllZWU4MDIxMV9odyAqaHcsDQorCQkJCSAgICBzdHJ1Y3QgaWVlZTgwMjEx X3ZpZiAqdmlmKQ0KK3sNCisJc3RydWN0IG10NzkxNV92aWYgKm12aWYgPSAoc3RydWN0IG10Nzkx NV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAqbXN0YSA9ICZtdmlm LT5zdGE7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisJ c3RydWN0IG10NzkxNV9waHkgKnBoeSA9IG10NzkxNV9od19waHkoaHcpOw0KKwlpbnQgaWR4ID0g bXN0YS0+d2NpZC5pZHg7DQorDQorCS8qIFRPRE86IGRpc2FibGUgYmVhY29uIGZvciB0aGUgYnNz ICovDQorDQorCW10NzkxNV9tY3VfYWRkX2Rldl9pbmZvKGRldiwgdmlmLCBmYWxzZSk7DQorDQor CXJjdV9hc3NpZ25fcG9pbnRlcihkZXYtPm10NzYud2NpZFtpZHhdLCBOVUxMKTsNCisJaWYgKHZp Zi0+dHhxKQ0KKwkJbXQ3Nl90eHFfcmVtb3ZlKCZkZXYtPm10NzYsIHZpZi0+dHhxKTsNCisNCisJ bXV0ZXhfbG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisJZGV2LT52aWZfbWFzayAmPSB+QklUKG12 aWYtPmlkeCk7DQorCWRldi0+b21hY19tYXNrICY9IH5CSVQobXZpZi0+b21hY19pZHgpOw0KKwlw aHktPm9tYWNfbWFzayAmPSB+QklUKG12aWYtPm9tYWNfaWR4KTsNCisJbXV0ZXhfdW5sb2NrKCZk ZXYtPm10NzYubXV0ZXgpOw0KKw0KKwlzcGluX2xvY2tfYmgoJmRldi0+c3RhX3BvbGxfbG9jayk7 DQorCWlmICghbGlzdF9lbXB0eSgmbXN0YS0+cG9sbF9saXN0KSkNCisJCWxpc3RfZGVsX2luaXQo Jm1zdGEtPnBvbGxfbGlzdCk7DQorCXNwaW5fdW5sb2NrX2JoKCZkZXYtPnN0YV9wb2xsX2xvY2sp Ow0KK30NCisNCitzdGF0aWMgdm9pZCBtdDc5MTVfaW5pdF9kZnNfc3RhdGUoc3RydWN0IG10Nzkx NV9waHkgKnBoeSkNCit7DQorCXN0cnVjdCBtdDc2X3BoeSAqbXBoeSA9IHBoeS0+bXQ3NjsNCisJ c3RydWN0IGllZWU4MDIxMV9odyAqaHcgPSBtcGh5LT5odzsNCisJc3RydWN0IGNmZzgwMjExX2No YW5fZGVmICpjaGFuZGVmID0gJmh3LT5jb25mLmNoYW5kZWY7DQorDQorCWlmIChody0+Y29uZi5m bGFncyAmIElFRUU4MDIxMV9DT05GX09GRkNIQU5ORUwpDQorCQlyZXR1cm47DQorDQorCWlmICgh KGNoYW5kZWYtPmNoYW4tPmZsYWdzICYgSUVFRTgwMjExX0NIQU5fUkFEQVIpKQ0KKwkJcmV0dXJu Ow0KKw0KKwlpZiAobXBoeS0+Y2hhbmRlZi5jaGFuLT5jZW50ZXJfZnJlcSA9PSBjaGFuZGVmLT5j aGFuLT5jZW50ZXJfZnJlcSAmJg0KKwkgICAgbXBoeS0+Y2hhbmRlZi53aWR0aCA9PSBjaGFuZGVm LT53aWR0aCkNCisJCXJldHVybjsNCisNCisJcGh5LT5kZnNfc3RhdGUgPSAtMTsNCit9DQorDQor c3RhdGljIGludCBtdDc5MTVfc2V0X2NoYW5uZWwoc3RydWN0IG10NzkxNV9waHkgKnBoeSkNCit7 DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBwaHktPmRldjsNCisJaW50IHJldDsNCisNCisJ Y2FuY2VsX2RlbGF5ZWRfd29ya19zeW5jKCZkZXYtPm10NzYubWFjX3dvcmspOw0KKw0KKwltdXRl eF9sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKwlzZXRfYml0KE1UNzZfUkVTRVQsICZwaHktPm10 NzYtPnN0YXRlKTsNCisNCisJbXQ3OTE1X2luaXRfZGZzX3N0YXRlKHBoeSk7DQorCW10NzZfc2V0 X2NoYW5uZWwocGh5LT5tdDc2KTsNCisNCisJcmV0ID0gbXQ3OTE1X21jdV9zZXRfY2hhbl9pbmZv KHBoeSwgTUNVX0VYVF9DTURfQ0hBTk5FTF9TV0lUQ0gpOw0KKwlpZiAocmV0KQ0KKwkJZ290byBv dXQ7DQorDQorCW10NzkxNV9tYWNfc2V0X3RpbWluZyhwaHkpOw0KKwlyZXQgPSBtdDc5MTVfZGZz X2luaXRfcmFkYXJfZGV0ZWN0b3IocGh5KTsNCisJbXQ3OTE1X21hY19jY2Ffc3RhdHNfcmVzZXQo cGh5KTsNCisNCisJbXQ3OTE1X21hY19yZXNldF9jb3VudGVycyhwaHkpOw0KKwlwaHktPm5vaXNl ID0gMDsNCisNCitvdXQ6DQorCWNsZWFyX2JpdChNVDc2X1JFU0VULCAmcGh5LT5tdDc2LT5zdGF0 ZSk7DQorCW11dGV4X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJbXQ3Nl90eHFfc2No ZWR1bGVfYWxsKHBoeS0+bXQ3Nik7DQorCWllZWU4MDIxMV9xdWV1ZV9kZWxheWVkX3dvcmsobXQ3 Nl9odyhkZXYpLCAmZGV2LT5tdDc2Lm1hY193b3JrLA0KKwkJCQkgICAgIE1UNzkxNV9XQVRDSERP R19USU1FKTsNCisNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIGludCBtdDc5MTVfc2V0 X2tleShzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywgZW51bSBzZXRfa2V5X2NtZCBjbWQsDQorCQkJ ICBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLCBzdHJ1Y3QgaWVlZTgwMjExX3N0YSAqc3RhLA0K KwkJCSAgc3RydWN0IGllZWU4MDIxMV9rZXlfY29uZiAqa2V5KQ0KK3sNCisJc3RydWN0IG10Nzkx NV9kZXYgKmRldiA9IG10NzkxNV9od19kZXYoaHcpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3ZpZiAqbXZp ZiA9IChzdHJ1Y3QgbXQ3OTE1X3ZpZiAqKXZpZi0+ZHJ2X3ByaXY7DQorCXN0cnVjdCBtdDc5MTVf c3RhICptc3RhID0gc3RhID8gKHN0cnVjdCBtdDc5MTVfc3RhICopc3RhLT5kcnZfcHJpdiA6DQor CQkJCSAgJm12aWYtPnN0YTsNCisJc3RydWN0IG10NzZfd2NpZCAqd2NpZCA9ICZtc3RhLT53Y2lk Ow0KKwlpbnQgaWR4ID0ga2V5LT5rZXlpZHg7DQorDQorCS8qIFRoZSBoYXJkd2FyZSBkb2VzIG5v dCBzdXBwb3J0IHBlci1TVEEgUlggR1RLLCBmYWxsYmFjaw0KKwkgKiB0byBzb2Z0d2FyZSBtb2Rl IGZvciB0aGVzZS4NCisJICovDQorCWlmICgodmlmLT50eXBlID09IE5MODAyMTFfSUZUWVBFX0FE SE9DIHx8DQorCSAgICAgdmlmLT50eXBlID09IE5MODAyMTFfSUZUWVBFX01FU0hfUE9JTlQpICYm DQorCSAgICAoa2V5LT5jaXBoZXIgPT0gV0xBTl9DSVBIRVJfU1VJVEVfVEtJUCB8fA0KKwkgICAg IGtleS0+Y2lwaGVyID09IFdMQU5fQ0lQSEVSX1NVSVRFX0NDTVApICYmDQorCSAgICAhKGtleS0+ ZmxhZ3MgJiBJRUVFODAyMTFfS0VZX0ZMQUdfUEFJUldJU0UpKQ0KKwkJcmV0dXJuIC1FT1BOT1RT VVBQOw0KKw0KKwkvKiBmYWxsIGJhY2sgdG8gc3cgZW5jcnlwdGlvbiBmb3IgdW5zdXBwb3J0ZWQg Y2lwaGVycyAqLw0KKwlzd2l0Y2ggKGtleS0+Y2lwaGVyKSB7DQorCWNhc2UgV0xBTl9DSVBIRVJf U1VJVEVfQUVTX0NNQUM6DQorCQlrZXktPmZsYWdzIHw9IElFRUU4MDIxMV9LRVlfRkxBR19HRU5F UkFURV9NTUlFOw0KKwkJYnJlYWs7DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfV0VQNDA6DQor CWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfV0VQMTA0Og0KKwljYXNlIFdMQU5fQ0lQSEVSX1NVSVRF X1RLSVA6DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfQ0NNUDoNCisJY2FzZSBXTEFOX0NJUEhF Ul9TVUlURV9DQ01QXzI1NjoNCisJY2FzZSBXTEFOX0NJUEhFUl9TVUlURV9HQ01QOg0KKwljYXNl IFdMQU5fQ0lQSEVSX1NVSVRFX0dDTVBfMjU2Og0KKwljYXNlIFdMQU5fQ0lQSEVSX1NVSVRFX1NN UzQ6DQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJCXJldHVybiAtRU9QTk9UU1VQUDsNCisJfQ0K Kw0KKwlpZiAoY21kID09IFNFVF9LRVkpIHsNCisJCWtleS0+aHdfa2V5X2lkeCA9IHdjaWQtPmlk eDsNCisJCXdjaWQtPmh3X2tleV9pZHggPSBpZHg7DQorCX0gZWxzZSBpZiAoaWR4ID09IHdjaWQt Pmh3X2tleV9pZHgpIHsNCisJCXdjaWQtPmh3X2tleV9pZHggPSAtMTsNCisJfQ0KKwltdDc2X3dj aWRfa2V5X3NldHVwKCZkZXYtPm10NzYsIHdjaWQsDQorCQkJICAgIGNtZCA9PSBTRVRfS0VZID8g a2V5IDogTlVMTCk7DQorDQorCXJldHVybiBtdDc5MTVfbWN1X2FkZF9rZXkoZGV2LCB2aWYsIG1z dGEsIGtleSwgY21kKTsNCit9DQorDQorc3RhdGljIGludCBtdDc5MTVfY29uZmlnKHN0cnVjdCBp ZWVlODAyMTFfaHcgKmh3LCB1MzIgY2hhbmdlZCkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpk ZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisJc3RydWN0IG10NzkxNV9waHkgKnBoeSA9IG10Nzkx NV9od19waHkoaHcpOw0KKwlib29sIGJhbmQgPSBwaHkgIT0gJmRldi0+cGh5Ow0KKwlpbnQgcmV0 Ow0KKw0KKwlpZiAoY2hhbmdlZCAmIElFRUU4MDIxMV9DT05GX0NIQU5HRV9DSEFOTkVMKSB7DQor CQlpZWVlODAyMTFfc3RvcF9xdWV1ZXMoaHcpOw0KKwkJcmV0ID0gbXQ3OTE1X3NldF9jaGFubmVs KHBoeSk7DQorCQlpZiAocmV0KQ0KKwkJCXJldHVybiByZXQ7DQorCQlpZWVlODAyMTFfd2FrZV9x dWV1ZXMoaHcpOw0KKwl9DQorDQorCW11dGV4X2xvY2soJmRldi0+bXQ3Ni5tdXRleCk7DQorDQor CWlmIChjaGFuZ2VkICYgSUVFRTgwMjExX0NPTkZfQ0hBTkdFX01PTklUT1IpIHsNCisJCWlmICgh KGh3LT5jb25mLmZsYWdzICYgSUVFRTgwMjExX0NPTkZfTU9OSVRPUikpDQorCQkJcGh5LT5yeGZp bHRlciB8PSBNVF9XRl9SRkNSX0RST1BfT1RIRVJfVUM7DQorCQllbHNlDQorCQkJcGh5LT5yeGZp bHRlciAmPSB+TVRfV0ZfUkZDUl9EUk9QX09USEVSX1VDOw0KKw0KKwkJbXQ3Nl93cihkZXYsIE1U X1dGX1JGQ1IoYmFuZCksIHBoeS0+cnhmaWx0ZXIpOw0KKwl9DQorDQorCW11dGV4X3VubG9jaygm ZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRpYyBpbnQNCitt dDc5MTVfY29uZl90eChzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywgc3RydWN0IGllZWU4MDIxMV92 aWYgKnZpZiwgdTE2IHF1ZXVlLA0KKwkgICAgICAgY29uc3Qgc3RydWN0IGllZWU4MDIxMV90eF9x dWV1ZV9wYXJhbXMgKnBhcmFtcykNCit7DQorCXN0cnVjdCBtdDc5MTVfdmlmICptdmlmID0gKHN0 cnVjdCBtdDc5MTVfdmlmICopdmlmLT5kcnZfcHJpdjsNCisNCisJLyogbm8gbmVlZCB0byB1cGRh dGUgcmlnaHQgYXdheSwgd2UnbGwgZ2V0IEJTU19DSEFOR0VEX1FPUyAqLw0KKwltdmlmLT53bW1b cXVldWVdLmN3X21pbiA9IHBhcmFtcy0+Y3dfbWluOw0KKwltdmlmLT53bW1bcXVldWVdLmN3X21h eCA9IHBhcmFtcy0+Y3dfbWF4Ow0KKwltdmlmLT53bW1bcXVldWVdLmFpZnMgPSBwYXJhbXMtPmFp ZnM7DQorCW12aWYtPndtbVtxdWV1ZV0udHhvcCA9IHBhcmFtcy0+dHhvcDsNCisNCisJcmV0dXJu IDA7DQorfQ0KKw0KK3N0YXRpYyB2b2lkIG10NzkxNV9jb25maWd1cmVfZmlsdGVyKHN0cnVjdCBp ZWVlODAyMTFfaHcgKmh3LA0KKwkJCQkgICAgdW5zaWduZWQgaW50IGNoYW5nZWRfZmxhZ3MsDQor CQkJCSAgICB1bnNpZ25lZCBpbnQgKnRvdGFsX2ZsYWdzLA0KKwkJCQkgICAgdTY0IG11bHRpY2Fz dCkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisJ c3RydWN0IG10NzkxNV9waHkgKnBoeSA9IG10NzkxNV9od19waHkoaHcpOw0KKwlib29sIGJhbmQg PSBwaHkgIT0gJmRldi0+cGh5Ow0KKw0KKwl1MzIgY3RsX2ZsYWdzID0gTVRfV0ZfUkZDUjFfRFJP UF9BQ0sgfA0KKwkJCU1UX1dGX1JGQ1IxX0RST1BfQkZfUE9MTCB8DQorCQkJTVRfV0ZfUkZDUjFf RFJPUF9CQSB8DQorCQkJTVRfV0ZfUkZDUjFfRFJPUF9DRkVORCB8DQorCQkJTVRfV0ZfUkZDUjFf RFJPUF9DRkFDSzsNCisJdTMyIGZsYWdzID0gMDsNCisNCisjZGVmaW5lIE1UNzZfRklMVEVSKF9m bGFnLCBfaHcpIGRvIHsJCQkJCVwNCisJCWZsYWdzIHw9ICp0b3RhbF9mbGFncyAmIEZJRl8jI19m bGFnOwkJCVwNCisJCXBoeS0+cnhmaWx0ZXIgJj0gfihfaHcpOwkJCQlcDQorCQlwaHktPnJ4Zmls dGVyIHw9ICEoZmxhZ3MgJiBGSUZfIyNfZmxhZykgKiAoX2h3KTsJXA0KKwl9IHdoaWxlICgwKQ0K Kw0KKwlwaHktPnJ4ZmlsdGVyICY9IH4oTVRfV0ZfUkZDUl9EUk9QX09USEVSX0JTUyB8DQorCQkJ ICAgTVRfV0ZfUkZDUl9EUk9QX09USEVSX0JFQUNPTiB8DQorCQkJICAgTVRfV0ZfUkZDUl9EUk9Q X0ZSQU1FX1JFUE9SVCB8DQorCQkJICAgTVRfV0ZfUkZDUl9EUk9QX1BST0JFUkVRIHwNCisJCQkg ICBNVF9XRl9SRkNSX0RST1BfTUNBU1RfRklMVEVSRUQgfA0KKwkJCSAgIE1UX1dGX1JGQ1JfRFJP UF9NQ0FTVCB8DQorCQkJICAgTVRfV0ZfUkZDUl9EUk9QX0JDQVNUIHwNCisJCQkgICBNVF9XRl9S RkNSX0RST1BfRFVQTElDQVRFIHwNCisJCQkgICBNVF9XRl9SRkNSX0RST1BfQTJfQlNTSUQgfA0K KwkJCSAgIE1UX1dGX1JGQ1JfRFJPUF9VTldBTlRFRF9DVEwgfA0KKwkJCSAgIE1UX1dGX1JGQ1Jf RFJPUF9TVEJDX01VTFRJKTsNCisNCisJTVQ3Nl9GSUxURVIoT1RIRVJfQlNTLCBNVF9XRl9SRkNS X0RST1BfT1RIRVJfVElNIHwNCisJCQkgICAgICAgTVRfV0ZfUkZDUl9EUk9QX0EzX01BQyB8DQor CQkJICAgICAgIE1UX1dGX1JGQ1JfRFJPUF9BM19CU1NJRCk7DQorDQorCU1UNzZfRklMVEVSKEZD U0ZBSUwsIE1UX1dGX1JGQ1JfRFJPUF9GQ1NGQUlMKTsNCisNCisJTVQ3Nl9GSUxURVIoQ09OVFJP TCwgTVRfV0ZfUkZDUl9EUk9QX0NUUyB8DQorCQkJICAgICBNVF9XRl9SRkNSX0RST1BfUlRTIHwN CisJCQkgICAgIE1UX1dGX1JGQ1JfRFJPUF9DVExfUlNWIHwNCisJCQkgICAgIE1UX1dGX1JGQ1Jf RFJPUF9ORFBBKTsNCisNCisJKnRvdGFsX2ZsYWdzID0gZmxhZ3M7DQorCW10NzZfd3IoZGV2LCBN VF9XRl9SRkNSKGJhbmQpLCBwaHktPnJ4ZmlsdGVyKTsNCisNCisJaWYgKCp0b3RhbF9mbGFncyAm IEZJRl9DT05UUk9MKQ0KKwkJbXQ3Nl9jbGVhcihkZXYsIE1UX1dGX1JGQ1IxKGJhbmQpLCBjdGxf ZmxhZ3MpOw0KKwllbHNlDQorCQltdDc2X3NldChkZXYsIE1UX1dGX1JGQ1IxKGJhbmQpLCBjdGxf ZmxhZ3MpOw0KK30NCisNCitzdGF0aWMgdm9pZCBtdDc5MTVfYnNzX2luZm9fY2hhbmdlZChzdHJ1 Y3QgaWVlZTgwMjExX2h3ICpodywNCisJCQkJICAgIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYs DQorCQkJCSAgICBzdHJ1Y3QgaWVlZTgwMjExX2Jzc19jb25mICppbmZvLA0KKwkJCQkgICAgdTMy IGNoYW5nZWQpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5ID0gbXQ3OTE1X2h3X3BoeSho dyk7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisNCisJ bXV0ZXhfbG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJLyoNCisJICogc3RhdGlvbiBtb2Rl IHVzZXMgQlNTSUQgdG8gbWFwIHRoZSB3bGFuIGVudHJ5IHRvIGEgcGVlciwNCisJICogYW5kIHRo ZW4gcGVlciByZWZlcmVuY2VzIGJzc19pbmZvX3JmY2ggdG8gc2V0IGJhbmR3aWR0aCBjYXAuDQor CSAqLw0KKwlpZiAoY2hhbmdlZCAmIEJTU19DSEFOR0VEX0JTU0lEICYmDQorCSAgICB2aWYtPnR5 cGUgPT0gTkw4MDIxMV9JRlRZUEVfU1RBVElPTikgew0KKwkJYm9vbCBqb2luID0gIWlzX3plcm9f ZXRoZXJfYWRkcihpbmZvLT5ic3NpZCk7DQorDQorCQltdDc5MTVfbWN1X2FkZF9ic3NfaW5mbyhw aHksIHZpZiwgam9pbik7DQorCQltdDc5MTVfbWN1X2FkZF9zdGEoZGV2LCB2aWYsIE5VTEwsIGpv aW4pOw0KKwl9DQorDQorCWlmIChjaGFuZ2VkICYgQlNTX0NIQU5HRURfQVNTT0MpDQorCQltdDc5 MTVfbWN1X2FkZF9ic3NfaW5mbyhwaHksIHZpZiwgaW5mby0+YXNzb2MpOw0KKw0KKwlpZiAoY2hh bmdlZCAmIEJTU19DSEFOR0VEX0VSUF9TTE9UKSB7DQorCQlpbnQgc2xvdHRpbWUgPSBpbmZvLT51 c2Vfc2hvcnRfc2xvdCA/IDkgOiAyMDsNCisNCisJCWlmIChzbG90dGltZSAhPSBwaHktPnNsb3R0 aW1lKSB7DQorCQkJcGh5LT5zbG90dGltZSA9IHNsb3R0aW1lOw0KKwkJCW10NzkxNV9tYWNfc2V0 X3RpbWluZyhwaHkpOw0KKwkJfQ0KKwl9DQorDQorCWlmIChjaGFuZ2VkICYgQlNTX0NIQU5HRURf QkVBQ09OX0VOQUJMRUQpIHsNCisJCW10NzkxNV9tY3VfYWRkX2Jzc19pbmZvKHBoeSwgdmlmLCBp bmZvLT5lbmFibGVfYmVhY29uKTsNCisJCW10NzkxNV9tY3VfYWRkX3N0YShkZXYsIHZpZiwgTlVM TCwgaW5mby0+ZW5hYmxlX2JlYWNvbik7DQorCX0NCisNCisJLyogZW5zdXJlIHRoYXQgZW5hYmxl IHR4Y21kX21vZGUgYWZ0ZXIgYnNzX2luZm8gKi8NCisJaWYgKGNoYW5nZWQgJiAoQlNTX0NIQU5H RURfUU9TIHwgQlNTX0NIQU5HRURfQkVBQ09OX0VOQUJMRUQpKQ0KKwkJbXQ3OTE1X21jdV9zZXRf dHgoZGV2LCB2aWYpOw0KKw0KKwlpZiAoY2hhbmdlZCAmIChCU1NfQ0hBTkdFRF9CRUFDT04gfA0K KwkJICAgICAgIEJTU19DSEFOR0VEX0JFQUNPTl9FTkFCTEVEKSkNCisJCW10NzkxNV9tY3VfYWRk X2JlYWNvbihodywgdmlmLCBpbmZvLT5lbmFibGVfYmVhY29uKTsNCisNCisJbXV0ZXhfdW5sb2Nr KCZkZXYtPm10NzYubXV0ZXgpOw0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9jaGFubmVs X3N3aXRjaF9iZWFjb24oc3RydWN0IGllZWU4MDIxMV9odyAqaHcsDQorCQkJICAgICBzdHJ1Y3Qg aWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkJCSAgICAgc3RydWN0IGNmZzgwMjExX2NoYW5fZGVmICpj aGFuZGVmKQ0KK3sNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IG10NzkxNV9od19kZXYoaHcp Ow0KKw0KKwltdXRleF9sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKwltdDc5MTVfbWN1X2FkZF9i ZWFjb24oaHcsIHZpZiwgdHJ1ZSk7DQorCW11dGV4X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsN Cit9DQorDQoraW50IG10NzkxNV9tYWNfc3RhX2FkZChzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYsIHN0 cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkgICAgICAgc3RydWN0IGllZWU4MDIxMV9zdGEg KnN0YSkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBjb250YWluZXJfb2YobWRldiwg c3RydWN0IG10NzkxNV9kZXYsIG10NzYpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAqbXN0YSA9IChz dHJ1Y3QgbXQ3OTE1X3N0YSAqKXN0YS0+ZHJ2X3ByaXY7DQorCXN0cnVjdCBtdDc5MTVfdmlmICpt dmlmID0gKHN0cnVjdCBtdDc5MTVfdmlmICopdmlmLT5kcnZfcHJpdjsNCisJaW50IGlkeDsNCisN CisJaWR4ID0gbXQ3Nl93Y2lkX2FsbG9jKGRldi0+bXQ3Ni53Y2lkX21hc2ssIE1UNzkxNV9XVEJM X1NUQSAtIDEpOw0KKwlpZiAoaWR4IDwgMCkNCisJCXJldHVybiAtRU5PU1BDOw0KKw0KKwlJTklU X0xJU1RfSEVBRCgmbXN0YS0+cG9sbF9saXN0KTsNCisJSU5JVF9XT1JLKCZtc3RhLT5zdGF0c193 b3JrLCBtdDc5MTVfbWFjX3N0YV9zdGF0c193b3JrKTsNCisJc3Bpbl9sb2NrX2luaXQoJm1zdGEt PmFtcGR1X2xvY2spOw0KKwltc3RhLT52aWYgPSBtdmlmOw0KKwltc3RhLT53Y2lkLnN0YSA9IDE7 DQorCW1zdGEtPndjaWQuaWR4ID0gaWR4Ow0KKwltc3RhLT53Y2lkLmV4dF9waHkgPSBtdmlmLT5i YW5kX2lkeDsNCisJbXN0YS0+d2NpZC50eF9pbmZvIHw9IE1UX1dDSURfVFhfSU5GT19TRVQ7DQor CW1zdGEtPnN0YXRzLmppZmZpZXMgPSBqaWZmaWVzOw0KKw0KKwltdDc5MTVfbWFjX3d0YmxfdXBk YXRlKGRldiwgaWR4LA0KKwkJCSAgICAgICBNVF9XVEJMX1VQREFURV9BRE1fQ09VTlRfQ0xFQVIp Ow0KKw0KKwltdDc5MTVfbWN1X2FkZF9zdGEoZGV2LCB2aWYsIHN0YSwgdHJ1ZSk7DQorDQorCXJl dHVybiAwOw0KK30NCisNCit2b2lkIG10NzkxNV9tYWNfc3RhX3JlbW92ZShzdHJ1Y3QgbXQ3Nl9k ZXYgKm1kZXYsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkJICAgc3RydWN0IGllZWU4 MDIxMV9zdGEgKnN0YSkNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBjb250YWluZXJf b2YobWRldiwgc3RydWN0IG10NzkxNV9kZXYsIG10NzYpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAq bXN0YSA9IChzdHJ1Y3QgbXQ3OTE1X3N0YSAqKXN0YS0+ZHJ2X3ByaXY7DQorDQorCW10NzkxNV9t Y3VfYWRkX3N0YShkZXYsIHZpZiwgc3RhLCBmYWxzZSk7DQorDQorCW10NzkxNV9tYWNfd3RibF91 cGRhdGUoZGV2LCBtc3RhLT53Y2lkLmlkeCwNCisJCQkgICAgICAgTVRfV1RCTF9VUERBVEVfQURN X0NPVU5UX0NMRUFSKTsNCisNCisJc3Bpbl9sb2NrX2JoKCZkZXYtPnN0YV9wb2xsX2xvY2spOw0K KwlpZiAoIWxpc3RfZW1wdHkoJm1zdGEtPnBvbGxfbGlzdCkpDQorCQlsaXN0X2RlbF9pbml0KCZt c3RhLT5wb2xsX2xpc3QpOw0KKwlzcGluX3VubG9ja19iaCgmZGV2LT5zdGFfcG9sbF9sb2NrKTsN Cit9DQorDQorc3RhdGljIHZvaWQgbXQ3OTE1X3R4KHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3LA0K KwkJICAgICAgc3RydWN0IGllZWU4MDIxMV90eF9jb250cm9sICpjb250cm9sLA0KKwkJICAgICAg c3RydWN0IHNrX2J1ZmYgKnNrYikNCit7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBtdDc5 MTVfaHdfZGV2KGh3KTsNCisJc3RydWN0IG10NzZfcGh5ICptcGh5ID0gaHctPnByaXY7DQorCXN0 cnVjdCBpZWVlODAyMTFfdHhfaW5mbyAqaW5mbyA9IElFRUU4MDIxMV9TS0JfQ0Ioc2tiKTsNCisJ c3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiA9IGluZm8tPmNvbnRyb2wudmlmOw0KKwlzdHJ1Y3Qg bXQ3Nl93Y2lkICp3Y2lkID0gJmRldi0+bXQ3Ni5nbG9iYWxfd2NpZDsNCisNCisJaWYgKGNvbnRy b2wtPnN0YSkgew0KKwkJc3RydWN0IG10NzkxNV9zdGEgKnN0YTsNCisNCisJCXN0YSA9IChzdHJ1 Y3QgbXQ3OTE1X3N0YSAqKWNvbnRyb2wtPnN0YS0+ZHJ2X3ByaXY7DQorCQl3Y2lkID0gJnN0YS0+ d2NpZDsNCisJfQ0KKw0KKwlpZiAodmlmICYmICFjb250cm9sLT5zdGEpIHsNCisJCXN0cnVjdCBt dDc5MTVfdmlmICptdmlmOw0KKw0KKwkJbXZpZiA9IChzdHJ1Y3QgbXQ3OTE1X3ZpZiAqKXZpZi0+ ZHJ2X3ByaXY7DQorCQl3Y2lkID0gJm12aWYtPnN0YS53Y2lkOw0KKwl9DQorDQorCW10NzZfdHgo bXBoeSwgY29udHJvbC0+c3RhLCB3Y2lkLCBza2IpOw0KK30NCisNCitzdGF0aWMgaW50IG10Nzkx NV9zZXRfcnRzX3RocmVzaG9sZChzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywgdTMyIHZhbCkNCit7 DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisJc3RydWN0 IG10NzkxNV9waHkgKnBoeSA9IG10NzkxNV9od19waHkoaHcpOw0KKw0KKwltdXRleF9sb2NrKCZk ZXYtPm10NzYubXV0ZXgpOw0KKwltdDc5MTVfbWN1X3NldF9ydHNfdGhyZXNoKHBoeSwgdmFsKTsN CisJbXV0ZXhfdW5sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKw0KKwlyZXR1cm4gMDsNCit9DQor DQorc3RhdGljIGludA0KK210NzkxNV9hbXBkdV9hY3Rpb24oc3RydWN0IGllZWU4MDIxMV9odyAq aHcsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkgICAgc3RydWN0IGllZWU4MDIxMV9h bXBkdV9wYXJhbXMgKnBhcmFtcykNCit7DQorCWVudW0gaWVlZTgwMjExX2FtcGR1X21sbWVfYWN0 aW9uIGFjdGlvbiA9IHBhcmFtcy0+YWN0aW9uOw0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0g bXQ3OTE1X2h3X2Rldihodyk7DQorCXN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEgPSBwYXJhbXMt PnN0YTsNCisJc3RydWN0IGllZWU4MDIxMV90eHEgKnR4cSA9IHN0YS0+dHhxW3BhcmFtcy0+dGlk XTsNCisJc3RydWN0IG10NzkxNV9zdGEgKm1zdGEgPSAoc3RydWN0IG10NzkxNV9zdGEgKilzdGEt PmRydl9wcml2Ow0KKwl1MTYgdGlkID0gcGFyYW1zLT50aWQ7DQorCXUxNiBzc24gPSBwYXJhbXMt PnNzbjsNCisJc3RydWN0IG10NzZfdHhxICptdHhxOw0KKwlpbnQgcmV0ID0gMDsNCisNCisJaWYg KCF0eHEpDQorCQlyZXR1cm4gLUVJTlZBTDsNCisNCisJbXR4cSA9IChzdHJ1Y3QgbXQ3Nl90eHEg Kil0eHEtPmRydl9wcml2Ow0KKw0KKwltdXRleF9sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0KKwlz d2l0Y2ggKGFjdGlvbikgew0KKwljYXNlIElFRUU4MDIxMV9BTVBEVV9SWF9TVEFSVDoNCisJCW10 NzZfcnhfYWdncl9zdGFydCgmZGV2LT5tdDc2LCAmbXN0YS0+d2NpZCwgdGlkLCBzc24sDQorCQkJ CSAgIHBhcmFtcy0+YnVmX3NpemUpOw0KKwkJbXQ3OTE1X21jdV9hZGRfcnhfYmEoZGV2LCBwYXJh bXMsIHRydWUpOw0KKwkJYnJlYWs7DQorCWNhc2UgSUVFRTgwMjExX0FNUERVX1JYX1NUT1A6DQor CQltdDc2X3J4X2FnZ3Jfc3RvcCgmZGV2LT5tdDc2LCAmbXN0YS0+d2NpZCwgdGlkKTsNCisJCW10 NzkxNV9tY3VfYWRkX3J4X2JhKGRldiwgcGFyYW1zLCBmYWxzZSk7DQorCQlicmVhazsNCisJY2Fz ZSBJRUVFODAyMTFfQU1QRFVfVFhfT1BFUkFUSU9OQUw6DQorCQltdHhxLT5hZ2dyID0gdHJ1ZTsN CisJCW10eHEtPnNlbmRfYmFyID0gZmFsc2U7DQorCQltdDc5MTVfc2V0X2FnZ3Jfc3RhdGUobXN0 YSwgdGlkLCBNVDc5MTVfQUdHUl9PUEVSQVRJT05BTCk7DQorCQltdDc5MTVfbWN1X2FkZF90eF9i YShkZXYsIHBhcmFtcywgdHJ1ZSk7DQorCQlicmVhazsNCisJY2FzZSBJRUVFODAyMTFfQU1QRFVf VFhfU1RPUF9GTFVTSDoNCisJY2FzZSBJRUVFODAyMTFfQU1QRFVfVFhfU1RPUF9GTFVTSF9DT05U Og0KKwkJbXR4cS0+YWdnciA9IGZhbHNlOw0KKwkJbXQ3OTE1X3NldF9hZ2dyX3N0YXRlKG1zdGEs IHRpZCwgTVQ3OTE1X0FHR1JfU1RPUCk7DQorCQltdDc5MTVfbWN1X2FkZF90eF9iYShkZXYsIHBh cmFtcywgZmFsc2UpOw0KKwkJYnJlYWs7DQorCWNhc2UgSUVFRTgwMjExX0FNUERVX1RYX1NUQVJU Og0KKwkJbXR4cS0+YWdnX3NzbiA9IElFRUU4MDIxMV9TTl9UT19TRVEoc3NuKTsNCisJCW10Nzkx NV9zZXRfYWdncl9zdGF0ZShtc3RhLCB0aWQsIE1UNzkxNV9BR0dSX1NUQVJUKTsNCisJCXJldCA9 IElFRUU4MDIxMV9BTVBEVV9UWF9TVEFSVF9JTU1FRElBVEU7DQorCQlicmVhazsNCisJY2FzZSBJ RUVFODAyMTFfQU1QRFVfVFhfU1RPUF9DT05UOg0KKwkJbXR4cS0+YWdnciA9IGZhbHNlOw0KKwkJ bXQ3OTE1X3NldF9hZ2dyX3N0YXRlKG1zdGEsIHRpZCwgTVQ3OTE1X0FHR1JfU1RPUCk7DQorCQlt dDc5MTVfbWN1X2FkZF90eF9iYShkZXYsIHBhcmFtcywgZmFsc2UpOw0KKwkJaWVlZTgwMjExX3N0 b3BfdHhfYmFfY2JfaXJxc2FmZSh2aWYsIHN0YS0+YWRkciwgdGlkKTsNCisJCWJyZWFrOw0KKwl9 DQorCW11dGV4X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJcmV0dXJuIHJldDsNCit9 DQorDQorc3RhdGljIGludA0KK210NzkxNV9zdGFfYWRkKHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3 LCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkgICAgICAgc3RydWN0IGllZWU4MDIxMV9z dGEgKnN0YSkNCit7DQorCXJldHVybiBtdDc2X3N0YV9zdGF0ZShodywgdmlmLCBzdGEsIElFRUU4 MDIxMV9TVEFfTk9URVhJU1QsDQorCQkJICAgICAgSUVFRTgwMjExX1NUQV9OT05FKTsNCit9DQor DQorc3RhdGljIGludA0KK210NzkxNV9zdGFfcmVtb3ZlKHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3 LCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkJICBzdHJ1Y3QgaWVlZTgwMjExX3N0YSAq c3RhKQ0KK3sNCisJcmV0dXJuIG10NzZfc3RhX3N0YXRlKGh3LCB2aWYsIHN0YSwgSUVFRTgwMjEx X1NUQV9OT05FLA0KKwkJCSAgICAgIElFRUU4MDIxMV9TVEFfTk9URVhJU1QpOw0KK30NCisNCitz dGF0aWMgaW50DQorbXQ3OTE1X2dldF9zdGF0cyhzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywNCisJ CSBzdHJ1Y3QgaWVlZTgwMjExX2xvd19sZXZlbF9zdGF0cyAqc3RhdHMpDQorew0KKwlzdHJ1Y3Qg bXQ3OTE1X3BoeSAqcGh5ID0gbXQ3OTE1X2h3X3BoeShodyk7DQorCXN0cnVjdCBtaWJfc3RhdHMg Km1pYiA9ICZwaHktPm1pYjsNCisNCisJc3RhdHMtPmRvdDExUlRTU3VjY2Vzc0NvdW50ID0gbWli LT5ydHNfY250Ow0KKwlzdGF0cy0+ZG90MTFSVFNGYWlsdXJlQ291bnQgPSBtaWItPnJ0c19yZXRy aWVzX2NudDsNCisJc3RhdHMtPmRvdDExRkNTRXJyb3JDb3VudCA9IG1pYi0+ZmNzX2Vycl9jbnQ7 DQorCXN0YXRzLT5kb3QxMUFDS0ZhaWx1cmVDb3VudCA9IG1pYi0+YWNrX2ZhaWxfY250Ow0KKw0K KwlyZXR1cm4gMDsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfc2V0X2NvdmVyYWdlX2Ns YXNzKHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3LCBzMTYgY292ZXJhZ2VfY2xhc3MpDQorew0KKwlz dHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5ID0gbXQ3OTE1X2h3X3BoeShodyk7DQorDQorCXBoeS0+Y292 ZXJhZ2VfY2xhc3MgPSBtYXhfdChzMTYsIGNvdmVyYWdlX2NsYXNzLCAwKTsNCisJbXQ3OTE1X21h Y19zZXRfdGltaW5nKHBoeSk7DQorfQ0KKw0KK3N0YXRpYyBpbnQNCittdDc5MTVfc2V0X2FudGVu bmEoc3RydWN0IGllZWU4MDIxMV9odyAqaHcsIHUzMiB0eF9hbnQsIHUzMiByeF9hbnQpDQorew0K KwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gbXQ3OTE1X2h3X2Rldihodyk7DQorCXN0cnVjdCBt dDc5MTVfcGh5ICpwaHkgPSBtdDc5MTVfaHdfcGh5KGh3KTsNCisJaW50IG1heF9uc3MgPSBod2Vp Z2h0OChody0+d2lwaHktPmF2YWlsYWJsZV9hbnRlbm5hc190eCk7DQorCWJvb2wgZXh0X3BoeSA9 IHBoeSAhPSAmZGV2LT5waHk7DQorDQorCWlmICghdHhfYW50IHx8IHR4X2FudCAhPSByeF9hbnQg fHwgZmZzKHR4X2FudCkgPiBtYXhfbnNzKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCWlmICgo QklUKGh3ZWlnaHQ4KHR4X2FudCkpIC0gMSkgIT0gdHhfYW50KQ0KKwkJdHhfYW50ID0gQklUKGZm cyh0eF9hbnQpIC0gMSkgLSAxOw0KKw0KKwltdXRleF9sb2NrKCZkZXYtPm10NzYubXV0ZXgpOw0K Kw0KKwlwaHktPm10NzYtPmFudGVubmFfbWFzayA9IHR4X2FudDsNCisNCisJaWYgKGV4dF9waHkp IHsNCisJCWlmIChkZXYtPmNoYWlubWFzayA9PSAweGYpDQorCQkJdHhfYW50IDw8PSAyOw0KKwkJ ZWxzZQ0KKwkJCXR4X2FudCA8PD0gMTsNCisJfQ0KKwlwaHktPmNoYWlubWFzayA9IHR4X2FudDsN CisNCisJbXQ3Nl9zZXRfc3RyZWFtX2NhcHMoJmRldi0+bXQ3NiwgdHJ1ZSk7DQorDQorCW11dGV4 X3VubG9jaygmZGV2LT5tdDc2Lm11dGV4KTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRp YyB2b2lkDQorbXQ3OTE1X3N0YV9yY191cGRhdGUoc3RydWN0IGllZWU4MDIxMV9odyAqaHcsDQor CQkgICAgIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkgICAgIHN0cnVjdCBpZWVlODAy MTFfc3RhICpzdGEsDQorCQkgICAgIHUzMiBjaGFuZ2VkKQ0KK3sNCisJc3RydWN0IG10NzkxNV9z dGEgKm1zdGEgPSAoc3RydWN0IG10NzkxNV9zdGEgKilzdGEtPmRydl9wcml2Ow0KKw0KKwlyY3Vf cmVhZF9sb2NrKCk7DQorCXN0YSA9IGllZWU4MDIxMV9maW5kX3N0YSh2aWYsIHN0YS0+YWRkcik7 DQorCWlmICghc3RhKSB7DQorCQlyY3VfcmVhZF91bmxvY2soKTsNCisJCXJldHVybjsNCisJfQ0K KwlyY3VfcmVhZF9sb2NrKCk7DQorDQorCXNldF9iaXQoY2hhbmdlZCwgJm1zdGEtPnN0YXRzLmNo YW5nZWQpOw0KKwlpZWVlODAyMTFfcXVldWVfd29yayhodywgJm1zdGEtPnN0YXRzX3dvcmspOw0K K30NCisNCitjb25zdCBzdHJ1Y3QgaWVlZTgwMjExX29wcyBtdDc5MTVfb3BzID0gew0KKwkudHgg PSBtdDc5MTVfdHgsDQorCS5zdGFydCA9IG10NzkxNV9zdGFydCwNCisJLnN0b3AgPSBtdDc5MTVf c3RvcCwNCisJLmFkZF9pbnRlcmZhY2UgPSBtdDc5MTVfYWRkX2ludGVyZmFjZSwNCisJLnJlbW92 ZV9pbnRlcmZhY2UgPSBtdDc5MTVfcmVtb3ZlX2ludGVyZmFjZSwNCisJLmNvbmZpZyA9IG10Nzkx NV9jb25maWcsDQorCS5jb25mX3R4ID0gbXQ3OTE1X2NvbmZfdHgsDQorCS5jb25maWd1cmVfZmls dGVyID0gbXQ3OTE1X2NvbmZpZ3VyZV9maWx0ZXIsDQorCS5ic3NfaW5mb19jaGFuZ2VkID0gbXQ3 OTE1X2Jzc19pbmZvX2NoYW5nZWQsDQorCS5zdGFfYWRkID0gbXQ3OTE1X3N0YV9hZGQsDQorCS5z dGFfcmVtb3ZlID0gbXQ3OTE1X3N0YV9yZW1vdmUsDQorCS5zdGFfcHJlX3JjdV9yZW1vdmUgPSBt dDc2X3N0YV9wcmVfcmN1X3JlbW92ZSwNCisJLnN0YV9yY191cGRhdGUgPSBtdDc5MTVfc3RhX3Jj X3VwZGF0ZSwNCisJLnNldF9rZXkgPSBtdDc5MTVfc2V0X2tleSwNCisJLmFtcGR1X2FjdGlvbiA9 IG10NzkxNV9hbXBkdV9hY3Rpb24sDQorCS5zZXRfcnRzX3RocmVzaG9sZCA9IG10NzkxNV9zZXRf cnRzX3RocmVzaG9sZCwNCisJLndha2VfdHhfcXVldWUgPSBtdDc2X3dha2VfdHhfcXVldWUsDQor CS5zd19zY2FuX3N0YXJ0ID0gbXQ3Nl9zd19zY2FuLA0KKwkuc3dfc2Nhbl9jb21wbGV0ZSA9IG10 NzZfc3dfc2Nhbl9jb21wbGV0ZSwNCisJLnJlbGVhc2VfYnVmZmVyZWRfZnJhbWVzID0gbXQ3Nl9y ZWxlYXNlX2J1ZmZlcmVkX2ZyYW1lcywNCisJLmdldF90eHBvd2VyID0gbXQ3Nl9nZXRfdHhwb3dl ciwNCisJLmNoYW5uZWxfc3dpdGNoX2JlYWNvbiA9IG10NzkxNV9jaGFubmVsX3N3aXRjaF9iZWFj b24sDQorCS5nZXRfc3RhdHMgPSBtdDc5MTVfZ2V0X3N0YXRzLA0KKwkuZ2V0X3N1cnZleSA9IG10 NzZfZ2V0X3N1cnZleSwNCisJLmdldF9hbnRlbm5hID0gbXQ3Nl9nZXRfYW50ZW5uYSwNCisJLnNl dF9hbnRlbm5hID0gbXQ3OTE1X3NldF9hbnRlbm5hLA0KKwkuc2V0X2NvdmVyYWdlX2NsYXNzID0g bXQ3OTE1X3NldF9jb3ZlcmFnZV9jbGFzcywNCit9Ow0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0 L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L21jdS5jIGIvZHJpdmVycy9uZXQvd2lyZWxl c3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWN1LmMNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRl eCAwMDAwMDAwMDAwMDAuLjVjYTZiZDlmMDk5Yw0KLS0tIC9kZXYvbnVsbA0KKysrIGIvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbWN1LmMNCkBAIC0wLDAgKzEsMjMx OSBAQA0KKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBJU0MNCisvKiBDb3B5cmlnaHQgKEMp IDIwMjAgTWVkaWFUZWsgSW5jLiAqLw0KKw0KKyNpbmNsdWRlIDxsaW51eC9maXJtd2FyZS5oPg0K KyNpbmNsdWRlIDxsaW51eC9mcy5oPg0KKyNpbmNsdWRlICJtdDc5MTUuaCINCisjaW5jbHVkZSAi bWN1LmgiDQorI2luY2x1ZGUgIm1hYy5oIg0KKyNpbmNsdWRlICJlZXByb20uaCINCisNCitzdHJ1 Y3QgbXQ3OTE1X3BhdGNoX2hkciB7DQorCWNoYXIgYnVpbGRfZGF0ZVsxNl07DQorCWNoYXIgcGxh dGZvcm1bNF07DQorCV9fYmUzMiBod19zd192ZXI7DQorCV9fYmUzMiBwYXRjaF92ZXI7DQorCV9f YmUxNiBjaGVja3N1bTsNCisJdTE2IHJlc2VydmVkOw0KKwlzdHJ1Y3Qgew0KKwkJX19iZTMyIHBh dGNoX3ZlcjsNCisJCV9fYmUzMiBzdWJzeXM7DQorCQlfX2JlMzIgZmVhdHVyZTsNCisJCV9fYmUz MiBuX3JlZ2lvbjsNCisJCV9fYmUzMiBjcmM7DQorCQl1MzIgcmVzZXJ2ZWRbMTFdOw0KKwl9IGRl c2M7DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3QgbXQ3OTE1X3BhdGNoX3NlYyB7DQorCV9fYmUz MiB0eXBlOw0KKwlfX2JlMzIgb2ZmczsNCisJX19iZTMyIHNpemU7DQorCXVuaW9uIHsNCisJCV9f YmUzMiBzcGVjWzEzXTsNCisJCXN0cnVjdCB7DQorCQkJX19iZTMyIGFkZHI7DQorCQkJX19iZTMy IGxlbjsNCisJCQlfX2JlMzIgc2VjX2tleV9pZHg7DQorCQkJX19iZTMyIGFsaWduX2xlbjsNCisJ CQl1MzIgcmVzZXJ2ZWRbOV07DQorCQl9IGluZm87DQorCX07DQorfSBfX3BhY2tlZDsNCisNCitz dHJ1Y3QgbXQ3OTE1X2Z3X3RyYWlsZXIgew0KKwl1OCBjaGlwX2lkOw0KKwl1OCBlY29fY29kZTsN CisJdTggbl9yZWdpb247DQorCXU4IGZvcm1hdF92ZXI7DQorCXU4IGZvcm1hdF9mbGFnOw0KKwl1 OCByZXNlcnZlZFsyXTsNCisJY2hhciBmd192ZXJbMTBdOw0KKwljaGFyIGJ1aWxkX2RhdGVbMTVd Ow0KKwl1MzIgY3JjOw0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IG10NzkxNV9md19yZWdpb24g ew0KKwlfX2xlMzIgZGVjb21wX2NyYzsNCisJX19sZTMyIGRlY29tcF9sZW47DQorCV9fbGUzMiBk ZWNvbXBfYmxrX3N6Ow0KKwl1OCByZXNlcnZlZFs0XTsNCisJX19sZTMyIGFkZHI7DQorCV9fbGUz MiBsZW47DQorCXU4IGZlYXR1cmVfc2V0Ow0KKwl1OCByZXNlcnZlZDFbMTVdOw0KK30gX19wYWNr ZWQ7DQorDQorI2RlZmluZSBNQ1VfUEFUQ0hfQUREUkVTUwkJMHgyMDAwMDANCisNCisjZGVmaW5l IEZXX0ZFQVRVUkVfU0VUX0VOQ1JZUFQJCUJJVCgwKQ0KKyNkZWZpbmUgRldfRkVBVFVSRV9TRVRf S0VZX0lEWAkJR0VOTUFTSygyLCAxKQ0KKyNkZWZpbmUgRldfRkVBVFVSRV9PVkVSUklERV9BRERS CUJJVCg1KQ0KKw0KKyNkZWZpbmUgRExfTU9ERV9FTkNSWVBUCQkJQklUKDApDQorI2RlZmluZSBE TF9NT0RFX0tFWV9JRFgJCQlHRU5NQVNLKDIsIDEpDQorI2RlZmluZSBETF9NT0RFX1JFU0VUX1NF Q19JVgkJQklUKDMpDQorI2RlZmluZSBETF9NT0RFX1dPUktJTkdfUERBX0NSNAkJQklUKDQpDQor I2RlZmluZSBETF9NT0RFX05FRURfUlNQCQlCSVQoMzEpDQorDQorI2RlZmluZSBGV19TVEFSVF9P VkVSUklERQkJQklUKDApDQorI2RlZmluZSBGV19TVEFSVF9XT1JLSU5HX1BEQV9DUjQJQklUKDIp DQorDQorI2RlZmluZSBQQVRDSF9TRUNfVFlQRV9NQVNLCQlHRU5NQVNLKDE1LCAwKQ0KKyNkZWZp bmUgUEFUQ0hfU0VDX1RZUEVfSU5GTwkJMHgyDQorDQorI2RlZmluZSB0b193Y2lkX2xvKGlkKQkJ CUZJRUxEX0dFVChHRU5NQVNLKDcsIDApLCAodTE2KWlkKQ0KKyNkZWZpbmUgdG9fd2NpZF9oaShp ZCkJCQlGSUVMRF9HRVQoR0VOTUFTSyg5LCA4KSwgKHUxNilpZCkNCisNCitzdGF0aWMgZW51bSBt dDc5MTVfY2lwaGVyX3R5cGUNCittdDc5MTVfbWN1X2dldF9jaXBoZXIoaW50IGNpcGhlcikNCit7 DQorCXN3aXRjaCAoY2lwaGVyKSB7DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfV0VQNDA6DQor CQlyZXR1cm4gTVRfQ0lQSEVSX1dFUDQwOw0KKwljYXNlIFdMQU5fQ0lQSEVSX1NVSVRFX1dFUDEw NDoNCisJCXJldHVybiBNVF9DSVBIRVJfV0VQMTA0Ow0KKwljYXNlIFdMQU5fQ0lQSEVSX1NVSVRF X1RLSVA6DQorCQlyZXR1cm4gTVRfQ0lQSEVSX1RLSVA7DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJ VEVfQUVTX0NNQUM6DQorCQlyZXR1cm4gTVRfQ0lQSEVSX0JJUF9DTUFDXzEyODsNCisJY2FzZSBX TEFOX0NJUEhFUl9TVUlURV9DQ01QOg0KKwkJcmV0dXJuIE1UX0NJUEhFUl9BRVNfQ0NNUDsNCisJ Y2FzZSBXTEFOX0NJUEhFUl9TVUlURV9DQ01QXzI1NjoNCisJCXJldHVybiBNVF9DSVBIRVJfQ0NN UF8yNTY7DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfR0NNUDoNCisJCXJldHVybiBNVF9DSVBI RVJfR0NNUDsNCisJY2FzZSBXTEFOX0NJUEhFUl9TVUlURV9HQ01QXzI1NjoNCisJCXJldHVybiBN VF9DSVBIRVJfR0NNUF8yNTY7DQorCWNhc2UgV0xBTl9DSVBIRVJfU1VJVEVfU01TNDoNCisJCXJl dHVybiBNVF9DSVBIRVJfV0FQSTsNCisJZGVmYXVsdDoNCisJCXJldHVybiBNVF9DSVBIRVJfTk9O RTsNCisJfQ0KK30NCisNCitzdGF0aWMgdTggbXQ3OTE1X21jdV9jaGFuX2J3KHN0cnVjdCBjZmc4 MDIxMV9jaGFuX2RlZiAqY2hhbmRlZikNCit7DQorCXN0YXRpYyBjb25zdCB1OCB3aWR0aF90b19i d1tdID0gew0KKwkJW05MODAyMTFfQ0hBTl9XSURUSF80MF0gPSBDTURfQ0JXXzQwTUhaLA0KKwkJ W05MODAyMTFfQ0hBTl9XSURUSF84MF0gPSBDTURfQ0JXXzgwTUhaLA0KKwkJW05MODAyMTFfQ0hB Tl9XSURUSF84MFA4MF0gPSBDTURfQ0JXXzgwODBNSFosDQorCQlbTkw4MDIxMV9DSEFOX1dJRFRI XzE2MF0gPSBDTURfQ0JXXzE2ME1IWiwNCisJCVtOTDgwMjExX0NIQU5fV0lEVEhfNV0gPSBDTURf Q0JXXzVNSFosDQorCQlbTkw4MDIxMV9DSEFOX1dJRFRIXzEwXSA9IENNRF9DQldfMTBNSFosDQor CQlbTkw4MDIxMV9DSEFOX1dJRFRIXzIwXSA9IENNRF9DQldfMjBNSFosDQorCQlbTkw4MDIxMV9D SEFOX1dJRFRIXzIwX05PSFRdID0gQ01EX0NCV18yME1IWiwNCisJfTsNCisNCisJaWYgKGNoYW5k ZWYtPndpZHRoID49IEFSUkFZX1NJWkUod2lkdGhfdG9fYncpKQ0KKwkJcmV0dXJuIDA7DQorDQor CXJldHVybiB3aWR0aF90b19id1tjaGFuZGVmLT53aWR0aF07DQorfQ0KKw0KK3N0YXRpYyB1OA0K K210NzkxNV9nZXRfcGh5X21vZGUoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgc3RydWN0IGllZWU4 MDIxMV92aWYgKnZpZiwNCisJCSAgICBlbnVtIG5sODAyMTFfYmFuZCBiYW5kLCBzdHJ1Y3QgaWVl ZTgwMjExX3N0YSAqc3RhKQ0KK3sNCisJc3RydWN0IGllZWU4MDIxMV9zdGFfaHRfY2FwICpodF9j YXA7DQorCXN0cnVjdCBpZWVlODAyMTFfc3RhX3ZodF9jYXAgKnZodF9jYXA7DQorCXU4IG1vZGUg PSAwOw0KKw0KKwlpZiAoc3RhKSB7DQorCQlodF9jYXAgPSAmc3RhLT5odF9jYXA7DQorCQl2aHRf Y2FwID0gJnN0YS0+dmh0X2NhcDsNCisJfSBlbHNlIHsNCisJCXN0cnVjdCBpZWVlODAyMTFfc3Vw cG9ydGVkX2JhbmQgKnNiYW5kOw0KKw0KKwkJaWYgKGJhbmQgPT0gTkw4MDIxMV9CQU5EXzJHSFop DQorCQkJc2JhbmQgPSAmZGV2LT5tcGh5LnNiYW5kXzJnLnNiYW5kOw0KKwkJZWxzZQ0KKwkJCXNi YW5kID0gJmRldi0+bXBoeS5zYmFuZF81Zy5zYmFuZDsNCisNCisJCWh0X2NhcCA9ICZzYmFuZC0+ aHRfY2FwOw0KKwkJdmh0X2NhcCA9ICZzYmFuZC0+dmh0X2NhcDsNCisJfQ0KKw0KKwlpZiAoYmFu ZCA9PSBOTDgwMjExX0JBTkRfMkdIWikgew0KKwkJbW9kZSB8PSBQSFlfTU9ERV9CIHwgUEhZX01P REVfRzsNCisNCisJCWlmIChodF9jYXAtPmh0X3N1cHBvcnRlZCkNCisJCQltb2RlIHw9IFBIWV9N T0RFX0dOOw0KKwl9IGVsc2UgaWYgKGJhbmQgPT0gTkw4MDIxMV9CQU5EXzVHSFopIHsNCisJCW1v ZGUgfD0gUEhZX01PREVfQTsNCisNCisJCWlmIChodF9jYXAtPmh0X3N1cHBvcnRlZCkNCisJCQlt b2RlIHw9IFBIWV9NT0RFX0FOOw0KKw0KKwkJaWYgKHZodF9jYXAtPnZodF9zdXBwb3J0ZWQpDQor CQkJbW9kZSB8PSBQSFlfTU9ERV9BQzsNCisJfQ0KKw0KKwlyZXR1cm4gbW9kZTsNCit9DQorDQor c3RhdGljIGludCBfX210NzkxNV9tY3VfbXNnX3NlbmQoc3RydWN0IG10NzkxNV9kZXYgKmRldiwg c3RydWN0IHNrX2J1ZmYgKnNrYiwNCisJCQkJIGludCBjbWQsIGludCAqd2FpdF9zZXEpDQorew0K KwlzdHJ1Y3QgbXQ3OTE1X21jdV90eGQgKm1jdV90eGQ7DQorCXU4IHNlcSwgcGt0X2ZtdCwgcWlk eDsNCisJZW51bSBtdDc5MTVfdHhxX2lkIHR4cTsNCisJX19sZTMyICp0eGQ7DQorCXUzMiB2YWw7 DQorDQorCXNlcSA9ICsrZGV2LT5tdDc2Lm1jdS5tc2dfc2VxICYgMHhmOw0KKwlpZiAoIXNlcSkN CisJCXNlcSA9ICsrZGV2LT5tdDc2Lm1jdS5tc2dfc2VxICYgMHhmOw0KKw0KKwlpZiAoY21kID09 IC1NQ1VfQ01EX0ZXX1NDQVRURVIpIHsNCisJCXR4cSA9IE1UX1RYUV9GV0RMOw0KKwkJZ290byBl eGl0Ow0KKwl9DQorDQorCW1jdV90eGQgPSAoc3RydWN0IG10NzkxNV9tY3VfdHhkICopc2tiX3B1 c2goc2tiLCBzaXplb2YoKm1jdV90eGQpKTsNCisNCisJaWYgKHRlc3RfYml0KE1UNzZfU1RBVEVf TUNVX1JVTk5JTkcsICZkZXYtPm1waHkuc3RhdGUpKSB7DQorCQl0eHEgPSBNVF9UWFFfTUNVX1dB Ow0KKwkJcWlkeCA9IE1UX1RYX01DVV9QT1JUX1JYX1EwOw0KKwkJcGt0X2ZtdCA9IE1UX1RYX1RZ UEVfQ01EOw0KKwl9IGVsc2Ugew0KKwkJdHhxID0gTVRfVFhRX01DVTsNCisJCXFpZHggPSBNVF9U WF9NQ1VfUE9SVF9SWF9RMDsNCisJCXBrdF9mbXQgPSBNVF9UWF9UWVBFX0NNRDsNCisJfQ0KKw0K Kwl0eGQgPSBtY3VfdHhkLT50eGQ7DQorDQorCXZhbCA9IEZJRUxEX1BSRVAoTVRfVFhEMF9UWF9C WVRFUywgc2tiLT5sZW4pIHwNCisJICAgICAgRklFTERfUFJFUChNVF9UWEQwX1BLVF9GTVQsIHBr dF9mbXQpIHwNCisJICAgICAgRklFTERfUFJFUChNVF9UWEQwX1FfSURYLCBxaWR4KTsNCisJdHhk WzBdID0gY3B1X3RvX2xlMzIodmFsKTsNCisNCisJdmFsID0gTVRfVFhEMV9MT05HX0ZPUk1BVCB8 DQorCSAgICAgIEZJRUxEX1BSRVAoTVRfVFhEMV9IRFJfRk9STUFULCBNVF9IRFJfRk9STUFUX0NN RCk7DQorCXR4ZFsxXSA9IGNwdV90b19sZTMyKHZhbCk7DQorDQorCW1jdV90eGQtPmxlbiA9IGNw dV90b19sZTE2KHNrYi0+bGVuIC0gc2l6ZW9mKG1jdV90eGQtPnR4ZCkpOw0KKwltY3VfdHhkLT5w cV9pZCA9IGNwdV90b19sZTE2KE1DVV9QUV9JRChNVF9UWF9QT1JUX0lEWF9NQ1UsIHFpZHgpKTsN CisJbWN1X3R4ZC0+cGt0X3R5cGUgPSBNQ1VfUEtUX0lEOw0KKwltY3VfdHhkLT5zZXEgPSBzZXE7 DQorDQorCWlmIChjbWQgPCAwKSB7DQorCQltY3VfdHhkLT5zZXRfcXVlcnkgPSBNQ1VfUV9OQTsN CisJCW1jdV90eGQtPmNpZCA9IC1jbWQ7DQorCX0gZWxzZSB7DQorCQltY3VfdHhkLT5jaWQgPSBN Q1VfQ01EX0VYVF9DSUQ7DQorCQltY3VfdHhkLT5leHRfY2lkID0gY21kOw0KKwkJbWN1X3R4ZC0+ ZXh0X2NpZF9hY2sgPSAxOw0KKw0KKwkJLyogZG8gbm90IHVzZSBRX1NFVCBmb3IgZWZ1c2UgKi8N CisJCWlmIChjbWQgPT0gTUNVX0VYVF9DTURfRUZVU0VfQUNDRVNTKQ0KKwkJCW1jdV90eGQtPnNl dF9xdWVyeSA9IE1DVV9RX1FVRVJZOw0KKwkJZWxzZQ0KKwkJCW1jdV90eGQtPnNldF9xdWVyeSA9 IE1DVV9RX1NFVDsNCisJfQ0KKw0KKwltY3VfdHhkLT5zMmRfaW5kZXggPSBNQ1VfUzJEX0gyTjsN CisJQlVJTERfQlVHX09OKGNtZCA9PSBNQ1VfRVhUX0NNRF9FRlVTRV9BQ0NFU1MgJiYNCisJCSAg ICAgbWN1X3R4ZC0+c2V0X3F1ZXJ5ICE9IE1DVV9RX1FVRVJZKTsNCisNCitleGl0Og0KKwlpZiAo d2FpdF9zZXEpDQorCQkqd2FpdF9zZXEgPSBzZXE7DQorDQorCXJldHVybiBtdDc2X3R4X3F1ZXVl X3NrYl9yYXcoZGV2LCB0eHEsIHNrYiwgMCk7DQorfQ0KKw0KK3N0YXRpYyBpbnQNCittdDc5MTVf bWN1X3BhcnNlX2VlcHJvbShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBzdHJ1Y3Qgc2tfYnVmZiAq c2tiKQ0KK3sNCisJc3RydWN0IG10NzkxNV9tY3VfZWVwcm9tX2luZm8gKnJlczsNCisJdTggKmJ1 ZjsNCisNCisJaWYgKCFza2IpDQorCQlyZXR1cm4gLUVJTlZBTDsNCisNCisJc2tiX3B1bGwoc2ti LCBzaXplb2Yoc3RydWN0IG10NzkxNV9tY3VfcnhkKSk7DQorDQorCXJlcyA9IChzdHJ1Y3QgbXQ3 OTE1X21jdV9lZXByb21faW5mbyAqKXNrYi0+ZGF0YTsNCisJYnVmID0gZGV2LT5tdDc2LmVlcHJv bS5kYXRhICsgbGUzMl90b19jcHUocmVzLT5hZGRyKTsNCisJbWVtY3B5KGJ1ZiwgcmVzLT5kYXRh LCAxNik7DQorDQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X21jdV9w YXJzZV9yZXNwb25zZShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBpbnQgY21kLA0KKwkJCSAgc3Ry dWN0IHNrX2J1ZmYgKnNrYiwgaW50IHNlcSkNCit7DQorCXN0cnVjdCBtdDc5MTVfbWN1X3J4ZCAq cnhkID0gKHN0cnVjdCBtdDc5MTVfbWN1X3J4ZCAqKXNrYi0+ZGF0YTsNCisJaW50IHJldCA9IDA7 DQorDQorCWlmIChzZXEgIT0gcnhkLT5zZXEpDQorCQlyZXR1cm4gLUVBR0FJTjsNCisNCisJc3dp dGNoIChjbWQpIHsNCisJY2FzZSAtTUNVX0NNRF9QQVRDSF9TRU1fQ09OVFJPTDoNCisJCXNrYl9w dWxsKHNrYiwgc2l6ZW9mKCpyeGQpIC0gNCk7DQorCQlyZXQgPSAqc2tiLT5kYXRhOw0KKwkJYnJl YWs7DQorCWNhc2UgTUNVX0VYVF9DTURfVEhFUk1BTF9DVFJMOg0KKwkJc2tiX3B1bGwoc2tiLCBz aXplb2YoKnJ4ZCkgKyA0KTsNCisJCXJldCA9IGxlMzJfdG9fY3B1KCooX19sZTMyICopc2tiLT5k YXRhKTsNCisJCWJyZWFrOw0KKwljYXNlIE1DVV9FWFRfQ01EX0VGVVNFX0FDQ0VTUzoNCisJCXJl dCA9IG10NzkxNV9tY3VfcGFyc2VfZWVwcm9tKGRldiwgc2tiKTsNCisJCWJyZWFrOw0KKwlkZWZh dWx0Og0KKwkJYnJlYWs7DQorCX0NCisJZGV2X2tmcmVlX3NrYihza2IpOw0KKw0KKwlyZXR1cm4g cmV0Ow0KK30NCisNCitzdGF0aWMgaW50DQorbXQ3OTE1X21jdV93YWl0X3Jlc3BvbnNlKHN0cnVj dCBtdDc5MTVfZGV2ICpkZXYsIGludCBjbWQsIGludCBzZXEpDQorew0KKwl1bnNpZ25lZCBsb25n IGV4cGlyZXMgPSBqaWZmaWVzICsgMjAgKiBIWjsNCisJc3RydWN0IHNrX2J1ZmYgKnNrYjsNCisJ aW50IHJldCA9IDA7DQorDQorCXdoaWxlICh0cnVlKSB7DQorCQlza2IgPSBtdDc2X21jdV9nZXRf cmVzcG9uc2UoJmRldi0+bXQ3NiwgZXhwaXJlcyk7DQorCQlpZiAoIXNrYikgew0KKwkJCWRldl9l cnIoZGV2LT5tdDc2LmRldiwgIk1lc3NhZ2UgJWQgKHNlcSAlZCkgdGltZW91dFxuIiwNCisJCQkJ Y21kLCBzZXEpOw0KKwkJCXJldHVybiAtRVRJTUVET1VUOw0KKwkJfQ0KKw0KKwkJcmV0ID0gbXQ3 OTE1X21jdV9wYXJzZV9yZXNwb25zZShkZXYsIGNtZCwgc2tiLCBzZXEpOw0KKwkJaWYgKHJldCAh PSAtRUFHQUlOKQ0KKwkJCWJyZWFrOw0KKwl9DQorDQorCXJldHVybiByZXQ7DQorfQ0KKw0KK3N0 YXRpYyBpbnQNCittdDc5MTVfbWN1X3NlbmRfbWVzc2FnZShzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYs IHN0cnVjdCBza19idWZmICpza2IsDQorCQkJaW50IGNtZCwgYm9vbCB3YWl0X3Jlc3ApDQorew0K KwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gY29udGFpbmVyX29mKG1kZXYsIHN0cnVjdCBtdDc5 MTVfZGV2LCBtdDc2KTsNCisJaW50IHJldCwgc2VxOw0KKw0KKwltdXRleF9sb2NrKCZtZGV2LT5t Y3UubXV0ZXgpOw0KKw0KKwlyZXQgPSBfX210NzkxNV9tY3VfbXNnX3NlbmQoZGV2LCBza2IsIGNt ZCwgJnNlcSk7DQorCWlmIChyZXQpDQorCQlnb3RvIG91dDsNCisNCisJaWYgKHdhaXRfcmVzcCkN CisJCXJldCA9IG10NzkxNV9tY3Vfd2FpdF9yZXNwb25zZShkZXYsIGNtZCwgc2VxKTsNCisNCitv dXQ6DQorCW11dGV4X3VubG9jaygmbWRldi0+bWN1Lm11dGV4KTsNCisNCisJcmV0dXJuIHJldDsN Cit9DQorDQorc3RhdGljIGludA0KK210NzkxNV9tY3VfbXNnX3NlbmQoc3RydWN0IG10NzZfZGV2 ICptZGV2LCBpbnQgY21kLCBjb25zdCB2b2lkICpkYXRhLA0KKwkJICAgIGludCBsZW4sIGJvb2wg d2FpdF9yZXNwKQ0KK3sNCisJc3RydWN0IHNrX2J1ZmYgKnNrYjsNCisNCisJc2tiID0gbXQ3Nl9t Y3VfbXNnX2FsbG9jKG1kZXYsIGRhdGEsIGxlbik7DQorCWlmICghc2tiKQ0KKwkJcmV0dXJuIC1F Tk9NRU07DQorDQorCXJldHVybiBfX210NzZfbWN1X3NrYl9zZW5kX21zZyhtZGV2LCBza2IsIGNt ZCwgd2FpdF9yZXNwKTsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X2NzYV9maW5p c2godm9pZCAqcHJpdiwgdTggKm1hYywgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZikNCit7DQor CWlmICh2aWYtPmNzYV9hY3RpdmUpDQorCQlpZWVlODAyMTFfY3NhX2ZpbmlzaCh2aWYpOw0KK30N CisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9tY3VfcnhfcmFkYXJfZGV0ZWN0ZWQoc3RydWN0IG10 NzkxNV9kZXYgKmRldiwgc3RydWN0IHNrX2J1ZmYgKnNrYikNCit7DQorCXN0cnVjdCBtdDc2X3Bo eSAqbXBoeSA9ICZkZXYtPm10NzYucGh5Ow0KKwlzdHJ1Y3QgbXQ3OTE1X21jdV9yZGRfcmVwb3J0 ICpyOw0KKw0KKwlyID0gKHN0cnVjdCBtdDc5MTVfbWN1X3JkZF9yZXBvcnQgKilza2ItPmRhdGE7 DQorDQorCWlmIChyLT5pZHggJiYgZGV2LT5tdDc2LnBoeTIpDQorCQltcGh5ID0gZGV2LT5tdDc2 LnBoeTI7DQorDQorCWllZWU4MDIxMV9yYWRhcl9kZXRlY3RlZChtcGh5LT5odyk7DQorCWRldi0+ aHdfcGF0dGVybisrOw0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9tY3VfdHhfcmF0ZV9j YWwoc3RydWN0IG10NzZfcGh5ICptcGh5LCBzdHJ1Y3QgbXQ3OTE1X21jdV9yYV9pbmZvICpyYSwN CisJCSAgICAgICBzdHJ1Y3QgcmF0ZV9pbmZvICpyYXRlLCB1MTYgcikNCit7DQorCXN0cnVjdCBp ZWVlODAyMTFfc3VwcG9ydGVkX2JhbmQgKnNiYW5kOw0KKwl1MTYgcnVfaWR4ID0gbGUxNl90b19j cHUocmEtPnJ1X2lkeCk7DQorCXUxNiBmbGFncyA9IDA7DQorDQorCXJhdGUtPm1jcyA9IEZJRUxE X0dFVChNVF9SQV9SQVRFX01DUywgcik7DQorCXJhdGUtPm5zcyA9IEZJRUxEX0dFVChNVF9SQV9S QVRFX05TUywgcikgKyAxOw0KKw0KKwlzd2l0Y2ggKEZJRUxEX0dFVChNVF9SQV9SQVRFX1RYX01P REUsIHIpKSB7DQorCWNhc2UgTVRfUEhZX1RZUEVfQ0NLOg0KKwljYXNlIE1UX1BIWV9UWVBFX09G RE06DQorCQlpZiAobXBoeS0+Y2hhbmRlZi5jaGFuLT5iYW5kID09IE5MODAyMTFfQkFORF81R0ha KQ0KKwkJCXNiYW5kID0gJm1waHktPnNiYW5kXzVnLnNiYW5kOw0KKwkJZWxzZQ0KKwkJCXNiYW5k ID0gJm1waHktPnNiYW5kXzJnLnNiYW5kOw0KKw0KKwkJcmF0ZS0+bGVnYWN5ID0gc2JhbmQtPmJp dHJhdGVzW3JhdGUtPm1jc10uYml0cmF0ZTsNCisJCWJyZWFrOw0KKwljYXNlIE1UX1BIWV9UWVBF X0hUOg0KKwljYXNlIE1UX1BIWV9UWVBFX0hUX0dGOg0KKwkJcmF0ZS0+bWNzICs9IChyYXRlLT5u c3MgLSAxKSAqIDg7DQorCQlmbGFncyB8PSBSQVRFX0lORk9fRkxBR1NfTUNTOw0KKw0KKwkJaWYg KHJhLT5naSkNCisJCQlmbGFncyB8PSBSQVRFX0lORk9fRkxBR1NfU0hPUlRfR0k7DQorCQlicmVh azsNCisJY2FzZSBNVF9QSFlfVFlQRV9WSFQ6DQorCQlmbGFncyB8PSBSQVRFX0lORk9fRkxBR1Nf VkhUX01DUzsNCisNCisJCWlmIChyYS0+Z2kpDQorCQkJZmxhZ3MgfD0gUkFURV9JTkZPX0ZMQUdT X1NIT1JUX0dJOw0KKwkJYnJlYWs7DQorCWNhc2UgTVRfUEhZX1RZUEVfSEVfU1U6DQorCWNhc2Ug TVRfUEhZX1RZUEVfSEVfRVhUX1NVOg0KKwljYXNlIE1UX1BIWV9UWVBFX0hFX1RCOg0KKwljYXNl IE1UX1BIWV9UWVBFX0hFX01VOg0KKwkJcmF0ZS0+aGVfZ2kgPSByYS0+Z2k7DQorCQlyYXRlLT5o ZV9kY20gPSBGSUVMRF9HRVQoTVRfUkFfUkFURV9EQ01fRU4sIHIpOw0KKw0KKwkJZmxhZ3MgfD0g UkFURV9JTkZPX0ZMQUdTX0hFX01DUzsNCisJCWJyZWFrOw0KKwlkZWZhdWx0Og0KKwkJYnJlYWs7 DQorCX0NCisJcmF0ZS0+ZmxhZ3MgPSBmbGFnczsNCisNCisJaWYgKHJ1X2lkeCkgew0KKwkJc3dp dGNoIChydV9pZHgpIHsNCisJCWNhc2UgMSAuLi4gMjoNCisJCQlyYXRlLT5oZV9ydV9hbGxvYyA9 IE5MODAyMTFfUkFURV9JTkZPX0hFX1JVX0FMTE9DXzk5NjsNCisJCQlicmVhazsNCisJCWNhc2Ug MyAuLi4gNjoNCisJCQlyYXRlLT5oZV9ydV9hbGxvYyA9IE5MODAyMTFfUkFURV9JTkZPX0hFX1JV X0FMTE9DXzQ4NDsNCisJCQlicmVhazsNCisJCWNhc2UgNyAuLi4gMTQ6DQorCQkJcmF0ZS0+aGVf cnVfYWxsb2MgPSBOTDgwMjExX1JBVEVfSU5GT19IRV9SVV9BTExPQ18yNDI7DQorCQkJYnJlYWs7 DQorCQlkZWZhdWx0Og0KKwkJCXJhdGUtPmhlX3J1X2FsbG9jID0gTkw4MDIxMV9SQVRFX0lORk9f SEVfUlVfQUxMT0NfMTA2Ow0KKwkJCWJyZWFrOw0KKwkJfQ0KKwkJcmF0ZS0+YncgPSBSQVRFX0lO Rk9fQldfSEVfUlU7DQorCX0gZWxzZSB7DQorCQl1OCBidyA9IG10NzkxNV9tY3VfY2hhbl9idygm bXBoeS0+Y2hhbmRlZikgLQ0KKwkJCUZJRUxEX0dFVChNVF9SQV9SQVRFX0JXLCByKTsNCisNCisJ CXN3aXRjaCAoYncpIHsNCisJCWNhc2UgSUVFRTgwMjExX1NUQV9SWF9CV18xNjA6DQorCQkJcmF0 ZS0+YncgPSBSQVRFX0lORk9fQldfMTYwOw0KKwkJCWJyZWFrOw0KKwkJY2FzZSBJRUVFODAyMTFf U1RBX1JYX0JXXzgwOg0KKwkJCXJhdGUtPmJ3ID0gUkFURV9JTkZPX0JXXzgwOw0KKwkJCWJyZWFr Ow0KKwkJY2FzZSBJRUVFODAyMTFfU1RBX1JYX0JXXzQwOg0KKwkJCXJhdGUtPmJ3ID0gUkFURV9J TkZPX0JXXzQwOw0KKwkJCWJyZWFrOw0KKwkJZGVmYXVsdDoNCisJCQlyYXRlLT5idyA9IFJBVEVf SU5GT19CV18yMDsNCisJCQlicmVhazsNCisJCX0NCisJfQ0KK30NCisNCitzdGF0aWMgdm9pZA0K K210NzkxNV9tY3VfdHhfcmF0ZV9yZXBvcnQoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgc3RydWN0 IHNrX2J1ZmYgKnNrYikNCit7DQorCXN0cnVjdCBtdDc5MTVfbWN1X3JhX2luZm8gKnJhID0gKHN0 cnVjdCBtdDc5MTVfbWN1X3JhX2luZm8gKilza2ItPmRhdGE7DQorCXUxNiB3Y2lkeCA9IGxlMTZf dG9fY3B1KHJhLT53bGFuX2lkeCk7DQorCXN0cnVjdCBtdDc2X3djaWQgKndjaWQgPSByY3VfZGVy ZWZlcmVuY2UoZGV2LT5tdDc2LndjaWRbd2NpZHhdKTsNCisJc3RydWN0IG10NzkxNV9zdGEgKm1z dGEgPSBjb250YWluZXJfb2Yod2NpZCwgc3RydWN0IG10NzkxNV9zdGEsIHdjaWQpOw0KKwlzdHJ1 Y3QgbXQ3OTE1X3N0YV9zdGF0cyAqc3RhdHMgPSAmbXN0YS0+c3RhdHM7DQorCXN0cnVjdCBtdDc2 X3BoeSAqbXBoeSA9ICZkZXYtPm1waHk7DQorCXN0cnVjdCByYXRlX2luZm8gcmF0ZSA9IHt9LCBw cm9iX3JhdGUgPSB7fTsNCisJdTE2IGF0dGVtcHRzID0gbGUxNl90b19jcHUocmEtPmF0dGVtcHRz KTsNCisJdTE2IGN1cnIgPSBsZTE2X3RvX2NwdShyYS0+Y3Vycl9yYXRlKTsNCisJdTE2IHByb2Jl ID0gbGUxNl90b19jcHUocmEtPnByb2JfdXBfcmF0ZSk7DQorDQorCWlmIChtc3RhLT53Y2lkLmV4 dF9waHkgJiYgZGV2LT5tdDc2LnBoeTIpDQorCQltcGh5ID0gZGV2LT5tdDc2LnBoeTI7DQorDQor CS8qIGN1cnJlbnQgcmF0ZSAqLw0KKwltdDc5MTVfbWN1X3R4X3JhdGVfY2FsKG1waHksIHJhLCAm cmF0ZSwgY3Vycik7DQorCXN0YXRzLT50eF9yYXRlID0gcmF0ZTsNCisNCisJLyogcHJvYmluZyBy YXRlICovDQorCW10NzkxNV9tY3VfdHhfcmF0ZV9jYWwobXBoeSwgcmEsICZwcm9iX3JhdGUsIHBy b2JlKTsNCisJc3RhdHMtPnByb2JfcmF0ZSA9IHByb2JfcmF0ZTsNCisNCisJaWYgKGF0dGVtcHRz KSB7DQorCQl1MTYgc3VjY2VzcyA9IGxlMTZfdG9fY3B1KHJhLT5zdWNjZXNzKTsNCisNCisJCXN0 YXRzLT5wZXIgPSAxMDAwICogKGF0dGVtcHRzIC0gc3VjY2VzcykgLyBhdHRlbXB0czsNCisJfQ0K K30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9tY3VfcnhfZXh0X2V2ZW50KHN0cnVjdCBtdDc5 MTVfZGV2ICpkZXYsIHN0cnVjdCBza19idWZmICpza2IpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X21j dV9yeGQgKnJ4ZCA9IChzdHJ1Y3QgbXQ3OTE1X21jdV9yeGQgKilza2ItPmRhdGE7DQorDQorCXN3 aXRjaCAocnhkLT5leHRfZWlkKSB7DQorCWNhc2UgTUNVX0VYVF9FVkVOVF9SRERfUkVQT1JUOg0K KwkJbXQ3OTE1X21jdV9yeF9yYWRhcl9kZXRlY3RlZChkZXYsIHNrYik7DQorCQlicmVhazsNCisJ Y2FzZSBNQ1VfRVhUX0VWRU5UX0NTQV9OT1RJRlk6DQorCQlpZWVlODAyMTFfaXRlcmF0ZV9hY3Rp dmVfaW50ZXJmYWNlc19hdG9taWMoZGV2LT5tdDc2Lmh3LA0KKwkJCQlJRUVFODAyMTFfSUZBQ0Vf SVRFUl9SRVNVTUVfQUxMLA0KKwkJCQltdDc5MTVfbWN1X2NzYV9maW5pc2gsIGRldik7DQorCQli cmVhazsNCisJY2FzZSBNQ1VfRVhUX0VWRU5UX1JBVEVfUkVQT1JUOg0KKwkJbXQ3OTE1X21jdV90 eF9yYXRlX3JlcG9ydChkZXYsIHNrYik7DQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJCWJyZWFr Ow0KKwl9DQorfQ0KKw0KK3N0YXRpYyB2b2lkDQorbXQ3OTE1X21jdV9yeF91bnNvbGljaXRlZF9l dmVudChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBzdHJ1Y3Qgc2tfYnVmZiAqc2tiKQ0KK3sNCisJ c3RydWN0IG10NzkxNV9tY3VfcnhkICpyeGQgPSAoc3RydWN0IG10NzkxNV9tY3VfcnhkICopc2ti LT5kYXRhOw0KKw0KKwlzd2l0Y2ggKHJ4ZC0+ZWlkKSB7DQorCWNhc2UgTUNVX0VWRU5UX0VYVDoN CisJCW10NzkxNV9tY3VfcnhfZXh0X2V2ZW50KGRldiwgc2tiKTsNCisJCWJyZWFrOw0KKwlkZWZh dWx0Og0KKwkJYnJlYWs7DQorCX0NCisJZGV2X2tmcmVlX3NrYihza2IpOw0KK30NCisNCit2b2lk IG10NzkxNV9tY3VfcnhfZXZlbnQoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgc3RydWN0IHNrX2J1 ZmYgKnNrYikNCit7DQorCXN0cnVjdCBtdDc5MTVfbWN1X3J4ZCAqcnhkID0gKHN0cnVjdCBtdDc5 MTVfbWN1X3J4ZCAqKXNrYi0+ZGF0YTsNCisNCisJaWYgKHJ4ZC0+ZXh0X2VpZCA9PSBNQ1VfRVhU X0VWRU5UX1RIRVJNQUxfUFJPVEVDVCB8fA0KKwkgICAgcnhkLT5leHRfZWlkID09IE1DVV9FWFRf RVZFTlRfQVNTRVJUX0RVTVAgfHwNCisJICAgIHJ4ZC0+ZXh0X2VpZCA9PSBNQ1VfRVhUX0VWRU5U X1BTX1NZTkMgfHwNCisJICAgIHJ4ZC0+ZXh0X2VpZCA9PSBNQ1VfRVhUX0VWRU5UX1JBVEVfUkVQ T1JUIHx8DQorCSAgICAhcnhkLT5zZXEpDQorCQltdDc5MTVfbWN1X3J4X3Vuc29saWNpdGVkX2V2 ZW50KGRldiwgc2tiKTsNCisJZWxzZQ0KKwkJbXQ3Nl9tY3VfcnhfZXZlbnQoJmRldi0+bXQ3Niwg c2tiKTsNCit9DQorDQorc3RhdGljIHN0cnVjdCBza19idWZmICoNCittdDc5MTVfbWN1X2FsbG9j X3N0YV9yZXEoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgc3RydWN0IG10NzkxNV92aWYgKm12aWYs DQorCQkJIHN0cnVjdCBtdDc5MTVfc3RhICptc3RhLCBpbnQgbGVuKQ0KK3sNCisJc3RydWN0IHN0 YV9yZXFfaGRyIGhkciA9IHsNCisJCS5ic3NfaWR4ID0gbXZpZi0+aWR4LA0KKwkJLndsYW5faWR4 X2xvID0gbXN0YSA/IHRvX3djaWRfbG8obXN0YS0+d2NpZC5pZHgpIDogMCwNCisJCS53bGFuX2lk eF9oaSA9IG1zdGEgPyB0b193Y2lkX2hpKG1zdGEtPndjaWQuaWR4KSA6IDAsDQorCQkubXVhcl9p ZHggPSBtc3RhID8gbXZpZi0+b21hY19pZHggOiAwLA0KKwkJLmlzX3Rsdl9hcHBlbmQgPSAxLA0K Kwl9Ow0KKwlzdHJ1Y3Qgc2tfYnVmZiAqc2tiOw0KKw0KKwlza2IgPSBtdDc2X21jdV9tc2dfYWxs b2MoJmRldi0+bXQ3NiwgTlVMTCwgbGVuKTsNCisJaWYgKCFza2IpDQorCQlyZXR1cm4gRVJSX1BU UigtRU5PTUVNKTsNCisNCisJc2tiX3B1dF9kYXRhKHNrYiwgJmhkciwgc2l6ZW9mKGhkcikpOw0K Kw0KKwlyZXR1cm4gc2tiOw0KK30NCisNCitzdGF0aWMgc3RydWN0IHd0YmxfcmVxX2hkciAqDQor bXQ3OTE1X21jdV9hbGxvY193dGJsX3JlcShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBzdHJ1Y3Qg bXQ3OTE1X3N0YSAqbXN0YSwNCisJCQkgIGludCBjbWQsIHZvaWQgKnN0YV93dGJsLCBzdHJ1Y3Qg c2tfYnVmZiAqKnNrYikNCit7DQorCXN0cnVjdCB0bHYgKnN0YV9oZHIgPSBzdGFfd3RibDsNCisJ c3RydWN0IHd0YmxfcmVxX2hkciBoZHIgPSB7DQorCQkud2xhbl9pZHhfbG8gPSB0b193Y2lkX2xv KG1zdGEtPndjaWQuaWR4KSwNCisJCS53bGFuX2lkeF9oaSA9IHRvX3djaWRfaGkobXN0YS0+d2Np ZC5pZHgpLA0KKwkJLm9wZXJhdGlvbiA9IGNtZCwNCisJfTsNCisJc3RydWN0IHNrX2J1ZmYgKm5z a2IgPSAqc2tiOw0KKw0KKwlpZiAoIW5za2IpIHsNCisJCW5za2IgPSBtdDc2X21jdV9tc2dfYWxs b2MoJmRldi0+bXQ3NiwgTlVMTCwNCisJCQkJCSAgTVQ3OTE1X1dUQkxfVVBEQVRFX0JBX1NJWkUp Ow0KKwkJaWYgKCFuc2tiKQ0KKwkJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0pOw0KKw0KKwkJKnNr YiA9IG5za2I7DQorCX0NCisNCisJaWYgKHN0YV9oZHIpDQorCQlzdGFfaGRyLT5sZW4gPSBjcHVf dG9fbGUxNihzaXplb2YoaGRyKSk7DQorDQorCXJldHVybiBza2JfcHV0X2RhdGEobnNrYiwgJmhk ciwgc2l6ZW9mKGhkcikpOw0KK30NCisNCitzdGF0aWMgc3RydWN0IHRsdiAqDQorbXQ3OTE1X21j dV9hZGRfbmVzdGVkX3RsdihzdHJ1Y3Qgc2tfYnVmZiAqc2tiLCBpbnQgdGFnLCBpbnQgbGVuLA0K KwkJCSAgdm9pZCAqc3RhX250bHYsIHZvaWQgKnN0YV93dGJsKQ0KK3sNCisJc3RydWN0IHN0YV9u dGx2X2hkciAqbnRsdl9oZHIgPSBzdGFfbnRsdjsNCisJc3RydWN0IHRsdiAqc3RhX2hkciA9IHN0 YV93dGJsOw0KKwlzdHJ1Y3QgdGx2ICpwdGx2LCB0bHYgPSB7DQorCQkudGFnID0gY3B1X3RvX2xl MTYodGFnKSwNCisJCS5sZW4gPSBjcHVfdG9fbGUxNihsZW4pLA0KKwl9Ow0KKwl1MTYgbnRsdjsN CisNCisJcHRsdiA9IHNrYl9wdXQoc2tiLCBsZW4pOw0KKwltZW1jcHkocHRsdiwgJnRsdiwgc2l6 ZW9mKHRsdikpOw0KKw0KKwludGx2ID0gbGUxNl90b19jcHUobnRsdl9oZHItPnRsdl9udW0pOw0K KwludGx2X2hkci0+dGx2X251bSA9IGNwdV90b19sZTE2KG50bHYgKyAxKTsNCisNCisJaWYgKHN0 YV9oZHIpIHsNCisJCXUxNiBzaXplID0gbGUxNl90b19jcHUoc3RhX2hkci0+bGVuKTsNCisNCisJ CXN0YV9oZHItPmxlbiA9IGNwdV90b19sZTE2KHNpemUgKyBsZW4pOw0KKwl9DQorDQorCXJldHVy biBwdGx2Ow0KK30NCisNCitzdGF0aWMgc3RydWN0IHRsdiAqDQorbXQ3OTE1X21jdV9hZGRfdGx2 KHN0cnVjdCBza19idWZmICpza2IsIGludCB0YWcsIGludCBsZW4pDQorew0KKwlyZXR1cm4gbXQ3 OTE1X21jdV9hZGRfbmVzdGVkX3Rsdihza2IsIHRhZywgbGVuLCBza2ItPmRhdGEsIE5VTEwpOw0K K30NCisNCitzdGF0aWMgc3RydWN0IHRsdiAqDQorbXQ3OTE1X21jdV9hZGRfbmVzdGVkX3N1YnRs dihzdHJ1Y3Qgc2tfYnVmZiAqc2tiLCBpbnQgc3ViX3RhZywgaW50IHN1Yl9sZW4sDQorCQkJICAg ICBfX2xlMTYgKnN1Yl9udGx2LCBfX2xlMTYgKmxlbikNCit7DQorCXN0cnVjdCB0bHYgKnB0bHYs IHRsdiA9IHsNCisJCS50YWcgPSBjcHVfdG9fbGUxNihzdWJfdGFnKSwNCisJCS5sZW4gPSBjcHVf dG9fbGUxNihzdWJfbGVuKSwNCisJfTsNCisNCisJcHRsdiA9IHNrYl9wdXQoc2tiLCBzdWJfbGVu KTsNCisJbWVtY3B5KHB0bHYsICZ0bHYsIHNpemVvZih0bHYpKTsNCisNCisJKnN1Yl9udGx2ID0g Y3B1X3RvX2xlMTYobGUxNl90b19jcHUoKnN1Yl9udGx2KSArIDEpOw0KKwkqbGVuID0gY3B1X3Rv X2xlMTYobGUxNl90b19jcHUoKmxlbikgKyBzdWJfbGVuKTsNCisNCisJcmV0dXJuIHB0bHY7DQor fQ0KKw0KKy8qKiBic3MgaW5mbyAqKi8NCitzdGF0aWMgaW50DQorbXQ3OTE1X21jdV9ic3NfYmFz aWNfdGx2KHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQor CQkJIHN0cnVjdCBtdDc5MTVfcGh5ICpwaHksIGJvb2wgZW5hYmxlKQ0KK3sNCisJc3RydWN0IG10 NzkxNV92aWYgKm12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlz dHJ1Y3QgY2ZnODAyMTFfY2hhbl9kZWYgKmNoYW5kZWYgPSAmcGh5LT5tdDc2LT5jaGFuZGVmOw0K KwllbnVtIG5sODAyMTFfYmFuZCBiYW5kID0gY2hhbmRlZi0+Y2hhbi0+YmFuZDsNCisJc3RydWN0 IGJzc19pbmZvX2Jhc2ljICpic3M7DQorCXUxNiB3bGFuX2lkeCA9IG12aWYtPnN0YS53Y2lkLmlk eDsNCisJdTMyIHR5cGUgPSBORVRXT1JLX0lORlJBOw0KKwlzdHJ1Y3QgdGx2ICp0bHY7DQorDQor CXRsdiA9IG10NzkxNV9tY3VfYWRkX3Rsdihza2IsIEJTU19JTkZPX0JBU0lDLCBzaXplb2YoKmJz cykpOw0KKw0KKwlzd2l0Y2ggKHZpZi0+dHlwZSkgew0KKwljYXNlIE5MODAyMTFfSUZUWVBFX01F U0hfUE9JTlQ6DQorCWNhc2UgTkw4MDIxMV9JRlRZUEVfQVA6DQorCQlicmVhazsNCisJY2FzZSBO TDgwMjExX0lGVFlQRV9TVEFUSU9OOg0KKwkJLyogVE9ETzogZW5hYmxlIEJTU19JTkZPX1VBUFNE ICYgQlNTX0lORk9fUE0gKi8NCisJCWlmIChlbmFibGUpIHsNCisJCQlzdHJ1Y3QgaWVlZTgwMjEx X3N0YSAqc3RhOw0KKwkJCXN0cnVjdCBtdDc5MTVfc3RhICptc3RhOw0KKw0KKwkJCXJjdV9yZWFk X2xvY2soKTsNCisJCQlzdGEgPSBpZWVlODAyMTFfZmluZF9zdGEodmlmLCB2aWYtPmJzc19jb25m LmJzc2lkKTsNCisJCQlpZiAoIXN0YSkgew0KKwkJCQlyY3VfcmVhZF91bmxvY2soKTsNCisJCQkJ cmV0dXJuIC1FSU5WQUw7DQorCQkJfQ0KKw0KKwkJCW1zdGEgPSAoc3RydWN0IG10NzkxNV9zdGEg KilzdGEtPmRydl9wcml2Ow0KKwkJCXdsYW5faWR4ID0gbXN0YS0+d2NpZC5pZHg7DQorCQkJcmN1 X3JlYWRfdW5sb2NrKCk7DQorCQl9DQorCQlicmVhazsNCisJY2FzZSBOTDgwMjExX0lGVFlQRV9B REhPQzoNCisJCXR5cGUgPSBORVRXT1JLX0lCU1M7DQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJ CVdBUk5fT04oMSk7DQorCQlicmVhazsNCisJfQ0KKw0KKwlic3MgPSAoc3RydWN0IGJzc19pbmZv X2Jhc2ljICopdGx2Ow0KKwltZW1jcHkoYnNzLT5ic3NpZCwgdmlmLT5ic3NfY29uZi5ic3NpZCwg RVRIX0FMRU4pOw0KKwlic3MtPmJjbl9pbnRlcnZhbCA9IGNwdV90b19sZTE2KHZpZi0+YnNzX2Nv bmYuYmVhY29uX2ludCk7DQorCWJzcy0+bmV0d29ya190eXBlID0gY3B1X3RvX2xlMzIodHlwZSk7 DQorCWJzcy0+ZHRpbV9wZXJpb2QgPSB2aWYtPmJzc19jb25mLmR0aW1fcGVyaW9kOw0KKwlic3Mt PmJtY193Y2lkX2xvID0gdG9fd2NpZF9sbyh3bGFuX2lkeCk7DQorCWJzcy0+Ym1jX3djaWRfaGkg PSB0b193Y2lkX2hpKHdsYW5faWR4KTsNCisJYnNzLT5waHlfbW9kZSA9IG10NzkxNV9nZXRfcGh5 X21vZGUocGh5LT5kZXYsIHZpZiwgYmFuZCwgTlVMTCk7DQorCWJzcy0+d21tX2lkeCA9IG12aWYt PndtbV9pZHg7DQorCWJzcy0+YWN0aXZlID0gZW5hYmxlOw0KKw0KKwlyZXR1cm4gMDsNCit9DQor DQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X2Jzc19vbWFjX3RsdihzdHJ1Y3Qgc2tfYnVmZiAq c2tiLCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmKQ0KK3sNCisJc3RydWN0IG10NzkxNV92aWYg Km12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlzdHJ1Y3QgYnNz X2luZm9fb21hYyAqb21hYzsNCisJc3RydWN0IHRsdiAqdGx2Ow0KKwl1MzIgdHlwZSA9IDA7DQor CXU4IGlkeDsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHNrYiwgQlNTX0lORk9fT01B Qywgc2l6ZW9mKCpvbWFjKSk7DQorDQorCXN3aXRjaCAodmlmLT50eXBlKSB7DQorCWNhc2UgTkw4 MDIxMV9JRlRZUEVfTUVTSF9QT0lOVDoNCisJY2FzZSBOTDgwMjExX0lGVFlQRV9BUDoNCisJCXR5 cGUgPSBDT05ORUNUSU9OX0lORlJBX0FQOw0KKwkJYnJlYWs7DQorCWNhc2UgTkw4MDIxMV9JRlRZ UEVfU1RBVElPTjoNCisJCXR5cGUgPSBDT05ORUNUSU9OX0lORlJBX1NUQTsNCisJCWJyZWFrOw0K KwljYXNlIE5MODAyMTFfSUZUWVBFX0FESE9DOg0KKwkJdHlwZSA9IENPTk5FQ1RJT05fSUJTU19B REhPQzsNCisJCWJyZWFrOw0KKwlkZWZhdWx0Og0KKwkJV0FSTl9PTigxKTsNCisJCWJyZWFrOw0K Kwl9DQorDQorCW9tYWMgPSAoc3RydWN0IGJzc19pbmZvX29tYWMgKil0bHY7DQorCWlkeCA9IG12 aWYtPm9tYWNfaWR4ID4gRVhUX0JTU0lEX1NUQVJUID8gSFdfQlNTSURfMCA6IG12aWYtPm9tYWNf aWR4Ow0KKwlvbWFjLT5jb25uX3R5cGUgPSBjcHVfdG9fbGUzMih0eXBlKTsNCisJb21hYy0+b21h Y19pZHggPSBtdmlmLT5vbWFjX2lkeDsNCisJb21hYy0+YmFuZF9pZHggPSBtdmlmLT5iYW5kX2lk eDsNCisJb21hYy0+aHdfYnNzX2lkeCA9IGlkeDsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5 MTVfbWN1X2Jzc19yZmNoX3RsdihzdHJ1Y3Qgc2tfYnVmZiAqc2tiLCBzdHJ1Y3QgaWVlZTgwMjEx X3ZpZiAqdmlmLA0KKwkJCXN0cnVjdCBtdDc5MTVfcGh5ICpwaHkpDQorew0KKwlzdHJ1Y3QgY2Zn ODAyMTFfY2hhbl9kZWYgKmNoYW5kZWYgPSAmcGh5LT5tdDc2LT5jaGFuZGVmOw0KKwlzdHJ1Y3Qg YnNzX2luZm9fcmZfY2ggKmNoOw0KKwlzdHJ1Y3QgdGx2ICp0bHY7DQorCWludCBmcmVxMSA9IGNo YW5kZWYtPmNlbnRlcl9mcmVxMTsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHNrYiwg QlNTX0lORk9fUkZfQ0gsIHNpemVvZigqY2gpKTsNCisNCisJY2ggPSAoc3RydWN0IGJzc19pbmZv X3JmX2NoICopdGx2Ow0KKwljaC0+cHJpX2NoID0gY2hhbmRlZi0+Y2hhbi0+aHdfdmFsdWU7DQor CWNoLT5jZW50ZXJfY2gwID0gaWVlZTgwMjExX2ZyZXF1ZW5jeV90b19jaGFubmVsKGZyZXExKTsN CisJY2gtPmJ3ID0gbXQ3OTE1X21jdV9jaGFuX2J3KGNoYW5kZWYpOw0KKw0KKwlpZiAoY2hhbmRl Zi0+d2lkdGggPT0gTkw4MDIxMV9DSEFOX1dJRFRIXzgwUDgwKSB7DQorCQlpbnQgZnJlcTIgPSBj aGFuZGVmLT5jZW50ZXJfZnJlcTI7DQorDQorCQljaC0+Y2VudGVyX2NoMSA9IGllZWU4MDIxMV9m cmVxdWVuY3lfdG9fY2hhbm5lbChmcmVxMik7DQorCX0NCisNCisJY2gtPmhlX2FsbF9kaXNhYmxl ID0gdHJ1ZTsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X2Jzc19yYV90bHYoc3Ry dWN0IHNrX2J1ZmYgKnNrYiwgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiwNCisJCSAgICAgIHN0 cnVjdCBtdDc5MTVfcGh5ICpwaHkpDQorew0KKwlzdHJ1Y3QgYnNzX2luZm9fcmEgKnJhOw0KKwlz dHJ1Y3QgdGx2ICp0bHY7DQorCWludCBtYXhfbnNzID0gaHdlaWdodDgocGh5LT5jaGFpbm1hc2sp Ow0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBCU1NfSU5GT19SQSwgc2l6ZW9m KCpyYSkpOw0KKw0KKwlyYSA9IChzdHJ1Y3QgYnNzX2luZm9fcmEgKil0bHY7DQorCXJhLT5vcF9t b2RlID0gdmlmLT50eXBlID09IE5MODAyMTFfSUZUWVBFX0FQOw0KKwlyYS0+YWRob2NfZW4gPSB2 aWYtPnR5cGUgPT0gTkw4MDIxMV9JRlRZUEVfQURIT0M7DQorCXJhLT5zaG9ydF9wcmVhbWJsZSA9 IHRydWU7DQorCXJhLT50eF9zdHJlYW1zID0gbWF4X25zczsNCisJcmEtPnJ4X3N0cmVhbXMgPSBt YXhfbnNzOw0KKwlyYS0+YWxnbyA9IDQ7DQorCXJhLT50cmFpbl91cF9ydWxlID0gMjsNCisJcmEt PnRyYWluX3VwX2hpZ2hfdGhyZXMgPSAxMTA7DQorCXJhLT50cmFpbl91cF9ydWxlX3Jzc2kgPSAt NzA7DQorCXJhLT5sb3dfdHJhZmZpY190aHJlcyA9IDI7DQorCXJhLT5waHlfY2FwID0gY3B1X3Rv X2xlMzIoMHhmZGYpOw0KKwlyYS0+aW50ZXJ2YWwgPSBjcHVfdG9fbGUzMig1MDApOw0KKwlyYS0+ ZmFzdF9pbnRlcnZhbCA9IGNwdV90b19sZTMyKDEwMCk7DQorfQ0KKw0KK3N0YXRpYyB2b2lkDQor bXQ3OTE1X21jdV9ic3NfZXh0X3RsdihzdHJ1Y3Qgc2tfYnVmZiAqc2tiLCBzdHJ1Y3QgbXQ3OTE1 X3ZpZiAqbXZpZikNCit7DQorLyogU0lGUyAyMHVzICsgNTEyIGJ5dGUgYmVhY29uIHRyYW5taXR0 ZWQgYnkgMU1icHMgKDM5MDZ1cykgKi8NCisjZGVmaW5lIEJDTl9UWF9FU1RJTUFURV9USU1FCSg0 MDk2ICsgMjApDQorCXN0cnVjdCBic3NfaW5mb19leHRfYnNzICpleHQ7DQorCWludCBleHRfYnNz X2lkeCwgdHNmX29mZnNldDsNCisJc3RydWN0IHRsdiAqdGx2Ow0KKw0KKwlleHRfYnNzX2lkeCA9 IG12aWYtPm9tYWNfaWR4IC0gRVhUX0JTU0lEX1NUQVJUOw0KKwlpZiAoZXh0X2Jzc19pZHggPCAw KQ0KKwkJcmV0dXJuOw0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBCU1NfSU5G T19FWFRfQlNTLCBzaXplb2YoKmV4dCkpOw0KKw0KKwlleHQgPSAoc3RydWN0IGJzc19pbmZvX2V4 dF9ic3MgKil0bHY7DQorCXRzZl9vZmZzZXQgPSBleHRfYnNzX2lkeCAqIEJDTl9UWF9FU1RJTUFU RV9USU1FOw0KKwlleHQtPm1ic3NfdHNmX29mZnNldCA9IGNwdV90b19sZTMyKHRzZl9vZmZzZXQp Ow0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9tY3VfYnNzX2JtY190bHYoc3RydWN0IHNr X2J1ZmYgKnNrYiwgc3RydWN0IG10NzkxNV9waHkgKnBoeSkNCit7DQorCXN0cnVjdCBic3NfaW5m b19ibWNfcmF0ZSAqYm1jOw0KKwlzdHJ1Y3QgY2ZnODAyMTFfY2hhbl9kZWYgKmNoYW5kZWYgPSAm cGh5LT5tdDc2LT5jaGFuZGVmOw0KKwllbnVtIG5sODAyMTFfYmFuZCBiYW5kID0gY2hhbmRlZi0+ Y2hhbi0+YmFuZDsNCisJc3RydWN0IHRsdiAqdGx2Ow0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2Fk ZF90bHYoc2tiLCBCU1NfSU5GT19CTUNfUkFURSwgc2l6ZW9mKCpibWMpKTsNCisNCisJYm1jID0g KHN0cnVjdCBic3NfaW5mb19ibWNfcmF0ZSAqKXRsdjsNCisJaWYgKGJhbmQgPT0gTkw4MDIxMV9C QU5EXzJHSFopIHsNCisJCWJtYy0+c2hvcnRfcHJlYW1ibGUgPSB0cnVlOw0KKwl9IGVsc2Ugew0K KwkJYm1jLT5iY190cmFucyA9IGNwdV90b19sZTE2KDB4MjAwMCk7DQorCQlibWMtPm1jX3RyYW5z ID0gY3B1X3RvX2xlMTYoMHgyMDgwKTsNCisJfQ0KK30NCisNCitzdGF0aWMgdm9pZA0KK210Nzkx NV9tY3VfYnNzX3N5bmNfdGx2KHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBpZWVlODAyMTFf dmlmICp2aWYpDQorew0KKwlzdHJ1Y3QgYnNzX2luZm9fc3luY19tb2RlICpzeW5jOw0KKwlzdHJ1 Y3QgdGx2ICp0bHY7DQorDQorCXRsdiA9IG10NzkxNV9tY3VfYWRkX3Rsdihza2IsIEJTU19JTkZP X1NZTkNfTU9ERSwgc2l6ZW9mKCpzeW5jKSk7DQorDQorCXN5bmMgPSAoc3RydWN0IGJzc19pbmZv X3N5bmNfbW9kZSAqKXRsdjsNCisJc3luYy0+YmNuX2ludGVydmFsID0gY3B1X3RvX2xlMTYodmlm LT5ic3NfY29uZi5iZWFjb25faW50KTsNCisJc3luYy0+ZHRpbV9wZXJpb2QgPSB2aWYtPmJzc19j b25mLmR0aW1fcGVyaW9kOw0KKwlzeW5jLT5lbmFibGUgPSB0cnVlOw0KK30NCisNCitpbnQgbXQ3 OTE1X21jdV9hZGRfYnNzX2luZm8oc3RydWN0IG10NzkxNV9waHkgKnBoeSwNCisJCQkgICAgc3Ry dWN0IGllZWU4MDIxMV92aWYgKnZpZiwgaW50IGVuYWJsZSkNCit7DQorCXN0cnVjdCBtdDc5MTVf dmlmICptdmlmID0gKHN0cnVjdCBtdDc5MTVfdmlmICopdmlmLT5kcnZfcHJpdjsNCisJc3RydWN0 IHNrX2J1ZmYgKnNrYjsNCisNCisJc2tiID0gbXQ3OTE1X21jdV9hbGxvY19zdGFfcmVxKHBoeS0+ ZGV2LCBtdmlmLCBOVUxMLA0KKwkJCQkgICAgICAgTVQ3OTE1X1NUQV9VUERBVEVfTUFYX1NJWkUp Ow0KKwlpZiAoSVNfRVJSKHNrYikpDQorCQlyZXR1cm4gUFRSX0VSUihza2IpOw0KKw0KKwkvKiBi c3Nfb21hYyBtdXN0IGJlIGZpcnN0ICovDQorCWlmIChlbmFibGUpDQorCQltdDc5MTVfbWN1X2Jz c19vbWFjX3Rsdihza2IsIHZpZik7DQorDQorCW10NzkxNV9tY3VfYnNzX2Jhc2ljX3Rsdihza2Is IHZpZiwgcGh5LCBlbmFibGUpOw0KKw0KKwlpZiAoZW5hYmxlKSB7DQorCQltdDc5MTVfbWN1X2Jz c19yZmNoX3Rsdihza2IsIHZpZiwgcGh5KTsNCisJCW10NzkxNV9tY3VfYnNzX2JtY190bHYoc2ti LCBwaHkpOw0KKwkJbXQ3OTE1X21jdV9ic3NfcmFfdGx2KHNrYiwgdmlmLCBwaHkpOw0KKw0KKwkJ aWYgKG12aWYtPm9tYWNfaWR4ID4gSFdfQlNTSURfTUFYKQ0KKwkJCW10NzkxNV9tY3VfYnNzX2V4 dF90bHYoc2tiLCBtdmlmKTsNCisJCWVsc2UNCisJCQltdDc5MTVfbWN1X2Jzc19zeW5jX3Rsdihz a2IsIHZpZik7DQorCX0NCisNCisJcmV0dXJuIF9fbXQ3Nl9tY3Vfc2tiX3NlbmRfbXNnKCZwaHkt PmRldi0+bXQ3Niwgc2tiLA0KKwkJCQkgICAgICAgTUNVX0VYVF9DTURfQlNTX0lORk9fVVBEQVRF LCB0cnVlKTsNCit9DQorDQorLyoqIHN0YXJlYyAmIHd0YmwgKiovDQorc3RhdGljIGludA0KK210 NzkxNV9tY3Vfc3RhX2tleV90bHYoc3RydWN0IHNrX2J1ZmYgKnNrYiwgc3RydWN0IGllZWU4MDIx MV9rZXlfY29uZiAqa2V5LA0KKwkJICAgICAgIGVudW0gc2V0X2tleV9jbWQgY21kKQ0KK3sNCisJ c3RydWN0IHN0YV9yZWNfc2VjICpzZWM7DQorCXN0cnVjdCB0bHYgKnRsdjsNCisJdTMyIGxlbiA9 IHNpemVvZigqc2VjKTsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHNrYiwgU1RBX1JF Q19LRVlfVjIsIHNpemVvZigqc2VjKSk7DQorDQorCXNlYyA9IChzdHJ1Y3Qgc3RhX3JlY19zZWMg Kil0bHY7DQorCXNlYy0+YWRkID0gY21kOw0KKw0KKwlpZiAoY21kID09IFNFVF9LRVkpIHsNCisJ CXN0cnVjdCBzZWNfa2V5ICpzZWNfa2V5Ow0KKwkJdTggY2lwaGVyOw0KKw0KKwkJY2lwaGVyID0g bXQ3OTE1X21jdV9nZXRfY2lwaGVyKGtleS0+Y2lwaGVyKTsNCisJCWlmIChjaXBoZXIgPT0gTVRf Q0lQSEVSX05PTkUpDQorCQkJcmV0dXJuIC1FT1BOT1RTVVBQOw0KKw0KKwkJc2VjX2tleSA9ICZz ZWMtPmtleVswXTsNCisJCXNlY19rZXktPmNpcGhlcl9sZW4gPSBzaXplb2YoKnNlY19rZXkpOw0K KwkJc2VjX2tleS0+a2V5X2lkID0ga2V5LT5rZXlpZHg7DQorDQorCQlpZiAoY2lwaGVyID09IE1U X0NJUEhFUl9CSVBfQ01BQ18xMjgpIHsNCisJCQlzZWNfa2V5LT5jaXBoZXJfaWQgPSBNVF9DSVBI RVJfQUVTX0NDTVA7DQorCQkJc2VjX2tleS0+a2V5X2xlbiA9IDE2Ow0KKwkJCW1lbWNweShzZWNf a2V5LT5rZXksIGtleS0+a2V5LCAxNik7DQorDQorCQkJc2VjX2tleSA9ICZzZWMtPmtleVsxXTsN CisJCQlzZWNfa2V5LT5jaXBoZXJfaWQgPSBNVF9DSVBIRVJfQklQX0NNQUNfMTI4Ow0KKwkJCXNl Y19rZXktPmNpcGhlcl9sZW4gPSBzaXplb2YoKnNlY19rZXkpOw0KKwkJCXNlY19rZXktPmtleV9s ZW4gPSAxNjsNCisJCQltZW1jcHkoc2VjX2tleS0+a2V5LCBrZXktPmtleSArIDE2LCAxNik7DQor DQorCQkJc2VjLT5uX2NpcGhlciA9IDI7DQorCQl9IGVsc2Ugew0KKwkJCXNlY19rZXktPmNpcGhl cl9pZCA9IGNpcGhlcjsNCisJCQlzZWNfa2V5LT5rZXlfbGVuID0ga2V5LT5rZXlsZW47DQorCQkJ bWVtY3B5KHNlY19rZXktPmtleSwga2V5LT5rZXksIGtleS0+a2V5bGVuKTsNCisNCisJCQlpZiAo Y2lwaGVyID09IE1UX0NJUEhFUl9US0lQKSB7DQorCQkJCS8qIFJ4L1R4IE1JQyBrZXlzIGFyZSBz d2FwcGVkICovDQorCQkJCW1lbWNweShzZWNfa2V5LT5rZXkgKyAxNiwga2V5LT5rZXkgKyAyNCwg OCk7DQorCQkJCW1lbWNweShzZWNfa2V5LT5rZXkgKyAyNCwga2V5LT5rZXkgKyAxNiwgOCk7DQor CQkJfQ0KKw0KKwkJCWxlbiAtPSBzaXplb2YoKnNlY19rZXkpOw0KKwkJCXNlYy0+bl9jaXBoZXIg PSAxOw0KKwkJfQ0KKwl9IGVsc2Ugew0KKwkJbGVuIC09IHNpemVvZihzZWMtPmtleSk7DQorCQlz ZWMtPm5fY2lwaGVyID0gMDsNCisJfQ0KKwlzZWMtPmxlbiA9IGNwdV90b19sZTE2KGxlbik7DQor DQorCXJldHVybiAwOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9hZGRfa2V5KHN0cnVjdCBtdDc5 MTVfZGV2ICpkZXYsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkgICAgICAgc3RydWN0 IG10NzkxNV9zdGEgKm1zdGEsIHN0cnVjdCBpZWVlODAyMTFfa2V5X2NvbmYgKmtleSwNCisJCSAg ICAgICBlbnVtIHNldF9rZXlfY21kIGNtZCkNCit7DQorCXN0cnVjdCBtdDc5MTVfdmlmICptdmlm ID0gKHN0cnVjdCBtdDc5MTVfdmlmICopdmlmLT5kcnZfcHJpdjsNCisJc3RydWN0IHNrX2J1ZmYg KnNrYjsNCisJaW50IHJldDsNCisNCisJc2tiID0gbXQ3OTE1X21jdV9hbGxvY19zdGFfcmVxKGRl diwgbXZpZiwgbXN0YSwNCisJCQkJICAgICAgIE1UNzkxNV9TVEFfVVBEQVRFX01BWF9TSVpFKTsN CisJaWYgKElTX0VSUihza2IpKQ0KKwkJcmV0dXJuIFBUUl9FUlIoc2tiKTsNCisNCisJcmV0ID0g bXQ3OTE1X21jdV9zdGFfa2V5X3Rsdihza2IsIGtleSwgY21kKTsNCisJaWYgKHJldCkNCisJCXJl dHVybiByZXQ7DQorDQorCXJldHVybiBfX210NzZfbWN1X3NrYl9zZW5kX21zZygmZGV2LT5tdDc2 LCBza2IsDQorCQkJCSAgICAgICBNQ1VfRVhUX0NNRF9TVEFfUkVDX1VQREFURSwgdHJ1ZSk7DQor fQ0KKw0KK3N0YXRpYyB2b2lkDQorbXQ3OTE1X21jdV9zdGFfYmFfdGx2KHN0cnVjdCBza19idWZm ICpza2IsDQorCQkgICAgICBzdHJ1Y3QgaWVlZTgwMjExX2FtcGR1X3BhcmFtcyAqcGFyYW1zLA0K KwkJICAgICAgYm9vbCBlbmFibGUsIGJvb2wgdHgpDQorew0KKwlzdHJ1Y3Qgc3RhX3JlY19iYSAq YmE7DQorCXN0cnVjdCB0bHYgKnRsdjsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHNr YiwgU1RBX1JFQ19CQSwgc2l6ZW9mKCpiYSkpOw0KKw0KKwliYSA9IChzdHJ1Y3Qgc3RhX3JlY19i YSAqKXRsdjsNCisJYmEtPmJhX3R5cGUgPSB0eCA/IE1UX0JBX1RZUEVfT1JJR0lOQVRPUiA6IE1U X0JBX1RZUEVfUkVDSVBJRU5ULA0KKwliYS0+d2luc2l6ZSA9IGNwdV90b19sZTE2KHBhcmFtcy0+ YnVmX3NpemUpOw0KKwliYS0+c3NuID0gY3B1X3RvX2xlMTYocGFyYW1zLT5zc24pOw0KKwliYS0+ YmFfZW4gPSBlbmFibGUgPDwgcGFyYW1zLT50aWQ7DQorCWJhLT5hbXNkdSA9IHBhcmFtcy0+YW1z ZHU7DQorCWJhLT50aWQgPSBwYXJhbXMtPnRpZDsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5 MTVfbWN1X3d0YmxfYmFfdGx2KHN0cnVjdCBza19idWZmICpza2IsDQorCQkgICAgICAgc3RydWN0 IGllZWU4MDIxMV9hbXBkdV9wYXJhbXMgKnBhcmFtcywNCisJCSAgICAgICBib29sIGVuYWJsZSwg Ym9vbCB0eCwgdm9pZCAqc3RhX3d0YmwsDQorCQkgICAgICAgdm9pZCAqd3RibF90bHYpDQorew0K KwlzdHJ1Y3Qgd3RibF9iYSAqYmE7DQorCXN0cnVjdCB0bHYgKnRsdjsNCisNCisJdGx2ID0gbXQ3 OTE1X21jdV9hZGRfbmVzdGVkX3Rsdihza2IsIFdUQkxfQkEsIHNpemVvZigqYmEpLA0KKwkJCQkJ d3RibF90bHYsIHN0YV93dGJsKTsNCisNCisJYmEgPSAoc3RydWN0IHd0YmxfYmEgKil0bHY7DQor CWJhLT50aWQgPSBwYXJhbXMtPnRpZDsNCisNCisJaWYgKHR4KSB7DQorCQliYS0+YmFfdHlwZSA9 IE1UX0JBX1RZUEVfT1JJR0lOQVRPUjsNCisJCWJhLT5zbiA9IGVuYWJsZSA/IGNwdV90b19sZTE2 KHBhcmFtcy0+c3NuKSA6IDA7DQorCQliYS0+YmFfZW4gPSBlbmFibGU7DQorCX0gZWxzZSB7DQor CQltZW1jcHkoYmEtPnBlZXJfYWRkciwgcGFyYW1zLT5zdGEtPmFkZHIsIEVUSF9BTEVOKTsNCisJ CWJhLT5iYV90eXBlID0gTVRfQkFfVFlQRV9SRUNJUElFTlQ7DQorCQliYS0+cnN0X2JhX3RpZCA9 IHBhcmFtcy0+dGlkOw0KKwkJYmEtPnJzdF9iYV9zZWwgPSBSU1RfQkFfTUFDX1RJRF9NQVRDSDsN CisJCWJhLT5yc3RfYmFfc2IgPSAxOw0KKwl9DQorDQorCWlmIChlbmFibGUgJiYgdHgpDQorCQli YS0+YmFfd2luc2l6ZSA9IGNwdV90b19sZTE2KHBhcmFtcy0+YnVmX3NpemUpOw0KK30NCisNCitz dGF0aWMgaW50DQorbXQ3OTE1X21jdV9zdGFfYmEoc3RydWN0IG10NzkxNV9kZXYgKmRldiwNCisJ CSAgc3RydWN0IGllZWU4MDIxMV9hbXBkdV9wYXJhbXMgKnBhcmFtcywNCisJCSAgYm9vbCBlbmFi bGUsIGJvb2wgdHgpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAqbXN0YSA9IChzdHJ1Y3QgbXQ3 OTE1X3N0YSAqKXBhcmFtcy0+c3RhLT5kcnZfcHJpdjsNCisJc3RydWN0IG10NzkxNV92aWYgKm12 aWYgPSBtc3RhLT52aWY7DQorCXN0cnVjdCB3dGJsX3JlcV9oZHIgKnd0YmxfaGRyOw0KKwlzdHJ1 Y3QgdGx2ICpzdGFfd3RibDsNCisJc3RydWN0IHNrX2J1ZmYgKnNrYjsNCisNCisJc2tiID0gbXQ3 OTE1X21jdV9hbGxvY19zdGFfcmVxKGRldiwgbXZpZiwgbXN0YSwNCisJCQkJICAgICAgIE1UNzkx NV9TVEFfVVBEQVRFX01BWF9TSVpFKTsNCisJaWYgKElTX0VSUihza2IpKQ0KKwkJcmV0dXJuIFBU Ul9FUlIoc2tiKTsNCisNCisJbXQ3OTE1X21jdV9zdGFfYmFfdGx2KHNrYiwgcGFyYW1zLCBlbmFi bGUsIHR4KTsNCisJc3RhX3d0YmwgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBTVEFfUkVDX1dU QkwsIHNpemVvZihzdHJ1Y3QgdGx2KSk7DQorDQorCXd0YmxfaGRyID0gbXQ3OTE1X21jdV9hbGxv Y193dGJsX3JlcShkZXYsIG1zdGEsIFdUQkxfU0VULCBzdGFfd3RibCwNCisJCQkJCSAgICAgJnNr Yik7DQorCW10NzkxNV9tY3Vfd3RibF9iYV90bHYoc2tiLCBwYXJhbXMsIGVuYWJsZSwgdHgsIHN0 YV93dGJsLCB3dGJsX2hkcik7DQorDQorCXJldHVybiBfX210NzZfbWN1X3NrYl9zZW5kX21zZygm ZGV2LT5tdDc2LCBza2IsDQorCQkJCSAgICAgICBNQ1VfRVhUX0NNRF9TVEFfUkVDX1VQREFURSwg dHJ1ZSk7DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1X2FkZF90eF9iYShzdHJ1Y3QgbXQ3OTE1X2Rl diAqZGV2LA0KKwkJCSBzdHJ1Y3QgaWVlZTgwMjExX2FtcGR1X3BhcmFtcyAqcGFyYW1zLA0KKwkJ CSBib29sIGVuYWJsZSkNCit7DQorCXJldHVybiBtdDc5MTVfbWN1X3N0YV9iYShkZXYsIHBhcmFt cywgZW5hYmxlLCB0cnVlKTsNCit9DQorDQoraW50IG10NzkxNV9tY3VfYWRkX3J4X2JhKHN0cnVj dCBtdDc5MTVfZGV2ICpkZXYsDQorCQkJIHN0cnVjdCBpZWVlODAyMTFfYW1wZHVfcGFyYW1zICpw YXJhbXMsDQorCQkJIGJvb2wgZW5hYmxlKQ0KK3sNCisJcmV0dXJuIG10NzkxNV9tY3Vfc3RhX2Jh KGRldiwgcGFyYW1zLCBlbmFibGUsIGZhbHNlKTsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5 MTVfbWN1X3d0YmxfZ2VuZXJpY190bHYoc3RydWN0IHNrX2J1ZmYgKnNrYiwgc3RydWN0IGllZWU4 MDIxMV92aWYgKnZpZiwNCisJCQkgICAgc3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YSwgdm9pZCAq c3RhX3d0YmwsDQorCQkJICAgIHZvaWQgKnd0YmxfdGx2KQ0KK3sNCisJc3RydWN0IG10NzkxNV92 aWYgKm12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlzdHJ1Y3Qg d3RibF9nZW5lcmljICpnZW5lcmljOw0KKwlzdHJ1Y3Qgd3RibF9yeCAqcng7DQorCXN0cnVjdCB0 bHYgKnRsdjsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfbmVzdGVkX3Rsdihza2IsIFdUQkxf R0VORVJJQywgc2l6ZW9mKCpnZW5lcmljKSwNCisJCQkJCXd0YmxfdGx2LCBzdGFfd3RibCk7DQor DQorCWdlbmVyaWMgPSAoc3RydWN0IHd0YmxfZ2VuZXJpYyAqKXRsdjsNCisNCisJaWYgKHN0YSkg ew0KKwkJbWVtY3B5KGdlbmVyaWMtPnBlZXJfYWRkciwgc3RhLT5hZGRyLCBFVEhfQUxFTik7DQor CQlnZW5lcmljLT5wYXJ0aWFsX2FpZCA9IGNwdV90b19sZTE2KHN0YS0+YWlkKTsNCisJCWdlbmVy aWMtPm11YXJfaWR4ID0gbXZpZi0+b21hY19pZHg7DQorCQlnZW5lcmljLT5xb3MgPSBzdGEtPndt ZTsNCisJfSBlbHNlIHsNCisJCS8qIHVzZSBCU1NJRCBpbiBzdGF0aW9uIG1vZGUgKi8NCisJCWlm ICh2aWYtPnR5cGUgPT0gTkw4MDIxMV9JRlRZUEVfU1RBVElPTikNCisJCQltZW1jcHkoZ2VuZXJp Yy0+cGVlcl9hZGRyLCB2aWYtPmJzc19jb25mLmJzc2lkLA0KKwkJCSAgICAgICBFVEhfQUxFTik7 DQorCQllbHNlDQorCQkJZXRoX2Jyb2FkY2FzdF9hZGRyKGdlbmVyaWMtPnBlZXJfYWRkcik7DQor DQorCQlnZW5lcmljLT5tdWFyX2lkeCA9IDB4ZTsNCisJfQ0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1 X2FkZF9uZXN0ZWRfdGx2KHNrYiwgV1RCTF9SWCwgc2l6ZW9mKCpyeCksDQorCQkJCQl3dGJsX3Rs diwgc3RhX3d0YmwpOw0KKw0KKwlyeCA9IChzdHJ1Y3Qgd3RibF9yeCAqKXRsdjsNCisJcngtPnJj YTEgPSBzdGEgPyB2aWYtPnR5cGUgIT0gTkw4MDIxMV9JRlRZUEVfQVAgOiAxOw0KKwlyeC0+cmNh MiA9IDE7DQorCXJ4LT5ydiA9IDE7DQorfQ0KKw0KK3N0YXRpYyB2b2lkDQorbXQ3OTE1X21jdV9z dGFfYmFzaWNfdGx2KHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2 aWYsDQorCQkJIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEsIGJvb2wgZW5hYmxlKQ0KK3sNCisj ZGVmaW5lIEVYVFJBX0lORk9fVkVSICAgICAgICAgIEJJVCgwKQ0KKyNkZWZpbmUgRVhUUkFfSU5G T19ORVcgICAgICAgICAgQklUKDEpDQorCXN0cnVjdCBzdGFfcmVjX2Jhc2ljICpiYXNpYzsNCisJ c3RydWN0IHRsdiAqdGx2Ow0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBTVEFf UkVDX0JBU0lDLCBzaXplb2YoKmJhc2ljKSk7DQorDQorCWJhc2ljID0gKHN0cnVjdCBzdGFfcmVj X2Jhc2ljICopdGx2Ow0KKwliYXNpYy0+ZXh0cmFfaW5mbyA9IGNwdV90b19sZTE2KEVYVFJBX0lO Rk9fVkVSKTsNCisNCisJaWYgKGVuYWJsZSkgew0KKwkJYmFzaWMtPmV4dHJhX2luZm8gfD0gY3B1 X3RvX2xlMTYoRVhUUkFfSU5GT19ORVcpOw0KKwkJYmFzaWMtPmNvbm5fc3RhdGUgPSBDT05OX1NU QVRFX1BPUlRfU0VDVVJFOw0KKwl9IGVsc2Ugew0KKwkJYmFzaWMtPmNvbm5fc3RhdGUgPSBDT05O X1NUQVRFX0RJU0NPTk5FQ1Q7DQorCX0NCisNCisJaWYgKCFzdGEpIHsNCisJCWJhc2ljLT5jb25u X3R5cGUgPSBjcHVfdG9fbGUzMihDT05ORUNUSU9OX0lORlJBX0JDKTsNCisJCWV0aF9icm9hZGNh c3RfYWRkcihiYXNpYy0+cGVlcl9hZGRyKTsNCisJCXJldHVybjsNCisJfQ0KKw0KKwlzd2l0Y2gg KHZpZi0+dHlwZSkgew0KKwljYXNlIE5MODAyMTFfSUZUWVBFX01FU0hfUE9JTlQ6DQorCWNhc2Ug Tkw4MDIxMV9JRlRZUEVfQVA6DQorCQliYXNpYy0+Y29ubl90eXBlID0gY3B1X3RvX2xlMzIoQ09O TkVDVElPTl9JTkZSQV9TVEEpOw0KKwkJYnJlYWs7DQorCWNhc2UgTkw4MDIxMV9JRlRZUEVfU1RB VElPTjoNCisJCWJhc2ljLT5jb25uX3R5cGUgPSBjcHVfdG9fbGUzMihDT05ORUNUSU9OX0lORlJB X0FQKTsNCisJCWJyZWFrOw0KKwljYXNlIE5MODAyMTFfSUZUWVBFX0FESE9DOg0KKwkJYmFzaWMt PmNvbm5fdHlwZSA9IGNwdV90b19sZTMyKENPTk5FQ1RJT05fSUJTU19BREhPQyk7DQorCQlicmVh azsNCisJZGVmYXVsdDoNCisJCVdBUk5fT04oMSk7DQorCQlicmVhazsNCisJfQ0KKw0KKwltZW1j cHkoYmFzaWMtPnBlZXJfYWRkciwgc3RhLT5hZGRyLCBFVEhfQUxFTik7DQorCWJhc2ljLT5haWQg PSBjcHVfdG9fbGUxNihzdGEtPmFpZCk7DQorCWJhc2ljLT5xb3MgPSBzdGEtPndtZTsNCit9DQor DQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X3N0YV90bHYoc3RydWN0IG10NzkxNV9kZXYgKmRl diwgc3RydWN0IHNrX2J1ZmYgKnNrYiwNCisJCSAgIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEp DQorew0KKwlzdHJ1Y3QgdGx2ICp0bHY7DQorDQorCWlmIChzdGEtPmh0X2NhcC5odF9zdXBwb3J0 ZWQpIHsNCisJCXN0cnVjdCBzdGFfcmVjX2h0ICpodDsNCisNCisJCS8qIHN0YXJlYyBodCAqLw0K KwkJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHNrYiwgU1RBX1JFQ19IVCwgc2l6ZW9mKCpodCkp Ow0KKwkJaHQgPSAoc3RydWN0IHN0YV9yZWNfaHQgKil0bHY7DQorCQlodC0+aHRfY2FwID0gY3B1 X3RvX2xlMTYoc3RhLT5odF9jYXAuY2FwKTsNCisJfQ0KKw0KKwkvKiBzdGFyZWMgdmh0ICovDQor CWlmIChzdGEtPnZodF9jYXAudmh0X3N1cHBvcnRlZCkgew0KKwkJc3RydWN0IHN0YV9yZWNfdmh0 ICp2aHQ7DQorDQorCQl0bHYgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBTVEFfUkVDX1ZIVCwg c2l6ZW9mKCp2aHQpKTsNCisJCXZodCA9IChzdHJ1Y3Qgc3RhX3JlY192aHQgKil0bHY7DQorCQl2 aHQtPnZodF9jYXAgPSBjcHVfdG9fbGUzMihzdGEtPnZodF9jYXAuY2FwKTsNCisJCXZodC0+dmh0 X3J4X21jc19tYXAgPSBzdGEtPnZodF9jYXAudmh0X21jcy5yeF9tY3NfbWFwOw0KKwkJdmh0LT52 aHRfdHhfbWNzX21hcCA9IHN0YS0+dmh0X2NhcC52aHRfbWNzLnR4X21jc19tYXA7DQorCX0NCit9 DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X3d0Ymxfc21wc190bHYoc3RydWN0IHNrX2J1 ZmYgKnNrYiwgc3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YSwNCisJCQkgdm9pZCAqc3RhX3d0Ymws IHZvaWQgKnd0YmxfdGx2KQ0KK3sNCisJc3RydWN0IHd0Ymxfc21wcyAqc21wczsNCisJc3RydWN0 IHRsdiAqdGx2Ow0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2FkZF9uZXN0ZWRfdGx2KHNrYiwgV1RC TF9TTVBTLCBzaXplb2YoKnNtcHMpLA0KKwkJCQkJd3RibF90bHYsIHN0YV93dGJsKTsNCisJc21w cyA9IChzdHJ1Y3Qgd3RibF9zbXBzICopdGx2Ow0KKw0KKwlpZiAoc3RhLT5zbXBzX21vZGUgPT0g SUVFRTgwMjExX1NNUFNfRFlOQU1JQykNCisJCXNtcHMtPnNtcHMgPSB0cnVlOw0KK30NCisNCitz dGF0aWMgdm9pZA0KK210NzkxNV9tY3Vfd3RibF9odF90bHYoc3RydWN0IHNrX2J1ZmYgKnNrYiwg c3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YSwNCisJCSAgICAgICB2b2lkICpzdGFfd3RibCwgdm9p ZCAqd3RibF90bHYpDQorew0KKwlzdHJ1Y3Qgd3RibF9odCAqaHQgPSBOVUxMOw0KKwlzdHJ1Y3Qg dGx2ICp0bHY7DQorDQorCS8qIHd0YmwgaHQgKi8NCisJaWYgKHN0YS0+aHRfY2FwLmh0X3N1cHBv cnRlZCkgew0KKwkJdGx2ID0gbXQ3OTE1X21jdV9hZGRfbmVzdGVkX3Rsdihza2IsIFdUQkxfSFQs IHNpemVvZigqaHQpLA0KKwkJCQkJCXd0YmxfdGx2LCBzdGFfd3RibCk7DQorCQlodCA9IChzdHJ1 Y3Qgd3RibF9odCAqKXRsdjsNCisJCWh0LT5sZHBjID0gc3RhLT5odF9jYXAuY2FwICYgSUVFRTgw MjExX0hUX0NBUF9MRFBDX0NPRElORzsNCisJCWh0LT5hZiA9IHN0YS0+aHRfY2FwLmFtcGR1X2Zh Y3RvcjsNCisJCWh0LT5tbSA9IHN0YS0+aHRfY2FwLmFtcGR1X2RlbnNpdHk7DQorCQlodC0+aHQg PSB0cnVlOw0KKwl9DQorDQorCS8qIHd0Ymwgdmh0ICovDQorCWlmIChzdGEtPnZodF9jYXAudmh0 X3N1cHBvcnRlZCkgew0KKwkJc3RydWN0IHd0Ymxfdmh0ICp2aHQ7DQorCQl1MzIgYWY7DQorDQor CQl0bHYgPSBtdDc5MTVfbWN1X2FkZF9uZXN0ZWRfdGx2KHNrYiwgV1RCTF9WSFQsIHNpemVvZigq dmh0KSwNCisJCQkJCQl3dGJsX3Rsdiwgc3RhX3d0YmwpOw0KKwkJdmh0ID0gKHN0cnVjdCB3dGJs X3ZodCAqKXRsdjsNCisJCXZodC0+bGRwYyA9IHN0YS0+dmh0X2NhcC5jYXAgJiBJRUVFODAyMTFf VkhUX0NBUF9SWExEUEMsDQorCQl2aHQtPnZodCA9IHRydWU7DQorDQorCQlhZiA9IChzdGEtPnZo dF9jYXAuY2FwICYNCisJCSAgICAgIElFRUU4MDIxMV9WSFRfQ0FQX01BWF9BX01QRFVfTEVOR1RI X0VYUE9ORU5UX01BU0spID4+DQorCQkgICAgIElFRUU4MDIxMV9WSFRfQ0FQX01BWF9BX01QRFVf TEVOR1RIX0VYUE9ORU5UX1NISUZUOw0KKw0KKwkJaWYgKGh0ICYmIGFmID4gaHQtPmFmKQ0KKwkJ CWh0LT5hZiA9IGFmOw0KKwl9DQorDQorCW10NzkxNV9tY3Vfd3RibF9zbXBzX3Rsdihza2IsIHN0 YSwgc3RhX3d0YmwsIHd0YmxfdGx2KTsNCit9DQorDQoraW50IG10NzkxNV9tY3VfYWRkX3NtcHMo c3RydWN0IG10NzkxNV9kZXYgKmRldiwgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiwNCisJCQlz dHJ1Y3QgaWVlZTgwMjExX3N0YSAqc3RhKQ0KK3sNCisJc3RydWN0IG10NzkxNV92aWYgKm12aWYg PSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlzdHJ1Y3QgbXQ3OTE1X3N0 YSAqbXN0YSA9IChzdHJ1Y3QgbXQ3OTE1X3N0YSAqKXN0YS0+ZHJ2X3ByaXY7DQorCXN0cnVjdCB3 dGJsX3JlcV9oZHIgKnd0YmxfaGRyOw0KKwlzdHJ1Y3QgdGx2ICpzdGFfd3RibDsNCisJc3RydWN0 IHNrX2J1ZmYgKnNrYjsNCisNCisJc2tiID0gbXQ3OTE1X21jdV9hbGxvY19zdGFfcmVxKGRldiwg bXZpZiwgbXN0YSwNCisJCQkJICAgICAgIE1UNzkxNV9TVEFfVVBEQVRFX01BWF9TSVpFKTsNCisJ aWYgKElTX0VSUihza2IpKQ0KKwkJcmV0dXJuIFBUUl9FUlIoc2tiKTsNCisNCisJc3RhX3d0Ymwg PSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBTVEFfUkVDX1dUQkwsIHNpemVvZihzdHJ1Y3QgdGx2 KSk7DQorDQorCXd0YmxfaGRyID0gbXQ3OTE1X21jdV9hbGxvY193dGJsX3JlcShkZXYsIG1zdGEs IFdUQkxfU0VULCBzdGFfd3RibCwNCisJCQkJCSAgICAgJnNrYik7DQorCW10NzkxNV9tY3Vfd3Ri bF9zbXBzX3Rsdihza2IsIHN0YSwgc3RhX3d0YmwsIHd0YmxfaGRyKTsNCisNCisJcmV0dXJuIF9f bXQ3Nl9tY3Vfc2tiX3NlbmRfbXNnKCZkZXYtPm10NzYsIHNrYiwNCisJCQkJICAgICAgIE1DVV9F WFRfQ01EX1NUQV9SRUNfVVBEQVRFLCB0cnVlKTsNCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5 MTVfbWN1X3N0YV9yYXRlX2N0cmxfdGx2KHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBtdDc5 MTVfZGV2ICpkZXYsDQorCQkJICAgICBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkJCSAg ICAgc3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YSkNCit7DQorCXN0cnVjdCBjZmc4MDIxMV9jaGFu X2RlZiAqY2hhbmRlZiA9ICZkZXYtPm1waHkuY2hhbmRlZjsNCisJc3RydWN0IHN0YV9yZWNfcmEg KnJhOw0KKwlzdHJ1Y3QgdGx2ICp0bHY7DQorCWVudW0gbmw4MDIxMV9iYW5kIGJhbmQgPSBjaGFu ZGVmLT5jaGFuLT5iYW5kOw0KKwl1MzIgc3VwcF9yYXRlID0gc3RhLT5zdXBwX3JhdGVzW2JhbmRd Ow0KKwlpbnQgbl9yYXRlcyA9IGh3ZWlnaHQzMihzdXBwX3JhdGUpOw0KKwl1MzIgY2FwID0gc3Rh LT53bWUgPyBTVEFfQ0FQX1dNTSA6IDA7DQorCXU4IGksIG5zcyA9IHN0YS0+cnhfbnNzLCBtY3Mg PSAwOw0KKw0KKwl0bHYgPSBtdDc5MTVfbWN1X2FkZF90bHYoc2tiLCBTVEFfUkVDX1JBLCBzaXpl b2YoKnJhKSk7DQorDQorCXJhID0gKHN0cnVjdCBzdGFfcmVjX3JhICopdGx2Ow0KKwlyYS0+dmFs aWQgPSB0cnVlOw0KKwlyYS0+YXV0b19yYXRlID0gdHJ1ZTsNCisJcmEtPnBoeV9tb2RlID0gbXQ3 OTE1X2dldF9waHlfbW9kZShkZXYsIHZpZiwgYmFuZCwgc3RhKTsNCisJcmEtPmNoYW5uZWwgPSBj aGFuZGVmLT5jaGFuLT5od192YWx1ZTsNCisJcmEtPmJ3ID0gc3RhLT5iYW5kd2lkdGg7DQorCXJh LT5yYXRlX2xlbiA9IG5fcmF0ZXM7DQorCXJhLT5waHkuYncgPSBzdGEtPmJhbmR3aWR0aDsNCisN CisJaWYgKG5fcmF0ZXMpIHsNCisJCWlmIChiYW5kID09IE5MODAyMTFfQkFORF8yR0haKSB7DQor CQkJcmEtPnN1cHBfbW9kZSA9IE1PREVfQ0NLOw0KKwkJCXJhLT5zdXBwX2Nja19yYXRlID0gc3Vw cF9yYXRlICYgR0VOTUFTSygzLCAwKTsNCisJCQlyYS0+cGh5LnR5cGUgPSBNVF9QSFlfVFlQRV9D Q0s7DQorDQorCQkJaWYgKG5fcmF0ZXMgPiA0KSB7DQorCQkJCXJhLT5zdXBwX21vZGUgfD0gTU9E RV9PRkRNOw0KKwkJCQlyYS0+c3VwcF9vZmRtX3JhdGUgPSBzdXBwX3JhdGUgPj4gNDsNCisJCQkJ cmEtPnBoeS50eXBlID0gTVRfUEhZX1RZUEVfT0ZETTsNCisJCQl9DQorCQl9IGVsc2Ugew0KKwkJ CXJhLT5zdXBwX21vZGUgPSBNT0RFX09GRE07DQorCQkJcmEtPnN1cHBfb2ZkbV9yYXRlID0gc3Vw cF9yYXRlOw0KKwkJCXJhLT5waHkudHlwZSA9IE1UX1BIWV9UWVBFX09GRE07DQorCQl9DQorCX0N CisNCisJaWYgKHN0YS0+aHRfY2FwLmh0X3N1cHBvcnRlZCkgew0KKwkJZm9yIChpID0gMDsgaSA8 IG5zczsgaSsrKQ0KKwkJCXJhLT5odF9tY3NbaV0gPSBzdGEtPmh0X2NhcC5tY3MucnhfbWFza1tp XTsNCisNCisJCXJhLT5zdXBwX2h0X21jcyA9ICooX19sZTMyICopcmEtPmh0X21jczsNCisJCXJh LT5zdXBwX21vZGUgfD0gTU9ERV9IVDsNCisJCW1jcyA9IGh3ZWlnaHQzMihyYS0+c3VwcF9odF9t Y3MpIC0gMTsNCisJCXJhLT5hZiA9IHN0YS0+aHRfY2FwLmFtcGR1X2ZhY3RvcjsNCisJCXJhLT5o dF9nZiA9ICEhKHN0YS0+aHRfY2FwLmNhcCAmIElFRUU4MDIxMV9IVF9DQVBfR1JOX0ZMRCk7DQor DQorCQljYXAgfD0gU1RBX0NBUF9IVDsNCisJCWlmIChzdGEtPmh0X2NhcC5jYXAgJiBJRUVFODAy MTFfSFRfQ0FQX1NHSV8yMCkNCisJCQljYXAgfD0gU1RBX0NBUF9TR0lfMjA7DQorCQlpZiAoc3Rh LT5odF9jYXAuY2FwICYgSUVFRTgwMjExX0hUX0NBUF9TR0lfNDApDQorCQkJY2FwIHw9IFNUQV9D QVBfU0dJXzQwOw0KKwkJaWYgKHN0YS0+aHRfY2FwLmNhcCAmIElFRUU4MDIxMV9IVF9DQVBfVFhf U1RCQykNCisJCQljYXAgfD0gU1RBX0NBUF9UWF9TVEJDOw0KKwkJaWYgKHN0YS0+aHRfY2FwLmNh cCAmIElFRUU4MDIxMV9IVF9DQVBfUlhfU1RCQykNCisJCQljYXAgfD0gU1RBX0NBUF9SWF9TVEJD Ow0KKwkJaWYgKHN0YS0+aHRfY2FwLmNhcCAmIElFRUU4MDIxMV9IVF9DQVBfTERQQ19DT0RJTkcp DQorCQkJY2FwIHw9IFNUQV9DQVBfTERQQzsNCisJfQ0KKw0KKwlpZiAoc3RhLT52aHRfY2FwLnZo dF9zdXBwb3J0ZWQpIHsNCisJCV9fbGUxNiBtY3NfbWFwID0gc3RhLT52aHRfY2FwLnZodF9tY3Mu cnhfbWNzX21hcDsNCisJCXUzMiBhZjsNCisJCXUxNiB2aHRfbWNzOw0KKwkJdTggbWNzX3ByZXY7 DQorDQorCQlhZiA9IChzdGEtPnZodF9jYXAuY2FwICYNCisJCSAgICAgIElFRUU4MDIxMV9WSFRf Q0FQX01BWF9BX01QRFVfTEVOR1RIX0VYUE9ORU5UX01BU0spID4+DQorCQkgICAgIElFRUU4MDIx MV9WSFRfQ0FQX01BWF9BX01QRFVfTEVOR1RIX0VYUE9ORU5UX1NISUZUOw0KKw0KKwkJaWYgKGFm ID4gc3RhLT5odF9jYXAuYW1wZHVfZmFjdG9yKQ0KKwkJCXJhLT5hZiA9IGFmOw0KKw0KKwkJY2Fw IHw9IFNUQV9DQVBfVkhUOw0KKwkJaWYgKHN0YS0+dmh0X2NhcC5jYXAgJiBJRUVFODAyMTFfVkhU X0NBUF9TSE9SVF9HSV84MCkNCisJCQljYXAgfD0gU1RBX0NBUF9WSFRfU0dJXzgwOw0KKwkJaWYg KHN0YS0+dmh0X2NhcC5jYXAgJiBJRUVFODAyMTFfVkhUX0NBUF9TSE9SVF9HSV8xNjApDQorCQkJ Y2FwIHw9IFNUQV9DQVBfVkhUX1NHSV8xNjA7DQorCQlpZiAoc3RhLT52aHRfY2FwLmNhcCAmIElF RUU4MDIxMV9WSFRfQ0FQX1RYU1RCQykNCisJCQljYXAgfD0gU1RBX0NBUF9WSFRfVFhfU1RCQzsN CisJCWlmIChzdGEtPnZodF9jYXAuY2FwICYgSUVFRTgwMjExX1ZIVF9DQVBfUlhTVEJDXzEpDQor CQkJY2FwIHw9IFNUQV9DQVBfVkhUX1JYX1NUQkM7DQorCQlpZiAoc3RhLT52aHRfY2FwLmNhcCAm IElFRUU4MDIxMV9WSFRfQ0FQX1JYTERQQykNCisJCQljYXAgfD0gU1RBX0NBUF9WSFRfTERQQzsN CisNCisJCXJhLT5zdXBwX21vZGUgfD0gTU9ERV9WSFQ7DQorCQlmb3IgKG1jcyA9IDAsIGkgPSAw OyBpIDwgbnNzOyBpKyssIG1jc19tYXAgPj49IDIpIHsNCisJCQlzd2l0Y2ggKG1jc19tYXAgJiAw eDMpIHsNCisJCQljYXNlIElFRUU4MDIxMV9WSFRfTUNTX1NVUFBPUlRfMF85Og0KKwkJCQl2aHRf bWNzID0gR0VOTUFTSyg5LCAwKTsNCisJCQkJYnJlYWs7DQorCQkJY2FzZSBJRUVFODAyMTFfVkhU X01DU19TVVBQT1JUXzBfODoNCisJCQkJdmh0X21jcyA9IEdFTk1BU0soOCwgMCk7DQorCQkJCWJy ZWFrOw0KKwkJCWNhc2UgSUVFRTgwMjExX1ZIVF9NQ1NfU1VQUE9SVF8wXzc6DQorCQkJCXZodF9t Y3MgPSBHRU5NQVNLKDcsIDApOw0KKwkJCQlicmVhazsNCisJCQlkZWZhdWx0Og0KKwkJCQl2aHRf bWNzID0gMDsNCisJCQl9DQorDQorCQkJcmEtPnN1cHBfdmh0X21jc1tpXSA9IGNwdV90b19sZTE2 KHZodF9tY3MpOw0KKw0KKwkJCW1jc19wcmV2ID0gaHdlaWdodDE2KHZodF9tY3MpIC0gMTsNCisJ CQlpZiAobWNzX3ByZXYgPiBtY3MpDQorCQkJCW1jcyA9IG1jc19wcmV2Ow0KKw0KKwkJCS8qIG9u bHkgc3VwcG9ydCAyc3Mgb24gMTYwTUh6ICovDQorCQkJaWYgKGkgPiAxICYmIChyYS0+YncgPT0g Q01EX0NCV18xNjBNSFogfHwNCisJCQkJICAgICAgcmEtPmJ3ID09IENNRF9DQldfODA4ME1IWikp DQorCQkJCWJyZWFrOw0KKwkJfQ0KKwl9DQorDQorCXJhLT5zdGFfc3RhdHVzID0gY3B1X3RvX2xl MzIoY2FwKTsNCisNCisJc3dpdGNoIChCSVQoZmxzKHJhLT5zdXBwX21vZGUpIC0gMSkpIHsNCisJ Y2FzZSBNT0RFX1ZIVDoNCisJCXJhLT5waHkudHlwZSA9IE1UX1BIWV9UWVBFX1ZIVDsNCisJCXJh LT5waHkubWNzID0gbWNzOw0KKwkJcmEtPnBoeS5uc3MgPSBuc3M7DQorCQlyYS0+cGh5LnN0YmMg PSAhIShzdGEtPnZodF9jYXAuY2FwICYgSUVFRTgwMjExX1ZIVF9DQVBfVFhTVEJDKTsNCisJCXJh LT5waHkubGRwYyA9ICEhKHN0YS0+dmh0X2NhcC5jYXAgJiBJRUVFODAyMTFfVkhUX0NBUF9SWExE UEMpOw0KKwkJcmEtPnBoeS5zZ2kgPQ0KKwkJCSEhKHN0YS0+dmh0X2NhcC5jYXAgJiBJRUVFODAy MTFfVkhUX0NBUF9TSE9SVF9HSV84MCk7DQorCQlicmVhazsNCisJY2FzZSBNT0RFX0hUOg0KKwkJ cmEtPnBoeS50eXBlID0gTVRfUEhZX1RZUEVfSFQ7DQorCQlyYS0+cGh5Lm1jcyA9IG1jczsNCisJ CXJhLT5waHkubGRwYyA9IHN0YS0+aHRfY2FwLmNhcCAmIElFRUU4MDIxMV9IVF9DQVBfTERQQ19D T0RJTkc7DQorCQlyYS0+cGh5LnN0YmMgPSAhIShzdGEtPmh0X2NhcC5jYXAgJiBJRUVFODAyMTFf SFRfQ0FQX1RYX1NUQkMpOw0KKwkJcmEtPnBoeS5zZ2kgPSAhIShzdGEtPmh0X2NhcC5jYXAgJiBJ RUVFODAyMTFfSFRfQ0FQX1NHSV8yMCk7DQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJCWJyZWFr Ow0KKwl9DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1X2FkZF9yYXRlX2N0cmwoc3RydWN0IG10Nzkx NV9kZXYgKmRldiwgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiwNCisJCQkgICAgIHN0cnVjdCBp ZWVlODAyMTFfc3RhICpzdGEpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X3ZpZiAqbXZpZiA9IChzdHJ1 Y3QgbXQ3OTE1X3ZpZiAqKXZpZi0+ZHJ2X3ByaXY7DQorCXN0cnVjdCBtdDc5MTVfc3RhICptc3Rh ID0gKHN0cnVjdCBtdDc5MTVfc3RhICopc3RhLT5kcnZfcHJpdjsNCisJc3RydWN0IHNrX2J1ZmYg KnNrYjsNCisNCisJc2tiID0gbXQ3OTE1X21jdV9hbGxvY19zdGFfcmVxKGRldiwgbXZpZiwgbXN0 YSwNCisJCQkJICAgICAgIE1UNzkxNV9TVEFfVVBEQVRFX01BWF9TSVpFKTsNCisJaWYgKElTX0VS Uihza2IpKQ0KKwkJcmV0dXJuIFBUUl9FUlIoc2tiKTsNCisNCisJbXQ3OTE1X21jdV9zdGFfcmF0 ZV9jdHJsX3Rsdihza2IsIGRldiwgdmlmLCBzdGEpOw0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9z a2Jfc2VuZF9tc2coJmRldi0+bXQ3Niwgc2tiLA0KKwkJCQkgICAgICAgTUNVX0VYVF9DTURfU1RB X1JFQ19VUERBVEUsIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9hZGRfc3RhKHN0cnVj dCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkgICAgICAg c3RydWN0IGllZWU4MDIxMV9zdGEgKnN0YSwgYm9vbCBlbmFibGUpDQorew0KKwlzdHJ1Y3QgbXQ3 OTE1X3ZpZiAqbXZpZiA9IChzdHJ1Y3QgbXQ3OTE1X3ZpZiAqKXZpZi0+ZHJ2X3ByaXY7DQorCXN0 cnVjdCB3dGJsX3JlcV9oZHIgKnd0YmxfaGRyOw0KKwlzdHJ1Y3QgbXQ3OTE1X3N0YSAqbXN0YTsN CisJc3RydWN0IHRsdiAqc3RhX3d0Ymw7DQorCXN0cnVjdCBza19idWZmICpza2I7DQorCWludCBy ZXQ7DQorDQorCW1zdGEgPSBzdGEgPyAoc3RydWN0IG10NzkxNV9zdGEgKilzdGEtPmRydl9wcml2 IDogJm12aWYtPnN0YTsNCisNCisJc2tiID0gbXQ3OTE1X21jdV9hbGxvY19zdGFfcmVxKGRldiwg bXZpZiwgbXN0YSwNCisJCQkJICAgICAgIE1UNzkxNV9TVEFfVVBEQVRFX01BWF9TSVpFKTsNCisJ aWYgKElTX0VSUihza2IpKQ0KKwkJcmV0dXJuIFBUUl9FUlIoc2tiKTsNCisNCisJbXQ3OTE1X21j dV9zdGFfYmFzaWNfdGx2KHNrYiwgdmlmLCBzdGEsIGVuYWJsZSk7DQorCWlmIChlbmFibGUgJiYg c3RhKQ0KKwkJbXQ3OTE1X21jdV9zdGFfdGx2KGRldiwgc2tiLCBzdGEpOw0KKw0KKwlzdGFfd3Ri bCA9IG10NzkxNV9tY3VfYWRkX3Rsdihza2IsIFNUQV9SRUNfV1RCTCwgc2l6ZW9mKHN0cnVjdCB0 bHYpKTsNCisNCisJd3RibF9oZHIgPSBtdDc5MTVfbWN1X2FsbG9jX3d0YmxfcmVxKGRldiwgbXN0 YSwgV1RCTF9SRVNFVF9BTkRfU0VULA0KKwkJCQkJICAgICBzdGFfd3RibCwgJnNrYik7DQorCWlm IChlbmFibGUpIHsNCisJCW10NzkxNV9tY3Vfd3RibF9nZW5lcmljX3Rsdihza2IsIHZpZiwgc3Rh LCBzdGFfd3RibCwgd3RibF9oZHIpOw0KKwkJaWYgKHN0YSkNCisJCQltdDc5MTVfbWN1X3d0Ymxf aHRfdGx2KHNrYiwgc3RhLCBzdGFfd3RibCwgd3RibF9oZHIpOw0KKwl9DQorDQorCXJldCA9IF9f bXQ3Nl9tY3Vfc2tiX3NlbmRfbXNnKCZkZXYtPm10NzYsIHNrYiwNCisJCQkJICAgICAgTUNVX0VY VF9DTURfU1RBX1JFQ19VUERBVEUsIHRydWUpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsN CisNCisJaWYgKGVuYWJsZSAmJiBzdGEpDQorCQlyZXR1cm4gbXQ3OTE1X21jdV9hZGRfcmF0ZV9j dHJsKGRldiwgdmlmLCBzdGEpOw0KKw0KKwlyZXR1cm4gMDsNCit9DQorDQoraW50IG10NzkxNV9t Y3VfYWRkX2Rldl9pbmZvKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsDQorCQkJICAgIHN0cnVjdCBp ZWVlODAyMTFfdmlmICp2aWYsIGJvb2wgZW5hYmxlKQ0KK3sNCisJc3RydWN0IG10NzkxNV92aWYg Km12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2Ow0KKwlzdHJ1Y3Qgew0K KwkJc3RydWN0IHJlcV9oZHIgew0KKwkJCXU4IG9tYWNfaWR4Ow0KKwkJCXU4IGRiZGNfaWR4Ow0K KwkJCV9fbGUxNiB0bHZfbnVtOw0KKwkJCXU4IGlzX3Rsdl9hcHBlbmQ7DQorCQkJdTggcnN2WzNd Ow0KKwkJfSBfX3BhY2tlZCBoZHI7DQorCQlzdHJ1Y3QgcmVxX3RsdiB7DQorCQkJX19sZTE2IHRh ZzsNCisJCQlfX2xlMTYgbGVuOw0KKwkJCXU4IGFjdGl2ZTsNCisJCQl1OCBkYmRjX2lkeDsNCisJ CQl1OCBvbWFjX2FkZHJbRVRIX0FMRU5dOw0KKwkJfSBfX3BhY2tlZCB0bHY7DQorCX0gZGF0YSA9 IHsNCisJCS5oZHIgPSB7DQorCQkJLm9tYWNfaWR4ID0gbXZpZi0+b21hY19pZHgsDQorCQkJLmRi ZGNfaWR4ID0gbXZpZi0+YmFuZF9pZHgsDQorCQkJLnRsdl9udW0gPSBjcHVfdG9fbGUxNigxKSwN CisJCQkuaXNfdGx2X2FwcGVuZCA9IDEsDQorCQl9LA0KKwkJLnRsdiA9IHsNCisJCQkudGFnID0g Y3B1X3RvX2xlMTYoREVWX0lORk9fQUNUSVZFKSwNCisJCQkubGVuID0gY3B1X3RvX2xlMTYoc2l6 ZW9mKHN0cnVjdCByZXFfdGx2KSksDQorCQkJLmFjdGl2ZSA9IGVuYWJsZSwNCisJCQkuZGJkY19p ZHggPSBtdmlmLT5iYW5kX2lkeCwNCisJCX0sDQorCX07DQorDQorCW1lbWNweShkYXRhLnRsdi5v bWFjX2FkZHIsIHZpZi0+YWRkciwgRVRIX0FMRU4pOw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5k X21zZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9ERVZfSU5GT19VUERBVEUsDQorCQkJCSAgICZk YXRhLCBzaXplb2YoZGF0YSksIHRydWUpOw0KK30NCisNCitzdGF0aWMgdm9pZA0KK210NzkxNV9t Y3VfYmVhY29uX2NzYShzdHJ1Y3Qgc2tfYnVmZiAqcnNrYiwgc3RydWN0IHNrX2J1ZmYgKnNrYiwN CisJCSAgICAgIHN0cnVjdCBic3NfaW5mb19iY24gKmJjbiwNCisJCSAgICAgIHN0cnVjdCBpZWVl ODAyMTFfbXV0YWJsZV9vZmZzZXRzICpvZmZzKQ0KK3sNCisJaWYgKG9mZnMtPmNzYV9jb3VudGVy X29mZnNbMF0pIHsNCisJCXN0cnVjdCB0bHYgKnRsdjsNCisJCXN0cnVjdCBic3NfaW5mb19iY25f Y3NhICpjc2E7DQorDQorCQl0bHYgPSBtdDc5MTVfbWN1X2FkZF9uZXN0ZWRfc3VidGx2KHJza2Is IEJTU19JTkZPX0JDTl9DU0EsDQorCQkJCQkJICAgc2l6ZW9mKCpjc2EpLCAmYmNuLT5zdWJfbnRs diwNCisJCQkJCQkgICAmYmNuLT5sZW4pOw0KKwkJY3NhID0gKHN0cnVjdCBic3NfaW5mb19iY25f Y3NhICopdGx2Ow0KKwkJY3NhLT5jbnQgPSBza2ItPmRhdGFbb2Zmcy0+Y3NhX2NvdW50ZXJfb2Zm c1swXV07DQorCX0NCit9DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfbWN1X2JlYWNvbl9jb250 KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBza19idWZmICpyc2tiLA0KKwkJICAgICAg IHN0cnVjdCBza19idWZmICpza2IsIHN0cnVjdCBic3NfaW5mb19iY24gKmJjbiwNCisJCSAgICAg ICBzdHJ1Y3QgaWVlZTgwMjExX211dGFibGVfb2Zmc2V0cyAqb2ZmcykNCit7DQorCXN0cnVjdCBt dDc2X3djaWQgKndjaWQgPSAmZGV2LT5tdDc2Lmdsb2JhbF93Y2lkOw0KKwlzdHJ1Y3QgYnNzX2lu Zm9fYmNuX2NvbnQgKmNvbnQ7DQorCXN0cnVjdCB0bHYgKnRsdjsNCisJdTggKmJ1ZjsNCisJaW50 IGxlbiA9IHNpemVvZigqY29udCkgKyBNVF9UWERfU0laRSArIHNrYi0+bGVuOw0KKw0KKwl0bHYg PSBtdDc5MTVfbWN1X2FkZF9uZXN0ZWRfc3VidGx2KHJza2IsIEJTU19JTkZPX0JDTl9DT05URU5U LA0KKwkJCQkJICAgbGVuLCAmYmNuLT5zdWJfbnRsdiwgJmJjbi0+bGVuKTsNCisNCisJY29udCA9 IChzdHJ1Y3QgYnNzX2luZm9fYmNuX2NvbnQgKil0bHY7DQorCWNvbnQtPnBrdF9sZW4gPSBjcHVf dG9fbGUxNihNVF9UWERfU0laRSArIHNrYi0+bGVuKTsNCisJY29udC0+dGltX29mcyA9IGNwdV90 b19sZTE2KG9mZnMtPnRpbV9vZmZzZXQpOw0KKw0KKwlpZiAob2Zmcy0+Y3NhX2NvdW50ZXJfb2Zm c1swXSkNCisJCWNvbnQtPmNzYV9vZnMgPSBjcHVfdG9fbGUxNihvZmZzLT5jc2FfY291bnRlcl9v ZmZzWzBdIC0gNCk7DQorDQorCWJ1ZiA9ICh1OCAqKXRsdiArIHNpemVvZigqY29udCk7DQorCW10 NzkxNV9tYWNfd3JpdGVfdHh3aShkZXYsIChfX2xlMzIgKilidWYsIHNrYiwgd2NpZCwgTlVMTCwN CisJCQkgICAgICB0cnVlKTsNCisJbWVtY3B5KGJ1ZiArIE1UX1RYRF9TSVpFLCBza2ItPmRhdGEs IHNrYi0+bGVuKTsNCit9DQorDQoraW50IG10NzkxNV9tY3VfYWRkX2JlYWNvbihzdHJ1Y3QgaWVl ZTgwMjExX2h3ICpodywNCisJCQkgIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsIGludCBlbikN Cit7DQorI2RlZmluZSBNQVhfQkVBQ09OX1NJWkUgNTEyDQorCXN0cnVjdCBtdDc5MTVfZGV2ICpk ZXYgPSBtdDc5MTVfaHdfZGV2KGh3KTsNCisJc3RydWN0IG10NzkxNV9waHkgKnBoeSA9IG10Nzkx NV9od19waHkoaHcpOw0KKwlzdHJ1Y3QgbXQ3OTE1X3ZpZiAqbXZpZiA9IChzdHJ1Y3QgbXQ3OTE1 X3ZpZiAqKXZpZi0+ZHJ2X3ByaXY7DQorCXN0cnVjdCBpZWVlODAyMTFfbXV0YWJsZV9vZmZzZXRz IG9mZnM7DQorCXN0cnVjdCBpZWVlODAyMTFfdHhfaW5mbyAqaW5mbzsNCisJc3RydWN0IHNrX2J1 ZmYgKnNrYiwgKnJza2I7DQorCXN0cnVjdCB0bHYgKnRsdjsNCisJc3RydWN0IGJzc19pbmZvX2Jj biAqYmNuOw0KKwlpbnQgbGVuID0gTVQ3OTE1X0JFQUNPTl9VUERBVEVfU0laRSArIE1BWF9CRUFD T05fU0laRTsNCisNCisJcnNrYiA9IG10NzkxNV9tY3VfYWxsb2Nfc3RhX3JlcShkZXYsIG12aWYs IE5VTEwsIGxlbik7DQorCWlmIChJU19FUlIocnNrYikpDQorCQlyZXR1cm4gUFRSX0VSUihyc2ti KTsNCisNCisJdGx2ID0gbXQ3OTE1X21jdV9hZGRfdGx2KHJza2IsIEJTU19JTkZPX09GRkxPQUQs IHNpemVvZigqYmNuKSk7DQorCWJjbiA9IChzdHJ1Y3QgYnNzX2luZm9fYmNuICopdGx2Ow0KKwli Y24tPmVuYWJsZSA9IGVuOw0KKw0KKwlza2IgPSBpZWVlODAyMTFfYmVhY29uX2dldF90ZW1wbGF0 ZShodywgdmlmLCAmb2Zmcyk7DQorCWlmICghc2tiKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQor CWlmIChza2ItPmxlbiA+IE1BWF9CRUFDT05fU0laRSAtIE1UX1RYRF9TSVpFKSB7DQorCQlkZXZf ZXJyKGRldi0+bXQ3Ni5kZXYsICJCY24gc2l6ZSBsaW1pdCBleGNlZWRcbiIpOw0KKwkJZGV2X2tm cmVlX3NrYihza2IpOw0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJaWYgKG12aWYtPmJh bmRfaWR4KSB7DQorCQlpbmZvID0gSUVFRTgwMjExX1NLQl9DQihza2IpOw0KKwkJaW5mby0+aHdf cXVldWUgfD0gTVRfVFhfSFdfUVVFVUVfRVhUX1BIWTsNCisJfQ0KKw0KKwkvKiBUT0RPOiBzdWJ0 YWcgLSBic3MgY29sb3IgY291bnQgJiAxMXYgTUJTU0lEICovDQorCW10NzkxNV9tY3VfYmVhY29u X2NzYShyc2tiLCBza2IsIGJjbiwgJm9mZnMpOw0KKwltdDc5MTVfbWN1X2JlYWNvbl9jb250KGRl diwgcnNrYiwgc2tiLCBiY24sICZvZmZzKTsNCisJZGV2X2tmcmVlX3NrYihza2IpOw0KKw0KKwly ZXR1cm4gX19tdDc2X21jdV9za2Jfc2VuZF9tc2coJnBoeS0+ZGV2LT5tdDc2LCByc2tiLA0KKwkJ CQkgICAgICAgTUNVX0VYVF9DTURfQlNTX0lORk9fVVBEQVRFLCB0cnVlKTsNCit9DQorDQorc3Rh dGljIGludCBtdDc5MTVfbWN1X3NlbmRfZmlybXdhcmUoc3RydWN0IG10NzkxNV9kZXYgKmRldiwg Y29uc3Qgdm9pZCAqZGF0YSwNCisJCQkJICAgIGludCBsZW4pDQorew0KKwlpbnQgcmV0ID0gMCwg Y3VyX2xlbjsNCisNCisJd2hpbGUgKGxlbiA+IDApIHsNCisJCWN1cl9sZW4gPSBtaW5fdChpbnQs IDQwOTYgLSBzaXplb2Yoc3RydWN0IG10NzkxNV9tY3VfdHhkKSwNCisJCQkJbGVuKTsNCisNCisJ CXJldCA9IF9fbXQ3Nl9tY3Vfc2VuZF9tc2coJmRldi0+bXQ3NiwgLU1DVV9DTURfRldfU0NBVFRF UiwNCisJCQkJCSAgZGF0YSwgY3VyX2xlbiwgZmFsc2UpOw0KKwkJaWYgKHJldCkNCisJCQlicmVh azsNCisNCisJCWRhdGEgKz0gY3VyX2xlbjsNCisJCWxlbiAtPSBjdXJfbGVuOw0KKwkJbXQ3Nl9x dWV1ZV90eF9jbGVhbnVwKGRldiwgTVRfVFhRX0ZXREwsIGZhbHNlKTsNCisJfQ0KKw0KKwlyZXR1 cm4gcmV0Ow0KK30NCisNCitzdGF0aWMgaW50IG10NzkxNV9tY3Vfc3RhcnRfZmlybXdhcmUoc3Ry dWN0IG10NzkxNV9kZXYgKmRldiwgdTMyIGFkZHIsDQorCQkJCSAgICAgdTMyIG9wdGlvbikNCit7 DQorCXN0cnVjdCB7DQorCQlfX2xlMzIgb3B0aW9uOw0KKwkJX19sZTMyIGFkZHI7DQorCX0gcmVx ID0gew0KKwkJLm9wdGlvbiA9IGNwdV90b19sZTMyKG9wdGlvbiksDQorCQkuYWRkciA9IGNwdV90 b19sZTMyKGFkZHIpLA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5kX21zZygmZGV2 LT5tdDc2LCAtTUNVX0NNRF9GV19TVEFSVF9SRVEsDQorCQkJCSAgICZyZXEsIHNpemVvZihyZXEp LCB0cnVlKTsNCit9DQorDQorc3RhdGljIGludCBtdDc5MTVfbWN1X3Jlc3RhcnQoc3RydWN0IG10 NzZfZGV2ICpkZXYpDQorew0KKwlzdHJ1Y3Qgew0KKwkJdTggcG93ZXJfbW9kZTsNCisJCXU4IHJz dlszXTsNCisJfSByZXEgPSB7DQorCQkucG93ZXJfbW9kZSA9IDEsDQorCX07DQorDQorCXJldHVy biBfX210NzZfbWN1X3NlbmRfbXNnKGRldiwgLU1DVV9DTURfTklDX1BPV0VSX0NUUkwsICZyZXEs DQorCQkJCSAgIHNpemVvZihyZXEpLCBmYWxzZSk7DQorfQ0KKw0KK3N0YXRpYyBpbnQgbXQ3OTE1 X21jdV9wYXRjaF9zZW1fY3RybChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBib29sIGdldCkNCit7 DQorCXN0cnVjdCB7DQorCQlfX2xlMzIgb3A7DQorCX0gcmVxID0gew0KKwkJLm9wID0gY3B1X3Rv X2xlMzIoZ2V0ID8gUEFUQ0hfU0VNX0dFVCA6IFBBVENIX1NFTV9SRUxFQVNFKSwNCisJfTsNCisN CisJcmV0dXJuIF9fbXQ3Nl9tY3Vfc2VuZF9tc2coJmRldi0+bXQ3NiwgLU1DVV9DTURfUEFUQ0hf U0VNX0NPTlRST0wsDQorCQkJCSAgICZyZXEsIHNpemVvZihyZXEpLCB0cnVlKTsNCit9DQorDQor c3RhdGljIGludCBtdDc5MTVfbWN1X3N0YXJ0X3BhdGNoKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYp DQorew0KKwlzdHJ1Y3Qgew0KKwkJdTggY2hlY2tfY3JjOw0KKwkJdTggcmVzZXJ2ZWRbM107DQor CX0gcmVxID0gew0KKwkJLmNoZWNrX2NyYyA9IDAsDQorCX07DQorDQorCXJldHVybiBfX210NzZf bWN1X3NlbmRfbXNnKCZkZXYtPm10NzYsIC1NQ1VfQ01EX1BBVENIX0ZJTklTSF9SRVEsDQorCQkJ CSAgICZyZXEsIHNpemVvZihyZXEpLCB0cnVlKTsNCit9DQorDQorc3RhdGljIGludCBtdDc5MTVf ZHJpdmVyX293bihzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJdTMyIHJlZyA9IG10Nzkx NV9yZWdfbWFwX2wxKGRldiwgTVRfVE9QX0xQQ1JfSE9TVF9CQU5EMCk7DQorDQorCW10NzZfd3Io ZGV2LCByZWcsIE1UX1RPUF9MUENSX0hPU1RfRFJWX09XTik7DQorCWlmICghbXQ3Nl9wb2xsX21z ZWMoZGV2LCByZWcsIE1UX1RPUF9MUENSX0hPU1RfRldfT1dOLA0KKwkJCSAgICAwLCA1MDApKSB7 DQorCQlkZXZfZXJyKGRldi0+bXQ3Ni5kZXYsICJUaW1lb3V0IGZvciBkcml2ZXIgb3duXG4iKTsN CisJCXJldHVybiAtRUlPOw0KKwl9DQorDQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50 IG10NzkxNV9tY3VfaW5pdF9kb3dubG9hZChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1MzIgYWRk ciwNCisJCQkJICAgIHUzMiBsZW4sIHUzMiBtb2RlKQ0KK3sNCisJc3RydWN0IHsNCisJCV9fbGUz MiBhZGRyOw0KKwkJX19sZTMyIGxlbjsNCisJCV9fbGUzMiBtb2RlOw0KKwl9IHJlcSA9IHsNCisJ CS5hZGRyID0gY3B1X3RvX2xlMzIoYWRkciksDQorCQkubGVuID0gY3B1X3RvX2xlMzIobGVuKSwN CisJCS5tb2RlID0gY3B1X3RvX2xlMzIobW9kZSksDQorCX07DQorCWludCBhdHRyOw0KKw0KKwlp ZiAocmVxLmFkZHIgPT0gTUNVX1BBVENIX0FERFJFU1MpDQorCQlhdHRyID0gLU1DVV9DTURfUEFU Q0hfU1RBUlRfUkVROw0KKwllbHNlDQorCQlhdHRyID0gLU1DVV9DTURfVEFSR0VUX0FERFJFU1Nf TEVOX1JFUTsNCisNCisJcmV0dXJuIF9fbXQ3Nl9tY3Vfc2VuZF9tc2coJmRldi0+bXQ3NiwgYXR0 ciwgJnJlcSwgc2l6ZW9mKHJlcSksIHRydWUpOw0KK30NCisNCitzdGF0aWMgaW50IG10NzkxNV9s b2FkX3BhdGNoKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwljb25zdCBzdHJ1Y3QgbXQ3 OTE1X3BhdGNoX2hkciAqaGRyOw0KKwljb25zdCBzdHJ1Y3QgZmlybXdhcmUgKmZ3ID0gTlVMTDsN CisJaW50IGksIHJldCwgc2VtOw0KKw0KKwlzZW0gPSBtdDc5MTVfbWN1X3BhdGNoX3NlbV9jdHJs KGRldiwgMSk7DQorCXN3aXRjaCAoc2VtKSB7DQorCWNhc2UgUEFUQ0hfSVNfREw6DQorCQlyZXR1 cm4gMDsNCisJY2FzZSBQQVRDSF9OT1RfRExfU0VNX1NVQ0NFU1M6DQorCQlicmVhazsNCisJZGVm YXVsdDoNCisJCWRldl9lcnIoZGV2LT5tdDc2LmRldiwgIkZhaWxlZCB0byBnZXQgcGF0Y2ggc2Vt YXBob3JlXG4iKTsNCisJCXJldHVybiAtRUFHQUlOOw0KKwl9DQorDQorCXJldCA9IHJlcXVlc3Rf ZmlybXdhcmUoJmZ3LCBNVDc5MTVfUk9NX1BBVENILCBkZXYtPm10NzYuZGV2KTsNCisJaWYgKHJl dCkNCisJCWdvdG8gb3V0Ow0KKw0KKwlpZiAoIWZ3IHx8ICFmdy0+ZGF0YSB8fCBmdy0+c2l6ZSA8 IHNpemVvZigqaGRyKSkgew0KKwkJZGV2X2VycihkZXYtPm10NzYuZGV2LCAiSW52YWxpZCBmaXJt d2FyZVxuIik7DQorCQlyZXQgPSAtRUlOVkFMOw0KKwkJZ290byBvdXQ7DQorCX0NCisNCisJaGRy ID0gKGNvbnN0IHN0cnVjdCBtdDc5MTVfcGF0Y2hfaGRyICopKGZ3LT5kYXRhKTsNCisNCisJZGV2 X2luZm8oZGV2LT5tdDc2LmRldiwgIkhXL1NXIFZlcnNpb246IDB4JXgsIEJ1aWxkIFRpbWU6ICUu MTZzXG4iLA0KKwkJIGJlMzJfdG9fY3B1KGhkci0+aHdfc3dfdmVyKSwgaGRyLT5idWlsZF9kYXRl KTsNCisNCisJZm9yIChpID0gMDsgaSA8IGJlMzJfdG9fY3B1KGhkci0+ZGVzYy5uX3JlZ2lvbik7 IGkrKykgew0KKwkJc3RydWN0IG10NzkxNV9wYXRjaF9zZWMgKnNlYzsNCisJCWNvbnN0IHU4ICpk bDsNCisJCXUzMiBsZW4sIGFkZHI7DQorDQorCQlzZWMgPSAoc3RydWN0IG10NzkxNV9wYXRjaF9z ZWMgKikoZnctPmRhdGEgKyBzaXplb2YoKmhkcikgKw0KKwkJCQkJCSAgaSAqIHNpemVvZigqc2Vj KSk7DQorCQlpZiAoKGJlMzJfdG9fY3B1KHNlYy0+dHlwZSkgJiBQQVRDSF9TRUNfVFlQRV9NQVNL KSAhPQ0KKwkJICAgIFBBVENIX1NFQ19UWVBFX0lORk8pIHsNCisJCQlyZXQgPSAtRUlOVkFMOw0K KwkJCWdvdG8gb3V0Ow0KKwkJfQ0KKw0KKwkJYWRkciA9IGJlMzJfdG9fY3B1KHNlYy0+aW5mby5h ZGRyKTsNCisJCWxlbiA9IGJlMzJfdG9fY3B1KHNlYy0+aW5mby5sZW4pOw0KKwkJZGwgPSBmdy0+ ZGF0YSArIGJlMzJfdG9fY3B1KHNlYy0+b2Zmcyk7DQorDQorCQlyZXQgPSBtdDc5MTVfbWN1X2lu aXRfZG93bmxvYWQoZGV2LCBhZGRyLCBsZW4sDQorCQkJCQkgICAgICAgRExfTU9ERV9ORUVEX1JT UCk7DQorCQlpZiAocmV0KSB7DQorCQkJZGV2X2VycihkZXYtPm10NzYuZGV2LCAiRG93bmxvYWQg cmVxdWVzdCBmYWlsZWRcbiIpOw0KKwkJCWdvdG8gb3V0Ow0KKwkJfQ0KKw0KKwkJcmV0ID0gbXQ3 OTE1X21jdV9zZW5kX2Zpcm13YXJlKGRldiwgZGwsIGxlbik7DQorCQlpZiAocmV0KSB7DQorCQkJ ZGV2X2VycihkZXYtPm10NzYuZGV2LCAiRmFpbGVkIHRvIHNlbmQgcGF0Y2hcbiIpOw0KKwkJCWdv dG8gb3V0Ow0KKwkJfQ0KKwl9DQorDQorCXJldCA9IG10NzkxNV9tY3Vfc3RhcnRfcGF0Y2goZGV2 KTsNCisJaWYgKHJldCkNCisJCWRldl9lcnIoZGV2LT5tdDc2LmRldiwgIkZhaWxlZCB0byBzdGFy dCBwYXRjaFxuIik7DQorDQorb3V0Og0KKwlzZW0gPSBtdDc5MTVfbWN1X3BhdGNoX3NlbV9jdHJs KGRldiwgMCk7DQorCXN3aXRjaCAoc2VtKSB7DQorCWNhc2UgUEFUQ0hfUkVMX1NFTV9TVUNDRVNT Og0KKwkJYnJlYWs7DQorCWRlZmF1bHQ6DQorCQlyZXQgPSAtRUFHQUlOOw0KKwkJZGV2X2Vycihk ZXYtPm10NzYuZGV2LCAiRmFpbGVkIHRvIHJlbGVhc2UgcGF0Y2ggc2VtYXBob3JlXG4iKTsNCisJ CWdvdG8gb3V0Ow0KKwl9DQorCXJlbGVhc2VfZmlybXdhcmUoZncpOw0KKw0KKwlyZXR1cm4gcmV0 Ow0KK30NCisNCitzdGF0aWMgdTMyIG10NzkxNV9tY3VfZ2VuX2RsX21vZGUodTggZmVhdHVyZV9z ZXQsIGJvb2wgaXNfd2EpDQorew0KKwl1MzIgcmV0ID0gMDsNCisNCisJcmV0IHw9IChmZWF0dXJl X3NldCAmIEZXX0ZFQVRVUkVfU0VUX0VOQ1JZUFQpID8NCisJICAgICAgIChETF9NT0RFX0VOQ1JZ UFQgfCBETF9NT0RFX1JFU0VUX1NFQ19JVikgOiAwOw0KKwlyZXQgfD0gRklFTERfUFJFUChETF9N T0RFX0tFWV9JRFgsDQorCQkJICBGSUVMRF9HRVQoRldfRkVBVFVSRV9TRVRfS0VZX0lEWCwgZmVh dHVyZV9zZXQpKTsNCisJcmV0IHw9IERMX01PREVfTkVFRF9SU1A7DQorCXJldCB8PSBpc193YSA/ IERMX01PREVfV09SS0lOR19QREFfQ1I0IDogMDsNCisNCisJcmV0dXJuIHJldDsNCit9DQorDQor c3RhdGljIGludA0KK210NzkxNV9tY3Vfc2VuZF9yYW1fZmlybXdhcmUoc3RydWN0IG10NzkxNV9k ZXYgKmRldiwNCisJCQkgICAgIGNvbnN0IHN0cnVjdCBtdDc5MTVfZndfdHJhaWxlciAqaGRyLA0K KwkJCSAgICAgY29uc3QgdTggKmRhdGEsIGJvb2wgaXNfd2EpDQorew0KKwlpbnQgaSwgb2Zmc2V0 ID0gMDsNCisJdTMyIG92ZXJyaWRlID0gMCwgb3B0aW9uID0gMDsNCisNCisJZm9yIChpID0gMDsg aSA8IGhkci0+bl9yZWdpb247IGkrKykgew0KKwkJY29uc3Qgc3RydWN0IG10NzkxNV9md19yZWdp b24gKnJlZ2lvbjsNCisJCWludCBlcnI7DQorCQl1MzIgbGVuLCBhZGRyLCBtb2RlOw0KKw0KKwkJ cmVnaW9uID0gKGNvbnN0IHN0cnVjdCBtdDc5MTVfZndfcmVnaW9uICopKChjb25zdCB1OCAqKWhk ciAtDQorCQkJIChoZHItPm5fcmVnaW9uIC0gaSkgKiBzaXplb2YoKnJlZ2lvbikpOw0KKwkJbW9k ZSA9IG10NzkxNV9tY3VfZ2VuX2RsX21vZGUocmVnaW9uLT5mZWF0dXJlX3NldCwgaXNfd2EpOw0K KwkJbGVuID0gbGUzMl90b19jcHUocmVnaW9uLT5sZW4pOw0KKwkJYWRkciA9IGxlMzJfdG9fY3B1 KHJlZ2lvbi0+YWRkcik7DQorDQorCQlpZiAocmVnaW9uLT5mZWF0dXJlX3NldCAmIEZXX0ZFQVRV UkVfT1ZFUlJJREVfQUREUikNCisJCQlvdmVycmlkZSA9IGFkZHI7DQorDQorCQllcnIgPSBtdDc5 MTVfbWN1X2luaXRfZG93bmxvYWQoZGV2LCBhZGRyLCBsZW4sIG1vZGUpOw0KKwkJaWYgKGVycikg ew0KKwkJCWRldl9lcnIoZGV2LT5tdDc2LmRldiwgIkRvd25sb2FkIHJlcXVlc3QgZmFpbGVkXG4i KTsNCisJCQlyZXR1cm4gZXJyOw0KKwkJfQ0KKw0KKwkJZXJyID0gbXQ3OTE1X21jdV9zZW5kX2Zp cm13YXJlKGRldiwgZGF0YSArIG9mZnNldCwgbGVuKTsNCisJCWlmIChlcnIpIHsNCisJCQlkZXZf ZXJyKGRldi0+bXQ3Ni5kZXYsICJGYWlsZWQgdG8gc2VuZCBmaXJtd2FyZS5cbiIpOw0KKwkJCXJl dHVybiBlcnI7DQorCQl9DQorDQorCQlvZmZzZXQgKz0gbGVuOw0KKwl9DQorDQorCWlmIChvdmVy cmlkZSkNCisJCW9wdGlvbiB8PSBGV19TVEFSVF9PVkVSUklERTsNCisNCisJaWYgKGlzX3dhKQ0K KwkJb3B0aW9uIHw9IEZXX1NUQVJUX1dPUktJTkdfUERBX0NSNDsNCisNCisJcmV0dXJuIG10Nzkx NV9tY3Vfc3RhcnRfZmlybXdhcmUoZGV2LCBvdmVycmlkZSwgb3B0aW9uKTsNCit9DQorDQorc3Rh dGljIGludCBtdDc5MTVfbG9hZF9yYW0oc3RydWN0IG10NzkxNV9kZXYgKmRldikNCit7DQorCWNv bnN0IHN0cnVjdCBtdDc5MTVfZndfdHJhaWxlciAqaGRyOw0KKwljb25zdCBzdHJ1Y3QgZmlybXdh cmUgKmZ3Ow0KKwlpbnQgcmV0Ow0KKw0KKwlyZXQgPSByZXF1ZXN0X2Zpcm13YXJlKCZmdywgTVQ3 OTE1X0ZJUk1XQVJFX1dNLCBkZXYtPm10NzYuZGV2KTsNCisJaWYgKHJldCkNCisJCXJldHVybiBy ZXQ7DQorDQorCWlmICghZncgfHwgIWZ3LT5kYXRhIHx8IGZ3LT5zaXplIDwgc2l6ZW9mKCpoZHIp KSB7DQorCQlkZXZfZXJyKGRldi0+bXQ3Ni5kZXYsICJJbnZhbGlkIGZpcm13YXJlXG4iKTsNCisJ CXJldCA9IC1FSU5WQUw7DQorCQlnb3RvIG91dDsNCisJfQ0KKw0KKwloZHIgPSAoY29uc3Qgc3Ry dWN0IG10NzkxNV9md190cmFpbGVyICopKGZ3LT5kYXRhICsgZnctPnNpemUgLQ0KKwkJCQkJc2l6 ZW9mKCpoZHIpKTsNCisNCisJZGV2X2luZm8oZGV2LT5tdDc2LmRldiwgIldNIEZpcm13YXJlIFZl cnNpb246ICUuMTBzLCBCdWlsZCBUaW1lOiAlLjE1c1xuIiwNCisJCSBoZHItPmZ3X3ZlciwgaGRy LT5idWlsZF9kYXRlKTsNCisNCisJcmV0ID0gbXQ3OTE1X21jdV9zZW5kX3JhbV9maXJtd2FyZShk ZXYsIGhkciwgZnctPmRhdGEsIGZhbHNlKTsNCisJaWYgKHJldCkgew0KKwkJZGV2X2VycihkZXYt Pm10NzYuZGV2LCAiRmFpbGVkIHRvIHN0YXJ0IFdNIGZpcm13YXJlXG4iKTsNCisJCWdvdG8gb3V0 Ow0KKwl9DQorDQorCXJlbGVhc2VfZmlybXdhcmUoZncpOw0KKw0KKwlyZXQgPSByZXF1ZXN0X2Zp cm13YXJlKCZmdywgTVQ3OTE1X0ZJUk1XQVJFX1dBLCBkZXYtPm10NzYuZGV2KTsNCisJaWYgKHJl dCkNCisJCXJldHVybiByZXQ7DQorDQorCWlmICghZncgfHwgIWZ3LT5kYXRhIHx8IGZ3LT5zaXpl IDwgc2l6ZW9mKCpoZHIpKSB7DQorCQlkZXZfZXJyKGRldi0+bXQ3Ni5kZXYsICJJbnZhbGlkIGZp cm13YXJlXG4iKTsNCisJCXJldCA9IC1FSU5WQUw7DQorCQlnb3RvIG91dDsNCisJfQ0KKw0KKwlo ZHIgPSAoY29uc3Qgc3RydWN0IG10NzkxNV9md190cmFpbGVyICopKGZ3LT5kYXRhICsgZnctPnNp emUgLQ0KKwkJCQkJc2l6ZW9mKCpoZHIpKTsNCisNCisJZGV2X2luZm8oZGV2LT5tdDc2LmRldiwg IldBIEZpcm13YXJlIFZlcnNpb246ICUuMTBzLCBCdWlsZCBUaW1lOiAlLjE1c1xuIiwNCisJCSBo ZHItPmZ3X3ZlciwgaGRyLT5idWlsZF9kYXRlKTsNCisNCisJcmV0ID0gbXQ3OTE1X21jdV9zZW5k X3JhbV9maXJtd2FyZShkZXYsIGhkciwgZnctPmRhdGEsIHRydWUpOw0KKwlpZiAocmV0KSB7DQor CQlkZXZfZXJyKGRldi0+bXQ3Ni5kZXYsICJGYWlsZWQgdG8gc3RhcnQgV0EgZmlybXdhcmVcbiIp Ow0KKwkJZ290byBvdXQ7DQorCX0NCisNCisJc25wcmludGYoZGV2LT5tdDc2Lmh3LT53aXBoeS0+ ZndfdmVyc2lvbiwNCisJCSBzaXplb2YoZGV2LT5tdDc2Lmh3LT53aXBoeS0+ZndfdmVyc2lvbiks DQorCQkgIiUuMTBzLSUuMTVzIiwgaGRyLT5md192ZXIsIGhkci0+YnVpbGRfZGF0ZSk7DQorDQor b3V0Og0KKwlyZWxlYXNlX2Zpcm13YXJlKGZ3KTsNCisNCisJcmV0dXJuIHJldDsNCit9DQorDQor c3RhdGljIGludCBtdDc5MTVfbG9hZF9maXJtd2FyZShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KQ0K K3sNCisJaW50IHJldDsNCisJdTMyIHZhbCwgcmVnID0gbXQ3OTE1X3JlZ19tYXBfbDEoZGV2LCBN VF9UT1BfTUlTQyk7DQorDQorCXZhbCA9IEZJRUxEX1BSRVAoTVRfVE9QX01JU0NfRldfU1RBVEUs IEZXX1NUQVRFX0ZXX0RPV05MT0FEKTsNCisNCisJaWYgKCFtdDc2X3BvbGxfbXNlYyhkZXYsIHJl ZywgTVRfVE9QX01JU0NfRldfU1RBVEUsIHZhbCwgMTAwMCkpIHsNCisJCS8qIHJlc3RhcnQgZmly bXdhcmUgb25jZSAqLw0KKwkJX19tdDc2X21jdV9yZXN0YXJ0KCZkZXYtPm10NzYpOw0KKwkJaWYg KCFtdDc2X3BvbGxfbXNlYyhkZXYsIHJlZywgTVRfVE9QX01JU0NfRldfU1RBVEUsDQorCQkJCSAg ICB2YWwsIDEwMDApKSB7DQorCQkJZGV2X2VycihkZXYtPm10NzYuZGV2LA0KKwkJCQkiRmlybXdh cmUgaXMgbm90IHJlYWR5IGZvciBkb3dubG9hZFxuIik7DQorCQkJcmV0dXJuIC1FSU87DQorCQl9 DQorCX0NCisNCisJcmV0ID0gbXQ3OTE1X2xvYWRfcGF0Y2goZGV2KTsNCisJaWYgKHJldCkNCisJ CXJldHVybiByZXQ7DQorDQorCXJldCA9IG10NzkxNV9sb2FkX3JhbShkZXYpOw0KKwlpZiAocmV0 KQ0KKwkJcmV0dXJuIHJldDsNCisNCisJaWYgKCFtdDc2X3BvbGxfbXNlYyhkZXYsIHJlZywgTVRf VE9QX01JU0NfRldfU1RBVEUsDQorCQkJICAgIEZJRUxEX1BSRVAoTVRfVE9QX01JU0NfRldfU1RB VEUsDQorCQkJCSAgICAgICBGV19TVEFURV9XQUNQVV9SRFkpLCAxMDAwKSkgew0KKwkJZGV2X2Vy cihkZXYtPm10NzYuZGV2LCAiVGltZW91dCBmb3IgaW5pdGlhbGl6aW5nIGZpcm13YXJlXG4iKTsN CisJCXJldHVybiAtRUlPOw0KKwl9DQorDQorCW10NzZfcXVldWVfdHhfY2xlYW51cChkZXYsIE1U X1RYUV9GV0RMLCBmYWxzZSk7DQorDQorCWRldl9kYmcoZGV2LT5tdDc2LmRldiwgIkZpcm13YXJl IGluaXQgZG9uZVxuIik7DQorDQorCXJldHVybiAwOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9p bml0KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0KKwlzdGF0aWMgY29uc3Qgc3RydWN0IG10 NzZfbWN1X29wcyBtdDc5MTVfbWN1X29wcyA9IHsNCisJCS5oZWFkcm9vbSA9IHNpemVvZihzdHJ1 Y3QgbXQ3OTE1X21jdV90eGQpLA0KKwkJLm1jdV9za2Jfc2VuZF9tc2cgPSBtdDc5MTVfbWN1X3Nl bmRfbWVzc2FnZSwNCisJCS5tY3Vfc2VuZF9tc2cgPSBtdDc5MTVfbWN1X21zZ19zZW5kLA0KKwkJ Lm1jdV9yZXN0YXJ0ID0gbXQ3OTE1X21jdV9yZXN0YXJ0LA0KKwl9Ow0KKwlpbnQgcmV0Ow0KKw0K KwlkZXYtPm10NzYubWN1X29wcyA9ICZtdDc5MTVfbWN1X29wcywNCisNCisJcmV0ID0gbXQ3OTE1 X2RyaXZlcl9vd24oZGV2KTsNCisJaWYgKHJldCkNCisJCXJldHVybiByZXQ7DQorDQorCXJldCA9 IG10NzkxNV9sb2FkX2Zpcm13YXJlKGRldik7DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0Ow0K Kw0KKwlzZXRfYml0KE1UNzZfU1RBVEVfTUNVX1JVTk5JTkcsICZkZXYtPm1waHkuc3RhdGUpOw0K Kw0KKwlyZXR1cm4gMDsNCit9DQorDQordm9pZCBtdDc5MTVfbWN1X2V4aXQoc3RydWN0IG10Nzkx NV9kZXYgKmRldikNCit7DQorCXUzMiByZWcgPSBtdDc5MTVfcmVnX21hcF9sMShkZXYsIE1UX1RP UF9NSVNDKTsNCisNCisJX19tdDc2X21jdV9yZXN0YXJ0KCZkZXYtPm10NzYpOw0KKwlpZiAoIW10 NzZfcG9sbF9tc2VjKGRldiwgcmVnLCBNVF9UT1BfTUlTQ19GV19TVEFURSwNCisJCQkgICAgRklF TERfUFJFUChNVF9UT1BfTUlTQ19GV19TVEFURSwNCisJCQkJICAgICAgIEZXX1NUQVRFX0ZXX0RP V05MT0FEKSwgMTAwMCkpIHsNCisJCWRldl9lcnIoZGV2LT5tdDc2LmRldiwgIkZhaWxlZCB0byBl eGl0IG1jdVxuIik7DQorCQlyZXR1cm47DQorCX0NCisNCisJcmVnID0gbXQ3OTE1X3JlZ19tYXBf bDEoZGV2LCBNVF9UT1BfTFBDUl9IT1NUX0JBTkQwKTsNCisJbXQ3Nl93cihkZXYsIHJlZywgTVRf VE9QX0xQQ1JfSE9TVF9GV19PV04pOw0KKwlza2JfcXVldWVfcHVyZ2UoJmRldi0+bXQ3Ni5tY3Uu cmVzX3EpOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9zZXRfbWFjKHN0cnVjdCBtdDc5MTVfZGV2 ICpkZXYsIGludCBiYW5kLA0KKwkJICAgICAgIGJvb2wgZW5hYmxlLCBib29sIGhkcl90cmFucykN Cit7DQorCXN0cnVjdCB7DQorCQl1OCBvcGVyYXRpb247DQorCQl1OCBlbmFibGU7DQorCQl1OCBj aGVja19ic3NpZDsNCisJCXU4IGluc2VydF92bGFuOw0KKwkJdTggcmVtb3ZlX3ZsYW47DQorCQl1 OCB0aWQ7DQorCQl1OCBtb2RlOw0KKwkJdTggcnN2Ow0KKwl9IF9fcGFja2VkIHJlcV90cmFucyA9 IHsNCisJCS5lbmFibGUgPSBoZHJfdHJhbnMsDQorCX07DQorCXN0cnVjdCB7DQorCQl1OCBlbmFi bGU7DQorCQl1OCBiYW5kOw0KKwkJdTggcnN2WzJdOw0KKwl9IF9fcGFja2VkIHJlcV9tYWMgPSB7 DQorCQkuZW5hYmxlID0gZW5hYmxlLA0KKwkJLmJhbmQgPSBiYW5kLA0KKwl9Ow0KKwlpbnQgcmV0 Ow0KKw0KKwlyZXQgPSBfX210NzZfbWN1X3NlbmRfbXNnKCZkZXYtPm10NzYsIE1DVV9FWFRfQ01E X1JYX0hEUl9UUkFOUywNCisJCQkJICAmcmVxX3RyYW5zLCBzaXplb2YocmVxX3RyYW5zKSwgZmFs c2UpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsNCisNCisJcmV0dXJuIF9fbXQ3Nl9tY3Vf c2VuZF9tc2coJmRldi0+bXQ3NiwgTUNVX0VYVF9DTURfTUFDX0lOSVRfQ1RSTCwNCisJCQkJICAg JnJlcV9tYWMsIHNpemVvZihyZXFfbWFjKSwgdHJ1ZSk7DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1 X3NldF9zY3Moc3RydWN0IG10NzkxNV9kZXYgKmRldiwgdTggYmFuZCwgYm9vbCBlbmFibGUpDQor ew0KKwlzdHJ1Y3Qgew0KKwkJX19sZTMyIGNtZDsNCisJCXU4IGJhbmQ7DQorCQl1OCBlbmFibGU7 DQorCX0gX19wYWNrZWQgcmVxID0gew0KKwkJLmNtZCA9IGNwdV90b19sZTMyKFNDU19FTkFCTEUp LA0KKwkJLmJhbmQgPSBiYW5kLA0KKwkJLmVuYWJsZSA9IGVuYWJsZSArIDEsDQorCX07DQorDQor CXJldHVybiBfX210NzZfbWN1X3NlbmRfbXNnKCZkZXYtPm10NzYsIE1DVV9FWFRfQ01EX1NDU19D VFJMLCAmcmVxLA0KKwkJCQkgICBzaXplb2YocmVxKSwgZmFsc2UpOw0KK30NCisNCitpbnQgbXQ3 OTE1X21jdV9zZXRfcnRzX3RocmVzaChzdHJ1Y3QgbXQ3OTE1X3BoeSAqcGh5LCB1MzIgdmFsKQ0K K3sNCisJc3RydWN0IG10NzkxNV9kZXYgKmRldiA9IHBoeS0+ZGV2Ow0KKwlzdHJ1Y3Qgew0KKwkJ dTggcHJvdF9pZHg7DQorCQl1OCBiYW5kOw0KKwkJdTggcnN2WzJdOw0KKwkJX19sZTMyIGxlbl90 aHJlc2g7DQorCQlfX2xlMzIgcGt0X3RocmVzaDsNCisJfSBfX3BhY2tlZCByZXEgPSB7DQorCQku cHJvdF9pZHggPSAxLA0KKwkJLmJhbmQgPSBwaHkgIT0gJmRldi0+cGh5LA0KKwkJLmxlbl90aHJl c2ggPSBjcHVfdG9fbGUzMih2YWwpLA0KKwkJLnBrdF90aHJlc2ggPSBjcHVfdG9fbGUzMigweDIp LA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5kX21zZygmZGV2LT5tdDc2LCBNQ1Vf RVhUX0NNRF9QUk9URUNUX0NUUkwsDQorCQkJCSAgICZyZXEsIHNpemVvZihyZXEpLCB0cnVlKTsN Cit9DQorDQoraW50IG10NzkxNV9tY3Vfc2V0X3R4KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0 cnVjdCBpZWVlODAyMTFfdmlmICp2aWYpDQorew0KKyNkZWZpbmUgV01NX0FJRlNfU0VUCQlCSVQo MCkNCisjZGVmaW5lIFdNTV9DV19NSU5fU0VUCQlCSVQoMSkNCisjZGVmaW5lIFdNTV9DV19NQVhf U0VUCQlCSVQoMikNCisjZGVmaW5lIFdNTV9UWE9QX1NFVAkJQklUKDMpDQorI2RlZmluZSBXTU1f UEFSQU1fU0VUCQlHRU5NQVNLKDMsIDApDQorI2RlZmluZSBUWF9DTURfTU9ERQkJMQ0KKwlzdHJ1 Y3QgZWRjYSB7DQorCQl1OCBxdWV1ZTsNCisJCXU4IHNldDsNCisJCXU4IGFpZnM7DQorCQl1OCBj d19taW47DQorCQlfX2xlMTYgY3dfbWF4Ow0KKwkJX19sZTE2IHR4b3A7DQorCX07DQorCXN0cnVj dCBtdDc5MTVfbWN1X3R4IHsNCisJCXU4IHRvdGFsOw0KKwkJdTggYWN0aW9uOw0KKwkJdTggdmFs aWQ7DQorCQl1OCBtb2RlOw0KKw0KKwkJc3RydWN0IGVkY2EgZWRjYVtJRUVFODAyMTFfTlVNX0FD U107DQorCX0gX19wYWNrZWQgcmVxID0gew0KKwkJLnZhbGlkID0gdHJ1ZSwNCisJCS5tb2RlID0g VFhfQ01EX01PREUsDQorCQkudG90YWwgPSBJRUVFODAyMTFfTlVNX0FDUywNCisJfTsNCisJc3Ry dWN0IG10NzkxNV92aWYgKm12aWYgPSAoc3RydWN0IG10NzkxNV92aWYgKil2aWYtPmRydl9wcml2 Ow0KKwlpbnQgYWM7DQorDQorCWZvciAoYWMgPSAwOyBhYyA8IElFRUU4MDIxMV9OVU1fQUNTOyBh YysrKSB7DQorCQlzdHJ1Y3QgZWRjYSAqZSA9ICZyZXEuZWRjYVthY107DQorDQorCQllLT5xdWV1 ZSA9IGFjICsgbXZpZi0+d21tX2lkeCAqIE1UNzkxNV9NQVhfV01NX1NFVFM7DQorCQllLT5haWZz ID0gbXZpZi0+d21tW2FjXS5haWZzOw0KKwkJZS0+dHhvcCA9IGNwdV90b19sZTE2KG12aWYtPndt bVthY10udHhvcCk7DQorDQorCQlpZiAobXZpZi0+d21tW2FjXS5jd19taW4pDQorCQkJZS0+Y3df bWluID0gZmxzKG12aWYtPndtbVthY10uY3dfbWF4KTsNCisJCWVsc2UNCisJCQllLT5jd19taW4g PSA1Ow0KKw0KKwkJaWYgKG12aWYtPndtbVthY10uY3dfbWF4KQ0KKwkJCWUtPmN3X21heCA9IGNw dV90b19sZTE2KGZscyhtdmlmLT53bW1bYWNdLmN3X21heCkpOw0KKwkJZWxzZQ0KKwkJCWUtPmN3 X21heCA9IGNwdV90b19sZTE2KDEwKTsNCisJfQ0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5k X21zZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9FRENBX1VQREFURSwNCisJCQkJICAmcmVxLCBz aXplb2YocmVxKSwgdHJ1ZSk7DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1X3NldF9wbShzdHJ1Y3Qg bXQ3OTE1X2RldiAqZGV2LCBpbnQgYmFuZCwgaW50IGVudGVyKQ0KK3sNCisjZGVmaW5lIEVOVEVS X1BNX1NUQVRFCQkxDQorI2RlZmluZSBFWElUX1BNX1NUQVRFCQkyDQorCXN0cnVjdCB7DQorCQl1 OCBwbV9udW1iZXI7DQorCQl1OCBwbV9zdGF0ZTsNCisJCXU4IGJzc2lkW0VUSF9BTEVOXTsNCisJ CXU4IGR0aW1fcGVyaW9kOw0KKwkJdTggd2xhbl9pZHhfbG87DQorCQlfX2xlMTYgYmNuX2ludGVy dmFsOw0KKwkJX19sZTMyIGFpZDsNCisJCV9fbGUzMiByeF9maWx0ZXI7DQorCQl1OCBiYW5kX2lk eDsNCisJCXU4IHdsYW5faWR4X2hpOw0KKwkJdTggcnN2WzJdOw0KKwkJX19sZTMyIGZlYXR1cmU7 DQorCQl1OCBvbWFjX2lkeDsNCisJCXU4IHdtbV9pZHg7DQorCQl1OCBiY25fbG9zc19jbnQ7DQor CQl1OCBiY25fc3BfZHVyYXRpb247DQorCX0gX19wYWNrZWQgcmVxID0gew0KKwkJLnBtX251bWJl ciA9IDUsDQorCQkucG1fc3RhdGUgPSAoZW50ZXIpID8gRU5URVJfUE1fU1RBVEUgOiBFWElUX1BN X1NUQVRFLA0KKwkJLmJhbmRfaWR4ID0gYmFuZCwNCisJfTsNCisNCisJcmV0dXJuIF9fbXQ3Nl9t Y3Vfc2VuZF9tc2coJmRldi0+bXQ3NiwgTUNVX0VYVF9DTURfUE1fU1RBVEVfQ1RSTCwNCisJCQkJ ICAgJnJlcSwgc2l6ZW9mKHJlcSksIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9yZGRf Y21kKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsDQorCQkgICAgICAgZW51bSBtdDc5MTVfcmRkX2Nt ZCBjbWQsIHU4IGluZGV4LA0KKwkJICAgICAgIHU4IHJ4X3NlbCwgdTggdmFsKQ0KK3sNCisJc3Ry dWN0IHsNCisJCXU4IGN0cmw7DQorCQl1OCByZGRfaWR4Ow0KKwkJdTggcmRkX3J4X3NlbDsNCisJ CXU4IHZhbDsNCisJCXU4IHJzdls0XTsNCisJfSBfX3BhY2tlZCByZXEgPSB7DQorCQkuY3RybCA9 IGNtZCwNCisJCS5yZGRfaWR4ID0gaW5kZXgsDQorCQkucmRkX3J4X3NlbCA9IHJ4X3NlbCwNCisJ CS52YWwgPSB2YWwsDQorCX07DQorDQorCXJldHVybiBfX210NzZfbWN1X3NlbmRfbXNnKCZkZXYt Pm10NzYsIE1DVV9FWFRfQ01EX1NFVF9SRERfQ1RSTCwNCisJCQkJICAgJnJlcSwgc2l6ZW9mKHJl cSksIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9zZXRfZmNjNV9scG4oc3RydWN0IG10 NzkxNV9kZXYgKmRldiwgaW50IHZhbCkNCit7DQorCXN0cnVjdCB7DQorCQl1MzIgdGFnOw0KKwkJ dTE2IG1pbl9scG47DQorCQl1OCByc3ZbMl07DQorCX0gX19wYWNrZWQgcmVxID0gew0KKwkJLnRh ZyA9IDB4MSwNCisJCS5taW5fbHBuID0gdmFsLA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19tdDc2X21j dV9zZW5kX21zZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9TRVRfUkREX1RILA0KKwkJCQkgICAm cmVxLCBzaXplb2YocmVxKSwgdHJ1ZSk7DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1X3NldF9wdWxz ZV90aChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LA0KKwkJCSAgICBjb25zdCBzdHJ1Y3QgbXQ3OTE1 X2Rmc19wdWxzZSAqcHVsc2UpDQorew0KKwlzdHJ1Y3Qgew0KKwkJdTMyIHRhZzsNCisJCXN0cnVj dCBtdDc5MTVfZGZzX3B1bHNlIHB1bHNlOw0KKwl9IF9fcGFja2VkIHJlcSA9IHsNCisJCS50YWcg PSAweDMsDQorCX07DQorDQorCW1lbWNweSgmcmVxLnB1bHNlLCBwdWxzZSwgc2l6ZW9mKCpwdWxz ZSkpOw0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5kX21zZygmZGV2LT5tdDc2LCBNQ1VfRVhU X0NNRF9TRVRfUkREX1RILA0KKwkJCQkgICAmcmVxLCBzaXplb2YocmVxKSwgdHJ1ZSk7DQorfQ0K Kw0KK2ludCBtdDc5MTVfbWN1X3NldF9yYWRhcl90aChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBp bnQgaW5kZXgsDQorCQkJICAgIGNvbnN0IHN0cnVjdCBtdDc5MTVfZGZzX3BhdHRlcm4gKnBhdHRl cm4pDQorew0KKwlzdHJ1Y3Qgew0KKwkJdTMyIHRhZzsNCisJCXUxNiByYWRhcl90eXBlOw0KKwkJ c3RydWN0IG10NzkxNV9kZnNfcGF0dGVybiBwYXR0ZXJuOw0KKwl9IF9fcGFja2VkIHJlcSA9IHsN CisJCS50YWcgPSAweDIsDQorCQkucmFkYXJfdHlwZSA9IGluZGV4LA0KKwl9Ow0KKw0KKwltZW1j cHkoJnJlcS5wYXR0ZXJuLCBwYXR0ZXJuLCBzaXplb2YoKnBhdHRlcm4pKTsNCisNCisJcmV0dXJu IF9fbXQ3Nl9tY3Vfc2VuZF9tc2coJmRldi0+bXQ3NiwgTUNVX0VYVF9DTURfU0VUX1JERF9USCwN CisJCQkJICAgJnJlcSwgc2l6ZW9mKHJlcSksIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1X21j dV9zZXRfY2hhbl9pbmZvKHN0cnVjdCBtdDc5MTVfcGh5ICpwaHksIGludCBjbWQpDQorew0KKwlz dHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0gcGh5LT5kZXY7DQorCXN0cnVjdCBjZmc4MDIxMV9jaGFu X2RlZiAqY2hhbmRlZiA9ICZwaHktPm10NzYtPmNoYW5kZWY7DQorCWludCBmcmVxMSA9IGNoYW5k ZWYtPmNlbnRlcl9mcmVxMTsNCisJc3RydWN0IHsNCisJCXU4IGNvbnRyb2xfY2g7DQorCQl1OCBj ZW50ZXJfY2g7DQorCQl1OCBidzsNCisJCXU4IHR4X3N0cmVhbXNfbnVtOw0KKwkJdTggcnhfc3Ry ZWFtczsJLyogbWFzayBvciBudW0gKi8NCisJCXU4IHN3aXRjaF9yZWFzb247DQorCQl1OCBiYW5k X2lkeDsNCisJCXU4IGNlbnRlcl9jaDI7CS8qIGZvciA4MCs4MCBvbmx5ICovDQorCQlfX2xlMTYg Y2FjX2Nhc2U7DQorCQl1OCBjaGFubmVsX2JhbmQ7DQorCQl1OCByc3YwOw0KKwkJX19sZTMyIG91 dGJhbmRfZnJlcTsNCisJCXU4IHR4cG93ZXJfZHJvcDsNCisJCXU4IGFwX2J3Ow0KKwkJdTggYXBf Y2VudGVyX2NoOw0KKwkJdTggcnN2MVs1N107DQorCX0gX19wYWNrZWQgcmVxID0gew0KKwkJLmNv bnRyb2xfY2ggPSBjaGFuZGVmLT5jaGFuLT5od192YWx1ZSwNCisJCS5jZW50ZXJfY2ggPSBpZWVl ODAyMTFfZnJlcXVlbmN5X3RvX2NoYW5uZWwoZnJlcTEpLA0KKwkJLmJ3ID0gbXQ3OTE1X21jdV9j aGFuX2J3KGNoYW5kZWYpLA0KKwkJLnR4X3N0cmVhbXNfbnVtID0gaHdlaWdodDgocGh5LT5tdDc2 LT5hbnRlbm5hX21hc2spLA0KKwkJLnJ4X3N0cmVhbXMgPSBwaHktPmNoYWlubWFzaywNCisJCS5i YW5kX2lkeCA9IHBoeSAhPSAmZGV2LT5waHksDQorCQkuY2hhbm5lbF9iYW5kID0gY2hhbmRlZi0+ Y2hhbi0+YmFuZCwNCisJfTsNCisNCisJaWYgKChjaGFuZGVmLT5jaGFuLT5mbGFncyAmIElFRUU4 MDIxMV9DSEFOX1JBREFSKSAmJg0KKwkgICAgY2hhbmRlZi0+Y2hhbi0+ZGZzX3N0YXRlICE9IE5M ODAyMTFfREZTX0FWQUlMQUJMRSkNCisJCXJlcS5zd2l0Y2hfcmVhc29uID0gQ0hfU1dJVENIX0RG UzsNCisJZWxzZQ0KKwkJcmVxLnN3aXRjaF9yZWFzb24gPSBDSF9TV0lUQ0hfTk9STUFMOw0KKw0K KwlpZiAoY21kID09IE1DVV9FWFRfQ01EX0NIQU5ORUxfU1dJVENIKQ0KKwkJcmVxLnJ4X3N0cmVh bXMgPSBod2VpZ2h0OChyZXEucnhfc3RyZWFtcyk7DQorDQorCWlmIChjaGFuZGVmLT53aWR0aCA9 PSBOTDgwMjExX0NIQU5fV0lEVEhfODBQODApIHsNCisJCWludCBmcmVxMiA9IGNoYW5kZWYtPmNl bnRlcl9mcmVxMjsNCisNCisJCXJlcS5jZW50ZXJfY2gyID0gaWVlZTgwMjExX2ZyZXF1ZW5jeV90 b19jaGFubmVsKGZyZXEyKTsNCisJfQ0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5kX21zZygm ZGV2LT5tdDc2LCBjbWQsICZyZXEsIHNpemVvZihyZXEpLCB0cnVlKTsNCit9DQorDQoraW50IG10 NzkxNV9tY3Vfc2V0X2VlcHJvbShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KQ0KK3sNCisJc3RydWN0 IHJlcV9oZHIgew0KKwkJdTggYnVmZmVyX21vZGU7DQorCQl1OCBmb3JtYXQ7DQorCQlfX2xlMTYg bGVuOw0KKwl9IF9fcGFja2VkIHJlcSA9IHsNCisJCS5idWZmZXJfbW9kZSA9IEVFX01PREVfRUZV U0UsDQorCQkuZm9ybWF0ID0gRUVfRk9STUFUX1dIT0xFLA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19t dDc2X21jdV9zZW5kX21zZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9FRlVTRV9CVUZGRVJfTU9E RSwNCisJCQkJICAgJnJlcSwgc2l6ZW9mKHJlcSksIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1 X21jdV9nZXRfZWVwcm9tKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBvZmZzZXQpDQorew0K KwlzdHJ1Y3QgbXQ3OTE1X21jdV9lZXByb21faW5mbyByZXEgPSB7DQorCQkuYWRkciA9IGNwdV90 b19sZTMyKHJvdW5kX2Rvd24ob2Zmc2V0LCAxNikpLA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19tdDc2 X21jdV9zZW5kX21zZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9FRlVTRV9BQ0NFU1MsICZyZXEs DQorCQkJCSAgIHNpemVvZihyZXEpLCB0cnVlKTsNCit9DQorDQoraW50IG10NzkxNV9tY3VfZ2V0 X3RlbXBlcmF0dXJlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIGludCBpbmRleCkNCit7DQorCXN0 cnVjdCB7DQorCQl1OCBjdHJsX2lkOw0KKwkJdTggYWN0aW9uOw0KKwkJdTggYmFuZDsNCisJCXU4 IHJzdls1XTsNCisJfSByZXEgPSB7DQorCQkuY3RybF9pZCA9IFRIRVJNQUxfU0VOU09SX1RFTVBf UVVFUlksDQorCQkuYWN0aW9uID0gaW5kZXgsDQorCX07DQorDQorCXJldHVybiBfX210NzZfbWN1 X3NlbmRfbXNnKCZkZXYtPm10NzYsIE1DVV9FWFRfQ01EX1RIRVJNQUxfQ1RSTCwgJnJlcSwNCisJ CQkJICAgc2l6ZW9mKHJlcSksIHRydWUpOw0KK30NCisNCitpbnQgbXQ3OTE1X21jdV9nZXRfcmF0 ZV9pbmZvKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBjbWQsIHUxNiB3bGFuX2lkeCkNCit7 DQorCXN0cnVjdCB7DQorCQlfX2xlMzIgY21kOw0KKwkJdTE2IHdsYW5faWR4Ow0KKwkJdTE2IHJ1 X2lkeDsNCisJCXUxNiBkaXJlY3Rpb247DQorCQl1MTYgZHVtcF9ncm91cDsNCisJfSByZXEgPSB7 DQorCQkuY21kID0gY3B1X3RvX2xlMzIoY21kKSwNCisJCS53bGFuX2lkeCA9IHdsYW5faWR4LA0K KwkJLmR1bXBfZ3JvdXAgPSAxLA0KKwl9Ow0KKw0KKwlyZXR1cm4gX19tdDc2X21jdV9zZW5kX21z ZygmZGV2LT5tdDc2LCBNQ1VfRVhUX0NNRF9SQVRFX0NUUkwsICZyZXEsDQorCQkJCSAgIHNpemVv ZihyZXEpLCBmYWxzZSk7DQorfQ0KKw0KK2ludCBtdDc5MTVfbWN1X3NldF9zZXIoc3RydWN0IG10 NzkxNV9kZXYgKmRldiwgdTggYWN0aW9uLCB1OCBzZXQsIHU4IGJhbmQpDQorew0KKwlzdHJ1Y3Qg ew0KKwkJdTggYWN0aW9uOw0KKwkJdTggc2V0Ow0KKwkJdTggYmFuZDsNCisJCXU4IHJzdjsNCisJ fSByZXEgPSB7DQorCQkuYWN0aW9uID0gYWN0aW9uLA0KKwkJLnNldCA9IHNldCwNCisJCS5iYW5k ID0gYmFuZCwNCisJfTsNCisNCisJcmV0dXJuIF9fbXQ3Nl9tY3Vfc2VuZF9tc2coJmRldi0+bXQ3 NiwgTUNVX0VYVF9DTURfU0VUX1NFUl9UUklHR0VSLA0KKwkJCQkgICAmcmVxLCBzaXplb2YocmVx KSwgZmFsc2UpOw0KK30NCmRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRl ay9tdDc2L210NzkxNS9tY3UuaCBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYv bXQ3OTE1L21jdS5oDQpuZXcgZmlsZSBtb2RlIDEwMDY0NA0KaW5kZXggMDAwMDAwMDAwMDAwLi41 ZTQ3MDg4NjFlZGUNCi0tLSAvZGV2L251bGwNCisrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21l ZGlhdGVrL210NzYvbXQ3OTE1L21jdS5oDQpAQCAtMCwwICsxLDgzNyBAQA0KKy8qIFNQRFgtTGlj ZW5zZS1JZGVudGlmaWVyOiBJU0MgKi8NCisvKiBDb3B5cmlnaHQgKEMpIDIwMjAgTWVkaWFUZWsg SW5jLiAqLw0KKw0KKyNpZm5kZWYgX19NVDc5MTVfTUNVX0gNCisjZGVmaW5lIF9fTVQ3OTE1X01D VV9IDQorDQorc3RydWN0IG10NzkxNV9tY3VfdHhkIHsNCisJX19sZTMyIHR4ZFs4XTsNCisNCisJ X19sZTE2IGxlbjsNCisJX19sZTE2IHBxX2lkOw0KKw0KKwl1OCBjaWQ7DQorCXU4IHBrdF90eXBl Ow0KKwl1OCBzZXRfcXVlcnk7IC8qIEZXIGRvbid0IGNhcmUgKi8NCisJdTggc2VxOw0KKw0KKwl1 OCB1Y19kMmIwX3JldjsNCisJdTggZXh0X2NpZDsNCisJdTggczJkX2luZGV4Ow0KKwl1OCBleHRf Y2lkX2FjazsNCisNCisJdTMyIHJlc2VydmVkWzVdOw0KK30gX19wYWNrZWQgX19hbGlnbmVkKDQp Ow0KKw0KKy8qIGV2ZW50IHRhYmxlICovDQorZW51bSB7DQorCU1DVV9FVkVOVF9UQVJHRVRfQURE UkVTU19MRU4gPSAweDAxLA0KKwlNQ1VfRVZFTlRfRldfU1RBUlQgPSAweDAxLA0KKwlNQ1VfRVZF TlRfR0VORVJJQyA9IDB4MDEsDQorCU1DVV9FVkVOVF9BQ0NFU1NfUkVHID0gMHgwMiwNCisJTUNV X0VWRU5UX01UX1BBVENIX1NFTSA9IDB4MDQsDQorCU1DVV9FVkVOVF9DSF9QUklWSUxFR0UgPSAw eDE4LA0KKwlNQ1VfRVZFTlRfRVhUID0gMHhlZCwNCisJTUNVX0VWRU5UX1JFU1RBUlRfREwgPSAw eGVmLA0KK307DQorDQorLyogZXh0IGV2ZW50IHRhYmxlICovDQorZW51bSB7DQorCU1DVV9FWFRf RVZFTlRfUFNfU1lOQyA9IDB4NSwNCisJTUNVX0VYVF9FVkVOVF9USEVSTUFMX1BST1RFQ1QgPSAw eDIyLA0KKwlNQ1VfRVhUX0VWRU5UX0FTU0VSVF9EVU1QID0gMHgyMywNCisJTUNVX0VYVF9FVkVO VF9SRERfUkVQT1JUID0gMHgzYSwNCisJTUNVX0VYVF9FVkVOVF9DU0FfTk9USUZZID0gMHg0ZiwN CisJTUNVX0VYVF9FVkVOVF9SQVRFX1JFUE9SVCA9IDB4ODcsDQorfTsNCisNCitzdHJ1Y3QgbXQ3 OTE1X21jdV9yeGQgew0KKwlfX2xlMzIgcnhkWzZdOw0KKw0KKwlfX2xlMTYgbGVuOw0KKwlfX2xl MTYgcGt0X3R5cGVfaWQ7DQorDQorCXU4IGVpZDsNCisJdTggc2VxOw0KKwlfX2xlMTYgX19yc3Y7 DQorDQorCXU4IGV4dF9laWQ7DQorCXU4IF9fcnN2MVsyXTsNCisJdTggczJkX2luZGV4Ow0KK307 DQorDQorc3RydWN0IG10NzkxNV9tY3VfcmRkX3JlcG9ydCB7DQorCXN0cnVjdCBtdDc5MTVfbWN1 X3J4ZCByeGQ7DQorDQorCXU4IGlkeDsNCisJdTggbG9uZ19kZXRlY3RlZDsNCisJdTggY29uc3Rh bnRfcHJmX2RldGVjdGVkOw0KKwl1OCBzdGFnZ2VyZWRfcHJmX2RldGVjdGVkOw0KKwl1OCByYWRh cl90eXBlX2lkeDsNCisJdTggcGVyaW9kaWNfcHVsc2VfbnVtOw0KKwl1OCBsb25nX3B1bHNlX251 bTsNCisJdTggaHdfcHVsc2VfbnVtOw0KKw0KKwl1OCBvdXRfbHBuOw0KKwl1OCBvdXRfc3BuOw0K Kwl1OCBvdXRfY3JwbjsNCisJdTggb3V0X2NycHc7DQorCXU4IG91dF9jcmJuOw0KKwl1OCBvdXRf c3RncG47DQorCXU4IG91dF9zdGdwdzsNCisNCisJdTggcnN2Ow0KKw0KKwlfX2xlMzIgb3V0X3By aV9jb25zdDsNCisJX19sZTMyIG91dF9wcmlfc3RnWzNdOw0KKw0KKwlzdHJ1Y3Qgew0KKwkJX19s ZTMyIHN0YXJ0Ow0KKwkJX19sZTE2IHB1bHNlX3dpZHRoOw0KKwkJX19sZTE2IHB1bHNlX3Bvd2Vy Ow0KKwkJdTggbWRyZHlfZmxhZzsNCisJCXU4IHJzdlszXTsNCisJfSBsb25nX3B1bHNlWzMyXTsN CisNCisJc3RydWN0IHsNCisJCV9fbGUzMiBzdGFydDsNCisJCV9fbGUxNiBwdWxzZV93aWR0aDsN CisJCV9fbGUxNiBwdWxzZV9wb3dlcjsNCisJCXU4IG1kcmR5X2ZsYWc7DQorCQl1OCByc3ZbM107 DQorCX0gcGVyaW9kaWNfcHVsc2VbMzJdOw0KKw0KKwlzdHJ1Y3Qgew0KKwkJX19sZTMyIHN0YXJ0 Ow0KKwkJX19sZTE2IHB1bHNlX3dpZHRoOw0KKwkJX19sZTE2IHB1bHNlX3Bvd2VyOw0KKwkJdTgg c2NfcGFzczsNCisJCXU4IHN3X3Jlc2V0Ow0KKwkJdTggbWRyZHlfZmxhZzsNCisJCXU4IHR4X2Fj dGl2ZTsNCisJfSBod19wdWxzZVszMl07DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3QgbXQ3OTE1 X21jdV9lZXByb21faW5mbyB7DQorCV9fbGUzMiBhZGRyOw0KKwlfX2xlMzIgdmFsaWQ7DQorCXU4 IGRhdGFbMTZdOw0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IG10NzkxNV9tY3VfcmFfaW5mbyB7 DQorCXN0cnVjdCBtdDc5MTVfbWN1X3J4ZCByeGQ7DQorDQorCV9fbGUzMiBldmVudF9pZDsNCisJ X19sZTE2IHdsYW5faWR4Ow0KKwlfX2xlMTYgcnVfaWR4Ow0KKwlfX2xlMTYgZGlyZWN0aW9uOw0K KwlfX2xlMTYgZHVtcF9ncm91cDsNCisNCisJX19sZTMyIHN1Z2dlc3RfcmF0ZTsNCisJX19sZTMy IG1pbl9yYXRlOwkvKiBmb3IgZHluYW1pYyBzb3VuZGluZyAqLw0KKwlfX2xlMzIgbWF4X3JhdGU7 CS8qIGZvciBkeW5hbWljIHNvdW5kaW5nICovDQorCV9fbGUzMiBpbml0X3JhdGVfZG93bl9yYXRl Ow0KKw0KKwlfX2xlMTYgY3Vycl9yYXRlOw0KKwlfX2xlMTYgaW5pdF9yYXRlX2Rvd25fdG90YWw7 DQorCV9fbGUxNiBpbml0X3JhdGVfZG93bl9zdWNjOw0KKwlfX2xlMTYgc3VjY2VzczsNCisJX19s ZTE2IGF0dGVtcHRzOw0KKw0KKwlfX2xlMTYgcHJldl9yYXRlOw0KKwlfX2xlMTYgcHJvYl91cF9y YXRlOw0KKwl1OCBub19yYXRlX3VwX2NudDsNCisJdTggcHBkdV9jbnQ7DQorCXU4IGdpOw0KKw0K Kwl1OCB0cnlfdXBfZmFpbDsNCisJdTggdHJ5X3VwX3RvdGFsOw0KKwl1OCBzdWdnZXN0X3dmOw0K Kwl1OCB0cnlfdXBfY2hlY2s7DQorCXU4IHByb2JfdXBfcGVyaW9kOw0KKwl1OCBwcm9iX2Rvd25f cGVuZGluZzsNCit9IF9fcGFja2VkOw0KKw0KKyNkZWZpbmUgTVRfUkFfUkFURV9OU1MJCQlHRU5N QVNLKDgsIDYpDQorI2RlZmluZSBNVF9SQV9SQVRFX01DUwkJCUdFTk1BU0soMywgMCkNCisjZGVm aW5lIE1UX1JBX1JBVEVfVFhfTU9ERQkJR0VOTUFTSygxMiwgOSkNCisjZGVmaW5lIE1UX1JBX1JB VEVfRENNX0VOCQlCSVQoNCkNCisjZGVmaW5lIE1UX1JBX1JBVEVfQlcJCQlHRU5NQVNLKDE0LCAx MykNCisNCisjZGVmaW5lIE1DVV9QUV9JRChwLCBxKQkJCSgoKHApIDw8IDE1KSB8ICgocSkgPDwg MTApKQ0KKyNkZWZpbmUgTUNVX1BLVF9JRAkJCTB4YTANCisNCitlbnVtIHsNCisJTUNVX1FfUVVF UlksDQorCU1DVV9RX1NFVCwNCisJTUNVX1FfUkVTRVJWRUQsDQorCU1DVV9RX05BDQorfTsNCisN CitlbnVtIHsNCisJTUNVX1MyRF9IMk4sDQorCU1DVV9TMkRfQzJOLA0KKwlNQ1VfUzJEX0gyQywN CisJTUNVX1MyRF9IMkNODQorfTsNCisNCitlbnVtIHsNCisJTUNVX0NNRF9UQVJHRVRfQUREUkVT U19MRU5fUkVRID0gMHgwMSwNCisJTUNVX0NNRF9GV19TVEFSVF9SRVEgPSAweDAyLA0KKwlNQ1Vf Q01EX0lOSVRfQUNDRVNTX1JFRyA9IDB4MywNCisJTUNVX0NNRF9OSUNfUE9XRVJfQ1RSTCA9IDB4 NCwNCisJTUNVX0NNRF9QQVRDSF9TVEFSVF9SRVEgPSAweDA1LA0KKwlNQ1VfQ01EX1BBVENIX0ZJ TklTSF9SRVEgPSAweDA3LA0KKwlNQ1VfQ01EX1BBVENIX1NFTV9DT05UUk9MID0gMHgxMCwNCisJ TUNVX0NNRF9FWFRfQ0lEID0gMHhFRCwNCisJTUNVX0NNRF9GV19TQ0FUVEVSID0gMHhFRSwNCisJ TUNVX0NNRF9SRVNUQVJUX0RMX1JFUSA9IDB4RUYsDQorfTsNCisNCitlbnVtIHsNCisJTUNVX0VY VF9DTURfRUZVU0VfQUNDRVNTID0gMHgwMSwNCisJTUNVX0VYVF9DTURfUE1fU1RBVEVfQ1RSTCA9 IDB4MDcsDQorCU1DVV9FWFRfQ01EX0NIQU5ORUxfU1dJVENIID0gMHgwOCwNCisJTUNVX0VYVF9D TURfRUZVU0VfQlVGRkVSX01PREUgPSAweDIxLA0KKwlNQ1VfRVhUX0NNRF9TVEFfUkVDX1VQREFU RSA9IDB4MjUsDQorCU1DVV9FWFRfQ01EX0JTU19JTkZPX1VQREFURSA9IDB4MjYsDQorCU1DVV9F WFRfQ01EX0VEQ0FfVVBEQVRFID0gMHgyNywNCisJTUNVX0VYVF9DTURfREVWX0lORk9fVVBEQVRF ID0gMHgyQSwNCisJTUNVX0VYVF9DTURfVEhFUk1BTF9DVFJMID0gMHgyYywNCisJTUNVX0VYVF9D TURfU0VUX1JERF9DVFJMID0gMHgzYSwNCisJTUNVX0VYVF9DTURfUFJPVEVDVF9DVFJMID0gMHgz ZSwNCisJTUNVX0VYVF9DTURfTUFDX0lOSVRfQ1RSTCA9IDB4NDYsDQorCU1DVV9FWFRfQ01EX1JY X0hEUl9UUkFOUyA9IDB4NDcsDQorCU1DVV9FWFRfQ01EX1NFVF9SWF9QQVRIID0gMHg0ZSwNCisJ TUNVX0VYVF9DTURfU0VUX1NFUl9UUklHR0VSID0gMHg4MSwNCisJTUNVX0VYVF9DTURfU0NTX0NU UkwgPSAweDgyLA0KKwlNQ1VfRVhUX0NNRF9SQVRFX0NUUkwgPSAweDg3LA0KKwlNQ1VfRVhUX0NN RF9TRVRfUkREX1RIID0gMHg5ZCwNCit9Ow0KKw0KK2VudW0gew0KKwlQQVRDSF9TRU1fUkVMRUFT RSwNCisJUEFUQ0hfU0VNX0dFVA0KK307DQorDQorZW51bSB7DQorCVBBVENIX05PVF9ETF9TRU1f RkFJTCwNCisJUEFUQ0hfSVNfREwsDQorCVBBVENIX05PVF9ETF9TRU1fU1VDQ0VTUywNCisJUEFU Q0hfUkVMX1NFTV9TVUNDRVNTDQorfTsNCisNCitlbnVtIHsNCisJRldfU1RBVEVfSU5JVElBTCwN CisJRldfU1RBVEVfRldfRE9XTkxPQUQsDQorCUZXX1NUQVRFX05PUk1BTF9PUEVSQVRJT04sDQor CUZXX1NUQVRFX05PUk1BTF9UUlgsDQorCUZXX1NUQVRFX1dBQ1BVX1JEWSAgICAgICAgPSA3DQor fTsNCisNCitlbnVtIHsNCisJRUVfTU9ERV9FRlVTRSwNCisJRUVfTU9ERV9CVUZGRVIsDQorfTsN CisNCitlbnVtIHsNCisJRUVfRk9STUFUX0JJTiwNCisJRUVfRk9STUFUX1dIT0xFLA0KKwlFRV9G T1JNQVRfTVVMVElQTEUsDQorfTsNCisNCisjZGVmaW5lIFNUQV9UWVBFX1NUQQkJCUJJVCgwKQ0K KyNkZWZpbmUgU1RBX1RZUEVfQVAJCQlCSVQoMSkNCisjZGVmaW5lIFNUQV9UWVBFX0FESE9DCQkJ QklUKDIpDQorI2RlZmluZSBTVEFfVFlQRV9XRFMJCQlCSVQoNCkNCisjZGVmaW5lIFNUQV9UWVBF X0JDCQkJQklUKDUpDQorDQorI2RlZmluZSBORVRXT1JLX0lORlJBCQkJQklUKDE2KQ0KKyNkZWZp bmUgTkVUV09SS19QMlAJCQlCSVQoMTcpDQorI2RlZmluZSBORVRXT1JLX0lCU1MJCQlCSVQoMTgp DQorI2RlZmluZSBORVRXT1JLX1dEUwkJCUJJVCgyMSkNCisNCisjZGVmaW5lIENPTk5FQ1RJT05f SU5GUkFfU1RBCQkoU1RBX1RZUEVfU1RBIHwgTkVUV09SS19JTkZSQSkNCisjZGVmaW5lIENPTk5F Q1RJT05fSU5GUkFfQVAJCShTVEFfVFlQRV9BUCB8IE5FVFdPUktfSU5GUkEpDQorI2RlZmluZSBD T05ORUNUSU9OX1AyUF9HQwkJKFNUQV9UWVBFX1NUQSB8IE5FVFdPUktfUDJQKQ0KKyNkZWZpbmUg Q09OTkVDVElPTl9QMlBfR08JCShTVEFfVFlQRV9BUCB8IE5FVFdPUktfUDJQKQ0KKyNkZWZpbmUg Q09OTkVDVElPTl9JQlNTX0FESE9DCQkoU1RBX1RZUEVfQURIT0MgfCBORVRXT1JLX0lCU1MpDQor I2RlZmluZSBDT05ORUNUSU9OX1dEUwkJCShTVEFfVFlQRV9XRFMgfCBORVRXT1JLX1dEUykNCisj ZGVmaW5lIENPTk5FQ1RJT05fSU5GUkFfQkMJCShTVEFfVFlQRV9CQyB8IE5FVFdPUktfSU5GUkEp DQorDQorI2RlZmluZSBDT05OX1NUQVRFX0RJU0NPTk5FQ1QJCTANCisjZGVmaW5lIENPTk5fU1RB VEVfQ09OTkVDVAkJMQ0KKyNkZWZpbmUgQ09OTl9TVEFURV9QT1JUX1NFQ1VSRQkJMg0KKw0KK2Vu dW0gew0KKwlERVZfSU5GT19BQ1RJVkUsDQorCURFVl9JTkZPX01BWF9OVU0NCit9Ow0KKw0KK2Vu dW0gew0KKwlTQ1NfU0VORF9EQVRBLA0KKwlTQ1NfU0VUX01BTlVBTF9QRF9USCwNCisJU0NTX0NP TkZJRywNCisJU0NTX0VOQUJMRSwNCisJU0NTX1NIT1dfSU5GTywNCisJU0NTX0dFVF9HTE9fQURE UiwNCisJU0NTX0dFVF9HTE9fQUREUl9FVkVOVCwNCit9Ow0KKw0KK2VudW0gew0KKwlDTURfQ0JX XzIwTUhaID0gSUVFRTgwMjExX1NUQV9SWF9CV18yMCwNCisJQ01EX0NCV180ME1IWiA9IElFRUU4 MDIxMV9TVEFfUlhfQldfNDAsDQorCUNNRF9DQldfODBNSFogPSBJRUVFODAyMTFfU1RBX1JYX0JX XzgwLA0KKwlDTURfQ0JXXzE2ME1IWiA9IElFRUU4MDIxMV9TVEFfUlhfQldfMTYwLA0KKwlDTURf Q0JXXzEwTUhaLA0KKwlDTURfQ0JXXzVNSFosDQorCUNNRF9DQldfODA4ME1IWiwNCisNCisJQ01E X0hFX01DU19CVzgwID0gMCwNCisJQ01EX0hFX01DU19CVzE2MCwNCisJQ01EX0hFX01DU19CVzgw ODAsDQorCUNNRF9IRV9NQ1NfQldfTlVNDQorfTsNCisNCitzdHJ1Y3QgdGx2IHsNCisJX19sZTE2 IHRhZzsNCisJX19sZTE2IGxlbjsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBic3NfaW5mb19v bWFjIHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJdTggaHdfYnNzX2lkeDsNCisJ dTggb21hY19pZHg7DQorCXU4IGJhbmRfaWR4Ow0KKwl1OCByc3YwOw0KKwlfX2xlMzIgY29ubl90 eXBlOw0KKwl1MzIgcnN2MTsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBic3NfaW5mb19iYXNp YyB7DQorCV9fbGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCV9fbGUzMiBuZXR3b3JrX3R5cGU7 DQorCXU4IGFjdGl2ZTsNCisJdTggcnN2MDsNCisJX19sZTE2IGJjbl9pbnRlcnZhbDsNCisJdTgg YnNzaWRbRVRIX0FMRU5dOw0KKwl1OCB3bW1faWR4Ow0KKwl1OCBkdGltX3BlcmlvZDsNCisJdTgg Ym1jX3djaWRfbG87DQorCXU4IGNpcGhlcjsNCisJdTggcGh5X21vZGU7DQorCXU4IG1heF9ic3Np ZDsJLyogbWF4IEJTU0lELiByYW5nZTogMSB+IDgsIDA6IE1CU1NJRCBkaXNhYmxlZCAqLw0KKwl1 OCBub25fdHhfYnNzaWQ7Lyogbm9uLXRyYW5zbWl0dGVkIEJTU0lELCAwOiB0cmFuc21pdHRlZCBC U1NJRCAqLw0KKwl1OCBibWNfd2NpZF9oaTsJLyogaGlnaCBCeXRlIGFuZCB2ZXJzaW9uICovDQor CXU4IHJzdlsyXTsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBic3NfaW5mb19yZl9jaCB7DQor CV9fbGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCXU4IHByaV9jaDsNCisJdTggY2VudGVyX2No MDsNCisJdTggY2VudGVyX2NoMTsNCisJdTggYnc7DQorCXU4IGhlX3J1MjZfYmxvY2s7CS8qIDE6 IGRvbid0IHNlbmQgSEVUQiBpbiBSVTI2LCAwOiBhbGxvdyAqLw0KKwl1OCBoZV9hbGxfZGlzYWJs ZTsJLyogMTogZGlzYWxsb3cgYWxsIEhFVEIsIDA6IGFsbG93ICovDQorCXU4IHJzdlsyXTsNCit9 IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBic3NfaW5mb19leHRfYnNzIHsNCisJX19sZTE2IHRhZzsN CisJX19sZTE2IGxlbjsNCisJX19sZTMyIG1ic3NfdHNmX29mZnNldDsgLyogaW4gdW5pdCBvZiB1 cyAqLw0KKwl1OCByc3ZbOF07DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3QgYnNzX2luZm9fc3lu Y19tb2RlIHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJX19sZTE2IGJjbl9pbnRl cnZhbDsNCisJdTggZW5hYmxlOw0KKwl1OCBkdGltX3BlcmlvZDsNCisJdTggcnN2WzhdOw0KK30g X19wYWNrZWQ7DQorDQorc3RydWN0IGJzc19pbmZvX2JtY19yYXRlIHsNCisJX19sZTE2IHRhZzsN CisJX19sZTE2IGxlbjsNCisJX19sZTE2IGJjX3RyYW5zOw0KKwlfX2xlMTYgbWNfdHJhbnM7DQor CXU4IHNob3J0X3ByZWFtYmxlOw0KKwl1OCByc3ZbN107DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1 Y3QgYnNzX2luZm9fcmEgew0KKwlfX2xlMTYgdGFnOw0KKwlfX2xlMTYgbGVuOw0KKwl1OCBvcF9t b2RlOw0KKwl1OCBhZGhvY19lbjsNCisJdTggc2hvcnRfcHJlYW1ibGU7DQorCXU4IHR4X3N0cmVh bXM7DQorCXU4IHJ4X3N0cmVhbXM7DQorCXU4IGFsZ287DQorCXU4IGZvcmNlX3NnaTsNCisJdTgg Zm9yY2VfZ2Y7DQorCXU4IGh0X21vZGU7DQorCXU4IGhhc18yMF9zdGE7CQkvKiBDaGVjayBpZiBh bnkgc3RhIHN1cHBvcnQgR0YuICovDQorCXU4IGJzc193aWR0aF90cmlnZ2VyX2V2ZW50czsNCisJ dTggdmh0X25zc19jYXA7DQorCXU4IHZodF9id19zaWduYWw7CS8qIG5vdCB1c2UgKi8NCisJdTgg dmh0X2ZvcmNlX3NnaTsJLyogbm90IHVzZSAqLw0KKwl1OCBzZV9vZmY7DQorCXU4IGFudGVubmFf aWR4Ow0KKwl1OCB0cmFpbl91cF9ydWxlOw0KKwl1OCByc3ZbM107DQorCXVuc2lnbmVkIHNob3J0 IHRyYWluX3VwX2hpZ2hfdGhyZXM7DQorCXNob3J0IHRyYWluX3VwX3J1bGVfcnNzaTsNCisJdW5z aWduZWQgc2hvcnQgbG93X3RyYWZmaWNfdGhyZXM7DQorCV9fbGUxNiBtYXhfcGh5cmF0ZTsNCisJ X19sZTMyIHBoeV9jYXA7DQorCV9fbGUzMiBpbnRlcnZhbDsNCisJX19sZTMyIGZhc3RfaW50ZXJ2 YWw7DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3QgYnNzX2luZm9fYmNuIHsNCisJX19sZTE2IHRh ZzsNCisJX19sZTE2IGxlbjsNCisJdTggdmVyOw0KKwl1OCBlbmFibGU7DQorCV9fbGUxNiBzdWJf bnRsdjsNCit9IF9fcGFja2VkIF9fYWxpZ25lZCg0KTsNCisNCitzdHJ1Y3QgYnNzX2luZm9fYmNu X2NzYSB7DQorCV9fbGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCXU4IGNudDsNCisJdTggcnN2 WzNdOw0KK30gX19wYWNrZWQgX19hbGlnbmVkKDQpOw0KKw0KK3N0cnVjdCBic3NfaW5mb19iY25f YmNjIHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJdTggY250Ow0KKwl1OCByc3Zb M107DQorfSBfX3BhY2tlZCBfX2FsaWduZWQoNCk7DQorDQorc3RydWN0IGJzc19pbmZvX2Jjbl9t YnNzIHsNCisjZGVmaW5lIE1BWF9CRUFDT05fTlVNCTMyDQorCV9fbGUxNiB0YWc7DQorCV9fbGUx NiBsZW47DQorCV9fbGUzMiBiaXRtYXA7DQorCV9fbGUxNiBvZmZzZXRbTUFYX0JFQUNPTl9OVU1d Ow0KKwl1OCByc3ZbOF07DQorfSBfX3BhY2tlZCBfX2FsaWduZWQoNCk7DQorDQorc3RydWN0IGJz c19pbmZvX2Jjbl9jb250IHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJX19sZTE2 IHRpbV9vZnM7DQorCV9fbGUxNiBjc2Ffb2ZzOw0KKwlfX2xlMTYgYmNjX29mczsNCisJX19sZTE2 IHBrdF9sZW47DQorfSBfX3BhY2tlZCBfX2FsaWduZWQoNCk7DQorDQorZW51bSB7DQorCUJTU19J TkZPX0JDTl9DU0EsDQorCUJTU19JTkZPX0JDTl9CQ0MsDQorCUJTU19JTkZPX0JDTl9NQlNTSUQs DQorCUJTU19JTkZPX0JDTl9DT05URU5ULA0KKwlCU1NfSU5GT19CQ05fTUFYDQorfTsNCisNCitl bnVtIHsNCisJQlNTX0lORk9fT01BQywNCisJQlNTX0lORk9fQkFTSUMsDQorCUJTU19JTkZPX1JG X0NILAkJLyogb3B0aW9uYWwsIGZvciBCVC9MVEUgY29leCAqLw0KKwlCU1NfSU5GT19QTSwJCS8q IHN0YSBvbmx5ICovDQorCUJTU19JTkZPX1VBUFNELAkJLyogc3RhIG9ubHkgKi8NCisJQlNTX0lO Rk9fUk9BTV9ERVRFQ1QsCS8qIG9ic29sZXRlZCAqLw0KKwlCU1NfSU5GT19MUV9STSwJCS8qIG9i c29sZXRlZCAqLw0KKwlCU1NfSU5GT19FWFRfQlNTLA0KKwlCU1NfSU5GT19CTUNfUkFURSwJLyog Zm9yIGJtYyByYXRlIGNvbnRyb2wgaW4gQ1I0ICovDQorCUJTU19JTkZPX1NZTkNfTU9ERSwNCisJ QlNTX0lORk9fUkEsDQorCUJTU19JTkZPX0hXX0FNU0RVLA0KKwlCU1NfSU5GT19CU1NfQ09MT1Is DQorCUJTU19JTkZPX0hFX0JBU0lDLA0KKwlCU1NfSU5GT19QUk9URUNUX0lORk8sDQorCUJTU19J TkZPX09GRkxPQUQsDQorCUJTU19JTkZPXzExVl9NQlNTSUQsDQorCUJTU19JTkZPX01BWF9OVU0N Cit9Ow0KKw0KK2VudW0gew0KKwlXVEJMX1JFU0VUX0FORF9TRVQgPSAxLA0KKwlXVEJMX1NFVCwN CisJV1RCTF9RVUVSWSwNCisJV1RCTF9SRVNFVF9BTEwNCit9Ow0KKw0KK3N0cnVjdCB3dGJsX3Jl cV9oZHIgew0KKwl1OCB3bGFuX2lkeF9sbzsNCisJdTggb3BlcmF0aW9uOw0KKwlfX2xlMTYgdGx2 X251bTsNCisJdTggd2xhbl9pZHhfaGk7DQorCXU4IHJzdlszXTsNCit9IF9fcGFja2VkOw0KKw0K K3N0cnVjdCB3dGJsX2dlbmVyaWMgew0KKwlfX2xlMTYgdGFnOw0KKwlfX2xlMTYgbGVuOw0KKwl1 OCBwZWVyX2FkZHJbRVRIX0FMRU5dOw0KKwl1OCBtdWFyX2lkeDsNCisJdTggc2tpcF90eDsNCisJ dTggY2ZfYWNrOw0KKwl1OCBxb3M7DQorCXU4IG1lc2g7DQorCXU4IGFkbTsNCisJX19sZTE2IHBh cnRpYWxfYWlkOw0KKwl1OCBiYWZfZW47DQorCXU4IGFhZF9vbTsNCit9IF9fcGFja2VkOw0KKw0K K3N0cnVjdCB3dGJsX3J4IHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJdTggcmNp ZDsNCisJdTggcmNhMTsNCisJdTggcmNhMjsNCisJdTggcnY7DQorCXU4IHJzdls0XTsNCit9IF9f cGFja2VkOw0KKw0KK3N0cnVjdCB3dGJsX2h0IHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxl bjsNCisJdTggaHQ7DQorCXU4IGxkcGM7DQorCXU4IGFmOw0KKwl1OCBtbTsNCisJdTggcnN2WzRd Ow0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHd0Ymxfdmh0IHsNCisJX19sZTE2IHRhZzsNCisJ X19sZTE2IGxlbjsNCisJdTggbGRwYzsNCisJdTggZHluX2J3Ow0KKwl1OCB2aHQ7DQorCXU4IHR4 b3BfcHM7DQorCXU4IHJzdls0XTsNCit9IF9fcGFja2VkOw0KKw0KK2VudW0gew0KKwlNVF9CQV9U WVBFX0lOVkFMSUQsDQorCU1UX0JBX1RZUEVfT1JJR0lOQVRPUiwNCisJTVRfQkFfVFlQRV9SRUNJ UElFTlQNCit9Ow0KKw0KK2VudW0gew0KKwlSU1RfQkFfTUFDX1RJRF9NQVRDSCwNCisJUlNUX0JB X01BQ19NQVRDSCwNCisJUlNUX0JBX05PX01BVENIDQorfTsNCisNCitzdHJ1Y3Qgd3RibF9iYSB7 DQorCV9fbGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCS8qIGNvbW1vbiAqLw0KKwl1OCB0aWQ7 DQorCXU4IGJhX3R5cGU7DQorCXU4IHJzdjBbMl07DQorCS8qIG9yaWdpbmF0b3Igb25seSAqLw0K KwlfX2xlMTYgc247DQorCXU4IGJhX2VuOw0KKwl1OCBiYV93aW5zaXplX2lkeDsNCisJX19sZTE2 IGJhX3dpbnNpemU7DQorCS8qIHJlY2lwaWVudCBvbmx5ICovDQorCXU4IHBlZXJfYWRkcltFVEhf QUxFTl07DQorCXU4IHJzdF9iYV90aWQ7DQorCXU4IHJzdF9iYV9zZWw7DQorCXU4IHJzdF9iYV9z YjsNCisJdTggYmFuZF9pZHg7DQorCXU4IHJzdjFbNF07DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1 Y3Qgd3RibF9iZiB7DQorCV9fbGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCXU4IGliZjsNCisJ dTggZWJmOw0KKwl1OCBpYmZfdmh0Ow0KKwl1OCBlYmZfdmh0Ow0KKwl1OCBnaWQ7DQorCXU4IHBm bXVfaWR4Ow0KKwl1OCByc3ZbMl07DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3Qgd3RibF9zbXBz IHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJdTggc21wczsNCisJdTggcnN2WzNd Ow0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHd0Ymxfc3BlIHsNCisJX19sZTE2IHRhZzsNCisJ X19sZTE2IGxlbjsNCisJdTggc3BlX2lkeDsNCisJdTggcnN2WzNdOw0KK30gX19wYWNrZWQ7DQor DQorZW51bSB7DQorCVdUQkxfR0VORVJJQywNCisJV1RCTF9SWCwNCisJV1RCTF9IVCwNCisJV1RC TF9WSFQsDQorCVdUQkxfUEVFUl9QUywJCS8qIG5vdCB1c2VkICovDQorCVdUQkxfVFhfUFMsDQor CVdUQkxfSERSX1RSQU5TLA0KKwlXVEJMX1NFQ19LRVksDQorCVdUQkxfQkEsDQorCVdUQkxfUkRH LAkJLyogb2Jzb2xldGVkICovDQorCVdUQkxfUFJPVEVDVCwJCS8qIG5vdCB1c2VkICovDQorCVdU QkxfQ0xFQVIsCQkvKiBub3QgdXNlZCAqLw0KKwlXVEJMX0JGLA0KKwlXVEJMX1NNUFMsDQorCVdU QkxfUkFXX0RBVEEsCQkvKiBkZWJ1ZyBvbmx5ICovDQorCVdUQkxfUE4sDQorCVdUQkxfU1BFLA0K KwlXVEJMX01BWF9OVU0NCit9Ow0KKw0KK3N0cnVjdCBzdGFfbnRsdl9oZHIgew0KKwl1OCByc3Zb Ml07DQorCV9fbGUxNiB0bHZfbnVtOw0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHN0YV9yZXFf aGRyIHsNCisJdTggYnNzX2lkeDsNCisJdTggd2xhbl9pZHhfbG87DQorCV9fbGUxNiB0bHZfbnVt Ow0KKwl1OCBpc190bHZfYXBwZW5kOw0KKwl1OCBtdWFyX2lkeDsNCisJdTggd2xhbl9pZHhfaGk7 DQorCXU4IHJzdjsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBzdGFfcmVjX2Jhc2ljIHsNCisJ X19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJX19sZTMyIGNvbm5fdHlwZTsNCisJdTggY29u bl9zdGF0ZTsNCisJdTggcW9zOw0KKwlfX2xlMTYgYWlkOw0KKwl1OCBwZWVyX2FkZHJbRVRIX0FM RU5dOw0KKwlfX2xlMTYgZXh0cmFfaW5mbzsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBzdGFf cmVjX2h0IHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisJX19sZTE2IGh0X2NhcDsN CisJdTE2IHJzdjsNCit9IF9fcGFja2VkOw0KKw0KK3N0cnVjdCBzdGFfcmVjX3ZodCB7DQorCV9f bGUxNiB0YWc7DQorCV9fbGUxNiBsZW47DQorCV9fbGUzMiB2aHRfY2FwOw0KKwlfX2xlMTYgdmh0 X3J4X21jc19tYXA7DQorCV9fbGUxNiB2aHRfdHhfbWNzX21hcDsNCisJdTggcnRzX2J3X3NpZzsN CisJdTggcnN2WzNdOw0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHN0YV9yZWNfYmEgew0KKwlf X2xlMTYgdGFnOw0KKwlfX2xlMTYgbGVuOw0KKwl1OCB0aWQ7DQorCXU4IGJhX3R5cGU7DQorCXU4 IGFtc2R1Ow0KKwl1OCBiYV9lbjsNCisJX19sZTE2IHNzbjsNCisJX19sZTE2IHdpbnNpemU7DQor fSBfX3BhY2tlZDsNCisNCitzdHJ1Y3Qgc2VjX2tleSB7DQorCXU4IGNpcGhlcl9pZDsNCisJdTgg Y2lwaGVyX2xlbjsNCisJdTgga2V5X2lkOw0KKwl1OCBrZXlfbGVuOw0KKwl1OCBrZXlbMzJdOw0K K30gX19wYWNrZWQ7DQorDQorc3RydWN0IHN0YV9yZWNfc2VjIHsNCisJX19sZTE2IHRhZzsNCisJ X19sZTE2IGxlbjsNCisJdTggYWRkOw0KKwl1OCBuX2NpcGhlcjsNCisJdTggcnN2WzJdOw0KKw0K KwlzdHJ1Y3Qgc2VjX2tleSBrZXlbMl07DQorfSBfX3BhY2tlZDsNCisNCitzdHJ1Y3QgcmFfcGh5 IHsNCisJdTggdHlwZTsNCisJdTggZmxhZzsNCisJdTggc3RiYzsNCisJdTggc2dpOw0KKwl1OCBi dzsNCisJdTggbGRwYzsNCisJdTggbWNzOw0KKwl1OCBuc3M7DQorCXU4IGhlX2x0ZjsNCit9Ow0K Kw0KK3N0cnVjdCBzdGFfcmVjX3JhIHsNCisJX19sZTE2IHRhZzsNCisJX19sZTE2IGxlbjsNCisN CisJdTggdmFsaWQ7DQorCXU4IGF1dG9fcmF0ZTsNCisJdTggcGh5X21vZGU7DQorCXU4IGNoYW5u ZWw7DQorCXU4IGJ3Ow0KKwl1OCBkaXNhYmxlX2NjazsNCisJdTggaHRfbWNzMzI7DQorCXU4IGh0 X2dmOw0KKwl1OCBodF9tY3NbNF07DQorCXU4IG1tcHNfbW9kZTsNCisJdTggZ2JhbmRfMjU2Ow0K Kwl1OCBhZjsNCisJdTggYXV0aF93YXBpX21vZGU7DQorCXU4IHJhdGVfbGVuOw0KKw0KKwl1OCBz dXBwX21vZGU7DQorCXU4IHN1cHBfY2NrX3JhdGU7DQorCXU4IHN1cHBfb2ZkbV9yYXRlOw0KKwlf X2xlMzIgc3VwcF9odF9tY3M7DQorCV9fbGUxNiBzdXBwX3ZodF9tY3NbNF07DQorDQorCXU4IG9w X21vZGU7DQorCXU4IG9wX3ZodF9jaGFuX3dpZHRoOw0KKwl1OCBvcF92aHRfcnhfbnNzOw0KKwl1 OCBvcF92aHRfcnhfbnNzX3R5cGU7DQorDQorCV9fbGUzMiBzdGFfc3RhdHVzOw0KKw0KKwlzdHJ1 Y3QgcmFfcGh5IHBoeTsNCit9IF9fcGFja2VkOw0KKw0KK2VudW0gew0KKwlTVEFfUkVDX0JBU0lD LA0KKwlTVEFfUkVDX1JBLA0KKwlTVEFfUkVDX1JBX0NNTV9JTkZPLA0KKwlTVEFfUkVDX1JBX1VQ REFURSwNCisJU1RBX1JFQ19CRiwNCisJU1RBX1JFQ19BTVNEVSwNCisJU1RBX1JFQ19CQSwNCisJ U1RBX1JFQ19SRUQsCQkvKiBub3QgdXNlZCAqLw0KKwlTVEFfUkVDX1RYX1BST0MsCS8qIGZvciBo ZHIgdHJhbnMgYW5kIENTTyBpbiBDUjQgKi8NCisJU1RBX1JFQ19IVCwNCisJU1RBX1JFQ19WSFQs DQorCVNUQV9SRUNfQVBQUywNCisJU1RBX1JFQ19LRVksDQorCVNUQV9SRUNfV1RCTCwNCisJU1RB X1JFQ19IRSwNCisJU1RBX1JFQ19IV19BTVNEVSwNCisJU1RBX1JFQ19XVEJMX0FBRE9NLA0KKwlT VEFfUkVDX0tFWV9WMiwNCisJU1RBX1JFQ19NVVJVLA0KKwlTVEFfUkVDX01VRURDQSwNCisJU1RB X1JFQ19NQVhfTlVNDQorfTsNCisNCitlbnVtIG10NzkxNV9jaXBoZXJfdHlwZSB7DQorCU1UX0NJ UEhFUl9OT05FLA0KKwlNVF9DSVBIRVJfV0VQNDAsDQorCU1UX0NJUEhFUl9XRVAxMDQsDQorCU1U X0NJUEhFUl9XRVAxMjgsDQorCU1UX0NJUEhFUl9US0lQLA0KKwlNVF9DSVBIRVJfQUVTX0NDTVAs DQorCU1UX0NJUEhFUl9DQ01QXzI1NiwNCisJTVRfQ0lQSEVSX0dDTVAsDQorCU1UX0NJUEhFUl9H Q01QXzI1NiwNCisJTVRfQ0lQSEVSX1dBUEksDQorCU1UX0NJUEhFUl9CSVBfQ01BQ18xMjgsDQor fTsNCisNCitlbnVtIHsNCisJQ0hfU1dJVENIX05PUk1BTCA9IDAsDQorCUNIX1NXSVRDSF9TQ0FO ID0gMywNCisJQ0hfU1dJVENIX01DQyA9IDQsDQorCUNIX1NXSVRDSF9ERlMgPSA1LA0KKwlDSF9T V0lUQ0hfQkFDS0dST1VORF9TQ0FOX1NUQVJUID0gNiwNCisJQ0hfU1dJVENIX0JBQ0tHUk9VTkRf U0NBTl9SVU5OSU5HID0gNywNCisJQ0hfU1dJVENIX0JBQ0tHUk9VTkRfU0NBTl9TVE9QID0gOCwN CisJQ0hfU1dJVENIX1NDQU5fQllQQVNTX0RQRCA9IDkNCit9Ow0KKw0KK2VudW0gew0KKwlUSEVS TUFMX1NFTlNPUl9URU1QX1FVRVJZLA0KKwlUSEVSTUFMX1NFTlNPUl9NQU5VQUxfQ1RSTCwNCisJ VEhFUk1BTF9TRU5TT1JfSU5GT19RVUVSWSwNCisJVEhFUk1BTF9TRU5TT1JfVEFTS19DVFJMLA0K K307DQorDQorI2RlZmluZSBNVDc5MTVfV1RCTF9VUERBVEVfTUFYX1NJWkUJKHNpemVvZihzdHJ1 Y3Qgd3RibF9yZXFfaGRyKSArCVwNCisJCQkJCSBzaXplb2Yoc3RydWN0IHd0YmxfZ2VuZXJpYykg KwlcDQorCQkJCQkgc2l6ZW9mKHN0cnVjdCB3dGJsX3J4KSArCVwNCisJCQkJCSBzaXplb2Yoc3Ry dWN0IHd0YmxfaHQpICsJXA0KKwkJCQkJIHNpemVvZihzdHJ1Y3Qgd3RibF92aHQpICsJXA0KKwkJ CQkJIHNpemVvZihzdHJ1Y3Qgd3RibF9iYSkgKwlcDQorCQkJCQkgc2l6ZW9mKHN0cnVjdCB3dGJs X2JmKSArCVwNCisJCQkJCSBzaXplb2Yoc3RydWN0IHd0Ymxfc21wcykgKwlcDQorCQkJCQkgc2l6 ZW9mKHN0cnVjdCB3dGJsX3NwZSkpDQorDQorI2RlZmluZSBNVDc5MTVfU1RBX1VQREFURV9NQVhf U0laRQkoc2l6ZW9mKHN0cnVjdCBzdGFfcmVxX2hkcikgKwlcDQorCQkJCQkgc2l6ZW9mKHN0cnVj dCBzdGFfcmVjX2Jhc2ljKSArCVwNCisJCQkJCSBzaXplb2Yoc3RydWN0IHN0YV9yZWNfaHQpICsJ XA0KKwkJCQkJIHNpemVvZihzdHJ1Y3Qgc3RhX3JlY19iYSkgKwlcDQorCQkJCQkgc2l6ZW9mKHN0 cnVjdCBzdGFfcmVjX3ZodCkgKwlcDQorCQkJCQkgc2l6ZW9mKHN0cnVjdCB0bHYpICsJCVwNCisJ CQkJCSBzaXplb2Yoc3RydWN0IHN0YV9yZWNfc2VjKSArCVwNCisJCQkJCSBzaXplb2Yoc3RydWN0 IHN0YV9yZWNfcmEpICsJXA0KKwkJCQkJIE1UNzkxNV9XVEJMX1VQREFURV9NQVhfU0laRSkNCisN CisjZGVmaW5lIE1UNzkxNV9XVEJMX1VQREFURV9CQV9TSVpFCShzaXplb2Yoc3RydWN0IHd0Ymxf cmVxX2hkcikgKwlcDQorCQkJCQkgc2l6ZW9mKHN0cnVjdCB3dGJsX2JhKSkNCisNCisjZGVmaW5l IE1UNzkxNV9CRUFDT05fVVBEQVRFX1NJWkUJKHNpemVvZihzdHJ1Y3Qgc3RhX3JlcV9oZHIpICsJ XA0KKwkJCQkJIHNpemVvZihzdHJ1Y3QgYnNzX2luZm9fYmNuX2NzYSkgKyBcDQorCQkJCQkgc2l6 ZW9mKHN0cnVjdCBic3NfaW5mb19iY25fYmNjKSArIFwNCisJCQkJCSBzaXplb2Yoc3RydWN0IGJz c19pbmZvX2Jjbl9tYnNzKSArIFwNCisJCQkJCSBzaXplb2Yoc3RydWN0IGJzc19pbmZvX2Jjbl9j b250KSkNCisNCisjZGVmaW5lIFBIWV9NT0RFX0EJCQlCSVQoMCkNCisjZGVmaW5lIFBIWV9NT0RF X0IJCQlCSVQoMSkNCisjZGVmaW5lIFBIWV9NT0RFX0cJCQlCSVQoMikNCisjZGVmaW5lIFBIWV9N T0RFX0dOCQkJQklUKDMpDQorI2RlZmluZSBQSFlfTU9ERV9BTgkJCUJJVCg0KQ0KKyNkZWZpbmUg UEhZX01PREVfQUMJCQlCSVQoNSkNCisNCisjZGVmaW5lIE1PREVfQ0NLCQkJQklUKDApDQorI2Rl ZmluZSBNT0RFX09GRE0JCQlCSVQoMSkNCisjZGVmaW5lIE1PREVfSFQJCQkJQklUKDIpDQorI2Rl ZmluZSBNT0RFX1ZIVAkJCUJJVCgzKQ0KKw0KKyNkZWZpbmUgU1RBX0NBUF9XTU0JCQlCSVQoMCkN CisjZGVmaW5lIFNUQV9DQVBfU0dJXzIwCQkJQklUKDQpDQorI2RlZmluZSBTVEFfQ0FQX1NHSV80 MAkJCUJJVCg1KQ0KKyNkZWZpbmUgU1RBX0NBUF9UWF9TVEJDCQkJQklUKDYpDQorI2RlZmluZSBT VEFfQ0FQX1JYX1NUQkMJCQlCSVQoNykNCisjZGVmaW5lIFNUQV9DQVBfVkhUX1NHSV84MAkJQklU KDE2KQ0KKyNkZWZpbmUgU1RBX0NBUF9WSFRfU0dJXzE2MAkJQklUKDE3KQ0KKyNkZWZpbmUgU1RB X0NBUF9WSFRfVFhfU1RCQwkJQklUKDE4KQ0KKyNkZWZpbmUgU1RBX0NBUF9WSFRfUlhfU1RCQwkJ QklUKDE5KQ0KKyNkZWZpbmUgU1RBX0NBUF9WSFRfTERQQwkJQklUKDIzKQ0KKyNkZWZpbmUgU1RB X0NBUF9MRFBDCQkJQklUKDI0KQ0KKyNkZWZpbmUgU1RBX0NBUF9IVAkJCUJJVCgyNikNCisjZGVm aW5lIFNUQV9DQVBfVkhUCQkJQklUKDI3KQ0KKw0KKyNlbmRpZg0KZGlmZiAtLWdpdCBhL2RyaXZl cnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L210NzkxNS5oIGIvZHJpdmVycy9u ZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbXQ3OTE1LmgNCm5ldyBmaWxlIG1vZGUg MTAwNjQ0DQppbmRleCAwMDAwMDAwMDAwMDAuLmYyMTM5YTUyNDhkOQ0KLS0tIC9kZXYvbnVsbA0K KysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvbXQ3OTE1LmgN CkBAIC0wLDAgKzEsNDQyIEBADQorLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IElTQyAqLw0K Ky8qIENvcHlyaWdodCAoQykgMjAyMCBNZWRpYVRlayBJbmMuICovDQorDQorI2lmbmRlZiBfX01U NzkxNV9IDQorI2RlZmluZSBfX01UNzkxNV9IDQorDQorI2luY2x1ZGUgPGxpbnV4L2ludGVycnVw dC5oPg0KKyNpbmNsdWRlIDxsaW51eC9rdGltZS5oPg0KKyNpbmNsdWRlICIuLi9tdDc2LmgiDQor I2luY2x1ZGUgInJlZ3MuaCINCisNCisjZGVmaW5lIE1UNzkxNV9NQVhfSU5URVJGQUNFUwkJNA0K KyNkZWZpbmUgTVQ3OTE1X01BWF9XTU1fU0VUUwkJNA0KKyNkZWZpbmUgTVQ3OTE1X1dUQkxfU0la RQkJMjg4DQorI2RlZmluZSBNVDc5MTVfV1RCTF9SRVNFUlZFRAkJKE1UNzkxNV9XVEJMX1NJWkUg LSAxKQ0KKyNkZWZpbmUgTVQ3OTE1X1dUQkxfU1RBCQkJKE1UNzkxNV9XVEJMX1JFU0VSVkVEIC0g XA0KKwkJCQkJIE1UNzkxNV9NQVhfSU5URVJGQUNFUykNCisNCisjZGVmaW5lIE1UNzkxNV9XQVRD SERPR19USU1FCQkoSFogLyAxMCkNCisjZGVmaW5lIE1UNzkxNV9SRVNFVF9USU1FT1VUCQkoMzAg KiBIWikNCisNCisjZGVmaW5lIE1UNzkxNV9UWF9SSU5HX1NJWkUJCTIwNDgNCisjZGVmaW5lIE1U NzkxNV9UWF9NQ1VfUklOR19TSVpFCQkyNTYNCisjZGVmaW5lIE1UNzkxNV9UWF9GV0RMX1JJTkdf U0laRQkxMjgNCisNCisjZGVmaW5lIE1UNzkxNV9SWF9SSU5HX1NJWkUJCTE1MzYNCisjZGVmaW5l IE1UNzkxNV9SWF9NQ1VfUklOR19TSVpFCQk1MTINCisNCisjZGVmaW5lIE1UNzkxNV9GSVJNV0FS RV9XQQkJIm1lZGlhdGVrL210NzkxNV93YS5iaW4iDQorI2RlZmluZSBNVDc5MTVfRklSTVdBUkVf V00JCSJtZWRpYXRlay9tdDc5MTVfd20uYmluIg0KKyNkZWZpbmUgTVQ3OTE1X1JPTV9QQVRDSAkJ Im1lZGlhdGVrL210NzkxNV9yb21fcGF0Y2guYmluIg0KKw0KKyNkZWZpbmUgTVQ3OTE1X0VFUFJP TV9TSVpFCQkzNTg0DQorI2RlZmluZSBNVDc5MTVfVE9LRU5fU0laRQkJODE5Mg0KKw0KKyNkZWZp bmUgTVQ3OTE1X0NGRU5EX1JBVEVfREVGQVVMVAkweDQ5CS8qIE9GRE0gMjRNICovDQorI2RlZmlu ZSBNVDc5MTVfQ0ZFTkRfUkFURV8xMUIJCTB4MDMJLyogMTFCIExQLCAxMU0gKi8NCisjZGVmaW5l IE1UNzkxNV81R19SQVRFX0RFRkFVTFQJCTB4NGIJLyogT0ZETSA2TSAqLw0KKyNkZWZpbmUgTVQ3 OTE1XzJHX1JBVEVfREVGQVVMVAkJMHgwCS8qIENDSyAxTSAqLw0KKw0KKw0KK3N0cnVjdCBtdDc5 MTVfdmlmOw0KK3N0cnVjdCBtdDc5MTVfc3RhOw0KK3N0cnVjdCBtdDc5MTVfZGZzX3B1bHNlOw0K K3N0cnVjdCBtdDc5MTVfZGZzX3BhdHRlcm47DQorDQorZW51bSBtdDc5MTVfdHhxX2lkIHsNCisJ TVQ3OTE1X1RYUV9GV0RMID0gMTYsDQorCU1UNzkxNV9UWFFfTUNVX1dNLA0KKwlNVDc5MTVfVFhR X0JBTkQwLA0KKwlNVDc5MTVfVFhRX0JBTkQxLA0KKwlNVDc5MTVfVFhRX01DVV9XQSwNCit9Ow0K Kw0KK2VudW0gbXQ3OTE1X3J4cV9pZCB7DQorCU1UNzkxNV9SWFFfQkFORDAgPSAwLA0KKwlNVDc5 MTVfUlhRX0JBTkQxLA0KKwlNVDc5MTVfUlhRX01DVV9XTSA9IDAsDQorCU1UNzkxNV9SWFFfTUNV X1dBLA0KK307DQorDQorZW51bSBtdDc5MTVfYW1wZHVfc3RhdGUgew0KKwlNVDc5MTVfQUdHUl9T VE9QLA0KKwlNVDc5MTVfQUdHUl9QUk9HUkVTUywNCisJTVQ3OTE1X0FHR1JfU1RBUlQsDQorCU1U NzkxNV9BR0dSX09QRVJBVElPTkFMDQorfTsNCisNCitzdHJ1Y3QgbXQ3OTE1X3N0YV9zdGF0cyB7 DQorCXN0cnVjdCByYXRlX2luZm8gcHJvYl9yYXRlOw0KKwlzdHJ1Y3QgcmF0ZV9pbmZvIHR4X3Jh dGU7DQorDQorCXVuc2lnbmVkIGxvbmcgcGVyOw0KKwl1bnNpZ25lZCBsb25nIGNoYW5nZWQ7DQor CXVuc2lnbmVkIGxvbmcgamlmZmllczsNCit9Ow0KKw0KK3N0cnVjdCBtdDc5MTVfc3RhIHsNCisJ c3RydWN0IG10NzZfd2NpZCB3Y2lkOyAvKiBtdXN0IGJlIGZpcnN0ICovDQorDQorCXN0cnVjdCBt dDc5MTVfdmlmICp2aWY7DQorDQorCXN0cnVjdCBsaXN0X2hlYWQgcG9sbF9saXN0Ow0KKwl1MzIg YWlydGltZV9hY1s4XTsNCisNCisJc3RydWN0IG10NzkxNV9zdGFfc3RhdHMgc3RhdHM7DQorCXN0 cnVjdCB3b3JrX3N0cnVjdCBzdGF0c193b3JrOw0KKw0KKwlzcGlubG9ja190IGFtcGR1X2xvY2s7 DQorCWVudW0gbXQ3OTE1X2FtcGR1X3N0YXRlIGFtcGR1X3N0YXRlW0lFRUU4MDIxMV9OVU1fVElE U107DQorfTsNCisNCitzdHJ1Y3QgbXQ3OTE1X3ZpZiB7DQorCXUxNiBpZHg7DQorCXU4IG9tYWNf aWR4Ow0KKwl1OCBiYW5kX2lkeDsNCisJdTggd21tX2lkeDsNCisNCisJc3RydWN0IHsNCisJCXUx NiBjd19taW47DQorCQl1MTYgY3dfbWF4Ow0KKwkJdTE2IHR4b3A7DQorCQl1OCBhaWZzOw0KKwl9 IHdtbVtJRUVFODAyMTFfTlVNX0FDU107DQorDQorCXN0cnVjdCBtdDc5MTVfc3RhIHN0YTsNCisJ c3RydWN0IG10NzkxNV9kZXYgKmRldjsNCit9Ow0KKw0KK3N0cnVjdCBtaWJfc3RhdHMgew0KKwl1 MTYgYWNrX2ZhaWxfY250Ow0KKwl1MTYgZmNzX2Vycl9jbnQ7DQorCXUxNiBydHNfY250Ow0KKwl1 MTYgcnRzX3JldHJpZXNfY250Ow0KKwl1MTYgYmFfbWlzc19jbnQ7DQorfTsNCisNCitzdHJ1Y3Qg bXQ3OTE1X3BoeSB7DQorCXN0cnVjdCBtdDc2X3BoeSAqbXQ3NjsNCisJc3RydWN0IG10NzkxNV9k ZXYgKmRldjsNCisNCisJdTMyIHJ4ZmlsdGVyOw0KKwl1MzIgb21hY19tYXNrOw0KKw0KKwl1MTYg bm9pc2U7DQorCXUxNiBjaGFpbm1hc2s7DQorDQorCXMxNiBjb3ZlcmFnZV9jbGFzczsNCisJdTgg c2xvdHRpbWU7DQorDQorCXU4IHJkZF9zdGF0ZTsNCisJaW50IGRmc19zdGF0ZTsNCisNCisJX19s ZTMyIHJ4X2FtcGR1X3RzOw0KKwl1MzIgYW1wZHVfcmVmOw0KKw0KKwlzdHJ1Y3QgbWliX3N0YXRz IG1pYjsNCit9Ow0KKw0KK3N0cnVjdCBtdDc5MTVfZGV2IHsNCisJdW5pb24geyAvKiBtdXN0IGJl IGZpcnN0ICovDQorCQlzdHJ1Y3QgbXQ3Nl9kZXYgbXQ3NjsNCisJCXN0cnVjdCBtdDc2X3BoeSBt cGh5Ow0KKwl9Ow0KKw0KKwlzdHJ1Y3QgbXQ3OTE1X3BoeSBwaHk7DQorCXUzMiB2aWZfbWFzazsN CisJdTMyIG9tYWNfbWFzazsNCisNCisJdTE2IGNoYWlubWFzazsNCisNCisJc3RydWN0IHdvcmtf c3RydWN0IGluaXRfd29yazsNCisJc3RydWN0IHdvcmtfc3RydWN0IHJlc2V0X3dvcms7DQorCXdh aXRfcXVldWVfaGVhZF90IHJlc2V0X3dhaXQ7DQorCXUzMiByZXNldF9zdGF0ZTsNCisNCisJc3Ry dWN0IGxpc3RfaGVhZCBzdGFfcG9sbF9saXN0Ow0KKwlzcGlubG9ja190IHN0YV9wb2xsX2xvY2s7 DQorDQorCXUzMiBod19wYXR0ZXJuOw0KKw0KKwlzcGlubG9ja190IHRva2VuX2xvY2s7DQorCXN0 cnVjdCBpZHIgdG9rZW47DQorDQorCXU4IG1hY193b3JrX2NvdW50Ow0KKwlib29sIGZ3X2RlYnVn Ow0KK307DQorDQorZW51bSB7DQorCUhXX0JTU0lEXzAgPSAweDAsDQorCUhXX0JTU0lEXzEsDQor CUhXX0JTU0lEXzIsDQorCUhXX0JTU0lEXzMsDQorCUhXX0JTU0lEX01BWCwNCisJRVhUX0JTU0lE X1NUQVJUID0gMHgxMCwNCisJRVhUX0JTU0lEXzEsDQorCUVYVF9CU1NJRF8yLA0KKwlFWFRfQlNT SURfMywNCisJRVhUX0JTU0lEXzQsDQorCUVYVF9CU1NJRF81LA0KKwlFWFRfQlNTSURfNiwNCisJ RVhUX0JTU0lEXzcsDQorCUVYVF9CU1NJRF84LA0KKwlFWFRfQlNTSURfOSwNCisJRVhUX0JTU0lE XzEwLA0KKwlFWFRfQlNTSURfMTEsDQorCUVYVF9CU1NJRF8xMiwNCisJRVhUX0JTU0lEXzEzLA0K KwlFWFRfQlNTSURfMTQsDQorCUVYVF9CU1NJRF8xNSwNCisJRVhUX0JTU0lEX0VORA0KK307DQor DQorZW51bSB7DQorCU1UX1JYX1NFTDAsDQorCU1UX1JYX1NFTDEsDQorfTsNCisNCitlbnVtIG10 NzkxNV9yZGRfY21kIHsNCisJUkREX1NUT1AsDQorCVJERF9TVEFSVCwNCisJUkREX0RFVF9NT0RF LA0KKwlSRERfUkFEQVJfRU1VTEFURSwNCisJUkREX1NUQVJUX1RYUSA9IDIwLA0KKwlSRERfQ0FD X1NUQVJUID0gNTAsDQorCVJERF9DQUNfRU5ELA0KKwlSRERfTk9STUFMX1NUQVJULA0KKwlSRERf RElTQUJMRV9ERlNfQ0FMLA0KKwlSRERfUFVMU0VfREJHLA0KKwlSRERfUkVBRF9QVUxTRSwNCisJ UkREX1JFU1VNRV9CRiwNCisJUkREX0lSUV9PRkYsDQorfTsNCisNCitlbnVtIHsNCisJUkFURV9D VFJMX1JVX0lORk8sDQorCVJBVEVfQ1RSTF9GSVhFRF9SQVRFX0lORk8sDQorCVJBVEVfQ1RSTF9E VU1QX0lORk8sDQorCVJBVEVfQ1RSTF9NVV9JTkZPLA0KK307DQorDQorc3RhdGljIGlubGluZSBz dHJ1Y3QgbXQ3OTE1X3BoeSAqDQorbXQ3OTE1X2h3X3BoeShzdHJ1Y3QgaWVlZTgwMjExX2h3ICpo dykNCit7DQorCXN0cnVjdCBtdDc2X3BoeSAqcGh5ID0gaHctPnByaXY7DQorDQorCXJldHVybiBw aHktPnByaXY7DQorfQ0KKw0KK3N0YXRpYyBpbmxpbmUgc3RydWN0IG10NzkxNV9kZXYgKg0KK210 NzkxNV9od19kZXYoc3RydWN0IGllZWU4MDIxMV9odyAqaHcpDQorew0KKwlzdHJ1Y3QgbXQ3Nl9w aHkgKnBoeSA9IGh3LT5wcml2Ow0KKw0KKwlyZXR1cm4gY29udGFpbmVyX29mKHBoeS0+ZGV2LCBz dHJ1Y3QgbXQ3OTE1X2RldiwgbXQ3Nik7DQorfQ0KKw0KK3N0YXRpYyBpbmxpbmUgc3RydWN0IG10 NzkxNV9waHkgKg0KK210NzkxNV9leHRfcGh5KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpDQorew0K KwlzdHJ1Y3QgbXQ3Nl9waHkgKnBoeSA9IGRldi0+bXQ3Ni5waHkyOw0KKw0KKwlpZiAoIXBoeSkN CisJCXJldHVybiBOVUxMOw0KKw0KKwlyZXR1cm4gcGh5LT5wcml2Ow0KK30NCisNCitzdGF0aWMg aW5saW5lIHZvaWQNCittdDc5MTVfc2V0X2FnZ3Jfc3RhdGUoc3RydWN0IG10NzkxNV9zdGEgKm1z dGEsIHU4IHRpZCwNCisJCSAgICAgIGVudW0gbXQ3OTE1X2FtcGR1X3N0YXRlIHN0YXRlKQ0KK3sN CisJc3Bpbl9sb2NrX2JoKCZtc3RhLT5hbXBkdV9sb2NrKTsNCisJbXN0YS0+YW1wZHVfc3RhdGVb dGlkXSA9IHN0YXRlOw0KKwlzcGluX3VubG9ja19iaCgmbXN0YS0+YW1wZHVfbG9jayk7DQorfQ0K Kw0KK2V4dGVybiBjb25zdCBzdHJ1Y3QgaWVlZTgwMjExX29wcyBtdDc5MTVfb3BzOw0KK2V4dGVy biBzdHJ1Y3QgcGNpX2RyaXZlciBtdDc5MTVfcGNpX2RyaXZlcjsNCisNCit1MzIgbXQ3OTE1X3Jl Z19tYXAoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgdTMyIGFkZHIpOw0KKw0KK2ludCBtdDc5MTVf cmVnaXN0ZXJfZGV2aWNlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpOw0KK3ZvaWQgbXQ3OTE1X3Vu cmVnaXN0ZXJfZGV2aWNlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpOw0KK2ludCBtdDc5MTVfcmVn aXN0ZXJfZXh0X3BoeShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KTsNCit2b2lkIG10NzkxNV91bnJl Z2lzdGVyX2V4dF9waHkoc3RydWN0IG10NzkxNV9kZXYgKmRldik7DQoraW50IG10NzkxNV9lZXBy b21faW5pdChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2KTsNCit1MzIgbXQ3OTE1X2VlcHJvbV9yZWFk KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBvZmZzZXQpOw0KK2ludCBtdDc5MTVfZWVwcm9t X2dldF90YXJnZXRfcG93ZXIoc3RydWN0IG10NzkxNV9kZXYgKmRldiwNCisJCQkJICAgc3RydWN0 IGllZWU4MDIxMV9jaGFubmVsICpjaGFuLA0KKwkJCQkgICB1OCBjaGFpbl9pZHgpOw0KK2ludCBt dDc5MTVfZG1hX2luaXQoc3RydWN0IG10NzkxNV9kZXYgKmRldik7DQordm9pZCBtdDc5MTVfZG1h X3ByZWZldGNoKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpOw0KK3ZvaWQgbXQ3OTE1X2RtYV9jbGVh bnVwKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYpOw0KK2ludCBtdDc5MTVfbWN1X2luaXQoc3RydWN0 IG10NzkxNV9kZXYgKmRldik7DQoraW50IG10NzkxNV9tY3VfYWRkX2Rldl9pbmZvKHN0cnVjdCBt dDc5MTVfZGV2ICpkZXYsDQorCQkJICAgIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsIGJvb2wg ZW5hYmxlKTsNCitpbnQgbXQ3OTE1X21jdV9hZGRfYnNzX2luZm8oc3RydWN0IG10NzkxNV9waHkg KnBoeSwNCisJCQkgICAgc3RydWN0IGllZWU4MDIxMV92aWYgKnZpZiwgaW50IGVuYWJsZSk7DQor aW50IG10NzkxNV9tY3VfYWRkX3N0YShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBzdHJ1Y3QgaWVl ZTgwMjExX3ZpZiAqdmlmLA0KKwkJICAgICAgIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEsIGJv b2wgZW5hYmxlKTsNCitpbnQgbXQ3OTE1X21jdV9hZGRfdHhfYmEoc3RydWN0IG10NzkxNV9kZXYg KmRldiwNCisJCQkgc3RydWN0IGllZWU4MDIxMV9hbXBkdV9wYXJhbXMgKnBhcmFtcywNCisJCQkg Ym9vbCBhZGQpOw0KK2ludCBtdDc5MTVfbWN1X2FkZF9yeF9iYShzdHJ1Y3QgbXQ3OTE1X2RldiAq ZGV2LA0KKwkJCSBzdHJ1Y3QgaWVlZTgwMjExX2FtcGR1X3BhcmFtcyAqcGFyYW1zLA0KKwkJCSBi b29sIGFkZCk7DQoraW50IG10NzkxNV9tY3VfYWRkX2tleShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2 LCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkJICAgICAgIHN0cnVjdCBtdDc5MTVfc3Rh ICptc3RhLCBzdHJ1Y3QgaWVlZTgwMjExX2tleV9jb25mICprZXksDQorCQkgICAgICAgZW51bSBz ZXRfa2V5X2NtZCBjbWQpOw0KK2ludCBtdDc5MTVfbWN1X2FkZF9iZWFjb24oc3RydWN0IGllZWU4 MDIxMV9odyAqaHcsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkJICBpbnQgZW5hYmxl KTsNCitpbnQgbXQ3OTE1X21jdV9hZGRfcmF0ZV9jdHJsKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYs IHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQorCQkJICAgICBzdHJ1Y3QgaWVlZTgwMjExX3N0 YSAqc3RhKTsNCitpbnQgbXQ3OTE1X21jdV9hZGRfc21wcyhzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2 LCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAqdmlmLA0KKwkJCXN0cnVjdCBpZWVlODAyMTFfc3RhICpz dGEpOw0KK2ludCBtdDc5MTVfbWN1X3NldF9jaGFuX2luZm8oc3RydWN0IG10NzkxNV9waHkgKnBo eSwgaW50IGNtZCk7DQoraW50IG10NzkxNV9tY3Vfc2V0X3R4KHN0cnVjdCBtdDc5MTVfZGV2ICpk ZXYsIHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYpOw0KK2ludCBtdDc5MTVfbWN1X3NldF9lZXBy b20oc3RydWN0IG10NzkxNV9kZXYgKmRldik7DQoraW50IG10NzkxNV9tY3VfZ2V0X2VlcHJvbShz dHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1MzIgb2Zmc2V0KTsNCitpbnQgbXQ3OTE1X21jdV9zZXRf bWFjKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIGludCBiYW5kLCBib29sIGVuYWJsZSwNCisJCSAg ICAgICBib29sIGhkcl90cmFucyk7DQoraW50IG10NzkxNV9tY3Vfc2V0X3NjcyhzdHJ1Y3QgbXQ3 OTE1X2RldiAqZGV2LCB1OCBiYW5kLCBib29sIGVuYWJsZSk7DQoraW50IG10NzkxNV9tY3Vfc2V0 X3NlcihzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1OCBhY3Rpb24sIHU4IHNldCwgdTggYmFuZCk7 DQoraW50IG10NzkxNV9tY3Vfc2V0X3J0c190aHJlc2goc3RydWN0IG10NzkxNV9waHkgKnBoeSwg dTMyIHZhbCk7DQoraW50IG10NzkxNV9tY3Vfc2V0X3BtKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYs IGludCBiYW5kLCBpbnQgZW50ZXIpOw0KK2ludCBtdDc5MTVfbWN1X3NldF9mY2M1X2xwbihzdHJ1 Y3QgbXQ3OTE1X2RldiAqZGV2LCBpbnQgdmFsKTsNCitpbnQgbXQ3OTE1X21jdV9zZXRfcHVsc2Vf dGgoc3RydWN0IG10NzkxNV9kZXYgKmRldiwNCisJCQkgICAgY29uc3Qgc3RydWN0IG10NzkxNV9k ZnNfcHVsc2UgKnB1bHNlKTsNCitpbnQgbXQ3OTE1X21jdV9zZXRfcmFkYXJfdGgoc3RydWN0IG10 NzkxNV9kZXYgKmRldiwgaW50IGluZGV4LA0KKwkJCSAgICBjb25zdCBzdHJ1Y3QgbXQ3OTE1X2Rm c19wYXR0ZXJuICpwYXR0ZXJuKTsNCitpbnQgbXQ3OTE1X21jdV9nZXRfcmF0ZV9pbmZvKHN0cnVj dCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBjbWQsIHUxNiB3bGFuX2lkeCk7DQoraW50IG10NzkxNV9t Y3VfZ2V0X3RlbXBlcmF0dXJlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIGludCBpbmRleCk7DQor aW50IG10NzkxNV9tY3VfcmRkX2NtZChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBlbnVtIG10Nzkx NV9yZGRfY21kIGNtZCwNCisJCSAgICAgICB1OCBpbmRleCwgdTggcnhfc2VsLCB1OCB2YWwpOw0K K3ZvaWQgbXQ3OTE1X21jdV9yeF9ldmVudChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBzdHJ1Y3Qg c2tfYnVmZiAqc2tiKTsNCit2b2lkIG10NzkxNV9tY3VfZXhpdChzdHJ1Y3QgbXQ3OTE1X2RldiAq ZGV2KTsNCisNCitzdGF0aWMgaW5saW5lIGJvb2wgaXNfbXQ3OTE1KHN0cnVjdCBtdDc2X2RldiAq ZGV2KQ0KK3sNCisJcmV0dXJuIG10NzZfY2hpcChkZXYpID09IDB4NzkxNTsNCit9DQorDQorc3Rh dGljIGlubGluZSB2b2lkIG10NzkxNV9pcnFfZW5hYmxlKHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYs IHUzMiBtYXNrKQ0KK3sNCisJbXQ3Nl9zZXRfaXJxX21hc2soJmRldi0+bXQ3NiwgTVRfSU5UX01B U0tfQ1NSLCAwLCBtYXNrKTsNCit9DQorDQorc3RhdGljIGlubGluZSB2b2lkIG10NzkxNV9pcnFf ZGlzYWJsZShzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1MzIgbWFzaykNCit7DQorCW10NzZfc2V0 X2lycV9tYXNrKCZkZXYtPm10NzYsIE1UX0lOVF9NQVNLX0NTUiwgbWFzaywgMCk7DQorfQ0KKw0K K3N0YXRpYyBpbmxpbmUgdTMyDQorbXQ3OTE1X3JlZ19tYXBfbDEoc3RydWN0IG10NzkxNV9kZXYg KmRldiwgdTMyIGFkZHIpDQorew0KKwl1MzIgb2Zmc2V0ID0gRklFTERfR0VUKE1UX0hJRl9SRU1B UF9MMV9PRkZTRVQsIGFkZHIpOw0KKwl1MzIgYmFzZSA9IEZJRUxEX0dFVChNVF9ISUZfUkVNQVBf TDFfQkFTRSwgYWRkcik7DQorDQorCW10NzZfcm13X2ZpZWxkKGRldiwgTVRfSElGX1JFTUFQX0wx LCBNVF9ISUZfUkVNQVBfTDFfTUFTSywgYmFzZSk7DQorCS8qIHVzZSByZWFkIHRvIHB1c2ggd3Jp dGUgKi8NCisJbXQ3Nl9ycihkZXYsIE1UX0hJRl9SRU1BUF9MMSk7DQorDQorCXJldHVybiBNVF9I SUZfUkVNQVBfQkFTRV9MMSArIG9mZnNldDsNCit9DQorDQorc3RhdGljIGlubGluZSB1MzINCitt dDc5MTVfbDFfcnIoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgdTMyIGFkZHIpDQorew0KKwlyZXR1 cm4gbXQ3Nl9ycihkZXYsIG10NzkxNV9yZWdfbWFwX2wxKGRldiwgYWRkcikpOw0KK30NCisNCitz dGF0aWMgaW5saW5lIHZvaWQNCittdDc5MTVfbDFfd3Ioc3RydWN0IG10NzkxNV9kZXYgKmRldiwg dTMyIGFkZHIsIHUzMiB2YWwpDQorew0KKwltdDc2X3dyKGRldiwgbXQ3OTE1X3JlZ19tYXBfbDEo ZGV2LCBhZGRyKSwgdmFsKTsNCit9DQorDQorc3RhdGljIGlubGluZSB1MzINCittdDc5MTVfbDFf cm13KHN0cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHUzMiBhZGRyLCB1MzIgbWFzaywgdTMyIHZhbCkN Cit7DQorCXZhbCB8PSBtdDc5MTVfbDFfcnIoZGV2LCBhZGRyKSAmIH5tYXNrOw0KKwltdDc5MTVf bDFfd3IoZGV2LCBhZGRyLCB2YWwpOw0KKw0KKwlyZXR1cm4gdmFsOw0KK30NCisNCisjZGVmaW5l IG10NzkxNV9sMV9zZXQoZGV2LCBhZGRyLCB2YWwpCW10NzkxNV9sMV9ybXcoZGV2LCBhZGRyLCAw LCB2YWwpDQorI2RlZmluZSBtdDc5MTVfbDFfY2xlYXIoZGV2LCBhZGRyLCB2YWwpCW10NzkxNV9s MV9ybXcoZGV2LCBhZGRyLCB2YWwsIDApDQorDQorc3RhdGljIGlubGluZSB1MzINCittdDc5MTVf cmVnX21hcF9sMihzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1MzIgYWRkcikNCit7DQorCXUzMiBv ZmZzZXQgPSBGSUVMRF9HRVQoTVRfSElGX1JFTUFQX0wyX09GRlNFVCwgYWRkcik7DQorCXUzMiBi YXNlID0gRklFTERfR0VUKE1UX0hJRl9SRU1BUF9MMl9CQVNFLCBhZGRyKTsNCisNCisJbXQ3Nl9y bXdfZmllbGQoZGV2LCBNVF9ISUZfUkVNQVBfTDIsIE1UX0hJRl9SRU1BUF9MMl9NQVNLLCBiYXNl KTsNCisJLyogdXNlIHJlYWQgdG8gcHVzaCB3cml0ZSAqLw0KKwltdDc2X3JyKGRldiwgTVRfSElG X1JFTUFQX0wyKTsNCisNCisJcmV0dXJuIE1UX0hJRl9SRU1BUF9CQVNFX0wyICsgb2Zmc2V0Ow0K K30NCisNCitzdGF0aWMgaW5saW5lIHUzMg0KK210NzkxNV9sMl9ycihzdHJ1Y3QgbXQ3OTE1X2Rl diAqZGV2LCB1MzIgYWRkcikNCit7DQorCXJldHVybiBtdDc2X3JyKGRldiwgbXQ3OTE1X3JlZ19t YXBfbDIoZGV2LCBhZGRyKSk7DQorfQ0KKw0KK3N0YXRpYyBpbmxpbmUgdm9pZA0KK210NzkxNV9s Ml93cihzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCB1MzIgYWRkciwgdTMyIHZhbCkNCit7DQorCW10 NzZfd3IoZGV2LCBtdDc5MTVfcmVnX21hcF9sMihkZXYsIGFkZHIpLCB2YWwpOw0KK30NCisNCitz dGF0aWMgaW5saW5lIHUzMg0KK210NzkxNV9sMl9ybXcoc3RydWN0IG10NzkxNV9kZXYgKmRldiwg dTMyIGFkZHIsIHUzMiBtYXNrLCB1MzIgdmFsKQ0KK3sNCisJdmFsIHw9IG10NzkxNV9sMl9ycihk ZXYsIGFkZHIpICYgfm1hc2s7DQorCW10NzkxNV9sMl93cihkZXYsIGFkZHIsIHZhbCk7DQorDQor CXJldHVybiB2YWw7DQorfQ0KKw0KKyNkZWZpbmUgbXQ3OTE1X2wyX3NldChkZXYsIGFkZHIsIHZh bCkJbXQ3OTE1X2wyX3JtdyhkZXYsIGFkZHIsIDAsIHZhbCkNCisjZGVmaW5lIG10NzkxNV9sMl9j bGVhcihkZXYsIGFkZHIsIHZhbCkJbXQ3OTE1X2wyX3JtdyhkZXYsIGFkZHIsIHZhbCwgMCkNCisN Citib29sIG10NzkxNV9tYWNfd3RibF91cGRhdGUoc3RydWN0IG10NzkxNV9kZXYgKmRldiwgaW50 IGlkeCwgdTMyIG1hc2spOw0KK3ZvaWQgbXQ3OTE1X21hY19yZXNldF9jb3VudGVycyhzdHJ1Y3Qg bXQ3OTE1X3BoeSAqcGh5KTsNCit2b2lkIG10NzkxNV9tYWNfY2NhX3N0YXRzX3Jlc2V0KHN0cnVj dCBtdDc5MTVfcGh5ICpwaHkpOw0KK3ZvaWQgbXQ3OTE1X21hY19zdGFfcG9sbChzdHJ1Y3QgbXQ3 OTE1X2RldiAqZGV2KTsNCit2b2lkIG10NzkxNV9tYWNfd3JpdGVfdHh3aShzdHJ1Y3QgbXQ3OTE1 X2RldiAqZGV2LCBfX2xlMzIgKnR4d2ksDQorCQkJICAgc3RydWN0IHNrX2J1ZmYgKnNrYiwgc3Ry dWN0IG10NzZfd2NpZCAqd2NpZCwNCisJCQkgICBzdHJ1Y3QgaWVlZTgwMjExX2tleV9jb25mICpr ZXksIGJvb2wgYmVhY29uKTsNCit2b2lkIG10NzkxNV9tYWNfc2V0X3RpbWluZyhzdHJ1Y3QgbXQ3 OTE1X3BoeSAqcGh5KTsNCitpbnQgbXQ3OTE1X21hY19maWxsX3J4KHN0cnVjdCBtdDc5MTVfZGV2 ICpkZXYsIHN0cnVjdCBza19idWZmICpza2IpOw0KK3ZvaWQgbXQ3OTE1X21hY190eF9mcmVlKHN0 cnVjdCBtdDc5MTVfZGV2ICpkZXYsIHN0cnVjdCBza19idWZmICpza2IpOw0KK2ludCBtdDc5MTVf bWFjX3N0YV9hZGQoc3RydWN0IG10NzZfZGV2ICptZGV2LCBzdHJ1Y3QgaWVlZTgwMjExX3ZpZiAq dmlmLA0KKwkJICAgICAgIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEpOw0KK3ZvaWQgbXQ3OTE1 X21hY19zdGFfcmVtb3ZlKHN0cnVjdCBtdDc2X2RldiAqbWRldiwgc3RydWN0IGllZWU4MDIxMV92 aWYgKnZpZiwNCisJCQkgICBzdHJ1Y3QgaWVlZTgwMjExX3N0YSAqc3RhKTsNCit2b2lkIG10Nzkx NV9tYWNfd29yayhzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspOw0KK3ZvaWQgbXQ3OTE1X21hY19y ZXNldF93b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yayk7DQordm9pZCBtdDc5MTVfbWFjX3N0 YV9zdGF0c193b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yayk7DQoraW50IG10NzkxNV90eF9w cmVwYXJlX3NrYihzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYsIHZvaWQgKnR4d2lfcHRyLA0KKwkJCSAg ZW51bSBtdDc2X3R4cV9pZCBxaWQsIHN0cnVjdCBtdDc2X3djaWQgKndjaWQsDQorCQkJICBzdHJ1 Y3QgaWVlZTgwMjExX3N0YSAqc3RhLA0KKwkJCSAgc3RydWN0IG10NzZfdHhfaW5mbyAqdHhfaW5m byk7DQordm9pZCBtdDc5MTVfdHhfY29tcGxldGVfc2tiKHN0cnVjdCBtdDc2X2RldiAqbWRldiwg ZW51bSBtdDc2X3R4cV9pZCBxaWQsDQorCQkJICAgIHN0cnVjdCBtdDc2X3F1ZXVlX2VudHJ5ICpl KTsNCit2b2lkIG10NzkxNV9xdWV1ZV9yeF9za2Ioc3RydWN0IG10NzZfZGV2ICptZGV2LCBlbnVt IG10NzZfcnhxX2lkIHEsDQorCQkJIHN0cnVjdCBza19idWZmICpza2IpOw0KK3ZvaWQgbXQ3OTE1 X3N0YV9wcyhzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYsIHN0cnVjdCBpZWVlODAyMTFfc3RhICpzdGEs IGJvb2wgcHMpOw0KK3ZvaWQgbXQ3OTE1X3N0YXRzX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3 b3JrKTsNCit2b2lkIG10NzkxNV90eHBfc2tiX3VubWFwKHN0cnVjdCBtdDc2X2RldiAqZGV2LA0K KwkJCSAgc3RydWN0IG10NzZfdHh3aV9jYWNoZSAqdHh3aSk7DQoraW50IG10NzZfZGZzX3N0YXJ0 X3JkZChzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2LCBib29sIGZvcmNlKTsNCitpbnQgbXQ3OTE1X2Rm c19pbml0X3JhZGFyX2RldGVjdG9yKHN0cnVjdCBtdDc5MTVfcGh5ICpwaHkpOw0KK3ZvaWQgbXQ3 OTE1X3VwZGF0ZV9jaGFubmVsKHN0cnVjdCBtdDc2X2RldiAqbWRldik7DQoraW50IG10NzkxNV9p bml0X2RlYnVnZnMoc3RydWN0IG10NzkxNV9kZXYgKmRldik7DQorDQorI2VuZGlmDQpkaWZmIC0t Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWVkaWF0ZWsvbXQ3Ni9tdDc5MTUvcGNpLmMgYi9k cml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9wY2kuYw0KbmV3IGZpbGUg bW9kZSAxMDA2NDQNCmluZGV4IDAwMDAwMDAwMDAwMC4uMTJhNTYyZDNhYTNkDQotLS0gL2Rldi9u dWxsDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210NzkxNS9wY2ku Yw0KQEAgLTAsMCArMSwxNjUgQEANCisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogSVNDDQor LyogQ29weXJpZ2h0IChDKSAyMDIwIE1lZGlhVGVrIEluYy4NCisgKg0KKyAqIEF1dGhvcjogUnlk ZXIgTGVlIDxyeWRlci5sZWVAbWVkaWF0ZWsuY29tPg0KKyAqLw0KKw0KKyNpbmNsdWRlIDxsaW51 eC9rZXJuZWwuaD4NCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQorI2luY2x1ZGUgPGxpbnV4 L3BjaS5oPg0KKw0KKyNpbmNsdWRlICJtdDc5MTUuaCINCisjaW5jbHVkZSAibWFjLmgiDQorI2lu Y2x1ZGUgIi4uL3RyYWNlLmgiDQorDQorc3RhdGljIGNvbnN0IHN0cnVjdCBwY2lfZGV2aWNlX2lk IG10NzkxNV9wY2lfZGV2aWNlX3RhYmxlW10gPSB7DQorCXsgUENJX0RFVklDRSgweDE0YzMsIDB4 NzkxNSkgfSwNCisJeyB9LA0KK307DQorDQorc3RhdGljIHZvaWQNCittdDc5MTVfcnhfcG9sbF9j b21wbGV0ZShzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYsIGVudW0gbXQ3Nl9yeHFfaWQgcSkNCit7DQor CXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBjb250YWluZXJfb2YobWRldiwgc3RydWN0IG10Nzkx NV9kZXYsIG10NzYpOw0KKw0KKwltdDc5MTVfaXJxX2VuYWJsZShkZXYsIE1UX0lOVF9SWF9ET05F KHEpKTsNCit9DQorDQorc3RhdGljIGlycXJldHVybl90IG10NzkxNV9pcnFfaGFuZGxlcihpbnQg aXJxLCB2b2lkICpkZXZfaW5zdGFuY2UpDQorew0KKwlzdHJ1Y3QgbXQ3OTE1X2RldiAqZGV2ID0g ZGV2X2luc3RhbmNlOw0KKwl1MzIgaW50cjsNCisNCisJaW50ciA9IG10NzZfcnIoZGV2LCBNVF9J TlRfU09VUkNFX0NTUik7DQorCW10NzZfd3IoZGV2LCBNVF9JTlRfU09VUkNFX0NTUiwgaW50cik7 DQorDQorCWlmICghdGVzdF9iaXQoTVQ3Nl9TVEFURV9JTklUSUFMSVpFRCwgJmRldi0+bXBoeS5z dGF0ZSkpDQorCQlyZXR1cm4gSVJRX05PTkU7DQorDQorCXRyYWNlX2Rldl9pcnEoJmRldi0+bXQ3 NiwgaW50ciwgZGV2LT5tdDc2Lm1taW8uaXJxbWFzayk7DQorDQorCWludHIgJj0gZGV2LT5tdDc2 Lm1taW8uaXJxbWFzazsNCisNCisJaWYgKGludHIgJiBNVF9JTlRfVFhfRE9ORV9BTEwpIHsNCisJ CW10NzkxNV9pcnFfZGlzYWJsZShkZXYsIE1UX0lOVF9UWF9ET05FX0FMTCk7DQorCQluYXBpX3Nj aGVkdWxlKCZkZXYtPm10NzYudHhfbmFwaSk7DQorCX0NCisNCisJaWYgKGludHIgJiBNVF9JTlRf UlhfRE9ORV9EQVRBKSB7DQorCQltdDc5MTVfaXJxX2Rpc2FibGUoZGV2LCBNVF9JTlRfUlhfRE9O RV9EQVRBKTsNCisJCW5hcGlfc2NoZWR1bGUoJmRldi0+bXQ3Ni5uYXBpWzBdKTsNCisJfQ0KKw0K KwlpZiAoaW50ciAmIE1UX0lOVF9SWF9ET05FX1dNKSB7DQorCQltdDc5MTVfaXJxX2Rpc2FibGUo ZGV2LCBNVF9JTlRfUlhfRE9ORV9XTSk7DQorCQluYXBpX3NjaGVkdWxlKCZkZXYtPm10NzYubmFw aVsxXSk7DQorCX0NCisNCisJaWYgKGludHIgJiBNVF9JTlRfUlhfRE9ORV9XQSkgew0KKwkJbXQ3 OTE1X2lycV9kaXNhYmxlKGRldiwgTVRfSU5UX1JYX0RPTkVfV0EpOw0KKwkJbmFwaV9zY2hlZHVs ZSgmZGV2LT5tdDc2Lm5hcGlbMl0pOw0KKwl9DQorDQorCWlmIChpbnRyICYgTVRfSU5UX01DVV9D TUQpIHsNCisJCXUzMiB2YWwgPSBtdDc2X3JyKGRldiwgTVRfTUNVX0NNRCk7DQorDQorCQltdDc2 X3dyKGRldiwgTVRfTUNVX0NNRCwgdmFsKTsNCisJCWlmICh2YWwgJiBNVF9NQ1VfQ01EX0VSUk9S X01BU0spIHsNCisJCQlkZXYtPnJlc2V0X3N0YXRlID0gdmFsOw0KKwkJCWllZWU4MDIxMV9xdWV1 ZV93b3JrKG10NzZfaHcoZGV2KSwgJmRldi0+cmVzZXRfd29yayk7DQorCQkJd2FrZV91cCgmZGV2 LT5yZXNldF93YWl0KTsNCisJCX0NCisJfQ0KKw0KKwlyZXR1cm4gSVJRX0hBTkRMRUQ7DQorfQ0K Kw0KK3N0YXRpYyBpbnQgbXQ3OTE1X3BjaV9wcm9iZShzdHJ1Y3QgcGNpX2RldiAqcGRldiwNCisJ CQkgICAgY29uc3Qgc3RydWN0IHBjaV9kZXZpY2VfaWQgKmlkKQ0KK3sNCisJc3RhdGljIGNvbnN0 IHN0cnVjdCBtdDc2X2RyaXZlcl9vcHMgZHJ2X29wcyA9IHsNCisJCS8qIHR4d2lfc2l6ZSA9IHR4 ZCBzaXplICsgdHhwIHNpemUgKi8NCisJCS50eHdpX3NpemUgPSBNVF9UWERfU0laRSArIHNpemVv ZihzdHJ1Y3QgbXQ3OTE1X3R4cCksDQorCQkuZHJ2X2ZsYWdzID0gTVRfRFJWX1RYV0lfTk9fRlJF RSwNCisJCS5zdXJ2ZXlfZmxhZ3MgPSBTVVJWRVlfSU5GT19USU1FX1RYIHwNCisJCQkJU1VSVkVZ X0lORk9fVElNRV9SWCB8DQorCQkJCVNVUlZFWV9JTkZPX1RJTUVfQlNTX1JYLA0KKwkJLnR4X3By ZXBhcmVfc2tiID0gbXQ3OTE1X3R4X3ByZXBhcmVfc2tiLA0KKwkJLnR4X2NvbXBsZXRlX3NrYiA9 IG10NzkxNV90eF9jb21wbGV0ZV9za2IsDQorCQkucnhfc2tiID0gbXQ3OTE1X3F1ZXVlX3J4X3Nr YiwNCisJCS5yeF9wb2xsX2NvbXBsZXRlID0gbXQ3OTE1X3J4X3BvbGxfY29tcGxldGUsDQorCQku c3RhX3BzID0gbXQ3OTE1X3N0YV9wcywNCisJCS5zdGFfYWRkID0gbXQ3OTE1X21hY19zdGFfYWRk LA0KKwkJLnN0YV9yZW1vdmUgPSBtdDc5MTVfbWFjX3N0YV9yZW1vdmUsDQorCQkudXBkYXRlX3N1 cnZleSA9IG10NzkxNV91cGRhdGVfY2hhbm5lbCwNCisJfTsNCisJc3RydWN0IG10NzkxNV9kZXYg KmRldjsNCisJc3RydWN0IG10NzZfZGV2ICptZGV2Ow0KKwlpbnQgcmV0Ow0KKw0KKwlyZXQgPSBw Y2ltX2VuYWJsZV9kZXZpY2UocGRldik7DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0Ow0KKw0K KwlyZXQgPSBwY2ltX2lvbWFwX3JlZ2lvbnMocGRldiwgQklUKDApLCBwY2lfbmFtZShwZGV2KSk7 DQorCWlmIChyZXQpDQorCQlyZXR1cm4gcmV0Ow0KKw0KKwlwY2lfc2V0X21hc3RlcihwZGV2KTsN CisNCisJcmV0ID0gcGNpX3NldF9kbWFfbWFzayhwZGV2LCBETUFfQklUX01BU0soMzIpKTsNCisJ aWYgKHJldCkNCisJCXJldHVybiByZXQ7DQorDQorCW1kZXYgPSBtdDc2X2FsbG9jX2RldmljZSgm cGRldi0+ZGV2LCBzaXplb2YoKmRldiksICZtdDc5MTVfb3BzLA0KKwkJCQkgJmRydl9vcHMpOw0K KwlpZiAoIW1kZXYpDQorCQlyZXR1cm4gLUVOT01FTTsNCisNCisJZGV2ID0gY29udGFpbmVyX29m KG1kZXYsIHN0cnVjdCBtdDc5MTVfZGV2LCBtdDc2KTsNCisNCisJbXQ3Nl9tbWlvX2luaXQoJmRl di0+bXQ3NiwgcGNpbV9pb21hcF90YWJsZShwZGV2KVswXSk7DQorCW1kZXYtPnJldiA9IChtdDc5 MTVfbDFfcnIoZGV2LCBNVF9IV19DSElQSUQpIDw8IDE2KSB8DQorCQkgICAgKG10NzkxNV9sMV9y cihkZXYsIE1UX0hXX1JFVikgJiAweGZmKTsNCisJZGV2X2RiZyhtZGV2LT5kZXYsICJBU0lDIHJl dmlzaW9uOiAlMDR4XG4iLCBtZGV2LT5yZXYpOw0KKw0KKwkvKiBtYXN0ZXIgc3dpdGNoIG9mIFBD SWUgdG50ZXJydXB0IGVuYWJsZSAqLw0KKwltdDc5MTVfbDFfd3IoZGV2LCBNVF9QQ0lFX01BQ19J TlRfRU5BQkxFLCAweGZmKTsNCisNCisJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShtZGV2LT5kZXYs IHBkZXYtPmlycSwgbXQ3OTE1X2lycV9oYW5kbGVyLA0KKwkJCSAgICAgICBJUlFGX1NIQVJFRCwg S0JVSUxEX01PRE5BTUUsIGRldik7DQorCWlmIChyZXQpDQorCQlnb3RvIGVycm9yOw0KKw0KKwly ZXQgPSBtdDc5MTVfcmVnaXN0ZXJfZGV2aWNlKGRldik7DQorCWlmIChyZXQpDQorCQlnb3RvIGVy cm9yOw0KKw0KKwlyZXR1cm4gMDsNCitlcnJvcjoNCisJaWVlZTgwMjExX2ZyZWVfaHcobXQ3Nl9o dyhkZXYpKTsNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIHZvaWQgbXQ3OTE1X3BjaV9y ZW1vdmUoc3RydWN0IHBjaV9kZXYgKnBkZXYpDQorew0KKwlzdHJ1Y3QgbXQ3Nl9kZXYgKm1kZXYg PSBwY2lfZ2V0X2RydmRhdGEocGRldik7DQorCXN0cnVjdCBtdDc5MTVfZGV2ICpkZXYgPSBjb250 YWluZXJfb2YobWRldiwgc3RydWN0IG10NzkxNV9kZXYsIG10NzYpOw0KKw0KKwltdDc5MTVfdW5y ZWdpc3Rlcl9kZXZpY2UoZGV2KTsNCit9DQorDQorc3RydWN0IHBjaV9kcml2ZXIgbXQ3OTE1X3Bj aV9kcml2ZXIgPSB7DQorCS5uYW1lCQk9IEtCVUlMRF9NT0ROQU1FLA0KKwkuaWRfdGFibGUJPSBt dDc5MTVfcGNpX2RldmljZV90YWJsZSwNCisJLnByb2JlCQk9IG10NzkxNV9wY2lfcHJvYmUsDQor CS5yZW1vdmUJCT0gbXQ3OTE1X3BjaV9yZW1vdmUsDQorfTsNCisNCittb2R1bGVfcGNpX2RyaXZl cihtdDc5MTVfcGNpX2RyaXZlcik7DQorDQorTU9EVUxFX0RFVklDRV9UQUJMRShwY2ksIG10Nzkx NV9wY2lfZGV2aWNlX3RhYmxlKTsNCitNT0RVTEVfRklSTVdBUkUoTVQ3OTE1X0ZJUk1XQVJFX1dB KTsNCitNT0RVTEVfRklSTVdBUkUoTVQ3OTE1X0ZJUk1XQVJFX1dNKTsNCitNT0RVTEVfRklSTVdB UkUoTVQ3OTE1X1JPTV9QQVRDSCk7DQorTU9EVUxFX0xJQ0VOU0UoIkR1YWwgQlNEL0dQTCIpOw0K ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L3Jl Z3MuaCBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21lZGlhdGVrL210NzYvbXQ3OTE1L3JlZ3MuaA0K bmV3IGZpbGUgbW9kZSAxMDA2NDQNCmluZGV4IDAwMDAwMDAwMDAwMC4uNTcyYmRjMTZmYjJkDQot LS0gL2Rldi9udWxsDQorKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tZWRpYXRlay9tdDc2L210 NzkxNS9yZWdzLmgNCkBAIC0wLDAgKzEsMzQ0IEBADQorLyogU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IElTQyAqLw0KKy8qIENvcHlyaWdodCAoQykgMjAyMCBNZWRpYVRlayBJbmMuICovDQorDQor I2lmbmRlZiBfX01UNzkxNV9SRUdTX0gNCisjZGVmaW5lIF9fTVQ3OTE1X1JFR1NfSA0KKw0KKy8q IE1DVSBXRkRNQTEgKi8NCisjZGVmaW5lIE1UX01DVV9XRkRNQTFfQkFTRQkJMHgzMDAwDQorI2Rl ZmluZSBNVF9NQ1VfV0ZETUExKG9mcykJCShNVF9NQ1VfV0ZETUExX0JBU0UgKyAob2ZzKSkNCisN CisjZGVmaW5lIE1UX01DVV9JTlRfRVZFTlQJCU1UX01DVV9XRkRNQTEoMHgxMDgpDQorI2RlZmlu ZSBNVF9NQ1VfSU5UX0VWRU5UX0RNQV9TVE9QUEVECUJJVCgwKQ0KKyNkZWZpbmUgTVRfTUNVX0lO VF9FVkVOVF9ETUFfSU5JVAlCSVQoMSkNCisjZGVmaW5lIE1UX01DVV9JTlRfRVZFTlRfU0VSX1RS SUdHRVIJQklUKDIpDQorI2RlZmluZSBNVF9NQ1VfSU5UX0VWRU5UX1JFU0VUX0RPTkUJQklUKDMp DQorDQorI2RlZmluZSBNVF9QTEVfQkFTRQkJCTB4ODAwMA0KKyNkZWZpbmUgTVRfUExFKG9mcykJ CQkoTVRfUExFX0JBU0UgKyAob2ZzKSkNCisNCisjZGVmaW5lIE1UX1BMRV9GTF9RMF9DVFJMCQlN VF9QTEUoMHgxYjApDQorI2RlZmluZSBNVF9QTEVfRkxfUTFfQ1RSTAkJTVRfUExFKDB4MWI0KQ0K KyNkZWZpbmUgTVRfUExFX0ZMX1EyX0NUUkwJCU1UX1BMRSgweDFiOCkNCisjZGVmaW5lIE1UX1BM RV9GTF9RM19DVFJMCQlNVF9QTEUoMHgxYmMpDQorDQorI2RlZmluZSBNVF9QTEVfQUNfUUVNUFRZ KGFjLCBuKQkJTVRfUExFKDB4MzAwICsgMHgxMCAqIChhYykgKyBcDQorCQkJCQkgICAgICAgKChu KSA8PCAyKSkNCisjZGVmaW5lIE1UX1BMRV9BTVNEVV9QQUNLX01TRFVfQ05UKG4pCU1UX1BMRSgw eDEwZTAgKyAoKG4pIDw8IDIpKQ0KKw0KKyNkZWZpbmUgTVRfTURQX0JBU0UJCQkweGYwMDANCisj ZGVmaW5lIE1UX01EUChvZnMpCQkJKE1UX01EUF9CQVNFICsgKG9mcykpDQorDQorI2RlZmluZSBN VF9NRFBfRENSMAkJCU1UX01EUCgweDAwMCkNCisjZGVmaW5lIE1UX01EUF9EQ1IwX0RBTVNEVV9F TgkJQklUKDE1KQ0KKw0KKyNkZWZpbmUgTVRfTURQX0RDUjEJCQlNVF9NRFAoMHgwMDQpDQorI2Rl ZmluZSBNVF9NRFBfRENSMV9NQVhfUlhfTEVOCQlHRU5NQVNLKDE1LCAzKQ0KKw0KKyNkZWZpbmUg TVRfTURQX0JOUkNGUjAoX2JhbmQpCQlNVF9NRFAoMHgwNzAgKyAoKF9iYW5kKSA8PCA4KSkNCisj ZGVmaW5lIE1UX01EUF9SQ0ZSMF9NQ1VfUlhfTUdNVAlHRU5NQVNLKDUsIDQpDQorI2RlZmluZSBN VF9NRFBfUkNGUjBfTUNVX1JYX0NUTF9OT05fQkFSCUdFTk1BU0soNywgNikNCisjZGVmaW5lIE1U X01EUF9SQ0ZSMF9NQ1VfUlhfQ1RMX0JBUglHRU5NQVNLKDksIDgpDQorDQorI2RlZmluZSBNVF9N RFBfQk5SQ0ZSMShfYmFuZCkJCU1UX01EUCgweDA3NCArICgoX2JhbmQpIDw8IDgpKQ0KKyNkZWZp bmUgTVRfTURQX1JDRlIxX01DVV9SWF9CWVBBU1MJR0VOTUFTSygyMywgMjIpDQorI2RlZmluZSBN VF9NRFBfUkNGUjFfUlhfRFJPUFBFRF9VQ0FTVAlHRU5NQVNLKDI4LCAyNykNCisjZGVmaW5lIE1U X01EUF9SQ0ZSMV9SWF9EUk9QUEVEX01DQVNUCUdFTk1BU0soMzAsIDI5KQ0KKyNkZWZpbmUgTVRf TURQX1RPX0hJRgkJCTANCisjZGVmaW5lIE1UX01EUF9UT19XTQkJCTENCisNCisvKiBUTUFDOiBi YW5kIDAoMHgyMTAwMCksIGJhbmQgMSgweGExMDAwKSAqLw0KKyNkZWZpbmUgTVRfV0ZfVE1BQ19C QVNFKF9iYW5kKQkJKChfYmFuZCkgPyAweGExMDAwIDogMHgyMTAwMCkNCisjZGVmaW5lIE1UX1dG X1RNQUMoX2JhbmQsIG9mcykJCShNVF9XRl9UTUFDX0JBU0UoX2JhbmQpICsgKG9mcykpDQorDQor I2RlZmluZSBNVF9UTUFDX0NEVFIoX2JhbmQpCQlNVF9XRl9UTUFDKF9iYW5kLCAweDA5MCkNCisj ZGVmaW5lIE1UX1RNQUNfT0RUUihfYmFuZCkJCU1UX1dGX1RNQUMoX2JhbmQsIDB4MDk0KQ0KKyNk ZWZpbmUgTVRfVElNRU9VVF9WQUxfUExDUAkJR0VOTUFTSygxNSwgMCkNCisjZGVmaW5lIE1UX1RJ TUVPVVRfVkFMX0NDQQkJR0VOTUFTSygzMSwgMTYpDQorDQorI2RlZmluZSBNVF9UTUFDX0lDUjAo X2JhbmQpCQlNVF9XRl9UTUFDKF9iYW5kLCAweDBhNCkNCisjZGVmaW5lIE1UX0lGU19FSUZTCQkJ R0VOTUFTSyg4LCAwKQ0KKyNkZWZpbmUgTVRfSUZTX1JJRlMJCQlHRU5NQVNLKDE0LCAxMCkNCisj ZGVmaW5lIE1UX0lGU19TSUZTCQkJR0VOTUFTSygyMiwgMTYpDQorI2RlZmluZSBNVF9JRlNfU0xP VAkJCUdFTk1BU0soMzAsIDI0KQ0KKw0KKyNkZWZpbmUgTVRfVE1BQ19DVENSMChfYmFuZCkJCQlN VF9XRl9UTUFDKF9iYW5kLCAweDBmNCkNCisjZGVmaW5lIE1UX1RNQUNfQ1RDUjBfSU5TX0RETE1U X1JFRlRJTUUJCUdFTk1BU0soNSwgMCkNCisjZGVmaW5lIE1UX1RNQUNfQ1RDUjBfSU5TX0RETE1U X0VOCQlCSVQoMTcpDQorI2RlZmluZSBNVF9UTUFDX0NUQ1IwX0lOU19ERExNVF9WSFRfU01QRFVf RU4JQklUKDE4KQ0KKw0KKy8qIERNQSBCYW5kIDAgKi8NCisjZGVmaW5lIE1UX1dGX0RNQV9CQVNF CQkJMHgyMWUwMA0KKyNkZWZpbmUgTVRfV0ZfRE1BKG9mcykJCQkoTVRfV0ZfRE1BX0JBU0UgKyAo b2ZzKSkNCisNCisjZGVmaW5lIE1UX0RNQV9EQ1IwCQkJTVRfV0ZfRE1BKDB4MDAwKQ0KKyNkZWZp bmUgTVRfRE1BX0RDUjBfTUFYX1JYX0xFTgkJR0VOTUFTSygxNSwgMykNCisjZGVmaW5lIE1UX0RN QV9EQ1IwX1JYRF9HNV9FTgkJQklUKDIzKQ0KKw0KKy8qIE1JQjogYmFuZCAwKDB4MjQ4MDApLCBi YW5kIDEoMHhhNDgwMCkgKi8NCisjZGVmaW5lIE1UX1dGX01JQl9CQVNFKF9iYW5kKQkJKChfYmFu ZCkgPyAweGE0ODAwIDogMHgyNDgwMCkNCisjZGVmaW5lIE1UX1dGX01JQihfYmFuZCwgb2ZzKQkJ KE1UX1dGX01JQl9CQVNFKF9iYW5kKSArIChvZnMpKQ0KKw0KKyNkZWZpbmUgTVRfTUlCX1NEUjMo X2JhbmQpCQlNVF9XRl9NSUIoX2JhbmQsIDB4MDE0KQ0KKyNkZWZpbmUgTVRfTUlCX1NEUjNfRkNT X0VSUl9NQVNLCUdFTk1BU0soMTUsIDApDQorDQorI2RlZmluZSBNVF9NSUJfU0RSOShfYmFuZCkJ CU1UX1dGX01JQihfYmFuZCwgMHgwMmMpDQorI2RlZmluZSBNVF9NSUJfU0RSOV9CVVNZX01BU0sJ CUdFTk1BU0soMjMsIDApDQorDQorI2RlZmluZSBNVF9NSUJfU0RSMTYoX2JhbmQpCQlNVF9XRl9N SUIoX2JhbmQsIDB4MDQ4KQ0KKyNkZWZpbmUgTVRfTUlCX1NEUjE2X0JVU1lfTUFTSwkJR0VOTUFT SygyMywgMCkNCisNCisjZGVmaW5lIE1UX01JQl9TRFIzNihfYmFuZCkJCU1UX1dGX01JQihfYmFu ZCwgMHgwOTgpDQorI2RlZmluZSBNVF9NSUJfU0RSMzZfVFhUSU1FX01BU0sJR0VOTUFTSygyMywg MCkNCisjZGVmaW5lIE1UX01JQl9TRFIzNyhfYmFuZCkJCU1UX1dGX01JQihfYmFuZCwgMHgwOWMp DQorI2RlZmluZSBNVF9NSUJfU0RSMzdfUlhUSU1FX01BU0sJR0VOTUFTSygyMywgMCkNCisNCisj ZGVmaW5lIE1UX01JQl9NQl9TRFIwKF9iYW5kLCBuKQlNVF9XRl9NSUIoX2JhbmQsIDB4MTAwICsg KChuKSA8PCA0KSkNCisjZGVmaW5lIE1UX01JQl9SVFNfUkVUUklFU19DT1VOVF9NQVNLCUdFTk1B U0soMzEsIDE2KQ0KKyNkZWZpbmUgTVRfTUlCX1JUU19DT1VOVF9NQVNLCQlHRU5NQVNLKDE1LCAw KQ0KKw0KKyNkZWZpbmUgTVRfTUlCX01CX1NEUjEoX2JhbmQsIG4pCU1UX1dGX01JQihfYmFuZCwg MHgxMDQgKyAoKG4pIDw8IDQpKQ0KKyNkZWZpbmUgTVRfTUlCX0JBX01JU1NfQ09VTlRfTUFTSwlH RU5NQVNLKDE1LCAwKQ0KKyNkZWZpbmUgTVRfTUlCX0FDS19GQUlMX0NPVU5UX01BU0sJR0VOTUFT SygzMSwgMTYpDQorDQorI2RlZmluZSBNVF9NSUJfTUJfU0RSMihfYmFuZCwgbikJTVRfV0ZfTUlC KF9iYW5kLCAweDEwOCArICgobikgPDwgNCkpDQorI2RlZmluZSBNVF9NSUJfRlJBTUVfUkVUUklF U19DT1VOVF9NQVNLCUdFTk1BU0soMTUsIDApDQorDQorI2RlZmluZSBNVF9UWF9BR0dfQ05UKF9i YW5kLCBuKQkJTVRfV0ZfTUlCKF9iYW5kLCAweDBhOCArICgobikgPDwgMikpDQorI2RlZmluZSBN VF9UWF9BR0dfQ05UMihfYmFuZCwgbikJTVRfV0ZfTUlCKF9iYW5kLCAweDE2NCArICgobikgPDwg MikpDQorI2RlZmluZSBNVF9NSUJfQVJORyhfYmFuZCwgbikJCU1UX1dGX01JQihfYmFuZCwgMHg0 YjggKyAoKG4pIDw8IDIpKQ0KKyNkZWZpbmUgTVRfTUlCX0FSTkNSX1JBTkdFKHZhbCwgbikJKCgo dmFsKSA+PiAoKG4pIDw8IDMpKSAmIEdFTk1BU0soNywgMCkpDQorDQorI2RlZmluZSBNVF9XVEJM T05fVE9QX0JBU0UJCTB4MzQwMDANCisjZGVmaW5lIE1UX1dUQkxPTl9UT1Aob2ZzKQkJKE1UX1dU QkxPTl9UT1BfQkFTRSArIChvZnMpKQ0KKyNkZWZpbmUgTVRfV1RCTE9OX1RPUF9XRFVDUgkJTVRf V1RCTE9OX1RPUCgweDApDQorI2RlZmluZSBNVF9XVEJMT05fVE9QX1dEVUNSX0dST1VQCUdFTk1B U0soMiwgMCkNCisNCisjZGVmaW5lIE1UX1dUQkxfVVBEQVRFCQkJTVRfV1RCTE9OX1RPUCgweDAz MCkNCisjZGVmaW5lIE1UX1dUQkxfVVBEQVRFX1dMQU5fSURYCQlHRU5NQVNLKDksIDApDQorI2Rl ZmluZSBNVF9XVEJMX1VQREFURV9BRE1fQ09VTlRfQ0xFQVIJQklUKDEyKQ0KKyNkZWZpbmUgTVRf V1RCTF9VUERBVEVfQlVTWQkJQklUKDMxKQ0KKw0KKyNkZWZpbmUgTVRfV1RCTF9CQVNFCQkJMHgz ODAwMA0KKyNkZWZpbmUgTVRfV1RCTF9MTUFDX0lECQkJR0VOTUFTSygxNCwgOCkNCisjZGVmaW5l IE1UX1dUQkxfTE1BQ19EVwkJCUdFTk1BU0soNywgMikNCisjZGVmaW5lIE1UX1dUQkxfTE1BQ19P RkZTKF9pZCwgX2R3KQkoTVRfV1RCTF9CQVNFIHwgXA0KKwkJCQkJRklFTERfUFJFUChNVF9XVEJM X0xNQUNfSUQsIF9pZCkgfCBcDQorCQkJCQlGSUVMRF9QUkVQKE1UX1dUQkxfTE1BQ19EVywgX2R3 KSkNCisNCisvKiBBR0c6IGJhbmQgMCgweDIwODAwKSwgYmFuZCAxKDB4YTA4MDApICovDQorI2Rl ZmluZSBNVF9XRl9BR0dfQkFTRShfYmFuZCkJCSgoX2JhbmQpID8gMHhhMDgwMCA6IDB4MjA4MDAp DQorI2RlZmluZSBNVF9XRl9BR0coX2JhbmQsIG9mcykJCShNVF9XRl9BR0dfQkFTRShfYmFuZCkg KyAob2ZzKSkNCisNCisjZGVmaW5lIE1UX0FHR19BQ1IwKF9iYW5kKQkJTVRfV0ZfQUdHKF9iYW5k LCAweDA4NCkNCisjZGVmaW5lIE1UX0FHR19BQ1JfQ0ZFTkRfUkFURQkJR0VOTUFTSygxMywgMCkN CisjZGVmaW5lIE1UX0FHR19BQ1JfQkFSX1JBVEUJCUdFTk1BU0soMjksIDE2KQ0KKw0KKy8qIEFS QjogYmFuZCAwKDB4MjBjMDApLCBiYW5kIDEoMHhhMGMwMCkgKi8NCisjZGVmaW5lIE1UX1dGX0FS Ql9CQVNFKF9iYW5kKQkJKChfYmFuZCkgPyAweGEwYzAwIDogMHgyMGMwMCkNCisjZGVmaW5lIE1U X1dGX0FSQihfYmFuZCwgb2ZzKQkJKE1UX1dGX0FSQl9CQVNFKF9iYW5kKSArIChvZnMpKQ0KKw0K KyNkZWZpbmUgTVRfQVJCX1NDUihfYmFuZCkJCU1UX1dGX0FSQihfYmFuZCwgMHgwODApDQorI2Rl ZmluZSBNVF9BUkJfU0NSX1RYX0RJU0FCTEUJCUJJVCg4KQ0KKyNkZWZpbmUgTVRfQVJCX1NDUl9S WF9ESVNBQkxFCQlCSVQoOSkNCisNCisvKiBSTUFDOiBiYW5kIDAoMHgyMTQwMCksIGJhbmQgMSgw eGExNDAwKSAqLw0KKyNkZWZpbmUgTVRfV0ZfUk1BQ19CQVNFKF9iYW5kKQkJKChfYmFuZCkgPyAw eGExNDAwIDogMHgyMTQwMCkNCisjZGVmaW5lIE1UX1dGX1JNQUMoX2JhbmQsIG9mcykJCShNVF9X Rl9STUFDX0JBU0UoX2JhbmQpICsgKG9mcykpDQorDQorI2RlZmluZSBNVF9XRl9SRkNSKF9iYW5k KQkJTVRfV0ZfUk1BQyhfYmFuZCwgMHgwMDApDQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfU1RC Q19NVUxUSQlCSVQoMCkNCisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9GQ1NGQUlMCQlCSVQoMSkN CisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9WRVJTSU9OCQlCSVQoMykNCisjZGVmaW5lIE1UX1dG X1JGQ1JfRFJPUF9QUk9CRVJFUQlCSVQoNCkNCisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9NQ0FT VAkJQklUKDUpDQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfQkNBU1QJCUJJVCg2KQ0KKyNkZWZp bmUgTVRfV0ZfUkZDUl9EUk9QX01DQVNUX0ZJTFRFUkVECUJJVCg3KQ0KKyNkZWZpbmUgTVRfV0Zf UkZDUl9EUk9QX0EzX01BQwkJQklUKDgpDQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfQTNfQlNT SUQJQklUKDkpDQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfQTJfQlNTSUQJQklUKDEwKQ0KKyNk ZWZpbmUgTVRfV0ZfUkZDUl9EUk9QX09USEVSX0JFQUNPTglCSVQoMTEpDQorI2RlZmluZSBNVF9X Rl9SRkNSX0RST1BfRlJBTUVfUkVQT1JUCUJJVCgxMikNCisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJP UF9DVExfUlNWCQlCSVQoMTMpDQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfQ1RTCQlCSVQoMTQp DQorI2RlZmluZSBNVF9XRl9SRkNSX0RST1BfUlRTCQlCSVQoMTUpDQorI2RlZmluZSBNVF9XRl9S RkNSX0RST1BfRFVQTElDQVRFCUJJVCgxNikNCisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9PVEhF Ul9CU1MJQklUKDE3KQ0KKyNkZWZpbmUgTVRfV0ZfUkZDUl9EUk9QX09USEVSX1VDCUJJVCgxOCkN CisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9PVEhFUl9USU0JQklUKDE5KQ0KKyNkZWZpbmUgTVRf V0ZfUkZDUl9EUk9QX05EUEEJCUJJVCgyMCkNCisjZGVmaW5lIE1UX1dGX1JGQ1JfRFJPUF9VTldB TlRFRF9DVEwJQklUKDIxKQ0KKw0KKyNkZWZpbmUgTVRfV0ZfUkZDUjEoX2JhbmQpCQlNVF9XRl9S TUFDKF9iYW5kLCAweDAwNCkNCisjZGVmaW5lIE1UX1dGX1JGQ1IxX0RST1BfQUNLCQlCSVQoNCkN CisjZGVmaW5lIE1UX1dGX1JGQ1IxX0RST1BfQkZfUE9MTAlCSVQoNSkNCisjZGVmaW5lIE1UX1dG X1JGQ1IxX0RST1BfQkEJCUJJVCg2KQ0KKyNkZWZpbmUgTVRfV0ZfUkZDUjFfRFJPUF9DRkVORAkJ QklUKDcpDQorI2RlZmluZSBNVF9XRl9SRkNSMV9EUk9QX0NGQUNLCQlCSVQoOCkNCisNCisjZGVm aW5lIE1UX1dGX1JNQUNfTUlCX1RJTUUwKF9iYW5kKQlNVF9XRl9STUFDKF9iYW5kLCAweDAzYzQp DQorI2RlZmluZSBNVF9XRl9STUFDX01JQl9SWFRJTUVfQ0xSCUJJVCgzMSkNCisjZGVmaW5lIE1U X1dGX1JNQUNfTUlCX1JYVElNRV9FTglCSVQoMzApDQorDQorI2RlZmluZSBNVF9XRl9STUFDX01J Ql9BSVJUSU1FMTQoX2JhbmQpCU1UX1dGX1JNQUMoX2JhbmQsIDB4MDNiOCkNCisjZGVmaW5lIE1U X01JQl9PQlNTVElNRV9NQVNLCQlHRU5NQVNLKDIzLCAwKQ0KKyNkZWZpbmUgTVRfV0ZfUk1BQ19N SUJfQUlSVElNRTAoX2JhbmQpCU1UX1dGX1JNQUMoX2JhbmQsIDB4MDM4MCkNCisNCisvKiBXRkRN QTAgKi8NCisjZGVmaW5lIE1UX1dGRE1BMF9CQVNFCQkJMHhkNDAwMA0KKyNkZWZpbmUgTVRfV0ZE TUEwKG9mcykJCQkoTVRfV0ZETUEwX0JBU0UgKyAob2ZzKSkNCisNCisjZGVmaW5lIE1UX1dGRE1B MF9SU1QJCQlNVF9XRkRNQTAoMHgxMDApDQorI2RlZmluZSBNVF9XRkRNQTBfUlNUX0xPR0lDX1JT VAkJQklUKDQpDQorI2RlZmluZSBNVF9XRkRNQTBfUlNUX0RNQVNIRExfQUxMX1JTVAlCSVQoNSkN CisNCisjZGVmaW5lIE1UX1dGRE1BMF9CVVNZX0VOQQkJTVRfV0ZETUEwKDB4MTNjKQ0KKyNkZWZp bmUgTVRfV0ZETUEwX0JVU1lfRU5BX1RYX0ZJRk8wCUJJVCgwKQ0KKyNkZWZpbmUgTVRfV0ZETUEw X0JVU1lfRU5BX1RYX0ZJRk8xCUJJVCgxKQ0KKyNkZWZpbmUgTVRfV0ZETUEwX0JVU1lfRU5BX1JY X0ZJRk8JQklUKDIpDQorDQorI2RlZmluZSBNVF9XRkRNQTBfR0xPX0NGRwkJTVRfV0ZETUEwKDB4 MjA4KQ0KKyNkZWZpbmUgTVRfV0ZETUEwX0dMT19DRkdfVFhfRE1BX0VOCUJJVCgwKQ0KKyNkZWZp bmUgTVRfV0ZETUEwX0dMT19DRkdfUlhfRE1BX0VOCUJJVCgyKQ0KKw0KKyNkZWZpbmUgTVRfV0ZE TUEwX1JTVF9EVFhfUFRSCQlNVF9XRkRNQTAoMHgyMGMpDQorI2RlZmluZSBNVF9XRkRNQTBfUFJJ X0RMWV9JTlRfQ0ZHMAlNVF9XRkRNQTAoMHgyZjApDQorDQorI2RlZmluZSBNVF9SWF9EQVRBX1JJ TkdfQkFTRQkJTVRfV0ZETUEwKDB4NTAwKQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUEwX1JYX1JJTkcw X0VYVF9DVFJMCU1UX1dGRE1BMCgweDY4MCkNCisjZGVmaW5lIE1UX1dGRE1BMF9SWF9SSU5HMV9F WFRfQ1RSTAlNVF9XRkRNQTAoMHg2ODQpDQorI2RlZmluZSBNVF9XRkRNQTBfUlhfUklORzJfRVhU X0NUUkwJTVRfV0ZETUEwKDB4Njg4KQ0KKw0KKy8qIFdGRE1BMSAqLw0KKyNkZWZpbmUgTVRfV0ZE TUExX0JBU0UJCQkweGQ1MDAwDQorI2RlZmluZSBNVF9XRkRNQTEob2ZzKQkJCShNVF9XRkRNQTFf QkFTRSArIChvZnMpKQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUExX1JTVAkJCU1UX1dGRE1BMSgweDEw MCkNCisjZGVmaW5lIE1UX1dGRE1BMV9SU1RfTE9HSUNfUlNUCQlCSVQoNCkNCisjZGVmaW5lIE1U X1dGRE1BMV9SU1RfRE1BU0hETF9BTExfUlNUCUJJVCg1KQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUEx X0JVU1lfRU5BCQlNVF9XRkRNQTEoMHgxM2MpDQorI2RlZmluZSBNVF9XRkRNQTFfQlVTWV9FTkFf VFhfRklGTzAJQklUKDApDQorI2RlZmluZSBNVF9XRkRNQTFfQlVTWV9FTkFfVFhfRklGTzEJQklU KDEpDQorI2RlZmluZSBNVF9XRkRNQTFfQlVTWV9FTkFfUlhfRklGTwlCSVQoMikNCisNCisjZGVm aW5lIE1UX01DVV9DTUQJCQlNVF9XRkRNQTEoMHgxZjApDQorI2RlZmluZSBNVF9NQ1VfQ01EX1NU T1BfRE1BX0ZXX1JFTE9BRAlCSVQoMSkNCisjZGVmaW5lIE1UX01DVV9DTURfU1RPUF9ETUEJCUJJ VCgyKQ0KKyNkZWZpbmUgTVRfTUNVX0NNRF9SRVNFVF9ET05FCQlCSVQoMykNCisjZGVmaW5lIE1U X01DVV9DTURfUkVDT1ZFUllfRE9ORQlCSVQoNCkNCisjZGVmaW5lIE1UX01DVV9DTURfTk9STUFM X1NUQVRFCQlCSVQoNSkNCisjZGVmaW5lIE1UX01DVV9DTURfRVJST1JfTUFTSwkJR0VOTUFTSyg1 LCAxKQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUExX0dMT19DRkcJCU1UX1dGRE1BMSgweDIwOCkNCisj ZGVmaW5lIE1UX1dGRE1BMV9HTE9fQ0ZHX1RYX0RNQV9FTglCSVQoMCkNCisjZGVmaW5lIE1UX1dG RE1BMV9HTE9fQ0ZHX1JYX0RNQV9FTglCSVQoMikNCisjZGVmaW5lIE1UX1dGRE1BMV9HTE9fQ0ZH X09NSVRfVFhfSU5GTwlCSVQoMjgpDQorI2RlZmluZSBNVF9XRkRNQTFfR0xPX0NGR19PTUlUX1JY X0lORk8JQklUKDI3KQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUExX1JTVF9EVFhfUFRSCQlNVF9XRkRN QTEoMHgyMGMpDQorI2RlZmluZSBNVF9XRkRNQTFfUFJJX0RMWV9JTlRfQ0ZHMAlNVF9XRkRNQTEo MHgyZjApDQorDQorI2RlZmluZSBNVF9UWF9SSU5HX0JBU0UJCQlNVF9XRkRNQTEoMHgzMDApDQor I2RlZmluZSBNVF9SWF9FVkVOVF9SSU5HX0JBU0UJCU1UX1dGRE1BMSgweDUwMCkNCisNCisjZGVm aW5lIE1UX1dGRE1BMV9UWF9SSU5HMF9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2MDApDQorI2RlZmlu ZSBNVF9XRkRNQTFfVFhfUklORzFfRVhUX0NUUkwJTVRfV0ZETUExKDB4NjA0KQ0KKyNkZWZpbmUg TVRfV0ZETUExX1RYX1JJTkcyX0VYVF9DVFJMCU1UX1dGRE1BMSgweDYwOCkNCisjZGVmaW5lIE1U X1dGRE1BMV9UWF9SSU5HM19FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2MGMpDQorI2RlZmluZSBNVF9X RkRNQTFfVFhfUklORzRfRVhUX0NUUkwJTVRfV0ZETUExKDB4NjEwKQ0KKyNkZWZpbmUgTVRfV0ZE TUExX1RYX1JJTkc1X0VYVF9DVFJMCU1UX1dGRE1BMSgweDYxNCkNCisjZGVmaW5lIE1UX1dGRE1B MV9UWF9SSU5HNl9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2MTgpDQorI2RlZmluZSBNVF9XRkRNQTFf VFhfUklORzdfRVhUX0NUUkwJTVRfV0ZETUExKDB4NjFjKQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUEx X1RYX1JJTkcxNl9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2NDApDQorI2RlZmluZSBNVF9XRkRNQTFf VFhfUklORzE3X0VYVF9DVFJMCU1UX1dGRE1BMSgweDY0NCkNCisjZGVmaW5lIE1UX1dGRE1BMV9U WF9SSU5HMThfRVhUX0NUUkwJTVRfV0ZETUExKDB4NjQ4KQ0KKyNkZWZpbmUgTVRfV0ZETUExX1RY X1JJTkcxOV9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2NGMpDQorI2RlZmluZSBNVF9XRkRNQTFfVFhf UklORzIwX0VYVF9DVFJMCU1UX1dGRE1BMSgweDY1MCkNCisjZGVmaW5lIE1UX1dGRE1BMV9UWF9S SU5HMjFfRVhUX0NUUkwJTVRfV0ZETUExKDB4NjU0KQ0KKyNkZWZpbmUgTVRfV0ZETUExX1RYX1JJ TkcyMl9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2NTgpDQorI2RlZmluZSBNVF9XRkRNQTFfVFhfUklO RzIzX0VYVF9DVFJMCU1UX1dGRE1BMSgweDY1YykNCisNCisjZGVmaW5lIE1UX1dGRE1BMV9SWF9S SU5HMF9FWFRfQ1RSTAlNVF9XRkRNQTEoMHg2ODApDQorI2RlZmluZSBNVF9XRkRNQTFfUlhfUklO RzFfRVhUX0NUUkwJTVRfV0ZETUExKDB4Njg0KQ0KKyNkZWZpbmUgTVRfV0ZETUExX1JYX1JJTkcy X0VYVF9DVFJMCU1UX1dGRE1BMSgweDY4OCkNCisjZGVmaW5lIE1UX1dGRE1BMV9SWF9SSU5HM19F WFRfQ1RSTAlNVF9XRkRNQTEoMHg2OGMpDQorDQorLyogV0ZETUEgQ1NSICovDQorI2RlZmluZSBN VF9XRkRNQV9FWFRfQ1NSX0JBU0UJCTB4ZDcwMDANCisjZGVmaW5lIE1UX1dGRE1BX0VYVF9DU1Io b2ZzKQkJKE1UX1dGRE1BX0VYVF9DU1JfQkFTRSArIChvZnMpKQ0KKw0KKyNkZWZpbmUgTVRfSU5U X1NPVVJDRV9DU1IJCU1UX1dGRE1BX0VYVF9DU1IoMHgxMCkNCisjZGVmaW5lIE1UX0lOVF9NQVNL X0NTUgkJCU1UX1dGRE1BX0VYVF9DU1IoMHgxNCkNCisjZGVmaW5lIE1UX0lOVF9SWF9ET05FX0RB VEEJCUJJVCgxNikNCisjZGVmaW5lIE1UX0lOVF9SWF9ET05FX1dNCQlCSVQoMCkNCisjZGVmaW5l IE1UX0lOVF9SWF9ET05FX1dBCQlCSVQoMSkNCisjZGVmaW5lIE1UX0lOVF9SWF9ET05FKF9uKQkJ KChfbikgPyBCSVQoKF9uKSAtIDEpIDogQklUKDE2KSkNCisjZGVmaW5lIE1UX0lOVF9SWF9ET05F X0FMTAkJKEJJVCgwKSB8IEJJVCgxKSB8IEJJVCgxNikpDQorI2RlZmluZSBNVF9JTlRfVFhfRE9O RV9BTEwJCShCSVQoMTUpIHwgR0VOTUFTSygyNywgMjYpIHwgQklUKDMwKSkNCisjZGVmaW5lIE1U X0lOVF9NQ1VfQ01ECQkJQklUKDI5KQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUFfRVhUX0NTUl9ISUZf TUlTQwlNVF9XRkRNQV9FWFRfQ1NSKDB4NDQpDQorI2RlZmluZSBNVF9XRkRNQV9FWFRfQ1NSX0hJ Rl9NSVNDX0JVU1kJQklUKDApDQorDQorLyogV0ZETUEwIFBDSUUxICovDQorI2RlZmluZSBNVF9X RkRNQTBfUENJRTFfQkFTRQkJCTB4ZDgwMDANCisjZGVmaW5lIE1UX1dGRE1BMF9QQ0lFMShvZnMp CQkJKE1UX1dGRE1BMF9QQ0lFMV9CQVNFICsgKG9mcykpDQorDQorI2RlZmluZSBNVF9XRkRNQTBf UENJRTFfQlVTWV9FTkEJCU1UX1dGRE1BMF9QQ0lFMSgweDEzYykNCisjZGVmaW5lIE1UX1dGRE1B MF9QQ0lFMV9CVVNZX0VOQV9UWF9GSUZPMAlCSVQoMCkNCisjZGVmaW5lIE1UX1dGRE1BMF9QQ0lF MV9CVVNZX0VOQV9UWF9GSUZPMQlCSVQoMSkNCisjZGVmaW5lIE1UX1dGRE1BMF9QQ0lFMV9CVVNZ X0VOQV9SWF9GSUZPCUJJVCgyKQ0KKw0KKy8qIFdGRE1BMSBQQ0lFMSAqLw0KKyNkZWZpbmUgTVRf V0ZETUExX1BDSUUxX0JBU0UJCQkweGQ5MDAwDQorI2RlZmluZSBNVF9XRkRNQTFfUENJRTEob2Zz KQkJCShNVF9XRkRNQTBfUENJRTFfQkFTRSArIChvZnMpKQ0KKw0KKyNkZWZpbmUgTVRfV0ZETUEx X1BDSUUxX0JVU1lfRU5BCQlNVF9XRkRNQTFfUENJRTEoMHgxM2MpDQorI2RlZmluZSBNVF9XRkRN QTFfUENJRTFfQlVTWV9FTkFfVFhfRklGTzAJQklUKDApDQorI2RlZmluZSBNVF9XRkRNQTFfUENJ RTFfQlVTWV9FTkFfVFhfRklGTzEJQklUKDEpDQorI2RlZmluZSBNVF9XRkRNQTFfUENJRTFfQlVT WV9FTkFfUlhfRklGTwlCSVQoMikNCisNCisjZGVmaW5lIE1UX0lORlJBX0NGR19CQVNFCQkweGYx MDAwDQorI2RlZmluZSBNVF9JTkZSQShvZnMpCQkJKE1UX0lORlJBX0NGR19CQVNFICsgKG9mcykp DQorDQorI2RlZmluZSBNVF9ISUZfUkVNQVBfTDEJCQlNVF9JTkZSQSgweDFhYykNCisjZGVmaW5l IE1UX0hJRl9SRU1BUF9MMV9NQVNLCQlHRU5NQVNLKDE1LCAwKQ0KKyNkZWZpbmUgTVRfSElGX1JF TUFQX0wxX09GRlNFVAkJR0VOTUFTSygxNSwgMCkNCisjZGVmaW5lIE1UX0hJRl9SRU1BUF9MMV9C QVNFCQlHRU5NQVNLKDMxLCAxNikNCisjZGVmaW5lIE1UX0hJRl9SRU1BUF9CQVNFX0wxCQkweGUw MDAwDQorDQorI2RlZmluZSBNVF9ISUZfUkVNQVBfTDIJCQlNVF9JTkZSQSgweDFiMCkNCisjZGVm aW5lIE1UX0hJRl9SRU1BUF9MMl9NQVNLCQlHRU5NQVNLKDE5LCAwKQ0KKyNkZWZpbmUgTVRfSElG X1JFTUFQX0wyX09GRlNFVAkJR0VOTUFTSygxMSwgMCkNCisjZGVmaW5lIE1UX0hJRl9SRU1BUF9M Ml9CQVNFCQlHRU5NQVNLKDMxLCAxMikNCisjZGVmaW5lIE1UX0hJRl9SRU1BUF9CQVNFX0wyCQkw eDAwMDAwDQorDQorI2RlZmluZSBNVF9UT1BfQkFTRQkJCTB4MTgwNjAwMDANCisjZGVmaW5lIE1U X1RPUChvZnMpCQkJKE1UX1RPUF9CQVNFICsgKG9mcykpDQorDQorI2RlZmluZSBNVF9UT1BfTFBD Ul9IT1NUX0JBTkQwCQlNVF9UT1AoMHgxMCkNCisjZGVmaW5lIE1UX1RPUF9MUENSX0hPU1RfRldf T1dOCQlCSVQoMCkNCisjZGVmaW5lIE1UX1RPUF9MUENSX0hPU1RfRFJWX09XTglCSVQoMSkNCisN CisjZGVmaW5lIE1UX1RPUF9NSVNDCQkJTVRfVE9QKDB4ZjApDQorI2RlZmluZSBNVF9UT1BfTUlT Q19GV19TVEFURQkJR0VOTUFTSygyLCAwKQ0KKw0KKyNkZWZpbmUgTVRfSFdfQk9VTkQJCQkweDcw MDEwMDIwDQorI2RlZmluZSBNVF9IV19DSElQSUQJCQkweDcwMDEwMjAwDQorI2RlZmluZSBNVF9I V19SRVYJCQkweDcwMDEwMjA0DQorDQorI2RlZmluZSBNVF9QQ0lFX01BQ19CQVNFCQkweDc0MDMw MDAwDQorI2RlZmluZSBNVF9QQ0lFX01BQyhvZnMpCQkoTVRfUENJRV9NQUNfQkFTRSArIChvZnMp KQ0KKyNkZWZpbmUgTVRfUENJRV9NQUNfSU5UX0VOQUJMRQkJTVRfUENJRV9NQUMoMHgxODgpDQor DQorLyogUEhZOiBiYW5kIDAoMHg4MzA4MDAwMCksIGJhbmQgMSgweDgzMDkwMDAwKSAqLw0KKyNk ZWZpbmUgTVRfV0ZfUEhZX0JBU0UJCQkweDgzMDgwMDAwDQorI2RlZmluZSBNVF9XRl9QSFkob2Zz KQkJCShNVF9XRl9QSFlfQkFTRSArIChvZnMpKQ0KKw0KKyNkZWZpbmUgTVRfV0ZfUEhZX1JYX0NU UkwxKF9waHkpCU1UX1dGX1BIWSgweDIwMDQgKyAoKF9waHkpIDw8IDE2KSkNCisjZGVmaW5lIE1U X1dGX1BIWV9SWF9DVFJMMV9TVFNDTlRfRU4JR0VOTUFTSygxMSwgOSkNCisNCisjZW5kaWYNCi0t IA0KMi4xOC4wDQo= 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=-9.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT 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 A5EBEC2BA2B for ; Fri, 10 Apr 2020 08:55:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4FC0F20787 for ; Fri, 10 Apr 2020 08:55:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Yo79+zh5"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="ujTql5gW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4FC0F20787 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/H8nPKDynrb48qSzO3GuWhb8M7BYi5NHzmYvx3AnXpM=; b=Yo79+zh57xHb1O BdlcX5eu/2ZXbCBkp1OOJbH6f5pjAOcUP7obFnRcOqa/j80N1bo9E0j4cPrm0VwMOwz2VjL23y80y EamvWnTCDdBtcVI0nG4Cj6wV+hehQe/Mg0FEdny3i23wSin3tK2lFzAFzK0JAosge3n7+eeqdQfOp JyFfMydCMMzTVWeaJIFnegAd8SBbBngzX0BVat6JjRj4JUy2dKIny6/k1bujaUY8tspdTCuPqhM9B ivqaU98PxGD2MvoBkeCTCEmBkDcJswhpDZb7LPN31EY81uNm1dk34m+CSkqu2bEn9Ro3MtIKt1/Ws HtDAlIGkKZRf6P/U2BPQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jMpRW-0007nL-Kx; Fri, 10 Apr 2020 08:55:18 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jMpRM-0005u4-0j for linux-mediatek@lists.infradead.org; Fri, 10 Apr 2020 08:55:16 +0000 X-UUID: 82a9f2f951ec411e9a53f82464533afb-20200410 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=Gw113brImNWXUUgWmPAzgFFc8mZhDULwKevqZGI9c0I=; b=ujTql5gW7xkbV14yYN6fza/Qor1lkX4fVQ8VGPzNqJXzxszoytNC9d5AOPkov9Xb5CzcG5vSTPyuslKeSajy3gZURg4qu/d8QqFyzqIGyo+f8F2047mPy82J1jQX3+PdphxJ0Rk6aDAzpUzj6rNaNppy0Q8xEoMAB2GgLtktVz0=; X-UUID: 82a9f2f951ec411e9a53f82464533afb-20200410 Received: from mtkcas67.mediatek.inc [(172.29.193.45)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 336605008; Fri, 10 Apr 2020 00:55:00 -0800 Received: from mtkmbs08n1.mediatek.inc (172.21.101.55) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 10 Apr 2020 01:54:59 -0700 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 10 Apr 2020 16:54:56 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 10 Apr 2020 16:54:56 +0800 From: Ryder Lee To: Felix Fietkau , Lorenzo Bianconi Subject: [PATCH 06/16] mt76: add mac80211 driver for MT7915 PCIe-based chipsets Date: Fri, 10 Apr 2020 16:54:43 +0800 Message-ID: <3d9a74111aaadde7be00ec7c8c53d095daf4f9d2.1586507878.git.ryder.lee@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: YF Luo , Evelyn Tsai , linux-wireless@vger.kernel.org, Sean Wang , Chih-Min Chen , Ryder Lee , Yiwei Chung , linux-mediatek@lists.infradead.org, Shayne Chen Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Add support for the MediaTek latest generation IEEE 802.11ax 4x4 device MT7915E, which supports concurrent dual-band operation at both 5GHz and 2.4GHz. Note that this patch just add basic part and will add more HE capabilities support in the further patches. The driver supports AP, Station, Mesh and monitor mode. Signed-off-by: Ryder Lee Signed-off-by: Shayne Chen Signed-off-by: Chih-Min Chen Tested-by: Evelyn Tsai Acked-by: Yiwei Chung Acked-by: YF Luo --- drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/Makefile | 1 + .../net/wireless/mediatek/mt76/mt7915/Kconfig | 13 + .../wireless/mediatek/mt76/mt7915/Makefile | 6 + .../wireless/mediatek/mt76/mt7915/debugfs.c | 245 ++ .../net/wireless/mediatek/mt76/mt7915/dma.c | 283 ++ .../wireless/mediatek/mt76/mt7915/eeprom.c | 125 + .../wireless/mediatek/mt76/mt7915/eeprom.h | 78 + .../net/wireless/mediatek/mt76/mt7915/init.c | 392 +++ .../net/wireless/mediatek/mt76/mt7915/mac.c | 1310 ++++++++++ .../net/wireless/mediatek/mt76/mt7915/mac.h | 330 +++ .../net/wireless/mediatek/mt76/mt7915/main.c | 743 ++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.c | 2319 +++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 837 ++++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 442 ++++ .../net/wireless/mediatek/mt76/mt7915/pci.c | 165 ++ .../net/wireless/mediatek/mt76/mt7915/regs.h | 344 +++ 17 files changed, 7634 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/Kconfig create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/Makefile create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/dma.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/init.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mac.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/main.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mcu.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mcu.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/pci.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/regs.h diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index cbc2d8a5d354..41533a0e1720 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -24,3 +24,4 @@ source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index d7a1ddc9e407..1df04156f97f 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT7603E) += mt7603/ obj-$(CONFIG_MT7615E) += mt7615/ +obj-$(CONFIG_MT7915E) += mt7915/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig new file mode 100644 index 000000000000..1737fb2b4adc --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +config MT7915E + tristate "MediaTek MT7915E (PCIe) support" + select MT76_CORE + depends on MAC80211 + depends on PCI + help + This adds support for MT7915-based wireless PCIe devices, + which support concurrent dual-band operation at both 5GHz + and 2.4GHz IEEE 802.11ax 4x4:4SS 1024-QAM, 160MHz channels, + OFDMA, spatial reuse and dual carrier modulation. + + To compile this driver as a module, choose M here. diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile new file mode 100644 index 000000000000..57fe726cc38b --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -0,0 +1,6 @@ +#SPDX-License-Identifier: ISC + +obj-$(CONFIG_MT7915E) += mt7915e.o + +mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ + debugfs.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c new file mode 100644 index 000000000000..152ae0617f3d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" +#include "eeprom.h" + +/** global debugfs **/ + +/* test knob of system layer 1/2 error recovery */ +static int mt7915_ser_trigger_set(void *data, u64 val) +{ + enum { + SER_SET_RECOVER_L1 = 1, + SER_SET_RECOVER_L2, + SER_ENABLE = 2, + SER_RECOVER + }; + struct mt7915_dev *dev = data; + int ret = 0; + + switch (val) { + case SER_SET_RECOVER_L1: + case SER_SET_RECOVER_L2: + /* fall through */ + ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0); + if (ret) + return ret; + + return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0); + default: + break; + } + + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL, + mt7915_ser_trigger_set, "%lld\n"); + +static int +mt7915_radar_trigger(void *data, u64 val) +{ + struct mt7915_dev *dev = data; + + return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0); +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, + mt7915_radar_trigger, "%lld\n"); + +static int +mt7915_dbdc_set(void *data, u64 val) +{ + struct mt7915_dev *dev = data; + + if (val) + mt7915_register_ext_phy(dev); + else + mt7915_unregister_ext_phy(dev); + + return 0; +} + +static int +mt7915_dbdc_get(void *data, u64 *val) +{ + struct mt7915_dev *dev = data; + + *val = !!mt7915_ext_phy(dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7915_dbdc_get, + mt7915_dbdc_set, "%lld\n"); + +static void +mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, + struct seq_file *file) +{ + struct mt7915_dev *dev = file->private; + bool ext_phy = phy != &dev->phy; + int bound[15], range[4], i, n; + + if (!phy) + return; + + /* Tx ampdu stat */ + for (i = 0; i < ARRAY_SIZE(range); i++) + range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i)); + + for (i = 0; i < ARRAY_SIZE(bound); i++) + bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1; + + seq_printf(file, "\nPhy %d\n", ext_phy); + + seq_printf(file, "Length: %8d | ", bound[0]); + for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) + seq_printf(file, "%3d -%3d | ", + bound[i] + 1, bound[i + 1]); + + seq_puts(file, "\nCount: "); + n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + for (i = 0; i < ARRAY_SIZE(bound); i++) + seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + n]); + seq_puts(file, "\n"); + + seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); +} + +static int +mt7915_tx_stats_read(struct seq_file *file, void *data) +{ + struct mt7915_dev *dev = file->private; + int stat[8], i, n; + + mt7915_ampdu_stat_read_phy(&dev->phy, file); + mt7915_ampdu_stat_read_phy(mt7915_ext_phy(dev), file); + + /* Tx amsdu info */ + seq_puts(file, "Tx MSDU stat:\n"); + for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) { + stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); + n += stat[i]; + } + + for (i = 0; i < ARRAY_SIZE(stat); i++) { + seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ", + i + 1, stat[i]); + if (n != 0) + seq_printf(file, "(%d%%)\n", stat[i] * 100 / n); + else + seq_puts(file, "\n"); + } + + return 0; +} + +static int +mt7915_tx_stats_open(struct inode *inode, struct file *f) +{ + return single_open(f, mt7915_tx_stats_read, inode->i_private); +} + +static const struct file_operations fops_tx_stats = { + .open = mt7915_tx_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mt7915_read_temperature(struct seq_file *s, void *data) +{ + struct mt7915_dev *dev = dev_get_drvdata(s->private); + int temp; + + /* cpu */ + temp = mt7915_mcu_get_temperature(dev, 0); + seq_printf(s, "Temperature: %d\n", temp); + + return 0; +} + +static int +mt7915_queues_acq(struct seq_file *s, void *data) +{ + struct mt7915_dev *dev = dev_get_drvdata(s->private); + int i; + + for (i = 0; i < 16; i++) { + int j, acs = i / 4, index = i % 4; + u32 ctrl, val, qlen = 0; + + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); + ctrl = BIT(31) | BIT(15) | (acs << 8); + + for (j = 0; j < 32; j++) { + if (val & BIT(j)) + continue; + + mt76_wr(dev, MT_PLE_FL_Q0_CTRL, + ctrl | (j + (index << 5))); + qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, + GENMASK(11, 0)); + } + seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); + } + + return 0; +} + +static int +mt7915_queues_read(struct seq_file *s, void *data) +{ + struct mt7915_dev *dev = dev_get_drvdata(s->private); + static const struct { + char *queue; + int id; + } queue_map[] = { + { "WFDMA0", MT_TXQ_BE }, + { "MCUWM", MT_TXQ_MCU }, + { "MCUWA", MT_TXQ_MCU_WA }, + { "MCUFWQ", MT_TXQ_FWDL }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) { + struct mt76_sw_queue *q = &dev->mt76.q_tx[queue_map[i].id]; + + if (!q->q) + continue; + + seq_printf(s, + "%s: queued=%d head=%d tail=%d\n", + queue_map[i].queue, q->q->queued, q->q->head, + q->q->tail); + } + + return 0; +} + +int mt7915_init_debugfs(struct mt7915_dev *dev) +{ + struct dentry *dir; + + dir = mt76_register_debugfs(&dev->mt76); + if (!dir) + return -ENOMEM; + + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt7915_queues_read); + debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, + mt7915_queues_acq); + debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats); + debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); + debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); + /* test knobs */ + debugfs_create_file("radar_trigger", 0200, dir, dev, + &fops_radar_trigger); + debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger); + debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, + mt7915_read_temperature); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c new file mode 100644 index 000000000000..0156e6e5933a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" +#include "../dma.h" +#include "mac.h" + +static int +mt7915_init_tx_queues(struct mt7915_dev *dev, int n_desc) +{ + struct mt76_sw_queue *q; + struct mt76_queue *hwq; + int err, i; + + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; + + err = mt76_queue_alloc(dev, hwq, MT7915_TXQ_BAND0, n_desc, 0, + MT_TX_RING_BASE); + if (err < 0) + return err; + + for (i = 0; i < MT_TXQ_MCU; i++) { + q = &dev->mt76.q_tx[i]; + INIT_LIST_HEAD(&q->swq); + q->q = hwq; + } + + return 0; +} + +static int +mt7915_init_mcu_queue(struct mt7915_dev *dev, struct mt76_sw_queue *q, + int idx, int n_desc) +{ + struct mt76_queue *hwq; + int err; + + hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); + if (!hwq) + return -ENOMEM; + + err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); + if (err < 0) + return err; + + INIT_LIST_HEAD(&q->swq); + q->q = hwq; + + return 0; +} + +void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + __le32 *rxd = (__le32 *)skb->data; + enum rx_pkt_type type; + + type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + + switch (type) { + case PKT_TYPE_TXRX_NOTIFY: + mt7915_mac_tx_free(dev, skb); + break; + case PKT_TYPE_RX_EVENT: + mt7915_mcu_rx_event(dev, skb); + break; + case PKT_TYPE_NORMAL: + if (!mt7915_mac_fill_rx(dev, skb)) { + mt76_rx(&dev->mt76, q, skb); + return; + } + /* fall through */ + default: + dev_kfree_skb(skb); + break; + } +} + +static int mt7915_poll_tx(struct napi_struct *napi, int budget) +{ + static const u8 queue_map[] = { + MT_TXQ_MCU, + MT_TXQ_MCU_WA, + MT_TXQ_BE + }; + struct mt7915_dev *dev; + int i; + + dev = container_of(napi, struct mt7915_dev, mt76.tx_napi); + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) + mt76_queue_tx_cleanup(dev, queue_map[i], false); + + if (napi_complete_done(napi, 0)) + mt7915_irq_enable(dev, MT_INT_TX_DONE_ALL); + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) + mt76_queue_tx_cleanup(dev, queue_map[i], false); + + mt7915_mac_sta_poll(dev); + + tasklet_schedule(&dev->mt76.tx_tasklet); + + return 0; +} + +void mt7915_dma_prefetch(struct mt7915_dev *dev) +{ +#define PREFETCH(base, depth) ((base) << 16 | (depth)) + + mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x40, 0x4)); + mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x80, 0x0)); + + mt76_wr(dev, MT_WFDMA1_TX_RING0_EXT_CTRL, PREFETCH(0x80, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING1_EXT_CTRL, PREFETCH(0xc0, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING2_EXT_CTRL, PREFETCH(0x100, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING3_EXT_CTRL, PREFETCH(0x140, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING4_EXT_CTRL, PREFETCH(0x180, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING5_EXT_CTRL, PREFETCH(0x1c0, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING6_EXT_CTRL, PREFETCH(0x200, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING7_EXT_CTRL, PREFETCH(0x240, 0x4)); + + mt76_wr(dev, MT_WFDMA1_TX_RING16_EXT_CTRL, PREFETCH(0x280, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING17_EXT_CTRL, PREFETCH(0x2c0, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING18_EXT_CTRL, PREFETCH(0x300, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING19_EXT_CTRL, PREFETCH(0x340, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING20_EXT_CTRL, PREFETCH(0x380, 0x4)); + mt76_wr(dev, MT_WFDMA1_TX_RING21_EXT_CTRL, PREFETCH(0x3c0, 0x0)); + + mt76_wr(dev, MT_WFDMA1_RX_RING0_EXT_CTRL, PREFETCH(0x3c0, 0x4)); + mt76_wr(dev, MT_WFDMA1_RX_RING1_EXT_CTRL, PREFETCH(0x400, 0x4)); + mt76_wr(dev, MT_WFDMA1_RX_RING2_EXT_CTRL, PREFETCH(0x440, 0x4)); + mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL, PREFETCH(0x480, 0x0)); +} + +int mt7915_dma_init(struct mt7915_dev *dev) +{ + int ret; + + mt76_dma_attach(&dev->mt76); + + /* configure global setting */ + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + + /* configure perfetch settings */ + mt7915_dma_prefetch(dev); + + /* reset dma idx */ + mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); + mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR, ~0); + + /* configure delay interrupt */ + mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0); + mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0); + + /* init tx queue */ + ret = mt7915_init_tx_queues(dev, MT7915_TX_RING_SIZE); + if (ret) + return ret; + + /* command to WM */ + ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7915_TXQ_MCU_WM, + MT7915_TX_MCU_RING_SIZE); + if (ret) + return ret; + + /* command to WA */ + ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU_WA], + MT7915_TXQ_MCU_WA, + MT7915_TX_MCU_RING_SIZE); + if (ret) + return ret; + + /* firmware download */ + ret = mt7915_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], + MT7915_TXQ_FWDL, + MT7915_TX_FWDL_RING_SIZE); + if (ret) + return ret; + + /* event from WM */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], + MT7915_RXQ_MCU_WM, MT7915_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + if (ret) + return ret; + + /* event from WA */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], + MT7915_RXQ_MCU_WA, MT7915_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + if (ret) + return ret; + + /* rx data */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, + MT7915_RX_RING_SIZE, MT_RX_BUF_SIZE, + MT_RX_DATA_RING_BASE); + if (ret) + return ret; + + ret = mt76_init_queues(dev); + if (ret < 0) + return ret; + + netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + mt7915_poll_tx, NAPI_POLL_WEIGHT); + napi_enable(&dev->mt76.tx_napi); + + /* hif wait WFDMA idle */ + mt76_set(dev, MT_WFDMA0_BUSY_ENA, + MT_WFDMA0_BUSY_ENA_TX_FIFO0 | + MT_WFDMA0_BUSY_ENA_TX_FIFO1 | + MT_WFDMA0_BUSY_ENA_RX_FIFO); + + mt76_set(dev, MT_WFDMA1_BUSY_ENA, + MT_WFDMA1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA1_BUSY_ENA_RX_FIFO); + + mt76_set(dev, MT_WFDMA0_PCIE1_BUSY_ENA, + MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO); + + mt76_set(dev, MT_WFDMA1_PCIE1_BUSY_ENA, + MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 | + MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 | + MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO); + + mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, + MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); + + /* set WFDMA Tx/Rx */ + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); + + /* enable interrupts for TX/RX rings */ + mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); + + return 0; +} + +void mt7915_dma_cleanup(struct mt7915_dev *dev) +{ + /* disable */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_clear(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN); + + /* reset */ + mt76_clear(dev, MT_WFDMA1_RST, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA1_RST, + MT_WFDMA1_RST_DMASHDL_ALL_RST | + MT_WFDMA1_RST_LOGIC_RST); + + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + tasklet_kill(&dev->mt76.tx_tasklet); + mt76_dma_cleanup(&dev->mt76); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c new file mode 100644 index 000000000000..2099dd40530f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include "mt7915.h" +#include "eeprom.h" + +static inline bool mt7915_efuse_valid(u8 val) +{ + return !(val == 0xff); +} + +u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) +{ + u8 *data = dev->mt76.eeprom.data; + + if (!mt7915_efuse_valid(data[offset])) + mt7915_mcu_get_eeprom(dev, offset); + + return data[offset]; +} + +static int mt7915_eeprom_load(struct mt7915_dev *dev) +{ + int ret; + + ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE); + if (ret < 0) + return ret; + + memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE); + + return 0; +} + +static int mt7915_check_eeprom(struct mt7915_dev *dev) +{ + u16 val; + u8 *eeprom = dev->mt76.eeprom.data; + + mt7915_eeprom_read(dev, 0); + val = get_unaligned_le16(eeprom); + + switch (val) { + case 0x7915: + return 0; + default: + return -EINVAL; + } +} + +static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) +{ + u8 *eeprom = dev->mt76.eeprom.data; + u8 tx_mask, max_nss = 4; + u32 val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF); + + val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val); + switch (val) { + case MT_EE_5GHZ: + dev->mt76.cap.has_5ghz = true; + break; + case MT_EE_2GHZ: + dev->mt76.cap.has_2ghz = true; + break; + default: + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + break; + } + + /* read tx mask from eeprom */ + tx_mask = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK, + eeprom[MT_EE_WIFI_CONF]); + if (!tx_mask || tx_mask > max_nss) + tx_mask = max_nss; + + dev->chainmask = BIT(tx_mask) - 1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; +} + +int mt7915_eeprom_init(struct mt7915_dev *dev) +{ + int ret; + + ret = mt7915_eeprom_load(dev); + if (ret < 0) + return ret; + + ret = mt7915_check_eeprom(dev); + if (ret) + return ret; + + mt7915_eeprom_parse_hw_cap(dev); + memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); + + mt76_eeprom_override(&dev->mt76); + + return 0; +} + +int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx) +{ + int index; + bool tssi_on; + + if (chain_idx > 3) + return -EINVAL; + + tssi_on = mt7915_tssi_enabled(dev, chan->band); + + if (chan->band == NL80211_BAND_2GHZ) { + index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on; + } else { + int group = tssi_on ? + mt7915_get_channel_group(chan->hw_value) : 8; + + index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group; + } + + return mt7915_eeprom_read(dev, index); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h new file mode 100644 index 000000000000..30fc607e466d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_EEPROM_H +#define __MT7915_EEPROM_H + +#include "mt7915.h" + +struct cal_data { + u8 count; + u16 offset[60]; +}; + +enum mt7915_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, + MT_EE_DDIE_FT_VERSION = 0x050, + MT_EE_WIFI_CONF = 0x190, + MT_EE_TX0_POWER_2G = 0x2fc, + MT_EE_TX0_POWER_5G = 0x34b, + MT_EE_ADIE_FT_VERSION = 0x9a0, + + __MT_EE_MAX = 0xe00 +}; + +#define MT_EE_WIFI_CONF_TX_MASK GENMASK(2, 0) +#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(7, 6) +#define MT_EE_WIFI_CONF_TSSI0_2G BIT(0) +#define MT_EE_WIFI_CONF_TSSI0_5G BIT(2) +#define MT_EE_WIFI_CONF_TSSI1_5G BIT(4) + +enum mt7915_eeprom_band { + MT_EE_DUAL_BAND, + MT_EE_5GHZ, + MT_EE_2GHZ, + MT_EE_DBDC, +}; + +struct sku_group { + u8 len; + u16 offset[2]; + const u8 *delta_map; +}; + +static inline int +mt7915_get_channel_group(int channel) +{ + if (channel >= 184 && channel <= 196) + return 0; + if (channel <= 48) + return 1; + if (channel <= 64) + return 2; + if (channel <= 96) + return 3; + if (channel <= 112) + return 4; + if (channel <= 128) + return 5; + if (channel <= 144) + return 6; + return 7; +} + +static inline bool +mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) +{ + u8 *eep = dev->mt76.eeprom.data; + + /* TODO: DBDC */ + if (band == NL80211_BAND_5GHZ) + return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF_TSSI0_5G; + else + return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF_TSSI0_2G; +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c new file mode 100644 index 000000000000..0e3e6b1547b3 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include +#include "mt7915.h" +#include "mac.h" +#include "eeprom.h" + +static void +mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) +{ + u32 mask, set; + + mt76_rmw_field(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); + mt76_set(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN); + + mask = MT_MDP_RCFR0_MCU_RX_MGMT | + MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR | + MT_MDP_RCFR0_MCU_RX_CTL_BAR; + set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) | + FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) | + FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF); + mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set); + + mask = MT_MDP_RCFR1_MCU_RX_BYPASS | + MT_MDP_RCFR1_RX_DROPPED_UCAST | + MT_MDP_RCFR1_RX_DROPPED_MCAST; + set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) | + FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) | + FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF); + mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); +} + +static void mt7915_mac_init(struct mt7915_dev *dev) +{ + int i; + + mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536); + mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); + /* enable rx rate report */ + mt76_set(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN); + /* disable hardware de-agg */ + mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); + + for (i = 0; i < MT7915_WTBL_SIZE; i++) + mt7915_mac_wtbl_update(dev, i, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + mt7915_mac_init_band(dev, 0); + mt7915_mac_init_band(dev, 1); + mt7915_mcu_set_rts_thresh(&dev->phy, 0x92b); +} + +static void +mt7915_init_txpower_band(struct mt7915_dev *dev, + struct ieee80211_supported_band *sband) +{ + int i, n_chains = hweight8(dev->mphy.antenna_mask); + + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *chan = &sband->channels[i]; + u32 target_power = 0; + int j; + + for (j = 0; j < n_chains; j++) { + u32 val; + + val = mt7915_eeprom_get_target_power(dev, chan, j); + target_power = max(target_power, val); + } + + chan->max_power = min_t(int, chan->max_reg_power, + target_power / 2); + chan->orig_mpwr = target_power / 2; + } +} + +static void mt7915_init_txpower(struct mt7915_dev *dev) +{ + mt7915_init_txpower_band(dev, &dev->mphy.sband_2g.sband); + mt7915_init_txpower_band(dev, &dev->mphy.sband_5g.sband); +} + +static void mt7915_init_work(struct work_struct *work) +{ + struct mt7915_dev *dev = container_of(work, struct mt7915_dev, + init_work); + + mt7915_mcu_set_eeprom(dev); + mt7915_mac_init(dev); + mt7915_init_txpower(dev); +} + +static int mt7915_init_hardware(struct mt7915_dev *dev) +{ + int ret, idx; + + mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + + INIT_WORK(&dev->init_work, mt7915_init_work); + spin_lock_init(&dev->token_lock); + idr_init(&dev->token); + + ret = mt7915_dma_init(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + + ret = mt7915_mcu_init(dev); + if (ret) + return ret; + + ret = mt7915_eeprom_init(dev); + if (ret < 0) + return ret; + + /* Beacon and mgmt frames should occupy wcid 0 */ + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1); + if (idx) + return -ENOSPC; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx = -1; + dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET; + rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); + + return 0; +} + +#define CCK_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ + .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \ +} + +#define OFDM_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ +} + +static struct ieee80211_rate mt7915_rates[] = { + CCK_RATE(0, 10), + CCK_RATE(1, 20), + CCK_RATE(2, 55), + CCK_RATE(3, 110), + OFDM_RATE(11, 60), + OFDM_RATE(15, 90), + OFDM_RATE(10, 120), + OFDM_RATE(14, 180), + OFDM_RATE(9, 240), + OFDM_RATE(13, 360), + OFDM_RATE(8, 480), + OFDM_RATE(12, 540), +}; + +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC) + }, { + .max = MT7915_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_STATION) + } +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = 4, + .num_different_channels = 1, + .beacon_int_infra_match = true, + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80) | + BIT(NL80211_CHAN_WIDTH_160) | + BIT(NL80211_CHAN_WIDTH_80P80), + } +}; + +static void +mt7915_regd_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct mt7915_phy *phy = mphy->priv; + struct cfg80211_chan_def *chandef = &mphy->chandef; + + dev->mt76.region = request->dfs_region; + + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + return; + + mt7915_dfs_init_radar_detector(phy); +} + +static void +mt7915_init_wiphy(struct ieee80211_hw *hw) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; + + phy->slottime = 9; + + hw->sta_data_size = sizeof(struct mt7915_sta); + hw->vif_data_size = sizeof(struct mt7915_vif); + + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + wiphy->reg_notifier = mt7915_regd_notifier; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + + hw->max_tx_fragments = 4; +} + +static void +mt7915_cap_dbdc_enable(struct mt7915_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap &= + ~(IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + + if (dev->chainmask == 0xf) + dev->mphy.antenna_mask = dev->chainmask >> 2; + else + dev->mphy.antenna_mask = dev->chainmask >> 1; + + dev->phy.chainmask = dev->mphy.antenna_mask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; + + mt76_set_stream_caps(&dev->mt76, true); +} + +static void +mt7915_cap_dbdc_disable(struct mt7915_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; + + mt76_set_stream_caps(&dev->mt76, true); +} + +int mt7915_register_ext_phy(struct mt7915_dev *dev) +{ + struct mt7915_phy *phy = mt7915_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + bool bound; + + bound = mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5); + if (!bound) + return -EINVAL; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return -EINVAL; + + if (phy) + return 0; + + mt7915_cap_dbdc_enable(dev); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7915_init_wiphy(mphy->hw); + + /* + * Make the secondary PHY MAC address local without overlapping with + * the usual MAC address allocation scheme on multiple virtual interfaces + */ + mphy->hw->wiphy->perm_addr[0] |= 2; + mphy->hw->wiphy->perm_addr[0] ^= BIT(7); + + /* The second interface does not get any packets unless it has a vif */ + ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + + ret = mt76_register_phy(mphy); + if (ret) + ieee80211_free_hw(mphy->hw); + + return ret; +} + +void mt7915_unregister_ext_phy(struct mt7915_dev *dev) +{ + struct mt7915_phy *phy = mt7915_ext_phy(dev); + struct mt76_phy *mphy = dev->mt76.phy2; + + if (!phy) + return; + + mt7915_cap_dbdc_disable(dev); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +} + +int mt7915_register_device(struct mt7915_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7915_mac_work); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); + + init_waitqueue_head(&dev->reset_wait); + INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); + + ret = mt7915_init_hardware(dev); + if (ret) + return ret; + + mt7915_init_wiphy(hw); + dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + mt7915_cap_dbdc_disable(dev); + dev->phy.dfs_state = -1; + + ret = mt76_register_device(&dev->mt76, true, mt7915_rates, + ARRAY_SIZE(mt7915_rates)); + if (ret) + return ret; + + ieee80211_queue_work(mt76_hw(dev), &dev->init_work); + + return mt7915_init_debugfs(dev); +} + +void mt7915_unregister_device(struct mt7915_dev *dev) +{ + struct mt76_txwi_cache *txwi; + int id; + + mt7915_unregister_ext_phy(dev); + mt76_unregister_device(&dev->mt76); + mt7915_mcu_exit(dev); + mt7915_dma_cleanup(dev); + + spin_lock_bh(&dev->token_lock); + idr_for_each_entry(&dev->token, txwi, id) { + mt7915_txp_skb_unmap(&dev->mt76, txwi); + if (txwi->skb) + dev_kfree_skb_any(txwi->skb); + mt76_put_txwi(&dev->mt76, txwi); + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); + + mt76_free_device(&dev->mt76); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c new file mode 100644 index 000000000000..349215dd417c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -0,0 +1,1310 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include +#include +#include "mt7915.h" +#include "../dma.h" +#include "mac.h" + +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) + +static const struct mt7915_dfs_radar_spec etsi_radar_specs = { + .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, + .radar_pattern = { + [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 }, + [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 }, + [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 }, + [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 }, + [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 }, + [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 }, + [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 }, + [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 }, + }, +}; + +static const struct mt7915_dfs_radar_spec fcc_radar_specs = { + .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, + [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, + }, +}; + +static const struct mt7915_dfs_radar_spec jp_radar_specs = { + .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, + [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, + [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 }, + [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 }, + [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 }, + }, +}; + +static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev, + u16 idx, bool unicast) +{ + struct mt7915_sta *sta; + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + return NULL; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (unicast || !wcid) + return wcid; + + if (!wcid->sta) + return NULL; + + sta = container_of(wcid, struct mt7915_sta, wcid); + if (!sta->vif) + return NULL; + + return &sta->vif->sta.wcid; +} + +void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) +{ +} + +bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask) +{ + mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); + + return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, + 0, 5000); +} + +static u32 mt7915_mac_wtbl_lmac_read(struct mt7915_dev *dev, u16 wcid, + u16 addr) +{ + mt76_wr(dev, MT_WTBLON_TOP_WDUCR, + FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); + + return mt76_rr(dev, MT_WTBL_LMAC_OFFS(wcid, addr)); +} + +void mt7915_mac_sta_poll(struct mt7915_dev *dev) +{ + static const u8 ac_to_tid[] = { + [IEEE80211_AC_BE] = 0, + [IEEE80211_AC_BK] = 1, + [IEEE80211_AC_VI] = 4, + [IEEE80211_AC_VO] = 6 + }; + static const u8 hw_queue_map[] = { + [IEEE80211_AC_BK] = 0, + [IEEE80211_AC_BE] = 1, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_VO] = 3, + }; + struct ieee80211_sta *sta; + struct mt7915_sta *msta; + u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; + int i; + + rcu_read_lock(); + + while (true) { + bool clear = false; + u16 idx; + + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&dev->sta_poll_list)) { + spin_unlock_bh(&dev->sta_poll_lock); + break; + } + msta = list_first_entry(&dev->sta_poll_list, + struct mt7915_sta, poll_list); + list_del_init(&msta->poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + + for (i = 0, idx = msta->wcid.idx; i < IEEE80211_NUM_ACS; i++) { + u32 tx_last = msta->airtime_ac[i]; + u32 rx_last = msta->airtime_ac[i + IEEE80211_NUM_ACS]; + + msta->airtime_ac[i] = + mt7915_mac_wtbl_lmac_read(dev, idx, 20 + i); + msta->airtime_ac[i + IEEE80211_NUM_ACS] = + mt7915_mac_wtbl_lmac_read(dev, idx, 21 + i); + tx_time[i] = msta->airtime_ac[i] - tx_last; + rx_time[i] = msta->airtime_ac[i + IEEE80211_NUM_ACS] - + rx_last; + + if ((tx_last | rx_last) & BIT(30)) + clear = true; + } + + if (clear) { + mt7915_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + } + + if (!msta->wcid.sta) + continue; + + sta = container_of((void *)msta, struct ieee80211_sta, + drv_priv); + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + u32 tx_cur = tx_time[i]; + u32 rx_cur = rx_time[hw_queue_map[i]]; + u8 tid = ac_to_tid[i]; + + if (!tx_cur && !rx_cur) + continue; + + ieee80211_sta_register_airtime(sta, tid, tx_cur, + rx_cur); + } + } + + rcu_read_unlock(); +} + +int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7915_phy *phy = &dev->phy; + struct ieee80211_supported_band *sband; + struct ieee80211_hdr *hdr; + struct mt7915_rxv rxv = {}; + __le32 *rxd = (__le32 *)skb->data; + u32 rxd1 = le32_to_cpu(rxd[1]); + u32 rxd2 = le32_to_cpu(rxd[2]); + u32 rxd3 = le32_to_cpu(rxd[3]); + bool unicast, insert_ccmp_hdr = false; + u8 remove_pad; + int i, idx; + + memset(status, 0, sizeof(*status)); + + if (rxd1 & MT_RXD1_NORMAL_BAND_IDX) { + mphy = dev->mt76.phy2; + if (!mphy) + return -EINVAL; + + phy = mphy->priv; + status->ext_phy = true; + } + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; + idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); + status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); + + if (status->wcid) { + struct mt7915_sta *msta; + + msta = container_of(status->wcid, struct mt7915_sta, wcid); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->poll_list)) + list_add_tail(&msta->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + } + + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; + if (status->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + if (!sband->channels) + return -EINVAL; + + if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + + if (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1) != 0 && + !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { + status->flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_IV_STRIPPED; + status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; + } + + if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != rxd[14]) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = rxd[14]; + + status->ampdu_ref = phy->ampdu_ref; + } + + remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); + + if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) + return -EINVAL; + + rxd += 6; + if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { + u8 *data = (u8 *)rxd; + + if (status->flag & RX_FLAG_DECRYPTED) { + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + + insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + } + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { + rxd += 2; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + + /* RXD Group 3 - P-RXV */ + if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { + memcpy(rxv.v, rxd, sizeof(rxv.v)); + + rxd += 2; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + + if (rxv.v[0] & MT_PRXV_HT_AD_CODE) + status->enc_flags |= RX_ENC_FLAG_LDPC; + + status->chains = mphy->antenna_mask; + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, rxv.v[1]); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, rxv.v[1]); + status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, rxv.v[1]); + status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, rxv.v[1]); + status->signal = status->chain_signal[0]; + + for (i = 1; i < hweight8(mphy->antenna_mask); i++) { + if (!(status->chains & BIT(i))) + continue; + + status->signal = max(status->signal, + status->chain_signal[i]); + } + + /* RXD Group 5 - C-RXV */ + if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { + u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, rxv.v[2]); + u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, rxv.v[2]); + bool cck = false; + + rxd += 18; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + + idx = i = FIELD_GET(MT_PRXV_TX_RATE, rxv.v[0]); + rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, rxv.v[2]); + + switch (rxv.phy) { + case MT_PHY_TYPE_CCK: + cck = true; + /* fall through */ + case MT_PHY_TYPE_OFDM: + i = mt76_get_rate(&dev->mt76, sband, i, cck); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + status->encoding = RX_ENC_HT; + if (i > 31) + return -EINVAL; + break; + case MT_PHY_TYPE_VHT: + status->nss = + FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + status->encoding = RX_ENC_VHT; + if (i > 9) + return -EINVAL; + break; + case MT_PHY_TYPE_HE_MU: + /* fall through */ + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + status->nss = + FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + status->encoding = RX_ENC_HE; + i &= GENMASK(3, 0); + + if (gi <= NL80211_RATE_INFO_HE_GI_3_2) + status->he_gi = gi; + + if (idx & MT_PRXV_TX_DCM) + status->he_dcm = true; + break; + default: + return -EINVAL; + } + status->rate_idx = i; + + switch (FIELD_GET(MT_CRXV_FRAME_MODE, rxv.v[2])) { + case IEEE80211_STA_RX_BW_20: + break; + case IEEE80211_STA_RX_BW_40: + if (rxv.phy & MT_PHY_TYPE_HE_EXT_SU && + (idx & MT_PRXV_TX_ER_SU_106T)) { + status->bw = RATE_INFO_BW_HE_RU; + status->he_ru = + NL80211_RATE_INFO_HE_RU_ALLOC_106; + } else { + status->bw = RATE_INFO_BW_40; + } + break; + case IEEE80211_STA_RX_BW_80: + status->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_160: + status->bw = RATE_INFO_BW_160; + break; + default: + return -EINVAL; + } + + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; + if (rxv.phy < MT_PHY_TYPE_HE_SU && gi) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + } + } + + skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); + + if (insert_ccmp_hdr) { + u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + + mt76_insert_ccmp_hdr(skb, key_id); + } + + hdr = mt76_skb_get_hdr(skb); + if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + return 0; + + status->aggr = unicast && + !ieee80211_is_qos_nullfunc(hdr->frame_control); + status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + + return 0; +} + +void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, bool beacon) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + bool multicast = is_multicast_ether_addr(hdr->addr1); + struct ieee80211_vif *vif = info->control.vif; + struct mt76_phy *mphy = &dev->mphy; + bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; + u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; + __le16 fc = hdr->frame_control; + u16 tx_count = 4, seqno = 0; + u32 val; + + if (vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + } + + if (ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; + + if (ieee80211_is_data(fc) || ieee80211_is_bufferable_mmpdu(fc)) { + q_idx = wmm_idx * MT7915_MAX_WMM_SETS + + skb_get_queue_mapping(skb); + p_fmt = MT_TX_TYPE_CT; + } else if (beacon) { + q_idx = MT_LMAC_BCN0; + p_fmt = MT_TX_TYPE_FW; + } else { + q_idx = MT_LMAC_ALTX0; + p_fmt = MT_TX_TYPE_CT; + } + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, + ieee80211_get_hdrlen_from_skb(skb) / 2) | + FIELD_PREP(MT_TXD1_TID, + skb->priority & IEEE80211_QOS_CTL_TID_MASK) | + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); + if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) + val |= cpu_to_le32(MT_TXD1_TGID); + + txwi[1] = cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) | + FIELD_PREP(MT_TXD2_MULTICAST, multicast); + if (key) { + if (multicast && ieee80211_is_robust_mgmt_frame(skb) && + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { + val |= MT_TXD2_BIP; + txwi[3] = 0; + } else { + txwi[3] = cpu_to_le32(MT_TXD3_PROTECT_FRAME); + } + } else { + txwi[3] = 0; + } + txwi[2] = cpu_to_le32(val); + + txwi[4] = 0; + txwi[5] = 0; + txwi[6] = 0; + + if (!ieee80211_is_data(fc) || multicast) { + u16 rate; + + /* hardware won't add HTC for mgmt/ctrl frame */ + txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE | MT_TXD2_HTC_VLD); + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + rate = MT7915_5G_RATE_DEFAULT; + else + rate = MT7915_2G_RATE_DEFAULT; + + val = MT_TXD6_FIXED_BW | + FIELD_PREP(MT_TXD6_TX_RATE, rate); + txwi[6] |= cpu_to_le32(val); + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); + } + + if (!ieee80211_is_beacon(fc)) + txwi[3] |= cpu_to_le32(MT_TXD3_SW_POWER_MGMT); + else + tx_count = 0x1f; + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); + + val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | + FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype); + txwi[7] = cpu_to_le32(val); + + val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); + if (ieee80211_is_data_qos(fc)) { + seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + val |= MT_TXD3_SN_VALID; + } else if (ieee80211_is_back_req(fc)) { + struct ieee80211_bar *bar; + + bar = (struct ieee80211_bar *)skb->data; + seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(bar->start_seq_num)); + val |= MT_TXD3_SN_VALID; + } + val |= FIELD_PREP(MT_TXD3_SEQ, seqno); + txwi[3] |= cpu_to_le32(val); +} + +int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct ieee80211_vif *vif = info->control.vif; + struct mt76_tx_cb *cb = mt76_tx_skb_cb(tx_info->skb); + struct mt76_txwi_cache *t; + struct mt7915_txp *txp; + int id, i, nbuf = tx_info->nbuf - 1; + u8 *txwi = (u8 *)txwi_ptr; + + if (!wcid) + wcid = &dev->mt76.global_wcid; + + cb->wcid = wcid->idx; + + mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, + false); + + txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE); + for (i = 0; i < nbuf; i++) { + txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); + txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); + } + txp->nbuf = nbuf; + + /* pass partial skb header to fw */ + tx_info->buf[1].len = MT_CT_PARSE_LEN; + tx_info->nbuf = MT_CT_DMA_BUF_NUM; + + txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); + + if (!key) + txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); + + if (ieee80211_is_mgmt(hdr->frame_control)) + txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); + + if (vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + + txp->bss_idx = mvif->idx; + } + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; + + spin_lock_bh(&dev->token_lock); + id = idr_alloc(&dev->token, t, 0, MT7915_TOKEN_SIZE, GFP_ATOMIC); + spin_unlock_bh(&dev->token_lock); + if (id < 0) + return id; + + txp->token = cpu_to_le16(id); + txp->rept_wds_wcid = 0xff; + tx_info->skb = DMA_DUMMY_DATA; + + return 0; +} + +static inline bool +mt7915_tx_check_aggr_tid(struct mt7915_sta *msta, u8 tid) +{ + bool ret = false; + + spin_lock_bh(&msta->ampdu_lock); + if (msta->ampdu_state[tid] == MT7915_AGGR_STOP) + ret = true; + spin_unlock_bh(&msta->ampdu_lock); + + return ret; +} + +static void +mt7915_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct mt7915_sta *msta; + u16 tid; + + if (!sta->ht_cap.ht_supported) + return; + + if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) + return; + + if (unlikely(!ieee80211_is_data_qos(hdr->frame_control))) + return; + + if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) + return; + + msta = (struct mt7915_sta *)sta->drv_priv; + tid = ieee80211_get_tid(hdr); + + if (mt7915_tx_check_aggr_tid(msta, tid)) { + ieee80211_start_tx_ba_session(sta, tid, 0); + mt7915_set_aggr_state(msta, tid, MT7915_AGGR_PROGRESS); + } +} + +static inline void +mt7915_tx_status(struct ieee80211_sta *sta, struct ieee80211_hw *hw, + struct ieee80211_tx_info *info, struct sk_buff *skb) +{ + struct ieee80211_tx_status status = { + .sta = sta, + .info = info, + }; + + if (skb) + status.skb = skb; + + if (sta) { + struct mt7915_sta *msta; + + msta = (struct mt7915_sta *)sta->drv_priv; + status.rate = &msta->stats.tx_rate; + } + + ieee80211_tx_status_ext(hw, &status); +} + +static void +mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb, + struct ieee80211_sta *sta, u8 stat) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hw *hw; + + hw = mt76_tx_status_get_hw(mdev, skb); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) + info->flags |= IEEE80211_TX_STAT_AMPDU; + else if (sta) + mt7915_tx_check_aggr(sta, skb); + + if (stat) + ieee80211_tx_info_clear_status(info); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.tx_time = 0; + + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { + mt7915_tx_status(sta, hw, info, skb); + return; + } + + if (sta || !(info->flags & IEEE80211_TX_CTL_NO_ACK)) + mt7915_tx_status(sta, hw, info, NULL); + + dev_kfree_skb(skb); +} + +void mt7915_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt7915_txp *txp; + int i; + + txp = mt7915_txwi_to_txp(dev, t); + for (i = 1; i < txp->nbuf; i++) + dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), + le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); +} + +void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data; + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + struct ieee80211_sta *sta = NULL; + u8 i, count; + + /* + * TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE, + * to the time ack is received or dropped by hw (air + hw queue time). + * Should avoid accessing WTBL to get Tx airtime, and use it instead. + */ + count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl)); + for (i = 0; i < count; i++) { + u32 msdu, info = le32_to_cpu(free->info[i]); + u8 stat; + + /* + * 1'b1: new wcid pair. + * 1'b0: msdu_id with the same 'wcid pair' as above. + */ + if (info & MT_TX_FREE_PAIR) { + struct mt7915_sta *msta; + struct mt76_wcid *wcid; + u16 idx; + + count++; + idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); + wcid = rcu_dereference(dev->mt76.wcid[idx]); + sta = wcid_to_sta(wcid); + if (!sta) + continue; + + msta = container_of(wcid, struct mt7915_sta, wcid); + ieee80211_queue_work(mt76_hw(dev), &msta->stats_work); + continue; + } + + msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); + stat = FIELD_GET(MT_TX_FREE_STATUS, info); + + spin_lock_bh(&dev->token_lock); + txwi = idr_remove(&dev->token, msdu); + spin_unlock_bh(&dev->token_lock); + + if (!txwi) + continue; + + mt7915_txp_skb_unmap(mdev, txwi); + if (txwi->skb) { + mt7915_tx_complete_status(mdev, txwi->skb, sta, stat); + txwi->skb = NULL; + } + + mt76_put_txwi(mdev, txwi); + } + dev_kfree_skb(skb); +} + +void mt7915_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e) +{ + struct mt7915_dev *dev; + + if (!e->txwi) { + dev_kfree_skb_any(e->skb); + return; + } + + dev = container_of(mdev, struct mt7915_dev, mt76); + + /* error path */ + if (e->skb == DMA_DUMMY_DATA) { + struct mt76_txwi_cache *t; + struct mt7915_txp *txp; + + txp = mt7915_txwi_to_txp(mdev, e->txwi); + + spin_lock_bh(&dev->token_lock); + t = idr_remove(&dev->token, le16_to_cpu(txp->token)); + spin_unlock_bh(&dev->token_lock); + e->skb = t ? t->skb : NULL; + } + + if (e->skb) { + struct mt76_tx_cb *cb = mt76_tx_skb_cb(e->skb); + struct mt76_wcid *wcid; + + wcid = rcu_dereference(dev->mt76.wcid[cb->wcid]); + + mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0); + } +} + +void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy); + + mt7915_l2_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); + mt7915_l2_set(dev, reg, BIT(11) | BIT(9)); +} + +void mt7915_mac_reset_counters(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + int i; + + for (i = 0; i < 4; i++) { + mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); + mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); + } + + if (ext_phy) { + dev->mt76.phy2->survey_time = ktime_get_boottime(); + i = ARRAY_SIZE(dev->mt76.aggr_stats) / 2; + } else { + dev->mt76.phy.survey_time = ktime_get_boottime(); + i = 0; + } + memset(&dev->mt76.aggr_stats[i], 0, sizeof(dev->mt76.aggr_stats) / 2); + + /* reset airtime counters */ + mt76_rr(dev, MT_MIB_SDR9(ext_phy)); + mt76_rr(dev, MT_MIB_SDR36(ext_phy)); + mt76_rr(dev, MT_MIB_SDR37(ext_phy)); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(ext_phy), + MT_WF_RMAC_MIB_RXTIME_CLR); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(ext_phy), + MT_WF_RMAC_MIB_RXTIME_CLR); +} + +void mt7915_mac_set_timing(struct mt7915_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 val, reg_offset; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); + int sifs, offset; + + if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) + sifs = 16; + else + sifs = 10; + + if (ext_phy) { + coverage_class = max_t(s16, dev->phy.coverage_class, + coverage_class); + } else { + struct mt7915_phy *phy_ext = mt7915_ext_phy(dev); + + if (phy_ext) + coverage_class = max_t(s16, phy_ext->coverage_class, + coverage_class); + } + mt76_set(dev, MT_ARB_SCR(ext_phy), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + + mt76_wr(dev, MT_TMAC_CDTR(ext_phy), cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR(ext_phy), ofdm + reg_offset); + mt76_wr(dev, MT_TMAC_ICR0(ext_phy), + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20) + val = MT7915_CFEND_RATE_DEFAULT; + else + val = MT7915_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR0(ext_phy), MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR(ext_phy), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); +} + +static void +mt7915_phy_update_channel(struct mt76_phy *mphy, int idx) +{ + struct mt7915_dev *dev = container_of(mphy->dev, struct mt7915_dev, mt76); + struct mt76_channel_state *state; + u64 busy_time, tx_time, rx_time, obss_time; + + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), + MT_MIB_SDR9_BUSY_MASK); + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), + MT_MIB_SDR36_TXTIME_MASK); + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), + MT_MIB_SDR37_RXTIME_MASK); + obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), + MT_MIB_OBSSTIME_MASK); + + /* TODO: state->noise */ + state = mphy->chan_state; + state->cc_busy += busy_time; + state->cc_tx += tx_time; + state->cc_rx += rx_time + obss_time; + state->cc_bss_rx += rx_time; +} + +void mt7915_update_channel(struct mt76_dev *mdev) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + + mt7915_phy_update_channel(&mdev->phy, 0); + if (mdev->phy2) + mt7915_phy_update_channel(mdev->phy2, 1); + + /* reset obss airtime */ + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); + if (mdev->phy2) + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(1), + MT_WF_RMAC_MIB_RXTIME_CLR); +} + +static bool +mt7915_wait_reset_state(struct mt7915_dev *dev, u32 state) +{ + bool ret; + + ret = wait_event_timeout(dev->reset_wait, + (READ_ONCE(dev->reset_state) & state), + MT7915_RESET_TIMEOUT); + + WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); + return ret; +} + +static void +mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = priv; + + mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); +} + +static void +mt7915_update_beacons(struct mt7915_dev *dev) +{ + ieee80211_iterate_active_interfaces(dev->mt76.hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_update_vif_beacon, dev->mt76.hw); + + if (!dev->mt76.phy2) + return; + + ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_update_vif_beacon, dev->mt76.phy2->hw); +} + +static void +mt7915_dma_reset(struct mt7915_dev *dev) +{ + int i; + + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_clear(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); + usleep_range(1000, 2000); + + for (i = 0; i < __MT_TXQ_MAX; i++) + mt76_queue_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_queue_rx_reset(dev, i); + + /* re-init prefetch settings after reset */ + mt7915_dma_prefetch(dev); + + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN); +} + +/* system error recovery */ +void mt7915_mac_reset_work(struct work_struct *work) +{ + struct mt7915_dev *dev; + + dev = container_of(work, struct mt7915_dev, reset_work); + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_stop_queues(dev->mt76.phy2->hw); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mcu.wait); + cancel_delayed_work_sync(&dev->mt76.mac_work); + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (dev->mt76.phy2) + mt76_txq_schedule_all(dev->mt76.phy2); + + tasklet_disable(&dev->mt76.tx_tasklet); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.napi[2]); + napi_disable(&dev->mt76.tx_napi); + + mutex_lock(&dev->mt76.mutex); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); + + if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7915_dma_reset(dev); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); + mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + } + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_RESET, &dev->mphy.state); + + tasklet_enable(&dev->mt76.tx_tasklet); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); + + napi_enable(&dev->mt76.napi[0]); + napi_schedule(&dev->mt76.napi[0]); + + napi_enable(&dev->mt76.napi[1]); + napi_schedule(&dev->mt76.napi[1]); + + napi_enable(&dev->mt76.napi[2]); + napi_schedule(&dev->mt76.napi[2]); + + ieee80211_wake_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_wake_queues(dev->mt76.phy2->hw); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mutex_unlock(&dev->mt76.mutex); + + mt7915_update_beacons(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7915_WATCHDOG_TIME); +} + +static void +mt7915_mac_update_mib_stats(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + bool ext_phy = phy != &dev->phy; + int i, aggr0, aggr1; + + memset(mib, 0, sizeof(*mib)); + + mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); + + aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; + for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { + u32 val, val2; + + val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); + + val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); + if (val2 > mib->ack_fail_cnt) + mib->ack_fail_cnt = val2; + + val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + if (val2 > mib->ba_miss_cnt) + mib->ba_miss_cnt = val2; + + val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); + val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); + if (val2 > mib->rts_retries_cnt) { + mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt = val2; + } + + val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); + val2 = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); + + dev->mt76.aggr_stats[aggr0++] += val & 0xffff; + dev->mt76.aggr_stats[aggr0++] += val >> 16; + dev->mt76.aggr_stats[aggr1++] += val2 & 0xffff; + dev->mt76.aggr_stats[aggr1++] += val2 >> 16; + } +} + +void mt7915_mac_sta_stats_work(struct work_struct *work) +{ + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + struct mt7915_sta_stats *stats; + struct mt7915_sta *msta; + struct mt7915_dev *dev; + + msta = container_of(work, struct mt7915_sta, stats_work); + sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); + vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); + dev = msta->vif->dev; + stats = &msta->stats; + + /* use MT_TX_FREE_RATE to report Tx rate for further devices */ + if (time_after(jiffies, stats->jiffies + HZ)) { + mt7915_mcu_get_rate_info(dev, RATE_CTRL_RU_INFO, + msta->wcid.idx); + + stats->jiffies = jiffies; + } + + if (test_and_clear_bit(IEEE80211_RC_SUPP_RATES_CHANGED | + IEEE80211_RC_NSS_CHANGED | + IEEE80211_RC_BW_CHANGED, &stats->changed)) + mt7915_mcu_add_rate_ctrl(dev, vif, sta); + + if (test_and_clear_bit(IEEE80211_RC_SMPS_CHANGED, &stats->changed)) + mt7915_mcu_add_smps(dev, vif, sta); + + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->poll_list)) + list_add_tail(&msta->poll_list, &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); +} + +void mt7915_mac_work(struct work_struct *work) +{ + struct mt7915_dev *dev; + + dev = (struct mt7915_dev *)container_of(work, struct mt76_dev, + mac_work.work); + + mutex_lock(&dev->mt76.mutex); + mt76_update_survey(&dev->mt76); + if (++dev->mac_work_count == 5) { + struct mt7915_phy *ext_phy = mt7915_ext_phy(dev); + + mt7915_mac_update_mib_stats(&dev->phy); + if (ext_phy) + mt7915_mac_update_mib_stats(ext_phy); + + dev->mac_work_count = 0; + } + mutex_unlock(&dev->mt76.mutex); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7915_WATCHDOG_TIME); +} + +static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + + if (phy->rdd_state & BIT(0)) + mt7915_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + if (phy->rdd_state & BIT(1)) + mt7915_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); +} + +static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) +{ + int err; + + err = mt7915_mcu_rdd_cmd(dev, RDD_START, chain, MT_RX_SEL0, 0); + if (err < 0) + return err; + + return mt7915_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, MT_RX_SEL0, 1); +} + +static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy) +{ + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + int err; + + /* start CAC */ + err = mt7915_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); + if (err < 0) + return err; + + err = mt7915_dfs_start_rdd(dev, ext_phy); + if (err < 0) + return err; + + phy->rdd_state |= BIT(ext_phy); + + if (chandef->width == NL80211_CHAN_WIDTH_160 || + chandef->width == NL80211_CHAN_WIDTH_80P80) { + err = mt7915_dfs_start_rdd(dev, 1); + if (err < 0) + return err; + + phy->rdd_state |= BIT(1); + } + + return 0; +} + +static int +mt7915_dfs_init_radar_specs(struct mt7915_phy *phy) +{ + const struct mt7915_dfs_radar_spec *radar_specs; + struct mt7915_dev *dev = phy->dev; + int err, i; + + switch (dev->mt76.region) { + case NL80211_DFS_FCC: + radar_specs = &fcc_radar_specs; + err = mt7915_mcu_set_fcc5_lpn(dev, 8); + if (err < 0) + return err; + break; + case NL80211_DFS_ETSI: + radar_specs = &etsi_radar_specs; + break; + case NL80211_DFS_JP: + radar_specs = &jp_radar_specs; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { + err = mt7915_mcu_set_radar_th(dev, i, + &radar_specs->radar_pattern[i]); + if (err < 0) + return err; + } + + return mt7915_mcu_set_pulse_th(dev, &radar_specs->pulse_th); +} + +int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) +{ + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7915_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + int err; + + if (dev->mt76.region == NL80211_DFS_UNSET) { + phy->dfs_state = -1; + if (phy->rdd_state) + goto stop; + + return 0; + } + + if (test_bit(MT76_SCANNING, &phy->mt76->state)) + return 0; + + if (phy->dfs_state == chandef->chan->dfs_state) + return 0; + + err = mt7915_dfs_init_radar_specs(phy); + if (err < 0) { + phy->dfs_state = -1; + goto stop; + } + + phy->dfs_state = chandef->chan->dfs_state; + + if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { + if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + return mt7915_dfs_start_radar_detector(phy); + + return mt7915_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, + MT_RX_SEL0, 0); + } + +stop: + err = mt7915_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, + MT_RX_SEL0, 0); + if (err < 0) + return err; + + mt7915_dfs_stop_radar_detector(phy); + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h new file mode 100644 index 000000000000..712753484aee --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_MAC_H +#define __MT7915_MAC_H + +#define MT_CT_PARSE_LEN 72 +#define MT_CT_DMA_BUF_NUM 2 + +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_TYPE GENMASK(31, 27) + +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) + +enum rx_pkt_type { + PKT_TYPE_TXS, + PKT_TYPE_TXRXV, + PKT_TYPE_NORMAL, + PKT_TYPE_RX_DUP_RFB, + PKT_TYPE_RX_TMR, + PKT_TYPE_RETRIEVE, + PKT_TYPE_TXRX_NOTIFY, + PKT_TYPE_RX_EVENT, +}; + +/* RXD DW1 */ +#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0) +#define MT_RXD1_NORMAL_GROUP_1 BIT(11) +#define MT_RXD1_NORMAL_GROUP_2 BIT(12) +#define MT_RXD1_NORMAL_GROUP_3 BIT(13) +#define MT_RXD1_NORMAL_GROUP_4 BIT(14) +#define MT_RXD1_NORMAL_GROUP_5 BIT(15) +#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) +#define MT_RXD1_NORMAL_CM BIT(23) +#define MT_RXD1_NORMAL_CLM BIT(24) +#define MT_RXD1_NORMAL_ICV_ERR BIT(25) +#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) +#define MT_RXD1_NORMAL_FCS_ERR BIT(27) +#define MT_RXD1_NORMAL_BAND_IDX BIT(28) +#define MT_RXD1_NORMAL_SPP_EN BIT(29) +#define MT_RXD1_NORMAL_ADD_OM BIT(30) +#define MT_RXD1_NORMAL_SEC_DONE BIT(31) + +/* RXD DW2 */ +#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) +#define MT_RXD2_NORMAL_CO_ANT BIT(6) +#define MT_RXD2_NORMAL_BF_CQI BIT(7) +#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) +#define MT_RXD2_NORMAL_HDR_TRANS BIT(13) +#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14) +#define MT_RXD2_NORMAL_TID GENMASK(19, 16) +#define MT_RXD2_NORMAL_MU_BAR BIT(21) +#define MT_RXD2_NORMAL_SW_BIT BIT(22) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) +#define MT_RXD2_NORMAL_INT_FRAME BIT(26) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) +#define MT_RXD2_NORMAL_BF_REPORT BIT(31) + +/* RXD DW3 */ +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) +#define MT_RXD3_NORMAL_U2M BIT(0) +#define MT_RXD3_NORMAL_HTC_VLD BIT(0) +#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19) +#define MT_RXD3_NORMAL_BEACON_MC BIT(20) +#define MT_RXD3_NORMAL_BEACON_UC BIT(21) +#define MT_RXD3_NORMAL_AMSDU BIT(22) +#define MT_RXD3_NORMAL_MESH BIT(23) +#define MT_RXD3_NORMAL_MHCP BIT(24) +#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25) +#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26) +#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27) +#define MT_RXD3_NORMAL_MORE BIT(28) +#define MT_RXD3_NORMAL_UNWANT BIT(29) +#define MT_RXD3_NORMAL_RX_DROP BIT(30) +#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) + +/* RXD DW4 */ +#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) +#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9) +#define MT_RXD4_NORMAL_CLS BIT(10) +#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11) +#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13) +#define MT_RXD4_NORMAL_WOL GENMASK(18, 14) +#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19) +#define MT_RXD3_NORMAL_PF_MODE BIT(29) +#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) + +/* P-RXV */ +#define MT_PRXV_TX_RATE GENMASK(6, 0) +#define MT_PRXV_TX_DCM BIT(4) +#define MT_PRXV_TX_ER_SU_106T BIT(5) +#define MT_PRXV_NSTS GENMASK(9, 7) +#define MT_PRXV_HT_AD_CODE BIT(11) +#define MT_PRXV_RCPI3 GENMASK(31, 24) +#define MT_PRXV_RCPI2 GENMASK(23, 16) +#define MT_PRXV_RCPI1 GENMASK(15, 8) +#define MT_PRXV_RCPI0 GENMASK(7, 0) + +/* C-RXV */ +#define MT_CRXV_HT_STBC GENMASK(1, 0) +#define MT_CRXV_TX_MODE GENMASK(7, 4) +#define MT_CRXV_FRAME_MODE GENMASK(10, 8) +#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13) + +struct mt7915_rxv { + u32 phy; + + /* P-RXV: bit 0~1, C-RXV: bit 2~19 */ + __le32 v[20]; +}; + +enum tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +enum tx_pkt_type { + MT_TX_TYPE_CT, + MT_TX_TYPE_SF, + MT_TX_TYPE_CMD, + MT_TX_TYPE_FW, +}; + +enum tx_pkt_queue_idx { + MT_LMAC_AC00, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0 = 0x10, + MT_LMAC_BCN0 = 0x12, +}; + +enum tx_port_idx { + MT_TX_PORT_IDX_LMAC, + MT_TX_PORT_IDX_MCU +}; + +enum tx_mcu_port_q_idx { + MT_TX_MCU_PORT_RX_Q0 = 0x20, + MT_TX_MCU_PORT_RX_Q1, + MT_TX_MCU_PORT_RX_Q2, + MT_TX_MCU_PORT_RX_Q3, + MT_TX_MCU_PORT_RX_FWDL = 0x3e +}; + +#define MT_CT_INFO_APPLY_TXD BIT(0) +#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) +#define MT_CT_INFO_MGMT_FRAME BIT(2) +#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define MT_CT_INFO_HSR2_TX BIT(4) + +#define MT_TXD_SIZE (8 * 4) + +#define MT_TXD0_Q_IDX GENMASK(31, 25) +#define MT_TXD0_PKT_FMT GENMASK(24, 23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_LONG_FORMAT BIT(31) +#define MT_TXD1_TGID BIT(30) +#define MT_TXD1_OWN_MAC GENMASK(29, 24) +#define MT_TXD1_AMSDU BIT(23) +#define MT_TXD1_TID GENMASK(22, 20) +#define MT_TXD1_HDR_PAD GENMASK(19, 18) +#define MT_TXD1_HDR_FORMAT GENMASK(17, 16) +#define MT_TXD1_HDR_INFO GENMASK(15, 11) +#define MT_TXD1_VTA BIT(10) +#define MT_TXD1_WLAN_IDX GENMASK(9, 0) + +#define MT_TXD2_FIX_RATE BIT(31) +#define MT_TXD2_FIXED_RATE BIT(30) +#define MT_TXD2_POWER_OFFSET GENMASK(29, 24) +#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_BIP BIT(11) +#define MT_TXD2_MULTICAST BIT(10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_SOUNDING BIT(8) +#define MT_TXD2_NDPA BIT(7) +#define MT_TXD2_NDP BIT(6) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SW_POWER_MGMT BIT(29) +#define MT_TXD3_BA_DISABLE BIT(28) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) +#define MT_TXD3_TIMING_MEASURE BIT(5) +#define MT_TXD3_DAS BIT(4) +#define MT_TXD3_EEOSP BIT(3) +#define MT_TXD3_EMRD BIT(2) +#define MT_TXD3_PROTECT_FRAME BIT(1) +#define MT_TXD3_NO_ACK BIT(0) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_MD BIT(15) +#define MT_TXD5_ADD_BA BIT(14) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_TX_IBF BIT(31) +#define MT_TXD6_TX_EBF BIT(30) +#define MT_TXD6_TX_RATE GENMASK(29, 16) +#define MT_TXD6_SGI GENMASK(15, 14) +#define MT_TXD6_HELTF GENMASK(13, 12) +#define MT_TXD6_LDPC BIT(11) +#define MT_TXD6_SPE_ID_IDX BIT(10) +#define MT_TXD6_ANT_ID GENMASK(7, 4) +#define MT_TXD6_DYN_BW BIT(3) +#define MT_TXD6_FIXED_BW BIT(2) +#define MT_TXD6_BW GENMASK(2, 0) + +#define MT_TXD7_TXD_LEN GENMASK(31, 30) +#define MT_TXD7_UDP_TCP_SUM BIT(29) +#define MT_TXD7_IP_SUM BIT(28) + +#define MT_TXD7_TYPE GENMASK(21, 20) +#define MT_TXD7_SUB_TYPE GENMASK(19, 16) + +#define MT_TXD7_PSE_FID GENMASK(27, 16) +#define MT_TXD7_SPE_IDX GENMASK(15, 11) +#define MT_TXD7_HW_AMSDU BIT(10) +#define MT_TXD7_TX_TIME GENMASK(9, 0) + +#define MT_TX_RATE_STBC BIT(13) +#define MT_TX_RATE_NSS GENMASK(12, 10) +#define MT_TX_RATE_MODE GENMASK(9, 6) +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXP_MAX_BUF_NUM 6 + +struct mt7915_txp { + __le16 flags; + __le16 token; + u8 bss_idx; + u8 rept_wds_wcid; + u8 rsv; + u8 nbuf; + __le32 buf[MT_TXP_MAX_BUF_NUM]; + __le16 len[MT_TXP_MAX_BUF_NUM]; +} __packed __aligned(4); + +struct mt7915_tx_free { + __le16 rx_byte_cnt; + __le16 ctrl; + u8 txd_cnt; + u8 rsv[3]; + __le32 info[]; +} __packed __aligned(4); + +#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) +#define MT_TX_FREE_WLAN_ID GENMASK(23, 14) +#define MT_TX_FREE_LATENCY GENMASK(12, 0) +/* 0: success, others: dropped */ +#define MT_TX_FREE_STATUS GENMASK(14, 13) +#define MT_TX_FREE_MSDU_ID GENMASK(30, 16) +#define MT_TX_FREE_PAIR BIT(31) +/* will support this field in further revision */ +#define MT_TX_FREE_RATE GENMASK(13, 0) + +struct mt7915_dfs_pulse { + u32 max_width; /* us */ + int max_pwr; /* dbm */ + int min_pwr; /* dbm */ + u32 min_stgr_pri; /* us */ + u32 max_stgr_pri; /* us */ + u32 min_cr_pri; /* us */ + u32 max_cr_pri; /* us */ +}; + +struct mt7915_dfs_pattern { + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u32 min_pri; + u32 max_pri; + u8 max_pw; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; + u8 rsv[2]; + u32 min_stgpr_diff; +} __packed; + +struct mt7915_dfs_radar_spec { + struct mt7915_dfs_pulse pulse_th; + struct mt7915_dfs_pattern radar_pattern[16]; +}; + +static inline struct mt7915_txp * +mt7915_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) +{ + u8 *txwi; + + if (!t) + return NULL; + + txwi = mt76_get_txwi_ptr(dev, t); + + return (struct mt7915_txp *)(txwi + MT_TXD_SIZE); +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c new file mode 100644 index 000000000000..e9e9e7e21388 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -0,0 +1,743 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include +#include +#include +#include +#include "mt7915.h" +#include "mcu.h" + +static bool mt7915_dev_running(struct mt7915_dev *dev) +{ + struct mt7915_phy *phy; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return true; + + phy = mt7915_ext_phy(dev); + + return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); +} + +static int mt7915_start(struct ieee80211_hw *hw) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + bool running; + + mutex_lock(&dev->mt76.mutex); + + running = mt7915_dev_running(dev); + + if (!running) { + mt7915_mcu_set_pm(dev, 0, 0); + mt7915_mcu_set_mac(dev, 0, true, false); + mt7915_mcu_set_scs(dev, 0, true); + } + + if (phy != &dev->phy) { + mt7915_mcu_set_pm(dev, 1, 0); + mt7915_mcu_set_mac(dev, 1, true, false); + mt7915_mcu_set_scs(dev, 1, true); + } + + mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (running) + goto out; + + mt7915_mac_reset_counters(phy); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7915_WATCHDOG_TIME); +out: + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static void mt7915_stop(struct ieee80211_hw *hw) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + + mutex_lock(&dev->mt76.mutex); + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (phy != &dev->phy) { + mt7915_mcu_set_pm(dev, 1, 1); + mt7915_mcu_set_mac(dev, 1, false, false); + } + + if (!mt7915_dev_running(dev)) { + cancel_delayed_work_sync(&dev->mt76.mac_work); + + mt7915_mcu_set_pm(dev, 0, 1); + mt7915_mcu_set_mac(dev, 0, false, false); + } + + mutex_unlock(&dev->mt76.mutex); +} + +static int get_omac_idx(enum nl80211_iftype type, u32 mask) +{ + int i; + + switch (type) { + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + /* ap uses hw bssid 0 and ext bssid */ + if (~mask & BIT(HW_BSSID_0)) + return HW_BSSID_0; + + for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++) + if (~mask & BIT(i)) + return i; + break; + case NL80211_IFTYPE_STATION: + /* station uses hw bssid other than 0 */ + for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++) + if (~mask & BIT(i)) + return i; + break; + default: + WARN_ON(1); + break; + } + + return -1; +} + +static int mt7915_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt76_txq *mtxq; + bool ext_phy = phy != &dev->phy; + int idx, ret = 0; + + mutex_lock(&dev->mt76.mutex); + + mvif->idx = ffs(~dev->vif_mask) - 1; + if (mvif->idx >= MT7915_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } + + idx = get_omac_idx(vif->type, dev->omac_mask); + if (idx < 0) { + ret = -ENOSPC; + goto out; + } + mvif->omac_idx = idx; + mvif->dev = dev; + + mvif->band_idx = ext_phy; + if (mt7915_ext_phy(dev)) + mvif->wmm_idx = ext_phy * (MT7915_MAX_WMM_SETS / 2) + + mvif->idx % (MT7915_MAX_WMM_SETS / 2); + else + mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS; + + ret = mt7915_mcu_add_dev_info(dev, vif, true); + if (ret) + goto out; + + dev->vif_mask |= BIT(mvif->idx); + dev->omac_mask |= BIT(mvif->omac_idx); + phy->omac_mask |= BIT(mvif->omac_idx); + + idx = MT7915_WTBL_RESERVED - mvif->idx; + + INIT_LIST_HEAD(&mvif->sta.poll_list); + mvif->sta.wcid.idx = idx; + mvif->sta.wcid.ext_phy = mvif->band_idx; + mvif->sta.wcid.hw_key_idx = -1; + mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; + mt7915_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + } + +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static void mt7915_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = &mvif->sta; + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + int idx = msta->wcid.idx; + + /* TODO: disable beacon for the bss */ + + mt7915_mcu_add_dev_info(dev, vif, false); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + if (vif->txq) + mt76_txq_remove(&dev->mt76, vif->txq); + + mutex_lock(&dev->mt76.mutex); + dev->vif_mask &= ~BIT(mvif->idx); + dev->omac_mask &= ~BIT(mvif->omac_idx); + phy->omac_mask &= ~BIT(mvif->omac_idx); + mutex_unlock(&dev->mt76.mutex); + + spin_lock_bh(&dev->sta_poll_lock); + if (!list_empty(&msta->poll_list)) + list_del_init(&msta->poll_list); + spin_unlock_bh(&dev->sta_poll_lock); +} + +static void mt7915_init_dfs_state(struct mt7915_phy *phy) +{ + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_hw *hw = mphy->hw; + struct cfg80211_chan_def *chandef = &hw->conf.chandef; + + if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + return; + + if (mphy->chandef.chan->center_freq == chandef->chan->center_freq && + mphy->chandef.width == chandef->width) + return; + + phy->dfs_state = -1; +} + +static int mt7915_set_channel(struct mt7915_phy *phy) +{ + struct mt7915_dev *dev = phy->dev; + int ret; + + cancel_delayed_work_sync(&dev->mt76.mac_work); + + mutex_lock(&dev->mt76.mutex); + set_bit(MT76_RESET, &phy->mt76->state); + + mt7915_init_dfs_state(phy); + mt76_set_channel(phy->mt76); + + ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); + if (ret) + goto out; + + mt7915_mac_set_timing(phy); + ret = mt7915_dfs_init_radar_detector(phy); + mt7915_mac_cca_stats_reset(phy); + + mt7915_mac_reset_counters(phy); + phy->noise = 0; + +out: + clear_bit(MT76_RESET, &phy->mt76->state); + mutex_unlock(&dev->mt76.mutex); + + mt76_txq_schedule_all(phy->mt76); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7915_WATCHDOG_TIME); + + return ret; +} + +static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; + int idx = key->keyidx; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. + */ + if ((vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + case WLAN_CIPHER_SUITE_SMS4: + break; + default: + return -EOPNOTSUPP; + } + + if (cmd == SET_KEY) { + key->hw_key_idx = wcid->idx; + wcid->hw_key_idx = idx; + } else if (idx == wcid->hw_key_idx) { + wcid->hw_key_idx = -1; + } + mt76_wcid_key_setup(&dev->mt76, wcid, + cmd == SET_KEY ? key : NULL); + + return mt7915_mcu_add_key(dev, vif, msta, key, cmd); +} + +static int mt7915_config(struct ieee80211_hw *hw, u32 changed) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + bool band = phy != &dev->phy; + int ret; + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ieee80211_stop_queues(hw); + ret = mt7915_set_channel(phy); + if (ret) + return ret; + ieee80211_wake_queues(hw); + } + + mutex_lock(&dev->mt76.mutex); + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) + phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + else + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + } + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + + /* no need to update right away, we'll get BSS_CHANGED_QOS */ + mvif->wmm[queue].cw_min = params->cw_min; + mvif->wmm[queue].cw_max = params->cw_max; + mvif->wmm[queue].aifs = params->aifs; + mvif->wmm[queue].txop = params->txop; + + return 0; +} + +static void mt7915_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + bool band = phy != &dev->phy; + + u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | + MT_WF_RFCR1_DROP_BF_POLL | + MT_WF_RFCR1_DROP_BA | + MT_WF_RFCR1_DROP_CFEND | + MT_WF_RFCR1_DROP_CFACK; + u32 flags = 0; + +#define MT76_FILTER(_flag, _hw) do { \ + flags |= *total_flags & FIF_##_flag; \ + phy->rxfilter &= ~(_hw); \ + phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + } while (0) + + phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); + + MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | + MT_WF_RFCR_DROP_A3_MAC | + MT_WF_RFCR_DROP_A3_BSSID); + + MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); + + MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | + MT_WF_RFCR_DROP_CTL_RSV | + MT_WF_RFCR_DROP_NDPA); + + *total_flags = flags; + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); + + if (*total_flags & FIF_CONTROL) + mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); + else + mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); +} + +static void mt7915_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + + /* + * station mode uses BSSID to map the wlan entry to a peer, + * and then peer references bss_info_rfch to set bandwidth cap. + */ + if (changed & BSS_CHANGED_BSSID && + vif->type == NL80211_IFTYPE_STATION) { + bool join = !is_zero_ether_addr(info->bssid); + + mt7915_mcu_add_bss_info(phy, vif, join); + mt7915_mcu_add_sta(dev, vif, NULL, join); + } + + if (changed & BSS_CHANGED_ASSOC) + mt7915_mcu_add_bss_info(phy, vif, info->assoc); + + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt7915_mac_set_timing(phy); + } + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + mt7915_mcu_add_bss_info(phy, vif, info->enable_beacon); + mt7915_mcu_add_sta(dev, vif, NULL, info->enable_beacon); + } + + /* ensure that enable txcmd_mode after bss_info */ + if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) + mt7915_mcu_set_tx(dev, vif); + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); + + mutex_unlock(&dev->mt76.mutex); +} + +static void +mt7915_channel_switch_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mt7915_mcu_add_beacon(hw, vif, true); + mutex_unlock(&dev->mt76.mutex); +} + +int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + int idx; + + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1); + if (idx < 0) + return -ENOSPC; + + INIT_LIST_HEAD(&msta->poll_list); + INIT_WORK(&msta->stats_work, mt7915_mac_sta_stats_work); + spin_lock_init(&msta->ampdu_lock); + msta->vif = mvif; + msta->wcid.sta = 1; + msta->wcid.idx = idx; + msta->wcid.ext_phy = mvif->band_idx; + msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; + msta->stats.jiffies = jiffies; + + mt7915_mac_wtbl_update(dev, idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + mt7915_mcu_add_sta(dev, vif, sta, true); + + return 0; +} + +void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + + mt7915_mcu_add_sta(dev, vif, sta, false); + + mt7915_mac_wtbl_update(dev, msta->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + + spin_lock_bh(&dev->sta_poll_lock); + if (!list_empty(&msta->poll_list)) + list_del_init(&msta->poll_list); + spin_unlock_bh(&dev->sta_poll_lock); +} + +static void mt7915_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + + if (control->sta) { + struct mt7915_sta *sta; + + sta = (struct mt7915_sta *)control->sta->drv_priv; + wcid = &sta->wcid; + } + + if (vif && !control->sta) { + struct mt7915_vif *mvif; + + mvif = (struct mt7915_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + + mt76_tx(mphy, control->sta, wcid, skb); +} + +static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + + mutex_lock(&dev->mt76.mutex); + mt7915_mcu_set_rts_thresh(phy, val); + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static int +mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + enum ieee80211_ampdu_mlme_action action = params->action; + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct ieee80211_sta *sta = params->sta; + struct ieee80211_txq *txq = sta->txq[params->tid]; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + u16 tid = params->tid; + u16 ssn = params->ssn; + struct mt76_txq *mtxq; + int ret = 0; + + if (!txq) + return -EINVAL; + + mtxq = (struct mt76_txq *)txq->drv_priv; + + mutex_lock(&dev->mt76.mutex); + switch (action) { + case IEEE80211_AMPDU_RX_START: + mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, + params->buf_size); + mt7915_mcu_add_rx_ba(dev, params, true); + break; + case IEEE80211_AMPDU_RX_STOP: + mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt7915_mcu_add_rx_ba(dev, params, false); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mtxq->aggr = true; + mtxq->send_bar = false; + mt7915_set_aggr_state(msta, tid, MT7915_AGGR_OPERATIONAL); + mt7915_mcu_add_tx_ba(dev, params, true); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mtxq->aggr = false; + mt7915_set_aggr_state(msta, tid, MT7915_AGGR_STOP); + mt7915_mcu_add_tx_ba(dev, params, false); + break; + case IEEE80211_AMPDU_TX_START: + mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn); + mt7915_set_aggr_state(msta, tid, MT7915_AGGR_START); + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + mt7915_set_aggr_state(msta, tid, MT7915_AGGR_STOP); + mt7915_mcu_add_tx_ba(dev, params, false); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + } + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static int +mt7915_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE); +} + +static int +mt7915_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); +} + +static int +mt7915_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + return 0; +} + +static void +mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt7915_mac_set_timing(phy); +} + +static int +mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + int max_nss = hweight8(hw->wiphy->available_antennas_tx); + bool ext_phy = phy != &dev->phy; + + if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + return -EINVAL; + + if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) + tx_ant = BIT(ffs(tx_ant) - 1) - 1; + + mutex_lock(&dev->mt76.mutex); + + phy->mt76->antenna_mask = tx_ant; + + if (ext_phy) { + if (dev->chainmask == 0xf) + tx_ant <<= 2; + else + tx_ant <<= 1; + } + phy->chainmask = tx_ant; + + mt76_set_stream_caps(&dev->mt76, true); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static void +mt7915_sta_rc_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u32 changed) +{ + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, sta->addr); + if (!sta) { + rcu_read_unlock(); + return; + } + rcu_read_lock(); + + set_bit(changed, &msta->stats.changed); + ieee80211_queue_work(hw, &msta->stats_work); +} + +const struct ieee80211_ops mt7915_ops = { + .tx = mt7915_tx, + .start = mt7915_start, + .stop = mt7915_stop, + .add_interface = mt7915_add_interface, + .remove_interface = mt7915_remove_interface, + .config = mt7915_config, + .conf_tx = mt7915_conf_tx, + .configure_filter = mt7915_configure_filter, + .bss_info_changed = mt7915_bss_info_changed, + .sta_add = mt7915_sta_add, + .sta_remove = mt7915_sta_remove, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, + .sta_rc_update = mt7915_sta_rc_update, + .set_key = mt7915_set_key, + .ampdu_action = mt7915_ampdu_action, + .set_rts_threshold = mt7915_set_rts_threshold, + .wake_tx_queue = mt76_wake_tx_queue, + .sw_scan_start = mt76_sw_scan, + .sw_scan_complete = mt76_sw_scan_complete, + .release_buffered_frames = mt76_release_buffered_frames, + .get_txpower = mt76_get_txpower, + .channel_switch_beacon = mt7915_channel_switch_beacon, + .get_stats = mt7915_get_stats, + .get_survey = mt76_get_survey, + .get_antenna = mt76_get_antenna, + .set_antenna = mt7915_set_antenna, + .set_coverage_class = mt7915_set_coverage_class, +}; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c new file mode 100644 index 000000000000..5ca6bd9f099c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -0,0 +1,2319 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + +#include +#include +#include "mt7915.h" +#include "mcu.h" +#include "mac.h" +#include "eeprom.h" + +struct mt7915_patch_hdr { + char build_date[16]; + char platform[4]; + __be32 hw_sw_ver; + __be32 patch_ver; + __be16 checksum; + u16 reserved; + struct { + __be32 patch_ver; + __be32 subsys; + __be32 feature; + __be32 n_region; + __be32 crc; + u32 reserved[11]; + } desc; +} __packed; + +struct mt7915_patch_sec { + __be32 type; + __be32 offs; + __be32 size; + union { + __be32 spec[13]; + struct { + __be32 addr; + __be32 len; + __be32 sec_key_idx; + __be32 align_len; + u32 reserved[9]; + } info; + }; +} __packed; + +struct mt7915_fw_trailer { + u8 chip_id; + u8 eco_code; + u8 n_region; + u8 format_ver; + u8 format_flag; + u8 reserved[2]; + char fw_ver[10]; + char build_date[15]; + u32 crc; +} __packed; + +struct mt7915_fw_region { + __le32 decomp_crc; + __le32 decomp_len; + __le32 decomp_blk_sz; + u8 reserved[4]; + __le32 addr; + __le32 len; + u8 feature_set; + u8 reserved1[15]; +} __packed; + +#define MCU_PATCH_ADDRESS 0x200000 + +#define FW_FEATURE_SET_ENCRYPT BIT(0) +#define FW_FEATURE_SET_KEY_IDX GENMASK(2, 1) +#define FW_FEATURE_OVERRIDE_ADDR BIT(5) + +#define DL_MODE_ENCRYPT BIT(0) +#define DL_MODE_KEY_IDX GENMASK(2, 1) +#define DL_MODE_RESET_SEC_IV BIT(3) +#define DL_MODE_WORKING_PDA_CR4 BIT(4) +#define DL_MODE_NEED_RSP BIT(31) + +#define FW_START_OVERRIDE BIT(0) +#define FW_START_WORKING_PDA_CR4 BIT(2) + +#define PATCH_SEC_TYPE_MASK GENMASK(15, 0) +#define PATCH_SEC_TYPE_INFO 0x2 + +#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) +#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) + +static enum mt7915_cipher_type +mt7915_mcu_get_cipher(int cipher) +{ + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return MT_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return MT_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + return MT_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_AES_CMAC: + return MT_CIPHER_BIP_CMAC_128; + case WLAN_CIPHER_SUITE_CCMP: + return MT_CIPHER_AES_CCMP; + case WLAN_CIPHER_SUITE_CCMP_256: + return MT_CIPHER_CCMP_256; + case WLAN_CIPHER_SUITE_GCMP: + return MT_CIPHER_GCMP; + case WLAN_CIPHER_SUITE_GCMP_256: + return MT_CIPHER_GCMP_256; + case WLAN_CIPHER_SUITE_SMS4: + return MT_CIPHER_WAPI; + default: + return MT_CIPHER_NONE; + } +} + +static u8 mt7915_mcu_chan_bw(struct cfg80211_chan_def *chandef) +{ + static const u8 width_to_bw[] = { + [NL80211_CHAN_WIDTH_40] = CMD_CBW_40MHZ, + [NL80211_CHAN_WIDTH_80] = CMD_CBW_80MHZ, + [NL80211_CHAN_WIDTH_80P80] = CMD_CBW_8080MHZ, + [NL80211_CHAN_WIDTH_160] = CMD_CBW_160MHZ, + [NL80211_CHAN_WIDTH_5] = CMD_CBW_5MHZ, + [NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ, + [NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ, + [NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ, + }; + + if (chandef->width >= ARRAY_SIZE(width_to_bw)) + return 0; + + return width_to_bw[chandef->width]; +} + +static u8 +mt7915_get_phy_mode(struct mt7915_dev *dev, struct ieee80211_vif *vif, + enum nl80211_band band, struct ieee80211_sta *sta) +{ + struct ieee80211_sta_ht_cap *ht_cap; + struct ieee80211_sta_vht_cap *vht_cap; + u8 mode = 0; + + if (sta) { + ht_cap = &sta->ht_cap; + vht_cap = &sta->vht_cap; + } else { + struct ieee80211_supported_band *sband; + + if (band == NL80211_BAND_2GHZ) + sband = &dev->mphy.sband_2g.sband; + else + sband = &dev->mphy.sband_5g.sband; + + ht_cap = &sband->ht_cap; + vht_cap = &sband->vht_cap; + } + + if (band == NL80211_BAND_2GHZ) { + mode |= PHY_MODE_B | PHY_MODE_G; + + if (ht_cap->ht_supported) + mode |= PHY_MODE_GN; + } else if (band == NL80211_BAND_5GHZ) { + mode |= PHY_MODE_A; + + if (ht_cap->ht_supported) + mode |= PHY_MODE_AN; + + if (vht_cap->vht_supported) + mode |= PHY_MODE_AC; + } + + return mode; +} + +static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + struct mt7915_mcu_txd *mcu_txd; + u8 seq, pkt_fmt, qidx; + enum mt7915_txq_id txq; + __le32 *txd; + u32 val; + + seq = ++dev->mt76.mcu.msg_seq & 0xf; + if (!seq) + seq = ++dev->mt76.mcu.msg_seq & 0xf; + + if (cmd == -MCU_CMD_FW_SCATTER) { + txq = MT_TXQ_FWDL; + goto exit; + } + + mcu_txd = (struct mt7915_mcu_txd *)skb_push(skb, sizeof(*mcu_txd)); + + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { + txq = MT_TXQ_MCU_WA; + qidx = MT_TX_MCU_PORT_RX_Q0; + pkt_fmt = MT_TX_TYPE_CMD; + } else { + txq = MT_TXQ_MCU; + qidx = MT_TX_MCU_PORT_RX_Q0; + pkt_fmt = MT_TX_TYPE_CMD; + } + + txd = mcu_txd->txd; + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | + FIELD_PREP(MT_TXD0_PKT_FMT, pkt_fmt) | + FIELD_PREP(MT_TXD0_Q_IDX, qidx); + txd[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD); + txd[1] = cpu_to_le32(val); + + mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); + mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, qidx)); + mcu_txd->pkt_type = MCU_PKT_ID; + mcu_txd->seq = seq; + + if (cmd < 0) { + mcu_txd->set_query = MCU_Q_NA; + mcu_txd->cid = -cmd; + } else { + mcu_txd->cid = MCU_CMD_EXT_CID; + mcu_txd->ext_cid = cmd; + mcu_txd->ext_cid_ack = 1; + + /* do not use Q_SET for efuse */ + if (cmd == MCU_EXT_CMD_EFUSE_ACCESS) + mcu_txd->set_query = MCU_Q_QUERY; + else + mcu_txd->set_query = MCU_Q_SET; + } + + mcu_txd->s2d_index = MCU_S2D_H2N; + BUILD_BUG_ON(cmd == MCU_EXT_CMD_EFUSE_ACCESS && + mcu_txd->set_query != MCU_Q_QUERY); + +exit: + if (wait_seq) + *wait_seq = seq; + + return mt76_tx_queue_skb_raw(dev, txq, skb, 0); +} + +static int +mt7915_mcu_parse_eeprom(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_mcu_eeprom_info *res; + u8 *buf; + + if (!skb) + return -EINVAL; + + skb_pull(skb, sizeof(struct mt7915_mcu_rxd)); + + res = (struct mt7915_mcu_eeprom_info *)skb->data; + buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); + memcpy(buf, res->data, 16); + + return 0; +} + +static int +mt7915_mcu_parse_response(struct mt7915_dev *dev, int cmd, + struct sk_buff *skb, int seq) +{ + struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + int ret = 0; + + if (seq != rxd->seq) + return -EAGAIN; + + switch (cmd) { + case -MCU_CMD_PATCH_SEM_CONTROL: + skb_pull(skb, sizeof(*rxd) - 4); + ret = *skb->data; + break; + case MCU_EXT_CMD_THERMAL_CTRL: + skb_pull(skb, sizeof(*rxd) + 4); + ret = le32_to_cpu(*(__le32 *)skb->data); + break; + case MCU_EXT_CMD_EFUSE_ACCESS: + ret = mt7915_mcu_parse_eeprom(dev, skb); + break; + default: + break; + } + dev_kfree_skb(skb); + + return ret; +} + +static int +mt7915_mcu_wait_response(struct mt7915_dev *dev, int cmd, int seq) +{ + unsigned long expires = jiffies + 20 * HZ; + struct sk_buff *skb; + int ret = 0; + + while (true) { + skb = mt76_mcu_get_response(&dev->mt76, expires); + if (!skb) { + dev_err(dev->mt76.dev, "Message %d (seq %d) timeout\n", + cmd, seq); + return -ETIMEDOUT; + } + + ret = mt7915_mcu_parse_response(dev, cmd, skb, seq); + if (ret != -EAGAIN) + break; + } + + return ret; +} + +static int +mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, bool wait_resp) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + int ret, seq; + + mutex_lock(&mdev->mcu.mutex); + + ret = __mt7915_mcu_msg_send(dev, skb, cmd, &seq); + if (ret) + goto out; + + if (wait_resp) + ret = mt7915_mcu_wait_response(dev, cmd, seq); + +out: + mutex_unlock(&mdev->mcu.mutex); + + return ret; +} + +static int +mt7915_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, + int len, bool wait_resp) +{ + struct sk_buff *skb; + + skb = mt76_mcu_msg_alloc(mdev, data, len); + if (!skb) + return -ENOMEM; + + return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); +} + +static void +mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + if (vif->csa_active) + ieee80211_csa_finish(vif); +} + +static void +mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7915_mcu_rdd_report *r; + + r = (struct mt7915_mcu_rdd_report *)skb->data; + + if (r->idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_radar_detected(mphy->hw); + dev->hw_pattern++; +} + +static void +mt7915_mcu_tx_rate_cal(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra, + struct rate_info *rate, u16 r) +{ + struct ieee80211_supported_band *sband; + u16 ru_idx = le16_to_cpu(ra->ru_idx); + u16 flags = 0; + + rate->mcs = FIELD_GET(MT_RA_RATE_MCS, r); + rate->nss = FIELD_GET(MT_RA_RATE_NSS, r) + 1; + + switch (FIELD_GET(MT_RA_RATE_TX_MODE, r)) { + case MT_PHY_TYPE_CCK: + case MT_PHY_TYPE_OFDM: + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + rate->legacy = sband->bitrates[rate->mcs].bitrate; + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: + rate->mcs += (rate->nss - 1) * 8; + flags |= RATE_INFO_FLAGS_MCS; + + if (ra->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_VHT: + flags |= RATE_INFO_FLAGS_VHT_MCS; + + if (ra->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + case MT_PHY_TYPE_HE_MU: + rate->he_gi = ra->gi; + rate->he_dcm = FIELD_GET(MT_RA_RATE_DCM_EN, r); + + flags |= RATE_INFO_FLAGS_HE_MCS; + break; + default: + break; + } + rate->flags = flags; + + if (ru_idx) { + switch (ru_idx) { + case 1 ... 2: + rate->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 3 ... 6: + rate->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_484; + break; + case 7 ... 14: + rate->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_242; + break; + default: + rate->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_106; + break; + } + rate->bw = RATE_INFO_BW_HE_RU; + } else { + u8 bw = mt7915_mcu_chan_bw(&mphy->chandef) - + FIELD_GET(MT_RA_RATE_BW, r); + + switch (bw) { + case IEEE80211_STA_RX_BW_160: + rate->bw = RATE_INFO_BW_160; + break; + case IEEE80211_STA_RX_BW_80: + rate->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_40: + rate->bw = RATE_INFO_BW_40; + break; + default: + rate->bw = RATE_INFO_BW_20; + break; + } + } +} + +static void +mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_mcu_ra_info *ra = (struct mt7915_mcu_ra_info *)skb->data; + u16 wcidx = le16_to_cpu(ra->wlan_idx); + struct mt76_wcid *wcid = rcu_dereference(dev->mt76.wcid[wcidx]); + struct mt7915_sta *msta = container_of(wcid, struct mt7915_sta, wcid); + struct mt7915_sta_stats *stats = &msta->stats; + struct mt76_phy *mphy = &dev->mphy; + struct rate_info rate = {}, prob_rate = {}; + u16 attempts = le16_to_cpu(ra->attempts); + u16 curr = le16_to_cpu(ra->curr_rate); + u16 probe = le16_to_cpu(ra->prob_up_rate); + + if (msta->wcid.ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + /* current rate */ + mt7915_mcu_tx_rate_cal(mphy, ra, &rate, curr); + stats->tx_rate = rate; + + /* probing rate */ + mt7915_mcu_tx_rate_cal(mphy, ra, &prob_rate, probe); + stats->prob_rate = prob_rate; + + if (attempts) { + u16 success = le16_to_cpu(ra->success); + + stats->per = 1000 * (attempts - success) / attempts; + } +} + +static void +mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + + switch (rxd->ext_eid) { + case MCU_EXT_EVENT_RDD_REPORT: + mt7915_mcu_rx_radar_detected(dev, skb); + break; + case MCU_EXT_EVENT_CSA_NOTIFY: + ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7915_mcu_csa_finish, dev); + break; + case MCU_EXT_EVENT_RATE_REPORT: + mt7915_mcu_tx_rate_report(dev, skb); + break; + default: + break; + } +} + +static void +mt7915_mcu_rx_unsolicited_event(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + + switch (rxd->eid) { + case MCU_EVENT_EXT: + mt7915_mcu_rx_ext_event(dev, skb); + break; + default: + break; + } + dev_kfree_skb(skb); +} + +void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) +{ + struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data; + + if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || + rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || + rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || + rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT || + !rxd->seq) + mt7915_mcu_rx_unsolicited_event(dev, skb); + else + mt76_mcu_rx_event(&dev->mt76, skb); +} + +static struct sk_buff * +mt7915_mcu_alloc_sta_req(struct mt7915_dev *dev, struct mt7915_vif *mvif, + struct mt7915_sta *msta, int len) +{ + struct sta_req_hdr hdr = { + .bss_idx = mvif->idx, + .wlan_idx_lo = msta ? to_wcid_lo(msta->wcid.idx) : 0, + .wlan_idx_hi = msta ? to_wcid_hi(msta->wcid.idx) : 0, + .muar_idx = msta ? mvif->omac_idx : 0, + .is_tlv_append = 1, + }; + struct sk_buff *skb; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + skb_put_data(skb, &hdr, sizeof(hdr)); + + return skb; +} + +static struct wtbl_req_hdr * +mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, + int cmd, void *sta_wtbl, struct sk_buff **skb) +{ + struct tlv *sta_hdr = sta_wtbl; + struct wtbl_req_hdr hdr = { + .wlan_idx_lo = to_wcid_lo(msta->wcid.idx), + .wlan_idx_hi = to_wcid_hi(msta->wcid.idx), + .operation = cmd, + }; + struct sk_buff *nskb = *skb; + + if (!nskb) { + nskb = mt76_mcu_msg_alloc(&dev->mt76, NULL, + MT7915_WTBL_UPDATE_BA_SIZE); + if (!nskb) + return ERR_PTR(-ENOMEM); + + *skb = nskb; + } + + if (sta_hdr) + sta_hdr->len = cpu_to_le16(sizeof(hdr)); + + return skb_put_data(nskb, &hdr, sizeof(hdr)); +} + +static struct tlv * +mt7915_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, + void *sta_ntlv, void *sta_wtbl) +{ + struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv; + struct tlv *sta_hdr = sta_wtbl; + struct tlv *ptlv, tlv = { + .tag = cpu_to_le16(tag), + .len = cpu_to_le16(len), + }; + u16 ntlv; + + ptlv = skb_put(skb, len); + memcpy(ptlv, &tlv, sizeof(tlv)); + + ntlv = le16_to_cpu(ntlv_hdr->tlv_num); + ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); + + if (sta_hdr) { + u16 size = le16_to_cpu(sta_hdr->len); + + sta_hdr->len = cpu_to_le16(size + len); + } + + return ptlv; +} + +static struct tlv * +mt7915_mcu_add_tlv(struct sk_buff *skb, int tag, int len) +{ + return mt7915_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL); +} + +static struct tlv * +mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len, + __le16 *sub_ntlv, __le16 *len) +{ + struct tlv *ptlv, tlv = { + .tag = cpu_to_le16(sub_tag), + .len = cpu_to_le16(sub_len), + }; + + ptlv = skb_put(skb, sub_len); + memcpy(ptlv, &tlv, sizeof(tlv)); + + *sub_ntlv = cpu_to_le16(le16_to_cpu(*sub_ntlv) + 1); + *len = cpu_to_le16(le16_to_cpu(*len) + sub_len); + + return ptlv; +} + +/** bss info **/ +static int +mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7915_phy *phy, bool enable) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + enum nl80211_band band = chandef->chan->band; + struct bss_info_basic *bss; + u16 wlan_idx = mvif->sta.wcid.idx; + u32 type = NETWORK_INFRA; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + break; + case NL80211_IFTYPE_STATION: + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (enable) { + struct ieee80211_sta *sta; + struct mt7915_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7915_sta *)sta->drv_priv; + wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + break; + case NL80211_IFTYPE_ADHOC: + type = NETWORK_IBSS; + break; + default: + WARN_ON(1); + break; + } + + bss = (struct bss_info_basic *)tlv; + memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); + bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + bss->network_type = cpu_to_le32(type); + bss->dtim_period = vif->bss_conf.dtim_period; + bss->bmc_wcid_lo = to_wcid_lo(wlan_idx); + bss->bmc_wcid_hi = to_wcid_hi(wlan_idx); + bss->phy_mode = mt7915_get_phy_mode(phy->dev, vif, band, NULL); + bss->wmm_idx = mvif->wmm_idx; + bss->active = enable; + + return 0; +} + +static void +mt7915_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct bss_info_omac *omac; + struct tlv *tlv; + u32 type = 0; + u8 idx; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: + type = CONNECTION_INFRA_STA; + break; + case NL80211_IFTYPE_ADHOC: + type = CONNECTION_IBSS_ADHOC; + break; + default: + WARN_ON(1); + break; + } + + omac = (struct bss_info_omac *)tlv; + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + omac->conn_type = cpu_to_le32(type); + omac->omac_idx = mvif->omac_idx; + omac->band_idx = mvif->band_idx; + omac->hw_bss_idx = idx; +} + +static void +mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7915_phy *phy) +{ + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct bss_info_rf_ch *ch; + struct tlv *tlv; + int freq1 = chandef->center_freq1; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RF_CH, sizeof(*ch)); + + ch = (struct bss_info_rf_ch *)tlv; + ch->pri_ch = chandef->chan->hw_value; + ch->center_ch0 = ieee80211_frequency_to_channel(freq1); + ch->bw = mt7915_mcu_chan_bw(chandef); + + if (chandef->width == NL80211_CHAN_WIDTH_80P80) { + int freq2 = chandef->center_freq2; + + ch->center_ch1 = ieee80211_frequency_to_channel(freq2); + } + + ch->he_all_disable = true; +} + +static void +mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7915_phy *phy) +{ + struct bss_info_ra *ra; + struct tlv *tlv; + int max_nss = hweight8(phy->chainmask); + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_RA, sizeof(*ra)); + + ra = (struct bss_info_ra *)tlv; + ra->op_mode = vif->type == NL80211_IFTYPE_AP; + ra->adhoc_en = vif->type == NL80211_IFTYPE_ADHOC; + ra->short_preamble = true; + ra->tx_streams = max_nss; + ra->rx_streams = max_nss; + ra->algo = 4; + ra->train_up_rule = 2; + ra->train_up_high_thres = 110; + ra->train_up_rule_rssi = -70; + ra->low_traffic_thres = 2; + ra->phy_cap = cpu_to_le32(0xfdf); + ra->interval = cpu_to_le32(500); + ra->fast_interval = cpu_to_le32(100); +} + +static void +mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif) +{ +/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ +#define BCN_TX_ESTIMATE_TIME (4096 + 20) + struct bss_info_ext_bss *ext; + int ext_bss_idx, tsf_offset; + struct tlv *tlv; + + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; + if (ext_bss_idx < 0) + return; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); + + ext = (struct bss_info_ext_bss *)tlv; + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); +} + +static void +mt7915_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7915_phy *phy) +{ + struct bss_info_bmc_rate *bmc; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + enum nl80211_band band = chandef->chan->band; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BMC_RATE, sizeof(*bmc)); + + bmc = (struct bss_info_bmc_rate *)tlv; + if (band == NL80211_BAND_2GHZ) { + bmc->short_preamble = true; + } else { + bmc->bc_trans = cpu_to_le16(0x2000); + bmc->mc_trans = cpu_to_le16(0x2080); + } +} + +static void +mt7915_mcu_bss_sync_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct bss_info_sync_mode *sync; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_SYNC_MODE, sizeof(*sync)); + + sync = (struct bss_info_sync_mode *)tlv; + sync->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + sync->dtim_period = vif->bss_conf.dtim_period; + sync->enable = true; +} + +int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, + struct ieee80211_vif *vif, int enable) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct sk_buff *skb; + + skb = mt7915_mcu_alloc_sta_req(phy->dev, mvif, NULL, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + /* bss_omac must be first */ + if (enable) + mt7915_mcu_bss_omac_tlv(skb, vif); + + mt7915_mcu_bss_basic_tlv(skb, vif, phy, enable); + + if (enable) { + mt7915_mcu_bss_rfch_tlv(skb, vif, phy); + mt7915_mcu_bss_bmc_tlv(skb, phy); + mt7915_mcu_bss_ra_tlv(skb, vif, phy); + + if (mvif->omac_idx > HW_BSSID_MAX) + mt7915_mcu_bss_ext_tlv(skb, mvif); + else + mt7915_mcu_bss_sync_tlv(skb, vif); + } + + return __mt76_mcu_skb_send_msg(&phy->dev->mt76, skb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); +} + +/** starec & wtbl **/ +static int +mt7915_mcu_sta_key_tlv(struct sk_buff *skb, struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + struct sta_rec_sec *sec; + struct tlv *tlv; + u32 len = sizeof(*sec); + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec)); + + sec = (struct sta_rec_sec *)tlv; + sec->add = cmd; + + if (cmd == SET_KEY) { + struct sec_key *sec_key; + u8 cipher; + + cipher = mt7915_mcu_get_cipher(key->cipher); + if (cipher == MT_CIPHER_NONE) + return -EOPNOTSUPP; + + sec_key = &sec->key[0]; + sec_key->cipher_len = sizeof(*sec_key); + sec_key->key_id = key->keyidx; + + if (cipher == MT_CIPHER_BIP_CMAC_128) { + sec_key->cipher_id = MT_CIPHER_AES_CCMP; + sec_key->key_len = 16; + memcpy(sec_key->key, key->key, 16); + + sec_key = &sec->key[1]; + sec_key->cipher_id = MT_CIPHER_BIP_CMAC_128; + sec_key->cipher_len = sizeof(*sec_key); + sec_key->key_len = 16; + memcpy(sec_key->key, key->key + 16, 16); + + sec->n_cipher = 2; + } else { + sec_key->cipher_id = cipher; + sec_key->key_len = key->keylen; + memcpy(sec_key->key, key->key, key->keylen); + + if (cipher == MT_CIPHER_TKIP) { + /* Rx/Tx MIC keys are swapped */ + memcpy(sec_key->key + 16, key->key + 24, 8); + memcpy(sec_key->key + 24, key->key + 16, 8); + } + + len -= sizeof(*sec_key); + sec->n_cipher = 1; + } + } else { + len -= sizeof(sec->key); + sec->n_cipher = 0; + } + sec->len = cpu_to_le16(len); + + return 0; +} + +int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct mt7915_sta *msta, struct ieee80211_key_conf *key, + enum set_key_cmd cmd) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct sk_buff *skb; + int ret; + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + ret = mt7915_mcu_sta_key_tlv(skb, key, cmd); + if (ret) + return ret; + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static void +mt7915_mcu_sta_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct sta_rec_ba *ba; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); + + ba = (struct sta_rec_ba *)tlv; + ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT, + ba->winsize = cpu_to_le16(params->buf_size); + ba->ssn = cpu_to_le16(params->ssn); + ba->ba_en = enable << params->tid; + ba->amsdu = params->amsdu; + ba->tid = params->tid; +} + +static void +mt7915_mcu_wtbl_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx, void *sta_wtbl, + void *wtbl_tlv) +{ + struct wtbl_ba *ba; + struct tlv *tlv; + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba), + wtbl_tlv, sta_wtbl); + + ba = (struct wtbl_ba *)tlv; + ba->tid = params->tid; + + if (tx) { + ba->ba_type = MT_BA_TYPE_ORIGINATOR; + ba->sn = enable ? cpu_to_le16(params->ssn) : 0; + ba->ba_en = enable; + } else { + memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN); + ba->ba_type = MT_BA_TYPE_RECIPIENT; + ba->rst_ba_tid = params->tid; + ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; + ba->rst_ba_sb = 1; + } + + if (enable && tx) + ba->ba_winsize = cpu_to_le16(params->buf_size); +} + +static int +mt7915_mcu_sta_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; + struct mt7915_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7915_mcu_sta_ba_tlv(skb, params, enable, tx); + sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, + &skb); + mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7915_mcu_sta_ba(dev, params, enable, true); +} + +int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7915_mcu_sta_ba(dev, params, enable, false); +} + +static void +mt7915_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *sta_wtbl, + void *wtbl_tlv) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct wtbl_generic *generic; + struct wtbl_rx *rx; + struct tlv *tlv; + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_GENERIC, sizeof(*generic), + wtbl_tlv, sta_wtbl); + + generic = (struct wtbl_generic *)tlv; + + if (sta) { + memcpy(generic->peer_addr, sta->addr, ETH_ALEN); + generic->partial_aid = cpu_to_le16(sta->aid); + generic->muar_idx = mvif->omac_idx; + generic->qos = sta->wme; + } else { + /* use BSSID in station mode */ + if (vif->type == NL80211_IFTYPE_STATION) + memcpy(generic->peer_addr, vif->bss_conf.bssid, + ETH_ALEN); + else + eth_broadcast_addr(generic->peer_addr); + + generic->muar_idx = 0xe; + } + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx), + wtbl_tlv, sta_wtbl); + + rx = (struct wtbl_rx *)tlv; + rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1; + rx->rca2 = 1; + rx->rv = 1; +} + +static void +mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ +#define EXTRA_INFO_VER BIT(0) +#define EXTRA_INFO_NEW BIT(1) + struct sta_rec_basic *basic; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic)); + + basic = (struct sta_rec_basic *)tlv; + basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); + + if (enable) { + basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); + basic->conn_state = CONN_STATE_PORT_SECURE; + } else { + basic->conn_state = CONN_STATE_DISCONNECT; + } + + if (!sta) { + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); + eth_broadcast_addr(basic->peer_addr); + return; + } + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + case NL80211_IFTYPE_STATION: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + break; + case NL80211_IFTYPE_ADHOC: + basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); + break; + default: + WARN_ON(1); + break; + } + + memcpy(basic->peer_addr, sta->addr, ETH_ALEN); + basic->aid = cpu_to_le16(sta->aid); + basic->qos = sta->wme; +} + +static void +mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + struct ieee80211_sta *sta) +{ + struct tlv *tlv; + + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *ht; + + /* starec ht */ + tlv = mt7915_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); + ht = (struct sta_rec_ht *)tlv; + ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + } + + /* starec vht */ + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *vht; + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); + vht = (struct sta_rec_vht *)tlv; + vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; + } +} + +static void +mt7915_mcu_wtbl_smps_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct wtbl_smps *smps; + struct tlv *tlv; + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), + wtbl_tlv, sta_wtbl); + smps = (struct wtbl_smps *)tlv; + + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) + smps->smps = true; +} + +static void +mt7915_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct wtbl_ht *ht = NULL; + struct tlv *tlv; + + /* wtbl ht */ + if (sta->ht_cap.ht_supported) { + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), + wtbl_tlv, sta_wtbl); + ht = (struct wtbl_ht *)tlv; + ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ht->af = sta->ht_cap.ampdu_factor; + ht->mm = sta->ht_cap.ampdu_density; + ht->ht = true; + } + + /* wtbl vht */ + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *vht; + u32 af; + + tlv = mt7915_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), + wtbl_tlv, sta_wtbl); + vht = (struct wtbl_vht *)tlv; + vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, + vht->vht = true; + + af = (sta->vht_cap.cap & + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >> + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; + + if (ht && af > ht->af) + ht->af = af; + } + + mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv); +} + +int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, + &skb); + mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static void +mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct sta_rec_ra *ra; + struct tlv *tlv; + enum nl80211_band band = chandef->chan->band; + u32 supp_rate = sta->supp_rates[band]; + int n_rates = hweight32(supp_rate); + u32 cap = sta->wme ? STA_CAP_WMM : 0; + u8 i, nss = sta->rx_nss, mcs = 0; + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra)); + + ra = (struct sta_rec_ra *)tlv; + ra->valid = true; + ra->auto_rate = true; + ra->phy_mode = mt7915_get_phy_mode(dev, vif, band, sta); + ra->channel = chandef->chan->hw_value; + ra->bw = sta->bandwidth; + ra->rate_len = n_rates; + ra->phy.bw = sta->bandwidth; + + if (n_rates) { + if (band == NL80211_BAND_2GHZ) { + ra->supp_mode = MODE_CCK; + ra->supp_cck_rate = supp_rate & GENMASK(3, 0); + ra->phy.type = MT_PHY_TYPE_CCK; + + if (n_rates > 4) { + ra->supp_mode |= MODE_OFDM; + ra->supp_ofdm_rate = supp_rate >> 4; + ra->phy.type = MT_PHY_TYPE_OFDM; + } + } else { + ra->supp_mode = MODE_OFDM; + ra->supp_ofdm_rate = supp_rate; + ra->phy.type = MT_PHY_TYPE_OFDM; + } + } + + if (sta->ht_cap.ht_supported) { + for (i = 0; i < nss; i++) + ra->ht_mcs[i] = sta->ht_cap.mcs.rx_mask[i]; + + ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; + ra->supp_mode |= MODE_HT; + mcs = hweight32(ra->supp_ht_mcs) - 1; + ra->af = sta->ht_cap.ampdu_factor; + ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); + + cap |= STA_CAP_HT; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + cap |= STA_CAP_SGI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + cap |= STA_CAP_SGI_40; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC) + cap |= STA_CAP_TX_STBC; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + cap |= STA_CAP_RX_STBC; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + cap |= STA_CAP_LDPC; + } + + if (sta->vht_cap.vht_supported) { + __le16 mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + u32 af; + u16 vht_mcs; + u8 mcs_prev; + + af = (sta->vht_cap.cap & + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >> + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; + + if (af > sta->ht_cap.ampdu_factor) + ra->af = af; + + cap |= STA_CAP_VHT; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + cap |= STA_CAP_VHT_SGI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + cap |= STA_CAP_VHT_SGI_160; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC) + cap |= STA_CAP_VHT_TX_STBC; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) + cap |= STA_CAP_VHT_RX_STBC; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + cap |= STA_CAP_VHT_LDPC; + + ra->supp_mode |= MODE_VHT; + for (mcs = 0, i = 0; i < nss; i++, mcs_map >>= 2) { + switch (mcs_map & 0x3) { + case IEEE80211_VHT_MCS_SUPPORT_0_9: + vht_mcs = GENMASK(9, 0); + break; + case IEEE80211_VHT_MCS_SUPPORT_0_8: + vht_mcs = GENMASK(8, 0); + break; + case IEEE80211_VHT_MCS_SUPPORT_0_7: + vht_mcs = GENMASK(7, 0); + break; + default: + vht_mcs = 0; + } + + ra->supp_vht_mcs[i] = cpu_to_le16(vht_mcs); + + mcs_prev = hweight16(vht_mcs) - 1; + if (mcs_prev > mcs) + mcs = mcs_prev; + + /* only support 2ss on 160MHz */ + if (i > 1 && (ra->bw == CMD_CBW_160MHZ || + ra->bw == CMD_CBW_8080MHZ)) + break; + } + } + + ra->sta_status = cpu_to_le32(cap); + + switch (BIT(fls(ra->supp_mode) - 1)) { + case MODE_VHT: + ra->phy.type = MT_PHY_TYPE_VHT; + ra->phy.mcs = mcs; + ra->phy.nss = nss; + ra->phy.stbc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC); + ra->phy.ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + ra->phy.sgi = + !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + break; + case MODE_HT: + ra->phy.type = MT_PHY_TYPE_HT; + ra->phy.mcs = mcs; + ra->phy.ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ra->phy.stbc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC); + ra->phy.sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); + break; + default: + break; + } +} + +int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct sk_buff *skb; + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct mt7915_sta *msta; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int ret; + + msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; + + skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, + MT7915_STA_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7915_mcu_sta_basic_tlv(skb, vif, sta, enable); + if (enable && sta) + mt7915_mcu_sta_tlv(dev, skb, sta); + + sta_wtbl = mt7915_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, + sta_wtbl, &skb); + if (enable) { + mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); + if (sta) + mt7915_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr); + } + + ret = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); + if (ret) + return ret; + + if (enable && sta) + return mt7915_mcu_add_rate_ctrl(dev, vif, sta); + + return 0; +} + +int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 dbdc_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 dbdc_idx; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .dbdc_idx = mvif->band_idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + .dbdc_idx = mvif->band_idx, + }, + }; + + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); +} + +static void +mt7915_mcu_beacon_csa(struct sk_buff *rskb, struct sk_buff *skb, + struct bss_info_bcn *bcn, + struct ieee80211_mutable_offsets *offs) +{ + if (offs->csa_counter_offs[0]) { + struct tlv *tlv; + struct bss_info_bcn_csa *csa; + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CSA, + sizeof(*csa), &bcn->sub_ntlv, + &bcn->len); + csa = (struct bss_info_bcn_csa *)tlv; + csa->cnt = skb->data[offs->csa_counter_offs[0]]; + } +} + +static void +mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb, + struct sk_buff *skb, struct bss_info_bcn *bcn, + struct ieee80211_mutable_offsets *offs) +{ + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct bss_info_bcn_cont *cont; + struct tlv *tlv; + u8 *buf; + int len = sizeof(*cont) + MT_TXD_SIZE + skb->len; + + tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT, + len, &bcn->sub_ntlv, &bcn->len); + + cont = (struct bss_info_bcn_cont *)tlv; + cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + cont->tim_ofs = cpu_to_le16(offs->tim_offset); + + if (offs->csa_counter_offs[0]) + cont->csa_ofs = cpu_to_le16(offs->csa_counter_offs[0] - 4); + + buf = (u8 *)tlv + sizeof(*cont); + mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, + true); + memcpy(buf + MT_TXD_SIZE, skb->data, skb->len); +} + +int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int en) +{ +#define MAX_BEACON_SIZE 512 + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct ieee80211_mutable_offsets offs; + struct ieee80211_tx_info *info; + struct sk_buff *skb, *rskb; + struct tlv *tlv; + struct bss_info_bcn *bcn; + int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE; + + rskb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len); + if (IS_ERR(rskb)) + return PTR_ERR(rskb); + + tlv = mt7915_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn)); + bcn = (struct bss_info_bcn *)tlv; + bcn->enable = en; + + skb = ieee80211_beacon_get_template(hw, vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + if (mvif->band_idx) { + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + } + + /* TODO: subtag - bss color count & 11v MBSSID */ + mt7915_mcu_beacon_csa(rskb, skb, bcn, &offs); + mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs); + dev_kfree_skb(skb); + + return __mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); +} + +static int mt7915_mcu_send_firmware(struct mt7915_dev *dev, const void *data, + int len) +{ + int ret = 0, cur_len; + + while (len > 0) { + cur_len = min_t(int, 4096 - sizeof(struct mt7915_mcu_txd), + len); + + ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + data, cur_len, false); + if (ret) + break; + + data += cur_len; + len -= cur_len; + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + } + + return ret; +} + +static int mt7915_mcu_start_firmware(struct mt7915_dev *dev, u32 addr, + u32 option) +{ + struct { + __le32 option; + __le32 addr; + } req = { + .option = cpu_to_le32(option), + .addr = cpu_to_le32(addr), + }; + + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, + &req, sizeof(req), true); +} + +static int mt7915_mcu_restart(struct mt76_dev *dev) +{ + struct { + u8 power_mode; + u8 rsv[3]; + } req = { + .power_mode = 1, + }; + + return __mt76_mcu_send_msg(dev, -MCU_CMD_NIC_POWER_CTRL, &req, + sizeof(req), false); +} + +static int mt7915_mcu_patch_sem_ctrl(struct mt7915_dev *dev, bool get) +{ + struct { + __le32 op; + } req = { + .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), + }; + + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, + &req, sizeof(req), true); +} + +static int mt7915_mcu_start_patch(struct mt7915_dev *dev) +{ + struct { + u8 check_crc; + u8 reserved[3]; + } req = { + .check_crc = 0, + }; + + return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, + &req, sizeof(req), true); +} + +static int mt7915_driver_own(struct mt7915_dev *dev) +{ + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); + + mt76_wr(dev, reg, MT_TOP_LPCR_HOST_DRV_OWN); + if (!mt76_poll_msec(dev, reg, MT_TOP_LPCR_HOST_FW_OWN, + 0, 500)) { + dev_err(dev->mt76.dev, "Timeout for driver own\n"); + return -EIO; + } + + return 0; +} + +static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, + u32 len, u32 mode) +{ + struct { + __le32 addr; + __le32 len; + __le32 mode; + } req = { + .addr = cpu_to_le32(addr), + .len = cpu_to_le32(len), + .mode = cpu_to_le32(mode), + }; + int attr; + + if (req.addr == MCU_PATCH_ADDRESS) + attr = -MCU_CMD_PATCH_START_REQ; + else + attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; + + return __mt76_mcu_send_msg(&dev->mt76, attr, &req, sizeof(req), true); +} + +static int mt7915_load_patch(struct mt7915_dev *dev) +{ + const struct mt7915_patch_hdr *hdr; + const struct firmware *fw = NULL; + int i, ret, sem; + + sem = mt7915_mcu_patch_sem_ctrl(dev, 1); + switch (sem) { + case PATCH_IS_DL: + return 0; + case PATCH_NOT_DL_SEM_SUCCESS: + break; + default: + dev_err(dev->mt76.dev, "Failed to get patch semaphore\n"); + return -EAGAIN; + } + + ret = request_firmware(&fw, MT7915_ROM_PATCH, dev->mt76.dev); + if (ret) + goto out; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7915_patch_hdr *)(fw->data); + + dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n", + be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); + + for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { + struct mt7915_patch_sec *sec; + const u8 *dl; + u32 len, addr; + + sec = (struct mt7915_patch_sec *)(fw->data + sizeof(*hdr) + + i * sizeof(*sec)); + if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) != + PATCH_SEC_TYPE_INFO) { + ret = -EINVAL; + goto out; + } + + addr = be32_to_cpu(sec->info.addr); + len = be32_to_cpu(sec->info.len); + dl = fw->data + be32_to_cpu(sec->offs); + + ret = mt7915_mcu_init_download(dev, addr, len, + DL_MODE_NEED_RSP); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7915_mcu_send_firmware(dev, dl, len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send patch\n"); + goto out; + } + } + + ret = mt7915_mcu_start_patch(dev); + if (ret) + dev_err(dev->mt76.dev, "Failed to start patch\n"); + +out: + sem = mt7915_mcu_patch_sem_ctrl(dev, 0); + switch (sem) { + case PATCH_REL_SEM_SUCCESS: + break; + default: + ret = -EAGAIN; + dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); + goto out; + } + release_firmware(fw); + + return ret; +} + +static u32 mt7915_mcu_gen_dl_mode(u8 feature_set, bool is_wa) +{ + u32 ret = 0; + + ret |= (feature_set & FW_FEATURE_SET_ENCRYPT) ? + (DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV) : 0; + ret |= FIELD_PREP(DL_MODE_KEY_IDX, + FIELD_GET(FW_FEATURE_SET_KEY_IDX, feature_set)); + ret |= DL_MODE_NEED_RSP; + ret |= is_wa ? DL_MODE_WORKING_PDA_CR4 : 0; + + return ret; +} + +static int +mt7915_mcu_send_ram_firmware(struct mt7915_dev *dev, + const struct mt7915_fw_trailer *hdr, + const u8 *data, bool is_wa) +{ + int i, offset = 0; + u32 override = 0, option = 0; + + for (i = 0; i < hdr->n_region; i++) { + const struct mt7915_fw_region *region; + int err; + u32 len, addr, mode; + + region = (const struct mt7915_fw_region *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); + mode = mt7915_mcu_gen_dl_mode(region->feature_set, is_wa); + len = le32_to_cpu(region->len); + addr = le32_to_cpu(region->addr); + + if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR) + override = addr; + + err = mt7915_mcu_init_download(dev, addr, len, mode); + if (err) { + dev_err(dev->mt76.dev, "Download request failed\n"); + return err; + } + + err = mt7915_mcu_send_firmware(dev, data + offset, len); + if (err) { + dev_err(dev->mt76.dev, "Failed to send firmware.\n"); + return err; + } + + offset += len; + } + + if (override) + option |= FW_START_OVERRIDE; + + if (is_wa) + option |= FW_START_WORKING_PDA_CR4; + + return mt7915_mcu_start_firmware(dev, override, option); +} + +static int mt7915_load_ram(struct mt7915_dev *dev) +{ + const struct mt7915_fw_trailer *hdr; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, MT7915_FIRMWARE_WM, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size - + sizeof(*hdr)); + + dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, false); + if (ret) { + dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); + goto out; + } + + release_firmware(fw); + + ret = request_firmware(&fw, MT7915_FIRMWARE_WA, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7915_fw_trailer *)(fw->data + fw->size - + sizeof(*hdr)); + + dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + + ret = mt7915_mcu_send_ram_firmware(dev, hdr, fw->data, true); + if (ret) { + dev_err(dev->mt76.dev, "Failed to start WA firmware\n"); + goto out; + } + + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + +out: + release_firmware(fw); + + return ret; +} + +static int mt7915_load_firmware(struct mt7915_dev *dev) +{ + int ret; + u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); + + val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD); + + if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) { + /* restart firmware once */ + __mt76_mcu_restart(&dev->mt76); + if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, + val, 1000)) { + dev_err(dev->mt76.dev, + "Firmware is not ready for download\n"); + return -EIO; + } + } + + ret = mt7915_load_patch(dev); + if (ret) + return ret; + + ret = mt7915_load_ram(dev); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, + FIELD_PREP(MT_TOP_MISC_FW_STATE, + FW_STATE_WACPU_RDY), 1000)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} + +int mt7915_mcu_init(struct mt7915_dev *dev) +{ + static const struct mt76_mcu_ops mt7915_mcu_ops = { + .headroom = sizeof(struct mt7915_mcu_txd), + .mcu_skb_send_msg = mt7915_mcu_send_message, + .mcu_send_msg = mt7915_mcu_msg_send, + .mcu_restart = mt7915_mcu_restart, + }; + int ret; + + dev->mt76.mcu_ops = &mt7915_mcu_ops, + + ret = mt7915_driver_own(dev); + if (ret) + return ret; + + ret = mt7915_load_firmware(dev); + if (ret) + return ret; + + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + + return 0; +} + +void mt7915_mcu_exit(struct mt7915_dev *dev) +{ + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); + + __mt76_mcu_restart(&dev->mt76); + if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, + FIELD_PREP(MT_TOP_MISC_FW_STATE, + FW_STATE_FW_DOWNLOAD), 1000)) { + dev_err(dev->mt76.dev, "Failed to exit mcu\n"); + return; + } + + reg = mt7915_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); + mt76_wr(dev, reg, MT_TOP_LPCR_HOST_FW_OWN); + skb_queue_purge(&dev->mt76.mcu.res_q); +} + +int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, + bool enable, bool hdr_trans) +{ + struct { + u8 operation; + u8 enable; + u8 check_bssid; + u8 insert_vlan; + u8 remove_vlan; + u8 tid; + u8 mode; + u8 rsv; + } __packed req_trans = { + .enable = hdr_trans, + }; + struct { + u8 enable; + u8 band; + u8 rsv[2]; + } __packed req_mac = { + .enable = enable, + .band = band, + }; + int ret; + + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, + &req_trans, sizeof(req_trans), false); + if (ret) + return ret; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, + &req_mac, sizeof(req_mac), true); +} + +int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable) +{ + struct { + __le32 cmd; + u8 band; + u8 enable; + } __packed req = { + .cmd = cpu_to_le32(SCS_ENABLE), + .band = band, + .enable = enable + 1, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SCS_CTRL, &req, + sizeof(req), false); +} + +int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val) +{ + struct mt7915_dev *dev = phy->dev; + struct { + u8 prot_idx; + u8 band; + u8 rsv[2]; + __le32 len_thresh; + __le32 pkt_thresh; + } __packed req = { + .prot_idx = 1, + .band = phy != &dev->phy, + .len_thresh = cpu_to_le32(val), + .pkt_thresh = cpu_to_le32(0x2), + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PROTECT_CTRL, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif) +{ +#define WMM_AIFS_SET BIT(0) +#define WMM_CW_MIN_SET BIT(1) +#define WMM_CW_MAX_SET BIT(2) +#define WMM_TXOP_SET BIT(3) +#define WMM_PARAM_SET GENMASK(3, 0) +#define TX_CMD_MODE 1 + struct edca { + u8 queue; + u8 set; + u8 aifs; + u8 cw_min; + __le16 cw_max; + __le16 txop; + }; + struct mt7915_mcu_tx { + u8 total; + u8 action; + u8 valid; + u8 mode; + + struct edca edca[IEEE80211_NUM_ACS]; + } __packed req = { + .valid = true, + .mode = TX_CMD_MODE, + .total = IEEE80211_NUM_ACS, + }; + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + int ac; + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + struct edca *e = &req.edca[ac]; + + e->queue = ac + mvif->wmm_idx * MT7915_MAX_WMM_SETS; + e->aifs = mvif->wmm[ac].aifs; + e->txop = cpu_to_le16(mvif->wmm[ac].txop); + + if (mvif->wmm[ac].cw_min) + e->cw_min = fls(mvif->wmm[ac].cw_max); + else + e->cw_min = 5; + + if (mvif->wmm[ac].cw_max) + e->cw_max = cpu_to_le16(fls(mvif->wmm[ac].cw_max)); + else + e->cw_max = cpu_to_le16(10); + } + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EDCA_UPDATE, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter) +{ +#define ENTER_PM_STATE 1 +#define EXIT_PM_STATE 2 + struct { + u8 pm_number; + u8 pm_state; + u8 bssid[ETH_ALEN]; + u8 dtim_period; + u8 wlan_idx_lo; + __le16 bcn_interval; + __le32 aid; + __le32 rx_filter; + u8 band_idx; + u8 wlan_idx_hi; + u8 rsv[2]; + __le32 feature; + u8 omac_idx; + u8 wmm_idx; + u8 bcn_loss_cnt; + u8 bcn_sp_duration; + } __packed req = { + .pm_number = 5, + .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, + .band_idx = band, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, + &req, sizeof(req), true); +} + +int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, + enum mt7915_rdd_cmd cmd, u8 index, + u8 rx_sel, u8 val) +{ + struct { + u8 ctrl; + u8 rdd_idx; + u8 rdd_rx_sel; + u8 val; + u8 rsv[4]; + } __packed req = { + .ctrl = cmd, + .rdd_idx = index, + .rdd_rx_sel = rx_sel, + .val = val, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val) +{ + struct { + u32 tag; + u16 min_lpn; + u8 rsv[2]; + } __packed req = { + .tag = 0x1, + .min_lpn = val, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, + const struct mt7915_dfs_pulse *pulse) +{ + struct { + u32 tag; + struct mt7915_dfs_pulse pulse; + } __packed req = { + .tag = 0x3, + }; + + memcpy(&req.pulse, pulse, sizeof(*pulse)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, + const struct mt7915_dfs_pattern *pattern) +{ + struct { + u32 tag; + u16 radar_type; + struct mt7915_dfs_pattern pattern; + } __packed req = { + .tag = 0x2, + .radar_type = index, + }; + + memcpy(&req.pattern, pattern, sizeof(*pattern)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) +{ + struct mt7915_dev *dev = phy->dev; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + int freq1 = chandef->center_freq1; + struct { + u8 control_ch; + u8 center_ch; + u8 bw; + u8 tx_streams_num; + u8 rx_streams; /* mask or num */ + u8 switch_reason; + u8 band_idx; + u8 center_ch2; /* for 80+80 only */ + __le16 cac_case; + u8 channel_band; + u8 rsv0; + __le32 outband_freq; + u8 txpower_drop; + u8 ap_bw; + u8 ap_center_ch; + u8 rsv1[57]; + } __packed req = { + .control_ch = chandef->chan->hw_value, + .center_ch = ieee80211_frequency_to_channel(freq1), + .bw = mt7915_mcu_chan_bw(chandef), + .tx_streams_num = hweight8(phy->mt76->antenna_mask), + .rx_streams = phy->chainmask, + .band_idx = phy != &dev->phy, + .channel_band = chandef->chan->band, + }; + + if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && + chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) + req.switch_reason = CH_SWITCH_DFS; + else + req.switch_reason = CH_SWITCH_NORMAL; + + if (cmd == MCU_EXT_CMD_CHANNEL_SWITCH) + req.rx_streams = hweight8(req.rx_streams); + + if (chandef->width == NL80211_CHAN_WIDTH_80P80) { + int freq2 = chandef->center_freq2; + + req.center_ch2 = ieee80211_frequency_to_channel(freq2); + } + + return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); +} + +int mt7915_mcu_set_eeprom(struct mt7915_dev *dev) +{ + struct req_hdr { + u8 buffer_mode; + u8 format; + __le16 len; + } __packed req = { + .buffer_mode = EE_MODE_EFUSE, + .format = EE_FORMAT_WHOLE, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + &req, sizeof(req), true); +} + +int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset) +{ + struct mt7915_mcu_eeprom_info req = { + .addr = cpu_to_le32(round_down(offset, 16)), + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_ACCESS, &req, + sizeof(req), true); +} + +int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index) +{ + struct { + u8 ctrl_id; + u8 action; + u8 band; + u8 rsv[5]; + } req = { + .ctrl_id = THERMAL_SENSOR_TEMP_QUERY, + .action = index, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_THERMAL_CTRL, &req, + sizeof(req), true); +} + +int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx) +{ + struct { + __le32 cmd; + u16 wlan_idx; + u16 ru_idx; + u16 direction; + u16 dump_group; + } req = { + .cmd = cpu_to_le32(cmd), + .wlan_idx = wlan_idx, + .dump_group = 1, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RATE_CTRL, &req, + sizeof(req), false); +} + +int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band) +{ + struct { + u8 action; + u8 set; + u8 band; + u8 rsv; + } req = { + .action = action, + .set = set, + .band = band, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SER_TRIGGER, + &req, sizeof(req), false); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h new file mode 100644 index 000000000000..5e4708861ede --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -0,0 +1,837 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_MCU_H +#define __MT7915_MCU_H + +struct mt7915_mcu_txd { + __le32 txd[8]; + + __le16 len; + __le16 pq_id; + + u8 cid; + u8 pkt_type; + u8 set_query; /* FW don't care */ + u8 seq; + + u8 uc_d2b0_rev; + u8 ext_cid; + u8 s2d_index; + u8 ext_cid_ack; + + u32 reserved[5]; +} __packed __aligned(4); + +/* event table */ +enum { + MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, + MCU_EVENT_FW_START = 0x01, + MCU_EVENT_GENERIC = 0x01, + MCU_EVENT_ACCESS_REG = 0x02, + MCU_EVENT_MT_PATCH_SEM = 0x04, + MCU_EVENT_CH_PRIVILEGE = 0x18, + MCU_EVENT_EXT = 0xed, + MCU_EVENT_RESTART_DL = 0xef, +}; + +/* ext event table */ +enum { + MCU_EXT_EVENT_PS_SYNC = 0x5, + MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, + MCU_EXT_EVENT_ASSERT_DUMP = 0x23, + MCU_EXT_EVENT_RDD_REPORT = 0x3a, + MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, + MCU_EXT_EVENT_RATE_REPORT = 0x87, +}; + +struct mt7915_mcu_rxd { + __le32 rxd[6]; + + __le16 len; + __le16 pkt_type_id; + + u8 eid; + u8 seq; + __le16 __rsv; + + u8 ext_eid; + u8 __rsv1[2]; + u8 s2d_index; +}; + +struct mt7915_mcu_rdd_report { + struct mt7915_mcu_rxd rxd; + + u8 idx; + u8 long_detected; + u8 constant_prf_detected; + u8 staggered_prf_detected; + u8 radar_type_idx; + u8 periodic_pulse_num; + u8 long_pulse_num; + u8 hw_pulse_num; + + u8 out_lpn; + u8 out_spn; + u8 out_crpn; + u8 out_crpw; + u8 out_crbn; + u8 out_stgpn; + u8 out_stgpw; + + u8 rsv; + + __le32 out_pri_const; + __le32 out_pri_stg[3]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 mdrdy_flag; + u8 rsv[3]; + } long_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 mdrdy_flag; + u8 rsv[3]; + } periodic_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 sc_pass; + u8 sw_reset; + u8 mdrdy_flag; + u8 tx_active; + } hw_pulse[32]; +} __packed; + +struct mt7915_mcu_eeprom_info { + __le32 addr; + __le32 valid; + u8 data[16]; +} __packed; + +struct mt7915_mcu_ra_info { + struct mt7915_mcu_rxd rxd; + + __le32 event_id; + __le16 wlan_idx; + __le16 ru_idx; + __le16 direction; + __le16 dump_group; + + __le32 suggest_rate; + __le32 min_rate; /* for dynamic sounding */ + __le32 max_rate; /* for dynamic sounding */ + __le32 init_rate_down_rate; + + __le16 curr_rate; + __le16 init_rate_down_total; + __le16 init_rate_down_succ; + __le16 success; + __le16 attempts; + + __le16 prev_rate; + __le16 prob_up_rate; + u8 no_rate_up_cnt; + u8 ppdu_cnt; + u8 gi; + + u8 try_up_fail; + u8 try_up_total; + u8 suggest_wf; + u8 try_up_check; + u8 prob_up_period; + u8 prob_down_pending; +} __packed; + +#define MT_RA_RATE_NSS GENMASK(8, 6) +#define MT_RA_RATE_MCS GENMASK(3, 0) +#define MT_RA_RATE_TX_MODE GENMASK(12, 9) +#define MT_RA_RATE_DCM_EN BIT(4) +#define MT_RA_RATE_BW GENMASK(14, 13) + +#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) +#define MCU_PKT_ID 0xa0 + +enum { + MCU_Q_QUERY, + MCU_Q_SET, + MCU_Q_RESERVED, + MCU_Q_NA +}; + +enum { + MCU_S2D_H2N, + MCU_S2D_C2N, + MCU_S2D_H2C, + MCU_S2D_H2CN +}; + +enum { + MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, + MCU_CMD_FW_START_REQ = 0x02, + MCU_CMD_INIT_ACCESS_REG = 0x3, + MCU_CMD_NIC_POWER_CTRL = 0x4, + MCU_CMD_PATCH_START_REQ = 0x05, + MCU_CMD_PATCH_FINISH_REQ = 0x07, + MCU_CMD_PATCH_SEM_CONTROL = 0x10, + MCU_CMD_EXT_CID = 0xED, + MCU_CMD_FW_SCATTER = 0xEE, + MCU_CMD_RESTART_DL_REQ = 0xEF, +}; + +enum { + MCU_EXT_CMD_EFUSE_ACCESS = 0x01, + MCU_EXT_CMD_PM_STATE_CTRL = 0x07, + MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, + MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + MCU_EXT_CMD_STA_REC_UPDATE = 0x25, + MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, + MCU_EXT_CMD_EDCA_UPDATE = 0x27, + MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, + MCU_EXT_CMD_THERMAL_CTRL = 0x2c, + MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, + MCU_EXT_CMD_PROTECT_CTRL = 0x3e, + MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, + MCU_EXT_CMD_RX_HDR_TRANS = 0x47, + MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_SET_SER_TRIGGER = 0x81, + MCU_EXT_CMD_SCS_CTRL = 0x82, + MCU_EXT_CMD_RATE_CTRL = 0x87, + MCU_EXT_CMD_SET_RDD_TH = 0x9d, +}; + +enum { + PATCH_SEM_RELEASE, + PATCH_SEM_GET +}; + +enum { + PATCH_NOT_DL_SEM_FAIL, + PATCH_IS_DL, + PATCH_NOT_DL_SEM_SUCCESS, + PATCH_REL_SEM_SUCCESS +}; + +enum { + FW_STATE_INITIAL, + FW_STATE_FW_DOWNLOAD, + FW_STATE_NORMAL_OPERATION, + FW_STATE_NORMAL_TRX, + FW_STATE_WACPU_RDY = 7 +}; + +enum { + EE_MODE_EFUSE, + EE_MODE_BUFFER, +}; + +enum { + EE_FORMAT_BIN, + EE_FORMAT_WHOLE, + EE_FORMAT_MULTIPLE, +}; + +#define STA_TYPE_STA BIT(0) +#define STA_TYPE_AP BIT(1) +#define STA_TYPE_ADHOC BIT(2) +#define STA_TYPE_WDS BIT(4) +#define STA_TYPE_BC BIT(5) + +#define NETWORK_INFRA BIT(16) +#define NETWORK_P2P BIT(17) +#define NETWORK_IBSS BIT(18) +#define NETWORK_WDS BIT(21) + +#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA) +#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA) +#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P) +#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P) +#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS) +#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS) +#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA) + +#define CONN_STATE_DISCONNECT 0 +#define CONN_STATE_CONNECT 1 +#define CONN_STATE_PORT_SECURE 2 + +enum { + DEV_INFO_ACTIVE, + DEV_INFO_MAX_NUM +}; + +enum { + SCS_SEND_DATA, + SCS_SET_MANUAL_PD_TH, + SCS_CONFIG, + SCS_ENABLE, + SCS_SHOW_INFO, + SCS_GET_GLO_ADDR, + SCS_GET_GLO_ADDR_EVENT, +}; + +enum { + CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20, + CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40, + CMD_CBW_80MHZ = IEEE80211_STA_RX_BW_80, + CMD_CBW_160MHZ = IEEE80211_STA_RX_BW_160, + CMD_CBW_10MHZ, + CMD_CBW_5MHZ, + CMD_CBW_8080MHZ, + + CMD_HE_MCS_BW80 = 0, + CMD_HE_MCS_BW160, + CMD_HE_MCS_BW8080, + CMD_HE_MCS_BW_NUM +}; + +struct tlv { + __le16 tag; + __le16 len; +} __packed; + +struct bss_info_omac { + __le16 tag; + __le16 len; + u8 hw_bss_idx; + u8 omac_idx; + u8 band_idx; + u8 rsv0; + __le32 conn_type; + u32 rsv1; +} __packed; + +struct bss_info_basic { + __le16 tag; + __le16 len; + __le32 network_type; + u8 active; + u8 rsv0; + __le16 bcn_interval; + u8 bssid[ETH_ALEN]; + u8 wmm_idx; + u8 dtim_period; + u8 bmc_wcid_lo; + u8 cipher; + u8 phy_mode; + u8 max_bssid; /* max BSSID. range: 1 ~ 8, 0: MBSSID disabled */ + u8 non_tx_bssid;/* non-transmitted BSSID, 0: transmitted BSSID */ + u8 bmc_wcid_hi; /* high Byte and version */ + u8 rsv[2]; +} __packed; + +struct bss_info_rf_ch { + __le16 tag; + __le16 len; + u8 pri_ch; + u8 center_ch0; + u8 center_ch1; + u8 bw; + u8 he_ru26_block; /* 1: don't send HETB in RU26, 0: allow */ + u8 he_all_disable; /* 1: disallow all HETB, 0: allow */ + u8 rsv[2]; +} __packed; + +struct bss_info_ext_bss { + __le16 tag; + __le16 len; + __le32 mbss_tsf_offset; /* in unit of us */ + u8 rsv[8]; +} __packed; + +struct bss_info_sync_mode { + __le16 tag; + __le16 len; + __le16 bcn_interval; + u8 enable; + u8 dtim_period; + u8 rsv[8]; +} __packed; + +struct bss_info_bmc_rate { + __le16 tag; + __le16 len; + __le16 bc_trans; + __le16 mc_trans; + u8 short_preamble; + u8 rsv[7]; +} __packed; + +struct bss_info_ra { + __le16 tag; + __le16 len; + u8 op_mode; + u8 adhoc_en; + u8 short_preamble; + u8 tx_streams; + u8 rx_streams; + u8 algo; + u8 force_sgi; + u8 force_gf; + u8 ht_mode; + u8 has_20_sta; /* Check if any sta support GF. */ + u8 bss_width_trigger_events; + u8 vht_nss_cap; + u8 vht_bw_signal; /* not use */ + u8 vht_force_sgi; /* not use */ + u8 se_off; + u8 antenna_idx; + u8 train_up_rule; + u8 rsv[3]; + unsigned short train_up_high_thres; + short train_up_rule_rssi; + unsigned short low_traffic_thres; + __le16 max_phyrate; + __le32 phy_cap; + __le32 interval; + __le32 fast_interval; +} __packed; + +struct bss_info_bcn { + __le16 tag; + __le16 len; + u8 ver; + u8 enable; + __le16 sub_ntlv; +} __packed __aligned(4); + +struct bss_info_bcn_csa { + __le16 tag; + __le16 len; + u8 cnt; + u8 rsv[3]; +} __packed __aligned(4); + +struct bss_info_bcn_bcc { + __le16 tag; + __le16 len; + u8 cnt; + u8 rsv[3]; +} __packed __aligned(4); + +struct bss_info_bcn_mbss { +#define MAX_BEACON_NUM 32 + __le16 tag; + __le16 len; + __le32 bitmap; + __le16 offset[MAX_BEACON_NUM]; + u8 rsv[8]; +} __packed __aligned(4); + +struct bss_info_bcn_cont { + __le16 tag; + __le16 len; + __le16 tim_ofs; + __le16 csa_ofs; + __le16 bcc_ofs; + __le16 pkt_len; +} __packed __aligned(4); + +enum { + BSS_INFO_BCN_CSA, + BSS_INFO_BCN_BCC, + BSS_INFO_BCN_MBSSID, + BSS_INFO_BCN_CONTENT, + BSS_INFO_BCN_MAX +}; + +enum { + BSS_INFO_OMAC, + BSS_INFO_BASIC, + BSS_INFO_RF_CH, /* optional, for BT/LTE coex */ + BSS_INFO_PM, /* sta only */ + BSS_INFO_UAPSD, /* sta only */ + BSS_INFO_ROAM_DETECT, /* obsoleted */ + BSS_INFO_LQ_RM, /* obsoleted */ + BSS_INFO_EXT_BSS, + BSS_INFO_BMC_RATE, /* for bmc rate control in CR4 */ + BSS_INFO_SYNC_MODE, + BSS_INFO_RA, + BSS_INFO_HW_AMSDU, + BSS_INFO_BSS_COLOR, + BSS_INFO_HE_BASIC, + BSS_INFO_PROTECT_INFO, + BSS_INFO_OFFLOAD, + BSS_INFO_11V_MBSSID, + BSS_INFO_MAX_NUM +}; + +enum { + WTBL_RESET_AND_SET = 1, + WTBL_SET, + WTBL_QUERY, + WTBL_RESET_ALL +}; + +struct wtbl_req_hdr { + u8 wlan_idx_lo; + u8 operation; + __le16 tlv_num; + u8 wlan_idx_hi; + u8 rsv[3]; +} __packed; + +struct wtbl_generic { + __le16 tag; + __le16 len; + u8 peer_addr[ETH_ALEN]; + u8 muar_idx; + u8 skip_tx; + u8 cf_ack; + u8 qos; + u8 mesh; + u8 adm; + __le16 partial_aid; + u8 baf_en; + u8 aad_om; +} __packed; + +struct wtbl_rx { + __le16 tag; + __le16 len; + u8 rcid; + u8 rca1; + u8 rca2; + u8 rv; + u8 rsv[4]; +} __packed; + +struct wtbl_ht { + __le16 tag; + __le16 len; + u8 ht; + u8 ldpc; + u8 af; + u8 mm; + u8 rsv[4]; +} __packed; + +struct wtbl_vht { + __le16 tag; + __le16 len; + u8 ldpc; + u8 dyn_bw; + u8 vht; + u8 txop_ps; + u8 rsv[4]; +} __packed; + +enum { + MT_BA_TYPE_INVALID, + MT_BA_TYPE_ORIGINATOR, + MT_BA_TYPE_RECIPIENT +}; + +enum { + RST_BA_MAC_TID_MATCH, + RST_BA_MAC_MATCH, + RST_BA_NO_MATCH +}; + +struct wtbl_ba { + __le16 tag; + __le16 len; + /* common */ + u8 tid; + u8 ba_type; + u8 rsv0[2]; + /* originator only */ + __le16 sn; + u8 ba_en; + u8 ba_winsize_idx; + __le16 ba_winsize; + /* recipient only */ + u8 peer_addr[ETH_ALEN]; + u8 rst_ba_tid; + u8 rst_ba_sel; + u8 rst_ba_sb; + u8 band_idx; + u8 rsv1[4]; +} __packed; + +struct wtbl_bf { + __le16 tag; + __le16 len; + u8 ibf; + u8 ebf; + u8 ibf_vht; + u8 ebf_vht; + u8 gid; + u8 pfmu_idx; + u8 rsv[2]; +} __packed; + +struct wtbl_smps { + __le16 tag; + __le16 len; + u8 smps; + u8 rsv[3]; +} __packed; + +struct wtbl_spe { + __le16 tag; + __le16 len; + u8 spe_idx; + u8 rsv[3]; +} __packed; + +enum { + WTBL_GENERIC, + WTBL_RX, + WTBL_HT, + WTBL_VHT, + WTBL_PEER_PS, /* not used */ + WTBL_TX_PS, + WTBL_HDR_TRANS, + WTBL_SEC_KEY, + WTBL_BA, + WTBL_RDG, /* obsoleted */ + WTBL_PROTECT, /* not used */ + WTBL_CLEAR, /* not used */ + WTBL_BF, + WTBL_SMPS, + WTBL_RAW_DATA, /* debug only */ + WTBL_PN, + WTBL_SPE, + WTBL_MAX_NUM +}; + +struct sta_ntlv_hdr { + u8 rsv[2]; + __le16 tlv_num; +} __packed; + +struct sta_req_hdr { + u8 bss_idx; + u8 wlan_idx_lo; + __le16 tlv_num; + u8 is_tlv_append; + u8 muar_idx; + u8 wlan_idx_hi; + u8 rsv; +} __packed; + +struct sta_rec_basic { + __le16 tag; + __le16 len; + __le32 conn_type; + u8 conn_state; + u8 qos; + __le16 aid; + u8 peer_addr[ETH_ALEN]; + __le16 extra_info; +} __packed; + +struct sta_rec_ht { + __le16 tag; + __le16 len; + __le16 ht_cap; + u16 rsv; +} __packed; + +struct sta_rec_vht { + __le16 tag; + __le16 len; + __le32 vht_cap; + __le16 vht_rx_mcs_map; + __le16 vht_tx_mcs_map; + u8 rts_bw_sig; + u8 rsv[3]; +} __packed; + +struct sta_rec_ba { + __le16 tag; + __le16 len; + u8 tid; + u8 ba_type; + u8 amsdu; + u8 ba_en; + __le16 ssn; + __le16 winsize; +} __packed; + +struct sec_key { + u8 cipher_id; + u8 cipher_len; + u8 key_id; + u8 key_len; + u8 key[32]; +} __packed; + +struct sta_rec_sec { + __le16 tag; + __le16 len; + u8 add; + u8 n_cipher; + u8 rsv[2]; + + struct sec_key key[2]; +} __packed; + +struct ra_phy { + u8 type; + u8 flag; + u8 stbc; + u8 sgi; + u8 bw; + u8 ldpc; + u8 mcs; + u8 nss; + u8 he_ltf; +}; + +struct sta_rec_ra { + __le16 tag; + __le16 len; + + u8 valid; + u8 auto_rate; + u8 phy_mode; + u8 channel; + u8 bw; + u8 disable_cck; + u8 ht_mcs32; + u8 ht_gf; + u8 ht_mcs[4]; + u8 mmps_mode; + u8 gband_256; + u8 af; + u8 auth_wapi_mode; + u8 rate_len; + + u8 supp_mode; + u8 supp_cck_rate; + u8 supp_ofdm_rate; + __le32 supp_ht_mcs; + __le16 supp_vht_mcs[4]; + + u8 op_mode; + u8 op_vht_chan_width; + u8 op_vht_rx_nss; + u8 op_vht_rx_nss_type; + + __le32 sta_status; + + struct ra_phy phy; +} __packed; + +enum { + STA_REC_BASIC, + STA_REC_RA, + STA_REC_RA_CMM_INFO, + STA_REC_RA_UPDATE, + STA_REC_BF, + STA_REC_AMSDU, + STA_REC_BA, + STA_REC_RED, /* not used */ + STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */ + STA_REC_HT, + STA_REC_VHT, + STA_REC_APPS, + STA_REC_KEY, + STA_REC_WTBL, + STA_REC_HE, + STA_REC_HW_AMSDU, + STA_REC_WTBL_AADOM, + STA_REC_KEY_V2, + STA_REC_MURU, + STA_REC_MUEDCA, + STA_REC_MAX_NUM +}; + +enum mt7915_cipher_type { + MT_CIPHER_NONE, + MT_CIPHER_WEP40, + MT_CIPHER_WEP104, + MT_CIPHER_WEP128, + MT_CIPHER_TKIP, + MT_CIPHER_AES_CCMP, + MT_CIPHER_CCMP_256, + MT_CIPHER_GCMP, + MT_CIPHER_GCMP_256, + MT_CIPHER_WAPI, + MT_CIPHER_BIP_CMAC_128, +}; + +enum { + CH_SWITCH_NORMAL = 0, + CH_SWITCH_SCAN = 3, + CH_SWITCH_MCC = 4, + CH_SWITCH_DFS = 5, + CH_SWITCH_BACKGROUND_SCAN_START = 6, + CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7, + CH_SWITCH_BACKGROUND_SCAN_STOP = 8, + CH_SWITCH_SCAN_BYPASS_DPD = 9 +}; + +enum { + THERMAL_SENSOR_TEMP_QUERY, + THERMAL_SENSOR_MANUAL_CTRL, + THERMAL_SENSOR_INFO_QUERY, + THERMAL_SENSOR_TASK_CTRL, +}; + +#define MT7915_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_generic) + \ + sizeof(struct wtbl_rx) + \ + sizeof(struct wtbl_ht) + \ + sizeof(struct wtbl_vht) + \ + sizeof(struct wtbl_ba) + \ + sizeof(struct wtbl_bf) + \ + sizeof(struct wtbl_smps) + \ + sizeof(struct wtbl_spe)) + +#define MT7915_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_ht) + \ + sizeof(struct sta_rec_ba) + \ + sizeof(struct sta_rec_vht) + \ + sizeof(struct tlv) + \ + sizeof(struct sta_rec_sec) + \ + sizeof(struct sta_rec_ra) + \ + MT7915_WTBL_UPDATE_MAX_SIZE) + +#define MT7915_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_ba)) + +#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct bss_info_bcn_csa) + \ + sizeof(struct bss_info_bcn_bcc) + \ + sizeof(struct bss_info_bcn_mbss) + \ + sizeof(struct bss_info_bcn_cont)) + +#define PHY_MODE_A BIT(0) +#define PHY_MODE_B BIT(1) +#define PHY_MODE_G BIT(2) +#define PHY_MODE_GN BIT(3) +#define PHY_MODE_AN BIT(4) +#define PHY_MODE_AC BIT(5) + +#define MODE_CCK BIT(0) +#define MODE_OFDM BIT(1) +#define MODE_HT BIT(2) +#define MODE_VHT BIT(3) + +#define STA_CAP_WMM BIT(0) +#define STA_CAP_SGI_20 BIT(4) +#define STA_CAP_SGI_40 BIT(5) +#define STA_CAP_TX_STBC BIT(6) +#define STA_CAP_RX_STBC BIT(7) +#define STA_CAP_VHT_SGI_80 BIT(16) +#define STA_CAP_VHT_SGI_160 BIT(17) +#define STA_CAP_VHT_TX_STBC BIT(18) +#define STA_CAP_VHT_RX_STBC BIT(19) +#define STA_CAP_VHT_LDPC BIT(23) +#define STA_CAP_LDPC BIT(24) +#define STA_CAP_HT BIT(26) +#define STA_CAP_VHT BIT(27) + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h new file mode 100644 index 000000000000..f2139a5248d9 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -0,0 +1,442 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_H +#define __MT7915_H + +#include +#include +#include "../mt76.h" +#include "regs.h" + +#define MT7915_MAX_INTERFACES 4 +#define MT7915_MAX_WMM_SETS 4 +#define MT7915_WTBL_SIZE 288 +#define MT7915_WTBL_RESERVED (MT7915_WTBL_SIZE - 1) +#define MT7915_WTBL_STA (MT7915_WTBL_RESERVED - \ + MT7915_MAX_INTERFACES) + +#define MT7915_WATCHDOG_TIME (HZ / 10) +#define MT7915_RESET_TIMEOUT (30 * HZ) + +#define MT7915_TX_RING_SIZE 2048 +#define MT7915_TX_MCU_RING_SIZE 256 +#define MT7915_TX_FWDL_RING_SIZE 128 + +#define MT7915_RX_RING_SIZE 1536 +#define MT7915_RX_MCU_RING_SIZE 512 + +#define MT7915_FIRMWARE_WA "mediatek/mt7915_wa.bin" +#define MT7915_FIRMWARE_WM "mediatek/mt7915_wm.bin" +#define MT7915_ROM_PATCH "mediatek/mt7915_rom_patch.bin" + +#define MT7915_EEPROM_SIZE 3584 +#define MT7915_TOKEN_SIZE 8192 + +#define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +#define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ +#define MT7915_5G_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7915_2G_RATE_DEFAULT 0x0 /* CCK 1M */ + + +struct mt7915_vif; +struct mt7915_sta; +struct mt7915_dfs_pulse; +struct mt7915_dfs_pattern; + +enum mt7915_txq_id { + MT7915_TXQ_FWDL = 16, + MT7915_TXQ_MCU_WM, + MT7915_TXQ_BAND0, + MT7915_TXQ_BAND1, + MT7915_TXQ_MCU_WA, +}; + +enum mt7915_rxq_id { + MT7915_RXQ_BAND0 = 0, + MT7915_RXQ_BAND1, + MT7915_RXQ_MCU_WM = 0, + MT7915_RXQ_MCU_WA, +}; + +enum mt7915_ampdu_state { + MT7915_AGGR_STOP, + MT7915_AGGR_PROGRESS, + MT7915_AGGR_START, + MT7915_AGGR_OPERATIONAL +}; + +struct mt7915_sta_stats { + struct rate_info prob_rate; + struct rate_info tx_rate; + + unsigned long per; + unsigned long changed; + unsigned long jiffies; +}; + +struct mt7915_sta { + struct mt76_wcid wcid; /* must be first */ + + struct mt7915_vif *vif; + + struct list_head poll_list; + u32 airtime_ac[8]; + + struct mt7915_sta_stats stats; + struct work_struct stats_work; + + spinlock_t ampdu_lock; + enum mt7915_ampdu_state ampdu_state[IEEE80211_NUM_TIDS]; +}; + +struct mt7915_vif { + u16 idx; + u8 omac_idx; + u8 band_idx; + u8 wmm_idx; + + struct { + u16 cw_min; + u16 cw_max; + u16 txop; + u8 aifs; + } wmm[IEEE80211_NUM_ACS]; + + struct mt7915_sta sta; + struct mt7915_dev *dev; +}; + +struct mib_stats { + u16 ack_fail_cnt; + u16 fcs_err_cnt; + u16 rts_cnt; + u16 rts_retries_cnt; + u16 ba_miss_cnt; +}; + +struct mt7915_phy { + struct mt76_phy *mt76; + struct mt7915_dev *dev; + + u32 rxfilter; + u32 omac_mask; + + u16 noise; + u16 chainmask; + + s16 coverage_class; + u8 slottime; + + u8 rdd_state; + int dfs_state; + + __le32 rx_ampdu_ts; + u32 ampdu_ref; + + struct mib_stats mib; +}; + +struct mt7915_dev { + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + + struct mt7915_phy phy; + u32 vif_mask; + u32 omac_mask; + + u16 chainmask; + + struct work_struct init_work; + struct work_struct reset_work; + wait_queue_head_t reset_wait; + u32 reset_state; + + struct list_head sta_poll_list; + spinlock_t sta_poll_lock; + + u32 hw_pattern; + + spinlock_t token_lock; + struct idr token; + + u8 mac_work_count; + bool fw_debug; +}; + +enum { + HW_BSSID_0 = 0x0, + HW_BSSID_1, + HW_BSSID_2, + HW_BSSID_3, + HW_BSSID_MAX, + EXT_BSSID_START = 0x10, + EXT_BSSID_1, + EXT_BSSID_2, + EXT_BSSID_3, + EXT_BSSID_4, + EXT_BSSID_5, + EXT_BSSID_6, + EXT_BSSID_7, + EXT_BSSID_8, + EXT_BSSID_9, + EXT_BSSID_10, + EXT_BSSID_11, + EXT_BSSID_12, + EXT_BSSID_13, + EXT_BSSID_14, + EXT_BSSID_15, + EXT_BSSID_END +}; + +enum { + MT_RX_SEL0, + MT_RX_SEL1, +}; + +enum mt7915_rdd_cmd { + RDD_STOP, + RDD_START, + RDD_DET_MODE, + RDD_RADAR_EMULATE, + RDD_START_TXQ = 20, + RDD_CAC_START = 50, + RDD_CAC_END, + RDD_NORMAL_START, + RDD_DISABLE_DFS_CAL, + RDD_PULSE_DBG, + RDD_READ_PULSE, + RDD_RESUME_BF, + RDD_IRQ_OFF, +}; + +enum { + RATE_CTRL_RU_INFO, + RATE_CTRL_FIXED_RATE_INFO, + RATE_CTRL_DUMP_INFO, + RATE_CTRL_MU_INFO, +}; + +static inline struct mt7915_phy * +mt7915_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + +static inline struct mt7915_dev * +mt7915_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt7915_dev, mt76); +} + +static inline struct mt7915_phy * +mt7915_ext_phy(struct mt7915_dev *dev) +{ + struct mt76_phy *phy = dev->mt76.phy2; + + if (!phy) + return NULL; + + return phy->priv; +} + +static inline void +mt7915_set_aggr_state(struct mt7915_sta *msta, u8 tid, + enum mt7915_ampdu_state state) +{ + spin_lock_bh(&msta->ampdu_lock); + msta->ampdu_state[tid] = state; + spin_unlock_bh(&msta->ampdu_lock); +} + +extern const struct ieee80211_ops mt7915_ops; +extern struct pci_driver mt7915_pci_driver; + +u32 mt7915_reg_map(struct mt7915_dev *dev, u32 addr); + +int mt7915_register_device(struct mt7915_dev *dev); +void mt7915_unregister_device(struct mt7915_dev *dev); +int mt7915_register_ext_phy(struct mt7915_dev *dev); +void mt7915_unregister_ext_phy(struct mt7915_dev *dev); +int mt7915_eeprom_init(struct mt7915_dev *dev); +u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset); +int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx); +int mt7915_dma_init(struct mt7915_dev *dev); +void mt7915_dma_prefetch(struct mt7915_dev *dev); +void mt7915_dma_cleanup(struct mt7915_dev *dev); +int mt7915_mcu_init(struct mt7915_dev *dev); +int mt7915_mcu_add_dev_info(struct mt7915_dev *dev, + struct ieee80211_vif *vif, bool enable); +int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, + struct ieee80211_vif *vif, int enable); +int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable); +int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool add); +int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, + struct ieee80211_ampdu_params *params, + bool add); +int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct mt7915_sta *msta, struct ieee80211_key_conf *key, + enum set_key_cmd cmd); +int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int enable); +int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd); +int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif); +int mt7915_mcu_set_eeprom(struct mt7915_dev *dev); +int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset); +int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable, + bool hdr_trans); +int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable); +int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); +int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val); +int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter); +int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val); +int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev, + const struct mt7915_dfs_pulse *pulse); +int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index, + const struct mt7915_dfs_pattern *pattern); +int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx); +int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index); +int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd, + u8 index, u8 rx_sel, u8 val); +void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb); +void mt7915_mcu_exit(struct mt7915_dev *dev); + +static inline bool is_mt7915(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7915; +} + +static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask) +{ + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); +} + +static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask) +{ + mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0); +} + +static inline u32 +mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) +{ + u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); + + mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base); + /* use read to push write */ + mt76_rr(dev, MT_HIF_REMAP_L1); + + return MT_HIF_REMAP_BASE_L1 + offset; +} + +static inline u32 +mt7915_l1_rr(struct mt7915_dev *dev, u32 addr) +{ + return mt76_rr(dev, mt7915_reg_map_l1(dev, addr)); +} + +static inline void +mt7915_l1_wr(struct mt7915_dev *dev, u32 addr, u32 val) +{ + mt76_wr(dev, mt7915_reg_map_l1(dev, addr), val); +} + +static inline u32 +mt7915_l1_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val) +{ + val |= mt7915_l1_rr(dev, addr) & ~mask; + mt7915_l1_wr(dev, addr, val); + + return val; +} + +#define mt7915_l1_set(dev, addr, val) mt7915_l1_rmw(dev, addr, 0, val) +#define mt7915_l1_clear(dev, addr, val) mt7915_l1_rmw(dev, addr, val, 0) + +static inline u32 +mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) +{ + u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr); + u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr); + + mt76_rmw_field(dev, MT_HIF_REMAP_L2, MT_HIF_REMAP_L2_MASK, base); + /* use read to push write */ + mt76_rr(dev, MT_HIF_REMAP_L2); + + return MT_HIF_REMAP_BASE_L2 + offset; +} + +static inline u32 +mt7915_l2_rr(struct mt7915_dev *dev, u32 addr) +{ + return mt76_rr(dev, mt7915_reg_map_l2(dev, addr)); +} + +static inline void +mt7915_l2_wr(struct mt7915_dev *dev, u32 addr, u32 val) +{ + mt76_wr(dev, mt7915_reg_map_l2(dev, addr), val); +} + +static inline u32 +mt7915_l2_rmw(struct mt7915_dev *dev, u32 addr, u32 mask, u32 val) +{ + val |= mt7915_l2_rr(dev, addr) & ~mask; + mt7915_l2_wr(dev, addr, val); + + return val; +} + +#define mt7915_l2_set(dev, addr, val) mt7915_l2_rmw(dev, addr, 0, val) +#define mt7915_l2_clear(dev, addr, val) mt7915_l2_rmw(dev, addr, val, 0) + +bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask); +void mt7915_mac_reset_counters(struct mt7915_phy *phy); +void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy); +void mt7915_mac_sta_poll(struct mt7915_dev *dev); +void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, bool beacon); +void mt7915_mac_set_timing(struct mt7915_phy *phy); +int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb); +void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb); +int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7915_mac_work(struct work_struct *work); +void mt7915_mac_reset_work(struct work_struct *work); +void mt7915_mac_sta_stats_work(struct work_struct *work); +int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + enum mt76_txq_id qid, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, + struct mt76_tx_info *tx_info); +void mt7915_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, + struct mt76_queue_entry *e); +void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb); +void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); +void mt7915_stats_work(struct work_struct *work); +void mt7915_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *txwi); +int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force); +int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy); +void mt7915_update_channel(struct mt76_dev *mdev); +int mt7915_init_debugfs(struct mt7915_dev *dev); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c new file mode 100644 index 000000000000..12a562d3aa3d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. + * + * Author: Ryder Lee + */ + +#include +#include +#include + +#include "mt7915.h" +#include "mac.h" +#include "../trace.h" + +static const struct pci_device_id mt7915_pci_device_table[] = { + { PCI_DEVICE(0x14c3, 0x7915) }, + { }, +}; + +static void +mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + + mt7915_irq_enable(dev, MT_INT_RX_DONE(q)); +} + +static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) +{ + struct mt7915_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_TX_DONE_ALL) { + mt7915_irq_disable(dev, MT_INT_TX_DONE_ALL); + napi_schedule(&dev->mt76.tx_napi); + } + + if (intr & MT_INT_RX_DONE_DATA) { + mt7915_irq_disable(dev, MT_INT_RX_DONE_DATA); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE_WM) { + mt7915_irq_disable(dev, MT_INT_RX_DONE_WM); + napi_schedule(&dev->mt76.napi[1]); + } + + if (intr & MT_INT_RX_DONE_WA) { + mt7915_irq_disable(dev, MT_INT_RX_DONE_WA); + napi_schedule(&dev->mt76.napi[2]); + } + + if (intr & MT_INT_MCU_CMD) { + u32 val = mt76_rr(dev, MT_MCU_CMD); + + mt76_wr(dev, MT_MCU_CMD, val); + if (val & MT_MCU_CMD_ERROR_MASK) { + dev->reset_state = val; + ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + wake_up(&dev->reset_wait); + } + } + + return IRQ_HANDLED; +} + +static int mt7915_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7915_txp), + .drv_flags = MT_DRV_TXWI_NO_FREE, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7915_tx_prepare_skb, + .tx_complete_skb = mt7915_tx_complete_skb, + .rx_skb = mt7915_queue_rx_skb, + .rx_poll_complete = mt7915_rx_poll_complete, + .sta_ps = mt7915_sta_ps, + .sta_add = mt7915_mac_sta_add, + .sta_remove = mt7915_mac_sta_remove, + .update_survey = mt7915_update_channel, + }; + struct mt7915_dev *dev; + struct mt76_dev *mdev; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops, + &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7915_dev, mt76); + + mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + mdev->rev = (mt7915_l1_rr(dev, MT_HW_CHIPID) << 16) | + (mt7915_l1_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + /* master switch of PCIe tnterrupt enable */ + mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); + + ret = devm_request_irq(mdev->dev, pdev->irq, mt7915_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7915_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} + +static void mt7915_pci_remove(struct pci_dev *pdev) +{ + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + + mt7915_unregister_device(dev); +} + +struct pci_driver mt7915_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = mt7915_pci_device_table, + .probe = mt7915_pci_probe, + .remove = mt7915_pci_remove, +}; + +module_pci_driver(mt7915_pci_driver); + +MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); +MODULE_FIRMWARE(MT7915_FIRMWARE_WA); +MODULE_FIRMWARE(MT7915_FIRMWARE_WM); +MODULE_FIRMWARE(MT7915_ROM_PATCH); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h new file mode 100644 index 000000000000..572bdc16fb2d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2020 MediaTek Inc. */ + +#ifndef __MT7915_REGS_H +#define __MT7915_REGS_H + +/* MCU WFDMA1 */ +#define MT_MCU_WFDMA1_BASE 0x3000 +#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) + +#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) +#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + +#define MT_PLE_BASE 0x8000 +#define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) + +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0) +#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4) +#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8) +#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc) + +#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \ + ((n) << 2)) +#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) + +#define MT_MDP_BASE 0xf000 +#define MT_MDP(ofs) (MT_MDP_BASE + (ofs)) + +#define MT_MDP_DCR0 MT_MDP(0x000) +#define MT_MDP_DCR0_DAMSDU_EN BIT(15) + +#define MT_MDP_DCR1 MT_MDP(0x004) +#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3) + +#define MT_MDP_BNRCFR0(_band) MT_MDP(0x070 + ((_band) << 8)) +#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4) +#define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6) +#define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8) + +#define MT_MDP_BNRCFR1(_band) MT_MDP(0x074 + ((_band) << 8)) +#define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22) +#define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27) +#define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29) +#define MT_MDP_TO_HIF 0 +#define MT_MDP_TO_WM 1 + +/* TMAC: band 0(0x21000), band 1(0xa1000) */ +#define MT_WF_TMAC_BASE(_band) ((_band) ? 0xa1000 : 0x21000) +#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) + +#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) +#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + +#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) +#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) +#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) +#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) + +/* DMA Band 0 */ +#define MT_WF_DMA_BASE 0x21e00 +#define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) + +#define MT_DMA_DCR0 MT_WF_DMA(0x000) +#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) +#define MT_DMA_DCR0_RXD_G5_EN BIT(23) + +/* MIB: band 0(0x24800), band 1(0xa4800) */ +#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800) +#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) + +#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0) + +#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) +#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048) +#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098) +#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) +#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c) +#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) + +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) +#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4)) +#define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16) + +#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) +#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) + +#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2)) +#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2)) +#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2)) +#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) + +#define MT_WTBLON_TOP_BASE 0x34000 +#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x0) +#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) + +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x030) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) +#define MT_WTBL_UPDATE_BUSY BIT(31) + +#define MT_WTBL_BASE 0x38000 +#define MT_WTBL_LMAC_ID GENMASK(14, 8) +#define MT_WTBL_LMAC_DW GENMASK(7, 2) +#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ + FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ + FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) + +/* AGG: band 0(0x20800), band 1(0xa0800) */ +#define MT_WF_AGG_BASE(_band) ((_band) ? 0xa0800 : 0x20800) +#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) + +#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) +#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) +#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) + +/* ARB: band 0(0x20c00), band 1(0xa0c00) */ +#define MT_WF_ARB_BASE(_band) ((_band) ? 0xa0c00 : 0x20c00) +#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) + +#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) +#define MT_ARB_SCR_TX_DISABLE BIT(8) +#define MT_ARB_SCR_RX_DISABLE BIT(9) + +/* RMAC: band 0(0x21400), band 1(0xa1400) */ +#define MT_WF_RMAC_BASE(_band) ((_band) ? 0xa1400 : 0x21400) +#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) + +#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) +#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) +#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) +#define MT_WF_RFCR_DROP_VERSION BIT(3) +#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) +#define MT_WF_RFCR_DROP_MCAST BIT(5) +#define MT_WF_RFCR_DROP_BCAST BIT(6) +#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) +#define MT_WF_RFCR_DROP_A3_MAC BIT(8) +#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) +#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) +#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) +#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) +#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) +#define MT_WF_RFCR_DROP_CTS BIT(14) +#define MT_WF_RFCR_DROP_RTS BIT(15) +#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) +#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) +#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) +#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) +#define MT_WF_RFCR_DROP_NDPA BIT(20) +#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) + +#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004) +#define MT_WF_RFCR1_DROP_ACK BIT(4) +#define MT_WF_RFCR1_DROP_BF_POLL BIT(5) +#define MT_WF_RFCR1_DROP_BA BIT(6) +#define MT_WF_RFCR1_DROP_CFEND BIT(7) +#define MT_WF_RFCR1_DROP_CFACK BIT(8) + +#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4) +#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) +#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) + +#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8) +#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) +#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380) + +/* WFDMA0 */ +#define MT_WFDMA0_BASE 0xd4000 +#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) + +#define MT_WFDMA0_RST MT_WFDMA0(0x100) +#define MT_WFDMA0_RST_LOGIC_RST BIT(4) +#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5) + +#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) + +#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) +#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) + +#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) +#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) + +#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x500) + +#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) +#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) +#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) + +/* WFDMA1 */ +#define MT_WFDMA1_BASE 0xd5000 +#define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs)) + +#define MT_WFDMA1_RST MT_WFDMA1(0x100) +#define MT_WFDMA1_RST_LOGIC_RST BIT(4) +#define MT_WFDMA1_RST_DMASHDL_ALL_RST BIT(5) + +#define MT_WFDMA1_BUSY_ENA MT_WFDMA1(0x13c) +#define MT_WFDMA1_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA1_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA1_BUSY_ENA_RX_FIFO BIT(2) + +#define MT_MCU_CMD MT_WFDMA1(0x1f0) +#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_DMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) + +#define MT_WFDMA1_GLO_CFG MT_WFDMA1(0x208) +#define MT_WFDMA1_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WFDMA1_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WFDMA1_GLO_CFG_OMIT_TX_INFO BIT(28) +#define MT_WFDMA1_GLO_CFG_OMIT_RX_INFO BIT(27) + +#define MT_WFDMA1_RST_DTX_PTR MT_WFDMA1(0x20c) +#define MT_WFDMA1_PRI_DLY_INT_CFG0 MT_WFDMA1(0x2f0) + +#define MT_TX_RING_BASE MT_WFDMA1(0x300) +#define MT_RX_EVENT_RING_BASE MT_WFDMA1(0x500) + +#define MT_WFDMA1_TX_RING0_EXT_CTRL MT_WFDMA1(0x600) +#define MT_WFDMA1_TX_RING1_EXT_CTRL MT_WFDMA1(0x604) +#define MT_WFDMA1_TX_RING2_EXT_CTRL MT_WFDMA1(0x608) +#define MT_WFDMA1_TX_RING3_EXT_CTRL MT_WFDMA1(0x60c) +#define MT_WFDMA1_TX_RING4_EXT_CTRL MT_WFDMA1(0x610) +#define MT_WFDMA1_TX_RING5_EXT_CTRL MT_WFDMA1(0x614) +#define MT_WFDMA1_TX_RING6_EXT_CTRL MT_WFDMA1(0x618) +#define MT_WFDMA1_TX_RING7_EXT_CTRL MT_WFDMA1(0x61c) + +#define MT_WFDMA1_TX_RING16_EXT_CTRL MT_WFDMA1(0x640) +#define MT_WFDMA1_TX_RING17_EXT_CTRL MT_WFDMA1(0x644) +#define MT_WFDMA1_TX_RING18_EXT_CTRL MT_WFDMA1(0x648) +#define MT_WFDMA1_TX_RING19_EXT_CTRL MT_WFDMA1(0x64c) +#define MT_WFDMA1_TX_RING20_EXT_CTRL MT_WFDMA1(0x650) +#define MT_WFDMA1_TX_RING21_EXT_CTRL MT_WFDMA1(0x654) +#define MT_WFDMA1_TX_RING22_EXT_CTRL MT_WFDMA1(0x658) +#define MT_WFDMA1_TX_RING23_EXT_CTRL MT_WFDMA1(0x65c) + +#define MT_WFDMA1_RX_RING0_EXT_CTRL MT_WFDMA1(0x680) +#define MT_WFDMA1_RX_RING1_EXT_CTRL MT_WFDMA1(0x684) +#define MT_WFDMA1_RX_RING2_EXT_CTRL MT_WFDMA1(0x688) +#define MT_WFDMA1_RX_RING3_EXT_CTRL MT_WFDMA1(0x68c) + +/* WFDMA CSR */ +#define MT_WFDMA_EXT_CSR_BASE 0xd7000 +#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) + +#define MT_INT_SOURCE_CSR MT_WFDMA_EXT_CSR(0x10) +#define MT_INT_MASK_CSR MT_WFDMA_EXT_CSR(0x14) +#define MT_INT_RX_DONE_DATA BIT(16) +#define MT_INT_RX_DONE_WM BIT(0) +#define MT_INT_RX_DONE_WA BIT(1) +#define MT_INT_RX_DONE(_n) ((_n) ? BIT((_n) - 1) : BIT(16)) +#define MT_INT_RX_DONE_ALL (BIT(0) | BIT(1) | BIT(16)) +#define MT_INT_TX_DONE_ALL (BIT(15) | GENMASK(27, 26) | BIT(30)) +#define MT_INT_MCU_CMD BIT(29) + +#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) +#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) + +/* WFDMA0 PCIE1 */ +#define MT_WFDMA0_PCIE1_BASE 0xd8000 +#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) + +#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c) +#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA0_PCIE1_BUSY_ENA_RX_FIFO BIT(2) + +/* WFDMA1 PCIE1 */ +#define MT_WFDMA1_PCIE1_BASE 0xd9000 +#define MT_WFDMA1_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs)) + +#define MT_WFDMA1_PCIE1_BUSY_ENA MT_WFDMA1_PCIE1(0x13c) +#define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2) + +#define MT_INFRA_CFG_BASE 0xf1000 +#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) + +#define MT_HIF_REMAP_L1 MT_INFRA(0x1ac) +#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0) +#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0) +#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) +#define MT_HIF_REMAP_BASE_L1 0xe0000 + +#define MT_HIF_REMAP_L2 MT_INFRA(0x1b0) +#define MT_HIF_REMAP_L2_MASK GENMASK(19, 0) +#define MT_HIF_REMAP_L2_OFFSET GENMASK(11, 0) +#define MT_HIF_REMAP_L2_BASE GENMASK(31, 12) +#define MT_HIF_REMAP_BASE_L2 0x00000 + +#define MT_TOP_BASE 0x18060000 +#define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) + +#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) +#define MT_TOP_LPCR_HOST_FW_OWN BIT(0) +#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) + +#define MT_TOP_MISC MT_TOP(0xf0) +#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) + +#define MT_HW_BOUND 0x70010020 +#define MT_HW_CHIPID 0x70010200 +#define MT_HW_REV 0x70010204 + +#define MT_PCIE_MAC_BASE 0x74030000 +#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) +#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) + +/* PHY: band 0(0x83080000), band 1(0x83090000) */ +#define MT_WF_PHY_BASE 0x83080000 +#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) + +#define MT_WF_PHY_RX_CTRL1(_phy) MT_WF_PHY(0x2004 + ((_phy) << 16)) +#define MT_WF_PHY_RX_CTRL1_STSCNT_EN GENMASK(11, 9) + +#endif -- 2.18.0 _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek