Linux那些事儿之我是Hub(12)再向虎山行 – fudan

徐志摩说:轻轻的我穿衣,正如我轻轻的脱;

后来徐志摩又说:轻轻的我走了,正如我轻轻的来.

hub_events(),没错,胡汉三又回来了.

再一次进入while这个(该)死(的)循环.

第一次来这里的时候,hub_event_list是空的,可是这一次不是了,我们刚刚在kick_khubd()里面才执行了往这个队列里插入的操作,所以我们不会再像第一次一样,从2621行的break跳出循环.相反,我们直接走到2624行,把刚才插入队列的那个节点取出来,存为tmp,然后把tmp从队列里删除掉.(是从队列里删除,不是把tmp本身给删除.)

2627行,list_entry(),这个经典的函数,或者说宏,就像复旦南区食堂的大排,永恒的经典.通过这个宏这里得到的是那个触发hub_events()的hub.然后2628行,同时用局部变量hdev记录hub->hdev.2629行,又得到对应的struct usb_interface和struct device,这下好了,什么都得到了,该付出了吧.

2640行, usb_get_intf(),看仔细了,别和我们当年在usb-storage里面调用的那个usb_get_intfdata()混淆了,这里usb_get_intf只是一个引用计数.是usb core提供的一个函数,以前黑客们推荐用另一个引用计数的函数usb_get_dev(),但在当今世界这样一种现状下,随着一个usb device越来越成为多个interface耦合的情况的出现,struct usb_device实际上已经快淡出历史舞台了,现在在驱动程序里关注的最多的就是interface,而不是device.和usb_get_intf()对应的有另一个函数,叫做usb_put_intf(),很显然,一个是增加引用计数一个减少引用计数.这个函数我们马上就能看到.

前面我们贴hub_events()只贴到2641行,现在继续贴,贴完这个粉恐怖的函数.

2642

2643 /* Lock the device, then check to see if we were

2644 * disconnected while waiting for the lock to succeed. */

2645 if (locktree(hdev) < 0) {

2646 usb_put_intf(intf);

2647 continue;

2648 }

2649 if (hub != usb_get_intfdata(intf))

2650 goto loop;

2651

2652 /* If the hub has died, clean up after it */

2653 if (hdev->state == USB_STATE_NOTATTACHED) {

2654 hub->error = -ENODEV;

2655 hub_pre_reset(intf);

2656 goto loop;

2657 }

2658

2659 /* Autoresume */

2660 ret = usb_autopm_get_interface(intf);

2661 if (ret) {

2662 dev_dbg(hub_dev, "Can’t autoresume: %d/n", ret);

2663 goto loop;

2664 }

2665

2666 /* If this is an inactive hub, do nothing */

2667 if (hub->quiescing)

2668 goto loop_autopm;

2669

2670 if (hub->error) {

2671 dev_dbg (hub_dev, "resetting for error %d/n",

2672 hub->error);

2673

2674 ret = usb_reset_composite_device(hdev, intf);

2675 if (ret) {

2676 dev_dbg (hub_dev,

2677 "error resetting hub: %d/n", ret);

2678 goto loop_autopm;

2679 }

2680

2681 hub->nerrors = 0;

2682 hub->error = 0;

2683 }

2684

2685 /* deal with port status changes */

