mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
net: can: rockchip: canfd: Add delay work to check tx errors
Fixes: aed0776380 ("canfd: Support extended frames transmit for rk3568")
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Change-Id: I7d3ea5ca8ac501d81ec9f0ca15f6e3816080a4b5
This commit is contained in:
@@ -230,6 +230,7 @@ struct rockchip_canfd {
|
||||
u32 rx_fifo_mask;
|
||||
bool txtorx;
|
||||
u32 tx_invalid[4];
|
||||
struct delayed_work tx_err_work;
|
||||
};
|
||||
|
||||
static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv,
|
||||
@@ -483,6 +484,25 @@ static int rockchip_canfd_set_mode(struct net_device *ndev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_canfd_tx_err_delay_work(struct work_struct *work)
|
||||
{
|
||||
struct rockchip_canfd *rcan =
|
||||
container_of(work, struct rockchip_canfd, tx_err_work.work);
|
||||
u32 mode, err_code, id;
|
||||
|
||||
id = rockchip_canfd_read(rcan, CAN_TXID);
|
||||
err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE);
|
||||
if (err_code & 0x1fe0000) {
|
||||
mode = rockchip_canfd_read(rcan, CAN_MODE);
|
||||
rockchip_canfd_write(rcan, CAN_MODE, 0);
|
||||
rockchip_canfd_write(rcan, CAN_MODE, mode);
|
||||
rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
|
||||
schedule_delayed_work(&rcan->tx_err_work, 1);
|
||||
} else if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && id & CAN_EFF_FLAG) {
|
||||
schedule_delayed_work(&rcan->tx_err_work, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* transmit a CAN message
|
||||
* message layout in the sk_buff should be like this:
|
||||
* xx xx xx xx ff ll 00 11 22 33 44 55 66 77
|
||||
@@ -565,6 +585,9 @@ static int rockchip_canfd_start_xmit(struct sk_buff *skb,
|
||||
|
||||
rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);
|
||||
|
||||
if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && cf->can_id & CAN_EFF_FLAG)
|
||||
schedule_delayed_work(&rcan->tx_err_work, 1);
|
||||
|
||||
can_put_echo_skb(skb, ndev, 0);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@@ -706,7 +729,7 @@ static int rockchip_canfd_err(struct net_device *ndev, u32 isr)
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
netif_receive_skb(skb);
|
||||
netif_rx(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -732,6 +755,7 @@ static irqreturn_t rockchip_canfd_interrupt(int irq, void *dev_id)
|
||||
stats->tx_bytes += (dlc & DLC_MASK);
|
||||
stats->tx_packets++;
|
||||
if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && dlc & FORMAT_MASK) {
|
||||
cancel_delayed_work(&rcan->tx_err_work);
|
||||
rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK);
|
||||
quota = (rockchip_canfd_read(rcan, CAN_RXFC) &
|
||||
rcan->rx_fifo_mask) >>
|
||||
@@ -814,6 +838,7 @@ static int rockchip_canfd_close(struct net_device *ndev)
|
||||
close_candev(ndev);
|
||||
can_led_event(ndev, CAN_LED_EVENT_STOP);
|
||||
pm_runtime_put(rcan->dev);
|
||||
cancel_delayed_work_sync(&rcan->tx_err_work);
|
||||
|
||||
netdev_dbg(ndev, "%s\n", __func__);
|
||||
return 0;
|
||||
@@ -1036,6 +1061,8 @@ static int rockchip_canfd_probe(struct platform_device *pdev)
|
||||
ndev->flags |= IFF_ECHO;
|
||||
rcan->can.restart_ms = 1;
|
||||
|
||||
INIT_DELAYED_WORK(&rcan->tx_err_work, rockchip_canfd_tx_err_delay_work);
|
||||
|
||||
platform_set_drvdata(pdev, ndev);
|
||||
SET_NETDEV_DEV(ndev, &pdev->dev);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user