From patchwork Sat Feb 10 14:04:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Matyukevich X-Patchwork-Id: 10210505 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 4E54D60594 for ; Sat, 10 Feb 2018 14:04:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E9D7286CF for ; Sat, 10 Feb 2018 14:04:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 32C5A2991F; Sat, 10 Feb 2018 14:04:47 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, 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 1843E298F9 for ; Sat, 10 Feb 2018 14:04:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751092AbeBJOEp (ORCPT ); Sat, 10 Feb 2018 09:04:45 -0500 Received: from mail-by2nam03on0056.outbound.protection.outlook.com ([104.47.42.56]:51356 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751053AbeBJOEi (ORCPT ); Sat, 10 Feb 2018 09:04:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantenna.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=CZ6ImoJtGeW8Q6gtGrh4/Spej+3eAx/oJGT+ZjNBTXc=; b=0uxn62dG4zWo/ng7T+dhwgB4rWA8+Vbv/KeKf51vlUGDLOWd67eHPu9tBI/mpppsRPHg88bJznbCOfnU4DFq3QXgZo7sXlpnQpxBVRT8uJZku63KdJ8T7axuLr5RmM+TZXfA9wEHm+DlKI7yQv5oFywTY2RuVqZE2Au9idDUquc= Received: from bars.quantenna.com (195.182.157.78) by SN1PR05MB1936.namprd05.prod.outlook.com (10.162.132.14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.485.3; Sat, 10 Feb 2018 14:04:36 +0000 From: Sergey Matyukevich To: linux-wireless@vger.kernel.org Cc: Igor Mitsyanko , Avinash Patil , Sergei Maksimenko , Sergey Matyukevich Subject: [PATCH v2 3/4] qtnfmac: implement asynchronous firmware loading Date: Sat, 10 Feb 2018 17:04:19 +0300 Message-Id: <20180210140420.17013-4-sergey.matyukevich.os@quantenna.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180210140420.17013-1-sergey.matyukevich.os@quantenna.com> References: <20180210140420.17013-1-sergey.matyukevich.os@quantenna.com> MIME-Version: 1.0 X-Originating-IP: [195.182.157.78] X-ClientProxiedBy: AM6PR0402CA0007.eurprd04.prod.outlook.com (52.133.16.20) To SN1PR05MB1936.namprd05.prod.outlook.com (10.162.132.14) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d9237e5d-01cf-4caf-75c4-08d5708f386d X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(4534165)(4627221)(201703031133081)(201702281549075)(5600026)(4604075)(2017052603307)(7153060)(7193020); SRVR:SN1PR05MB1936; X-Microsoft-Exchange-Diagnostics: 1; SN1PR05MB1936; 3:RdoCB4RqE0U/tZZkWE7CTHgMU4YApPzqMvjH7gowomySqVt5GMl3hhEytmczVRAkbzZ03I1MovgA6bP1iNNLnq3PAh//0txtZ2EVVJdUy4WcDYwGHPF+KacVzlmkHRj6z1KHwkaw8dSzjeR3YG9HUb74AruYrw+qWfinlZw+fqd8U4LSGVUrIpRuhs9HjdVZh7j8Qq0ZCVlJ5E1K8+dP+zeahUwXxJ4HBDOWEV2iHDDkmsYAXUttd7vRlB9QqSwi; 25:eRmBslJ4UNdDL+qDOv8jcrzZju/am7ORtibrv7BH8uqubO6ROtCIFB2Nrwfie4DMsJYqjEb9CN3EkyRx/91/rEKMLd198ViNcqf83KZgiHQOcsnu9HHbW4lDiQ4A4I3pZuGvIL9jBl6YsQrYd5NH0R+NjYHnciupO6U78tpEdT4pYTtYYKP9RshkHh7tUU264hSVu4YHhco/XQHf6EiQyUCowLiYLg+tSMJNHQaUXsgpnW+d+vIxwPZj926qrpoIJiiEtMDIrokyN8jDeKt55e6+SLyCvdi4W4YJQcGCSuTdyChDFdb6o0lofL/JwZk3W/hhYHm4C2XGSLRf8fARtA==; 31:/E1t8XFNZsfw1P/4VQHcVhbVfFbUXKjSwstiv2kKKpQz29U9qT7sISdCd2JTduXqwv7aOSO3s/4zWvpKa2Bg4Wn8gKqwNtK1c32nY5Ay9V1TqkeRn8pn3LLq9NjA5hu4q+sg3yE6d9pq0kts1X+0bGDn3FHVYiYEYk17s13YVUB3wtfHdL6lWvCA9GZdzI9JIKc+9p0PBUlCQOAHNxJ+1/4j0KONCbnPABmhCsu8PFE= X-MS-TrafficTypeDiagnostic: SN1PR05MB1936: X-Microsoft-Exchange-Diagnostics: 1; SN1PR05MB1936; 20:LMft0nQihiT6xN1SuSJHDAfr8jeO12nx2gN90C+jBoGGLPeBkj4XA4qnOjgkJJWcSulHabxsPaqbboXjCYpgbfVNy0+9XmPhVkMshpp0aJ8iZE6v0PyJoSnSEjzpHTe0o1Fb8UITYX3VpM9X1kqPDQ7cz1tnPIkkXBccH0+oIu9igf547sJS9eWuCBWdJYGTlM3d9wGAX1Qz1ZGy0++boU1ZwA0FVxZzh/aMVi9Y3u7fVDoMIrATRUoAk4FIUypftdW14MXuQuahMJzV2iD7wJMw+dVAdjizU0iVlOB3r1OMD2QXLPo+rjrrEYdyOCGweOdzgRxNZdyROa7ARvr1TXYTMbzUegucMW+O530BHxiyOyrY+BhNy5qm/rUxexE6DeKae/cNZCj077/tqmYVSrvkPJqJ8cFQXt8yICUqvx659ambB6J+XblGL7K4A7F++AC1XyQjMsLzjmHeB4Tb32sCIKyQJnGuzC/jfYWLM3MOmr2tup9GzAbDUJX5ebgm; 4:qHfpPj34TxdOsdFfI9U5dufhBKQKY32L6qzumGI+rhi8LjCpb5V9hEOUFi1t2MWPXV+zmTtK1ACQklg197rBOnOkUjRwHpndHSgUWcG9xUudG9cC7l5CIk49uexoBE+UVWhzDE6Hln2VWEz8orrhfUv7OtxfwiDpI9bbGje1aJou4tcBkvzXYje9JwuUI8G2ZH/02TrYPjzHXyObqFLvGAHJOOCk+iYwvKMUA5aiPflXE9yedVyao0263xxi1DjkfZehIO9tVEuEwufrFgAn1Q== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040501)(2401047)(5005006)(8121501046)(3002001)(10201501046)(93006095)(93001095)(3231101)(2400082)(944501161)(6041288)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(6072148)(201708071742011); SRVR:SN1PR05MB1936; BCL:0; PCL:0; RULEID:; SRVR:SN1PR05MB1936; X-Forefront-PRVS: 057906460E X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(376002)(39380400002)(39840400004)(396003)(346002)(366004)(199004)(189003)(478600001)(54906003)(68736007)(386003)(26005)(76176011)(16586007)(105586002)(66066001)(59450400001)(16526019)(186003)(6346003)(53936002)(51416003)(7696005)(52116002)(107886003)(6916009)(2950100002)(6666003)(5660300001)(36756003)(97736004)(316002)(25786009)(4326008)(6486002)(48376002)(2361001)(2906002)(81156014)(106356001)(81166006)(1076002)(47776003)(8676002)(2351001)(86362001)(3846002)(575784001)(6116002)(5890100001)(50466002)(69596002)(7736002)(305945005)(8936002)(50226002)(53416004)(103116003); DIR:OUT; SFP:1101; SCL:1; SRVR:SN1PR05MB1936; H:bars.quantenna.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: quantenna.com does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=sergey.matyukevich.os@quantenna.com; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN1PR05MB1936; 23:uVBBrvO3zsQEUb3XAPYzyQUZYYcyV7RrjeiRa35Nf?= =?us-ascii?Q?EZO0Hht+VKLGeE68ZUO4D15M1WRegnEkAXYfbBt35iKoyfxHJpyPkPLD7mAA?= =?us-ascii?Q?yyjqJXXIIi2G7p5eAsMTmrB1SXlM/2u6jO6w7HO5nXLbzS81lhRomSaqBdt8?= =?us-ascii?Q?515lTYiPNwdGjF1ZC60NrrKBA4cjaWXnJYHfu3qX/vIXg9J/UFyeEuM5dlwH?= =?us-ascii?Q?6J2gJX8p+rhYrPHoThXv3BfRH1O0DsN4e2joqAzTeLFQxPK3HTJqR/MigbwB?= =?us-ascii?Q?+dshyhCxv4AYnTJeidiMX4C0eQdN2cK7YGnAfbRCzc5GEIbGJIs1m6dwNuuu?= =?us-ascii?Q?HjncY3WVY4r7xvVrS0/hT6tr1hAVz8zf6gGXmHqcD+ubZfmfTVl1u+Nh07K+?= =?us-ascii?Q?YO9BvQEgiHUXuBkNlSm87KDX2cuc8Fp92/gbKcHy79yGP7JbA5bUwjAuNGJ8?= =?us-ascii?Q?V7AKYqAgr8I6351M1Jz2l2BRwuPinkTv6ZP5XKkv1u90zU/2L3l2CTZhSLZz?= =?us-ascii?Q?hnFFhforif/3Lp4pmvaYHbqhqhcN4ZonAdq+JJumqh08DrK6EbPVihtu+XkQ?= =?us-ascii?Q?UEjvqURmCtw/j75gmk1HAcAFwPZJxI3CdwUTpOctM0EM0NrZwO13RExwlox9?= =?us-ascii?Q?H1PBN7J9ElG69Si+gOhwpOPlHhLAWJBnJP9yepjcoq1Fq5IPXLCKcR7gKGTI?= =?us-ascii?Q?rZRWIwt5978vEHFBrFO2sdiSyC6Wo8yhg5NO6fB4ruANpvWHOK2Bs5jzwMUr?= =?us-ascii?Q?qR4wzhoOhD3Z7w5SFkDtUn7ICmbYY5fnvHyrCxFeZGgPmSXuFGXBXQsSisuS?= =?us-ascii?Q?PCbvDjk0AIUdKOSys67YKWq93S/kRGASBV7VYpwsPq0cCHEm5Xz1lcB059Li?= =?us-ascii?Q?p0v0uvWz8gN3UHlNShk3dGty/SPjIJ++GJhLV19xJZT9r+3r7K5NgHUsckK+?= =?us-ascii?Q?G655gM2XRpqhQC0ouOKGOCnQJ8q1wXU4sxsYhzQD/6F741N+oJpjL4SU8y/V?= =?us-ascii?Q?MdSxdwTA5iHR4xJHoSvtNo08TJQ/WDdKWxk8W9aZsjZXP3ufgX+vFaq59VeL?= =?us-ascii?Q?LH5frVOO9sV8M5XNB5BT8BRxEtuhX6fA6DGXnPScfqL+8N0nEZlx4iQzzwaC?= =?us-ascii?Q?ejfcEuuMiUABUbkQ/a4EXUHYZNdGtrm6RMn5fNfAGovBlG//EN5igHl5UNv3?= =?us-ascii?Q?keeoCyIPa1fySKdnnnVw0qIQ1l4cKxdulsU2+zHwJjGOPo2jPP41WuUS9O2u?= =?us-ascii?Q?qsMfz98uvz20qcisibQO22f4W7y23MX5nyApBP37gnA/fTb7whJicJPMwDKa?= =?us-ascii?Q?MWsN126GTzQgetpnEewVaCTshBx7o6qapybYg3u4uB7?= X-Microsoft-Exchange-Diagnostics: 1; SN1PR05MB1936; 6:W4PeuaRQYq5kvXfIfuONrNih1i0wNyXCavx8sSPRoh+Yu6XTnw6uuLttu+BqtTfgHud7a8gnLz8Zb4YSxZwPVdTrx/wnUD3eulxRxgolKVoEnGXjbhRGUXe2/o2cs0taoB0SrPsIv4pUVDhc2W45dASEOsL1+mhdBEmXz0sIT1Jj2nNH6KVfu4hEixadkng75emsPPbtcvZTQvXJwtq8cw92FfnWV6S60Z1UMb84w3/XHAxJTtkk9xXV3h6FwK+0rE33lfwyUZA8m4QVfus9ng5oGSDKYOd8OIVDjkxWoosxx9ruq3YXXRGFZ5sA44Z8IvwEC+UhWvQZti0WtvpU/YbFrtfFzRD1WD27KZcaeDI=; 5:52G5SGwozFFLYEHRYr2yVa5JRIkh6yXQD+9N4u2DqpD1Y6sMA/Crre5dw2es5G0fnPjKerrkkiXOTxvbRXTqO1mF6YnEoSzyauFkZnHk6xnIGNRHFmj9CopSyzNq8EBprLt/rwtftVsH2p3IOunUm6dectIbfiMx1t7CS9qgDNY=; 24:5ndm9GvQMFYZDyDAgFB1USNqGO9d12/0YFpMtBJw7zYZbhK43aznKvGHErANQ2ReGeFPpFMtKwtvcmDF9n83MYR0Lefjwa93obhfhAbj9fk=; 7:UZCJA7MICk48fz7I7AAxXM4q5Qkvly6J6EkSnzamz0nWcMO11MkThFn4ROwQ9IgCeloSjdK3cyMP6MBl6BFV2+Cud7UgQ9Q1mdXfJrx+WNJArYO9reIhwcaMHZMSYfz81Fpx9OA0C/C7NH97GFAYHwaC6r3oPrOqrVGrI4vGR7wQ3q/WtXc+2Hlhujd+CH7OjnsNPDgnNZLCUmYML1/FRzCS2iyUpyN/nW07nMQifQucUJZZyGL8OeRN1Wz5jU1m SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: quantenna.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Feb 2018 14:04:36.0562 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d9237e5d-01cf-4caf-75c4-08d5708f386d X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a355dbce-62b4-4789-9446-c1d5582180ff X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR05MB1936 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 In pci probe() function start firmware loading, protocol handshake and driver core initialization, and not wait for completion. Signed-off-by: Sergei Maksimenko --- drivers/net/wireless/quantenna/qtnfmac/bus.h | 3 +- .../net/wireless/quantenna/qtnfmac/pearl/pcie.c | 375 ++++++++++----------- 2 files changed, 180 insertions(+), 198 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h index 56e5fed92a2a..0a1604683bab 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/bus.h +++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h @@ -59,8 +59,9 @@ struct qtnf_bus { char fwname[32]; struct napi_struct mux_napi; struct net_device mux_dev; - struct completion request_firmware_complete; + struct completion firmware_init_complete; struct workqueue_struct *workqueue; + struct work_struct fw_work; struct work_struct event_work; struct mutex bus_lock; /* lock during command/event processing */ struct dentry *dbg_dir; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c index 7aa222286d8e..f117904d9120 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c @@ -127,7 +127,7 @@ static inline void qtnf_dis_txdone_irq(struct qtnf_pcie_bus_priv *priv) spin_unlock_irqrestore(&priv->irq_lock, flags); } -static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv) +static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv) { struct pci_dev *pdev = priv->pdev; @@ -148,8 +148,6 @@ static int qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv) pr_warn("legacy PCIE interrupts enabled\n"); pci_intx(pdev, 1); } - - return 0; } static void qtnf_deassert_intx(struct qtnf_pcie_bus_priv *priv) @@ -956,6 +954,98 @@ static const struct qtnf_bus_ops qtnf_pcie_bus_ops = { .data_rx_stop = qtnf_pcie_data_rx_stop, }; +static int qtnf_dbg_mps_show(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + + seq_printf(s, "%d\n", priv->mps); + + return 0; +} + +static int qtnf_dbg_msi_show(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + + seq_printf(s, "%u\n", priv->msi_enabled); + + return 0; +} + +static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base)); + u32 status; + + seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count); + seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count); + status = reg & PCIE_HDP_INT_TX_BITS; + seq_printf(s, "pcie_irq_tx_status(%s)\n", + (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS"); + seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count); + status = reg & PCIE_HDP_INT_RX_BITS; + seq_printf(s, "pcie_irq_rx_status(%s)\n", + (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS"); + seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count); + status = reg & PCIE_HDP_INT_HHBM_UF; + seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n", + (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS"); + + return 0; +} + +static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + + seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); + seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); + seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); + seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); + + seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); + seq_printf(s, "tx_bd_p_index(%u)\n", + readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) + & (priv->tx_bd_num - 1)); + seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); + seq_printf(s, "tx queue len(%u)\n", + CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, + priv->tx_bd_num)); + + seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); + seq_printf(s, "rx_bd_p_index(%u)\n", + readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base)) + & (priv->rx_bd_num - 1)); + seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); + seq_printf(s, "rx alloc queue len(%u)\n", + CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, + priv->rx_bd_num)); + + return 0; +} + +static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + + seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n", + priv->shm_ipc_ep_in.tx_packet_count); + seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n", + priv->shm_ipc_ep_in.rx_packet_count); + seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n", + priv->shm_ipc_ep_out.tx_timeout_count); + seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n", + priv->shm_ipc_ep_out.rx_packet_count); + + return 0; +} + static int qtnf_ep_fw_send(struct qtnf_pcie_bus_priv *priv, uint32_t size, int blk, const u8 *pblk, const u8 *fw) { @@ -1071,181 +1161,102 @@ qtnf_ep_fw_load(struct qtnf_pcie_bus_priv *priv, const u8 *fw, u32 fw_size) return 0; } -static void qtnf_firmware_load(const struct firmware *fw, void *context) -{ - struct qtnf_pcie_bus_priv *priv = (void *)context; - struct pci_dev *pdev = priv->pdev; - struct qtnf_bus *bus = pci_get_drvdata(pdev); - int ret; - - if (!fw) { - pr_err("failed to get firmware %s\n", bus->fwname); - goto fw_load_err; - } - - ret = qtnf_ep_fw_load(priv, fw->data, fw->size); - if (ret) { - pr_err("FW upload error\n"); - goto fw_load_err; - } - - if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE, - QTN_FW_DL_TIMEOUT_MS)) { - pr_err("FW bringup timed out\n"); - goto fw_load_err; - } - - bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; - pr_info("firmware is up and running\n"); - -fw_load_err: - - if (fw) - release_firmware(fw); - - complete(&bus->request_firmware_complete); -} - -static int qtnf_bringup_fw(struct qtnf_bus *bus) +static void qtnf_fw_work_handler(struct work_struct *work) { + struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); struct pci_dev *pdev = priv->pdev; + const struct firmware *fw; int ret; u32 state = QTN_RC_FW_LOADRDY | QTN_RC_FW_QLINK; - if (flashboot) + if (flashboot) { state |= QTN_RC_FW_FLASHBOOT; + } else { + ret = request_firmware(&fw, bus->fwname, &pdev->dev); + if (ret < 0) { + pr_err("failed to get firmware %s\n", bus->fwname); + goto fw_load_fail; + } + } qtnf_set_state(&priv->bda->bda_rc_state, state); if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY, QTN_FW_DL_TIMEOUT_MS)) { pr_err("card is not ready\n"); - return -ETIMEDOUT; + goto fw_load_fail; } qtnf_clear_state(&priv->bda->bda_ep_state, QTN_EP_FW_LOADRDY); if (flashboot) { - pr_info("Booting FW from flash\n"); - - if (!qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE, - QTN_FW_DL_TIMEOUT_MS)) - bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; + pr_info("booting firmware from flash\n"); + } else { + pr_info("starting firmware upload: %s\n", bus->fwname); - return 0; + ret = qtnf_ep_fw_load(priv, fw->data, fw->size); + release_firmware(fw); + if (ret) { + pr_err("firmware upload error\n"); + goto fw_load_fail; + } } - pr_info("starting firmware upload: %s\n", bus->fwname); - - ret = request_firmware_nowait(THIS_MODULE, 1, bus->fwname, &pdev->dev, - GFP_KERNEL, priv, qtnf_firmware_load); - if (ret < 0) - pr_err("request_firmware_nowait error %d\n", ret); - else - ret = 1; - - return ret; -} - -static void qtnf_reclaim_tasklet_fn(unsigned long data) -{ - struct qtnf_pcie_bus_priv *priv = (void *)data; - - qtnf_pcie_data_tx_reclaim(priv); - qtnf_en_txdone_irq(priv); -} - -static int qtnf_dbg_mps_show(struct seq_file *s, void *data) -{ - struct qtnf_bus *bus = dev_get_drvdata(s->private); - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - - seq_printf(s, "%d\n", priv->mps); + if (qtnf_poll_state(&priv->bda->bda_ep_state, QTN_EP_FW_DONE, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("firmware bringup timed out\n"); + goto fw_load_fail; + } - return 0; -} + bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE; + pr_info("firmware is up and running\n"); -static int qtnf_dbg_msi_show(struct seq_file *s, void *data) -{ - struct qtnf_bus *bus = dev_get_drvdata(s->private); - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); + if (qtnf_poll_state(&priv->bda->bda_ep_state, + QTN_EP_FW_QLINK_DONE, QTN_FW_QLINK_TIMEOUT_MS)) { + pr_err("firmware runtime failure\n"); + goto fw_load_fail; + } - seq_printf(s, "%u\n", priv->msi_enabled); + ret = qtnf_core_attach(bus); + if (ret) { + pr_err("failed to attach core\n"); + goto fw_load_fail; + } - return 0; -} + qtnf_debugfs_init(bus, DRV_NAME); + qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); + qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); + qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); + qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); + qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); -static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) -{ - struct qtnf_bus *bus = dev_get_drvdata(s->private); - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - u32 reg = readl(PCIE_HDP_INT_EN(priv->pcie_reg_base)); - u32 status; + goto fw_load_exit; - seq_printf(s, "pcie_irq_count(%u)\n", priv->pcie_irq_count); - seq_printf(s, "pcie_irq_tx_count(%u)\n", priv->pcie_irq_tx_count); - status = reg & PCIE_HDP_INT_TX_BITS; - seq_printf(s, "pcie_irq_tx_status(%s)\n", - (status == PCIE_HDP_INT_TX_BITS) ? "EN" : "DIS"); - seq_printf(s, "pcie_irq_rx_count(%u)\n", priv->pcie_irq_rx_count); - status = reg & PCIE_HDP_INT_RX_BITS; - seq_printf(s, "pcie_irq_rx_status(%s)\n", - (status == PCIE_HDP_INT_RX_BITS) ? "EN" : "DIS"); - seq_printf(s, "pcie_irq_uf_count(%u)\n", priv->pcie_irq_uf_count); - status = reg & PCIE_HDP_INT_HHBM_UF; - seq_printf(s, "pcie_irq_hhbm_uf_status(%s)\n", - (status == PCIE_HDP_INT_HHBM_UF) ? "EN" : "DIS"); +fw_load_fail: + bus->fw_state = QTNF_FW_STATE_DEAD; - return 0; +fw_load_exit: + complete(&bus->firmware_init_complete); + put_device(&pdev->dev); } -static int qtnf_dbg_hdp_stats(struct seq_file *s, void *data) +static void qtnf_bringup_fw_async(struct qtnf_bus *bus) { - struct qtnf_bus *bus = dev_get_drvdata(s->private); - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - - seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); - seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); - seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); - seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); - - seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); - seq_printf(s, "tx_bd_p_index(%u)\n", - readl(PCIE_HDP_RX0DMA_CNT(priv->pcie_reg_base)) - & (priv->tx_bd_num - 1)); - seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); - seq_printf(s, "tx queue len(%u)\n", - CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, - priv->tx_bd_num)); - - seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); - seq_printf(s, "rx_bd_p_index(%u)\n", - readl(PCIE_HDP_TX0DMA_CNT(priv->pcie_reg_base)) - & (priv->rx_bd_num - 1)); - seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); - seq_printf(s, "rx alloc queue len(%u)\n", - CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, - priv->rx_bd_num)); + struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); + struct pci_dev *pdev = priv->pdev; - return 0; + get_device(&pdev->dev); + INIT_WORK(&bus->fw_work, qtnf_fw_work_handler); + schedule_work(&bus->fw_work); } -static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) +static void qtnf_reclaim_tasklet_fn(unsigned long data) { - struct qtnf_bus *bus = dev_get_drvdata(s->private); - struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - - seq_printf(s, "shm_ipc_ep_in.tx_packet_count(%zu)\n", - priv->shm_ipc_ep_in.tx_packet_count); - seq_printf(s, "shm_ipc_ep_in.rx_packet_count(%zu)\n", - priv->shm_ipc_ep_in.rx_packet_count); - seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n", - priv->shm_ipc_ep_out.tx_timeout_count); - seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n", - priv->shm_ipc_ep_out.rx_packet_count); + struct qtnf_pcie_bus_priv *priv = (void *)data; - return 0; + qtnf_pcie_data_tx_reclaim(priv); + qtnf_en_txdone_irq(priv); } static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -1256,10 +1267,8 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) bus = devm_kzalloc(&pdev->dev, sizeof(*bus) + sizeof(*pcie_priv), GFP_KERNEL); - if (!bus) { - ret = -ENOMEM; - goto err_init; - } + if (!bus) + return -ENOMEM; pcie_priv = get_bus_priv(bus); @@ -1270,7 +1279,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcie_priv->pdev = pdev; strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME); - init_completion(&bus->request_firmware_complete); + init_completion(&bus->firmware_init_complete); mutex_init(&bus->bus_lock); spin_lock_init(&pcie_priv->tx0_lock); spin_lock_init(&pcie_priv->irq_lock); @@ -1286,11 +1295,18 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcie_priv->tx_reclaim_done = 0; pcie_priv->tx_reclaim_req = 0; + tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn, + (unsigned long)pcie_priv); + + init_dummy_netdev(&bus->mux_dev); + netif_napi_add(&bus->mux_dev, &bus->mux_napi, + qtnf_rx_poll, 10); + pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PEARL_PCIE"); if (!pcie_priv->workqueue) { pr_err("failed to alloc bus workqueue\n"); ret = -ENODEV; - goto err_priv; + goto err_init; } if (!pci_is_pcie(pdev)) { @@ -1320,12 +1336,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) } pci_set_master(pdev); - - ret = qtnf_pcie_init_irq(pcie_priv); - if (ret < 0) { - pr_err("irq init failed\n"); - goto err_base; - } + qtnf_pcie_init_irq(pcie_priv); ret = qtnf_pcie_init_memory(pcie_priv); if (ret < 0) { @@ -1344,7 +1355,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = qtnf_pcie_init_xfer(pcie_priv); if (ret) { pr_err("PCIE xfer init failed\n"); - goto err_base; + goto err_ipc; } /* init default irq settings */ @@ -1360,58 +1371,25 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_xfer; } - tasklet_init(&pcie_priv->reclaim_tq, qtnf_reclaim_tasklet_fn, - (unsigned long)pcie_priv); - init_dummy_netdev(&bus->mux_dev); - netif_napi_add(&bus->mux_dev, &bus->mux_napi, - qtnf_rx_poll, 10); - - ret = qtnf_bringup_fw(bus); - if (ret < 0) - goto err_bringup_fw; - else if (ret) - wait_for_completion(&bus->request_firmware_complete); - - if (bus->fw_state != QTNF_FW_STATE_FW_DNLD_DONE) { - pr_err("failed to start FW\n"); - goto err_bringup_fw; - } - - if (qtnf_poll_state(&pcie_priv->bda->bda_ep_state, QTN_EP_FW_QLINK_DONE, - QTN_FW_QLINK_TIMEOUT_MS)) { - pr_err("FW runtime failure\n"); - goto err_bringup_fw; - } - - ret = qtnf_core_attach(bus); - if (ret) { - pr_err("failed to attach core\n"); - goto err_bringup_fw; - } - - qtnf_debugfs_init(bus, DRV_NAME); - qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); - qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); - qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); - qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); - qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); + qtnf_bringup_fw_async(bus); return 0; -err_bringup_fw: - netif_napi_del(&bus->mux_napi); - err_xfer: qtnf_free_xfer_buffers(pcie_priv); +err_ipc: + qtnf_pcie_free_shm_ipc(pcie_priv); + err_base: flush_workqueue(pcie_priv->workqueue); destroy_workqueue(pcie_priv->workqueue); + netif_napi_del(&bus->mux_napi); -err_priv: +err_init: + tasklet_kill(&pcie_priv->reclaim_tq); pci_set_drvdata(pdev, NULL); -err_init: return ret; } @@ -1424,11 +1402,14 @@ static void qtnf_pcie_remove(struct pci_dev *pdev) if (!bus) return; + wait_for_completion(&bus->firmware_init_complete); + + if (bus->fw_state == QTNF_FW_STATE_ACTIVE) + qtnf_core_detach(bus); + priv = get_bus_priv(bus); - qtnf_core_detach(bus); netif_napi_del(&bus->mux_napi); - flush_workqueue(priv->workqueue); destroy_workqueue(priv->workqueue); tasklet_kill(&priv->reclaim_tq);