Skip to content

Commit 82f9e5a

Browse files
committed
can: mcp25xxfd: add prediction of CanFD frames sizes based on history
Allow prediction of can frame sizes based on the last 32 Can Frames received. Naive histogram approach hast been taken for now. Some simple stats based on 1000 frames received with DLC=6: ==> /sys/kernel/debug/mcp25xxfd-spi0.0/can_fifo_rx/rx_reads_prefetched_too_few 16 ==> /sys/kernel/debug/mcp25xxfd-spi0.0/can_fifo_rx/rx_reads_prefetched_too_few_bytes 96 ==> /sys/kernel/debug/mcp25xxfd-spi0.0/can_fifo_rx/rx_reads_prefetched_too_many 0 ==> /sys/kernel/debug/mcp25xxfd-spi0.0/can_fifo_rx/rx_reads_prefetched_too_many_bytes 0 ==> /sys/kernel/debug/mcp25xxfd-spi0.0/can_fifo_rx/rx_reads_prefetch_predicted 6 The first 16 frames are predicted as 0, but after that the prediction is 6. It should be possible to take this prediction to use bulk reads for CanFD as well when we have a prediction of length of 48 or 64. Signed-off-by: Martin Sperl <[email protected]>
1 parent 61b32c5 commit 82f9e5a

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,10 @@ struct mcp25xxfd_can_priv {
640640
u64 rx_bulk_reads;
641641
#define RX_BULK_READ_STATS_BINS 8
642642
u64 rx_bulk_read_sizes[RX_BULK_READ_STATS_BINS];
643+
#define RX_HISTORY_SIZE 32
644+
u8 rx_history_dlc[RX_HISTORY_SIZE];
645+
u8 rx_history_index;
646+
u32 rx_reads_prefetch_predicted;
643647
} stats;
644648

645649
/* bus state */

drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ void mcp25xxfd_can_rx_fifo_debugfs(struct net_device *net)
5353
&cpriv->stats.rx_reads_prefetched_too_many);
5454
debugfs_create_u64("rx_reads_prefetched_too_many_bytes", 0444, dir,
5555
&cpriv->stats.rx_reads_prefetched_too_many_bytes);
56+
debugfs_create_u32("rx_reads_prefetch_predicted", 0444, dir,
57+
&cpriv->stats.rx_reads_prefetch_predicted);
5658

5759
/* present the fifos */
5860
for (i = 0; i < RX_BULK_READ_STATS_BINS - 2; i++) {
@@ -73,6 +75,40 @@ void mcp25xxfd_can_rx_fifo_debugfs(struct net_device *net)
7375
}
7476
#endif
7577

78+
static int mcp25xxfd_can_rx_predict_prefetch(struct net_device *net)
79+
{
80+
struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
81+
int dlc, i, highest;
82+
u8 histo[16];
83+
84+
/* if we have a prfecth set then use that one */
85+
if (rx_prefetch_bytes != -1)
86+
return min_t(int, rx_prefetch_bytes,
87+
(net->mtu == CANFD_MTU) ? 64 : 8);
88+
89+
/* memset */
90+
memset(histo, 0, sizeof(histo));
91+
92+
/* for all others compute the histogram */
93+
for (i = 0; i < RX_HISTORY_SIZE; i++)
94+
histo[cpriv->stats.rx_history_dlc[i]]++;
95+
96+
/* and now find the highest fit */
97+
for (i = (net->mtu == CANFD_MTU) ? 15 : 8, dlc = 8, highest = 0;
98+
i >= 0; i--) {
99+
if (highest < histo[i]) {
100+
highest = histo[i];
101+
dlc = i;
102+
}
103+
}
104+
105+
/* compute length from dlc */
106+
cpriv->stats.rx_reads_prefetch_predicted = can_dlc2len(dlc);
107+
108+
/* return the predicted length */
109+
return cpriv->stats.rx_reads_prefetch_predicted;
110+
}
111+
76112
static
77113
struct sk_buff *mcp25xxfd_can_submit_rx_normal_frame(struct net_device *net,
78114
u32 id,
@@ -148,6 +184,12 @@ int mcp25xxfd_can_submit_rx_frame(struct spi_device *spi, int fifo)
148184
if (rx->flags & CAN_OBJ_FLAGS_FDF)
149185
cpriv->fifos.rx.fd_count++;
150186

187+
/* add to rx_dlc_history */
188+
cpriv->stats.rx_history_dlc[cpriv->stats.rx_history_index] = dlc;
189+
cpriv->stats.rx_history_index++;
190+
if (cpriv->stats.rx_history_index >= RX_HISTORY_SIZE)
191+
cpriv->stats.rx_history_index = 0;
192+
151193
/* allocate the skb buffer */
152194
if (rx->flags & CAN_OBJ_FLAGS_FDF) {
153195
flags = 0;
@@ -413,10 +455,7 @@ static int mcp25xxfd_can_read_rx_frames_fd(struct spi_device *spi)
413455
int ret;
414456

415457
/* calculate optimal prefetch to use */
416-
if (rx_prefetch_bytes != -1)
417-
prefetch = min_t(int, rx_prefetch_bytes, 64);
418-
else
419-
prefetch = 8;
458+
prefetch = mcp25xxfd_can_rx_predict_prefetch(net);
420459

421460
/* loop all frames */
422461
for (i = 0, fifo = cpriv->fifos.rx.start;

0 commit comments

Comments
 (0)