Received: by 2002:a05:6a10:2785:0:0:0:0 with SMTP id ia5csp11590pxb; Fri, 15 Jan 2021 04:38:01 -0800 (PST) X-Google-Smtp-Source: ABdhPJxAHLE3fOHrdwfoyICys8VAQF1VUMT0z/NSO7WIi6WJQp6jZTYrGtDNXIhdSFcQLwjuvqj0 X-Received: by 2002:a17:907:20a6:: with SMTP id pw6mr8917367ejb.73.1610714281196; Fri, 15 Jan 2021 04:38:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610714281; cv=none; d=google.com; s=arc-20160816; b=j3d5jZf/60YOKneqpuNncku9gCEKWG7x+X9oVUPjshzKFlYDQPd/9lJl1EnuJhHvu5 sMzl4Coti+xWKFJA1YmkRPb5OHaFu58PZv7zvWz4mEC9vAKJ7S2zL99hmEbs6QO9bZKm 7wvYThA2b5zNXFkpkhNyjDhGwm6NsgNxj0jNknoRH6lxzspAfnvU0GmCZy+o2th+W45B OdTcJ5KAwhHQLZ2vPVmpwflo6uHxUEtEIrTRPOi8VnkyhwPW9tO04R48+NDhhWhUbNFe 7BYiOtFR76cfIm+JCSIu9Expc58YBMEP+iszGF/6jhBBvy3GQU23THY3kp/hHjlwiWAd VHrQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ccTtfMQSEGuo8sddJ+8usfsXn4Tc+sS9nsHsRkvRvbM=; b=RudvLBv1HhDXmak7jHFQv0Z9jRQ1jNdW6zLrC2UNyfRToNPNEWVKYbZAvd6DWQ8pYw RagDl/DdL7NhCplTKV3bED7DApLQmHrUlJNq8MhO+ly4zCUzq91MhG2du27GLBxX/aF1 NyTNq9YgiDWkOoSec5xb8zabtYDChkuglxDtUjqeOUiaf8v8UMtQYHe5YnWqzAuVo7Gg ZAz77OoKS6Z6SkbHKt1tMngXpZ7OG+vNOIrTxv3eqgpPvI5nBmCjs89fALs9lM+Ankwh 1tFPMDMhyxz+FnE2DkHe9PWBqlBHWigIb9oqx14Ikkc8M1srEPnO9UzStV4SId7GRkHX T7Xg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Vh46HN7m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id gq25si1546192ejb.85.2021.01.15.04.37.37; Fri, 15 Jan 2021 04:38:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Vh46HN7m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387646AbhAOMfY (ORCPT + 99 others); Fri, 15 Jan 2021 07:35:24 -0500 Received: from mail.kernel.org ([198.145.29.99]:41338 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387586AbhAOMfD (ORCPT ); Fri, 15 Jan 2021 07:35:03 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5E64C2256F; Fri, 15 Jan 2021 12:34:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1610714087; bh=e+Ad1xVCP6360ODNJ3AXbV2DBzNaz5/GhxxnnKuCGgw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vh46HN7mZGcDbts5wPRWAjVkzi1gl+zzUowT1NFCnPa1w9lA4T4lNGNoMqS8J5Qc3 0PfgZbhV4k6RP1pV2dfaUagMKlL6uXRzc8wHAAmTinWPpcV1umBATad/s2E0+Ze0WY J/DXBZhR4WZpvS6jNCoGhRmigT7DfvM5q3n3ZXGQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Douglas Anderson , Stephen Boyd , Mark Brown Subject: [PATCH 5.4 40/62] spi: spi-geni-qcom: Fix geni_spi_isr() NULL dereference in timeout case Date: Fri, 15 Jan 2021 13:28:02 +0100 Message-Id: <20210115122000.333323971@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210115121958.391610178@linuxfoundation.org> References: <20210115121958.391610178@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Douglas Anderson commit 4aa1464acbe3697710279a4bd65cb4801ed30425 upstream. In commit 7ba9bdcb91f6 ("spi: spi-geni-qcom: Don't keep a local state variable") we changed handle_fifo_timeout() so that we set "mas->cur_xfer" to NULL to make absolutely sure that we don't mess with the buffers from the previous transfer in the timeout case. Unfortunately, this caused the IRQ handler to dereference NULL in some cases. One case: CPU0 CPU1 ---- ---- setup_fifo_xfer() geni_se_setup_m_cmd() ... handle_fifo_timeout() spin_lock_irq(mas->lock) mas->cur_xfer = NULL geni_se_cancel_m_cmd() spin_unlock_irq(mas->lock) geni_spi_isr() spin_lock(mas->lock) if (m_irq & M_RX_FIFO_WATERMARK_EN) geni_spi_handle_rx() mas->cur_xfer NULL dereference! tl;dr: Seriously delayed interrupts for RX/TX can lead to timeout handling setting mas->cur_xfer to NULL. Let's check for the NULL transfer in the TX and RX cases and reset the watermark or clear out the fifo respectively to put the hardware back into a sane state. NOTE: things still could get confused if we get timeouts all the way through handle_fifo_timeout() and then start a new transfer because interrupts from the old transfer / cancel / abort could still be pending. A future patch will help this corner case. Fixes: 561de45f72bd ("spi: spi-geni-qcom: Add SPI driver support for GENI based QUP") Signed-off-by: Douglas Anderson Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20201217142842.v3.1.I99ee04f0cb823415df59bd4f550d6ff5756e43d6@changeid Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-geni-qcom.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -415,6 +415,12 @@ static void geni_spi_handle_tx(struct sp unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); unsigned int i = 0; + /* Stop the watermark IRQ if nothing to send */ + if (!mas->cur_xfer) { + writel(0, se->base + SE_GENI_TX_WATERMARK_REG); + return false; + } + max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word; if (mas->tx_rem_bytes < max_bytes) max_bytes = mas->tx_rem_bytes; @@ -454,6 +460,14 @@ static void geni_spi_handle_rx(struct sp if (rx_last_byte_valid && rx_last_byte_valid < 4) rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid; } + + /* Clear out the FIFO and bail if nowhere to put it */ + if (!mas->cur_xfer) { + for (i = 0; i < DIV_ROUND_UP(rx_bytes, bytes_per_fifo_word); i++) + readl(se->base + SE_GENI_RX_FIFOn); + return; + } + if (mas->rx_rem_bytes < rx_bytes) rx_bytes = mas->rx_rem_bytes;