From patchwork Mon Jan 15 10:09:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wright Feng X-Patchwork-Id: 10163389 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7945F60325 for ; Mon, 15 Jan 2018 10:10:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 65AF1274D0 for ; Mon, 15 Jan 2018 10:10:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 598B92858D; Mon, 15 Jan 2018 10:10:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64905274D0 for ; Mon, 15 Jan 2018 10:10:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755312AbeAOKKE (ORCPT ); Mon, 15 Jan 2018 05:10:04 -0500 Received: from mail-sn1nam02on0134.outbound.protection.outlook.com ([104.47.36.134]:53061 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755309AbeAOKKC (ORCPT ); Mon, 15 Jan 2018 05:10:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cycorp.onmicrosoft.com; s=selector1-cypress-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=+SwQHMCD7QgegpCDpC2bPFKcmTqevXx+EX+wKPbtn6E=; b=xqGgrxUZu4XZmmlHs17vUh3EA2VInnqcNXMGoung2fBh3SvZ30XnCPKrbOFtVi+7Cy7f+8RSPlsUOsxhzaalaO830JS5nhKu6k7LxoNMKuQAW7SDIOgbJtoeiJVrd69KU9+HHEG4kUyn3kcj33BnjpYqXWqgGPEMqEewD5hDGlE= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Wright.Feng@cypress.com; Received: from [10.240.113.189] (61.222.14.99) by DM5PR0601MB3592.namprd06.prod.outlook.com (2603:10b6:4:7c::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.407.7; Mon, 15 Jan 2018 10:09:58 +0000 Subject: Re: [PATCH v2] brcmfmac: fix CLM load error for legacy chips when user helper is enabled To: Kalle Valo , Arend van Spriel Cc: franky.lin@broadcom.com, hante.meuleman@broadcom.com, chi-hsien.lin@cypress.com, linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com References: <1515743056-8109-1-git-send-email-wright.feng@cypress.com> <5A589428.7020502@broadcom.com> <87a7xjs4xa.fsf@kamboji.qca.qualcomm.com> From: Wright Feng Message-ID: <713a8666-8b72-9198-03a3-a3656c5cb84d@cypress.com> Date: Mon, 15 Jan 2018 18:09:35 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.2.0 MIME-Version: 1.0 In-Reply-To: <87a7xjs4xa.fsf@kamboji.qca.qualcomm.com> Content-Language: en-US X-Originating-IP: [61.222.14.99] X-ClientProxiedBy: TY1PR01CA0110.jpnprd01.prod.outlook.com (2603:1096:401:d::28) To DM5PR0601MB3592.namprd06.prod.outlook.com (2603:10b6:4:7c::14) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 45d74f9c-e2cf-4621-eb6c-08d55c00236e X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(4534125)(4602075)(4627221)(201703031133081)(201702281549075)(2017052603307)(7153060)(7193020); SRVR:DM5PR0601MB3592; X-Microsoft-Exchange-Diagnostics: 1; DM5PR0601MB3592; 3:SweQkl7xufNme4qRZ0hVHgQYfx+GjsiiWlvAswr1TsipDKtogaexhK15sVjj9TCfIwT2rg7jpPUsweVnNdAi5xbYga4JbgxbPIvsqEuKUS+ZyawwRw6N+4EIvB3kd1+nqIbSDApqbmoHnQCymynG5rYwGWvBRFyJ3clucANc8wCZc4vxkXF/I9SwA8ha0iLXL9CSs5cL3qJKZUdQSdArmyYIwzgrNK0wc9K0/oiFNaHNaPYVxbsVvLsVzJ6PMORA; 25:HoI+pOkIFwA/vESLBGktTDAogQnP5fDobqbo7pqHB8allCjg0r1hOSg/364KduDu9ofIKQKB1oDvR0S2/U6jXw5mtf2HqwuUk7+eqIEfkNg94n4N+S+F5aucaPoq8vO+1CtCu8focfV8RUu6uxUdFQI4QWAMsP2QZ9TtZntE5Swf/N+nKjMjiItgfgs8e398AJSnXgPtwQ6WS1Xqoz83dCuLmMO3C0bJIrK02BGySpArvwXVKUqxg2WYxamuGQwxeaTpmZmx1OlFwjzMnAEJVjNeeBq1KfW5ptvayiq1WnYOF72KCuAFrq1L5syeJ2uaXid5tDgr31t9pN0L93BCGw==; 31:g+qu6TlnEnQnEt1NObcAs6iqxDk5eES3x02X56t2rSHOB5UVCJcmOXPTpAcMg4HXiFYmuMuC/Atko9K06cejd64RK0f5DJHztEYXlHYUkIEeNTjFt9NSEJjNyOrKwFljCx5HGGCU43TC7rIzMhhVasVyRzx9yx4evrkxOz8BZOpEOWG5jlycBhzIXB3wodG98e60wjYLF4BWleBjvFEZc+xkGHr86Glgpza/YFNpdPE= X-MS-TrafficTypeDiagnostic: DM5PR0601MB3592: X-Microsoft-Exchange-Diagnostics: 1; DM5PR0601MB3592; 20:yQMr+cNisEeYoxhCqRALd5uYVCeAi48/gJx6ZXqVG7DHfjqUrpkYvi5283CGI+kg8bXaq6q+NG9PO3vqr9c+W/lX4hmmgIi6jB+Lp8m8NA6NXxMoO9RSf5VVVsKley3bMkDwzAwW2Ki5r6EksG4cn27eTTrEoHCNW6qRJKH1mQgCPuolEEBM9K2JGzRGFrgzd4Q+extSolh/J5oSMNYciL7Mfc0xXvpLJ8C2YY0zmU3iHA8601V0WiugEBs8Nn1xnVjziA3a62VrTk0ZSgn7dn0lBBeEGoFEBwNI4fYg/b/U9NuhGtUfaSqYG44Aruu3JHRdfdqSDy1a5TFrzNOEZm9CnqNodQgaAJ2SYkcoclh778Aq9SixRhoKEFYxL2nx68gXzk0FZxhcKDCLFsKyCUjuHODecaA6uS79DilC8IxxE2bRAKaiXrdj/7atQOrLiD4oe24zlIykfowaopkmjeyRJua/5aDva9tGMPzEYfgn9YtCPh31v5o6G+Nf2V82; 4:0+8uxsxpnOaXnYQM0PPTHoAHlCmaZW5VMu+tiBTVLpUyyr9zyeSHvSTFkG+a7ZFgbudjmlEyJNiHEhHEP8dS9gllh8jR8QbnY6wTY1K+v3MbtEr2raDwFH4c5g68B1/nmIXaevWRQr+Di8UhA8bUJRw/En4EAzG94geykLk0hbz4+cK65zLUhNel6i3q8u5k78wbgE8YwDjL+FbM9o44fczPjHX33yf+VazZoUdOzdcZfd4e5eTGWrALzPC+PsMqNXfXPRxSOExXeD+n7psSJfKOLR3emipgj8LQmkMa4Za75AiPbjPgasvz12KFtMK6LllcAepGV/fvCgBviYBuGGnu77k1+LwJzYV2r6tFqdE= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(258095267146985)(21532816269658); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(5005006)(8121501046)(93006095)(93001095)(3002001)(3231023)(944501161)(10201501046)(6055026)(6041268)(20161123560045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123564045)(6072148)(201708071742011); SRVR:DM5PR0601MB3592; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:DM5PR0601MB3592; X-Forefront-PRVS: 0553CBB77A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6049001)(346002)(376002)(39860400002)(366004)(39380400002)(396003)(199004)(189003)(24454002)(53936002)(106356001)(72206003)(478600001)(47776003)(68736007)(105586002)(86362001)(575784001)(6666003)(2870700001)(65806001)(65826007)(66066001)(65956001)(6246003)(36756003)(2906002)(64126003)(5660300001)(77096006)(31686004)(229853002)(8676002)(67846002)(110136005)(305945005)(83506002)(2950100002)(16576012)(25786009)(8936002)(81166006)(58126008)(316002)(81156014)(6116002)(2486003)(31696002)(52146003)(3846002)(52116002)(23676004)(76176011)(59450400001)(4326008)(6486002)(53546011)(7736002)(97736004)(386003)(50466002)(16526018); DIR:OUT; SFP:1102; SCL:1; SRVR:DM5PR0601MB3592; H:[10.240.113.189]; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: cypress.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtETTVQUjA2MDFNQjM1OTI7MjM6ek9KamRDWGN0Qm81d2xucHA5elkya3kz?= =?utf-8?B?VXRBMS9DYjc0V3VGSEhkNlFkV0lDYWZDRG9Ob3JkcXhVVkphaVB6NU5wVUZk?= =?utf-8?B?UG5WR2J6Nm9hRDRjQisyV1YxRHBTczQ0UWlvT1FzeDJtcjF6VmZzczlYK1Bq?= =?utf-8?B?WjZFRW5MTmNQdm5LUGJGdEFHaEFOQnRrZGVVQVpIaXZKYTRrbTliNTVrMFhJ?= =?utf-8?B?d21LbWJzbmZ3eUtrc0ZBSURBK2taY0xYTmsyZFBoUWp4OGdUQmZWRml4cDIx?= =?utf-8?B?NUlvaWN2eWFTVFQrL3QyVWErdk9WT095dWRwckdmMnNxRmZ0dUQvT1JTR3dO?= =?utf-8?B?UVIwanZyQUF3V285enowelV0UWMrQW9icDJYempVN3lpSGE3TnJiTUlNbjZS?= =?utf-8?B?Njh2ZnpDdkcyT1liYnlQRlczckVGbmFPeDZ2VElxMDJnQlh0eVBnRTFsMVUr?= =?utf-8?B?d2VZNW5lVmVUQkRTTDJnYWVyMFczRmFjOTF3UE42bjhDSnM2a0dJUnJyQ01O?= =?utf-8?B?ZXBDbWx0bHFqa1JyOTB3a21md0tjRVdVTzIrNXN5OG95eWNXMVlYOUVqZEVo?= =?utf-8?B?Y1NEbGNiUEdXZmV6UXJyWmUxNTNkbDZyRHpIUFBhbWk0aVhOK21wOHJnMnRt?= =?utf-8?B?Q0Z4VXdqbnRpU2s1WndoUGErNjQ3L2FrSWx1T0t2Qk9mMEp1bS9DcVZvemd4?= =?utf-8?B?REpIcUtZeXNsRlVQZndkWDFCM0FaVVdZT0RPbkplZjlPS0tWd0wwVVB1dG52?= =?utf-8?B?S1FyeWtZZm5FbTE3cWx3aW5GS01ITFVYM1RPSG1pcG4yYnZpaGt4S3B4ZzNh?= =?utf-8?B?R3dmSHZXaTY0SkMxTkdBdjVUSXlBdDdudVVVdnJOQXlQQS94ZjlwQjQ4V3lM?= =?utf-8?B?dDM4VjkyUUlqZ1Z3L21Sb1hsTmpqbVdQMUhWdU9aOElJL3pzZ0hwc2sxcXli?= =?utf-8?B?U1hTOVRpeEZ2KzB1R2owYVpLdi80MGJXTktqcE9keVJ6eFJwbmJCR1J2enFG?= =?utf-8?B?OUZrcmdRZVNsVndNVE1xVmMwbFNYRktlQzdmL3dtSndMbnZZZkRibTRNb1Zx?= =?utf-8?B?UDhhZzJEeXJmL1c4TlpkSkY0RFlCaTVCQm1xYjRac1lWRkJwZkdZTnRWS0RH?= =?utf-8?B?R3UxdGJmSm5NS1czc0psN0g5QkRHMHJpblhsNEErZWxScEkxMDRJS1kvbUMw?= =?utf-8?B?c3RzNWFxdm0zTlQ2YmxsWi9VU3FpRGRUQ2hNR3ZybFNoaUdnTDZZamxzeWF4?= =?utf-8?B?b2ltSkNDNWthNmRobTlQWjROZWdGSEJFTmR0WTNkOHlWcHVqNVprbkFCOVp0?= =?utf-8?B?NjQyeVRvVVd6TjMrcWdPRUY4di9EK251VXNQVG1LNnZmcWpKczVEamZSVTBm?= =?utf-8?B?cXJlRXU1enNNbzRvNG9JYjVhL3JJMUtYRW9KTjNzT2pJZjU5TmhuQ0RkNVBm?= =?utf-8?B?bUtzZGlXSkZ0M3hJbm1vWmRXYWZRVHBpbXZFQzJqWnN2K25vY2orbUZLdG1P?= =?utf-8?B?Q2krMDdSR1YvUEtwOFJ5dmZoTVBWVE12NkVZNjlMWVhxSVp5YzZoNXdRcWJp?= =?utf-8?B?azZFZDlVSENjNGZoK1FZdURKWFAwL0FVWXgwekFFaWdvZGhESUVhNWQ3VlNu?= =?utf-8?B?V21IVkRXc3FTV3JJU29aN2loRWdLRVJwQWFveWQ4VGJYcVI5RVRtak8rUUZx?= =?utf-8?B?ZEV4dit3OEVicFVLR2U5RTlULzhTSStGZWNWQjczMEw1YkNkWEZIUldXaHZU?= =?utf-8?B?MkRZQ3AxOTBEeEl0TDJETVlwZ2xvL1kwU2VxT3NCNkZnanZHUlllMENpd04v?= =?utf-8?B?K3pyVzhIUFR5Ymo2T1BrM3JkOTBKVjJzOVBnaklIbHNRc3RuY2MvOEhaaE1q?= =?utf-8?B?RkhTWHpNWGljd3BGemNtQkxqVFpjOStYYmZQNk4xdEZGa1lnLzRndE55U05H?= =?utf-8?Q?ExXpAb9L4YXcVNYIaCMo1/rOveXtn7b8=3D?= X-Microsoft-Exchange-Diagnostics: 1; DM5PR0601MB3592; 6:0PGHX+HmD6sOd2KogRECdvdiXyjtc1aNDAAJP/zqtHX56Gc4dOM3dZg+sc/jjcV7CIccCYro2pwOKxUL3tpCpQzKLbxmMfs5yptU62Fyk8Neyr8oLXAvVu7x4nyc9RrVkS3j2k2x7ggO21W5WGrjHF71rXlBjf9bWTJHBfZ2G57A65MfMAsJxsjbYRYyjTiLWqligu+9tCPE+WBErIxOvycrFUTF/PpFjwiHQ0VgKbFlVQ0elgWBcVX0Bku/+h5KXx1DIbRTraqKpmnXwg7RYsEwunf5eup7HxLaIp1hMIMIgu4sGZah5PMSdIojO/sfDeaOAy3rSfcpzh3T1P5R/RGDP50VlEOVOEZ6ar8NNJk=; 5:jeSndpuGlE2VTKnjTNmy1g3+h1DiaTpM9WzIl73nRwrYu4E1WIYbus2pZ2cgozPftrJL4dYL67iES0miFNG5A0yQHi6WKHKRhXbem27UZiQZKb3k1zlDWto0cQj7yoV4C1jVTuvQFud1eCKN88k8B88fwidYfg3PqA8q9nagsMs=; 24:vAadJCdfv0ZFhDiEKHCGZhyazYj73EvMetv63AM4YgWmV5wtlmwBVno3aIqvSJjJnKzp8TNoMMsAXWVgYOm6yxF78B2JsebqtUbhfzpQBTg=; 7:sd4MbTNaXazdKfIhT6hJzERvSvnBNwbTto2C9mgxjijgmPBbppvFem/getbaCaqG5GuQQC6rGqdt+uJewwNwWijwC5vJbgvOgfnKMQtxIQS4OnPAh1YoijHCIJCdHVddrDXEK8YmdX1TU4EIpd4eryHcaFAMzMjD3pQ0XPNeXQz32o688acM4j+eta5cONt9I1a0foJ5KTdqUFsXVS0RU+osbkqEaBlOVfoYTs4GzsWXW6+aZ+av72ikPOSzf3tu SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cypress.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jan 2018 10:09:58.6238 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 45d74f9c-e2cf-4621-eb6c-08d55c00236e X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 011addfc-2c09-450d-8938-e0bbc2dd2376 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR0601MB3592 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 2018/1/12 下午 07:16, Kalle Valo wrote: > Arend van Spriel writes: > >> On 1/12/2018 8:44 AM, Wright Feng wrote: >>> For legacy chips without CLM blob files, kernel with user helper function >>> returns -EAGAIN when we request_firmware() for blob file. > > _Why_ is the -EAGAIN returned? Is it because of user space, due to > timing when loading the brcmfmac module or what? You should explain the > problem in detail in the commit log and why this is the right approach > to fix the problem. > > Based on the commit log to me this still looks like a random attempt to > workaround a bug, not a proper fix. > It is not about the timing issue, it is about "the clm blob is not existence in firmware path for legacy firmware with CLM data built-in" and the -ENOENT error is transferred to -EAGAIN in firmware_class.c. Here is explanation of -EAGAIN returned in detail. In drivers/base/firmware_class.c:__fw_state_wait_common, it returns -ENOENT to indicate the clm_blob file is not found via user helper. However, in drivers/base/firmware_class.c:_request_firmware_load, all errors with fw status aborted are transferred to: 1. -ERESTARTSYS: The signal is pending and the task is interruptible. Before 76098b36b5db ("firmware: send -EINTR on signal abort on fallback mechanism"), all errors with fw status aborted are transferred to -EAGAIN. 2. -EAGAIN: All others fw status aborted(include -ENOENT) except for -ERESTARTSYS. And that's why I handle -EAGAIN error to let driver using CLM data in firmware. >>> In this case, brcmf_bus_started gets error and failed to bring up >>> legacy chips. Because of that, we should continue with CLM data >>> currently present in firmware if getting -EAGAIN when doing >>> request_firmware(). >>> >>> Signed-off-by: Wright Feng >>> --- >>> v2: remove retry from patch v1 >>> --- >>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- >>> 1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >>> index 6a59d06..0baab4c 100644 >>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c >>> @@ -182,7 +182,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) >>> >>> err = request_firmware(&clm, clm_name, dev); >>> if (err) { >>> - if (err == -ENOENT) { >>> + if (err == -ENOENT || err == -EAGAIN) { >>> brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); >>> return 0; >>> } >> >> Why don't we just fall-back to "CLM in firmware" regardless of the >> error code? > > Indeed, I was thinking the same. > For the firmwares with CLM data built-in, it is okay to continue the bringing-up flow. But when users put clm_blob file to firmware path, the corresponding firmware may not have CLM data built-in. If we fall-back to use empty CLM data in firmware when hitting other errors like "-ENOMEM" or "-EINTR", the country code revision will be null and users will meet error when trying to connect to access point. It is fine to fall-back to "CLM in firmware" regardless of the error code, but it would be better to print error log to indicate the error if the returned error codes are not what we expected. Please let me know your opinion of below commit log and diff, if it is okay to you, I will post Patch v3 later. For legacy chips without CLM blob files, kernel with user helper function returns -EAGAIN when we request_firmware() for blob file. So, it got failed when bring up legacy chips. We expect the CLM blob files is not existence in firmware path, however the -ENOENT error is transferred to -EAGAIN in firmware_class.c. Because of that, we continue with CLM data currently present in firmware if getting error in doing request_firmware(). --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); -- diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 6a59d06..aaab0e6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -182,12 +182,12 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) err = request_firmware(&clm, clm_name, dev); if (err) { - if (err == -ENOENT) { - brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); - return 0; - } - brcmf_err("request CLM blob file failed (%d)\n", err); - return err; + if (err == -ENOENT || err == -EAGAIN) + brcmf_info("continue with CLM data in FW\n"); + else + brcmf_err("request clm_blob failed(%d) continue with CLM data in FW\n", + err); + return 0; }