From patchwork Tue May 20 22:07:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 4213231 Return-Path: X-Original-To: patchwork-linux-samsung-soc@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 0D8AFBEEAB for ; Tue, 20 May 2014 22:09:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3EE2220320 for ; Tue, 20 May 2014 22:09:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4B7FF2021B for ; Tue, 20 May 2014 22:09:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750832AbaETWIx (ORCPT ); Tue, 20 May 2014 18:08:53 -0400 Received: from mail-pd0-f202.google.com ([209.85.192.202]:49069 "EHLO mail-pd0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750721AbaETWIw (ORCPT ); Tue, 20 May 2014 18:08:52 -0400 Received: by mail-pd0-f202.google.com with SMTP id fp1so143393pdb.5 for ; Tue, 20 May 2014 15:08:51 -0700 (PDT) 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=U709fIeGDXNWOSbAcgT/5JY5HZKZLiZJ00hgZ5zuIUM=; b=XG/+OrgdWA4uK6VczCx03mEvLeEw9kkaGcIreGACHNoeXjpQXOzNZdLVHkJhNBZCS7 40FotJsaf2VEy8fVPs7a6Qbml7nrJTlEWLnR5tme+ZvxGrzkl4RJy2XBIYE+tCRij5Gd AKBIT/q/gDlUbAztQ6xrtaY0xV2EtbNQZTOmNzN/N3xxIe5XubhG2JKlCctGwtjY9uCM zFIuBGIBecMJ352O5nGNm2a2QzU4wLo1IG+3DT8fx7W+CYCSwwHXYy7Orq1yTU7rrWjE 3I5ZLNAP6LdzNYfKUokmo3BvMQDLGeLh2+nThDZvpqucDYZ3wHIZ/ZxGOxebAvnIbhI4 2dfw== X-Gm-Message-State: ALoCoQkhbKfymhXTV6VUn4V0TyXgjw0teyKzqhbY6JwD1NanmKmp+oUhy2MptWzk1u0hyhIJ6/IX X-Received: by 10.68.202.99 with SMTP id kh3mr7109766pbc.8.1400623731459; Tue, 20 May 2014 15:08:51 -0700 (PDT) Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) by gmr-mx.google.com with ESMTPS id c50si1093264yhl.7.2014.05.20.15.08.51 for (version=TLSv1.1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 20 May 2014 15:08:51 -0700 (PDT) Received: from tictac.mtv.corp.google.com (tictac.mtv.corp.google.com [172.22.72.141]) by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 269F65A427D; Tue, 20 May 2014 15:08:51 -0700 (PDT) Received: by tictac.mtv.corp.google.com (Postfix, from userid 121310) id C3E608080B; Tue, 20 May 2014 15:08:50 -0700 (PDT) From: Doug Anderson To: Seungwon Jeon , Jaehoon Chung Cc: Chris Ball , Sonny Rao , Grant Grundler , linux-samsung-soc , Kukjin Kim , sunil joshi , Tomasz Figa , Doug Anderson , Yuvaraj Kumar C D , chris@printf.net, ulf.hansson@linaro.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] mmc: dw_mmc: Make sure we don't get stuck when we get an error Date: Tue, 20 May 2014 15:07:50 -0700 Message-Id: <1400623670-2657-1-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 1.9.1.423.g4596e3a Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. 2. Fix it so that if we detect that we've got an error in the "data busy" state and we're not going to do anything else we end the request and unblock anyone waiting. Signed-off-by: Doug Anderson Signed-off-by: Yuvaraj Kumar C D Acked-by: Seungwon Jeon --- Changes in v2: - Removed TODO - Set cmd to NULL before calling dw_mci_request_end() drivers/mmc/host/dw_mmc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cced599..54ec8b0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1318,6 +1318,14 @@ static void dw_mci_tasklet_func(unsigned long priv) /* fall through */ case STATE_SENDING_DATA: + /* + * We could get a data error and never a transfer + * complete so we'd better check for it here. + * + * Note that we don't really care if we also got a + * transfer complete; stopping the DMA and sending an + * abort won't hurt. + */ if (test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events)) { dw_mci_stop_dma(host); @@ -1331,7 +1339,29 @@ static void dw_mci_tasklet_func(unsigned long priv) break; set_bit(EVENT_XFER_COMPLETE, &host->completed_events); + + /* + * Handle an EVENT_DATA_ERROR that might have shown up + * before the transfer completed. This might not have + * been caught by the check above because the interrupt + * could have gone off between the previous check and + * the check for transfer complete. + * + * Technically this ought not be needed assuming we + * get a DATA_COMPLETE eventually (we'll notice the + * error and end the request), but it shouldn't hurt. + * + * This has the advantage of sending the stop command. + */ + if (test_and_clear_bit(EVENT_DATA_ERROR, + &host->pending_events)) { + dw_mci_stop_dma(host); + send_stop_abort(host, data); + state = STATE_DATA_ERROR; + break; + } prev_state = state = STATE_DATA_BUSY; + /* fall through */ case STATE_DATA_BUSY: @@ -1354,6 +1384,22 @@ static void dw_mci_tasklet_func(unsigned long priv) /* stop command for open-ended transfer*/ if (data->stop) send_stop_abort(host, data); + } else { + /* + * If we don't have a command complete now we'll + * never get one since we just reset everything; + * better end the request. + * + * If we do have a command complete we'll fall + * through to the SENDING_STOP command and + * everything will be peachy keen. + */ + if (!test_bit(EVENT_CMD_COMPLETE, + &host->pending_events)) { + host->cmd = NULL; + dw_mci_request_end(host, mrq); + goto unlock; + } } /*