From patchwork Tue Jul 18 07:56:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Schneider-Pargmann X-Patchwork-Id: 121844 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c923:0:b0:3e4:2afc:c1 with SMTP id j3csp1579015vqt; Tue, 18 Jul 2023 01:03:33 -0700 (PDT) X-Google-Smtp-Source: APBJJlFIE1vBdQQg8g+UnJ5/W2HdS6ArjDKgiQgQYQxE1gUS+gm75HbxZfFnUfQKWoTffPzebX68 X-Received: by 2002:a17:907:774d:b0:994:34a2:8724 with SMTP id kx13-20020a170907774d00b0099434a28724mr11944705ejc.52.1689667413322; Tue, 18 Jul 2023 01:03:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689667413; cv=none; d=google.com; s=arc-20160816; b=DnAGAUd9gfREr55cCaoDHqILyUji6C9crYs6b8OdK/B/FNKigPEyNVqGtY4l3qsebr XLhNXAcNm0oM6rCBlpBV7bxKof8NSpR1bwJWXZBegmVfpUak8naDZg6walsdu1DxGDcu DDyQwNawN0ByNPy6wLj6U1gHqXhu6b8TiLaFZwYVpcmj5D4YQqS5onbJaWtxfoYX/trC W1eNAFq7VA5wE020h/dddTELwa+7ABnnFIsL2fDwpykqpAkyRd4okZOdWXQPccxOHWbF 3P79JtGaCYXKZnQrAzcnm7rT6Mh6l/LNXLjHTfnwEZjGO2McstAJQBKFV9DCY49KQZ+r jOyQ== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=A+IAHaKiSJpEhojt50oheCT5NYSZEmbWbjYZr+oWDZU=; fh=HEvpsrq2tYe3N9GuSJCCr6vVuOqDDDbQ2hrVJYmjlns=; b=tWuOtHIwbfX/KDdbVzTYO8uvA3ArTvAmhd2HgIrEQdfAqf/2KTYzEUTdlipgsVwwaY cYdd8r4sRW/xFtna1JyASuo06kyigF61ueNHHW9Y4Cs7JS3tFnyR0ivd5RbsFXV/5soT KoI/gUkzS8roEJ6gaNq3pQy/M0VPEGrJ9hO6IJ1UzE/kZAKhvTw13UTp0Q++w4mFDBkz 510KpPyBv2G+Cmn0uynE1tKwth+GA8QNKj4lE8WdLF6pYiEbCENdrLGe0uqwJbLrYHYb niOjiimwW1VuPvStypm9BAtnnCZ3Jys9Gbj8N0q2/zyBrDcDUmKmHUZHsgf3CKom5o0x r95Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20221208.gappssmtp.com header.s=20221208 header.b=tuzmz2M1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ch12-20020a170906c2cc00b0098dfd35276esi748301ejb.1055.2023.07.18.01.03.06; Tue, 18 Jul 2023 01:03:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20221208.gappssmtp.com header.s=20221208 header.b=tuzmz2M1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231822AbjGRH5w (ORCPT + 99 others); Tue, 18 Jul 2023 03:57:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230447AbjGRH5n (ORCPT ); Tue, 18 Jul 2023 03:57:43 -0400 Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [IPv6:2a00:1450:4864:20::231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 69914198C for ; Tue, 18 Jul 2023 00:57:16 -0700 (PDT) Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2b6f0508f54so80522081fa.3 for ; Tue, 18 Jul 2023 00:57:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20221208.gappssmtp.com; s=20221208; t=1689667034; x=1690271834; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=A+IAHaKiSJpEhojt50oheCT5NYSZEmbWbjYZr+oWDZU=; b=tuzmz2M1KjgLzrFx+29v3jKlzDjX4seJGwcbCnoiErGJSramNmn6cmFzOggAjZD0EA EOyn/iIzNFW1HmSZeLI5tb7KuhrxqY61F9t0oms4zr4kYbQCaB1sdxtGvQF+4cE463qa O/EexOPi4BIjF9GEOwHuTbTNrTtCS0mqb8CVP8pm6O/ABJJ+bBFDHwdQlsyaNKQCoen5 iaFowxfaELx+sKlWL5ECotiAin05bd4hATnYeCqi6F6XD9OYrOlibD8K9av9KWqY0Tya bUrx+9QBZTevXxCrN4hPp26w36Lbxi2sMkeiGIENrIuWY2cJXfojGl0vR4kX65RzZ6Jc yRqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689667034; x=1690271834; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=A+IAHaKiSJpEhojt50oheCT5NYSZEmbWbjYZr+oWDZU=; b=CHk1IJYFDKitdkKk0ndRo8w1sXzd5ORr5jcger+vUNFaeWw5a9UR9NNQLBE5mrja9j OAZoj0JxkTfuFqbUSK6r1zNfLxlFQAEtJBlIk8jLaYGiuWHmoI84LhcgKDoC8fpJ3CkU Y9EduJF5zlZ90tUb7hgA6X9wi75kOKKmJvOSZrui+6wOt8oh2I6T9hifveKwggtnSsDc 9S/Lq/1iUMGzDyD928RKR5aXwPgwm4WRwqyk72A5RWZFHnUPYTwtjA8XSTYnwF7bIn7T 4okL1g+Bll9XoiiS2MnJPNRYPxG1OA0Wm14Gw2Iy74gj2646nMGBMsOm7vgeMgyJar75 EUmg== X-Gm-Message-State: ABy/qLZQXa/I2zgCKrMc4nPe9Jy47SekFkO8eatc0sGzKOOaI2RV8in2 cvfL5YYwpzpYv8VSkjLnETHFSw== X-Received: by 2002:a2e:b70a:0:b0:2b6:eb5a:6504 with SMTP id j10-20020a2eb70a000000b002b6eb5a6504mr10786531ljo.18.1689667034110; Tue, 18 Jul 2023 00:57:14 -0700 (PDT) Received: from blmsp.fritz.box ([2001:4091:a247:82fa:b762:4f68:e1ed:5041]) by smtp.gmail.com with ESMTPSA id x4-20020a5d54c4000000b003142439c7bcsm1585959wrv.80.2023.07.18.00.57.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jul 2023 00:57:13 -0700 (PDT) From: Markus Schneider-Pargmann To: Marc Kleine-Budde , Chandrasekar Ramakrishnan , Wolfgang Grandegger Cc: Vincent MAILHOL , Simon Horman , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-can@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Panis , Markus Schneider-Pargmann Subject: [PATCH v5 02/12] can: m_can: Implement receive coalescing Date: Tue, 18 Jul 2023 09:56:58 +0200 Message-Id: <20230718075708.958094-3-msp@baylibre.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230718075708.958094-1-msp@baylibre.com> References: <20230718075708.958094-1-msp@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771744697354836240 X-GMAIL-MSGID: 1771744697354836240 m_can offers the possibility to set an interrupt on reaching a watermark level in the receive FIFO. This can be used to implement coalescing. Unfortunately there is no hardware timeout available to trigger an interrupt if only a few messages were received within a given time. To solve this I am using a hrtimer to wake up the irq thread after x microseconds. The timer is always started if receive coalescing is enabled and new received frames were available during an interrupt. The timer is stopped if during a interrupt handling no new data was available. If the timer is started the new item interrupt is disabled and the watermark interrupt takes over. If the timer is not started again, the new item interrupt is enabled again, notifying the handler about every new item received. Signed-off-by: Markus Schneider-Pargmann Reviewed-by: Simon Horman --- drivers/net/can/m_can/m_can.c | 70 ++++++++++++++++++++++++++++++++--- drivers/net/can/m_can/m_can.h | 7 ++++ 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 478e0670f0d1..dd0fa58660d7 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -419,6 +419,22 @@ static void m_can_config_endisable(struct m_can_classdev *cdev, bool enable) } } +static void m_can_interrupt_enable(struct m_can_classdev *cdev, u32 interrupts) +{ + if (cdev->active_interrupts == interrupts) + return; + cdev->ops->write_reg(cdev, M_CAN_IE, interrupts); + cdev->active_interrupts = interrupts; +} + +static void m_can_coalescing_disable(struct m_can_classdev *cdev) +{ + u32 new_interrupts = cdev->active_interrupts | IR_RF0N; + + hrtimer_cancel(&cdev->irq_timer); + m_can_interrupt_enable(cdev, new_interrupts); +} + static inline void m_can_enable_all_interrupts(struct m_can_classdev *cdev) { /* Only interrupt line 0 is used in this driver */ @@ -427,6 +443,7 @@ static inline void m_can_enable_all_interrupts(struct m_can_classdev *cdev) static inline void m_can_disable_all_interrupts(struct m_can_classdev *cdev) { + m_can_coalescing_disable(cdev); m_can_write(cdev, M_CAN_ILE, 0x0); } @@ -1076,15 +1093,39 @@ static int m_can_echo_tx_event(struct net_device *dev) return err; } +static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir) +{ + u32 new_interrupts = cdev->active_interrupts; + bool enable_timer = false; + + if (cdev->rx_coalesce_usecs_irq > 0 && (ir & (IR_RF0N | IR_RF0W))) { + enable_timer = true; + new_interrupts &= ~IR_RF0N; + } else if (!hrtimer_active(&cdev->irq_timer)) { + new_interrupts |= IR_RF0N; + } + + m_can_interrupt_enable(cdev, new_interrupts); + if (enable_timer) { + hrtimer_start(&cdev->irq_timer, + ns_to_ktime(cdev->rx_coalesce_usecs_irq * NSEC_PER_USEC), + HRTIMER_MODE_REL); + } +} + static irqreturn_t m_can_isr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct m_can_classdev *cdev = netdev_priv(dev); u32 ir; - if (pm_runtime_suspended(cdev->dev)) + if (pm_runtime_suspended(cdev->dev)) { + m_can_coalescing_disable(cdev); return IRQ_NONE; + } + ir = m_can_read(cdev, M_CAN_IR); + m_can_coalescing_update(cdev, ir); if (!ir) return IRQ_NONE; @@ -1099,13 +1140,17 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) * - state change IRQ * - bus error IRQ and bus error reporting */ - if ((ir & IR_RF0N) || (ir & IR_ERR_ALL_30X)) { + if (ir & (IR_RF0N | IR_RF0W | IR_ERR_ALL_30X)) { cdev->irqstatus = ir; if (!cdev->is_peripheral) { m_can_disable_all_interrupts(cdev); napi_schedule(&cdev->napi); - } else if (m_can_rx_peripheral(dev, ir) < 0) { - goto out_fail; + } else { + int pkts; + + pkts = m_can_rx_peripheral(dev, ir); + if (pkts < 0) + goto out_fail; } } @@ -1141,6 +1186,15 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static enum hrtimer_restart m_can_irq_timer(struct hrtimer *timer) +{ + struct m_can_classdev *cdev = container_of(timer, struct m_can_classdev, irq_timer); + + irq_wake_thread(cdev->net->irq, cdev->net); + + return HRTIMER_NORESTART; +} + static const struct can_bittiming_const m_can_bittiming_const_30X = { .name = KBUILD_MODNAME, .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ @@ -1281,7 +1335,7 @@ static int m_can_chip_config(struct net_device *dev) /* Disable unused interrupts */ interrupts &= ~(IR_ARA | IR_ELO | IR_DRX | IR_TEFF | IR_TEFW | IR_TFE | IR_TCF | IR_HPM | IR_RF1F | IR_RF1W | IR_RF1N | - IR_RF0F | IR_RF0W); + IR_RF0F); m_can_config_endisable(cdev, true); @@ -1325,6 +1379,7 @@ static int m_can_chip_config(struct net_device *dev) /* rx fifo configuration, blocking mode, fifo size 1 */ m_can_write(cdev, M_CAN_RXF0C, + FIELD_PREP(RXFC_FWM_MASK, cdev->rx_max_coalesced_frames_irq) | FIELD_PREP(RXFC_FS_MASK, cdev->mcfg[MRAM_RXF0].num) | cdev->mcfg[MRAM_RXF0].off); @@ -1383,7 +1438,7 @@ static int m_can_chip_config(struct net_device *dev) else interrupts &= ~(IR_ERR_LEC_31X); } - m_can_write(cdev, M_CAN_IE, interrupts); + m_can_interrupt_enable(cdev, interrupts); /* route all interrupts to INT0 */ m_can_write(cdev, M_CAN_ILS, ILS_ALL_INT0); @@ -2047,6 +2102,9 @@ int m_can_class_register(struct m_can_classdev *cdev) of_can_transceiver(cdev->net); + hrtimer_init(&cdev->irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + cdev->irq_timer.function = m_can_irq_timer; + dev_info(cdev->dev, "%s device registered (irq=%d, version=%d)\n", KBUILD_MODNAME, cdev->net->irq, cdev->version); diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index a839dc71dc9b..c59099d3f5b9 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -84,6 +84,8 @@ struct m_can_classdev { struct sk_buff *tx_skb; struct phy *transceiver; + struct hrtimer irq_timer; + struct m_can_ops *ops; int version; @@ -92,6 +94,11 @@ struct m_can_classdev { int pm_clock_support; int is_peripheral; + // Cached M_CAN_IE register content + u32 active_interrupts; + u32 rx_max_coalesced_frames_irq; + u32 rx_coalesce_usecs_irq; + struct mram_cfg mcfg[MRAM_CFG_NUM]; };