Skip to content

Commit 52be626

Browse files
Merge patch series "can: gs_usb: convert to NAPI"
Marc Kleine-Budde <mkl@pengutronix.de> says: Traditionally USB drivers used netif_rx to pass the received CAN frames/skbs to the network stack. In netif_rx() the skbs are queued to the local CPU. If IRQs are handled in round robin, CAN frames may be delivered out-of-order to user space. To support devices without timestamping the TX path of the rx-offload helper is cleaned up and extended: - rename rx_offload_get_echo_skb() -> can_rx_offload_get_echo_skb_queue_timestamp() - add can_rx_offload_get_echo_skb_queue_tail() The last patch converts the gs_usb driver to NAPI with the rx-offload helper. Link: https://lore.kernel.org/all/20230718-gs_usb-rx-offload-v2-0-716e542d14d5@pengutronix.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2 parents 412fbb8 + 24bc41b commit 52be626

File tree

8 files changed

+116
-39
lines changed

8 files changed

+116
-39
lines changed

drivers/net/can/dev/rx-offload.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/* Copyright (c) 2014 Protonic Holland,
33
* David Jander
4-
* Copyright (C) 2014-2021 Pengutronix,
4+
* Copyright (C) 2014-2021, 2023 Pengutronix,
55
* Marc Kleine-Budde <kernel@pengutronix.de>
66
*/
77

@@ -240,9 +240,10 @@ int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
240240
}
241241
EXPORT_SYMBOL_GPL(can_rx_offload_queue_timestamp);
242242

243-
unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
244-
unsigned int idx, u32 timestamp,
245-
unsigned int *frame_len_ptr)
243+
unsigned int
244+
can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload,
245+
unsigned int idx, u32 timestamp,
246+
unsigned int *frame_len_ptr)
246247
{
247248
struct net_device *dev = offload->dev;
248249
struct net_device_stats *stats = &dev->stats;
@@ -262,7 +263,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
262263

263264
return len;
264265
}
265-
EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb);
266+
EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_timestamp);
266267

267268
int can_rx_offload_queue_tail(struct can_rx_offload *offload,
268269
struct sk_buff *skb)
@@ -279,6 +280,31 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
279280
}
280281
EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
281282

283+
unsigned int
284+
can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload,
285+
unsigned int idx,
286+
unsigned int *frame_len_ptr)
287+
{
288+
struct net_device *dev = offload->dev;
289+
struct net_device_stats *stats = &dev->stats;
290+
struct sk_buff *skb;
291+
unsigned int len;
292+
int err;
293+
294+
skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
295+
if (!skb)
296+
return 0;
297+
298+
err = can_rx_offload_queue_tail(offload, skb);
299+
if (err) {
300+
stats->rx_errors++;
301+
stats->tx_fifo_errors++;
302+
}
303+
304+
return len;
305+
}
306+
EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb_queue_tail);
307+
282308
void can_rx_offload_irq_finish(struct can_rx_offload *offload)
283309
{
284310
unsigned long flags;

drivers/net/can/flexcan/flexcan-core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,8 +1097,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
10971097

10981098
handled = IRQ_HANDLED;
10991099
stats->tx_bytes +=
1100-
can_rx_offload_get_echo_skb(&priv->offload, 0,
1101-
reg_ctrl << 16, NULL);
1100+
can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 0,
1101+
reg_ctrl << 16, NULL);
11021102
stats->tx_packets++;
11031103

11041104
/* after sending a RTR frame MB is in RX mode */

drivers/net/can/m_can/m_can.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,10 +1016,10 @@ static void m_can_tx_update_stats(struct m_can_classdev *cdev,
10161016

10171017
if (cdev->is_peripheral)
10181018
stats->tx_bytes +=
1019-
can_rx_offload_get_echo_skb(&cdev->offload,
1020-
msg_mark,
1021-
timestamp,
1022-
NULL);
1019+
can_rx_offload_get_echo_skb_queue_timestamp(&cdev->offload,
1020+
msg_mark,
1021+
timestamp,
1022+
NULL);
10231023
else
10241024
stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL);
10251025

drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
111111
if (skb)
112112
mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts);
113113
stats->tx_bytes +=
114-
can_rx_offload_get_echo_skb(&priv->offload,
115-
tef_tail, hw_tef_obj->ts,
116-
frame_len_ptr);
114+
can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
115+
tef_tail, hw_tef_obj->ts,
116+
frame_len_ptr);
117117
stats->tx_packets++;
118118
priv->tef->tail++;
119119

