linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, kuba@kernel.org, linux-can@vger.kernel.org,
	kernel@pengutronix.de, Marc Kleine-Budde <mkl@pengutronix.de>,
	Oleksij Rempel <o.rempel@pengutronix.de>,
	Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
Subject: [PATCH net-next 07/46] can: rx-offload: add skb queue for use during ISR
Date: Mon, 26 Jul 2021 16:11:05 +0200	[thread overview]
Message-ID: <20210726141144.862529-8-mkl@pengutronix.de> (raw)
In-Reply-To: <20210726141144.862529-1-mkl@pengutronix.de>

Adding a skb to the skb_queue in rx-offload requires to take a lock.

This commit avoids this by adding an unlocked skb queue that is
appended at the end of the ISR. Having one lock at the end of the ISR
should be OK as the HW is empty, not about to overflow.

Link: https://lore.kernel.org/r/20210724204745.736053-2-mkl@pengutronix.de
Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
Co-developed-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
Signed-off-by: Kurt Van Dijck <dev.kurt@vandijck-laurijssen.be>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/rx-offload.c              | 67 +++++++++----------
 drivers/net/can/flexcan.c                     |  3 +
 drivers/net/can/m_can/m_can.c                 |  3 +
 .../net/can/spi/mcp251xfd/mcp251xfd-core.c    |  6 +-
 drivers/net/can/ti_hecc.c                     |  2 +
 include/linux/can/rx-offload.h                |  2 +
 6 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index ab2c1543786c..d0bdb6db3a57 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2014      Protonic Holland,
  *                         David Jander
- * Copyright (C) 2014-2017 Pengutronix,
+ * Copyright (C) 2014-2021 Pengutronix,
  *                         Marc Kleine-Budde <kernel@pengutronix.de>
  */
 
@@ -174,10 +174,8 @@ can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
 int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
 					 u64 pending)
 {
-	struct sk_buff_head skb_queue;
 	unsigned int i;
-
-	__skb_queue_head_init(&skb_queue);
+	int received = 0;
 
 	for (i = offload->mb_first;
 	     can_rx_offload_le(offload, i, offload->mb_last);
@@ -191,26 +189,12 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
 		if (IS_ERR_OR_NULL(skb))
 			continue;
 
-		__skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare);
-	}
-
-	if (!skb_queue_empty(&skb_queue)) {
-		unsigned long flags;
-		u32 queue_len;
-
-		spin_lock_irqsave(&offload->skb_queue.lock, flags);
-		skb_queue_splice_tail(&skb_queue, &offload->skb_queue);
-		spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
-
-		queue_len = skb_queue_len(&offload->skb_queue);
-		if (queue_len > offload->skb_queue_len_max / 8)
-			netdev_dbg(offload->dev, "%s: queue_len=%d\n",
-				   __func__, queue_len);
-
-		can_rx_offload_schedule(offload);
+		__skb_queue_add_sort(&offload->skb_irq_queue, skb,
+				     can_rx_offload_compare);
+		received++;
 	}
 
-	return skb_queue_len(&skb_queue);
+	return received;
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp);
 
@@ -226,13 +210,10 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
 		if (!skb)
 			break;
 
-		skb_queue_tail(&offload->skb_queue, skb);
+		__skb_queue_tail(&offload->skb_irq_queue, skb);
 		received++;
 	}
 
-	if (received)
-		can_rx_offload_schedule(offload);
-
 	return received;
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
@@ -241,7 +222,6 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 				struct sk_buff *skb, u32 timestamp)
 {
 	struct can_rx_offload_cb *cb;
-	unsigned long flags;
 
 	if (skb_queue_len(&offload->skb_queue) >
 	    offload->skb_queue_len_max) {
@@ -252,11 +232,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 	cb = can_rx_offload_get_cb(skb);
 	cb->timestamp = timestamp;
 
-	spin_lock_irqsave(&offload->skb_queue.lock, flags);
-	__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare);
-	spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
-
-	can_rx_offload_schedule(offload);
+	__skb_queue_add_sort(&offload->skb_irq_queue, skb,
+			     can_rx_offload_compare);
 
 	return 0;
 }
