现在的位置: 首页 > 综合 > 正文

Linux那些事儿之我是Hub(14)没完没了的判断

2013年10月04日 ⁄ 综合 ⁄ 共 5310字 ⁄ 字号 评论关闭

看着这代码,空虚的代码,麻木的走在崩溃边缘.最讨厌这种没完没了的判断了.记得有一次在中信泰富广场去摩托罗拉中国研发中心面试,也是问了一道挺简单的题目,我就把基本的算法说了一下,然后面试官就说为什么没有错误判断.你说像我这种根本不怎么懂编程的人好不容易能回答出一道题,已经很不错了,为何那些企业要求都这么高呢?一个人因为没有工作经验而不能得到一个工作,但是他又因为没有一个工作而得不到工作经验.算了,现实充满残忍,何必太认真.算法没错,程序没错,世界没错,我错了.

2645行我们返回了,前面说了,正常都是返回0或者正数,如果小于0那就说明失败了,前面我们还说了,我们在使用interface之前会调用usb_get_intf()来增加引用计数,而与之对应的是usb_put_intf(),这里我们就调用了usb_put_intf()来减少引用计数.continue的意思开始新的一轮while循环,就是踏上奈何桥,喝下孟婆汤,卸下前世的情仇,忘却今生的爱人,睁开眼又是一生,如果hub_event_list里还有东西的话就继续处理,没有那就歇息吧,日子还是像原来那样一天天的过着.

2649,usb_get_intfdata(),判断一下,得到的是不是hub,你问为什么得到的是hub?回过去看hub_probe(),别忘了那时候我们调用过usb_set_intfdata从而把intfhub联系了起来的,这两个函数当年我们在usb-storage里面就这样用的,不过当时我们不会判断usb_get_intfdata()得到的到底是什么,而这里我们却要判断,因为在hub_disconnect(),又这么一句,usb_set_intfdata(intf,NULL),hub_events()hub_disconnect()是异步执行的,就是说你执行你的,我执行我的,换言之,当咱们这里hub_events()正执行着呢,hub_disconnect()那边可能就已经取消了intfhub之间建立起来的那层美好的关系,所以咱们这里需要判断一下.

2653,现在是时候该说一说USB_STATE_NOTATTACHED这个宏了,include/linux/usb/ch9.h:

    557 enum usb_device_state {

    558         /* NOTATTACHED isn't in the USB spec, and this state acts

    559          * the same as ATTACHED ... but it's clearer this way.

    560          */

    561         USB_STATE_NOTATTACHED = 0,

    562

    563         /* chapter 9 and authentication (wireless) device states */

    564         USB_STATE_ATTACHED,

    565         USB_STATE_POWERED,                      /* wired */

    566         USB_STATE_UNAUTHENTICATED,              /* auth */

    567         USB_STATE_RECONNECTING,                 /* auth */

    568         USB_STATE_DEFAULT,                      /* limited function */

    569         USB_STATE_ADDRESS,

    570         USB_STATE_CONFIGURED,                   /* most functions */

    571

    572         USB_STATE_SUSPENDED

    573

    574         /* NOTE:  there are actually four different SUSPENDED

    575          * states, returning to POWERED, DEFAULT, ADDRESS, or

    576          * CONFIGURED respectively when SOF tokens flow again.

    577          */

    578 };

定义了这么一堆的宏,其中USB_STATE_NOTATTACHED的意思很明显,设备没有插在端口上,在代码里,有几个函数会把设备的状态设置成这个,一个是汇报Host Controller异常死机的函数,usb_hc_died(),一个是咱们hub驱动自己提供的函数,hub_port_disable(),用于关掉一个端口的函数,还有就是用来断开设备的函数usb_disconnect(),总之这几个函数没一个是好鸟,只要它们执行了,那么咱们的设备肯定就没法工作了,所以这里在干正经事之前,先判断设备的状态是不是USB_STATE_NOTATTACHED,如果是的那么就设置错误代码为-ENODEV,然后调用hub_pre_reset(),这个函数是与reset相关的,咱们先不理睬.以后再来看.

