• ehci及其伴随ohci主机控制器驱动分析


    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处理了!

  • 相关阅读:
    并发编程(十)—— Java 并发队列 BlockingQueue 实现之 SynchronousQueue源码分析
    并发编程(九)—— Java 并发队列 BlockingQueue 实现之 LinkedBlockingQueue 源码分析
    Java工程师成神之路
    并发编程(八)—— Java 并发队列 BlockingQueue 实现之 ArrayBlockingQueue 源码分析
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
    星空雅梦
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/9981179.html
Copyright © 2020-2023  润新知