From patchwork Tue Oct 14 16:33:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 5080951 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 217899F295 for ; Tue, 14 Oct 2014 16:33:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9245420127 for ; Tue, 14 Oct 2014 16:33:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E597A20154 for ; Tue, 14 Oct 2014 16:33:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754661AbaJNQdT (ORCPT ); Tue, 14 Oct 2014 12:33:19 -0400 Received: from mail-pd0-f180.google.com ([209.85.192.180]:48070 "EHLO mail-pd0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754323AbaJNQdS (ORCPT ); Tue, 14 Oct 2014 12:33:18 -0400 Received: by mail-pd0-f180.google.com with SMTP id fp1so7851186pdb.11 for ; Tue, 14 Oct 2014 09:33:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id; bh=826llYD7SEk12BFxUZWcc70LN1YrrvJiCf7NskI/oBc=; b=a4CjQmXFK2IBpH5xsXRa5vudSWG2ebvuwfOw9HzkxD7DPixZcAKgEP08o2+jk0H6Zl Ud6uA8w0Cc1HyJiHeDYwq/uTs6Sps1I6xXtDX78fTvUinzkK3qYgYlrHKtEeYVxvmpjP WgvpOskJN3DqQcPXT3nUBroTEM3ML33Tt4G84= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=826llYD7SEk12BFxUZWcc70LN1YrrvJiCf7NskI/oBc=; b=JJApn0Q0Q32d+6Xi8fHiTKPk+opxQafOn7a1XlyE4ZeZvs4cpwjsS5u4jGje5Ba01A 9WuNI7ygC6jjBgiAVciiHBoSC63QDKBBoKcwpLjemNAIEcGWTNmKFoRh0q0oOOnxRqCG +OiUQibJp4U+u2/WLbkgQcL8bBCimOEjapcZ0OYNQ/Bss5+xpn8aj74QOZQPEh2erugY I8ppKhbnnsbJx3l7WFPWesP11Pmy2+wD4ruusdv3FdLxknvCpSkdqu0E68Hi9/Sv5jsR KN2UBdBav0BKZY/eXni0RrSk2BSPyut+5IKl8vM3FST1l9RuVZ0S7pI5ihYPZVwoo+bv Qy/Q== X-Gm-Message-State: ALoCoQnfPiZacwRWGbjK6NC2erm8xOBs4oD5FBdR0QsAR3Qh8jhn5IWrM6FeUbGrL1hcLj3wBX4r X-Received: by 10.66.252.193 with SMTP id zu1mr3230440pac.153.1413304397245; Tue, 14 Oct 2014 09:33:17 -0700 (PDT) Received: from tictac.mtv.corp.google.com (tictac.mtv.corp.google.com [172.22.162.15]) by mx.google.com with ESMTPSA id yk3sm14148378pbb.60.2014.10.14.09.33.15 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 14 Oct 2014 09:33:16 -0700 (PDT) From: Doug Anderson To: Ulf Hansson , Seungwon Jeon , Jaehoon Chung Cc: Addy Ke , Sonny Rao , Alim Akhtar , Andrew Bresticker , Doug Anderson , chris@printf.net, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] mmc: dw_mmc: Remove old card detect infrastructure Date: Tue, 14 Oct 2014 09:33:09 -0700 Message-Id: <1413304389-6580-1-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.1.0.rc2.206.gedb03e5 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The dw_mmc driver had a bunch of code that ran whenever a card was ejected and inserted. However, this code was old and crufty and should be removed. Some evidence that it's really not needed: 1. Is is supposed to be legal to use 'cd-gpio' on dw_mmc instead of using the built-in card detect mechanism. The 'cd-gpio' code doesn't run any of the crufty old code but yet still works. 2. While looking at this, I realized that my old change (369ac86 mmc: dw_mmc: don't queue up a card detect at slot startup) actually castrated the old code a little bit already and nobody noticed. Specifically "last_detect_state" was left as 0 at bootup. That means that on the first card removal none of the crufty code ran. 3. I can run "while true; do dd if=/dev/mmcblk1 of=/dev/null; done" while ejecting and inserting an SD Card and the world doesn't explode. If some of the crufty old code is actually needed, we should justify it and also put it in some place where it will be run even with "cd-gpio". Note that in my case I'm using the "cd-gpio" mechanism but for various reasons the hardware triggers a dw_mmc "card detect" at bootup. That was actually causing a real bug. The card detect workqueue was running while the system was trying to enumerate the card. The "present != slot->last_detect_state" triggered and we were doing all kinds of crazy stuff and messing up enumeration. The new mechanism of just asking the core to check the card is much safer and then the bogus interrupt doesn't hurt. Signed-off-by: Doug Anderson Tested-by: Jaehoon Chung Acked-by: Jaehoon Chung Tested-by: alim.akhtar --- drivers/mmc/host/dw_mmc.c | 121 ++++++++------------------------------------- drivers/mmc/host/dw_mmc.h | 2 - include/linux/mmc/dw_mmc.h | 2 - 3 files changed, 20 insertions(+), 105 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 69f0cc6..6a86495 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -1954,6 +1953,23 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) tasklet_schedule(&host->tasklet); } +static void dw_mci_handle_cd(struct dw_mci *host) +{ + int i; + + for (i = 0; i < host->num_slots; i++) { + struct dw_mci_slot *slot = host->slot[i]; + + if (!slot) + continue; + + if (slot->mmc->ops->card_event) + slot->mmc->ops->card_event(slot->mmc); + mmc_detect_change(slot->mmc, + msecs_to_jiffies(host->pdata->detect_delay_ms)); + } +} + static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; @@ -2029,7 +2045,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending & SDMMC_INT_CD) { mci_writel(host, RINTSTS, SDMMC_INT_CD); - queue_work(host->card_workqueue, &host->card_work); + dw_mci_handle_cd(host); } /* Handle SDIO Interrupts */ @@ -2056,88 +2072,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void dw_mci_work_routine_card(struct work_struct *work) -{ - struct dw_mci *host = container_of(work, struct dw_mci, card_work); - int i; - - for (i = 0; i < host->num_slots; i++) { - struct dw_mci_slot *slot = host->slot[i]; - struct mmc_host *mmc = slot->mmc; - struct mmc_request *mrq; - int present; - - present = dw_mci_get_cd(mmc); - while (present != slot->last_detect_state) { - dev_dbg(&slot->mmc->class_dev, "card %s\n", - present ? "inserted" : "removed"); - - spin_lock_bh(&host->lock); - - /* Card change detected */ - slot->last_detect_state = present; - - /* Clean up queue if present */ - mrq = slot->mrq; - if (mrq) { - if (mrq == host->mrq) { - host->data = NULL; - host->cmd = NULL; - - switch (host->state) { - case STATE_IDLE: - case STATE_WAITING_CMD11_DONE: - break; - case STATE_SENDING_CMD11: - case STATE_SENDING_CMD: - mrq->cmd->error = -ENOMEDIUM; - if (!mrq->data) - break; - /* fall through */ - case STATE_SENDING_DATA: - mrq->data->error = -ENOMEDIUM; - dw_mci_stop_dma(host); - break; - case STATE_DATA_BUSY: - case STATE_DATA_ERROR: - if (mrq->data->error == -EINPROGRESS) - mrq->data->error = -ENOMEDIUM; - /* fall through */ - case STATE_SENDING_STOP: - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - break; - } - - dw_mci_request_end(host, mrq); - } else { - list_del(&slot->queue_node); - mrq->cmd->error = -ENOMEDIUM; - if (mrq->data) - mrq->data->error = -ENOMEDIUM; - if (mrq->stop) - mrq->stop->error = -ENOMEDIUM; - - spin_unlock(&host->lock); - mmc_request_done(slot->mmc, mrq); - spin_lock(&host->lock); - } - } - - /* Power down slot */ - if (present == 0) - dw_mci_reset(host); - - spin_unlock_bh(&host->lock); - - present = dw_mci_get_cd(mmc); - } - - mmc_detect_change(slot->mmc, - msecs_to_jiffies(host->pdata->detect_delay_ms)); - } -} - #ifdef CONFIG_OF /* given a slot id, find out the device node representing that slot */ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) @@ -2289,9 +2223,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) dw_mci_init_debugfs(slot); #endif - /* Card initially undetected */ - slot->last_detect_state = 0; - return 0; err_host_allocated: @@ -2672,17 +2603,10 @@ int dw_mci_probe(struct dw_mci *host) host->data_offset = DATA_240A_OFFSET; tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); - host->card_workqueue = alloc_workqueue("dw-mci-card", - WQ_MEM_RECLAIM, 1); - if (!host->card_workqueue) { - ret = -ENOMEM; - goto err_dmaunmap; - } - INIT_WORK(&host->card_work, dw_mci_work_routine_card); ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host); if (ret) - goto err_workqueue; + goto err_dmaunmap; if (host->pdata->num_slots) host->num_slots = host->pdata->num_slots; @@ -2718,7 +2642,7 @@ int dw_mci_probe(struct dw_mci *host) } else { dev_dbg(host->dev, "attempted to initialize %d slots, " "but failed on all\n", host->num_slots); - goto err_workqueue; + goto err_dmaunmap; } if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) @@ -2726,9 +2650,6 @@ int dw_mci_probe(struct dw_mci *host) return 0; -err_workqueue: - destroy_workqueue(host->card_workqueue); - err_dmaunmap: if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); @@ -2762,8 +2683,6 @@ void dw_mci_remove(struct dw_mci *host) mci_writel(host, CLKENA, 0); mci_writel(host, CLKSRC, 0); - destroy_workqueue(host->card_workqueue); - if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 01b99e8..71d4995 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -214,7 +214,6 @@ extern int dw_mci_resume(struct dw_mci *host); * with CONFIG_MMC_CLKGATE. * @flags: Random state bits associated with the slot. * @id: Number of this slot. - * @last_detect_state: Most recently observed card detect state. */ struct dw_mci_slot { struct mmc_host *mmc; @@ -234,7 +233,6 @@ struct dw_mci_slot { #define DW_MMC_CARD_PRESENT 0 #define DW_MMC_CARD_NEED_INIT 1 int id; - int last_detect_state; }; struct dw_mci_tuning_data { diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 0013669..69d0814 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -135,7 +135,6 @@ struct dw_mci { struct mmc_command stop_abort; unsigned int prev_blksz; unsigned char timing; - struct workqueue_struct *card_workqueue; /* DMA interface members*/ int use_dma; @@ -154,7 +153,6 @@ struct dw_mci { u32 stop_cmdr; u32 dir_status; struct tasklet_struct tasklet; - struct work_struct card_work; unsigned long pending_events; unsigned long completed_events; enum dw_mci_state state;