2686 for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {

2687 if (test_bit(i, hub->busy_bits))

2688 continue;

2689 connect_change = test_bit(i, hub->change_bits);

2690 if (!test_and_clear_bit(i, hub->event_bits) &&

2691 !connect_change && !hub->activating)

2692 continue;

2693

2694 ret = hub_port_status(hub, i,

2695 &portstatus, &portchange);

2696 if (ret < 0)

2697 continue;

2698

2699 if (hub->activating && !hdev->children[i-1] &&

2700 (portstatus &

2701 USB_PORT_STAT_CONNECTION))

2702 connect_change = 1;

2703

2704 if (portchange & USB_PORT_STAT_C_CONNECTION) {

2705 clear_port_feature(hdev, i,

2706 USB_PORT_FEAT_C_CONNECTION);

2707 connect_change = 1;

2708 }

2709

2710 if (portchange & USB_PORT_STAT_C_ENABLE) {

2711 if (!connect_change)

2712 dev_dbg (hub_dev,

2713 "port %d enable change, "

2714 "status %08x/n",

2715 i, portstatus);

2716 clear_port_feature(hdev, i,

2717 USB_PORT_FEAT_C_ENABLE);

2718

2719 /*

2720 * EM interference sometimes causes badly

2721 * shielded USB devices to be shutdown by

2722 * the hub, this hack enables them again.

2723 * Works at least with mouse driver.

2724 */

2725 if (!(portstatus & USB_PORT_STAT_ENABLE)

2726 && !connect_change

2727 && hdev->children[i-1]) {

2728 dev_err (hub_dev,

2729 "port %i "

2730 "disabled by hub (EMI?), "

2731 "re-enabling…/n",

2732 i);

2733 connect_change = 1;

2734 }

2735 }

2736

2737 if (portchange & USB_PORT_STAT_C_SUSPEND) {

2738 clear_port_feature(hdev, i,

2739 USB_PORT_FEAT_C_SUSPEND);

2740 if (hdev->children[i-1]) {

2741 ret = remote_wakeup(hdev->

2742 children[i-1]);

2743 if (ret < 0)

2744 connect_change = 1;

2745 } else {

2746 ret = -ENODEV;

2747 hub_port_disable(hub, i, 1);

2748 }

2749 dev_dbg (hub_dev,

2750 "resume on port %d, status %d/n",

2751 i, ret);

2752 }

2753

2754 if (portchange & USB_PORT_STAT_C_OVERCURRENT) {

2755 dev_err (hub_dev,

2756 "over-current change on port %d/n",

2757 i);

2758 clear_port_feature(hdev, i,

2759 USB_PORT_FEAT_C_OVER_CURRENT);

2760 hub_power_on(hub);

2761 }

2762

2763 if (portchange & USB_PORT_STAT_C_RESET) {

2764 dev_dbg (hub_dev,

2765 "reset change on port %d/n",

2766 i);

2767 clear_port_feature(hdev, i,

2768 USB_PORT_FEAT_C_RESET);

2769 }

2770

2771 if (connect_change)

2772 hub_port_connect_change(hub, i,

2773 portstatus, portchange);

2774 } /* end for i */

2775

2776 /* deal with hub status changes */

2777 if (test_and_clear_bit(0, hub->event_bits) == 0)

2778 ; /* do nothing */

2779 else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)

2780 dev_err (hub_dev, "get_hub_status failed/n");

2781 else {

2782 if (hubchange & HUB_CHANGE_LOCAL_POWER) {

2783 dev_dbg (hub_dev, "power change/n");

2784 clear_hub_feature(hdev, C_HUB_LOCAL_POWER);

2785 if (hubstatus & HUB_STATUS_LOCAL_POWER)

2786 /* FIXME: Is this always true? */

2787 hub->limited_power = 0;

2788 else

2789 hub->limited_power = 1;

2790 }

2791 if (hubchange & HUB_CHANGE_OVERCURRENT) {

2792 dev_dbg (hub_dev, "overcurrent change/n");

2793 msleep(500); /* Cool down */

2794 clear_hub_feature(hdev, C_HUB_OVER_CURRENT);

2795 hub_power_on(hub);

2796 }

2797 }

2798

2799 hub->activating = 0;

2800

2801 /* If this is a root hub, tell the HCD it’s okay to

2802 * re-enable port-change interrupts now. */

2803 if (!hdev->parent && !hub->busy_bits[0])

2804 usb_enable_root_hub_irq(hdev->bus);

2805

2806 loop_autopm:

2807 /* Allow autosuspend if we’re not going to run again */

2808 if (list_empty(&hub->event_list))

2809 usb_autopm_enable(intf);

2810 loop:

2811 usb_unlock_device(hdev);

2812 usb_put_intf(intf);

2813

2814 } /* end while (1) */

2815 }

我真想诚恳的问候一下写代码的人的女性长辈.当裴多菲说:"若为自由故,两者皆可抛",我懂得了作为人的价值;当鲁迅说:"不在沉默中爆发,就在沉默中灭亡",我懂得人应具有反抗精神;当白朗宁说:"拿走爱,世界将变成一座坟墓",我懂得了为他人奉献爱心的重要;当简爱说:"我们是平等的,我不是无感情的机器",我懂得了作为女性的自尊;当我看到这段代码,我却完全不懂写代码的人为什么总要写一些恐怖的函数出来.一定要吓唬吓唬我他们就开心么?我是复旦的,不是厦(吓)大的.

而是深沉的意志恢弘的想象炙热的恋情;青春是生命的深泉在涌流。

Linux那些事儿之我是Hub(12)再向虎山行 – fudan

相关文章:

你感兴趣的文章:

标签云: