Return-path: Received: from mail-wi0-f182.google.com ([209.85.212.182]:47496 "EHLO mail-wi0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752026AbaJIJt4 (ORCPT ); Thu, 9 Oct 2014 05:49:56 -0400 Received: by mail-wi0-f182.google.com with SMTP id n3so1211610wiv.9 for ; Thu, 09 Oct 2014 02:49:54 -0700 (PDT) From: Michal Kazior To: ath10k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, Michal Kazior Subject: [PATCH 1/3] ath10k: fix possible bmi crash Date: Thu, 9 Oct 2014 11:38:45 +0200 Message-Id: <1412847527-25983-2-git-send-email-michal.kazior@tieto.com> (sfid-20141009_115001_850795_EDF20EB8) In-Reply-To: <1412847527-25983-1-git-send-email-michal.kazior@tieto.com> References: <1412847527-25983-1-git-send-email-michal.kazior@tieto.com> Sender: linux-wireless-owner@vger.kernel.org List-ID: While testing other things I've found that CE items aren't cleared properly. This could lead to null dereferences in BMI. To prevent that make sure CE revoking clears the nbytes value (which is used as a buffer completion indication) and memset the entire CE rings when (re)initializing. Also make sure to check BMI xfer pointer and print a splat instead of crashing the kernel. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/ce.c | 7 +++++++ drivers/net/wireless/ath/ath10k/pci.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 4745ef2..134dea5 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -558,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, /* sanity */ dest_ring->per_transfer_context[sw_index] = NULL; + desc->nbytes = 0; /* Update sw_index */ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); @@ -837,6 +838,10 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, memset(src_ring->per_transfer_context, 0, nentries * sizeof(*src_ring->per_transfer_context)); + memset(src_ring->base_addr_owner_space, 0, + nentries * sizeof(struct ce_desc)); + memset(src_ring->shadow_base, 0, + nentries * sizeof(struct ce_desc)); src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); src_ring->sw_index &= src_ring->nentries_mask; @@ -874,6 +879,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, memset(dest_ring->per_transfer_context, 0, nentries * sizeof(*dest_ring->per_transfer_context)); + memset(dest_ring->base_addr_owner_space, 0, + nentries * sizeof(struct ce_desc)); dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); dest_ring->sw_index &= dest_ring->nentries_mask; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6e8e098..ca2adbd 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1428,6 +1428,9 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) &nbytes, &transfer_id, &flags)) return; + if (WARN_ON_ONCE(!xfer)) + return; + if (!xfer->wait_for_resp) { ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); return; -- 1.8.5.3