From patchwork Thu Mar 27 06:18:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yuvaraj CD X-Patchwork-Id: 3896511 Return-Path: X-Original-To: patchwork-linux-samsung-soc@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 00C499F334 for ; Thu, 27 Mar 2014 06:19:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1392220122 for ; Thu, 27 Mar 2014 06:19:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1CF4C20149 for ; Thu, 27 Mar 2014 06:19:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753523AbaC0GTC (ORCPT ); Thu, 27 Mar 2014 02:19:02 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:38889 "EHLO mail-pb0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750777AbaC0GTB (ORCPT ); Thu, 27 Mar 2014 02:19:01 -0400 Received: by mail-pb0-f45.google.com with SMTP id uo5so3016911pbc.4 for ; Wed, 26 Mar 2014 23:19:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=dp5eQT8V99uQ1Mr3hZhrXuJJbRsnZ0fObPTAUxu1hdg=; b=FjckUJmMfNy51KyCwAqulsE2vF9qDYo+Kok4MeS06AWjrG7zSFhZHSwCXBXdm8P1yr eNTJcxgr+vMN34eAWh7K/24D1OLwa9PfT4QPt/yCB494edGzh16kS3187zJDkW/ZpYmh 45psXQt1zcO4cHe9phOaT9vcMg1zLjbAbS+NaYT9L0Ontrhm8wHokq5KvAlq74uifEY0 27zJY89+uxHyQR3lUd4ThRymX5GNJQnUMXj4IG7fCOTiNEcEYqcY3bq3eJC70o0lM0Hn uaujqOPZz6QVE5FI+5jczNCBMIzA0PYHJOm3Si89FEy0ndvO+TtilKNuKpmBouXc0eko 2F9Q== X-Received: by 10.68.12.133 with SMTP id y5mr28298291pbb.134.1395901140216; Wed, 26 Mar 2014 23:19:00 -0700 (PDT) Received: from localhost.localdomain ([115.113.119.130]) by mx.google.com with ESMTPSA id dk1sm4074847pbc.46.2014.03.26.23.18.55 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 26 Mar 2014 23:18:59 -0700 (PDT) From: Yuvaraj Kumar C D To: grundler@chromium.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jh80.chung@samsung.com, cjb@laptop.org, tgih.jun@samsung.com, linux-mmc@vger.kernel.org, sonnyrao@chromium.org, kgene.kim@samsung.com, joshi@samsung.com Cc: t.figa@samsung.com, Doug Anderson , Yuvaraj Kumar C D Subject: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error Date: Thu, 27 Mar 2014 11:48:46 +0530 Message-Id: <1395901126-6141-1-git-send-email-yuvaraj.cd@samsung.com> X-Mailer: git-send-email 1.7.10.4 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.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 From: Doug Anderson 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 --- drivers/mmc/host/dw_mmc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1d77431..4c589f1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1300,6 +1300,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); @@ -1313,7 +1321,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: @@ -1336,6 +1366,23 @@ 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. + * + * TODO: I guess we shouldn't send a stop? + */ + if (!test_bit(EVENT_CMD_COMPLETE, + &host->pending_events)) { + dw_mci_request_end(host, mrq); + goto unlock; + } } /*