From patchwork Fri Aug 2 07:15:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 2837547 Return-Path: X-Original-To: patchwork-linux-wireless@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 CB8DABF535 for ; Fri, 2 Aug 2013 07:16:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 568D5201FD for ; Fri, 2 Aug 2013 07:16:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 94CC9201FC for ; Fri, 2 Aug 2013 07:16:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757601Ab3HBHQH (ORCPT ); Fri, 2 Aug 2013 03:16:07 -0400 Received: from ebb05.tieto.com ([131.207.168.36]:49704 "EHLO ebb05.tieto.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757358Ab3HBHQE (ORCPT ); Fri, 2 Aug 2013 03:16:04 -0400 X-AuditID: 83cfa824-b7f348e000004c45-68-51fb5cb1f00d Received: from FIHGA-EXHUB01.eu.tieto.com ( [131.207.136.34]) by ebb05.tieto.com (SMTP Mailer) with SMTP id 3F.9B.19525.1BC5BF15; Fri, 2 Aug 2013 10:16:01 +0300 (EEST) Received: from uw001058.eu.tieto.com (10.28.19.57) by inbound.tieto.com (131.207.136.49) with Microsoft SMTP Server id 8.3.298.1; Fri, 2 Aug 2013 10:16:00 +0300 From: Michal Kazior To: CC: , Michal Kazior Subject: [PATCH v2] ath10k: fix device teardown Date: Fri, 2 Aug 2013 09:15:47 +0200 Message-ID: <1375427747-9539-1-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1374129572-6079-1-git-send-email-michal.kazior@tieto.com> References: <1374129572-6079-1-git-send-email-michal.kazior@tieto.com> MIME-Version: 1.0 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrJIsWRmVeSWpSXmKPExsXSfL5DSXdjzO9Ag2dTbSweXTrGbPFmxR12 i29bH7A5MHt8nnmXzWPzknqPz5vkApijuGxSUnMyy1KL9O0SuDI+fHzEWnBSqWLd6VtMDYy7 ZboYOTkkBEwknr09ywZhi0lcuLceyObiEBJYxSjRuP0QC4SzhFHi570udpAqNgFdiVeNZ1lB bBEBBYlfkz6CdTML+Eo8e7KMCcQWFtCXOL/zB1icRUBF4vPLc2D1vAJuEou/vQCawwG0TUFi ziQbkDCngLvE1eOrwcqFgEoOzLsKVS4ocXLmExaI8RISB1+8YIaoUZE4uH4/8wRGgVlIymYh KVvAyLSKkT81KcnAVK8kM7UkXy85P3cTIzgEV6jsYDz7QOoQowAHoxIPr0XOr0Ah1sSy4src Q4ySHExKorxV0b8DhfiS8lMqMxKLM+KLSnNSiw8xSnAwK4nw/pkNVM6bklhZlVqUD5OS5mBR Euf1yvkeKCSQnliSmp2aWpBaBJOV4eBQkuC9CjJUsCg1PbUiLTOnBCHNxMEJMpwHaLhUFFAN b3FBYm5xZjpE/hSjopQ4rwlIQgAkkVGaB9cLSxGvGMWBXhHmrQBZwQNML3Ddr4AGMwENVpoD cnVxSSJCSqqBcTJn0ESbYn4un4isouT9yrwJinY7eG5sy6n3k767+9WRSXba5umTxB7nTZdZ FsLi/Dxtx/7VE/zs2WaefMmZuqasa7NBj2ZMrcm3/p0bNGYfnLBy5189jRxTplUbKov+59oa 74gq5vvgYlfSX+6aEH3vUFMj47oEDfHNbjUXBKTP7ztZ+EZWiaU4I9FQi7moOBEA3rDGzuwC AAA= Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-8.3 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 This fixes interrupt-related issue when no interfaces were running thus the device was considered powered down. The power_down() function isn't really powering down the device. It simply assumed it won't interrupt. This wasn't true in some cases and could lead to paging failures upon FW indication interrupt (i.e. FW crash) because some structures aren't allocated in that device state. One reason for that was that ar_pci->started wasn't reset. The other is interrupts should've been masked when teardown starts. The patch reorganized interrupt setup and makes sure ar_pci->started is reset accordingly. Reported-by: Ben Greear Signed-off-by: Michal Kazior --- v2: * updated commit message * added Reported-By: Ben * added disable_irq() in hif_stop() * added ar_pci->started resetting * removed ar_pci->intr_started drivers/net/wireless/ath/ath10k/pci.c | 41 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c71b488..690a8b4 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -56,6 +56,8 @@ static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info); static void ath10k_pci_stop_ce(struct ath10k *ar); static void ath10k_pci_device_reset(struct ath10k *ar); static int ath10k_pci_reset_target(struct ath10k *ar); +static int ath10k_pci_start_intr(struct ath10k *ar); +static void ath10k_pci_stop_intr(struct ath10k *ar); static const struct ce_attr host_ce_config_wlan[] = { /* host->target HTC control and raw streams */ @@ -1254,10 +1256,25 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) } } +static void ath10k_pci_disable_irqs(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int i; + + for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) + disable_irq(ar_pci->pdev->irq + i); +} + static void ath10k_pci_hif_stop(struct ath10k *ar) { + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + /* Irqs are never explicitly re-enabled. They are implicitly re-enabled + * by ath10k_pci_start_intr(). */ + ath10k_pci_disable_irqs(ar); + ath10k_pci_stop_ce(ar); /* At this point, asynchronous threads are stopped, the target should @@ -1267,6 +1284,8 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_pci_process_ce(ar); ath10k_pci_cleanup_ce(ar); ath10k_pci_buffer_cleanup(ar); + + ar_pci->started = 0; } static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, @@ -1742,6 +1761,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) { int ret; + ret = ath10k_pci_start_intr(ar); + if (ret) { + ath10k_err("could not start interrupt handling (%d)\n", ret); + goto err; + } + /* * Bring the target up cleanly. * @@ -1756,7 +1781,7 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ret = ath10k_pci_reset_target(ar); if (ret) - goto err; + goto err_irq; if (ath10k_target_ps) { ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n"); @@ -1787,12 +1812,15 @@ err_ce: err_ps: if (!ath10k_target_ps) ath10k_do_pci_sleep(ar); +err_irq: + ath10k_pci_stop_intr(ar); err: return ret; } static void ath10k_pci_hif_power_down(struct ath10k *ar) { + ath10k_pci_stop_intr(ar); ath10k_pci_ce_deinit(ar); if (!ath10k_target_ps) ath10k_do_pci_sleep(ar); @@ -2358,22 +2386,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->cacheline_sz = dma_get_cache_alignment(); - ret = ath10k_pci_start_intr(ar); - if (ret) { - ath10k_err("could not start interrupt handling (%d)\n", ret); - goto err_iomap; - } - ret = ath10k_core_register(ar); if (ret) { ath10k_err("could not register driver core (%d)\n", ret); - goto err_intr; + goto err_iomap; } return 0; -err_intr: - ath10k_pci_stop_intr(ar); err_iomap: pci_iounmap(pdev, mem); err_master: @@ -2410,7 +2430,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) tasklet_kill(&ar_pci->msi_fw_err); ath10k_core_unregister(ar); - ath10k_pci_stop_intr(ar); pci_set_drvdata(pdev, NULL); pci_iounmap(pdev, ar_pci->mem);