Rickey 裘 一无所知

USB系统--hub线程

2016-09-26
佚名

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/


评论