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.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,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 A0831C43381 for ; Thu, 14 Feb 2019 19:46:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5827521916 for ; Thu, 14 Feb 2019 19:46:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=cadence.com header.i=@cadence.com header.b="TTBBxGe7"; dkim=pass (1024-bit key) header.d=cadence.com header.i=@cadence.com header.b="KF/PYqX4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437328AbfBNTqo (ORCPT ); Thu, 14 Feb 2019 14:46:44 -0500 Received: from mx0a-0014ca01.pphosted.com ([208.84.65.235]:57420 "EHLO mx0a-0014ca01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2436519AbfBNTqa (ORCPT ); Thu, 14 Feb 2019 14:46:30 -0500 Received: from pps.filterd (m0042385.ppops.net [127.0.0.1]) by mx0a-0014ca01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x1EJgug5020708; Thu, 14 Feb 2019 11:46:15 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cadence.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=proofpoint; bh=3gOesdJgOTx1waRetlX1lT5bnmyRu1vCBsZ2lcnjiIM=; b=TTBBxGe7kftUlXSQnWcnH58lg7QPBP9jqUB/o7dUHElcsHhfAqgxgNlBpK705IXc25kf ReG//NHnkjPyARowUSbOeSIZAv/DYL0FX3fsygXe1EqETGWuTxEnB6VFpcbXFyO5Zkuf msV2I9eiWShricWmDvFJrj7eS1mG/LOL/bpclK/Iq+GtPjl14yeC3CdRjRyuTU23FdUX Hxms4cQUJsuuAXhUbT/GPCyHxf4Z8B4ipIW9K6hRMYlTIsAo/vFiFjGuWE+oWOE4qtva O0sgZg1PEZmmaX21q0oIV2dojMVm6c0yJHz+OcfLAe9ZsHjXEJZWm59gxQ9PLHmEGkV+ VQ== Authentication-Results: cadence.com; spf=pass smtp.mailfrom=pawell@cadence.com Received: from nam01-by2-obe.outbound.protection.outlook.com (mail-by2nam01lp2057.outbound.protection.outlook.com [104.47.34.57]) by mx0a-0014ca01.pphosted.com with ESMTP id 2qmt3v4vpv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 14 Feb 2019 11:46:14 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cadence.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3gOesdJgOTx1waRetlX1lT5bnmyRu1vCBsZ2lcnjiIM=; b=KF/PYqX4SBYJBU4TOcWAOwh6995KKHx7JKt0n/z6yLUsxWcBbeAr/O6BMDoGjlrRqypwEDE+e06J+wYV1leFGE2jprHlptesMGyBVJwlDYJbxTd8yPHCT4e6u3fhxP5Ch/s9oPmwg2Gz2Vvfsgj/+EAcA0dBUh88jdpze/gTVkI= Received: from BYAPR07CA0051.namprd07.prod.outlook.com (2603:10b6:a03:60::28) by CY1PR07MB2248.namprd07.prod.outlook.com (2a01:111:e400:5a10::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1622.16; Thu, 14 Feb 2019 19:46:09 +0000 Received: from CO1NAM05FT020.eop-nam05.prod.protection.outlook.com (2a01:111:f400:7e50::208) by BYAPR07CA0051.outlook.office365.com (2603:10b6:a03:60::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1622.16 via Frontend Transport; Thu, 14 Feb 2019 19:46:09 +0000 Received-SPF: SoftFail (protection.outlook.com: domain of transitioning cadence.com discourages use of 158.140.1.28 as permitted sender) Received: from sjmaillnx1.cadence.com (158.140.1.28) by CO1NAM05FT020.mail.protection.outlook.com (10.152.96.128) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1580.2 via Frontend Transport; Thu, 14 Feb 2019 19:46:08 +0000 Received: from maileu3.global.cadence.com (maileu3.cadence.com [10.160.88.99]) by sjmaillnx1.cadence.com (8.14.4/8.14.4) with ESMTP id x1EJk2cW012765 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=OK); Thu, 14 Feb 2019 11:46:07 -0800 X-CrossPremisesHeadersFilteredBySendConnector: maileu3.global.cadence.com Received: from maileu3.global.cadence.com (10.160.88.99) by maileu3.global.cadence.com (10.160.88.99) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Thu, 14 Feb 2019 20:46:02 +0100 Received: from lvlogina.cadence.com (10.165.176.102) by maileu3.global.cadence.com (10.160.88.99) with Microsoft SMTP Server (TLS) id 15.0.1367.3 via Frontend Transport; Thu, 14 Feb 2019 20:46:02 +0100 Received: from lvlogina.cadence.com (localhost.localdomain [127.0.0.1]) by lvlogina.cadence.com (8.14.4/8.14.4) with ESMTP id x1EJk38M031479; Thu, 14 Feb 2019 19:46:03 GMT Received: (from pawell@localhost) by lvlogina.cadence.com (8.14.4/8.14.4/Submit) id x1EJk3ta031477; Thu, 14 Feb 2019 19:46:03 GMT From: Pawel Laszczak To: CC: , , , , , , , , , , , , , , , , Pawel Laszczak Subject: [PATCH v4 6/6] usb:cdns3 Fix for stuck packets in on-chip OUT buffer. Date: Thu, 14 Feb 2019 19:45:14 +0000 Message-ID: <1550173514-23573-7-git-send-email-pawell@cadence.com> X-Mailer: git-send-email 1.7.11.2 In-Reply-To: <1550173514-23573-1-git-send-email-pawell@cadence.com> References: <1550173514-23573-1-git-send-email-pawell@cadence.com> MIME-Version: 1.0 Content-Type: text/plain X-OrganizationHeadersPreserved: maileu3.global.cadence.com X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:158.140.1.28;IPV:CAL;SCL:-1;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(376002)(39860400002)(346002)(396003)(136003)(2980300002)(189003)(199004)(36092001)(87636003)(26005)(16586007)(6916009)(186003)(2351001)(14444005)(316002)(107886003)(486006)(106466001)(336012)(42186006)(476003)(2616005)(36756003)(11346002)(105596002)(4326008)(126002)(4720700003)(446003)(426003)(478600001)(7636002)(51416003)(26826003)(47776003)(305945005)(76176011)(30864003)(48376002)(7416002)(246002)(50466002)(2906002)(6666004)(356004)(54906003)(8936002)(50226002)(86362001)(8676002);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR07MB2248;H:sjmaillnx1.cadence.com;FPR:;SPF:SoftFail;LANG:en;PTR:corp.cadence.com;MX:1;A:1; X-Microsoft-Exchange-Diagnostics: 1;CO1NAM05FT020;1:51wsYKFgXH9AX++Jyt15tY09hFZVqBmsxeQXu8byDShOyaGtebV5UF5sIWpqE5mN/6zg1tFstrhdu6Y4rCp3P5eZEVckx+m6POqAr8NRP46o9V+O1s52btSWq6oiPU2FrknrT28dmoSZwa9OiMnJO3OgZLFL07J5I88pbFKyoA8= X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 4cdbe357-b669-4fef-cbe7-08d692b510f7 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600110)(711020)(4605077)(2017052603328)(7153060);SRVR:CY1PR07MB2248; X-MS-TrafficTypeDiagnostic: CY1PR07MB2248: X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2248;20:Q+n6cqEajQFWKS6MZA7sCgQE8DC9YKgiKscU6aX/Wkg7hYPDUa7ieuxEaOeyaEAd5L9UNvX6iH+gJe+MhLyYgHluyPby5TsjRyfWP1+oH8VPva3bcIlYPBag9/eAiyuyPh2G2n0o0tOJxEDZkINK7pqs2Lj85mxHbASHumTkY82JV60CM+MVMrot5yKfhk0QxyTdfLyivJNXKYDwE2/NZrGPzfBEqkJcsy3XtPQqFjy8LZUrtDRTfZqoZbp8snvw3wvZRtBT5PLv+mwWnXmQBUFXY1JZuoqzgh6OVT8tF0UfgMzbMEosDFn0pqyS7ox62UYwk0f+aVKVT4j2JzAGTbL3FNdqV4XDEDeRSbdeZyd1T/1rfbLx4amYpR3y1mJAlCotwM2ni8zUt7jLgawe/ug2z/q5+NHtg7O0jPZ1P7vNvKJ4/is9m7nhgun/47PGJ8xdB6pn5wGG7FepE/YgeODMcNcmr49mUSNnVnytXjoYAJTBcbEs/TcHn4GUbdti X-Microsoft-Antispam-PRVS: X-Forefront-PRVS: 09480768F8 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY1PR07MB2248;23:dQFh/Wd0utzTqxYzQfxJtRCJG4NTfDTTpQLfDh/PF?= =?us-ascii?Q?j+sYIiZUXwIibnxhS5hMUrgeg5wjUvjj1NK5vnoTXmVu5NSbA0/TzELNAuzQ?= =?us-ascii?Q?auxwwiSnzSkDIM2OPROOeVI79Hi3LQ4cPqPvhhQTsGMgQRWGdgDkuI23aLeP?= =?us-ascii?Q?2ywWtrm8OueW6dwIuSPtRhEQvlCtx7m5c0gSMkG7YAS51B/tVvFnSzWlISBa?= =?us-ascii?Q?ZLpFyvPUFJYH6yWxByAP02RxehIn0iH+9Cqdjjb2+kIBkvWSsq+kuMXVqWZS?= =?us-ascii?Q?kcLqgDDNm27JQsTdNAmhjSfJstgx73lMoahuykbioVF4ypYr4XuKm4jhNHr5?= =?us-ascii?Q?KEx+eYHtoLKWC9fS6DGE2kSqcpr702HzcNP3yb0GGrc5h9+4GxalQORjWnrm?= =?us-ascii?Q?WLkeORBmbpbS/VIRNvYM0tQs8kiNswcDdGs++UgCS/3ma9RFiy+gQ8fgdTtY?= =?us-ascii?Q?1tRZ44v3TSgTURmdk6p0lY0pQuDIaO+WA59Izn1MsG1OYKuvD2+1L3t/nIDr?= =?us-ascii?Q?au0opywa1OrvA477YbdwjP55ujckbO4HG4eBqzSOadyPmIU2yeEtSlhbl6LO?= =?us-ascii?Q?zLMudvrWZQX1WYV+vVF1rpdqv01QSppeilTBQkJARVvLMI5HkGh0DHl/R3w1?= =?us-ascii?Q?zVVKL14eKAWHEg+sVBirtWruY1CkpCawtXHuI1NAvSWYqU3Zvmd92X9Rf5HR?= =?us-ascii?Q?uJMNlomqvk9mPoplXed2pSHKSUzcyEukmKAeIZv4D2Yc3tCrtebWxuW6+lw/?= =?us-ascii?Q?7q7A/7UEGh8zV4ggiPKBtzOsXuPCys2IauMdsIGFvKTLfNAPnAufGZKsUMb5?= =?us-ascii?Q?Rdbjq7agOVnJjiLa1OVm2nny1ZXPss5nrmbdPoCl7vup+YbqSuVpDoPUX91i?= =?us-ascii?Q?Uyr0lSfVFv6WFULcgbk5mv4KCWc6e57VrNUdpLsFIGBSCWa3L7FmJ8NwI5am?= =?us-ascii?Q?MbdHnnOFm0Zv8vYt7r/ejLxQnclyv2qNpTDhIUSMXUrsN9qR15bOdRwMfLuB?= =?us-ascii?Q?NiIx30lEqIpFyqtA1ilfUn6nxvHL+9DeakBhSdJLUGVfu88WTAOUl4pekUE8?= =?us-ascii?Q?LJy4VqxqslLlSEEnLnYpd/cGuWL2onJo4Ir+6nVtk4CqpCmqPfae2IFXak50?= =?us-ascii?Q?UEKJf6mH9al8A+5IlddvhLwXxOm5H69?= X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: kt1hxvMKRCp5PX3ey2sDh40vSdBRq/7F0ciI7OC8NN8OvuhzWxYltkVLF+FEBGzAr6zmkDX4tXW17FKG8IfFxwUECSc5JWT9mYJfjTpXjFfd6rTfdRH1Wwi3WzE8eVl1x59EGHoFZe1ucJ8FSDpzKWjZAHCx6jU6uyFSgJUyzuA6zuFwVDPsh6n7oKh5zWIJpv8JKe9LY8oGcUGaNSh86Q9E6w9EvKR5uIfovLn1M2711bdecGpi2JLjrNYT/OzafX8/Oxo+KUObOIMNCHVMhkiFcQYGuyXFhgjGA0WvjXhMsIrMgXQtdI1row57Sic7SJ1SGT7+VGB2vF1NqYyRD2tGHfVPw/oUHOBQ0J+V9X9piCU36rD8XeqkKkRfiScGQY2Feqz8ShKfnYvmvqB/3FM+fm9DGROuOjtabph3EbY= X-Microsoft-Exchange-Diagnostics: 1;CY1PR07MB2248;20:nKgFdWWb5BvATAORzgz3eq4H/JyuRlVWm8pMpx7XBFlCnB1+PuOYcBe64DJSjB8Uk0zEFjM64BvfAj4/6nOax5RNL6EpKfYhxdzYcB0RQZEW8j+TEqy9LTUrRZ9tu3lYnH0YJBWnSZfI/KI/cIhh2OoWCh6ON3XSJCyD5UxBdBuRiXeaMuNmfHNFcYRetn2C2lbOnX1RO0O7PP6xqBHDBTEX/a5IEtIDHJ1xw+hOK7f+b6fTp66W5MIKJjdR9vHL X-OriginatorOrg: cadence.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Feb 2019 19:46:08.6100 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4cdbe357-b669-4fef-cbe7-08d692b510f7 X-MS-Exchange-CrossTenant-Id: d36035c5-6ce6-4662-a3dc-e762e61ae4c9 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=d36035c5-6ce6-4662-a3dc-e762e61ae4c9;Ip=[158.140.1.28];Helo=[sjmaillnx1.cadence.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR07MB2248 X-Proofpoint-SPF-Result: pass X-Proofpoint-SPF-Record: v=spf1 include:_spf.salesforce.com include:mktomail.com include:spf-0014ca01.pphosted.com include:spf.protection.outlook.com include:auth.msgapp.com include:spf.mandrillapp.com ~all X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-02-14_10:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_check_notspam policy=outbound_check score=0 suspectscore=3 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1902140131 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Controller for OUT endpoints has shared on-chip buffers for all incoming packets, including ep0out. It's FIFO buffer, so packets must be handle by DMA in correct order. If the first packet in the buffer will not be handled, then the following packets directed for other endpoints and functions will be blocked. Additionally the packets directed to one endpoint can block entire on-chip buffers. In this case transfer to other endpoints also will blocked. To resolve this issue after raising the descriptor missing interrupt driver prepares internal usb_request object and use it to arm DMA transfer. The problematic situation was observed in case when endpoint has been enabled but no usb_request were queued. Driver try detects such endpoints and will use this workaround only for these endpoint. Driver use limited number of buffer. This number can be set by macro CDNS_WA2_NUM_BUFFERS. Such blocking situation was observed on ACM gadget. For this function host send OUT data packet but ACM function is not prepared for this packet. It's cause that buffer placed in on chip memory block transfer to other endpoints. It's limitation of controller but maybe this issues should be fixed in function driver. This work around can be disabled/enabled by means of quirk_internal_buffer module parameter. By default feature is enabled. It can has impact to transfer performance and in most case this feature can be disabled. Signed-off-by: Pawel Laszczak --- drivers/usb/cdns3/gadget.c | 273 ++++++++++++++++++++++++++++++++++++- drivers/usb/cdns3/gadget.h | 7 + 2 files changed, 278 insertions(+), 2 deletions(-) diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 7f7f24ee3c4b..5dfbe6e1421c 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -27,6 +27,37 @@ * If (((Dequeue Ptr (i.e. EP_TRADDR) == Enqueue Ptr-1) or * (Dequeue Ptr (i.e. EP_TRADDR) == Enqueue Ptr)) * and (DRBL==1 and (not EP0))) + * + * Work around 2: + * Controller for OUT endpoints has shared on-chip buffers for all incoming + * packets, including ep0out. It's FIFO buffer, so packets must be handle by DMA + * in correct order. If the first packet in the buffer will not be handled, + * then the following packets directed for other endpoints and functions + * will be blocked. + * Additionally the packets directed to one endpoint can block entire on-chip + * buffers. In this case transfer to other endpoints also will blocked. + * + * To resolve this issue after raising the descriptor missing interrupt + * driver prepares internal usb_request object and use it to arm DMA transfer. + * + * The problematic situation was observed in case when endpoint has been enabled + * but no usb_request were queued. Driver try detects such endpoints and will + * use this workaround only for these endpoint. + * + * Driver use limited number of buffer. This number can be set by macro + * CDNS_WA2_NUM_BUFFERS. + * + * Such blocking situation was observed on ACM gadget. For this function + * host send OUT data packet but ACM function is not prepared for this packet. + * It's cause that buffer placed in on chip memory block transfer to other + * endpoints. + * + * It's limitation of controller but maybe this issues should be fixed in + * function driver. + * + * This work around can be disabled/enabled by means of quirk_internal_buffer + * module parameter. By default feature is enabled. It can has impact to + * transfer performance and in most case this feature can be disabled. */ #include @@ -42,6 +73,14 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags); +/* + * Parameter allows to disable/enable handling of work around 2 feature. + * By default this value is enabled. + */ +static bool quirk_internal_buffer = 1; +module_param(quirk_internal_buffer, bool, 0644); +MODULE_PARM_DESC(quirk_internal_buffer, "Disable/enable WA2 algorithm"); + /** * cdns3_handshake - spin reading until handshake completes or fails * @ptr: address of device controller register to be read @@ -105,6 +144,17 @@ struct usb_request *cdns3_next_request(struct list_head *list) return list_first_entry_or_null(list, struct usb_request, list); } +/** + * cdns3_next_priv_request - returns next request from list + * @list: list containing requests + * + * Returns request or NULL if no requests in list + */ +struct cdns3_request *cdns3_next_priv_request(struct list_head *list) +{ + return list_first_entry_or_null(list, struct cdns3_request, list); +} + /** * select_ep - selects endpoint * @priv_dev: extended gadget object @@ -384,6 +434,53 @@ static int cdns3_start_all_request(struct cdns3_device *priv_dev, return ret; } +/** + * cdns3_descmiss_copy_data copy data from internal requests to request queued + * by class driver. + * @priv_ep: extended endpoint object + * @request: request object + */ +static void cdns3_descmiss_copy_data(struct cdns3_endpoint *priv_ep, + struct usb_request *request) +{ + struct usb_request *descmiss_req; + struct cdns3_request *descmiss_priv_req; + + while (!list_empty(&priv_ep->descmiss_req_list)) { + int chunk_end; + int length; + + descmiss_priv_req = + cdns3_next_priv_request(&priv_ep->descmiss_req_list); + descmiss_req = &descmiss_priv_req->request; + + /* driver can't touch pending request */ + if (descmiss_priv_req->flags & REQUEST_PENDING) + break; + + chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; + length = request->actual + descmiss_req->actual; + + if (length <= request->length) { + memcpy(&((u8 *)request->buf)[request->actual], + descmiss_req->buf, + descmiss_req->actual); + request->actual = length; + } else { + /* It should never occures */ + request->status = -ENOMEM; + } + + list_del_init(&descmiss_priv_req->list); + + kfree(descmiss_req->buf); + cdns3_gadget_ep_free_request(&priv_ep->endpoint, descmiss_req); + + if (!chunk_end) + break; + } +} + /** * cdns3_gadget_giveback - call struct usb_request's ->complete callback * @priv_ep: The endpoint to whom the request belongs to @@ -412,6 +509,32 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, priv_req->flags &= ~REQUEST_PENDING; trace_cdns3_gadget_giveback(priv_req); + /* WA2: */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN && + priv_req->flags & REQUEST_INTERNAL) { + struct usb_request *req; + + req = cdns3_next_request(&priv_ep->deferred_req_list); + request = req; + priv_ep->descmis_req = NULL; + + if (!req) + return; + + cdns3_descmiss_copy_data(priv_ep, req); + if (!(priv_ep->flags & EP_QUIRK_END_TRANSFER) && + req->length != req->actual) { + /* wait for next part of transfer */ + return; + } + + if (req->status == -EINPROGRESS) + req->status = 0; + + list_del_init(&req->list); + cdns3_start_all_request(priv_dev, priv_ep); + } + /* Start all not pending request */ if (priv_ep->flags & EP_RING_FULL) cdns3_start_all_request(priv_dev, priv_ep); @@ -774,6 +897,59 @@ void cdns3_rearm_transfer(struct cdns3_endpoint *priv_ep, u8 rearm) } } +/** + * cdns3_descmissing_packet - handles descriptor missing event. + * @priv_dev: extended gadget object + * + * This function is used only for WA2. For more information see Work around 2 + * description. + */ +static int cdns3_descmissing_packet(struct cdns3_endpoint *priv_ep) +{ + struct cdns3_request *priv_req; + struct usb_request *request; + + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { + priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; + priv_ep->flags |= EP_QUIRK_EXTRA_BUF_EN; + } + + cdns3_dbg(priv_ep->cdns3_dev, "WA2: Description Missing detected\n"); + + request = cdns3_gadget_ep_alloc_request(&priv_ep->endpoint, + GFP_ATOMIC); + if (!request) + return -ENOMEM; + + priv_req = to_cdns3_request(request); + priv_req->flags |= REQUEST_INTERNAL; + + /* if this field is still assigned it indicate that transfer related + * with this request has not been finished yet. Driver in this + * case simply allocate next request and assign flag REQUEST_INTERNAL_CH + * flag to previous one. It will indicate that current request is + * part of the previous one. + */ + if (priv_ep->descmis_req) + priv_ep->descmis_req->flags |= REQUEST_INTERNAL_CH; + + priv_req->request.buf = kzalloc(CDNS3_DESCMIS_BUF_SIZE, + GFP_ATOMIC); + if (!priv_req) { + cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); + return -ENOMEM; + } + + priv_req->request.length = CDNS3_DESCMIS_BUF_SIZE; + priv_ep->descmis_req = priv_req; + + __cdns3_gadget_ep_queue(&priv_ep->endpoint, + &priv_ep->descmis_req->request, + GFP_ATOMIC); + + return 0; +} + /** * cdns3_check_ep_interrupt_proceed - Processes interrupt related to endpoint * @priv_ep: endpoint object @@ -807,8 +983,31 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) cdns3_rearm_transfer(priv_ep, priv_ep->wa1_set); } - if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) + if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { + if (ep_sts_reg & EP_STS_ISP) + priv_ep->flags |= EP_QUIRK_END_TRANSFER; + else + priv_ep->flags &= ~EP_QUIRK_END_TRANSFER; + } + cdns3_transfer_completed(priv_dev, priv_ep); + } + + /* + * WA2: this condition should only be meet when + * priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET or + * priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN. + * In other cases this interrupt will be disabled/ + */ + if (ep_sts_reg & EP_STS_DESCMIS) { + int err; + + err = cdns3_descmissing_packet(priv_ep); + if (err) + dev_err(priv_dev->dev, + "Failed: No sufficient memory for DESCMIS\n"); + } return 0; } @@ -1241,13 +1440,26 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, /* enable interrupt for selected endpoint */ cdns3_set_register_bit(&priv_dev->regs->ep_ien, BIT(cdns3_ep_addr_to_index(bEndpointAddress))); + /* + * WA2: Set flag for all not ISOC OUT endpoints. If this flag is set + * driver try to detect whether endpoint need additional internal + * buffer for unblocking on-chip FIFO buffer. This flag will be cleared + * if before first DESCMISS interrupt the DMA will be armed. + */ + if (quirk_internal_buffer) { + if (!priv_ep->dir && priv_ep->type != USB_ENDPOINT_XFER_ISOC) { + priv_ep->flags |= EP_QUIRK_EXTRA_BUF_DET; + reg |= EP_STS_EN_DESCMISEN; + } + } writel(reg, &priv_dev->regs->ep_sts_en); cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE); ep->desc = desc; - priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALL); + priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALL | + EP_QUIRK_EXTRA_BUF_EN); priv_ep->flags |= EP_ENABLED | EP_UPDATE_EP_TRBADDR; priv_ep->wa1_set = 0; priv_ep->enqueue = 0; @@ -1272,6 +1484,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, static int cdns3_gadget_ep_disable(struct usb_ep *ep) { struct cdns3_endpoint *priv_ep; + struct cdns3_request *priv_req; struct cdns3_device *priv_dev; struct usb_request *request; unsigned long flags; @@ -1308,6 +1521,14 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) -ESHUTDOWN); } + while (!list_empty(&priv_ep->descmiss_req_list)) { + priv_req = cdns3_next_priv_request(&priv_ep->descmiss_req_list); + + kfree(priv_req->request.buf); + cdns3_gadget_ep_free_request(&priv_ep->endpoint, + &priv_req->request); + } + while (!list_empty(&priv_ep->deferred_req_list)) { request = cdns3_next_request(&priv_ep->deferred_req_list); @@ -1348,6 +1569,53 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep, priv_req = to_cdns3_request(request); trace_cdns3_ep_queue(priv_req); + /* + * WA2: if transfer was queued before DESCMISS appear than we + * can disable handling of DESCMISS interrupt. Driver assumes that it + * can disable special treatment for this endpoint. + */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { + u32 reg; + + cdns3_select_ep(priv_dev, priv_ep->num | priv_ep->dir); + priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; + reg = readl(&priv_dev->regs->ep_sts_en); + reg &= ~EP_STS_EN_DESCMISEN; + writel(reg, &priv_dev->regs->ep_sts_en); + } + + /* WA2 */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { + u8 pending_empty = list_empty(&priv_ep->pending_req_list); + u8 descmiss_empty = list_empty(&priv_ep->descmiss_req_list); + + /* + * DESCMISS transfer has been finished, so data will be + * directly copied from internal allocated usb_request + * objects. + */ + if (pending_empty && !descmiss_empty && + !(priv_req->flags & REQUEST_INTERNAL)) { + cdns3_descmiss_copy_data(priv_ep, request); + list_add_tail(&request->list, + &priv_ep->pending_req_list); + cdns3_gadget_giveback(priv_ep, priv_req, + request->status); + return ret; + } + + /* + * WA2 driver will wait for completion DESCMISS transfer, + * before starts new, not DESCMISS transfer. + */ + if (!pending_empty && !descmiss_empty) + deferred = 1; + + if (priv_req->flags & REQUEST_INTERNAL) + list_add_tail(&priv_req->list, + &priv_ep->descmiss_req_list); + } + ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, usb_endpoint_dir_in(ep->desc)); if (ret) @@ -1782,6 +2050,7 @@ static int cdns3_init_eps(struct cdns3_device *priv_dev) INIT_LIST_HEAD(&priv_ep->pending_req_list); INIT_LIST_HEAD(&priv_ep->deferred_req_list); + INIT_LIST_HEAD(&priv_ep->descmiss_req_list); } return 0; diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h index 817f8ae7a4da..8de733b315e9 100644 --- a/drivers/usb/cdns3/gadget.h +++ b/drivers/usb/cdns3/gadget.h @@ -1000,6 +1000,7 @@ struct cdns3_device; * @endpoint: usb endpoint * @pending_req_list: list of requests queuing on transfer ring. * @deferred_req_list: list of requests waiting for queuing on transfer ring. + * @descmiss_req_list: list of requests internally allocated by driver (WA2). * @trb_pool: transfer ring - array of transaction buffers * @trb_pool_dma: dma address of transfer ring * @cdns3_dev: device associated with this endpoint @@ -1026,6 +1027,7 @@ struct cdns3_endpoint { struct usb_ep endpoint; struct list_head pending_req_list; struct list_head deferred_req_list; + struct list_head descmiss_req_list; struct cdns3_trb *trb_pool; dma_addr_t trb_pool_dma; @@ -1041,6 +1043,9 @@ struct cdns3_endpoint { #define EP_PENDING_REQUEST BIT(5) #define EP_RING_FULL BIT(6) #define EP_CLAIMED BIT(7) +#define EP_QUIRK_EXTRA_BUF_DET BIT(8) +#define EP_QUIRK_EXTRA_BUF_EN BIT(9) +#define EP_QUIRK_END_TRANSFER BIT(10) u32 flags; @@ -1074,6 +1079,7 @@ struct cdns3_endpoint { * @start_trb: number of the first TRB in transfer ring * @end_trb: number of the last TRB in transfer ring * @flags: flag specifying special usage of request + * @list: used by internally allocated request to add to descmiss_req_list. */ struct cdns3_request { struct usb_request request; @@ -1086,6 +1092,7 @@ struct cdns3_request { #define REQUEST_INTERNAL_CH BIT(2) #define REQUEST_ZLP BIT(3) u32 flags; + struct list_head list; }; #define to_cdns3_request(r) (container_of(r, struct cdns3_request, request)) -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pawel Laszczak Subject: [PATCH v4 6/6] usb:cdns3 Fix for stuck packets in on-chip OUT buffer. Date: Thu, 14 Feb 2019 19:45:14 +0000 Message-ID: <1550173514-23573-7-git-send-email-pawell@cadence.com> References: <1550173514-23573-1-git-send-email-pawell@cadence.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: <1550173514-23573-1-git-send-email-pawell@cadence.com> Sender: linux-kernel-owner@vger.kernel.org To: devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, felipe.balbi@linux.intel.com, mark.rutland@arm.com, linux-usb@vger.kernel.org, hdegoede@redhat.com, heikki.krogerus@linux.intel.com, andy.shevchenko@gmail.com, robh+dt@kernel.org, rogerq@ti.com, linux-kernel@vger.kernel.org, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, kurahul@cadence.com, Pawel Laszczak List-Id: devicetree@vger.kernel.org Controller for OUT endpoints has shared on-chip buffers for all incoming packets, including ep0out. It's FIFO buffer, so packets must be handle by DMA in correct order. If the first packet in the buffer will not be handled, then the following packets directed for other endpoints and functions will be blocked. Additionally the packets directed to one endpoint can block entire on-chip buffers. In this case transfer to other endpoints also will blocked. To resolve this issue after raising the descriptor missing interrupt driver prepares internal usb_request object and use it to arm DMA transfer. The problematic situation was observed in case when endpoint has been enabled but no usb_request were queued. Driver try detects such endpoints and will use this workaround only for these endpoint. Driver use limited number of buffer. This number can be set by macro CDNS_WA2_NUM_BUFFERS. Such blocking situation was observed on ACM gadget. For this function host send OUT data packet but ACM function is not prepared for this packet. It's cause that buffer placed in on chip memory block transfer to other endpoints. It's limitation of controller but maybe this issues should be fixed in function driver. This work around can be disabled/enabled by means of quirk_internal_buffer module parameter. By default feature is enabled. It can has impact to transfer performance and in most case this feature can be disabled. Signed-off-by: Pawel Laszczak --- drivers/usb/cdns3/gadget.c | 273 ++++++++++++++++++++++++++++++++++++- drivers/usb/cdns3/gadget.h | 7 + 2 files changed, 278 insertions(+), 2 deletions(-) diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 7f7f24ee3c4b..5dfbe6e1421c 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -27,6 +27,37 @@ * If (((Dequeue Ptr (i.e. EP_TRADDR) == Enqueue Ptr-1) or * (Dequeue Ptr (i.e. EP_TRADDR) == Enqueue Ptr)) * and (DRBL==1 and (not EP0))) + * + * Work around 2: + * Controller for OUT endpoints has shared on-chip buffers for all incoming + * packets, including ep0out. It's FIFO buffer, so packets must be handle by DMA + * in correct order. If the first packet in the buffer will not be handled, + * then the following packets directed for other endpoints and functions + * will be blocked. + * Additionally the packets directed to one endpoint can block entire on-chip + * buffers. In this case transfer to other endpoints also will blocked. + * + * To resolve this issue after raising the descriptor missing interrupt + * driver prepares internal usb_request object and use it to arm DMA transfer. + * + * The problematic situation was observed in case when endpoint has been enabled + * but no usb_request were queued. Driver try detects such endpoints and will + * use this workaround only for these endpoint. + * + * Driver use limited number of buffer. This number can be set by macro + * CDNS_WA2_NUM_BUFFERS. + * + * Such blocking situation was observed on ACM gadget. For this function + * host send OUT data packet but ACM function is not prepared for this packet. + * It's cause that buffer placed in on chip memory block transfer to other + * endpoints. + * + * It's limitation of controller but maybe this issues should be fixed in + * function driver. + * + * This work around can be disabled/enabled by means of quirk_internal_buffer + * module parameter. By default feature is enabled. It can has impact to + * transfer performance and in most case this feature can be disabled. */ #include @@ -42,6 +73,14 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags); +/* + * Parameter allows to disable/enable handling of work around 2 feature. + * By default this value is enabled. + */ +static bool quirk_internal_buffer = 1; +module_param(quirk_internal_buffer, bool, 0644); +MODULE_PARM_DESC(quirk_internal_buffer, "Disable/enable WA2 algorithm"); + /** * cdns3_handshake - spin reading until handshake completes or fails * @ptr: address of device controller register to be read @@ -105,6 +144,17 @@ struct usb_request *cdns3_next_request(struct list_head *list) return list_first_entry_or_null(list, struct usb_request, list); } +/** + * cdns3_next_priv_request - returns next request from list + * @list: list containing requests + * + * Returns request or NULL if no requests in list + */ +struct cdns3_request *cdns3_next_priv_request(struct list_head *list) +{ + return list_first_entry_or_null(list, struct cdns3_request, list); +} + /** * select_ep - selects endpoint * @priv_dev: extended gadget object @@ -384,6 +434,53 @@ static int cdns3_start_all_request(struct cdns3_device *priv_dev, return ret; } +/** + * cdns3_descmiss_copy_data copy data from internal requests to request queued + * by class driver. + * @priv_ep: extended endpoint object + * @request: request object + */ +static void cdns3_descmiss_copy_data(struct cdns3_endpoint *priv_ep, + struct usb_request *request) +{ + struct usb_request *descmiss_req; + struct cdns3_request *descmiss_priv_req; + + while (!list_empty(&priv_ep->descmiss_req_list)) { + int chunk_end; + int length; + + descmiss_priv_req = + cdns3_next_priv_request(&priv_ep->descmiss_req_list); + descmiss_req = &descmiss_priv_req->request; + + /* driver can't touch pending request */ + if (descmiss_priv_req->flags & REQUEST_PENDING) + break; + + chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; + length = request->actual + descmiss_req->actual; + + if (length <= request->length) { + memcpy(&((u8 *)request->buf)[request->actual], + descmiss_req->buf, + descmiss_req->actual); + request->actual = length; + } else { + /* It should never occures */ + request->status = -ENOMEM; + } + + list_del_init(&descmiss_priv_req->list); + + kfree(descmiss_req->buf); + cdns3_gadget_ep_free_request(&priv_ep->endpoint, descmiss_req); + + if (!chunk_end) + break; + } +} + /** * cdns3_gadget_giveback - call struct usb_request's ->complete callback * @priv_ep: The endpoint to whom the request belongs to @@ -412,6 +509,32 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, priv_req->flags &= ~REQUEST_PENDING; trace_cdns3_gadget_giveback(priv_req); + /* WA2: */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN && + priv_req->flags & REQUEST_INTERNAL) { + struct usb_request *req; + + req = cdns3_next_request(&priv_ep->deferred_req_list); + request = req; + priv_ep->descmis_req = NULL; + + if (!req) + return; + + cdns3_descmiss_copy_data(priv_ep, req); + if (!(priv_ep->flags & EP_QUIRK_END_TRANSFER) && + req->length != req->actual) { + /* wait for next part of transfer */ + return; + } + + if (req->status == -EINPROGRESS) + req->status = 0; + + list_del_init(&req->list); + cdns3_start_all_request(priv_dev, priv_ep); + } + /* Start all not pending request */ if (priv_ep->flags & EP_RING_FULL) cdns3_start_all_request(priv_dev, priv_ep); @@ -774,6 +897,59 @@ void cdns3_rearm_transfer(struct cdns3_endpoint *priv_ep, u8 rearm) } } +/** + * cdns3_descmissing_packet - handles descriptor missing event. + * @priv_dev: extended gadget object + * + * This function is used only for WA2. For more information see Work around 2 + * description. + */ +static int cdns3_descmissing_packet(struct cdns3_endpoint *priv_ep) +{ + struct cdns3_request *priv_req; + struct usb_request *request; + + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { + priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; + priv_ep->flags |= EP_QUIRK_EXTRA_BUF_EN; + } + + cdns3_dbg(priv_ep->cdns3_dev, "WA2: Description Missing detected\n"); + + request = cdns3_gadget_ep_alloc_request(&priv_ep->endpoint, + GFP_ATOMIC); + if (!request) + return -ENOMEM; + + priv_req = to_cdns3_request(request); + priv_req->flags |= REQUEST_INTERNAL; + + /* if this field is still assigned it indicate that transfer related + * with this request has not been finished yet. Driver in this + * case simply allocate next request and assign flag REQUEST_INTERNAL_CH + * flag to previous one. It will indicate that current request is + * part of the previous one. + */ + if (priv_ep->descmis_req) + priv_ep->descmis_req->flags |= REQUEST_INTERNAL_CH; + + priv_req->request.buf = kzalloc(CDNS3_DESCMIS_BUF_SIZE, + GFP_ATOMIC); + if (!priv_req) { + cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); + return -ENOMEM; + } + + priv_req->request.length = CDNS3_DESCMIS_BUF_SIZE; + priv_ep->descmis_req = priv_req; + + __cdns3_gadget_ep_queue(&priv_ep->endpoint, + &priv_ep->descmis_req->request, + GFP_ATOMIC); + + return 0; +} + /** * cdns3_check_ep_interrupt_proceed - Processes interrupt related to endpoint * @priv_ep: endpoint object @@ -807,8 +983,31 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) cdns3_rearm_transfer(priv_ep, priv_ep->wa1_set); } - if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) + if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { + if (ep_sts_reg & EP_STS_ISP) + priv_ep->flags |= EP_QUIRK_END_TRANSFER; + else + priv_ep->flags &= ~EP_QUIRK_END_TRANSFER; + } + cdns3_transfer_completed(priv_dev, priv_ep); + } + + /* + * WA2: this condition should only be meet when + * priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET or + * priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN. + * In other cases this interrupt will be disabled/ + */ + if (ep_sts_reg & EP_STS_DESCMIS) { + int err; + + err = cdns3_descmissing_packet(priv_ep); + if (err) + dev_err(priv_dev->dev, + "Failed: No sufficient memory for DESCMIS\n"); + } return 0; } @@ -1241,13 +1440,26 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, /* enable interrupt for selected endpoint */ cdns3_set_register_bit(&priv_dev->regs->ep_ien, BIT(cdns3_ep_addr_to_index(bEndpointAddress))); + /* + * WA2: Set flag for all not ISOC OUT endpoints. If this flag is set + * driver try to detect whether endpoint need additional internal + * buffer for unblocking on-chip FIFO buffer. This flag will be cleared + * if before first DESCMISS interrupt the DMA will be armed. + */ + if (quirk_internal_buffer) { + if (!priv_ep->dir && priv_ep->type != USB_ENDPOINT_XFER_ISOC) { + priv_ep->flags |= EP_QUIRK_EXTRA_BUF_DET; + reg |= EP_STS_EN_DESCMISEN; + } + } writel(reg, &priv_dev->regs->ep_sts_en); cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE); ep->desc = desc; - priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALL); + priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALL | + EP_QUIRK_EXTRA_BUF_EN); priv_ep->flags |= EP_ENABLED | EP_UPDATE_EP_TRBADDR; priv_ep->wa1_set = 0; priv_ep->enqueue = 0; @@ -1272,6 +1484,7 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep, static int cdns3_gadget_ep_disable(struct usb_ep *ep) { struct cdns3_endpoint *priv_ep; + struct cdns3_request *priv_req; struct cdns3_device *priv_dev; struct usb_request *request; unsigned long flags; @@ -1308,6 +1521,14 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) -ESHUTDOWN); } + while (!list_empty(&priv_ep->descmiss_req_list)) { + priv_req = cdns3_next_priv_request(&priv_ep->descmiss_req_list); + + kfree(priv_req->request.buf); + cdns3_gadget_ep_free_request(&priv_ep->endpoint, + &priv_req->request); + } + while (!list_empty(&priv_ep->deferred_req_list)) { request = cdns3_next_request(&priv_ep->deferred_req_list); @@ -1348,6 +1569,53 @@ static int __cdns3_gadget_ep_queue(struct usb_ep *ep, priv_req = to_cdns3_request(request); trace_cdns3_ep_queue(priv_req); + /* + * WA2: if transfer was queued before DESCMISS appear than we + * can disable handling of DESCMISS interrupt. Driver assumes that it + * can disable special treatment for this endpoint. + */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_DET) { + u32 reg; + + cdns3_select_ep(priv_dev, priv_ep->num | priv_ep->dir); + priv_ep->flags &= ~EP_QUIRK_EXTRA_BUF_DET; + reg = readl(&priv_dev->regs->ep_sts_en); + reg &= ~EP_STS_EN_DESCMISEN; + writel(reg, &priv_dev->regs->ep_sts_en); + } + + /* WA2 */ + if (priv_ep->flags & EP_QUIRK_EXTRA_BUF_EN) { + u8 pending_empty = list_empty(&priv_ep->pending_req_list); + u8 descmiss_empty = list_empty(&priv_ep->descmiss_req_list); + + /* + * DESCMISS transfer has been finished, so data will be + * directly copied from internal allocated usb_request + * objects. + */ + if (pending_empty && !descmiss_empty && + !(priv_req->flags & REQUEST_INTERNAL)) { + cdns3_descmiss_copy_data(priv_ep, request); + list_add_tail(&request->list, + &priv_ep->pending_req_list); + cdns3_gadget_giveback(priv_ep, priv_req, + request->status); + return ret; + } + + /* + * WA2 driver will wait for completion DESCMISS transfer, + * before starts new, not DESCMISS transfer. + */ + if (!pending_empty && !descmiss_empty) + deferred = 1; + + if (priv_req->flags & REQUEST_INTERNAL) + list_add_tail(&priv_req->list, + &priv_ep->descmiss_req_list); + } + ret = usb_gadget_map_request_by_dev(priv_dev->sysdev, request, usb_endpoint_dir_in(ep->desc)); if (ret) @@ -1782,6 +2050,7 @@ static int cdns3_init_eps(struct cdns3_device *priv_dev) INIT_LIST_HEAD(&priv_ep->pending_req_list); INIT_LIST_HEAD(&priv_ep->deferred_req_list); + INIT_LIST_HEAD(&priv_ep->descmiss_req_list); } return 0; diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h index 817f8ae7a4da..8de733b315e9 100644 --- a/drivers/usb/cdns3/gadget.h +++ b/drivers/usb/cdns3/gadget.h @@ -1000,6 +1000,7 @@ struct cdns3_device; * @endpoint: usb endpoint * @pending_req_list: list of requests queuing on transfer ring. * @deferred_req_list: list of requests waiting for queuing on transfer ring. + * @descmiss_req_list: list of requests internally allocated by driver (WA2). * @trb_pool: transfer ring - array of transaction buffers * @trb_pool_dma: dma address of transfer ring * @cdns3_dev: device associated with this endpoint @@ -1026,6 +1027,7 @@ struct cdns3_endpoint { struct usb_ep endpoint; struct list_head pending_req_list; struct list_head deferred_req_list; + struct list_head descmiss_req_list; struct cdns3_trb *trb_pool; dma_addr_t trb_pool_dma; @@ -1041,6 +1043,9 @@ struct cdns3_endpoint { #define EP_PENDING_REQUEST BIT(5) #define EP_RING_FULL BIT(6) #define EP_CLAIMED BIT(7) +#define EP_QUIRK_EXTRA_BUF_DET BIT(8) +#define EP_QUIRK_EXTRA_BUF_EN BIT(9) +#define EP_QUIRK_END_TRANSFER BIT(10) u32 flags; @@ -1074,6 +1079,7 @@ struct cdns3_endpoint { * @start_trb: number of the first TRB in transfer ring * @end_trb: number of the last TRB in transfer ring * @flags: flag specifying special usage of request + * @list: used by internally allocated request to add to descmiss_req_list. */ struct cdns3_request { struct usb_request request; @@ -1086,6 +1092,7 @@ struct cdns3_request { #define REQUEST_INTERNAL_CH BIT(2) #define REQUEST_ZLP BIT(3) u32 flags; + struct list_head list; }; #define to_cdns3_request(r) (container_of(r, struct cdns3_request, request)) -- 2.17.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v4,6/6] usb:cdns3 Fix for stuck packets in on-chip OUT buffer. From: Pawel Laszczak Message-Id: <1550173514-23573-7-git-send-email-pawell@cadence.com> Date: Thu, 14 Feb 2019 19:45:14 +0000 To: devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, felipe.balbi@linux.intel.com, mark.rutland@arm.com, linux-usb@vger.kernel.org, hdegoede@redhat.com, heikki.krogerus@linux.intel.com, andy.shevchenko@gmail.com, robh+dt@kernel.org, rogerq@ti.com, linux-kernel@vger.kernel.org, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, kurahul@cadence.com, Pawel Laszczak List-ID: Q29udHJvbGxlciBmb3IgT1VUIGVuZHBvaW50cyBoYXMgc2hhcmVkIG9uLWNoaXAgYnVmZmVycyBm b3IgYWxsIGluY29taW5nCnBhY2tldHMsIGluY2x1ZGluZyBlcDBvdXQuIEl0J3MgRklGTyBidWZm ZXIsIHNvIHBhY2tldHMgbXVzdCBiZSBoYW5kbGUKYnkgRE1BIGluIGNvcnJlY3Qgb3JkZXIuIElm IHRoZSBmaXJzdCBwYWNrZXQgaW4gdGhlIGJ1ZmZlciB3aWxsIG5vdCBiZQpoYW5kbGVkLCB0aGVu IHRoZSBmb2xsb3dpbmcgcGFja2V0cyBkaXJlY3RlZCBmb3Igb3RoZXIgZW5kcG9pbnRzIGFuZApm dW5jdGlvbnMgd2lsbCBiZSBibG9ja2VkLgoKQWRkaXRpb25hbGx5IHRoZSBwYWNrZXRzIGRpcmVj dGVkIHRvIG9uZSBlbmRwb2ludCBjYW4gYmxvY2sgZW50aXJlIG9uLWNoaXAKYnVmZmVycy4gSW4g dGhpcyBjYXNlIHRyYW5zZmVyIHRvIG90aGVyIGVuZHBvaW50cyBhbHNvIHdpbGwgYmxvY2tlZC4K ClRvIHJlc29sdmUgdGhpcyBpc3N1ZSBhZnRlciByYWlzaW5nIHRoZSBkZXNjcmlwdG9yIG1pc3Np bmcgaW50ZXJydXB0CmRyaXZlciBwcmVwYXJlcyBpbnRlcm5hbCB1c2JfcmVxdWVzdCBvYmplY3Qg YW5kIHVzZSBpdCB0byBhcm0gRE1BCnRyYW5zZmVyLgoKVGhlIHByb2JsZW1hdGljIHNpdHVhdGlv biB3YXMgb2JzZXJ2ZWQgaW4gY2FzZSB3aGVuIGVuZHBvaW50IGhhcwpiZWVuIGVuYWJsZWQgYnV0 IG5vIHVzYl9yZXF1ZXN0IHdlcmUgcXVldWVkLiBEcml2ZXIgdHJ5IGRldGVjdHMKc3VjaCBlbmRw b2ludHMgYW5kIHdpbGwgdXNlIHRoaXMgd29ya2Fyb3VuZCBvbmx5IGZvciB0aGVzZSBlbmRwb2lu dC4KCkRyaXZlciB1c2UgbGltaXRlZCBudW1iZXIgb2YgYnVmZmVyLiBUaGlzIG51bWJlciBjYW4g YmUgc2V0IGJ5IG1hY3JvCkNETlNfV0EyX05VTV9CVUZGRVJTLgoKU3VjaCBibG9ja2luZyBzaXR1 YXRpb24gd2FzIG9ic2VydmVkIG9uIEFDTSBnYWRnZXQuIEZvciB0aGlzIGZ1bmN0aW9uCmhvc3Qg c2VuZCBPVVQgZGF0YSBwYWNrZXQgYnV0IEFDTSBmdW5jdGlvbiBpcyBub3QgcHJlcGFyZWQgZm9y CnRoaXMgcGFja2V0LiBJdCdzIGNhdXNlIHRoYXQgYnVmZmVyIHBsYWNlZCBpbiBvbiBjaGlwIG1l bW9yeSBibG9jawp0cmFuc2ZlciB0byBvdGhlciBlbmRwb2ludHMuCgpJdCdzIGxpbWl0YXRpb24g b2YgY29udHJvbGxlciBidXQgbWF5YmUgdGhpcyBpc3N1ZXMgc2hvdWxkIGJlIGZpeGVkIGluCmZ1 bmN0aW9uIGRyaXZlci4KClRoaXMgd29yayBhcm91bmQgY2FuIGJlIGRpc2FibGVkL2VuYWJsZWQg YnkgbWVhbnMgb2YgcXVpcmtfaW50ZXJuYWxfYnVmZmVyCm1vZHVsZSBwYXJhbWV0ZXIuIEJ5IGRl ZmF1bHQgZmVhdHVyZSBpcyBlbmFibGVkLiBJdCBjYW4gaGFzIGltcGFjdCB0bwp0cmFuc2ZlciBw ZXJmb3JtYW5jZSBhbmQgaW4gbW9zdCBjYXNlIHRoaXMgZmVhdHVyZSBjYW4gYmUgZGlzYWJsZWQu CgpTaWduZWQtb2ZmLWJ5OiBQYXdlbCBMYXN6Y3phayA8cGF3ZWxsQGNhZGVuY2UuY29tPgotLS0K IGRyaXZlcnMvdXNiL2NkbnMzL2dhZGdldC5jIHwgMjczICsrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKy0KIGRyaXZlcnMvdXNiL2NkbnMzL2dhZGdldC5oIHwgICA3ICsKIDIgZmls ZXMgY2hhbmdlZCwgMjc4IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0 IGEvZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMgYi9kcml2ZXJzL3VzYi9jZG5zMy9nYWRnZXQu YwppbmRleCA3ZjdmMjRlZTNjNGIuLjVkZmJlNmUxNDIxYyAxMDA2NDQKLS0tIGEvZHJpdmVycy91 c2IvY2RuczMvZ2FkZ2V0LmMKKysrIGIvZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMKQEAgLTI3 LDYgKzI3LDM3IEBACiAgKiBJZiAoKChEZXF1ZXVlIFB0ciAoaS5lLiBFUF9UUkFERFIpID09IEVu cXVldWUgUHRyLTEpIG9yCiAgKgkoRGVxdWV1ZSBQdHIgKGkuZS4gRVBfVFJBRERSKSA9PSBFbnF1 ZXVlIFB0cikpCiAgKgkJYW5kIChEUkJMPT0xIGFuZCAobm90IEVQMCkpKQorICoKKyAqIFdvcmsg YXJvdW5kIDI6CisgKiBDb250cm9sbGVyIGZvciBPVVQgZW5kcG9pbnRzIGhhcyBzaGFyZWQgb24t Y2hpcCBidWZmZXJzIGZvciBhbGwgaW5jb21pbmcKKyAqIHBhY2tldHMsIGluY2x1ZGluZyBlcDBv dXQuIEl0J3MgRklGTyBidWZmZXIsIHNvIHBhY2tldHMgbXVzdCBiZSBoYW5kbGUgYnkgRE1BCisg KiBpbiBjb3JyZWN0IG9yZGVyLiBJZiB0aGUgZmlyc3QgcGFja2V0IGluIHRoZSBidWZmZXIgd2ls bCBub3QgYmUgaGFuZGxlZCwKKyAqIHRoZW4gdGhlIGZvbGxvd2luZyBwYWNrZXRzIGRpcmVjdGVk IGZvciBvdGhlciBlbmRwb2ludHMgYW5kICBmdW5jdGlvbnMKKyAqIHdpbGwgYmUgYmxvY2tlZC4K KyAqIEFkZGl0aW9uYWxseSB0aGUgcGFja2V0cyBkaXJlY3RlZCB0byBvbmUgZW5kcG9pbnQgY2Fu IGJsb2NrIGVudGlyZSBvbi1jaGlwCisgKiBidWZmZXJzLiBJbiB0aGlzIGNhc2UgdHJhbnNmZXIg dG8gb3RoZXIgZW5kcG9pbnRzIGFsc28gd2lsbCBibG9ja2VkLgorICoKKyAqIFRvIHJlc29sdmUg dGhpcyBpc3N1ZSBhZnRlciByYWlzaW5nIHRoZSBkZXNjcmlwdG9yIG1pc3NpbmcgaW50ZXJydXB0 CisgKiBkcml2ZXIgcHJlcGFyZXMgaW50ZXJuYWwgdXNiX3JlcXVlc3Qgb2JqZWN0IGFuZCB1c2Ug aXQgdG8gYXJtIERNQSB0cmFuc2Zlci4KKyAqCisgKiBUaGUgcHJvYmxlbWF0aWMgc2l0dWF0aW9u IHdhcyBvYnNlcnZlZCBpbiBjYXNlIHdoZW4gZW5kcG9pbnQgaGFzIGJlZW4gZW5hYmxlZAorICog YnV0IG5vIHVzYl9yZXF1ZXN0IHdlcmUgcXVldWVkLiBEcml2ZXIgdHJ5IGRldGVjdHMgc3VjaCBl bmRwb2ludHMgYW5kIHdpbGwKKyAqIHVzZSB0aGlzIHdvcmthcm91bmQgb25seSBmb3IgdGhlc2Ug ZW5kcG9pbnQuCisgKgorICogRHJpdmVyIHVzZSBsaW1pdGVkIG51bWJlciBvZiBidWZmZXIuIFRo aXMgbnVtYmVyIGNhbiBiZSBzZXQgYnkgbWFjcm8KKyAqIENETlNfV0EyX05VTV9CVUZGRVJTLgor ICoKKyAqIFN1Y2ggYmxvY2tpbmcgc2l0dWF0aW9uIHdhcyBvYnNlcnZlZCBvbiBBQ00gZ2FkZ2V0 LiBGb3IgdGhpcyBmdW5jdGlvbgorICogaG9zdCBzZW5kIE9VVCBkYXRhIHBhY2tldCBidXQgQUNN IGZ1bmN0aW9uIGlzIG5vdCBwcmVwYXJlZCBmb3IgdGhpcyBwYWNrZXQuCisgKiBJdCdzIGNhdXNl IHRoYXQgYnVmZmVyIHBsYWNlZCBpbiBvbiBjaGlwIG1lbW9yeSBibG9jayB0cmFuc2ZlciB0byBv dGhlcgorICogZW5kcG9pbnRzLgorICoKKyAqIEl0J3MgbGltaXRhdGlvbiBvZiBjb250cm9sbGVy IGJ1dCBtYXliZSB0aGlzIGlzc3VlcyBzaG91bGQgYmUgZml4ZWQgaW4KKyAqIGZ1bmN0aW9uIGRy aXZlci4KKyAqCisgKiBUaGlzIHdvcmsgYXJvdW5kIGNhbiBiZSBkaXNhYmxlZC9lbmFibGVkIGJ5 IG1lYW5zIG9mIHF1aXJrX2ludGVybmFsX2J1ZmZlcgorICogbW9kdWxlIHBhcmFtZXRlci4gQnkg ZGVmYXVsdCBmZWF0dXJlIGlzIGVuYWJsZWQuIEl0IGNhbiBoYXMgaW1wYWN0IHRvCisgKiB0cmFu c2ZlciBwZXJmb3JtYW5jZSBhbmQgaW4gbW9zdCBjYXNlIHRoaXMgZmVhdHVyZSBjYW4gYmUgZGlz YWJsZWQuCiAgKi8KIAogI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+CkBAIC00Miw2ICs3 MywxNCBAQCBzdGF0aWMgaW50IF9fY2RuczNfZ2FkZ2V0X2VwX3F1ZXVlKHN0cnVjdCB1c2JfZXAg KmVwLAogCQkJCSAgIHN0cnVjdCB1c2JfcmVxdWVzdCAqcmVxdWVzdCwKIAkJCQkgICBnZnBfdCBn ZnBfZmxhZ3MpOwogCisvKgorICogUGFyYW1ldGVyIGFsbG93cyB0byBkaXNhYmxlL2VuYWJsZSBo YW5kbGluZyBvZiB3b3JrIGFyb3VuZCAyIGZlYXR1cmUuCisgKiBCeSBkZWZhdWx0IHRoaXMgdmFs dWUgaXMgZW5hYmxlZC4KKyAqLworc3RhdGljIGJvb2wgcXVpcmtfaW50ZXJuYWxfYnVmZmVyID0g MTsKK21vZHVsZV9wYXJhbShxdWlya19pbnRlcm5hbF9idWZmZXIsIGJvb2wsIDA2NDQpOworTU9E VUxFX1BBUk1fREVTQyhxdWlya19pbnRlcm5hbF9idWZmZXIsICJEaXNhYmxlL2VuYWJsZSBXQTIg YWxnb3JpdGhtIik7CisKIC8qKgogICogY2RuczNfaGFuZHNoYWtlIC0gc3BpbiByZWFkaW5nICB1 bnRpbCBoYW5kc2hha2UgY29tcGxldGVzIG9yIGZhaWxzCiAgKiBAcHRyOiBhZGRyZXNzIG9mIGRl dmljZSBjb250cm9sbGVyIHJlZ2lzdGVyIHRvIGJlIHJlYWQKQEAgLTEwNSw2ICsxNDQsMTcgQEAg c3RydWN0IHVzYl9yZXF1ZXN0ICpjZG5zM19uZXh0X3JlcXVlc3Qoc3RydWN0IGxpc3RfaGVhZCAq bGlzdCkKIAlyZXR1cm4gbGlzdF9maXJzdF9lbnRyeV9vcl9udWxsKGxpc3QsIHN0cnVjdCB1c2Jf cmVxdWVzdCwgbGlzdCk7CiB9CiAKKy8qKgorICogY2RuczNfbmV4dF9wcml2X3JlcXVlc3QgLSBy ZXR1cm5zIG5leHQgcmVxdWVzdCBmcm9tIGxpc3QKKyAqIEBsaXN0OiBsaXN0IGNvbnRhaW5pbmcg cmVxdWVzdHMKKyAqCisgKiBSZXR1cm5zIHJlcXVlc3Qgb3IgTlVMTCBpZiBubyByZXF1ZXN0cyBp biBsaXN0CisgKi8KK3N0cnVjdCBjZG5zM19yZXF1ZXN0ICpjZG5zM19uZXh0X3ByaXZfcmVxdWVz dChzdHJ1Y3QgbGlzdF9oZWFkICpsaXN0KQoreworCXJldHVybiBsaXN0X2ZpcnN0X2VudHJ5X29y X251bGwobGlzdCwgc3RydWN0IGNkbnMzX3JlcXVlc3QsIGxpc3QpOworfQorCiAvKioKICAqIHNl bGVjdF9lcCAtIHNlbGVjdHMgZW5kcG9pbnQKICAqIEBwcml2X2RldjogIGV4dGVuZGVkIGdhZGdl dCBvYmplY3QKQEAgLTM4NCw2ICs0MzQsNTMgQEAgc3RhdGljIGludCBjZG5zM19zdGFydF9hbGxf cmVxdWVzdChzdHJ1Y3QgY2RuczNfZGV2aWNlICpwcml2X2RldiwKIAlyZXR1cm4gcmV0OwogfQog CisvKioKKyAqIGNkbnMzX2Rlc2NtaXNzX2NvcHlfZGF0YSBjb3B5IGRhdGEgZnJvbSBpbnRlcm5h bCByZXF1ZXN0cyB0byByZXF1ZXN0IHF1ZXVlZAorICogYnkgY2xhc3MgZHJpdmVyLgorICogQHBy aXZfZXA6IGV4dGVuZGVkIGVuZHBvaW50IG9iamVjdAorICogQHJlcXVlc3Q6IHJlcXVlc3Qgb2Jq ZWN0CisgKi8KK3N0YXRpYyB2b2lkIGNkbnMzX2Rlc2NtaXNzX2NvcHlfZGF0YShzdHJ1Y3QgY2Ru czNfZW5kcG9pbnQgKnByaXZfZXAsCisJCQkJICAgICBzdHJ1Y3QgdXNiX3JlcXVlc3QgKnJlcXVl c3QpCit7CisJc3RydWN0IHVzYl9yZXF1ZXN0ICpkZXNjbWlzc19yZXE7CisJc3RydWN0IGNkbnMz X3JlcXVlc3QgKmRlc2NtaXNzX3ByaXZfcmVxOworCisJd2hpbGUgKCFsaXN0X2VtcHR5KCZwcml2 X2VwLT5kZXNjbWlzc19yZXFfbGlzdCkpIHsKKwkJaW50IGNodW5rX2VuZDsKKwkJaW50IGxlbmd0 aDsKKworCQlkZXNjbWlzc19wcml2X3JlcSA9CisJCQljZG5zM19uZXh0X3ByaXZfcmVxdWVzdCgm cHJpdl9lcC0+ZGVzY21pc3NfcmVxX2xpc3QpOworCQlkZXNjbWlzc19yZXEgPSAmZGVzY21pc3Nf cHJpdl9yZXEtPnJlcXVlc3Q7CisKKwkJLyogZHJpdmVyIGNhbid0IHRvdWNoIHBlbmRpbmcgcmVx dWVzdCAqLworCQlpZiAoZGVzY21pc3NfcHJpdl9yZXEtPmZsYWdzICYgUkVRVUVTVF9QRU5ESU5H KQorCQkJYnJlYWs7CisKKwkJY2h1bmtfZW5kID0gZGVzY21pc3NfcHJpdl9yZXEtPmZsYWdzICYg UkVRVUVTVF9JTlRFUk5BTF9DSDsKKwkJbGVuZ3RoID0gcmVxdWVzdC0+YWN0dWFsICsgZGVzY21p c3NfcmVxLT5hY3R1YWw7CisKKwkJaWYgKGxlbmd0aCA8PSByZXF1ZXN0LT5sZW5ndGgpIHsKKwkJ CW1lbWNweSgmKCh1OCAqKXJlcXVlc3QtPmJ1ZilbcmVxdWVzdC0+YWN0dWFsXSwKKwkJCSAgICAg ICBkZXNjbWlzc19yZXEtPmJ1ZiwKKwkJCSAgICAgICBkZXNjbWlzc19yZXEtPmFjdHVhbCk7CisJ CQlyZXF1ZXN0LT5hY3R1YWwgPSBsZW5ndGg7CisJCX0gZWxzZSB7CisJCQkvKiBJdCBzaG91bGQg bmV2ZXIgb2NjdXJlcyAqLworCQkJcmVxdWVzdC0+c3RhdHVzID0gLUVOT01FTTsKKwkJfQorCisJ CWxpc3RfZGVsX2luaXQoJmRlc2NtaXNzX3ByaXZfcmVxLT5saXN0KTsKKworCQlrZnJlZShkZXNj bWlzc19yZXEtPmJ1Zik7CisJCWNkbnMzX2dhZGdldF9lcF9mcmVlX3JlcXVlc3QoJnByaXZfZXAt PmVuZHBvaW50LCBkZXNjbWlzc19yZXEpOworCisJCWlmICghY2h1bmtfZW5kKQorCQkJYnJlYWs7 CisJfQorfQorCiAvKioKICAqIGNkbnMzX2dhZGdldF9naXZlYmFjayAtIGNhbGwgc3RydWN0IHVz Yl9yZXF1ZXN0J3MgLT5jb21wbGV0ZSBjYWxsYmFjawogICogQHByaXZfZXA6IFRoZSBlbmRwb2lu dCB0byB3aG9tIHRoZSByZXF1ZXN0IGJlbG9uZ3MgdG8KQEAgLTQxMiw2ICs1MDksMzIgQEAgdm9p ZCBjZG5zM19nYWRnZXRfZ2l2ZWJhY2soc3RydWN0IGNkbnMzX2VuZHBvaW50ICpwcml2X2VwLAog CXByaXZfcmVxLT5mbGFncyAmPSB+UkVRVUVTVF9QRU5ESU5HOwogCXRyYWNlX2NkbnMzX2dhZGdl dF9naXZlYmFjayhwcml2X3JlcSk7CiAKKwkvKiBXQTI6ICovCisJaWYgKHByaXZfZXAtPmZsYWdz ICYgRVBfUVVJUktfRVhUUkFfQlVGX0VOICYmCisJICAgIHByaXZfcmVxLT5mbGFncyAmIFJFUVVF U1RfSU5URVJOQUwpIHsKKwkJc3RydWN0IHVzYl9yZXF1ZXN0ICpyZXE7CisKKwkJcmVxID0gY2Ru czNfbmV4dF9yZXF1ZXN0KCZwcml2X2VwLT5kZWZlcnJlZF9yZXFfbGlzdCk7CisJCXJlcXVlc3Qg PSByZXE7CisJCXByaXZfZXAtPmRlc2NtaXNfcmVxID0gTlVMTDsKKworCQlpZiAoIXJlcSkKKwkJ CXJldHVybjsKKworCQljZG5zM19kZXNjbWlzc19jb3B5X2RhdGEocHJpdl9lcCwgcmVxKTsKKwkJ aWYgKCEocHJpdl9lcC0+ZmxhZ3MgJiBFUF9RVUlSS19FTkRfVFJBTlNGRVIpICYmCisJCSAgICBy ZXEtPmxlbmd0aCAhPSByZXEtPmFjdHVhbCkgeworCQkJLyogd2FpdCBmb3IgbmV4dCBwYXJ0IG9m IHRyYW5zZmVyICovCisJCQlyZXR1cm47CisJCX0KKworCQlpZiAocmVxLT5zdGF0dXMgPT0gLUVJ TlBST0dSRVNTKQorCQkJcmVxLT5zdGF0dXMgPSAwOworCisJCWxpc3RfZGVsX2luaXQoJnJlcS0+ bGlzdCk7CisJCWNkbnMzX3N0YXJ0X2FsbF9yZXF1ZXN0KHByaXZfZGV2LCBwcml2X2VwKTsKKwl9 CisKIAkvKiBTdGFydCBhbGwgbm90IHBlbmRpbmcgcmVxdWVzdCAqLwogCWlmIChwcml2X2VwLT5m bGFncyAmIEVQX1JJTkdfRlVMTCkKIAkJY2RuczNfc3RhcnRfYWxsX3JlcXVlc3QocHJpdl9kZXYs IHByaXZfZXApOwpAQCAtNzc0LDYgKzg5Nyw1OSBAQCB2b2lkIGNkbnMzX3JlYXJtX3RyYW5zZmVy KHN0cnVjdCBjZG5zM19lbmRwb2ludCAqcHJpdl9lcCwgdTggcmVhcm0pCiAJfQogfQogCisvKioK KyAqIGNkbnMzX2Rlc2NtaXNzaW5nX3BhY2tldCAtIGhhbmRsZXMgZGVzY3JpcHRvciBtaXNzaW5n IGV2ZW50LgorICogQHByaXZfZGV2OiBleHRlbmRlZCBnYWRnZXQgb2JqZWN0CisgKgorICogVGhp cyBmdW5jdGlvbiBpcyB1c2VkIG9ubHkgZm9yIFdBMi4gRm9yIG1vcmUgaW5mb3JtYXRpb24gc2Vl IFdvcmsgYXJvdW5kIDIKKyAqIGRlc2NyaXB0aW9uLgorICovCitzdGF0aWMgaW50IGNkbnMzX2Rl c2NtaXNzaW5nX3BhY2tldChzdHJ1Y3QgY2RuczNfZW5kcG9pbnQgKnByaXZfZXApCit7CisJc3Ry dWN0IGNkbnMzX3JlcXVlc3QgKnByaXZfcmVxOworCXN0cnVjdCB1c2JfcmVxdWVzdCAqcmVxdWVz dDsKKworCWlmIChwcml2X2VwLT5mbGFncyAmIEVQX1FVSVJLX0VYVFJBX0JVRl9ERVQpIHsKKwkJ cHJpdl9lcC0+ZmxhZ3MgJj0gfkVQX1FVSVJLX0VYVFJBX0JVRl9ERVQ7CisJCXByaXZfZXAtPmZs YWdzIHw9IEVQX1FVSVJLX0VYVFJBX0JVRl9FTjsKKwl9CisKKwljZG5zM19kYmcocHJpdl9lcC0+ Y2RuczNfZGV2LCAiV0EyOiBEZXNjcmlwdGlvbiBNaXNzaW5nIGRldGVjdGVkXG4iKTsKKworCXJl cXVlc3QgPSBjZG5zM19nYWRnZXRfZXBfYWxsb2NfcmVxdWVzdCgmcHJpdl9lcC0+ZW5kcG9pbnQs CisJCQkJCQlHRlBfQVRPTUlDKTsKKwlpZiAoIXJlcXVlc3QpCisJCXJldHVybiAtRU5PTUVNOwor CisJcHJpdl9yZXEgPSB0b19jZG5zM19yZXF1ZXN0KHJlcXVlc3QpOworCXByaXZfcmVxLT5mbGFn cyB8PSBSRVFVRVNUX0lOVEVSTkFMOworCisJLyogaWYgdGhpcyBmaWVsZCBpcyBzdGlsbCBhc3Np Z25lZCBpdCBpbmRpY2F0ZSB0aGF0IHRyYW5zZmVyIHJlbGF0ZWQKKwkgKiB3aXRoIHRoaXMgcmVx dWVzdCBoYXMgbm90IGJlZW4gZmluaXNoZWQgeWV0LiBEcml2ZXIgaW4gdGhpcworCSAqIGNhc2Ug c2ltcGx5IGFsbG9jYXRlIG5leHQgcmVxdWVzdCBhbmQgYXNzaWduIGZsYWcgUkVRVUVTVF9JTlRF Uk5BTF9DSAorCSAqIGZsYWcgdG8gcHJldmlvdXMgb25lLiBJdCB3aWxsIGluZGljYXRlIHRoYXQg Y3VycmVudCByZXF1ZXN0IGlzCisJICogcGFydCBvZiB0aGUgcHJldmlvdXMgb25lLgorCSAqLwor CWlmIChwcml2X2VwLT5kZXNjbWlzX3JlcSkKKwkJcHJpdl9lcC0+ZGVzY21pc19yZXEtPmZsYWdz IHw9IFJFUVVFU1RfSU5URVJOQUxfQ0g7CisKKwlwcml2X3JlcS0+cmVxdWVzdC5idWYgPSBremFs bG9jKENETlMzX0RFU0NNSVNfQlVGX1NJWkUsCisJCQkJCUdGUF9BVE9NSUMpOworCWlmICghcHJp dl9yZXEpIHsKKwkJY2RuczNfZ2FkZ2V0X2VwX2ZyZWVfcmVxdWVzdCgmcHJpdl9lcC0+ZW5kcG9p bnQsIHJlcXVlc3QpOworCQlyZXR1cm4gLUVOT01FTTsKKwl9CisKKwlwcml2X3JlcS0+cmVxdWVz dC5sZW5ndGggPSBDRE5TM19ERVNDTUlTX0JVRl9TSVpFOworCXByaXZfZXAtPmRlc2NtaXNfcmVx ID0gcHJpdl9yZXE7CisKKwlfX2NkbnMzX2dhZGdldF9lcF9xdWV1ZSgmcHJpdl9lcC0+ZW5kcG9p bnQsCisJCQkJJnByaXZfZXAtPmRlc2NtaXNfcmVxLT5yZXF1ZXN0LAorCQkJCUdGUF9BVE9NSUMp OworCisJcmV0dXJuIDA7Cit9CisKIC8qKgogICogY2RuczNfY2hlY2tfZXBfaW50ZXJydXB0X3By b2NlZWQgLSBQcm9jZXNzZXMgaW50ZXJydXB0IHJlbGF0ZWQgdG8gZW5kcG9pbnQKICAqIEBwcml2 X2VwOiBlbmRwb2ludCBvYmplY3QKQEAgLTgwNyw4ICs5ODMsMzEgQEAgc3RhdGljIGludCBjZG5z M19jaGVja19lcF9pbnRlcnJ1cHRfcHJvY2VlZChzdHJ1Y3QgY2RuczNfZW5kcG9pbnQgKnByaXZf ZXApCiAJCQljZG5zM19yZWFybV90cmFuc2Zlcihwcml2X2VwLCBwcml2X2VwLT53YTFfc2V0KTsK IAl9CiAKLQlpZiAoKGVwX3N0c19yZWcgJiBFUF9TVFNfSU9DKSB8fCAoZXBfc3RzX3JlZyAmIEVQ X1NUU19JU1ApKQorCWlmICgoZXBfc3RzX3JlZyAmIEVQX1NUU19JT0MpIHx8IChlcF9zdHNfcmVn ICYgRVBfU1RTX0lTUCkpIHsKKwkJaWYgKHByaXZfZXAtPmZsYWdzICYgRVBfUVVJUktfRVhUUkFf QlVGX0VOKSB7CisJCQlpZiAoZXBfc3RzX3JlZyAmIEVQX1NUU19JU1ApCisJCQkJcHJpdl9lcC0+ ZmxhZ3MgfD0gRVBfUVVJUktfRU5EX1RSQU5TRkVSOworCQkJZWxzZQorCQkJCXByaXZfZXAtPmZs YWdzICY9IH5FUF9RVUlSS19FTkRfVFJBTlNGRVI7CisJCX0KKwogCQljZG5zM190cmFuc2Zlcl9j b21wbGV0ZWQocHJpdl9kZXYsIHByaXZfZXApOworCX0KKworCS8qCisJICogV0EyOiB0aGlzIGNv bmRpdGlvbiBzaG91bGQgb25seSBiZSBtZWV0IHdoZW4KKwkgKiBwcml2X2VwLT5mbGFncyAmIEVQ X1FVSVJLX0VYVFJBX0JVRl9ERVQgb3IKKwkgKiBwcml2X2VwLT5mbGFncyAmIEVQX1FVSVJLX0VY VFJBX0JVRl9FTi4KKwkgKiBJbiBvdGhlciBjYXNlcyB0aGlzIGludGVycnVwdCB3aWxsIGJlIGRp c2FibGVkLworCSAqLworCWlmIChlcF9zdHNfcmVnICYgRVBfU1RTX0RFU0NNSVMpIHsKKwkJaW50 IGVycjsKKworCQllcnIgPSBjZG5zM19kZXNjbWlzc2luZ19wYWNrZXQocHJpdl9lcCk7CisJCWlm IChlcnIpCisJCQlkZXZfZXJyKHByaXZfZGV2LT5kZXYsCisJCQkJIkZhaWxlZDogTm8gc3VmZmlj aWVudCBtZW1vcnkgZm9yIERFU0NNSVNcbiIpOworCX0KIAogCXJldHVybiAwOwogfQpAQCAtMTI0 MSwxMyArMTQ0MCwyNiBAQCBzdGF0aWMgaW50IGNkbnMzX2dhZGdldF9lcF9lbmFibGUoc3RydWN0 IHVzYl9lcCAqZXAsCiAJLyogZW5hYmxlIGludGVycnVwdCBmb3Igc2VsZWN0ZWQgZW5kcG9pbnQg Ki8KIAljZG5zM19zZXRfcmVnaXN0ZXJfYml0KCZwcml2X2Rldi0+cmVncy0+ZXBfaWVuLAogCQkJ ICAgICAgIEJJVChjZG5zM19lcF9hZGRyX3RvX2luZGV4KGJFbmRwb2ludEFkZHJlc3MpKSk7CisJ LyoKKwkgKiBXQTI6IFNldCBmbGFnIGZvciBhbGwgbm90IElTT0MgT1VUIGVuZHBvaW50cy4gSWYg dGhpcyBmbGFnIGlzIHNldAorCSAqIGRyaXZlciB0cnkgdG8gZGV0ZWN0IHdoZXRoZXIgZW5kcG9p bnQgbmVlZCBhZGRpdGlvbmFsIGludGVybmFsCisJICogYnVmZmVyIGZvciB1bmJsb2NraW5nIG9u LWNoaXAgRklGTyBidWZmZXIuIFRoaXMgZmxhZyB3aWxsIGJlIGNsZWFyZWQKKwkgKiBpZiBiZWZv cmUgZmlyc3QgREVTQ01JU1MgaW50ZXJydXB0IHRoZSBETUEgd2lsbCBiZSBhcm1lZC4KKwkgKi8K KwlpZiAocXVpcmtfaW50ZXJuYWxfYnVmZmVyKSB7CisJCWlmICghcHJpdl9lcC0+ZGlyICYmIHBy aXZfZXAtPnR5cGUgIT0gVVNCX0VORFBPSU5UX1hGRVJfSVNPQykgeworCQkJcHJpdl9lcC0+Zmxh Z3MgfD0gRVBfUVVJUktfRVhUUkFfQlVGX0RFVDsKKwkJCXJlZyB8PSBFUF9TVFNfRU5fREVTQ01J U0VOOworCQl9CisJfQogCiAJd3JpdGVsKHJlZywgJnByaXZfZGV2LT5yZWdzLT5lcF9zdHNfZW4p OwogCiAJY2RuczNfc2V0X3JlZ2lzdGVyX2JpdCgmcHJpdl9kZXYtPnJlZ3MtPmVwX2NmZywgRVBf Q0ZHX0VOQUJMRSk7CiAKIAllcC0+ZGVzYyA9IGRlc2M7Ci0JcHJpdl9lcC0+ZmxhZ3MgJj0gfihF UF9QRU5ESU5HX1JFUVVFU1QgfCBFUF9TVEFMTCk7CisJcHJpdl9lcC0+ZmxhZ3MgJj0gfihFUF9Q RU5ESU5HX1JFUVVFU1QgfCBFUF9TVEFMTCB8CisJCQkgICAgRVBfUVVJUktfRVhUUkFfQlVGX0VO KTsKIAlwcml2X2VwLT5mbGFncyB8PSBFUF9FTkFCTEVEIHwgRVBfVVBEQVRFX0VQX1RSQkFERFI7 CiAJcHJpdl9lcC0+d2ExX3NldCA9IDA7CiAJcHJpdl9lcC0+ZW5xdWV1ZSA9IDA7CkBAIC0xMjcy LDYgKzE0ODQsNyBAQCBzdGF0aWMgaW50IGNkbnMzX2dhZGdldF9lcF9lbmFibGUoc3RydWN0IHVz Yl9lcCAqZXAsCiBzdGF0aWMgaW50IGNkbnMzX2dhZGdldF9lcF9kaXNhYmxlKHN0cnVjdCB1c2Jf ZXAgKmVwKQogewogCXN0cnVjdCBjZG5zM19lbmRwb2ludCAqcHJpdl9lcDsKKwlzdHJ1Y3QgY2Ru czNfcmVxdWVzdCAqcHJpdl9yZXE7CiAJc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXY7CiAJ c3RydWN0IHVzYl9yZXF1ZXN0ICpyZXF1ZXN0OwogCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CkBAIC0x MzA4LDYgKzE1MjEsMTQgQEAgc3RhdGljIGludCBjZG5zM19nYWRnZXRfZXBfZGlzYWJsZShzdHJ1 Y3QgdXNiX2VwICplcCkKIAkJCQkgICAgICAtRVNIVVRET1dOKTsKIAl9CiAKKwl3aGlsZSAoIWxp c3RfZW1wdHkoJnByaXZfZXAtPmRlc2NtaXNzX3JlcV9saXN0KSkgeworCQlwcml2X3JlcSA9IGNk bnMzX25leHRfcHJpdl9yZXF1ZXN0KCZwcml2X2VwLT5kZXNjbWlzc19yZXFfbGlzdCk7CisKKwkJ a2ZyZWUocHJpdl9yZXEtPnJlcXVlc3QuYnVmKTsKKwkJY2RuczNfZ2FkZ2V0X2VwX2ZyZWVfcmVx dWVzdCgmcHJpdl9lcC0+ZW5kcG9pbnQsCisJCQkJCSAgICAgJnByaXZfcmVxLT5yZXF1ZXN0KTsK Kwl9CisKIAl3aGlsZSAoIWxpc3RfZW1wdHkoJnByaXZfZXAtPmRlZmVycmVkX3JlcV9saXN0KSkg ewogCQlyZXF1ZXN0ID0gY2RuczNfbmV4dF9yZXF1ZXN0KCZwcml2X2VwLT5kZWZlcnJlZF9yZXFf bGlzdCk7CiAKQEAgLTEzNDgsNiArMTU2OSw1MyBAQCBzdGF0aWMgaW50IF9fY2RuczNfZ2FkZ2V0 X2VwX3F1ZXVlKHN0cnVjdCB1c2JfZXAgKmVwLAogCXByaXZfcmVxID0gdG9fY2RuczNfcmVxdWVz dChyZXF1ZXN0KTsKIAl0cmFjZV9jZG5zM19lcF9xdWV1ZShwcml2X3JlcSk7CiAKKwkvKgorCSAq IFdBMjogaWYgdHJhbnNmZXIgd2FzIHF1ZXVlZCBiZWZvcmUgREVTQ01JU1MgYXBwZWFyIHRoYW4g d2UKKwkgKiBjYW4gZGlzYWJsZSBoYW5kbGluZyBvZiBERVNDTUlTUyBpbnRlcnJ1cHQuIERyaXZl ciBhc3N1bWVzIHRoYXQgaXQKKwkgKiBjYW4gZGlzYWJsZSBzcGVjaWFsIHRyZWF0bWVudCBmb3Ig dGhpcyBlbmRwb2ludC4KKwkgKi8KKwlpZiAocHJpdl9lcC0+ZmxhZ3MgJiBFUF9RVUlSS19FWFRS QV9CVUZfREVUKSB7CisJCXUzMiByZWc7CisKKwkJY2RuczNfc2VsZWN0X2VwKHByaXZfZGV2LCBw cml2X2VwLT5udW0gfCBwcml2X2VwLT5kaXIpOworCQlwcml2X2VwLT5mbGFncyAmPSB+RVBfUVVJ UktfRVhUUkFfQlVGX0RFVDsKKwkJcmVnID0gcmVhZGwoJnByaXZfZGV2LT5yZWdzLT5lcF9zdHNf ZW4pOworCQlyZWcgJj0gfkVQX1NUU19FTl9ERVNDTUlTRU47CisJCXdyaXRlbChyZWcsICZwcml2 X2Rldi0+cmVncy0+ZXBfc3RzX2VuKTsKKwl9CisKKwkvKiBXQTIgKi8KKwlpZiAocHJpdl9lcC0+ ZmxhZ3MgJiBFUF9RVUlSS19FWFRSQV9CVUZfRU4pIHsKKwkJdTggcGVuZGluZ19lbXB0eSA9IGxp c3RfZW1wdHkoJnByaXZfZXAtPnBlbmRpbmdfcmVxX2xpc3QpOworCQl1OCBkZXNjbWlzc19lbXB0 eSA9IGxpc3RfZW1wdHkoJnByaXZfZXAtPmRlc2NtaXNzX3JlcV9saXN0KTsKKworCQkvKgorCQkg KiAgREVTQ01JU1MgdHJhbnNmZXIgaGFzIGJlZW4gZmluaXNoZWQsIHNvIGRhdGEgd2lsbCBiZQor CQkgKiAgZGlyZWN0bHkgY29waWVkIGZyb20gaW50ZXJuYWwgYWxsb2NhdGVkIHVzYl9yZXF1ZXN0 CisJCSAqICBvYmplY3RzLgorCQkgKi8KKwkJaWYgKHBlbmRpbmdfZW1wdHkgJiYgIWRlc2NtaXNz X2VtcHR5ICYmCisJCSAgICAhKHByaXZfcmVxLT5mbGFncyAmIFJFUVVFU1RfSU5URVJOQUwpKSB7 CisJCQljZG5zM19kZXNjbWlzc19jb3B5X2RhdGEocHJpdl9lcCwgcmVxdWVzdCk7CisJCQlsaXN0 X2FkZF90YWlsKCZyZXF1ZXN0LT5saXN0LAorCQkJCSAgICAgICZwcml2X2VwLT5wZW5kaW5nX3Jl cV9saXN0KTsKKwkJCWNkbnMzX2dhZGdldF9naXZlYmFjayhwcml2X2VwLCBwcml2X3JlcSwKKwkJ CQkJICAgICAgcmVxdWVzdC0+c3RhdHVzKTsKKwkJCXJldHVybiByZXQ7CisJCX0KKworCQkvKgor CQkgKiBXQTIgZHJpdmVyIHdpbGwgd2FpdCBmb3IgY29tcGxldGlvbiBERVNDTUlTUyB0cmFuc2Zl ciwKKwkJICogYmVmb3JlIHN0YXJ0cyBuZXcsIG5vdCBERVNDTUlTUyB0cmFuc2Zlci4KKwkJICov CisJCWlmICghcGVuZGluZ19lbXB0eSAmJiAhZGVzY21pc3NfZW1wdHkpCisJCQlkZWZlcnJlZCA9 IDE7CisKKwkJaWYgKHByaXZfcmVxLT5mbGFncyAmIFJFUVVFU1RfSU5URVJOQUwpCisJCQlsaXN0 X2FkZF90YWlsKCZwcml2X3JlcS0+bGlzdCwKKwkJCQkgICAgICAmcHJpdl9lcC0+ZGVzY21pc3Nf cmVxX2xpc3QpOworCX0KKwogCXJldCA9IHVzYl9nYWRnZXRfbWFwX3JlcXVlc3RfYnlfZGV2KHBy aXZfZGV2LT5zeXNkZXYsIHJlcXVlc3QsCiAJCQkJCSAgICB1c2JfZW5kcG9pbnRfZGlyX2luKGVw LT5kZXNjKSk7CiAJaWYgKHJldCkKQEAgLTE3ODIsNiArMjA1MCw3IEBAIHN0YXRpYyBpbnQgY2Ru czNfaW5pdF9lcHMoc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYpCiAKIAkJSU5JVF9MSVNU X0hFQUQoJnByaXZfZXAtPnBlbmRpbmdfcmVxX2xpc3QpOwogCQlJTklUX0xJU1RfSEVBRCgmcHJp dl9lcC0+ZGVmZXJyZWRfcmVxX2xpc3QpOworCQlJTklUX0xJU1RfSEVBRCgmcHJpdl9lcC0+ZGVz Y21pc3NfcmVxX2xpc3QpOwogCX0KIAogCXJldHVybiAwOwpkaWZmIC0tZ2l0IGEvZHJpdmVycy91 c2IvY2RuczMvZ2FkZ2V0LmggYi9kcml2ZXJzL3VzYi9jZG5zMy9nYWRnZXQuaAppbmRleCA4MTdm OGFlN2E0ZGEuLjhkZTczM2IzMTVlOSAxMDA2NDQKLS0tIGEvZHJpdmVycy91c2IvY2RuczMvZ2Fk Z2V0LmgKKysrIGIvZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmgKQEAgLTEwMDAsNiArMTAwMCw3 IEBAIHN0cnVjdCBjZG5zM19kZXZpY2U7CiAgKiBAZW5kcG9pbnQ6IHVzYiBlbmRwb2ludAogICog QHBlbmRpbmdfcmVxX2xpc3Q6IGxpc3Qgb2YgcmVxdWVzdHMgcXVldWluZyBvbiB0cmFuc2ZlciBy aW5nLgogICogQGRlZmVycmVkX3JlcV9saXN0OiBsaXN0IG9mIHJlcXVlc3RzIHdhaXRpbmcgZm9y IHF1ZXVpbmcgb24gdHJhbnNmZXIgcmluZy4KKyAqIEBkZXNjbWlzc19yZXFfbGlzdDogbGlzdCBv ZiByZXF1ZXN0cyBpbnRlcm5hbGx5IGFsbG9jYXRlZCBieSBkcml2ZXIgKFdBMikuCiAgKiBAdHJi X3Bvb2w6IHRyYW5zZmVyIHJpbmcgLSBhcnJheSBvZiB0cmFuc2FjdGlvbiBidWZmZXJzCiAgKiBA dHJiX3Bvb2xfZG1hOiBkbWEgYWRkcmVzcyBvZiB0cmFuc2ZlciByaW5nCiAgKiBAY2RuczNfZGV2 OiBkZXZpY2UgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZW5kcG9pbnQKQEAgLTEwMjYsNiArMTAyNyw3 IEBAIHN0cnVjdCBjZG5zM19lbmRwb2ludCB7CiAJc3RydWN0IHVzYl9lcAkJZW5kcG9pbnQ7CiAJ c3RydWN0IGxpc3RfaGVhZAlwZW5kaW5nX3JlcV9saXN0OwogCXN0cnVjdCBsaXN0X2hlYWQJZGVm ZXJyZWRfcmVxX2xpc3Q7CisJc3RydWN0IGxpc3RfaGVhZAlkZXNjbWlzc19yZXFfbGlzdDsKIAog CXN0cnVjdCBjZG5zM190cmIJKnRyYl9wb29sOwogCWRtYV9hZGRyX3QJCXRyYl9wb29sX2RtYTsK QEAgLTEwNDEsNiArMTA0Myw5IEBAIHN0cnVjdCBjZG5zM19lbmRwb2ludCB7CiAjZGVmaW5lIEVQ X1BFTkRJTkdfUkVRVUVTVAlCSVQoNSkKICNkZWZpbmUgRVBfUklOR19GVUxMCQlCSVQoNikKICNk ZWZpbmUgRVBfQ0xBSU1FRAkJQklUKDcpCisjZGVmaW5lIEVQX1FVSVJLX0VYVFJBX0JVRl9ERVQJ QklUKDgpCisjZGVmaW5lIEVQX1FVSVJLX0VYVFJBX0JVRl9FTglCSVQoOSkKKyNkZWZpbmUgRVBf UVVJUktfRU5EX1RSQU5TRkVSCUJJVCgxMCkKIAogCXUzMgkJCWZsYWdzOwogCkBAIC0xMDc0LDYg KzEwNzksNyBAQCBzdHJ1Y3QgY2RuczNfZW5kcG9pbnQgewogICogQHN0YXJ0X3RyYjogbnVtYmVy IG9mIHRoZSBmaXJzdCBUUkIgaW4gdHJhbnNmZXIgcmluZwogICogQGVuZF90cmI6IG51bWJlciBv ZiB0aGUgbGFzdCBUUkIgaW4gdHJhbnNmZXIgcmluZwogICogQGZsYWdzOiBmbGFnIHNwZWNpZnlp bmcgc3BlY2lhbCB1c2FnZSBvZiByZXF1ZXN0CisgKiBAbGlzdDogdXNlZCBieSBpbnRlcm5hbGx5 IGFsbG9jYXRlZCByZXF1ZXN0IHRvIGFkZCB0byBkZXNjbWlzc19yZXFfbGlzdC4KICAqLwogc3Ry dWN0IGNkbnMzX3JlcXVlc3QgewogCXN0cnVjdCB1c2JfcmVxdWVzdAlyZXF1ZXN0OwpAQCAtMTA4 Niw2ICsxMDkyLDcgQEAgc3RydWN0IGNkbnMzX3JlcXVlc3QgewogI2RlZmluZSBSRVFVRVNUX0lO VEVSTkFMX0NICUJJVCgyKQogI2RlZmluZSBSRVFVRVNUX1pMUAkJQklUKDMpCiAJdTMyCQkJZmxh Z3M7CisJc3RydWN0IGxpc3RfaGVhZAlsaXN0OwogfTsKIAogI2RlZmluZSB0b19jZG5zM19yZXF1 ZXN0KHIpIChjb250YWluZXJfb2Yociwgc3RydWN0IGNkbnMzX3JlcXVlc3QsIHJlcXVlc3QpKQo=