结论:NAPI机制不适用于此芯片
1.现象:
控制器上电后,电机驱动器平均以0.2ms帧间隔持续发送CAN报文,绑定该CAN硬件中断的核心CPU负载率飙至100%
2.debug思路:
2.1 查看CAN硬件中断绑定在哪个CPU核心
cat /proc/interrupts
2.2 使用trace工具抓取内核事件
分析trace后发现:CAN的软中断嵌套、softirq_raise调用频繁;ksoftirqd/1一直运行,代表一直被唤醒处理软中断;CAN使用了NAPI机制。
NAPI机制适用于大量小包的网络设备,包括CAN。但是事实证明,有些CPU不适用于NAPI。
3. 优化思路
3.1 将CAN0中断同时绑定到多个CPU核心,分摊核心的资源消耗
echo 0-2 > /proc/irq/52/smp_affinity_list
但是未奏效,CAN0中断仍然只跑在一个核心里
3.2 排查NAPI机制问题
NAPI机制通过接收到硬件中断后,屏蔽CPU响应硬件中断,然后用轮询的方式读取FIFO,减少CPU响应硬件中断次数,所以该FIFO内的数据帧不应该过少。
由于NAPI是接收中断中调用,且其能够减少CPU响应硬件中断次数,所以对其掩码CPU响应中断的地方打log。包括:rx_init_cnt计数值、napi_schedule()调用次数。
结果:驱动调用napi_schedule()的次数与USB-CAN卡发送的CAN帧数一致,且rx_init_cnt一直为0,接收缓存区一直只有1帧CAN报文;于是认为该NAPI机制起到了反效果,所以导致了NAPI机制不仅没有减少CPU响应硬件中断次数,反而增加了NAPI的资源调度,导致ksoftirqd/1一直执行,将CPU负载率抬到了100%。
4.修改NAPI机制驱动
取消NAPI机制,改为普通中断响应
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// napi_enable(&rcan->napi);
......
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// napi_disable(&rcan->napi);
......
// netif_napi_add(ndev, &rcan->napi, rockchip_canfd_rx_poll, 6);
.....
// if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2)
// netif_napi_del(&rcan->napi);
......
#if 0
static int rockchip_canfd_rx_poll(struct napi_struct *napi, int quota){
.....
}
static void rockchip_canfd_tx_retry(struct net_device *ndev, u32 isr) {
......
}
#endif
.......
if ((isr & RX_FINISH_INT) || (isr & RX_FIFO_OV_INT) ||
(isr & RX_FIFO_FULL_INT)) {
if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) {
// rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1);
work_done = 0;
quota =
(rockchip_canfd_read(rcan, CAN_RXFC) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift;
if (quota) {
while (work_done < quota) work_done += rockchip_canfd_rx(ndev);
}
} else {
work_done = 0;
quota =
(rockchip_canfd_read(rcan, CAN_RXFC) & rcan->rx_fifo_mask) >>
rcan->rx_fifo_shift;
if (quota) {
while (work_done < quota) work_done += rockchip_canfd_rx(ndev);
}
}
}
1696

被折叠的 条评论
为什么被折叠?



