From patchwork Tue Jul 19 10:34:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 9236697 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3B774602F0 for ; Tue, 19 Jul 2016 10:32:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2CD9B20120 for ; Tue, 19 Jul 2016 10:32:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 217782521F; Tue, 19 Jul 2016 10:32:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9402D20120 for ; Tue, 19 Jul 2016 10:32:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752916AbcGSKck (ORCPT ); Tue, 19 Jul 2016 06:32:40 -0400 Received: from mail-lf0-f54.google.com ([209.85.215.54]:35724 "EHLO mail-lf0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752868AbcGSKch (ORCPT ); Tue, 19 Jul 2016 06:32:37 -0400 Received: by mail-lf0-f54.google.com with SMTP id f93so10086041lfi.2 for ; Tue, 19 Jul 2016 03:32:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=c0ix5bH9XjD2rH8foVQSWOPKC+QMa5ErlDtJ/20tcg4=; b=mNwdqSbHZ5/j7CmYHdlNvU+qBPC7m19NacERXMYyPj/uDU1XkoV36MYnwcKpR6nE4g rvTQbepdIjcIeZkNbYtePTtLjjvdAuy76pEGd9fdjZXtkRn6ugM8StZ8m0w+UpRkCGv4 9OWv8oLTuKO4p5s49AidiV8G46N7qHnvVdpLQ= 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:in-reply-to :references; bh=c0ix5bH9XjD2rH8foVQSWOPKC+QMa5ErlDtJ/20tcg4=; b=QQ7lcTkugH6rBRQberClTtpaJPsR724D9wAvvygWmyoSVcfQm5KZCH9Df9dGUeqdme YundwrheJdyXRsI2gkSyBs1H8zs0x76MEO5BNuTbSVNiSX3DjUS6zvg+RS5Pz0Upc4Zc ANN+lDP4LIbkJrkHy0uW9Tre2lZptvtYylAMUYnMMqChbJpsHHunqirLQ6z96C9XnlGR /JKhhmKtqsBhLUnPr/82dxAob8xCRi/2iu/b1Vka8TJbp8J4aePtejmI6pQ7IHsIKQvc RLDHdVx1G/CNLIck7qXQE5pn1RoA5sGATb5qcBf6ope3dpXIZaRyRzmNT4SDLDTtUPYQ qp8A== X-Gm-Message-State: ALyK8tKKlhRa/Eq6W0tvkRsp0oC07W2qBvHv55pSvTMebptcp7R88UUtyUV1L6bfbJSbSL9jhB0VwQ4ivLNGGbNz2kmWzSJ+t1prPqjtCJlTwUP6xU1CVSuBaET7Spc6msLxlRK8A7BJNw== X-Received: by 10.25.22.234 with SMTP id 103mr17875909lfw.100.1468924355220; Tue, 19 Jul 2016 03:32:35 -0700 (PDT) Received: from localhost.localdomain ([91.198.246.8]) by smtp.gmail.com with ESMTPSA id y200sm2963977lfd.12.2016.07.19.03.32.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 19 Jul 2016 03:32:34 -0700 (PDT) From: Michal Kazior To: kvalo@qca.qualcomm.com Cc: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org, marek.puzyniak@tieto.com, Michal Kazior Subject: [PATCH 4/4] ath10k: fix spurious tx/rx during boot Date: Tue, 19 Jul 2016 12:34:12 +0200 Message-Id: <1468924452-23877-5-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1468924452-23877-1-git-send-email-michal.kazior@tieto.com> References: <1468924452-23877-1-git-send-email-michal.kazior@tieto.com> X-DomainID: tieto.com Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP HW Rx filters and masks are not configured properly by firmware during boot sequences. The MAC_PCU_ADDR1 is set to 0s instead of 1s which allows the HW to ACK any frame that passes through MAC_PCU_RX_FILTER. The MAC_PCU_RX_FILTER itself is misconfigured on boot as well. The combination of these bugs ended up with the following manifestations: - "no channel configured; ignoring frame(s)!" warnings in the driver - spurious ACKs (transmission) on the air during firmware bootup sequences The former was a long standing and known bug originally though mostly harmless. However Marek recently discovered that this problem also involves ACKing *all* frames the HW receives (including beacons ;). Such frames are delivered to host and generate the former warning as well. This could be a problem with regulatory compliance in some rare cases (e.g. Taiwan which forbids transmissions on channel 36 which is the default bootup channel on 5Ghz band cards). The good news is that it'd require someone else to violate regulatory first to coerce our device to generate and transmit an ACK. The problem could be reproduced in a rather busy environment that has a lot of APs. The likelihood could be increased by injecting an msleep() of 5000 or longer immediately after ath10k_htt_setup() in ath10k_core_start(). The reason why the former warnings were only showing up seldom is because the device was either quickly reset again (i.e. during firmware probing) or wmi vdev was created (which fixes hw and fw states). It is technically possible for host driver to override adequate hw registers however this can't work reliably because the bug root cause lies in incorrect firmware state on boot (internal structure used to program MAC_PCU_ADDR1 is not properly initialized) and only vdev create/delete events can fix it. This is why the patch takes dummy vdev approach. This could be fixed in firmware as well but having this fixed in driver is more robust, most notably when thinking of users of older firmware such as 999.999.0.636. Reported-by: Marek Puzyniak Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/core.c | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e88982921aa3..d2e255418d1b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1705,6 +1705,55 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return 0; } +static int ath10k_core_reset_rx_filter(struct ath10k *ar) +{ + int ret; + int vdev_id; + int vdev_type; + int vdev_subtype; + const u8 *vdev_addr; + + vdev_id = 0; + vdev_type = WMI_VDEV_TYPE_STA; + vdev_subtype = ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE); + vdev_addr = ar->mac_addr; + + ret = ath10k_wmi_vdev_create(ar, vdev_id, vdev_type, vdev_subtype, + vdev_addr); + if (ret) { + ath10k_err(ar, "failed to create dummy vdev: %d\n", ret); + return ret; + } + + ret = ath10k_wmi_vdev_delete(ar, vdev_id); + if (ret) { + ath10k_err(ar, "failed to delete dummy vdev: %d\n", ret); + return ret; + } + + /* WMI and HTT may use separate HIF pipes and are not guaranteed to be + * serialized properly implicitly. + * + * Moreover (most) WMI commands have no explicit acknowledges. It is + * possible to infer it implicitly by poking firmware with echo + * command - getting a reply means all preceding comments have been + * (mostly) processed. + * + * In case of vdev create/delete this is sufficient. + * + * Without this it's possible to end up with a race when HTT Rx ring is + * started before vdev create/delete hack is complete allowing a short + * window of opportunity to receive (and Tx ACK) a bunch of frames. + */ + ret = ath10k_wmi_barrier(ar); + if (ret) { + ath10k_err(ar, "failed to ping firmware: %d\n", ret); + return ret; + } + + return 0; +} + int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, const struct ath10k_fw_components *fw) { @@ -1872,6 +1921,25 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, goto err_hif_stop; } + /* Some firmware revisions do not properly set up hardware rx filter + * registers. + * + * A known example from QCA9880 and 10.2.4 is that MAC_PCU_ADDR1_MASK + * is filled with 0s instead of 1s allowing HW to respond with ACKs to + * any frames that matches MAC_PCU_RX_FILTER which is also + * misconfigured to accept anything. + * + * The ADDR1 is programmed using internal firmware structure field and + * can't be (easily/sanely) reached from the driver explicitly. It is + * possible to implicitly make it correct by creating a dummy vdev and + * then deleting it. + */ + status = ath10k_core_reset_rx_filter(ar); + if (status) { + ath10k_err(ar, "failed to reset rx filter: %d\n", status); + goto err_hif_stop; + } + /* If firmware indicates Full Rx Reorder support it must be used in a * slightly different manner. Let HTT code know. */