Received: by 2002:a25:31c3:0:0:0:0:0 with SMTP id x186csp6570252ybx; Mon, 11 Nov 2019 11:07:23 -0800 (PST) X-Google-Smtp-Source: APXvYqyREWnl/LKvdS/YZ4mRupqevovdWAi5Jg1Dz13NQgmik4YfkdOakMFQhy5v45RdEyHvaBho X-Received: by 2002:a50:f747:: with SMTP id j7mr28301690edn.247.1573499243669; Mon, 11 Nov 2019 11:07:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573499243; cv=none; d=google.com; s=arc-20160816; b=zsQ4RLMOS9sizb0sXN4ToOOTOd5zwDrudMttVFP8aOzf5WZzvw2fWu5Y1Xfj18g0pS bTvwj+CD5hlIGbcaqIA0VG2voeGbaxgBlULgp+oOc6SAON8zGEY6Elne+uk1F6NFncRs mIWG8CSe2cccfk3dH5gp1fv4JWnsvJmWdQdz0OasAiFhEsPwsX9NBlHFAWL6whe9HBGm tgT+3I4o/lzq49SmkltkhjYdiHczJDlPavkiTUuf8b+S2PnVU9nKBU4ySPEamc203hJP nWWLgRgqSkAANoMlDh+2hxJ4cp7ZIZfV6OmKl9e4rt1GLbXfr59gFPM1NtbsyORCPO9/ FagQ== 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=HiSOpZC7wS/1al46uXuHLBZnSjidNj44mErD8mpYUMA=; b=gXFaMMiSLK/dU7mpm9/nFJgjnOEHRyDdSIz8uO561jV6JBJxGXbyVuH5N1s+gUZIvB KzgyJD1s1ndBGYjAYQcYssz/div9YufLThWGDacpLwi42IcOl7BHBNo0S49BcYg/iK2Q 8kXOKvvIZsvMlq+VapX23YO/QViy0xs5bp8yXzQmsj/PsIqdPV8XfcqeW7bWd31Dv/P5 Zr02IQkjRmHFPom+joO23gLIcTdX46fzkUpY/81XFVNc0YGs7hiQM7RaZt0DPCGSde1M 2aEGIX4vCKbB3ybCDOfoBnz01OL7m8W73Exw8WGDoS8S66hJr2+m6n5OR2VzFOYQRlz9 /3Ng== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=IDXJgJt2; 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 cc4si10636213edb.237.2019.11.11.11.06.59; Mon, 11 Nov 2019 11:07:23 -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=IDXJgJt2; 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 S1729519AbfKKSm1 (ORCPT + 99 others); Mon, 11 Nov 2019 13:42:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:33602 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729072AbfKKSmX (ORCPT ); Mon, 11 Nov 2019 13:42:23 -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 07CEB21783; Mon, 11 Nov 2019 18:42:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573497742; bh=MegO0AW1S5ijek+lrnxfYqx5M+fzH8XtDZcN2iYagM4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IDXJgJt2aSdsPbDj6FacpTakxTm+khjAFAYy1WuHH7IhSRbwvMjGehDvPlM0SZiKU 8aDInVwkJjqI6ZQDggr+tX0uxhxCsZzMVJ4/TgP/1z2V1Zos/vaSLtYomyVfFmANXx LqiEO1orXsfQsWMAvq0cvQ4lTbRWoQ4SjE2lRs3I= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kurt Van Dijck , Wolfgang Grandegger , Joe Burmeister , Marc Kleine-Budde Subject: [PATCH 4.19 045/125] can: c_can: c_can_poll(): only read status register after status IRQ Date: Mon, 11 Nov 2019 19:28:04 +0100 Message-Id: <20191111181446.305910183@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191111181438.945353076@linuxfoundation.org> References: <20191111181438.945353076@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kurt Van Dijck commit 3cb3eaac52c0f145d895f4b6c22834d5f02b8569 upstream. When the status register is read without the status IRQ pending, the chip may not raise the interrupt line for an upcoming status interrupt and the driver may miss a status interrupt. It is critical that the BUSOFF status interrupt is forwarded to the higher layers, since no more interrupts will follow without intervention. Thanks to Wolfgang and Joe for bringing up the first idea. Signed-off-by: Kurt Van Dijck Cc: Wolfgang Grandegger Cc: Joe Burmeister Fixes: fa39b54ccf28 ("can: c_can: Get rid of pointless interrupts") Cc: linux-stable Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 25 ++++++++++++++++++++----- drivers/net/can/c_can/c_can.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -97,6 +97,9 @@ #define BTR_TSEG2_SHIFT 12 #define BTR_TSEG2_MASK (0x7 << BTR_TSEG2_SHIFT) +/* interrupt register */ +#define INT_STS_PENDING 0x8000 + /* brp extension register */ #define BRP_EXT_BRPE_MASK 0x0f #define BRP_EXT_BRPE_SHIFT 0 @@ -1029,10 +1032,16 @@ static int c_can_poll(struct napi_struct u16 curr, last = priv->last_status; int work_done = 0; - priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); - /* Ack status on C_CAN. D_CAN is self clearing */ - if (priv->type != BOSCH_D_CAN) - priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); + /* Only read the status register if a status interrupt was pending */ + if (atomic_xchg(&priv->sie_pending, 0)) { + priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); + /* Ack status on C_CAN. D_CAN is self clearing */ + if (priv->type != BOSCH_D_CAN) + priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); + } else { + /* no change detected ... */ + curr = last; + } /* handle state changes */ if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { @@ -1083,10 +1092,16 @@ static irqreturn_t c_can_isr(int irq, vo { struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); + int reg_int; - if (!priv->read_reg(priv, C_CAN_INT_REG)) + reg_int = priv->read_reg(priv, C_CAN_INT_REG); + if (!reg_int) return IRQ_NONE; + /* save for later use */ + if (reg_int & INT_STS_PENDING) + atomic_set(&priv->sie_pending, 1); + /* disable all interrupts and schedule the NAPI */ c_can_irq_control(priv, false); napi_schedule(&priv->napi); --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -198,6 +198,7 @@ struct c_can_priv { struct net_device *dev; struct device *device; atomic_t tx_active; + atomic_t sie_pending; unsigned long tx_dir; int last_status; u16 (*read_reg) (const struct c_can_priv *priv, enum reg index);