From patchwork Sat Sep 26 15:06:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 259153 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=-14.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,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 D8318C4727E for ; Sat, 26 Sep 2020 15:07:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9F2F52184D for ; Sat, 26 Sep 2020 15:07:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1601132824; bh=iYGKTY5SXpEb5xniCe3b2ZAzCFOv4PNzH302wFjldM0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=tHMyd8VmX6bA35dO8BnD3ltYpj5J+oQqEG0nWX8XWWmnyv/4+FOnK+zFFoafzwEwF QMviUOPhllrmbBcYL1uM9zjGXnwB0ptHD96uscoL/9Ua9FrFUZlYHTMZUvCUjqDIRc TyVbwBoDZs5kba6zw5Bs4E3DT+vBgEwcNhMi46w8= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729699AbgIZPHD (ORCPT ); Sat, 26 Sep 2020 11:07:03 -0400 Received: from mail.kernel.org ([198.145.29.99]:46178 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729510AbgIZPHD (ORCPT ); Sat, 26 Sep 2020 11:07:03 -0400 Received: from localhost.localdomain (unknown [151.66.98.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6D8412184D; Sat, 26 Sep 2020 15:07:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1601132822; bh=iYGKTY5SXpEb5xniCe3b2ZAzCFOv4PNzH302wFjldM0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ox8ecVSkXOKUXbVRnV5R0l0DY59Nc26hV8UK1Jv4YyDLL3/OcdaOEa782kzXP3X4n 33iSswQqDRWJOBYJ0f3CqWGt+u54N4GfTpGRvafJMazhVMvbY2UlFT39gbdlrUoZeZ JVCi1m7N1u3CYYm7U/EouVfU5pk41Hdq9/OrsEJE= From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com Subject: [PATCH 2/4] mt76: mt7663s: convert txrx_work to mt76_worker Date: Sat, 26 Sep 2020 17:06:23 +0200 Message-Id: <0cbaf58638ec4bfa0fe5e0baae30fcb594f158b6.1601132347.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org In order to improve driver throughput, convert txrx_work to mt76 worker threads APIs. Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- .../net/wireless/mediatek/mt76/mt7615/sdio.c | 19 +++++++-- .../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 41 +++++++++---------- drivers/net/wireless/mediatek/mt76/sdio.c | 5 ++- 5 files changed, 41 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 243cb89c0a92..e47696e5d3f0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -447,7 +447,7 @@ struct mt76_usb { struct mt76_sdio { struct workqueue_struct *txrx_wq; - struct work_struct txrx_work; + struct mt76_worker txrx_worker; struct work_struct status_work; struct work_struct net_work; struct work_struct stat_work; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 11b4caa5cb69..716956b58c13 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -681,7 +681,7 @@ int mt7663u_mcu_init(struct mt7615_dev *dev); /* sdio */ u32 mt7663s_read_pcr(struct mt7615_dev *dev); int mt7663s_mcu_init(struct mt7615_dev *dev); -void mt7663s_txrx_work(struct work_struct *work); +void mt7663s_txrx_worker(struct mt76_worker *w); void mt7663s_rx_work(struct work_struct *work); void mt7663s_sdio_irq(struct sdio_func *func); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index ad7e422ea52e..6f8adba2a78b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -368,8 +368,6 @@ static int mt7663s_probe(struct sdio_func *func, if (ret < 0) goto err_free; - INIT_WORK(&mdev->sdio.txrx_work, mt7663s_txrx_work); - ret = mt7663s_hw_init(dev, func); if (ret) goto err_deinit; @@ -400,6 +398,13 @@ static int mt7663s_probe(struct sdio_func *func, if (ret) goto err_deinit; + ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker, + mt7663s_txrx_worker, "sdio-txrx"); + if (ret) + goto err_deinit; + + sched_set_fifo_low(mdev->sdio.txrx_worker.task); + ret = mt7663_usb_sdio_register_device(dev); if (ret) goto err_deinit; @@ -431,6 +436,7 @@ static int mt7663s_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct mt7615_dev *mdev = sdio_get_drvdata(func); + int err; if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) && mt7615_firmware_offload(mdev)) { @@ -443,9 +449,14 @@ static int mt7663s_suspend(struct device *dev) sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + err = mt7615_mcu_set_fw_ctrl(mdev); + if (err) + return err; + + mt76_worker_disable(&mdev->mt76.sdio.txrx_worker); mt76s_stop_txrx(&mdev->mt76); - return mt7615_mcu_set_fw_ctrl(mdev); + return 0; } static int mt7663s_resume(struct device *dev) @@ -454,6 +465,8 @@ static int mt7663s_resume(struct device *dev) struct mt7615_dev *mdev = sdio_get_drvdata(func); int err; + mt76_worker_enable(&mdev->mt76.sdio.txrx_worker); + err = mt7615_mcu_set_drv_ctrl(mdev); if (err) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 1194df0405ed..10ed211d7d11 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -286,34 +286,33 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid) } mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz); + queue_work(sdio->txrx_wq, &sdio->status_work); + return nframes; } -void mt7663s_txrx_work(struct work_struct *work) +void mt7663s_txrx_worker(struct mt76_worker *w) { - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - txrx_work); + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + txrx_worker); struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i, nframes = 0; - - /* tx */ - for (i = 0; i < MT_TXQ_MCU_WA; i++) { - int ret; - - ret = mt7663s_tx_run_queue(dev, i); - if (ret < 0) - break; + int i, nframes, ret; - nframes += ret; - } - - /* rx */ - nframes += mt7663s_rx_handler(dev); + do { + nframes = 0; - if (nframes) - queue_work(sdio->txrx_wq, &sdio->txrx_work); + /* tx */ + for (i = 0; i < MT_TXQ_MCU_WA; i++) { + ret = mt7663s_tx_run_queue(dev, i); + if (ret > 0) + nframes += ret; + } - queue_work(sdio->txrx_wq, &sdio->status_work); + /* rx */ + ret = mt7663s_rx_handler(dev); + if (ret > 0) + nframes += ret; + } while (nframes > 0); } void mt7663s_sdio_irq(struct sdio_func *func) @@ -324,5 +323,5 @@ void mt7663s_sdio_irq(struct sdio_func *func) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.phy.state)) return; - queue_work(sdio->txrx_wq, &sdio->txrx_work); + mt76_worker_schedule(&sdio->txrx_worker); } diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 6eb75ffa9e0f..37e05ec40e1d 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -66,7 +66,6 @@ void mt76s_stop_txrx(struct mt76_dev *dev) { struct mt76_sdio *sdio = &dev->sdio; - cancel_work_sync(&sdio->txrx_work); cancel_work_sync(&sdio->status_work); cancel_work_sync(&sdio->net_work); cancel_work_sync(&sdio->stat_work); @@ -256,7 +255,7 @@ static void mt76s_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) { struct mt76_sdio *sdio = &dev->sdio; - queue_work(sdio->txrx_wq, &sdio->txrx_work); + mt76_worker_schedule(&sdio->txrx_worker); } static const struct mt76_queue_ops sdio_queue_ops = { @@ -303,6 +302,8 @@ void mt76s_deinit(struct mt76_dev *dev) struct mt76_sdio *sdio = &dev->sdio; int i; + mt76_worker_teardown(&sdio->txrx_worker); + mt76s_stop_txrx(dev); if (sdio->txrx_wq) { destroy_workqueue(sdio->txrx_wq); From patchwork Sat Sep 26 15:06:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 259152 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=-14.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,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 06F4BC4741F for ; Sat, 26 Sep 2020 15:07:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C40B0208FE for ; Sat, 26 Sep 2020 15:07:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1601132827; bh=PST2CSG6OuX8NF85bb5jg8MAh/zFi9LLeymYi/EKT5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=aQ9N2GgyRHyugg5I1QtjJtgpF2o1xzDRIAwLl+OLAKt+TK5UiShRlpkGBfa2AT9Ys 3kvcLouas/Ua3kDmTWgld57B9n4KZ8tE2/XZsfPeTZmhPB3I/UjZkylcNenZ6ImYVx QrzpkNWZ0oqBwTvVHvYbOg2CSoCEIDca9PiKaxYQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729734AbgIZPHH (ORCPT ); Sat, 26 Sep 2020 11:07:07 -0400 Received: from mail.kernel.org ([198.145.29.99]:46202 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729527AbgIZPHG (ORCPT ); Sat, 26 Sep 2020 11:07:06 -0400 Received: from localhost.localdomain (unknown [151.66.98.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id F27062184D; Sat, 26 Sep 2020 15:07:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1601132825; bh=PST2CSG6OuX8NF85bb5jg8MAh/zFi9LLeymYi/EKT5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c81qzyyWuchi1ug4Zg3Tv/GczNoIbPYA7KfQ6TAXekKRijtWfgA0ZFiSWrIZS0Cie vbGsyLrENO4vWBD4CERn6Z9IdGH2qi8vEK/XwC4k50Lbz9ySauah1YOgt1a3TMc1bx zYlJJqhHCxqwI0XYhotavPhaXEojqj7M0P/Wpc+A= From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com Subject: [PATCH 4/4] mt76: sdio: convert {status/net}_work to mt76_worker Date: Sat, 26 Sep 2020 17:06:25 +0200 Message-Id: X-Mailer: git-send-email 2.26.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org In order to improve driver throughput, convert status_work and net_work to mt76 worker APIs. Remove txrx_wq sdio workqueue since it is no longer used Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt76.h | 8 +- .../net/wireless/mediatek/mt76/mt7615/sdio.c | 27 ++-- .../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 6 +- drivers/net/wireless/mediatek/mt76/sdio.c | 124 +++++++++--------- 4 files changed, 87 insertions(+), 78 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e47696e5d3f0..6bb162a2cdd3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -445,11 +445,10 @@ struct mt76_usb { #define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE) struct mt76_sdio { - struct workqueue_struct *txrx_wq; - struct mt76_worker txrx_worker; - struct work_struct status_work; - struct work_struct net_work; + struct mt76_worker status_worker; + struct mt76_worker net_worker; + struct work_struct stat_work; u8 *xmit_buf[MT_TXQ_MCU_WA]; @@ -1059,7 +1058,6 @@ void mt76u_queues_deinit(struct mt76_dev *dev); int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, const struct mt76_bus_ops *bus_ops); int mt76s_alloc_queues(struct mt76_dev *dev); -void mt76s_stop_txrx(struct mt76_dev *dev); void mt76s_deinit(struct mt76_dev *dev); struct sk_buff * diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c index 6f8adba2a78b..a3718c501eb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c @@ -366,11 +366,11 @@ static int mt7663s_probe(struct sdio_func *func, ret = mt76s_init(mdev, func, &mt7663s_ops); if (ret < 0) - goto err_free; + goto error; ret = mt7663s_hw_init(dev, func); if (ret) - goto err_deinit; + goto error; mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); @@ -381,7 +381,7 @@ static int mt7663s_probe(struct sdio_func *func, GFP_KERNEL); if (!mdev->sdio.intr_data) { ret = -ENOMEM; - goto err_deinit; + goto error; } for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) { @@ -390,30 +390,29 @@ static int mt7663s_probe(struct sdio_func *func, GFP_KERNEL); if (!mdev->sdio.xmit_buf[i]) { ret = -ENOMEM; - goto err_deinit; + goto error; } } ret = mt76s_alloc_queues(&dev->mt76); if (ret) - goto err_deinit; + goto error; ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker, mt7663s_txrx_worker, "sdio-txrx"); if (ret) - goto err_deinit; + goto error; sched_set_fifo_low(mdev->sdio.txrx_worker.task); ret = mt7663_usb_sdio_register_device(dev); if (ret) - goto err_deinit; + goto error; return 0; -err_deinit: +error: mt76s_deinit(&dev->mt76); -err_free: mt76_free_device(&dev->mt76); return ret; @@ -454,7 +453,13 @@ static int mt7663s_suspend(struct device *dev) return err; mt76_worker_disable(&mdev->mt76.sdio.txrx_worker); - mt76s_stop_txrx(&mdev->mt76); + mt76_worker_disable(&mdev->mt76.sdio.status_worker); + mt76_worker_disable(&mdev->mt76.sdio.net_worker); + + cancel_work_sync(&mdev->mt76.sdio.stat_work); + clear_bit(MT76_READING_STATS, &mdev->mphy.state); + + mt76_tx_status_check(&mdev->mt76, NULL, true); return 0; } @@ -466,6 +471,8 @@ static int mt7663s_resume(struct device *dev) int err; mt76_worker_enable(&mdev->mt76.sdio.txrx_worker); + mt76_worker_enable(&mdev->mt76.sdio.status_worker); + mt76_worker_enable(&mdev->mt76.sdio.net_worker); err = mt7615_mcu_set_drv_ctrl(mdev); if (err) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index d8f9148fe777..a4969380c860 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -150,7 +150,7 @@ static int mt7663s_rx_handler(struct mt76_dev *dev) if (intr->isr & WHIER_RX0_DONE_INT_EN) { ret = mt7663s_rx_run_queue(dev, 0, intr); if (ret > 0) { - queue_work(sdio->txrx_wq, &sdio->net_work); + mt76_worker_schedule(&sdio->net_worker); nframes += ret; } } @@ -158,7 +158,7 @@ static int mt7663s_rx_handler(struct mt76_dev *dev) if (intr->isr & WHIER_RX1_DONE_INT_EN) { ret = mt7663s_rx_run_queue(dev, 1, intr); if (ret > 0) { - queue_work(sdio->txrx_wq, &sdio->net_work); + mt76_worker_schedule(&sdio->net_worker); nframes += ret; } } @@ -269,7 +269,7 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid) } mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz); - queue_work(sdio->txrx_wq, &sdio->status_work); + mt76_worker_schedule(&sdio->status_worker); return nframes; } diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c index 37e05ec40e1d..41e832b11199 100644 --- a/drivers/net/wireless/mediatek/mt76/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/sdio.c @@ -62,19 +62,6 @@ static int mt76s_alloc_tx(struct mt76_dev *dev) return 0; } -void mt76s_stop_txrx(struct mt76_dev *dev) -{ - struct mt76_sdio *sdio = &dev->sdio; - - cancel_work_sync(&sdio->status_work); - cancel_work_sync(&sdio->net_work); - cancel_work_sync(&sdio->stat_work); - clear_bit(MT76_READING_STATS, &dev->phy.state); - - mt76_tx_status_check(dev, NULL, true); -} -EXPORT_SYMBOL_GPL(mt76s_stop_txrx); - int mt76s_alloc_queues(struct mt76_dev *dev) { int err; @@ -129,10 +116,32 @@ mt76s_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) return nframes; } -static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) +static void mt76s_net_worker(struct mt76_worker *w) +{ + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + net_worker); + struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); + int i, nframes; + + do { + nframes = 0; + + local_bh_disable(); + rcu_read_lock(); + + mt76_for_each_q_rx(dev, i) + nframes += mt76s_process_rx_queue(dev, &dev->q_rx[i]); + + rcu_read_unlock(); + local_bh_enable(); + } while (nframes > 0); +} + +static int mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) { struct mt76_queue *q = dev->q_tx[qid]; struct mt76_queue_entry entry; + int nframes = 0; bool wake; while (q->queued > 0) { @@ -148,6 +157,7 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) } mt76_queue_tx_complete(dev, q, &entry); + nframes++; } wake = q->stopped && q->queued < q->ndesc - 8; @@ -158,12 +168,32 @@ static void mt76s_process_tx_queue(struct mt76_dev *dev, enum mt76_txq_id qid) wake_up(&dev->tx_wait); if (qid == MT_TXQ_MCU) - return; + goto out; mt76_txq_schedule(&dev->phy, qid); if (wake) ieee80211_wake_queue(dev->hw, qid); +out: + return nframes; +} + +static void mt76s_status_worker(struct mt76_worker *w) +{ + struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, + status_worker); + struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); + int i, nframes; + + do { + nframes = 0; + for (i = 0; i < MT_TXQ_MCU_WA; i++) + nframes += mt76s_process_tx_queue(dev, i); + + if (dev->drv->tx_status_data && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) + queue_work(dev->wq, &dev->sdio.stat_work); + } while (nframes > 0); } static void mt76s_tx_status_data(struct work_struct *work) @@ -264,51 +294,19 @@ static const struct mt76_queue_ops sdio_queue_ops = { .tx_queue_skb_raw = mt76s_tx_queue_skb_raw, }; -static void mt76s_tx_work(struct work_struct *work) -{ - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - status_work); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i; - - for (i = 0; i < MT_TXQ_MCU_WA; i++) - mt76s_process_tx_queue(dev, i); - - if (dev->drv->tx_status_data && - !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) - queue_work(dev->wq, &dev->sdio.stat_work); -} - -static void mt76s_rx_work(struct work_struct *work) -{ - struct mt76_sdio *sdio = container_of(work, struct mt76_sdio, - net_work); - struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio); - int i; - - /* rx processing */ - local_bh_disable(); - rcu_read_lock(); - - mt76_for_each_q_rx(dev, i) - mt76s_process_rx_queue(dev, &dev->q_rx[i]); - - rcu_read_unlock(); - local_bh_enable(); -} - void mt76s_deinit(struct mt76_dev *dev) { struct mt76_sdio *sdio = &dev->sdio; int i; mt76_worker_teardown(&sdio->txrx_worker); + mt76_worker_teardown(&sdio->status_worker); + mt76_worker_teardown(&sdio->net_worker); - mt76s_stop_txrx(dev); - if (sdio->txrx_wq) { - destroy_workqueue(sdio->txrx_wq); - sdio->txrx_wq = NULL; - } + cancel_work_sync(&sdio->stat_work); + clear_bit(MT76_READING_STATS, &dev->phy.state); + + mt76_tx_status_check(dev, NULL, true); sdio_claim_host(sdio->func); sdio_release_irq(sdio->func); @@ -335,16 +333,22 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func, const struct mt76_bus_ops *bus_ops) { struct mt76_sdio *sdio = &dev->sdio; + int err; - sdio->txrx_wq = alloc_workqueue("mt76s_txrx_wq", - WQ_UNBOUND | WQ_HIGHPRI, - WQ_UNBOUND_MAX_ACTIVE); - if (!sdio->txrx_wq) - return -ENOMEM; + err = mt76_worker_setup(dev->hw, &sdio->status_worker, + mt76s_status_worker, "sdio-status"); + if (err) + return err; + + err = mt76_worker_setup(dev->hw, &sdio->net_worker, mt76s_net_worker, + "sdio-net"); + if (err) + return err; + + sched_set_fifo_low(sdio->status_worker.task); + sched_set_fifo_low(sdio->net_worker.task); INIT_WORK(&sdio->stat_work, mt76s_tx_status_data); - INIT_WORK(&sdio->status_work, mt76s_tx_work); - INIT_WORK(&sdio->net_work, mt76s_rx_work); mutex_init(&sdio->sched.lock); dev->queue_ops = &sdio_queue_ops;