usb suspend/resume
来源:互联网 发布:cn域名个人能备案吗 编辑:程序博客网 时间:2024/05/20 15:42
1. 简介
做USB 这么长时间以来,一直埋头在各种gadget, android framework以及芯片bug,很少涉及到usb core层,今天有机会,正好看了suspend/resume, 下面就以一个具体的实例来回顾下usb suspend/resume。
从上图可以看出,这个实例用的是 Synopsys的usb控制器(dwc),下面来具体介绍下suspen/resume
2. suspend
2.1. suspend U盘
usb_dev_suspend --> usb_suspend --> usb_suspend_both
从usb_suspend_both的code中可以看出我们前面提到了一个原则 “先suspend interface, 然后是设备本身"
1168 static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)1169 {1170 int status = 0;1171 int i = 0, n = 0;1172 struct usb_interface *intf;1173 1174 if (udev->state == USB_STATE_NOTATTACHED ||1175 udev->state == USB_STATE_SUSPENDED)1176 goto done;1177 1178 /* Suspend all the interfaces and then udev itself */1179 if (udev->actconfig) {1180 n = udev->actconfig->desc.bNumInterfaces;1181 printk("%s interface:%d\n", __func__, n);1182 for (i = n - 1; i >= 0; --i) {1183 intf = udev->actconfig->interface[i];1184 status = usb_suspend_interface(udev, intf, msg); 1185 1186 /* Ignore errors during system sleep transitions */1187 if (!PMSG_IS_AUTO(msg))1188 status = 0;1189 if (status != 0)1190 break;1191 }1192 }1193 if (status == 0) {1194 status = usb_suspend_device(udev, msg);1195 1196 /*1197 * Ignore errors from non-root-hub devices during1198 * system sleep transitions. For the most part,1199 * these devices should go to low power anyway when1200 * the entire bus is suspended.1201 */1202 if (udev->parent && !PMSG_IS_AUTO(msg))1203 status = 0;1204 }1205 1206 /* If the suspend failed, resume interfaces that did get suspended */1207 if (status != 0) {1208 msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);1209 while (++i < n) {1210 intf = udev->actconfig->interface[i];1211 usb_resume_interface(udev, intf, msg, 0);1212 }1213 1214 /* If the suspend succeeded then prevent any more URB submissions1215 * and flush any outstanding URBs.1216 */1217 } else {1218 udev->can_submit = 0;1219 for (i = 0; i < 16; ++i) {1220 usb_hcd_flush_endpoint(udev, udev->ep_out[i]);1221 usb_hcd_flush_endpoint(udev, udev->ep_in[i]);1222 }1223 }1224 1225 done:1226 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);1227 return status;1228 }
U盘只有一个interface:mass_storage. 所以这里suspend interface会调用到 usb_stor_suspend(drivers/usb/storage/usb.c),接下来就是suspend U盘本身,这里会调用到
generic_suspend
197 static int generic_suspend(struct usb_device *udev, pm_message_t msg)198 {199 int rc;200 201 /* Normal USB devices suspend through their upstream port.202 * Root hubs don't have upstream ports to suspend,203 * so we have to shut down their downstream HC-to-USB204 * interfaces manually by doing a bus (or "global") suspend.205 */206 if (!udev->parent)207 rc = hcd_bus_suspend(udev, msg);208 209 /* Non-root devices don't need to do anything for FREEZE or PRETHAW */210 else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)211 rc = 0;212 else213 rc = usb_port_suspend(udev, msg);214 215 return rc;216 }
因为这个是外设,所以具体调用的是usb_port_suspend,这个函数的主要作用就是发送usb request SET_FEATURE PORT_SUSPEND给设备。
2.2 suspend OTG Host
和device相同,还是从usb_suspend_both开始,只不过HOST只有一个interface: hub,所以这里会调用到hub_suspend
hub_suspend主要作用是停止urb以及一些delay work. 接下来就是suspend HOST本身,与device相同,这里调用的还是generic_suspend,
只不过由于是root hub,所以调用的是hcd_bus_suspend
1959 int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)1960 {1961 struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);1962 int status;1963 int old_state = hcd->state;1964 1965 dev_dbg(&rhdev->dev, "bus %ssuspend, wakeup %d\n",1966 (PMSG_IS_AUTO(msg) ? "auto-" : ""),1967 rhdev->do_remote_wakeup);1968 if (HCD_DEAD(hcd)) {1969 dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");1970 return 0;1971 }1972 1973 if (!hcd->driver->bus_suspend) {1974 status = -ENOENT;1975 } else {1976 clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);1977 hcd->state = HC_STATE_QUIESCING;1978 status = hcd->driver->bus_suspend(hcd);1979 }
这里主要起作用的是 status = hcd->driver->bus_suspend(hcd),这个函数指针会调用到HOST控制器注册的bus_suspend函数,针对这个实例为
static int dwc_otg_bus_suspend(struct usb_hcd *hcd)
3. resume
resume是suspend的一个反过程,从Host到device,从Host/device本身然后再到各个interface.
3.1 resume OTG Host
从usb_resume_both开始
1248 static int usb_resume_both(struct usb_device *udev, pm_message_t msg)1249 {1250 int status = 0;1251 int i;1252 struct usb_interface *intf;1253 1254 if (udev->state == USB_STATE_NOTATTACHED) {1255 status = -ENODEV; 1256 goto done;1257 }1258 udev->can_submit = 1; 1259 1260 /* Resume the device */1261 if (udev->state == USB_STATE_SUSPENDED || udev->reset_resume)1262 status = usb_resume_device(udev, msg);1263 1264 /* Resume the interfaces */1265 if (status == 0 && udev->actconfig) {1266 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {1267 intf = udev->actconfig->interface[i];1268 usb_resume_interface(udev, intf, msg,1269 udev->reset_resume);1270 }1271 }1272 usb_mark_last_busy(udev);1273 1274 done:1275 dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);1276 if (!status)1277 udev->reset_resume = 0;1278 return status;1279 }
和suspend对应,这里先resume Host本身,调用dwc_otg_bus_resume。接下来resume interface,调用hub_resume
hub_resume会判断每一个port的port status,然后做对应的处理(这里先略过,需要参照协议)
3.2. resume U盘
从usb_resume_both开始,先resume U盘本身,调用usb_port_resume, 这里会判断port状态,并且下usb request CLEAR_FEATURE PORT_SUSPEND,
通过返回的状态判定是做resume/reset_resume/disconnect。这里先不展开,需要结合协议来看。
接下来会调用usb_stor_resume去resume interface。
- USB 2.0 suspend resume
- usb suspend/resume
- 说说usb suspend/resume
- Linux下USB suspend/resume源码分析
- Linux下USB suspend/resume源码分析
- USB驱动Suspend&Resume 调用流程分析
- Linux下USB suspend/resume源码分析
- Linux下USB suspend/resume源码分析
- suspend/resume
- 解决了USB中suspend和resume的一个问题
- USB的挂起和唤醒 (Suspend and Resume)
- USB的挂起和唤醒 (Suspend and Resume)
- USB的挂起和唤醒 (Suspend and Resume)
- USB的挂起和唤醒 (Suspend and Resume)
- USB的挂起和唤醒(Suspend and Resume)
- EZ-USB的挂起恢复机制:suspend-resume mechanism
- resume suspend wait sleep
- android suspend/resume
- Linux-C编程-数据管理
- VS2008+AE 提示This control requires an ArcGIS Engine Developer Kit license
- quagga 命令定义的代码分析
- ORACLE的sign函数
- restlet借助servlet部署到Tomcat
- usb suspend/resume
- sed
- OCP-1Z0-053-V13.02-131题
- 网站优化中404页面所带来的影响
- 未能进入中断模式,原因如下:源文件“XXXXXX”不属于正在调试的项目。
- Fragment自定义动画、动画以及兼容性包应用
- opencv学习-imgprocess-计算图像矩moments
- 网页设计中将被淘汰的8个趋势
- VM redhat6.4 yum