From patchwork Sun Jul 25 16:11:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 485778 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B78BBC4320A for ; Sun, 25 Jul 2021 16:12:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9BABD60F57 for ; Sun, 25 Jul 2021 16:12:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230507AbhGYPbm (ORCPT ); Sun, 25 Jul 2021 11:31:42 -0400 Received: from smtp-34.italiaonline.it ([213.209.10.34]:51765 "EHLO libero.it" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S230193AbhGYPbb (ORCPT ); Sun, 25 Jul 2021 11:31:31 -0400 Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.45.45.231]) by smtp-34.iol.local with ESMTPA id 7gjJmU9oJLCum7gjQmo2af; Sun, 25 Jul 2021 18:12:00 +0200 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2021; t=1627229520; bh=ukKbkV8ZQ3gcpPYd1NqECiAHtTGPMg1hlJa5khe340Q=; h=From; b=EpPZYY5ByvJp0lrg1Zi6s5oGl90NKPFWe7w2qYKcpi93QwgSFEc3fisX7nVCs9U0L M5Qi96g0Owbbadf/XwR3tnI8KUXKvXsnFCTP1jKhtgHw63JlfEGihNAbPh6E0vBW3o qzUZhn6LOdYst87GRu+MNjQY9H3CbkuaOt6kJjZ3cvG/9smGo518a0PARUg12ItvQ5 HcptLC7dkClRSmavEgT7OvmYUIpJXTLmsc9F3nSxGeb2S4jx2PUhfSJeA0Qe6GN4XS upj2qxEX9s2USjemCoVG0ZLm3l/UBYATwkN4nmFNCM0oouFWrZ3GiHiNzE79AvN9vv k/qSSvUc6fdvQ== X-CNFS-Analysis: v=2.4 cv=a8D1SWeF c=1 sm=1 tr=0 ts=60fd8d50 cx=a_exe a=TX8r+oJM0yLPAmPh5WrBoQ==:117 a=TX8r+oJM0yLPAmPh5WrBoQ==:17 a=TSeAaTSCjiJB7GOU1roA:9 From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: Gianluca Falavigna , Dario Binacchi , Andrew Lunn , "David S. Miller" , Jakub Kicinski , Marc Kleine-Budde , Tong Zhang , Wolfgang Grandegger , linux-can@vger.kernel.org, netdev@vger.kernel.org Subject: [RESEND PATCH 1/4] can: c_can: remove struct c_can_priv::priv field Date: Sun, 25 Jul 2021 18:11:47 +0200 Message-Id: <20210725161150.11801-2-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210725161150.11801-1-dariobin@libero.it> References: <20210725161150.11801-1-dariobin@libero.it> X-CMAE-Envelope: MS4xfJeXdyHedOw0ts0LyJhcJzHXuN79YT/uv4IU9SvVqG08qfRMLNlv01T3VreYJagfFelH1UkoxTG5hGKvwCIdVTCUWm9t9iBddkNTXrLCgUsDFDcYHipC rV3o9uuDGwfWkXjkyxhIirLue12LMjjo2PxzGhI4MlgU5uVqOW5Bvqdc3kAmPd4cqIXKNi4ibjI2qhQQ2YataYb0aV4F8BLRZnEUDqknyrwPcfIvXq3K9DFa LrL512c0PGvbr30Zt7lnxKnEFJIWAw5pjl2V+RfDLghxfInctamQSyl+ldXca4DPDB9cbx5ENPuUSXzqxgsdCT9KwznwVnJH17Q0zUH47HxA3wGKvugpWZK5 miB2tO7sqKkP+w3CdDPdi/70QPrsx3nw03R+c6Le60oIm6xZmNudDl8LWdnp2yyiDKNEBGPiBKmKqhIVgN+Pjcr1TLvQiWmLekI/dJArcj9oHQlVO+4SwmDa +QYq3xHpB7Zkg5qBchD5X6ZjyKT8TPj3l5wxDYaouXu4kM/vMcjE+L+Eh+fde5gvqAiSspFB9pOghDW4 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org It references the clock but it is never used. So let's remove it. Signed-off-by: Dario Binacchi --- drivers/net/can/c_can/c_can.h | 1 - drivers/net/can/c_can/c_can_platform.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 4247ff80a29c..8f23e9c83c84 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -200,7 +200,6 @@ struct c_can_priv { void (*write_reg32)(const struct c_can_priv *priv, enum reg index, u32 val); void __iomem *base; const u16 *regs; - void *priv; /* for board-specific data */ enum c_can_dev_id type; struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */ void (*raminit)(const struct c_can_priv *priv, bool enable); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 36950363682f..86e95e9d6533 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -385,7 +385,6 @@ static int c_can_plat_probe(struct platform_device *pdev) priv->base = addr; priv->device = &pdev->dev; priv->can.clock.freq = clk_get_rate(clk); - priv->priv = clk; priv->type = drvdata->id; platform_set_drvdata(pdev, dev); From patchwork Sun Jul 25 16:11:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 486246 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D93FC432BE for ; Sun, 25 Jul 2021 16:12:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5624860F39 for ; Sun, 25 Jul 2021 16:12:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230471AbhGYPbj (ORCPT ); Sun, 25 Jul 2021 11:31:39 -0400 Received: from smtp-34-i2.italiaonline.it ([213.209.12.34]:49449 "EHLO libero.it" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S230261AbhGYPbc (ORCPT ); Sun, 25 Jul 2021 11:31:32 -0400 Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.45.45.231]) by smtp-34.iol.local with ESMTPA id 7gjJmU9oJLCum7gjQmo2ay; Sun, 25 Jul 2021 18:12:01 +0200 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2021; t=1627229521; bh=aipa+Z7keBjj+2EjLI43y9cbq8bUs5mFT1fgia6YCVA=; h=From; b=PvTfF9O4pQvzTe/7xgPFFOHWAqMqnpqBE2LV4M/fa4Hoej4zOaEzkGprJThOihOP7 LeWmMSeHpg9+NvI1hYOHVoRtd0Q4iAUV5dMlg3ZUXcs0m+LYzfSyZ5UvwH2X6kcNgV OA/3mrw3SSHj3JwOok/UbdD/QNLSszs62n/rJfi69UUbyr0VwLkvAQ3mP+tZpWF+Vn aDFqL5xlWn2BqfAui/7WJ4i+V5g+maxZXociRtftR3hVtbUoG2ofIY0OJmEkxnGMsl KUNsYE/24tVWV/IiOp1J3ynqmGvsqB56iY3ObpF1jywU+0rB3YDgN8OCzTXo15IiBy DbiVhFwz/h1NA== X-CNFS-Analysis: v=2.4 cv=a8D1SWeF c=1 sm=1 tr=0 ts=60fd8d51 cx=a_exe a=TX8r+oJM0yLPAmPh5WrBoQ==:117 a=TX8r+oJM0yLPAmPh5WrBoQ==:17 a=0RFnQWo-as75lT-uasUA:9 From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: Gianluca Falavigna , Dario Binacchi , "David S. Miller" , Jakub Kicinski , Marc Kleine-Budde , Oliver Hartkopp , Vincent Mailhol , Wolfgang Grandegger , linux-can@vger.kernel.org, netdev@vger.kernel.org Subject: [RESEND PATCH 2/4] can: c_can: exit c_can_do_tx() early if no frames have been sent Date: Sun, 25 Jul 2021 18:11:48 +0200 Message-Id: <20210725161150.11801-3-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210725161150.11801-1-dariobin@libero.it> References: <20210725161150.11801-1-dariobin@libero.it> X-CMAE-Envelope: MS4xfNA4QVyiaiFewOl+nU41eANhJeeO/BmmBM3xrAsuJNLHzhEpIjPTsVS1RaaOwvRwhsAWm2kuFXTzHAtkjweyAAr4+lyAsE+pgMd2Rv0SOeKwx3UOlPq+ oSbBplIAsJJmE85TQT29nszBLFYKpQ7RiLmIQNf6tceSbqmoPFWIFiNAnXpjcplK+e39xstj7Fs3pYrnzy2UtVKGBlvctCYVbAFHnZQzF6wGP6N4gq/3phVM +sQ3XUCHdegVjvKChbQIYyPBb4F3wAp5OkhMzCvGC+0gGTfaBTZFjDBKCL7SR7888+vX3ThmnmuWT9VWC6ZNxO65CMW+nN7Cg6h/1AZPmtBs6zbnSl8tECMz u06JEFGLz4gtruHA6HBUJy0nGdLOf7cJwy/8rmUGKf5uqyDXFDDVQfLtGFuKET34PYctg2FIrU7WmUet3+vWaZ0yAs8RAHqf0Cfc7LxOmGcCjJGnno1rUGKy VbQ0B9eYnslSMmeQWq6ZDxb6nJnPmeAVUA3nKJUAQaEJskDeVWUksWjork/PCA88VXewRIz6Ybj6bGyueEatvjPoQTtETMbTRFYIcQ== Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The c_can_poll() handles RX/TX events unconditionally. It may therefore happen that c_can_do_tx() is called unnecessarily because the interrupt was triggered by the reception of a frame. In these cases, we avoid to execute unnecessary statements and exit immediately. Signed-off-by: Dario Binacchi --- drivers/net/can/c_can/c_can_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index 7588f70ca0fe..fec0e3416970 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -720,17 +720,18 @@ static void c_can_do_tx(struct net_device *dev) pkts++; } + if (!pkts) + return; + /* Clear the bits in the tx_active mask */ atomic_sub(clr, &priv->tx_active); if (clr & BIT(priv->msg_obj_tx_num - 1)) netif_wake_queue(dev); - if (pkts) { - stats->tx_bytes += bytes; - stats->tx_packets += pkts; - can_led_event(dev, CAN_LED_EVENT_TX); - } + stats->tx_bytes += bytes; + stats->tx_packets += pkts; + can_led_event(dev, CAN_LED_EVENT_TX); } /* If we have a gap in the pending bits, that means we either From patchwork Sun Jul 25 16:11:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 486247 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1690C4320E for ; Sun, 25 Jul 2021 16:12:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D26C76069E for ; Sun, 25 Jul 2021 16:12:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230433AbhGYPbf (ORCPT ); Sun, 25 Jul 2021 11:31:35 -0400 Received: from smtp-34-i2.italiaonline.it ([213.209.12.34]:40694 "EHLO libero.it" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S230312AbhGYPbc (ORCPT ); Sun, 25 Jul 2021 11:31:32 -0400 Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.45.45.231]) by smtp-34.iol.local with ESMTPA id 7gjJmU9oJLCum7gjRmo2bI; Sun, 25 Jul 2021 18:12:01 +0200 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2021; t=1627229521; bh=VGNCFLBzeyw84IVyEb6PZZrx3WMwI604pwR2tdhmc4g=; h=From; b=VHnQzkMVCc7OEUzPRANx/n/9VZDYPiqQsk0N1hseCtEtHqzLIgMK1NV7QUgLQUN5I olVED7M6LBNAF3oWsGzCIkOPGl/eRZmvsacbfPK0NevWdrINa0CWqlR6cfR38jz3AE 5QLQMrr2v91mBcmImiE3E7TTvUeIPzEMSjN1wD9SCioinTddruyMK0DLryjZKGRLXn ckJmT7Ala5cJOy5snKHDMCwx0p7C5joHKYoMM6z5rDguI+ryozri0dxVME6Cff//wU owrRSxTFo3Tr36haBNuaXSRvL7js9bFYdlc+OdXEVoCKK/BgsfoenQtOomQQ2aakKQ t7jg3qUt2EQfw== X-CNFS-Analysis: v=2.4 cv=a8D1SWeF c=1 sm=1 tr=0 ts=60fd8d51 cx=a_exe a=TX8r+oJM0yLPAmPh5WrBoQ==:117 a=TX8r+oJM0yLPAmPh5WrBoQ==:17 a=VwQbUJbxAAAA:8 a=83yiEfbaggHBMMd4CMwA:9 a=TlxWwjO5pACKU3_K:21 a=9s_oUIA50SGwrPgz:21 a=AjGcO6oz07-iQ99wixmX:22 From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: Gianluca Falavigna , Dario Binacchi , Andrew Lunn , "David S. Miller" , Jakub Kicinski , Marc Kleine-Budde , Oliver Hartkopp , Vincent Mailhol , Wolfgang Grandegger , linux-can@vger.kernel.org, netdev@vger.kernel.org Subject: [RESEND PATCH 3/4] can: c_can: support tx ring algorithm Date: Sun, 25 Jul 2021 18:11:49 +0200 Message-Id: <20210725161150.11801-4-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210725161150.11801-1-dariobin@libero.it> References: <20210725161150.11801-1-dariobin@libero.it> X-CMAE-Envelope: MS4xfNA4QVyiaiFewOl+nU41eANhJeeO/BmmBM3xrAsuJNLHzhEpIjPTsVS1RaaOwvRwhsAWm2kuFXTzHAtkjweyAAr4+lyAsE+pgMd2Rv0SOeKwx3UOlPq+ oSbBplIAsJJmE85TQT29nszBLFYKpQ7RiLmIQNf6tceSbqmoPFWIFiNAEC9Hb34WPel/70THbCMkVUxXNZgKcRWgCStBbkuUwc2LDZby2gGm3HWexmuZmRK+ Zw+wnEcTHmmnbOqjTKpaTprWWus5aeldBKTS9e5ZXNIvZCiVNCzUk12tNvA1VOgQoPOjmerRynaugw7jSLb/SDIOoUrcfh7AMYeoOSJkGxuQvhKd+EwxWmt0 xvVSoOAyzIjwA4SscwfFMM7A1TPb12gayNMBBkbuBTp5bwi8YVksIbbkQyE86kmwccRHkllH6kQDi8lOf3t8XvUQ5udZpOIbJStFnWJy5V26uK/KxLoSsIwW oiAqwTMrQq0ndFto1ri0Tp1oykBK1JmGjwgnGxTUuOMZqB68tAkltU4kBM1MBgeDsYYZr4HTHXwFXlCS8tsvGSnBPQPVm+XXJU8kPAiu3XkD02YABDMwLe8r wV4= Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The algorithm is already used successfully by other CAN drivers (e.g. mcp251xfd). Its implementation was kindly suggested to me by Marc Kleine-Budde following a patch I had previously submitted. You can find every detail at https://lore.kernel.org/patchwork/patch/1422929/. The idea is that after this patch, it will be easier to patch the driver to use the message object memory as a true FIFO. Suggested-by: Marc Kleine-Budde Signed-off-by: Dario Binacchi --- drivers/net/can/c_can/c_can.h | 19 ++++++- drivers/net/can/c_can/c_can_main.c | 81 +++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 8f23e9c83c84..8fe7e2138620 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -176,6 +176,13 @@ struct c_can_raminit { bool needs_pulse; }; +/* c_can tx ring structure */ +struct c_can_tx_ring { + unsigned int head; + unsigned int tail; + unsigned int obj_num; +}; + /* c_can private data structure */ struct c_can_priv { struct can_priv can; /* must be the first member */ @@ -190,10 +197,10 @@ struct c_can_priv { unsigned int msg_obj_tx_first; unsigned int msg_obj_tx_last; u32 msg_obj_rx_mask; - atomic_t tx_active; atomic_t sie_pending; unsigned long tx_dir; int last_status; + struct c_can_tx_ring tx; u16 (*read_reg)(const struct c_can_priv *priv, enum reg index); void (*write_reg)(const struct c_can_priv *priv, enum reg index, u16 val); u32 (*read_reg32)(const struct c_can_priv *priv, enum reg index); @@ -219,4 +226,14 @@ int c_can_power_down(struct net_device *dev); void c_can_set_ethtool_ops(struct net_device *dev); +static inline u8 c_can_get_tx_head(const struct c_can_tx_ring *ring) +{ + return ring->head & (ring->obj_num - 1); +} + +static inline u8 c_can_get_tx_tail(const struct c_can_tx_ring *ring) +{ + return ring->tail & (ring->obj_num - 1); +} + #endif /* C_CAN_H */ diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index fec0e3416970..451ac9a9586a 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -427,24 +427,64 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface, c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP); } +static u8 c_can_get_tx_free(const struct c_can_tx_ring *ring) +{ + u8 head = c_can_get_tx_head(ring); + u8 tail = c_can_get_tx_tail(ring); + + /* This is not a FIFO. C/D_CAN sends out the buffers + * prioritized. The lowest buffer number wins. + */ + if (head < tail) + return 0; + + return ring->obj_num - head; +} + +static bool c_can_tx_busy(const struct c_can_priv *priv, + const struct c_can_tx_ring *tx_ring) +{ + if (c_can_get_tx_free(tx_ring) > 0) + return false; + + netif_stop_queue(priv->dev); + + /* Memory barrier before checking tx_free (head and tail) */ + smp_mb(); + + if (c_can_get_tx_free(tx_ring) == 0) { + netdev_dbg(priv->dev, + "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", + tx_ring->head, tx_ring->tail, + tx_ring->head - tx_ring->tail); + return true; + } + + netif_start_queue(priv->dev); + return false; +} + static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct can_frame *frame = (struct can_frame *)skb->data; struct c_can_priv *priv = netdev_priv(dev); + struct c_can_tx_ring *tx_ring = &priv->tx; u32 idx, obj; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; - /* This is not a FIFO. C/D_CAN sends out the buffers - * prioritized. The lowest buffer number wins. - */ - idx = fls(atomic_read(&priv->tx_active)); - obj = idx + priv->msg_obj_tx_first; - /* If this is the last buffer, stop the xmit queue */ - if (idx == priv->msg_obj_tx_num - 1) + if (c_can_tx_busy(priv, tx_ring)) + return NETDEV_TX_BUSY; + + idx = c_can_get_tx_head(tx_ring); + tx_ring->head++; + if (c_can_get_tx_free(tx_ring) == 0) netif_stop_queue(dev); + + obj = idx + priv->msg_obj_tx_first; + /* Store the message in the interface so we can call * can_put_echo_skb(). We must do this before we enable * transmit as we might race against do_tx(). @@ -453,8 +493,6 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, priv->dlc[idx] = frame->len; can_put_echo_skb(skb, dev, idx, 0); - /* Update the active bits */ - atomic_add(BIT(idx), &priv->tx_active); /* Start transmission */ c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); @@ -567,6 +605,7 @@ static int c_can_software_reset(struct net_device *dev) static int c_can_chip_config(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); + struct c_can_tx_ring *tx_ring = &priv->tx; int err; err = c_can_software_reset(dev); @@ -598,7 +637,8 @@ static int c_can_chip_config(struct net_device *dev) priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); /* Clear all internal status */ - atomic_set(&priv->tx_active, 0); + tx_ring->head = 0; + tx_ring->tail = 0; priv->tx_dir = 0; /* set bittiming params */ @@ -696,14 +736,14 @@ static int c_can_get_berr_counter(const struct net_device *dev, static void c_can_do_tx(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); + struct c_can_tx_ring *tx_ring = &priv->tx; struct net_device_stats *stats = &dev->stats; - u32 idx, obj, pkts = 0, bytes = 0, pend, clr; + u32 idx, obj, pkts = 0, bytes = 0, pend; if (priv->msg_obj_tx_last > 32) pend = priv->read_reg32(priv, C_CAN_INTPND3_REG); else pend = priv->read_reg(priv, C_CAN_INTPND2_REG); - clr = pend; while ((idx = ffs(pend))) { idx--; @@ -723,11 +763,14 @@ static void c_can_do_tx(struct net_device *dev) if (!pkts) return; - /* Clear the bits in the tx_active mask */ - atomic_sub(clr, &priv->tx_active); - - if (clr & BIT(priv->msg_obj_tx_num - 1)) - netif_wake_queue(dev); + tx_ring->tail += pkts; + if (c_can_get_tx_free(tx_ring)) { + /* Make sure that anybody stopping the queue after + * this sees the new tx_ring->tail. + */ + smp_mb(); + netif_wake_queue(priv->dev); + } stats->tx_bytes += bytes; stats->tx_packets += pkts; @@ -1206,6 +1249,10 @@ struct net_device *alloc_c_can_dev(int msg_obj_num) priv->msg_obj_tx_last = priv->msg_obj_tx_first + priv->msg_obj_tx_num - 1; + priv->tx.head = 0; + priv->tx.tail = 0; + priv->tx.obj_num = msg_obj_tx_num; + netif_napi_add(dev, &priv->napi, c_can_poll, priv->msg_obj_rx_num); priv->dev = dev; From patchwork Sun Jul 25 16:11:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 485777 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA6EDC432BE for ; Sun, 25 Jul 2021 16:13:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BDAF86069E for ; Sun, 25 Jul 2021 16:13:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231208AbhGYPcd (ORCPT ); Sun, 25 Jul 2021 11:32:33 -0400 Received: from smtp-34-i2.italiaonline.it ([213.209.12.34]:40694 "EHLO libero.it" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S230193AbhGYPcc (ORCPT ); Sun, 25 Jul 2021 11:32:32 -0400 Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.45.45.231]) by smtp-34.iol.local with ESMTPA id 7gjJmU9oJLCum7gjSmo2bn; Sun, 25 Jul 2021 18:12:02 +0200 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2021; t=1627229522; bh=KWD/wzdaPvT0fsYgJVYpslUqQQ4hDFaggJS+tSzFXM8=; h=From; b=QliIcZ4I+F5R8H0t27EFH9yzE0ICwZGsMia4BsOnFHi5QH+RM0FmG+AXw9us5wG1a 02VtPbFQkuL+uR2pjJNdaQgYmWUbAIcCSvbYdLBglTBpg3DLy7AsTdYrBsO1TgItZa Fs3ZjiwpWdFMrotiYTKerg/TZD2N3LbGMaeqjtoEaghQZfbT5DO/5ivHnTlb4IWaBX XwnkQnK3Rn5uY5YXzkJYzL1tmIv09HnrA3qzRKd4Q1zqHBxX6j8aVmowlOOIHgnsqD tcAzu9M1/kkGEe2hYL9sqyR0gisKFMFYlcCEG6Q4GI9S9j3Ny3UxBJFE7usHPCvhM8 P42q2ajitEfSA== X-CNFS-Analysis: v=2.4 cv=a8D1SWeF c=1 sm=1 tr=0 ts=60fd8d52 cx=a_exe a=TX8r+oJM0yLPAmPh5WrBoQ==:117 a=TX8r+oJM0yLPAmPh5WrBoQ==:17 a=ci6mTl68RD0LDj9SGHYA:9 a=zPaA-w0dnRgsZjSy:21 a=aeJ6SaH8bT6bZ-aJ:21 From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: Gianluca Falavigna , Dario Binacchi , Andrew Lunn , "David S. Miller" , Jakub Kicinski , Marc Kleine-Budde , Oliver Hartkopp , Vincent Mailhol , Wolfgang Grandegger , linux-can@vger.kernel.org, netdev@vger.kernel.org Subject: [RESEND PATCH 4/4] can: c_can: cache frames to operate as a true FIFO Date: Sun, 25 Jul 2021 18:11:50 +0200 Message-Id: <20210725161150.11801-5-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210725161150.11801-1-dariobin@libero.it> References: <20210725161150.11801-1-dariobin@libero.it> X-CMAE-Envelope: MS4xfIdjIeQbYQxCHXI1IzDDSRX94empUNn2kdd8dI6AHTZ1bBFklhiaYMo7vYRy+DDyhS6t+/ME0UOY1G8D/po+eBY1qs8J3MY5I98L7np9Ctmcd4JIdK7m hBpPdwUJjASEqHRnqfKl7arzyn+XVQWQqu3nCl270SftmXUvcc2N/mSNAYxZ0vr8WpvfJdBNNaZ0npEgXBtIddt4l1j1fTe9CHOnbfDBWUCMQ7RVijfM8JPn sDk827U7rb4thhOkc9xeF7qvcWlO2zuw0Z6QZg0GDv3T7kNSvteyqKvr+QOgIXKZ/ATHCcR1+pL7vMlBZ7XImYzS6BGq68Zl+ij7iBOp9DgSx4dy9a670UlO 5abUw975TL0zt46xuLyHKZZgZaYlMevW9uu9z9JqSCKhG2KQO5nUiXZLTgDEMcxWlaqPRngji74Tsvsb1M/NzCos1YbMqvHHS4PuYnIx6SOnaBntYarUTHUh Gk6gnmK7vKu9Mvf9mqc7Vq+ALD5cS6v371rpzQUM7Mf7z5MnUFjJ3AKbOodDfQvICxvDaJzNZhvgHVOrkPh4VHUtNVVRkeybxoRLGuGL/vmX2ArPDqNTEYIS /TY= Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org As reported by a comment in the c_can_start_xmit() this was not a FIFO. C/D_CAN controller sends out the buffers prioritized so that the lowest buffer number wins. What did c_can_start_xmit() do if head was less tail in the tx ring ? It waited until all the frames queued in the FIFO was actually transmitted by the controller before accepting a new CAN frame to transmit, even if the FIFO was not full, to ensure that the messages were transmitted in the order in which they were loaded. By storing the frames in the FIFO without requiring its transmission, we will be able to use the full size of the FIFO even in cases such as the one described above. The transmission interrupt will trigger their transmission only when all the messages previously loaded but stored in less priority positions of the buffers have been transmitted. Suggested-by: Gianluca Falavigna Signed-off-by: Dario Binacchi --- drivers/net/can/c_can/c_can.h | 6 +++++ drivers/net/can/c_can/c_can_main.c | 42 +++++++++++++++++------------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 8fe7e2138620..fc499a70b797 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -200,6 +200,7 @@ struct c_can_priv { atomic_t sie_pending; unsigned long tx_dir; int last_status; + spinlock_t tx_lock; struct c_can_tx_ring tx; u16 (*read_reg)(const struct c_can_priv *priv, enum reg index); void (*write_reg)(const struct c_can_priv *priv, enum reg index, u16 val); @@ -236,4 +237,9 @@ static inline u8 c_can_get_tx_tail(const struct c_can_tx_ring *ring) return ring->tail & (ring->obj_num - 1); } +static inline u8 c_can_get_tx_free(const struct c_can_tx_ring *ring) +{ + return ring->obj_num - (ring->head - ring->tail); +} + #endif /* C_CAN_H */ diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c index 451ac9a9586a..4c061fef002c 100644 --- a/drivers/net/can/c_can/c_can_main.c +++ b/drivers/net/can/c_can/c_can_main.c @@ -427,20 +427,6 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface, c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP); } -static u8 c_can_get_tx_free(const struct c_can_tx_ring *ring) -{ - u8 head = c_can_get_tx_head(ring); - u8 tail = c_can_get_tx_tail(ring); - - /* This is not a FIFO. C/D_CAN sends out the buffers - * prioritized. The lowest buffer number wins. - */ - if (head < tail) - return 0; - - return ring->obj_num - head; -} - static bool c_can_tx_busy(const struct c_can_priv *priv, const struct c_can_tx_ring *tx_ring) { @@ -470,7 +456,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, struct can_frame *frame = (struct can_frame *)skb->data; struct c_can_priv *priv = netdev_priv(dev); struct c_can_tx_ring *tx_ring = &priv->tx; - u32 idx, obj; + u32 idx, obj, cmd = IF_COMM_TX; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; @@ -483,7 +469,11 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, if (c_can_get_tx_free(tx_ring) == 0) netif_stop_queue(dev); - obj = idx + priv->msg_obj_tx_first; + spin_lock_bh(&priv->tx_lock); + if (idx < c_can_get_tx_tail(tx_ring)) + cmd &= ~IF_COMM_TXRQST; /* Cache the message */ + else + spin_unlock_bh(&priv->tx_lock); /* Store the message in the interface so we can call * can_put_echo_skb(). We must do this before we enable @@ -492,9 +482,11 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, c_can_setup_tx_object(dev, IF_TX, frame, idx); priv->dlc[idx] = frame->len; can_put_echo_skb(skb, dev, idx, 0); + obj = idx + priv->msg_obj_tx_first; + c_can_object_put(dev, IF_TX, obj, cmd); - /* Start transmission */ - c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); + if (spin_is_locked(&priv->tx_lock)) + spin_unlock_bh(&priv->tx_lock); return NETDEV_TX_OK; } @@ -739,6 +731,7 @@ static void c_can_do_tx(struct net_device *dev) struct c_can_tx_ring *tx_ring = &priv->tx; struct net_device_stats *stats = &dev->stats; u32 idx, obj, pkts = 0, bytes = 0, pend; + u8 tail; if (priv->msg_obj_tx_last > 32) pend = priv->read_reg32(priv, C_CAN_INTPND3_REG); @@ -775,6 +768,18 @@ static void c_can_do_tx(struct net_device *dev) stats->tx_bytes += bytes; stats->tx_packets += pkts; can_led_event(dev, CAN_LED_EVENT_TX); + + tail = c_can_get_tx_tail(tx_ring); + + if (tail == 0) { + u8 head = c_can_get_tx_head(tx_ring); + + /* Start transmission for all cached messages */ + for (idx = tail; idx < head; idx++) { + obj = idx + priv->msg_obj_tx_first; + c_can_object_put(dev, IF_TX, obj, IF_COMM_TXRQST); + } + } } /* If we have a gap in the pending bits, that means we either @@ -1237,6 +1242,7 @@ struct net_device *alloc_c_can_dev(int msg_obj_num) return NULL; priv = netdev_priv(dev); + spin_lock_init(&priv->tx_lock); priv->msg_obj_num = msg_obj_num; priv->msg_obj_rx_num = msg_obj_num - msg_obj_tx_num; priv->msg_obj_rx_first = 1;