并发、锁、中断、DMA 与错误恢复

并发、锁、中断、DMA 与错误恢复

1. 并发来源

Bus driver并发通常来自:

  • child driver的I/O;
  • controller IRQ;
  • runtime/system PM;
  • sysfs/debugfs;
  • hotplug或firmware rescan;
  • reset/recovery work;
  • DMA completion;
  • device remove。

仅用一个mutex不能覆盖hardirq和ring更新,也不应让spinlock包围可睡眠路径。

2. 锁分层

典型规则:

  • mutex:probe/remove、配置、枚举、sysfs;
  • spinlock:IRQ状态、短ring指针、doorbell;
  • rwlock/RCU:读多写少状态或device查找;
  • completion/waitqueue:命令及状态转换;
  • refcount/device reference:异步对象生命周期;
  • workqueue:从IRQ转到可睡眠恢复。

必须规定锁顺序,例如controller state → channel → ring,避免recovery与I/O形成ABBA。

3. 中断

错误IRQ:

  1. 读取并保存全部latch;
  2. mask或ack;
  3. 最小化格式化日志;
  4. 重处理放thread/work;
  5. 根据严重度决定继续、reset或panic。

若先清后读会丢fault;若不mask持续level IRQ会形成风暴。

MHI event IRQ还需确保ring element在读取前已通过DMA barrier可见。

4. DMA

MHI/FSL-MC及bus children可能DMA。关键点:

  • 使用DMA API,不直接假定物理地址;
  • 检查dma mask;
  • coherent ring仍需遵守producer/consumer顺序;
  • streaming buffer必须map/unmap和sync;
  • reset前停止device DMA;
  • IOMMU domain必须先于设备启动;
  • controller释放前等待completion不再访问ring。

5. Ring一致性

Producer顺序:

1
2
3
4
write descriptor/payload metadata
-> dma_wmb
-> update write pointer
-> doorbell

Consumer:

1
2
3
4
5
observe producer pointer/event
-> dma_rmb
-> read descriptor
-> process
-> update read pointer

普通spin_lock不自动替代所有设备DMA barrier。

6. 错误分级

级别 处理
可重试命令失败 返回errno,不重置全总线
单channel错误 stop/reset channel
timeout/target abort 保存现场,隔离故障child
controller SYS_ERR 阻止I/O,重建controller
DMA越界/不可恢复一致性错误 禁用设备,必要时系统级恢复

错误恢复不能在旧I/O仍可能completion时直接重新分配同一ring。

7. Recovery状态机

1
2
3
4
5
6
RUNNING
-> QUIESCING
-> RESETTING
-> REINITIALIZING
-> REENUMERATING
-> RUNNING

所有提交API先检查状态。只有一个worker负责主恢复;重复错误合并,避免并发reset。

8. Hot Remove

MHI PCI设备拔出或FSL-MC object消失时:

  • 从匹配表阻止新probe;
  • 标记device offline;
  • 取消client callbacks;
  • 完成pending I/O为-ENODEV
  • device_unregister()
  • 等release后释放parent对象。

功能driver不能缓存未持引用的channel/object指针。

9. Sysfs/Debugfs

写timeout、priority或状态触发器必须和I/O串行。Debugfs默认不是稳定ABI,不能让生产守护进程依赖其格式。

显示register时要避免:

  • 读取会clear的状态;
  • 访问已断电域;
  • 暴露物理地址或敏感DMA内容;
  • 在锁内生成超长输出。

10. Fault Injection

建议测试:

  • clock/reset失败;
  • IRQ丢失/风暴;
  • ring满和wrap;
  • DMA map失败;
  • firmware超时;
  • suspend与I/O竞争;
  • remove与completion竞争;
  • malformed descriptor;
  • recovery中再次SYS_ERR。

成功probe和正常传输不足以证明生命周期正确。

文章互动

阅读 --

留言

0 条留言

正在加载留言…