2660,usb_autopm_get_interface(),这个函数是usb core提供的,又是一个电源管理的函数,这个函数所做的事情就是让这个usb interface的电源引用计数加一,也就是说,只要这个引用计数大于0,这个设备就不允许autosuspend.autosuspend就是当用户在指定的时间内没有什么活动的话,就自动挂起.应该说,usb中引入autosuspend/autoresume这还是最近的事情了,最初有这个想法是在去年,2006年的5月底,Alan Stern大侠在开源社区提出,同志们,俺最近打算开始在USB里面实现对autosuspend/autoresume的支持.所谓的autosuspend/autoresume,实际上是一种运行时的电源管理方式.而这些事情将由驱动程序来负责,,当驱动程序觉得它的设备闲置了,它就会触发suspend事件,而当驱动程序要使用一个设备了,但该设备正处于suspended状态,那么驱动程序就会触发一个resume事件,suspend事件和resume事件很显然是相对应的,一个挂起一个恢复.这里有一个很关键的理念,又涉及到了前面讲的那个设备树,,当一个设备挂起的时候,它必须通知它的parent,parent就会决定看parent是不是也自动挂起,反过来,如果一个设备需要resume,那么它必须要求它的parentresume,就是说这里有这么一种逻辑关系,一个parent要想suspend,只有在它的childrensuspend它才可以suspend,而一个child想要resume,只有在它的parentresume了它才可以resume.还不明白?举个例子,我和我的室友放寒假在复旦南区澡堂洗澡,每人一个水龙头,洗着洗着,管理员说国家下发了文件说要建设节约型社会,考虑到寒假期间洗澡的人数比较少,决定把水龙头的总闸调小,但是也不能让我们正在洗的人洗不了,所以,它就得先问我们,只有满足了我们在洗的人的那几个水龙头的水量,才可以关小总闸,否则我们肯定得跟他急.同样,开学了以后,大家都来洗澡,可是总闸还是那么小,那大家不干了,但是不干了你得跟管理员说调整总闸,你不能说每个人就调整自己的那个开关,那样肯定没用,总的流量就那么小,时不时还来点侧漏,你说你能洗吗?所以这种情况下就得先开了总闸你单个的开关的调节才有意义.

对于hub来说,hub_events()处于运行的状态,那么这个hub interface就是在使用,这种情况下是不可以进行autosuspend.对于咱们这个上下文来说,usb_autopm_get_interface()返回的就是0.但是如果咱们的hub是处于suspended状态,那么这里首先就会把hub唤醒,即会执行resume.先不多说了,继续往下看吧.

2667,判断quiescing,以前咱们说过,struct usb_hub里面有两个成员,quiescingactiviating,并且咱们在hub_activate()中已经看到了,我们把quiescing设置成了0,而把activating设置成了1.现在是时候来说一说这两个变量的含义了.我们说了quiescing是停止的意思,reset的时候我们会设置它为1,suspend的时候我们也会把它设置为1,一旦把它设置成了1,那么hub驱动程序就不会再提交任何URB,而如果我们把activating,那么hub驱动程序就会给每个端口发送一个叫做Get Port Status的请求,通常情况下,hub驱动只有在一个端口发生了状态变化的情况下才会去发送Get Port Status从而去获得端口的状态.所以就是说,正常情况下,这两个flag都是不会设置的.即正常情况下这两个flag都应该是0.

2671,以咱们这个情景来到这里,hub->error当然是0,但是如果今后我们正式工作以后,再次来到这里的话,hub->error可能就不再是0.对于那种情况,咱们需要调用usb_reset_composite_device(),这个函数是咱们自己定义的,目的就是把设备reset,我们来具体看一下,来自drivers/usb/core/hub.c:

   3041 /**

   3042  * usb_reset_composite_device - warn interface drivers and perform a USB port reset

   3043  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)

   3044  * @iface: interface bound to the driver making the request (optional)

   3045  *

   3046  * Warns all drivers bound to registered interfaces (using their pre_reset

   3047  * method), performs the port reset, and then lets the drivers know that

   3048  * the reset is over (using their post_reset method).

   3049  *

   3050  * Return value is the same as for usb_reset_device().

   3051  *

   3052  * The caller must own the device lock.  For example, it's safe to use

   3053  * this from a driver probe() routine after downloading new firmware.

   3054  * For calls that might not occur during probe(), drivers should lock

   3055  * the device using usb_lock_device_for_reset().

   3056  *

   3057  * The interface locks are acquired during the pre_reset stage and released

   3058  * during the post_reset stage.  However if iface is not NULL and is

   3059  * currently being probed, we assume that the caller already owns its

   3060  * lock.

   3061  */

   3062 int usb_reset_composite_device(struct usb_device *udev,

   3063                 struct usb_interface *iface)

   3064 {

   3065         int ret;

   3066         struct usb_host_config *config = udev->actconfig;

   3067

   3068         if (udev->state == USB_STATE_NOTATTACHED ||

   3069                         udev->state == USB_STATE_SUSPENDED) {

   3070                 dev_dbg(&udev->dev, "device reset not allowed in state %d/n",

   <

抱歉!评论已关闭.