Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1763528AbYCZUSs (ORCPT ); Wed, 26 Mar 2008 16:18:48 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756903AbYCZUNX (ORCPT ); Wed, 26 Mar 2008 16:13:23 -0400 Received: from smtp.nokia.com ([192.100.122.230]:59818 "EHLO mgw-mx03.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756604AbYCZUNV (ORCPT ); Wed, 26 Mar 2008 16:13:21 -0400 Message-ID: <47EAAD96.6030208@indt.org.br> Date: Wed, 26 Mar 2008 16:09:58 -0400 From: Carlos Aguiar User-Agent: Thunderbird 1.5.0.12 (X11/20070604) MIME-Version: 1.0 To: ext Pierre Ossman CC: Tony Lindgren , linux-kernel@vger.kernel.org Subject: [PATCH 17/18] MMC: OMAP: Start new commands from work queue instead of irq References: <47DAD39C.90405@indt.org.br> <20080324132631.1e0d2125@mjolnir.drzeus.cx> In-Reply-To: <20080324132631.1e0d2125@mjolnir.drzeus.cx> X-Enigmail-Version: 0.94.0.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 26 Mar 2008 20:12:41.0343 (UTC) FILETIME=[BEB758F0:01C88F7D] X-Nokia-AV: Clean Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3893 Lines: 122 From: Jarkko Lavinen Use work queues for starting new commands instead of starting them directly from irq handler. The command scheduling needs to be delayed a bit for some cards which should not be done from an interrupt. Signed-off-by: Jarkko Lavinen --- drivers/mmc/host/omap.c | 48 +++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 19001d3..b28ae3b 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -138,6 +138,11 @@ struct mmc_omap_host { unsigned abort:1; struct timer_list cmd_abort_timer; + struct work_struct slot_release_work; + struct mmc_omap_slot *next_slot; + struct work_struct send_stop_work; + struct mmc_data *stop_data; + unsigned int sg_len; int sg_idx; u16 * buffer; @@ -236,6 +241,21 @@ no_claim: static void mmc_omap_start_request(struct mmc_omap_host *host, struct mmc_request *req); +static void mmc_omap_slot_release_work(struct work_struct *work) +{ + struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, + slot_release_work); + struct mmc_omap_slot *next_slot = host->next_slot; + struct mmc_request *rq; + + host->next_slot = NULL; + mmc_omap_select_slot(next_slot, 1); + + rq = next_slot->mrq; + next_slot->mrq = NULL; + mmc_omap_start_request(host, rq); +} + static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) { struct mmc_omap_host *host = slot->host; @@ -257,21 +277,19 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled) /* Check for any pending requests */ for (i = 0; i < host->nr_slots; i++) { struct mmc_omap_slot *new_slot; - struct mmc_request *rq; if (host->slots[i] == NULL || host->slots[i]->mrq == NULL) continue; + BUG_ON(host->next_slot != NULL); new_slot = host->slots[i]; /* The current slot should not have a request in queue */ BUG_ON(new_slot == host->current_slot); + host->next_slot = new_slot; host->mmc = new_slot->mmc; spin_unlock_irqrestore(&host->slot_lock, flags); - mmc_omap_select_slot(new_slot, 1); - rq = new_slot->mrq; - new_slot->mrq = NULL; - mmc_omap_start_request(host, rq); + schedule_work(&host->slot_release_work); return; } @@ -400,6 +418,20 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data, dma_data_dir); } +static void mmc_omap_send_stop_work(struct work_struct *work) +{ + struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, + send_stop_work); + struct mmc_omap_slot *slot = host->current_slot; + struct mmc_data *data = host->stop_data; + unsigned long tick_ns; + + tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq; + ndelay(8*tick_ns); + + mmc_omap_start_command(host, data->stop); +} + static void mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) { @@ -424,7 +456,8 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) return; } - mmc_omap_start_command(host, data->stop); + host->stop_data = data; + schedule_work(&host->send_stop_work); } static void @@ -1389,6 +1422,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev) goto err_free_mem_region; } + INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); + INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); + INIT_WORK(&host->cmd_abort_work, mmc_omap_abort_command); setup_timer(&host->cmd_abort_timer, mmc_omap_cmd_timer, (unsigned long) host); -- 1.5.3.GIT -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/