From patchwork Mon Mar 1 19:01:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 83042 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o21J2AYn011674 for ; Mon, 1 Mar 2010 19:02:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751298Ab0CATBu (ORCPT ); Mon, 1 Mar 2010 14:01:50 -0500 Received: from www.tglx.de ([62.245.132.106]:45421 "EHLO www.tglx.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751447Ab0CATBt (ORCPT ); Mon, 1 Mar 2010 14:01:49 -0500 Received: from localhost (www.tglx.de [127.0.0.1]) by www.tglx.de (8.13.8/8.13.8/TGLX-2007100201) with ESMTP id o21J1igl011988 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 1 Mar 2010 20:01:45 +0100 Date: Mon, 1 Mar 2010 20:01:44 +0100 (CET) From: Thomas Gleixner To: LKML cc: linux-omap@vger.kernel.org, linux-mmc@vger.kernel.org Subject: [PATCH] mmc: omap_hsmmc: Fix conditional locking Message-ID: User-Agent: Alpine 2.00 (LFD 1167 2008-08-23) MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.95.1 at www.tglx.de X-Virus-Status: Clean X-Spam-Status: No, score=-1.7 required=5.0 tests=ALL_TRUSTED,AWL autolearn=failed version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on www.tglx.de Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 01 Mar 2010 19:02:10 +0000 (UTC) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4b23225..99a3383 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -468,14 +468,6 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, if (host->use_dma) cmdreg |= DMA_EN; - /* - * In an interrupt context (i.e. STOP command), the spinlock is unlocked - * by the interrupt handler, otherwise (i.e. for a new request) it is - * unlocked here. - */ - if (!in_interrupt()) - spin_unlock_irqrestore(&host->irq_lock, host->flags); - OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); } @@ -506,7 +498,9 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) } host->mrq = NULL; + spin_unlock(&host->irq_lock); mmc_request_done(host->mmc, mrq); + spin_lock(&host->irq_lock); return; } @@ -523,7 +517,9 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) if (!data->stop) { host->mrq = NULL; + spin_unlock(&host->irq_lock); mmc_request_done(host->mmc, data->mrq); + spin_lock(&host->irq_lock); return; } omap_hsmmc_start_command(host, data->stop, NULL); @@ -551,7 +547,9 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) } if ((host->data == NULL && !host->response_busy) || cmd->error) { host->mrq = NULL; + spin_unlock(&host->irq_lock); mmc_request_done(host->mmc, cmd->mrq); + spin_lock(&host->irq_lock); } } @@ -1077,37 +1075,31 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) struct omap_hsmmc_host *host = mmc_priv(mmc); int err; + spin_lock_irqsave(&host->irq_lock, host->flags); /* - * Prevent races with the interrupt handler because of unexpected - * interrupts, but not if we are already in interrupt context i.e. - * retries. + * Protect the card from I/O if there is a possibility + * it can be removed. */ - if (!in_interrupt()) { - spin_lock_irqsave(&host->irq_lock, host->flags); - /* - * Protect the card from I/O if there is a possibility - * it can be removed. - */ - if (host->protect_card) { - if (host->reqs_blocked < 3) { - /* - * Ensure the controller is left in a consistent - * state by resetting the command and data state - * machines. - */ - omap_hsmmc_reset_controller_fsm(host, SRD); - omap_hsmmc_reset_controller_fsm(host, SRC); - host->reqs_blocked += 1; - } - req->cmd->error = -EBADF; - if (req->data) - req->data->error = -EBADF; - spin_unlock_irqrestore(&host->irq_lock, host->flags); - mmc_request_done(mmc, req); - return; - } else if (host->reqs_blocked) - host->reqs_blocked = 0; - } + if (host->protect_card) { + if (host->reqs_blocked < 3) { + /* + * Ensure the controller is left in a consistent + * state by resetting the command and data state + * machines. + */ + omap_hsmmc_reset_controller_fsm(host, SRD); + omap_hsmmc_reset_controller_fsm(host, SRC); + host->reqs_blocked += 1; + } + req->cmd->error = -EBADF; + if (req->data) + req->data->error = -EBADF; + spin_unlock_irqrestore(&host->irq_lock, host->flags); + mmc_request_done(mmc, req); + return; + } else if (host->reqs_blocked) + host->reqs_blocked = 0; + WARN_ON(host->mrq != NULL); host->mrq = req; err = omap_hsmmc_prepare_data(host, req); @@ -1116,13 +1108,13 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = err; host->mrq = NULL; - if (!in_interrupt()) - spin_unlock_irqrestore(&host->irq_lock, host->flags); + spin_unlock_irqrestore(&host->irq_lock, host->flags); mmc_request_done(mmc, req); return; } omap_hsmmc_start_command(host, req->cmd, req->data); + spin_unlock_irqrestore(&host->irq_lock, host->flags); } /* Routine to configure clock values. Exposed API to core */