summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sperl <kernel@martin.sperl.org>2019-02-10 18:47:15 +0000
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2020-02-09 22:38:56 +0100
commit4633ecd87e2200ccca478a8a5c9f6d0b1d3f82bf (patch)
treeafbe381997429f2bf730ce4a8de289ba9fe43821
parent05bb6fe873e1d595780cf40e2e202f75fa770b23 (diff)
can: mcp25xxfd: optimize reception of big CanFD frame reception with BRS
In case of predicted DLC=15 and in case at least 33% of those are sent via BRS be aggressive and use bulk fifo reads to avoid missing any frames due to releasing FIFOs not as fast as possible. This would be of most impact when having a 1MHz Can Bus with a 8MHz data bitrate. Signed-off-by: Martin Sperl <kernel@martin.sperl.org> (cherry picked from commit c23b97d9301f0683d0064f446cc2116109b03b6b)
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h1
-rw-r--r--drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c48
2 files changed, 35 insertions, 14 deletions
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h
index 1a48e801065d..eeb9c88c7e97 100644
--- a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_priv.h
@@ -178,6 +178,7 @@ struct mcp25xxfd_can_priv {
struct {
#define MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE 32
u8 dlc[MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE];
+ u8 brs[MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE];
u8 index;
u32 predicted_len;
} rx_history;
diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c
index 39b59beb5234..0e3334f83f57 100644
--- a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c
+++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can_rx.c
@@ -104,6 +104,8 @@ int mcp25xxfd_can_rx_submit_frame(struct mcp25xxfd_can_priv *cpriv, int fifo)
/* add to rx_history */
cpriv->rx_history.dlc[cpriv->rx_history.index] = dlc;
+ cpriv->rx_history.brs[cpriv->rx_history.index] =
+ (rx->flags & MCP25XXFD_CAN_OBJ_FLAGS_BRS) ? CANFD_BRS : 0;
cpriv->rx_history.index++;
if (cpriv->rx_history.index >= MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE)
cpriv->rx_history.index = 0;
@@ -395,19 +397,10 @@ static int mcp25xxfd_can_rx_predict_prefetch(struct mcp25xxfd_can_priv *cpriv)
* reading multiple rx fifos is a realistic option of optimization
*/
-/* right now we only optimize for sd (can2.0) frame case,
- * but in principle it could be also be valuable for CANFD
- * frames when we receive lots of 64 byte packets with BRS set
- * and a big difference between nominal and data bitrates
- */
-
-static int mcp25xxfd_can_rx_read_fd_frames(struct mcp25xxfd_can_priv *cpriv)
+static int mcp25xxfd_can_rx_read_single_frames(struct mcp25xxfd_can_priv *cpriv,
+ int prefetch)
{
- int i, f, prefetch;
- int ret;
-
- /* calculate optimal prefetch to use */
- prefetch = mcp25xxfd_can_rx_predict_prefetch(cpriv);
+ int i, f, ret;
/* loop all frames */
for (i = 0, f = cpriv->fifos.rx.start; i < cpriv->fifos.rx.count;
@@ -424,7 +417,7 @@ static int mcp25xxfd_can_rx_read_fd_frames(struct mcp25xxfd_can_priv *cpriv)
return 0;
}
-static int mcp25xxfd_can_rx_read_sd_frames(struct mcp25xxfd_can_priv *cpriv)
+static int mcp25xxfd_can_rx_read_bulk_frames(struct mcp25xxfd_can_priv *cpriv)
{
int i, start, end;
int ret;
@@ -447,12 +440,39 @@ static int mcp25xxfd_can_rx_read_sd_frames(struct mcp25xxfd_can_priv *cpriv)
return 0;
}
+static int mcp25xxfd_can_rx_read_fd_frames(struct mcp25xxfd_can_priv *cpriv)
+{
+ int i, count_dlc15, count_brs, prefetch;
+
+ /* get a prediction on prefetch */
+ prefetch = mcp25xxfd_can_rx_predict_prefetch(cpriv);
+
+ /* if the prefetch is < 64 then just read single */
+ if (prefetch < 64)
+ return mcp25xxfd_can_rx_read_single_frames(cpriv, prefetch);
+
+ /* check if we have mostly brs frames of those DLC=15 frames */
+ for (i = 0, count_brs = 0, count_dlc15 = 0;
+ i < MCP25XXFD_CAN_RX_DLC_HISTORY_SIZE; i++)
+ if (cpriv->rx_history.dlc[i] == 15) {
+ count_dlc15++;
+ if (cpriv->rx_history.brs[i])
+ count_brs++;
+ }
+
+ /* if we have at least 33% brs frames then run bulk */
+ if (count_brs * 3 >= count_dlc15)
+ return mcp25xxfd_can_rx_read_bulk_frames(cpriv);
+ else
+ return mcp25xxfd_can_rx_read_single_frames(cpriv, prefetch);
+}
+
static int mcp25xxfd_can_rx_read_frames(struct mcp25xxfd_can_priv *cpriv)
{
if (cpriv->can.dev->mtu == CANFD_MTU)
return mcp25xxfd_can_rx_read_fd_frames(cpriv);
else
- return mcp25xxfd_can_rx_read_sd_frames(cpriv);
+ return mcp25xxfd_can_rx_read_bulk_frames(cpriv);
}
int mcp25xxfd_can_rx_handle_int_rxif(struct mcp25xxfd_can_priv *cpriv)