drivers/net/can/ti_hecc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
747747
spin_unlock_irqrestore(&priv->mbx_lock, flags);
748748
stamp = hecc_read_stamp(priv, mbxno);
749749
stats->tx_bytes +=
750-
can_rx_offload_get_echo_skb(&priv->offload,
751-
mbxno, stamp, NULL);
750+
can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
751+
mbxno, stamp, NULL);
752752
stats->tx_packets++;
753753
--priv->tx_tail;
754754
}

drivers/net/can/usb/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ config CAN_F81604
5252

5353
config CAN_GS_USB
5454
tristate "Geschwister Schneider UG and candleLight compatible interfaces"
55+
select CAN_RX_OFFLOAD
5556
help
5657
This driver supports the Geschwister Schneider and
5758
bytewerk.org candleLight compatible

drivers/net/can/usb/gs_usb.c

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (C) 2013-2016 Geschwister Schneider Technologie-,
66
* Entwicklungs- und Vertriebs UG (Haftungsbeschränkt).
77
* Copyright (C) 2016 Hubert Denkmair
8+
* Copyright (c) 2023 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
89
*
910
* Many thanks to all socketcan devs!
1011
*/
@@ -24,6 +25,7 @@
2425
#include <linux/can.h>
2526
#include <linux/can/dev.h>
2627
#include <linux/can/error.h>
28+
#include <linux/can/rx-offload.h>
2729

2830
/* Device specific constants */
2931
#define USB_GS_USB_1_VENDOR_ID 0x1d50
@@ -282,6 +284,8 @@ struct gs_host_frame {
282284
#define GS_MAX_TX_URBS 10
283285
/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */
284286
#define GS_MAX_RX_URBS 30
287+
#define GS_NAPI_WEIGHT 32
288+
285289
/* Maximum number of interfaces the driver supports per device.
286290
* Current hardware only supports 3 interfaces. The future may vary.
287291
*/
@@ -295,6 +299,7 @@ struct gs_tx_context {
295299
struct gs_can {
296300
struct can_priv can; /* must be the first member */
297301

302+
struct can_rx_offload offload;
298303
struct gs_usb *parent;
299304

300305
struct net_device *netdev;
@@ -506,20 +511,59 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
506511
}
507512
}
508513

509-
static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
510-
const struct gs_host_frame *hf)
514+
static u32 gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
515+
const struct gs_host_frame *hf)
511516
{
512517
u32 timestamp;
513518

514-
if (!(dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP))
515-
return;
516-
517519
if (hf->flags & GS_CAN_FLAG_FD)
518520
timestamp = le32_to_cpu(hf->canfd_ts->timestamp_us);
519521
else
520522
timestamp = le32_to_cpu(hf->classic_can_ts->timestamp_us);
521523

522-
gs_usb_skb_set_timestamp(dev, skb, timestamp);
524+
if (skb)
525+
gs_usb_skb_set_timestamp(dev, skb, timestamp);
526+
527+
return timestamp;
528+
}
529+
530+
static void gs_usb_rx_offload(struct gs_can *dev, struct sk_buff *skb,
531+
const struct gs_host_frame *hf)
532+
{
533+
struct can_rx_offload *offload = &dev->offload;
534+
int rc;
535+
536+
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
537+
const u32 ts = gs_usb_set_timestamp(dev, skb, hf);
538+
539+
rc = can_rx_offload_queue_timestamp(offload, skb, ts);
540+
} else {
541+
rc = can_rx_offload_queue_tail(offload, skb);
542+
}
543+
544+
if (rc)
545+
dev->netdev->stats.rx_fifo_errors++;
546+
}
547+
548+
static unsigned int
549+
gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb,
550+
const struct gs_host_frame *hf)
551+
{
552+
struct can_rx_offload *offload = &dev->offload;
553+
const u32 echo_id = hf->echo_id;
554+
unsigned int len;
555+
556+
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
557+
const u32 ts = gs_usb_set_timestamp(dev, skb, hf);
558+
559+
len = can_rx_offload_get_echo_skb_queue_timestamp(offload, echo_id,
560+
ts, NULL);
561+
} else {
562+
len = can_rx_offload_get_echo_skb_queue_tail(offload, echo_id,
563+
NULL);
564+
}
565+
566+
return len;
523567
}
524568

525569
static void gs_usb_receive_bulk_callback(struct urb *urb)
@@ -592,12 +636,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
592636
gs_update_state(dev, cf);
593637
}
594638

