USB学习之三 故障自恢复

USB支持热插拔。拔出插入之后如果文件句柄(mount和losetup)资源被释放,那么旧的设备节点会释放(sda),重新插入后会重新生成设备节点sda;而如果旧资源没被释放,那么会生成新的设备节点sdb, sdc。旧的设备节点和资源会被泄露。
usb会自恢复一些异常。但是如果USB固件出现故障,需要上下电才能恢复,linux驱动无法处理这种故障,除非对驱动进行大的整改。
USB卡如果固定插在开发板,不考虑热插拔的话,那么修改旧有的驱动,这种故障的修复变成可能。

我们考虑两种故障场景:
运行的时候USB固件跑飞了(挂死了),需要对USB固件上下电才能恢复(假设单板的EPLD固件支持对USB进行下点或者上电);
另外一种场景是USB电源线和数据线(四根线)受外界影响,出现闪断故障,导致设备断链(这样会导致旧的资源未释放,而生成新的设备)。
这两种故障场景都是标准的linux设备驱动无法处理的。
故障自恢复需要梳理初始化流程和读写流程。
先考虑第一种场景,就是读写流程
USB读写流程的关键函数是usb_stor_invoke_transport
该函数会封装qtd,内部包含CBW,DATA和CSW下发到USB控制器;触发USB控制器DMA传输。如果出现协议不可恢复故障(CRC, TIMEOUT和BAD PID),会进入Handle_Errors流程,Handle_Errors流程会复位HUB等操作,这个流程如果恢复不了,那就悲剧了。也就是说,上下电故障需要在这个流程里面添加。

usb_stor_invoke_transport
Handle_Errors:
    =>result = usb_stor_port_reset(us);
        =>result = rc_lock = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
        =>result = usb_reset_composite_device(us->pusb_dev, us->pusb_intf);
            =>ret = usb_reset_device(udev);
                =>ep0_reinit(udev);
                =>ret = hub_port_init(parent_hub, udev, port1, i);
                    =>retval = hub_port_reset(hub, port1, udev, delay);
                        =>status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_RESET);
                        =>status = hub_port_wait_reset(hub, port1, udev, delay);
        =>usb_unlock_device(us->pusb_dev);
    =>if (result < 0)
        usb_stor_report_device_reset(us);//通知上层重传
        us->transport_reset(us);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值