1. 正常插入
插上U盘产生中断调用usb_hcd_irq: usb_hcd_irq ehci_irq usb_hcd_resume_root_hub queue_work(pm_wq, &hcd->wakeup_work); //hcd.c中的__usb_create_hcd中INIT_WORK(&hcd->wakeup_work, hcd_resume_work); hcd_resume_work usb_remote_wakeup usb_autoresume_device __pm_runtime_resume rpm_resume rpm_callback __rpm_callback usb_runtime_resume usb_resume_both usb_resume_interface hub_resume hub_activate //这个函数中会延时HUB_DEBOUNCE_STABLE时间 kick_hub_wq queue_work(hub_wq, &hub->events) //hub.c的hub_probe中INIT_WORK(&hub->events, hub_event); hub_event //hub.c usb_reset_device //hub.c usb_reset_and_verify_device hub_port_init //hub.c hub_port_reset //hub.c 在这里面进行速率识别握手,默认路由到ehci上,握手就可能路由到ohci上,然后中断线程判断寄存器状态后ohci直接就处理了,然后ehci判断断开了连接就退出了。 hub_set_address port_event hub_port_connect_change hub_port_connect
hub_port_debounce_be_stable
hub_port_debounce //执行消抖操作
usb_new_device usb_enumerate_device //hub.c 枚举设备 正常拔出 hub_irq 作为一个中断传输最先调用
2. 斜着插入U盘,使D+先接触,还会调用到其伴随的ohci控制器驱动
ohci和ehci在 hub_port_init() 中加 dump_stack() 显示的调用路径是一样的!
在 kick_hub_wq 中继续 dump_stack() 直到 usb_hcd_resume_root_hub() 也应该是一样的
不同之处:
//ehci: start_kernel rest_init cpu_startup_entry do_idle arch_cpu_idle el1_irq //起源于硬件中断,产生中断进入中断处理,el1_irq汇编,中断总入口 gic_handle_irq __handle_domain_irq generic_handle_irq handle_fasteoi_irq //这个是有IO中断直接触发的 handle_irq_event handle_irq_event_percpu __handle_irq_event_percpu usb_hcd_irq ehci_irq usb_hcd_resume_root_hub
//ohci: ksoftirqd //起源于软中断 ret_from_fork kthread worker_thread process_one_work //kick_hub_wq中queue_work(hub_wq, &hub->events),hub_irq中调用了kick_hub_wq hub_event hub_port_init hub_port_reset hub_ext_port_status usb_control_msg usb_start_wait_urb usb_submit_urb usb_hcd_submit_urb //这里面触发了这个中断 el1_irq //这个中断是? gic_handle_irq __handle_domain_irq generic_handle_irq handle_fasteoi_irq handle_irq_event handle_irq_event_percpu __handle_irq_event_percpu usb_hcd_irq ohci_irq usb_hcd_poll_rh_status ohci_hub_status_data usb_hcd_resume_root_hub
3. 结论
插入U盘产生的IO中断直接作用在ehci上,并由ehci先处理一遍。当由于速率识别,导致中断不再ehci上,此传输完成,hub_irq被调用,
然后它执行hub_event,之后触发一个硬中断,此中断由ohci处理了!