From patchwork Thu Dec 11 12:26:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 5475681 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 399A9BEEBA for ; Thu, 11 Dec 2014 12:27:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6969E20115 for ; Thu, 11 Dec 2014 12:27:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 751D620173 for ; Thu, 11 Dec 2014 12:27:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933434AbaLKM10 (ORCPT ); Thu, 11 Dec 2014 07:27:26 -0500 Received: from mezzanine.sirena.org.uk ([106.187.55.193]:55537 "EHLO mezzanine.sirena.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933471AbaLKM1Y (ORCPT ); Thu, 11 Dec 2014 07:27:24 -0500 Received: from cpc11-sgyl31-2-0-cust672.sgyl.cable.virginm.net ([94.175.94.161] helo=debutante) by mezzanine.sirena.org.uk with esmtpsa (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1Xz2pW-0002Oo-TK; Thu, 11 Dec 2014 12:26:51 +0000 Received: from broonie by debutante with local (Exim 4.84) (envelope-from ) id 1Xz2pS-00010l-PC; Thu, 11 Dec 2014 12:26:46 +0000 From: Mark Brown To: linux-spi@vger.kernel.org Cc: Mark Brown Date: Thu, 11 Dec 2014 12:26:42 +0000 Message-Id: <1418300802-3803-4-git-send-email-broonie@kernel.org> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1418300802-3803-1-git-send-email-broonie@kernel.org> References: <1418300802-3803-1-git-send-email-broonie@kernel.org> X-SA-Exim-Connect-IP: 94.175.94.161 X-SA-Exim-Mail-From: broonie@sirena.org.uk X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Subject: [PATCH 4/4] spi: Only idle the message pump in the worker kthread X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:24:06 +0000) X-SA-Exim-Scanned: Yes (on mezzanine.sirena.org.uk) Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In order to avoid the situation where the kthread is waiting for another context to make the hardware idle let the message pump know if it's being called from the worker thread context and if it isn't then defer to the worker thread instead of idling the hardware immediately. This will ensure that if this situation happens we block rather than busy waiting. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e1bf2579b9c0..3ac188fc36f5 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -875,8 +875,9 @@ void spi_finalize_current_transfer(struct spi_master *master) EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); /** - * spi_pump_messages - kthread work function which processes spi message queue - * @work: pointer to kthread work struct contained in the master struct + * __spi_pump_messages - function which processes spi message queue + * @master: master to process queue for + * @in_kthread: true if we are in the context of the message pump thread * * This function checks if there is any spi message in the queue that * needs processing and if so call out to the driver to initialize hardware @@ -886,10 +887,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); * inside spi_sync(); the queue extraction handling at the top of the * function should deal with this safely. */ -static void spi_pump_messages(struct kthread_work *work) +static void __spi_pump_messages(struct spi_master *master, bool in_kthread) { - struct spi_master *master = - container_of(work, struct spi_master, pump_messages); unsigned long flags; bool was_busy = false; int ret; @@ -916,6 +915,15 @@ static void spi_pump_messages(struct kthread_work *work) spin_unlock_irqrestore(&master->queue_lock, flags); return; } + + /* Only do teardown in the thread */ + if (!in_kthread) { + queue_kthread_work(&master->kworker, + &master->pump_messages); + spin_unlock_irqrestore(&master->queue_lock, flags); + return; + } + master->busy = false; master->idling = true; spin_unlock_irqrestore(&master->queue_lock, flags); @@ -1004,6 +1012,18 @@ static void spi_pump_messages(struct kthread_work *work) } } +/** + * spi_pump_messages - kthread work function which processes spi message queue + * @work: pointer to kthread work struct contained in the master struct + */ +static void spi_pump_messages(struct kthread_work *work) +{ + struct spi_master *master = + container_of(work, struct spi_master, pump_messages); + + __spi_pump_messages(master, true); +} + static int spi_init_queue(struct spi_master *master) { struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; @@ -2163,7 +2183,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, * can. */ if (master->transfer == spi_queued_transfer) - spi_pump_messages(&master->pump_messages); + __spi_pump_messages(master, false); wait_for_completion(&done); status = message->status;