From patchwork Wed Dec 11 15:05:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg KH X-Patchwork-Id: 181222 Delivered-To: patch@linaro.org Received: by 2002:a92:3001:0:0:0:0:0 with SMTP id x1csp656409ile; Wed, 11 Dec 2019 07:07:46 -0800 (PST) X-Google-Smtp-Source: APXvYqxu7RxfzP8zkVsA46vK2ohwczmRI/HbLB5XVU8Z7itg/7a1+RmzTQcHxHAoG2ExPk7f0aYX X-Received: by 2002:aca:fdc2:: with SMTP id b185mr3236756oii.74.1576076866023; Wed, 11 Dec 2019 07:07:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1576076866; cv=none; d=google.com; s=arc-20160816; b=pyunpYougCkyKiVh3yf9bElOuSlXJKfJH4dHCVqb9UCwmj4NSoVSOyTXEaF0OQUBl+ oohPYXkHNToQXDcNXiDA9Xd7mJwfI1Cd4T9TccfYXDSAFr6/bkWC6r8Iyk1HD5itnSZQ CcY0JZWxXn79zdV5PB4L77QXiBxLK1Mf09uCIc+ScpcvkKi/ysHlF8j0R4HfWD/+C8sQ RZ6DFri1XW0TW14AN85SsxdiKkoDmjgOXJLPw5KoThMgNaxNZJ9pxI7D2yrRJyj9Rtba n4i1T1GIHdZE12oHoOZODeeXQ9dm+BbGESDwt3zKnp14iL2IHTDLG7BIdyH36885hzS1 MvrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1t1aiJdfxbez9cPtxc/ntAE+5A93D0WfLY4AnymLx48=; b=OauC5ut2F2TYe6U7UzPot+tUDyBAZedLFIGu/Vnjk6gU7h7mXfbkEUP/TTvD0zEIwz AW28eijzdXv0uuEat30kbdgyh0+py5IAZd3EoBUrP7+EQav8gdbT0Gv5pGAu5/wjmKu8 UgexbMAaNb+tL3nOVPXlrdU3alJvd9KAuxB4wo/IHC7Nm1fzionc14WOruOkJCggtm2z ArbwWuXvakmFIMT7UbqGktN5b6g4gZtwbFajbnKS5FXkdFpEZ/3tAse0uje/OHH33UaI pMW6j2fchPs/Lv0WykHdJ57jFm6TnKUiO3HfX/oGuUjWhCWsSVJgo7HqZ67tSq14uzwa 8XmA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="hBPDON/Q"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e18si1325246otj.99.2019.12.11.07.07.45; Wed, 11 Dec 2019 07:07:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="hBPDON/Q"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730097AbfLKPHn (ORCPT + 27 others); Wed, 11 Dec 2019 10:07:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:54882 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730076AbfLKPHl (ORCPT ); Wed, 11 Dec 2019 10:07:41 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B34C020663; Wed, 11 Dec 2019 15:07:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576076861; bh=2iLlGMrkETmSLochaz1pSpins8fUVRRprn5VD23TrUM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hBPDON/QeMDl5YXMoN3sWsdOTNpqscPoE6+o87pq6AcX+0eCRAgcB6eaEUS1Bouch qdzrmyMRXNKOuyWN4l3WRsGX8PTwL54Qcbj9xZMPgfv3R1Ec1BdZQOGuDlGTACQ7bO y4jRlVbKsUZ52olKzg7pdoo9EXwwuOSfpDXi+mUs= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Douglas Anderson , Kalle Valo , Ulf Hansson Subject: [PATCH 5.4 19/92] mwifiex: Re-work support for SDIO HW reset Date: Wed, 11 Dec 2019 16:05:10 +0100 Message-Id: <20191211150227.375343546@linuxfoundation.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20191211150221.977775294@linuxfoundation.org> References: <20191211150221.977775294@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ulf Hansson commit cdb2256f795e8e78cc43f32d091695b127dfb4df upstream. The SDIO HW reset procedure in mwifiex_sdio_card_reset_work() is broken, when the SDIO card is shared with another SDIO func driver. This is the case when the Bluetooth btmrvl driver is being used in combination with mwifiex. More precisely, when mwifiex_sdio_card_reset_work() runs to resets the SDIO card, the btmrvl driver doesn't get notified about it. Beyond that point, the btmrvl driver will fail to communicate with the SDIO card. This is a generic problem for SDIO func drivers sharing an SDIO card, which are about to be addressed in subsequent changes to the mmc core and the mmc_hw_reset() interface. In principle, these changes means the mmc_hw_reset() interface starts to return 1 if the are multiple drivers for the SDIO card, as to indicate to the caller that the reset needed to be scheduled asynchronously through a hotplug mechanism of the SDIO card. Let's prepare the mwifiex driver to support the upcoming new behaviour of mmc_hw_reset(), which means extending the mwifiex_sdio_card_reset_work() to support the asynchronous SDIO HW reset path. This also means, we need to allow the ->remove() callback to run, without waiting for the FW to be loaded. Additionally, during system suspend, mwifiex_sdio_suspend() may be called when a reset has been scheduled, but waiting to be executed. In this scenario let's simply return -EBUSY to abort the suspend process, as to allow the reset to be completed first. Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Cc: stable@vger.kernel.org # v5.4+ Acked-by: Kalle Valo Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/marvell/mwifiex/main.c | 5 +++- drivers/net/wireless/marvell/mwifiex/main.h | 1 drivers/net/wireless/marvell/mwifiex/sdio.c | 33 ++++++++++++++++++---------- 3 files changed, 27 insertions(+), 12 deletions(-) --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -631,6 +631,7 @@ static int _mwifiex_fw_dpc(const struct mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt); + adapter->is_up = true; goto done; err_add_intf: @@ -1469,6 +1470,7 @@ int mwifiex_shutdown_sw(struct mwifiex_a mwifiex_deauthenticate(priv, NULL); mwifiex_uninit_sw(adapter); + adapter->is_up = false; if (adapter->if_ops.down_dev) adapter->if_ops.down_dev(adapter); @@ -1730,7 +1732,8 @@ int mwifiex_remove_card(struct mwifiex_a if (!adapter) return 0; - mwifiex_uninit_sw(adapter); + if (adapter->is_up) + mwifiex_uninit_sw(adapter); if (adapter->irq_wakeup >= 0) device_init_wakeup(adapter->dev, false); --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1017,6 +1017,7 @@ struct mwifiex_adapter { /* For synchronizing FW initialization with device lifecycle. */ struct completion *fw_done; + bool is_up; bool ext_scan; u8 fw_api_ver; --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -444,6 +444,9 @@ static int mwifiex_sdio_suspend(struct d return 0; } + if (!adapter->is_up) + return -EBUSY; + mwifiex_enable_wake(adapter); /* Enable the Host Sleep */ @@ -2220,22 +2223,30 @@ static void mwifiex_sdio_card_reset_work struct sdio_func *func = card->func; int ret; + /* Prepare the adapter for the reset. */ mwifiex_shutdown_sw(adapter); + clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); + clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - /* power cycle the adapter */ + /* Run a HW reset of the SDIO interface. */ sdio_claim_host(func); - mmc_hw_reset(func->card->host); + ret = mmc_hw_reset(func->card->host); sdio_release_host(func); - /* Previous save_adapter won't be valid after this. We will cancel - * pending work requests. - */ - clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); - clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); - - ret = mwifiex_reinit_sw(adapter); - if (ret) - dev_err(&func->dev, "reinit failed: %d\n", ret); + switch (ret) { + case 1: + dev_dbg(&func->dev, "SDIO HW reset asynchronous\n"); + complete_all(adapter->fw_done); + break; + case 0: + ret = mwifiex_reinit_sw(adapter); + if (ret) + dev_err(&func->dev, "reinit failed: %d\n", ret); + break; + default: + dev_err(&func->dev, "SDIO HW reset failed: %d\n", ret); + break; + } } /* This function read/write firmware */