From patchwork Fri Apr 5 12:40:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 10887333 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2EDAB1390 for ; Fri, 5 Apr 2019 12:41:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 178FB28B76 for ; Fri, 5 Apr 2019 12:41:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1581728B70; Fri, 5 Apr 2019 12:41:57 +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.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 6E4EE28B76 for ; Fri, 5 Apr 2019 12:41:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726730AbfDEMlz (ORCPT ); Fri, 5 Apr 2019 08:41:55 -0400 Received: from mga06.intel.com ([134.134.136.31]:50738 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726027AbfDEMlz (ORCPT ); Fri, 5 Apr 2019 08:41:55 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Apr 2019 05:41:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,312,1549958400"; d="scan'208";a="131733538" Received: from ahunter-desktop.fi.intel.com ([10.237.72.198]) by orsmga008.jf.intel.com with ESMTP; 05 Apr 2019 05:41:52 -0700 From: Adrian Hunter To: Ulf Hansson Cc: Faiz Abbas , kishon@ti.com, zhang.chunyan@linaro.org, linux-mmc Subject: [PATCH 5/5] mmc: sdhci: Remove finish_tasklet Date: Fri, 5 Apr 2019 15:40:20 +0300 Message-Id: <20190405124020.27230-6-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190405124020.27230-1-adrian.hunter@intel.com> References: <20190405124020.27230-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Remove finish_tasklet. Requests that require DMA-unmapping or sdhci_reset are completed either in the IRQ thread or a workqueue if the completion is not initiated by the IRQ. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 37 +++++++++++++++++++++---------------- drivers/mmc/host/sdhci.h | 3 ++- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3317c6a2f0f9..5c82387d53e2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1281,7 +1281,7 @@ static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { __sdhci_finish_mrq(host, mrq); - tasklet_schedule(&host->finish_tasklet); + queue_work(host->complete_wq, &host->complete_work); } static void sdhci_finish_data(struct sdhci_host *host) @@ -2599,7 +2599,7 @@ static const struct mmc_host_ops sdhci_ops = { /*****************************************************************************\ * * - * Tasklets * + * Request done * * * \*****************************************************************************/ @@ -2713,9 +2713,10 @@ static bool sdhci_request_done(struct sdhci_host *host) return false; } -static void sdhci_tasklet_finish(unsigned long param) +static void sdhci_complete_work(struct work_struct *work) { - struct sdhci_host *host = (struct sdhci_host *)param; + struct sdhci_host *host = container_of(work, struct sdhci_host, + complete_work); while (!sdhci_request_done(host)) ; @@ -2761,7 +2762,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) if (host->data) { host->data->error = -ETIMEDOUT; sdhci_finish_data(host); - tasklet_schedule(&host->finish_tasklet); + queue_work(host->complete_wq, &host->complete_work); } else if (host->data_cmd) { host->data_cmd->error = -ETIMEDOUT; sdhci_finish_mrq(host, host->data_cmd->mrq); @@ -3122,7 +3123,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) continue; if (sdhci_defer_done(host, mrq)) { - tasklet_schedule(&host->finish_tasklet); + result = IRQ_WAKE_THREAD; } else { mrqs_done[i] = mrq; host->mrqs_done[i] = NULL; @@ -3152,6 +3153,9 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) unsigned long flags; u32 isr; + while (!sdhci_request_done(host)) + ; + spin_lock_irqsave(&host->lock, flags); isr = host->thread_isr; host->thread_isr = 0; @@ -3173,7 +3177,7 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) spin_unlock_irqrestore(&host->lock, flags); } - return isr ? IRQ_HANDLED : IRQ_NONE; + return IRQ_HANDLED; } /*****************************************************************************\ @@ -4259,14 +4263,15 @@ EXPORT_SYMBOL_GPL(sdhci_cleanup_host); int __sdhci_add_host(struct sdhci_host *host) { + unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; struct mmc_host *mmc = host->mmc; int ret; - /* - * Init tasklets. - */ - tasklet_init(&host->finish_tasklet, - sdhci_tasklet_finish, (unsigned long)host); + host->complete_wq = alloc_workqueue("sdhci", flags, 0); + if (!host->complete_wq) + return -ENOMEM; + + INIT_WORK(&host->complete_work, sdhci_complete_work); timer_setup(&host->timer, sdhci_timeout_timer, 0); timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); @@ -4280,7 +4285,7 @@ int __sdhci_add_host(struct sdhci_host *host) if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); - goto untasklet; + goto unwq; } ret = sdhci_led_register(host); @@ -4313,8 +4318,8 @@ int __sdhci_add_host(struct sdhci_host *host) sdhci_writel(host, 0, SDHCI_INT_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); free_irq(host->irq, host); -untasklet: - tasklet_kill(&host->finish_tasklet); +unwq: + destroy_workqueue(host->complete_wq); return ret; } @@ -4376,7 +4381,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) del_timer_sync(&host->timer); del_timer_sync(&host->data_timer); - tasklet_kill(&host->finish_tasklet); + destroy_workqueue(host->complete_wq); if (!IS_ERR(mmc->supply.vqmmc)) regulator_disable(mmc->supply.vqmmc); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 57bb3e3dca89..d6bcc584c92b 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -560,7 +560,8 @@ struct sdhci_host { unsigned int desc_sz; /* ADMA descriptor size */ - struct tasklet_struct finish_tasklet; /* Tasklet structures */ + struct workqueue_struct *complete_wq; /* Request completion wq */ + struct work_struct complete_work; /* Request completion work */ struct timer_list timer; /* Timer for timeouts */ struct timer_list data_timer; /* Timer for data timeouts */