@@ -295,13 +272,33 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
 		return -ENOBUFS;
 	}
 
-	skb_queue_tail(&offload->skb_queue, skb);
-	can_rx_offload_schedule(offload);
+	__skb_queue_tail(&offload->skb_irq_queue, skb);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
 
+void can_rx_offload_irq_finish(struct can_rx_offload *offload)
+{
+	unsigned long flags;
+	int queue_len;
+
+	if (skb_queue_empty_lockless(&offload->skb_irq_queue))
+		return;
+
+	spin_lock_irqsave(&offload->skb_queue.lock, flags);
+	skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
+	spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
+
+	queue_len = skb_queue_len(&offload->skb_queue);
+	if (queue_len > offload->skb_queue_len_max / 8)
+		netdev_dbg(offload->dev, "%s: queue_len=%d\n",
+			   __func__, queue_len);
+
+	can_rx_offload_schedule(offload);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_irq_finish);
+
 static int can_rx_offload_init_queue(struct net_device *dev,
 				     struct can_rx_offload *offload,
 				     unsigned int weight)
@@ -312,6 +309,7 @@ static int can_rx_offload_init_queue(struct net_device *dev,
 	offload->skb_queue_len_max = 2 << fls(weight);
 	offload->skb_queue_len_max *= 4;
 	skb_queue_head_init(&offload->skb_queue);
+	__skb_queue_head_init(&offload->skb_irq_queue);
 
 	netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight);
 
@@ -373,5 +371,6 @@ void can_rx_offload_del(struct can_rx_offload *offload)
 {
 	netif_napi_del(&offload->napi);
 	skb_queue_purge(&offload->skb_queue);
+	__skb_queue_purge(&offload->skb_irq_queue);
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_del);
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 57f3635ad8d7..d9dcf6a8412b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1198,6 +1198,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		}
 	}
 
+	if (handled)
+		can_rx_offload_irq_finish(&priv->offload);
+
 	return handled;
 }
 
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index bba2a449ac70..18461982f7a1 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1058,6 +1058,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
 		}
 	}
 
+	if (cdev->is_peripheral)
+		can_rx_offload_irq_finish(&cdev->offload);
+
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 47c3f408a799..f3b267ec22e0 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -2195,8 +2195,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
 			FIELD_GET(MCP251XFD_REG_INT_IE_MASK,
 				  priv->regs_status.intf);
 
