USB系统: hub线程

USB系统: hub线程

1. hub表征

usb子系统中所有和hub相关的都交由一个内核线程表征, 通过
static struct workqueue_struct *hub_wq
来管理。

  • 创建/删除
hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);
destroy_workqueue(hub_wq);
queue_work(hub_wq, &hub->events);

INIT_WORK(&hub->events, hub_event);
  • 访问
    所有和hub_wq相关的访问都通过kick_hub_wq进入。
static void kick_hub_wq(struct usb_hub *hub)
{
    struct usb_interface *intf;

    if (hub->disconnected || work_pending(&hub->events))
        return;

    /* * Suppress autosuspend until the event is proceed. * * Be careful and make sure that the symmetric operation is * always called. We are here only when there is no pending * work for this hub. Therefore put the interface either when * the new work is called or when it is canceled. */
    intf = to_usb_interface(hub->intfdev);
    usb_autopm_get_interface_no_resume(intf);
    kref_get(&hub->kref);

    if (queue_work(hub_wq, &hub->events))
        return;

    /* the work has already been scheduled */
    usb_autopm_put_interface_async(intf);
    kref_put(&hub->kref, hub_release);
}

首先,检查hub是否处于连接状态或者正在等待事件,如果是,则返回。否则将work_struct加入工作队列等待调度。

2 hub事件

这些接口中会触发hub events。
- hub_irq: 枚举hub时的回调函数,中断触发
- hub_port_logical_disconnect: 断开usb设备连接
- hub_activate: 激活hub, 包括复位,初始化,挂起后恢复
重点关注一下hub_activate

enum hub_activation_type {
    HUB_INIT, HUB_INIT2, HUB_INIT3,     /* INITs must come first */
    HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME,
};

static void hub_activate(struct usb_hub *hub, enum hub_activation_type type);

hub_activate根据hub port状态来设置各个event,其实就是设置struct usb_hub结构体中的event_bits, change_bits和wakeup_bits各个比特位。
参考USB 2.0 spec chapter 11

3 事件处理

在hub probe阶段初始化了hub event的处理函数

INIT_WORK(&hub->events, hub_event);

hub_event函数会根据event_bits,change_bits以及wakeup_bits来做事件响应,最终通过port_event处理各个port上的事件。

static void port_event(struct usb_hub *hub, int port1) __must_hold(&port_dev->status_lock)

参考文献: http://www.ibm.com/developerworks/cn/linux/l-tasklets/

你可能感兴趣的:(线程,内核,usb)