Skip to content

Commit

Permalink
can: m_can: Batch FIFO writes during CAN transmit
Browse files Browse the repository at this point in the history
Give FIFO writes the same treatment as reads to avoid fixed costs of
individual transfers on a slow bus (e.g., tcan4x5x).

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Matt Kline <[email protected]>
Signed-off-by: Marc Kleine-Budde <[email protected]>
  • Loading branch information
mrkline authored and marckleinebudde committed Aug 19, 2021
1 parent 1aa6772 commit 812270e
Showing 1 changed file with 26 additions and 35 deletions.
61 changes: 26 additions & 35 deletions drivers/net/can/m_can/m_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ enum m_can_reg {
/* Message RAM Elements */
#define M_CAN_FIFO_ID 0x0
#define M_CAN_FIFO_DLC 0x4
#define M_CAN_FIFO_DATA(n) (0x8 + ((n) << 2))
#define M_CAN_FIFO_DATA 0x8

/* Rx Buffer Element */
/* R0 */
Expand Down Expand Up @@ -514,7 +514,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs)
if (fifo_header.dlc & RX_BUF_BRS)
cf->flags |= CANFD_BRS;

err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA(0),
err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA,
cf->data, DIV_ROUND_UP(cf->len, 4));
if (err)
goto out_fail;
Expand Down Expand Up @@ -1588,43 +1588,40 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
struct canfd_frame *cf = (struct canfd_frame *)cdev->tx_skb->data;
struct net_device *dev = cdev->net;
struct sk_buff *skb = cdev->tx_skb;
u32 id, dlc, cccr, fdflags;
int i, err;
struct id_and_dlc fifo_header;
u32 cccr, fdflags;
int err;
int putidx;

cdev->tx_skb = NULL;

/* Generate ID field for TX buffer Element */
/* Common to all supported M_CAN versions */
if (cf->can_id & CAN_EFF_FLAG) {
id = cf->can_id & CAN_EFF_MASK;
id |= TX_BUF_XTD;
fifo_header.id = cf->can_id & CAN_EFF_MASK;
fifo_header.id |= TX_BUF_XTD;
} else {
id = ((cf->can_id & CAN_SFF_MASK) << 18);
fifo_header.id = ((cf->can_id & CAN_SFF_MASK) << 18);
}

if (cf->can_id & CAN_RTR_FLAG)
id |= TX_BUF_RTR;
fifo_header.id |= TX_BUF_RTR;

if (cdev->version == 30) {
netif_stop_queue(dev);

/* message ram configuration */
err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_ID, &id, 1);
fifo_header.dlc = can_fd_len2dlc(cf->len) << 16;

/* Write the frame ID, DLC, and payload to the FIFO element. */
err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_ID, &fifo_header, 2);
if (err)
goto out_fail;

dlc = can_fd_len2dlc(cf->len) << 16;
err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_DLC, &dlc, 1);
err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_DATA,
cf->data, DIV_ROUND_UP(cf->len, 4));
if (err)
goto out_fail;

for (i = 0; i < cf->len; i += 4) {
err = m_can_fifo_write(cdev, 0, M_CAN_FIFO_DATA(i / 4), cf->data + i, 1);
if (err)
goto out_fail;
}

can_put_echo_skb(skb, dev, 0, 0);

if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) {
Expand Down Expand Up @@ -1667,10 +1664,11 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
/* get put index for frame */
putidx = FIELD_GET(TXFQS_TFQPI_MASK,
m_can_read(cdev, M_CAN_TXFQS));
/* Write ID Field to FIFO Element */
err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_ID, &id, 1);
if (err)
goto out_fail;

/* Construct DLC Field, with CAN-FD configuration.
* Use the put index of the fifo as the message marker,
* used in the TX interrupt for sending the correct echo frame.
*/

/* get CAN FD configuration of frame */
fdflags = 0;
Expand All @@ -1680,24 +1678,17 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
fdflags |= TX_BUF_BRS;
}

/* Construct DLC Field. Also contains CAN-FD configuration
* use put index of fifo as message marker
* it is used in TX interrupt for
* sending the correct echo frame
*/
dlc = FIELD_PREP(TX_BUF_MM_MASK, putidx) |
fifo_header.dlc = FIELD_PREP(TX_BUF_MM_MASK, putidx) |
FIELD_PREP(TX_BUF_DLC_MASK, can_fd_len2dlc(cf->len)) |
fdflags | TX_BUF_EFC;
err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DLC, &dlc, 1);
err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_ID, &fifo_header, 2);
if (err)
goto out_fail;

for (i = 0; i < cf->len; i += 4) {
err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DATA(i / 4),
cf->data + i, 1);
if (err)
goto out_fail;
}
err = m_can_fifo_write(cdev, putidx, M_CAN_FIFO_DATA,
cf->data, DIV_ROUND_UP(cf->len, 4));
if (err)
goto out_fail;

/* Push loopback echo.
* Will be looped back on TX interrupt based on message marker
Expand Down

0 comments on commit 812270e

Please sign in to comment.