-		if (!(intf_pending))
+		if (!(intf_pending)) {
+			can_rx_offload_irq_finish(&priv->offload);
 			return handled;
+		}
 
 		/* Some interrupts must be ACKed in the
 		 * MCP251XFD_REG_INT register.
@@ -2296,6 +2298,8 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
 	} while (1);
 
  out_fail:
+	can_rx_offload_irq_finish(&priv->offload);
+
 	netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
 		   err, priv->regs_status.intf);
 	mcp251xfd_dump(priv);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 73245d8836a9..353062ead98f 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -786,6 +786,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
 		int_status = hecc_read(priv, HECC_CANGIF0);
 	}
 
+	can_rx_offload_irq_finish(&priv->offload);
+
 	return IRQ_HANDLED;
 }
 
diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h
index 40882df7105e..d71c938e17d0 100644
--- a/include/linux/can/rx-offload.h
+++ b/include/linux/can/rx-offload.h
@@ -20,6 +20,7 @@ struct can_rx_offload {
 					bool drop);
 
 	struct sk_buff_head skb_queue;
+	struct sk_buff_head skb_irq_queue;
 	u32 skb_queue_len_max;
 
 	unsigned int mb_first;
@@ -48,6 +49,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
 					 unsigned int *frame_len_ptr);
 int can_rx_offload_queue_tail(struct can_rx_offload *offload,
 			      struct sk_buff *skb);
+void can_rx_offload_irq_finish(struct can_rx_offload *offload);
 void can_rx_offload_del(struct can_rx_offload *offload);
 void can_rx_offload_enable(struct can_rx_offload *offload);
 
-- 
2.30.2



  parent reply	other threads:[~2021-07-26 14:12 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-26 14:10 pull-request: can-next 2021-07-25 Marc Kleine-Budde
2021-07-26 14:10 ` [PATCH net-next 01/46] can: j1939: j1939_sk_sock_destruct(): correct a grammatical error Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 02/46] can: j1939: fix checkpatch warnings Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 03/46] can: j1939: replace fall through comment by fallthrough pseudo-keyword Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 04/46] can: j1939: j1939_session_completed(): use consistent name se_skb for the session skb Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 05/46] can: j1939: j1939_session_tx_dat(): use consistent name se_skcb for session skb control buffer Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 06/46] can: j1939: j1939_xtp_rx_dat_one(): use separate pointer " Marc Kleine-Budde
2021-07-26 14:11 ` Marc Kleine-Budde [this message]
2021-07-26 14:11 ` [PATCH net-next 08/46] can: rx-offload: can_rx_offload_irq_finish(): directly call napi_schedule() Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 09/46] can: rx-offload: can_rx_offload_threaded_irq_finish(): add new function to be called from threaded interrupt Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 10/46] can: bittiming: fix documentation for struct can_tdc Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 11/46] can: netlink: clear data_bittiming if FD is turned off Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 12/46] can: netlink: remove redundant check in can_validate() Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 13/46] dt-bindings: net: can: Document transceiver implementation as phy Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 14/46] can: m_can: Add support for transceiver " Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 15/46] can: m_can: use devm_platform_ioremap_resource_byname Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 16/46] can: m_can: remove support for custom bit timing Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 17/46] can: mcp251xfd: mcp251xfd_probe(): try to get crystal clock rate from property Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 18/46] can: mcp251xfd: Fix header block to clarify independence from OF Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 19/46] can: mcp251xfd: mcp251xfd_open(): request IRQ as shared Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 20/46] can: esd_usb2: use DEVICE_ATTR_RO() helper macro Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 21/46] can: janz-ican3: use DEVICE_ATTR_RO/RW() " Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 22/46] can: at91_can: use DEVICE_ATTR_RW() " Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 23/46] net: at91_can: remove redundant blank lines Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 24/46] net: at91_can: add blank line after declarations Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 25/46] net: at91_can: fix the code style issue about macro Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 26/46] net: at91_can: use BIT macro Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 27/46] net: at91_can: fix the alignment issue Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 28/46] net: at91_can: add braces {} to all arms of the statement Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 29/46] net: at91_can: remove redundant space Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 30/46] net: at91_can: fix the comments style issue Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 31/46] can: peak_pci: convert comments to network style comments Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 32/46] can: peak_pci: fix checkpatch warnings Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 33/46] can: peak_pci: Add name and FW version of the card in kernel buffer Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 34/46] can: peak_usb: pcan_usb_get_device_id(): read value only in case of success Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 35/46] can: peak_usb: PCAN-USB: add support of loopback and one-shot mode Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 36/46] can: peak_usb: pcan_usb_encode_msg(): add information Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 37/46] can: peak_usb: pcan_usb_decode_error(): upgrade handling of bus state changes Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 38/46] can: etas_es58x: fix three typos in author name and documentation Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 39/46] can: etas_es58x: use error pointer during device probing Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 40/46] can: etas_es58x: use devm_kzalloc() to allocate device resources Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 41/46] can: etas_es58x: add es58x_free_netdevs() to factorize code Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 42/46] can: etas_es58x: use sizeof and sizeof_field macros instead of constant values Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 43/46] can: etas_es58x: rewrite the message cast in es58{1,_fd}_tx_can_msg to increase readability Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 44/46] can: flexcan: add platform data header Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 45/46] can: flexcan: add mcf5441x support Marc Kleine-Budde
2021-07-26 14:11 ` [PATCH net-next 46/46] can: flexcan: update Kconfig to enable coldfire Marc Kleine-Budde
2021-07-26 21:20 ` pull-request: can-next 2021-07-25 patchwork-bot+netdevbpf
2021-08-25 13:55   ` TR: " Stéphane Grosjean
2021-08-25 15:26     ` Marc Kleine-Budde

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210726141144.862529-8-mkl@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=davem@davemloft.net \
    --cc=dev.kurt@vandijck-laurijssen.be \
    --cc=kernel@pengutronix.de \
    --cc=kuba@kernel.org \
    --cc=linux-can@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=o.rempel@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).