595-
gs_usb_set_timestamp(dev, skb, hf);
596-
597-
stats->rx_packets++;
598-
stats->rx_bytes += hf->can_dlc;
599-
600-
netif_rx(skb);
639+
gs_usb_rx_offload(dev, skb, hf);
601640
} else { /* echo_id == hf->echo_id */
602641
if (hf->echo_id >= GS_MAX_TX_URBS) {
603642
netdev_err(netdev,
@@ -617,12 +656,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
617656
}
618657

619658
skb = dev->can.echo_skb[hf->echo_id];
620-
gs_usb_set_timestamp(dev, skb, hf);
621-
622659
stats->tx_packets++;
623-
stats->tx_bytes += can_get_echo_skb(netdev, hf->echo_id,
624-
NULL);
625-
660+
stats->tx_bytes += gs_usb_get_echo_skb(dev, skb, hf);
626661
gs_free_tx_context(txc);
627662

628663
atomic_dec(&dev->active_tx_urbs);
@@ -641,9 +676,12 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
641676
cf->can_id |= CAN_ERR_CRTL;
642677
cf->len = CAN_ERR_DLC;
643678
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
644-
netif_rx(skb);
679+
680+
gs_usb_rx_offload(dev, skb, hf);
645681
}
646682

683+
can_rx_offload_irq_finish(&dev->offload);
684+
647685
resubmit_urb:
648686
usb_fill_bulk_urb(urb, parent->udev,
649687
usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
@@ -857,6 +895,8 @@ static int gs_can_open(struct net_device *netdev)
857895
dev->hf_size_tx = struct_size(hf, classic_can, 1);
858896
}
859897

898+
can_rx_offload_enable(&dev->offload);
899+
860900
if (!parent->active_channels) {
861901
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
862902
gs_usb_timestamp_init(parent);
@@ -965,6 +1005,7 @@ static int gs_can_open(struct net_device *netdev)
9651005
gs_usb_timestamp_stop(parent);
9661006
}
9671007

1008+
can_rx_offload_disable(&dev->offload);
9681009
close_candev(netdev);
9691010

9701011
return rc;
@@ -1037,6 +1078,8 @@ static int gs_can_close(struct net_device *netdev)
10371078
dev->tx_context[rc].echo_id = GS_MAX_TX_URBS;
10381079
}
10391080

1081+
can_rx_offload_disable(&dev->offload);
1082+
10401083
/* close the netdev */
10411084
close_candev(netdev);
10421085

@@ -1336,18 +1379,21 @@ static struct gs_can *gs_make_candev(unsigned int channel,
13361379
dev->can.data_bittiming_const = &dev->data_bt_const;
13371380
}
13381381

1382+
can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT);
13391383
SET_NETDEV_DEV(netdev, &intf->dev);
13401384

13411385
rc = register_candev(dev->netdev);
13421386
if (rc) {
13431387
dev_err(&intf->dev,
13441388
"Couldn't register candev for channel %d (%pe)\n",
13451389
channel, ERR_PTR(rc));
1346-
goto out_free_candev;
1390+
goto out_can_rx_offload_del;
13471391
}
13481392

13491393
return dev;
13501394

1395+
out_can_rx_offload_del:
1396+
can_rx_offload_del(&dev->offload);
13511397
out_free_candev:
13521398
free_candev(dev->netdev);
13531399
return ERR_PTR(rc);
@@ -1356,6 +1402,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
13561402
static void gs_destroy_candev(struct gs_can *dev)
13571403
{
13581404
unregister_candev(dev->netdev);
1405+
can_rx_offload_del(&dev->offload);
13591406
free_candev(dev->netdev);
13601407
}
13611408

include/linux/can/rx-offload.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* linux/can/rx-offload.h
44
*
55
* Copyright (c) 2014 David Jander, Protonic Holland
6-
* Copyright (c) 2014-2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
6+
* Copyright (c) 2014-2017, 2023 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
77
*/
88

99
#ifndef _CAN_RX_OFFLOAD_H
@@ -44,11 +44,14 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
4444
int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
4545
int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
4646
struct sk_buff *skb, u32 timestamp);
47-
unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
48-
unsigned int idx, u32 timestamp,
49-
unsigned int *frame_len_ptr);
47+
unsigned int can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload,
48+
unsigned int idx, u32 timestamp,
49+
unsigned int *frame_len_ptr);
5050
int can_rx_offload_queue_tail(struct can_rx_offload *offload,
5151
struct sk_buff *skb);
52+
unsigned int can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload,
53+
unsigned int idx,
54+
unsigned int *frame_len_ptr);
5255
void can_rx_offload_irq_finish(struct can_rx_offload *offload);
5356
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload);
5457
void can_rx_offload_del(struct can_rx_offload *offload);

0 commit comments

Comments
 (0)