diff options
| author | hayeswang <hayeswang@realtek.com> | 2014-02-18 08:49:07 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-02-18 16:40:02 -0500 |
| commit | 9a4be1bd04d6df0cb1a1a0fe49430b27152bb98f (patch) | |
| tree | 39405f3d31abdadb948a5811e783bc85ad545682 | |
| parent | 21ff2e8976b1be23eb0125ee83eb807ad40fb226 (diff) | |
r8152: support runtime suspend
Support runtime suspend for RTL8152 and RTL8153.
Move tx_bottom() from tasklet to delayed_work. That avoids to
transmit tx packets after calling autosuspend.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/usb/r8152.c | 181 |
1 files changed, 158 insertions, 23 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 5d520bee6c0c..f303549b416a 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
| @@ -445,6 +445,7 @@ enum rtl8152_flags { | |||
| 445 | RTL8152_SET_RX_MODE, | 445 | RTL8152_SET_RX_MODE, |
| 446 | WORK_ENABLE, | 446 | WORK_ENABLE, |
| 447 | RTL8152_LINK_CHG, | 447 | RTL8152_LINK_CHG, |
| 448 | SELECTIVE_SUSPEND, | ||
| 448 | PHY_RESET, | 449 | PHY_RESET, |
| 449 | }; | 450 | }; |
| 450 | 451 | ||
| @@ -877,11 +878,21 @@ static u16 sram_read(struct r8152 *tp, u16 addr) | |||
| 877 | static int read_mii_word(struct net_device *netdev, int phy_id, int reg) | 878 | static int read_mii_word(struct net_device *netdev, int phy_id, int reg) |
| 878 | { | 879 | { |
| 879 | struct r8152 *tp = netdev_priv(netdev); | 880 | struct r8152 *tp = netdev_priv(netdev); |
| 881 | int ret; | ||
| 880 | 882 | ||
| 881 | if (phy_id != R8152_PHY_ID) | 883 | if (phy_id != R8152_PHY_ID) |
| 882 | return -EINVAL; | 884 | return -EINVAL; |
| 883 | 885 | ||
| 884 | return r8152_mdio_read(tp, reg); | 886 | ret = usb_autopm_get_interface(tp->intf); |
| 887 | if (ret < 0) | ||
| 888 | goto out; | ||
| 889 | |||
| 890 | ret = r8152_mdio_read(tp, reg); | ||
| 891 | |||
| 892 | usb_autopm_put_interface(tp->intf); | ||
| 893 | |||
| 894 | out: | ||
| 895 | return ret; | ||
| 885 | } | 896 | } |
| 886 | 897 | ||
| 887 | static | 898 | static |
| @@ -892,7 +903,12 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val) | |||
| 892 | if (phy_id != R8152_PHY_ID) | 903 | if (phy_id != R8152_PHY_ID) |
| 893 | return; | 904 | return; |
| 894 | 905 | ||
| 906 | if (usb_autopm_get_interface(tp->intf) < 0) | ||
| 907 | return; | ||
| 908 | |||
| 895 | r8152_mdio_write(tp, reg, val); | 909 | r8152_mdio_write(tp, reg, val); |
| 910 | |||
| 911 | usb_autopm_put_interface(tp->intf); | ||
| 896 | } | 912 | } |
| 897 | 913 | ||
| 898 | static | 914 | static |
| @@ -978,6 +994,8 @@ static void read_bulk_callback(struct urb *urb) | |||
| 978 | if (!netif_carrier_ok(netdev)) | 994 | if (!netif_carrier_ok(netdev)) |
| 979 | return; | 995 | return; |
| 980 | 996 | ||
| 997 | usb_mark_last_busy(tp->udev); | ||
| 998 | |||
| 981 | switch (status) { | 999 | switch (status) { |
| 982 | case 0: | 1000 | case 0: |
| 983 | if (urb->actual_length < ETH_ZLEN) | 1001 | if (urb->actual_length < ETH_ZLEN) |
| @@ -1045,6 +1063,8 @@ static void write_bulk_callback(struct urb *urb) | |||
| 1045 | list_add_tail(&agg->list, &tp->tx_free); | 1063 | list_add_tail(&agg->list, &tp->tx_free); |
| 1046 | spin_unlock_irqrestore(&tp->tx_lock, flags); | 1064 | spin_unlock_irqrestore(&tp->tx_lock, flags); |
| 1047 | 1065 | ||
| 1066 | usb_autopm_put_interface_async(tp->intf); | ||
| 1067 | |||
| 1048 | if (!netif_carrier_ok(tp->netdev)) | 1068 | if (!netif_carrier_ok(tp->netdev)) |
| 1049 | return; | 1069 | return; |
| 1050 | 1070 | ||
| @@ -1055,7 +1075,7 @@ static void write_bulk_callback(struct urb *urb) | |||
| 1055 | return; | 1075 | return; |
| 1056 | 1076 | ||
| 1057 | if (!skb_queue_empty(&tp->tx_queue)) | 1077 | if (!skb_queue_empty(&tp->tx_queue)) |
| 1058 | tasklet_schedule(&tp->tl); | 1078 | schedule_delayed_work(&tp->schedule, 0); |
| 1059 | } | 1079 | } |
| 1060 | 1080 | ||
| 1061 | static void intr_callback(struct urb *urb) | 1081 | static void intr_callback(struct urb *urb) |
| @@ -1313,7 +1333,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) | |||
| 1313 | { | 1333 | { |
| 1314 | struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue; | 1334 | struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue; |
| 1315 | unsigned long flags; | 1335 | unsigned long flags; |
| 1316 | int remain; | 1336 | int remain, ret; |
| 1317 | u8 *tx_data; | 1337 | u8 *tx_data; |
| 1318 | 1338 | ||
| 1319 | __skb_queue_head_init(&skb_head); | 1339 | __skb_queue_head_init(&skb_head); |
| @@ -1361,19 +1381,28 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) | |||
| 1361 | spin_unlock_irqrestore(&tx_queue->lock, flags); | 1381 | spin_unlock_irqrestore(&tx_queue->lock, flags); |
| 1362 | } | 1382 | } |
| 1363 | 1383 | ||
| 1364 | netif_tx_lock(tp->netdev); | 1384 | netif_tx_lock_bh(tp->netdev); |
| 1365 | 1385 | ||
| 1366 | if (netif_queue_stopped(tp->netdev) && | 1386 | if (netif_queue_stopped(tp->netdev) && |
| 1367 | skb_queue_len(&tp->tx_queue) < tp->tx_qlen) | 1387 | skb_queue_len(&tp->tx_queue) < tp->tx_qlen) |
| 1368 | netif_wake_queue(tp->netdev); | 1388 | netif_wake_queue(tp->netdev); |
| 1369 | 1389 | ||
| 1370 | netif_tx_unlock(tp->netdev); | 1390 | netif_tx_unlock_bh(tp->netdev); |
| 1391 | |||
| 1392 | ret = usb_autopm_get_interface(tp->intf); | ||
| 1393 | if (ret < 0) | ||
| 1394 | goto out_tx_fill; | ||
| 1371 | 1395 | ||
| 1372 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | 1396 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), |
| 1373 | agg->head, (int)(tx_data - (u8 *)agg->head), | 1397 | agg->head, (int)(tx_data - (u8 *)agg->head), |
| 1374 | (usb_complete_t)write_bulk_callback, agg); | 1398 | (usb_complete_t)write_bulk_callback, agg); |
| 1375 | 1399 | ||
| 1376 | return usb_submit_urb(agg->urb, GFP_ATOMIC); | 1400 | ret = usb_submit_urb(agg->urb, GFP_KERNEL); |
| 1401 | if (ret < 0) | ||
| 1402 | usb_autopm_put_interface(tp->intf); | ||
| 1403 | |||
| 1404 | out_tx_fill: | ||
| 1405 | return ret; | ||
| 1377 | } | 1406 | } |
| 1378 | 1407 | ||
| 1379 | static void rx_bottom(struct r8152 *tp) | 1408 | static void rx_bottom(struct r8152 *tp) |
| @@ -1511,7 +1540,6 @@ static void bottom_half(unsigned long data) | |||
| 1511 | return; | 1540 | return; |
| 1512 | 1541 | ||
| 1513 | rx_bottom(tp); | 1542 | rx_bottom(tp); |
| 1514 | tx_bottom(tp); | ||
| 1515 | } | 1543 | } |
| 1516 | 1544 | ||
| 1517 | static | 1545 | static |
| @@ -1621,7 +1649,7 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, | |||
| 1621 | netif_stop_queue(netdev); | 1649 | netif_stop_queue(netdev); |
| 1622 | 1650 | ||
| 1623 | if (!list_empty(&tp->tx_free)) | 1651 | if (!list_empty(&tp->tx_free)) |
| 1624 | tasklet_schedule(&tp->tl); | 1652 | schedule_delayed_work(&tp->schedule, 0); |
| 1625 | 1653 | ||
| 1626 | return NETDEV_TX_OK; | 1654 | return NETDEV_TX_OK; |
| 1627 | } | 1655 | } |
| @@ -1876,6 +1904,25 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) | |||
| 1876 | device_set_wakeup_enable(&tp->udev->dev, false); | 1904 | device_set_wakeup_enable(&tp->udev->dev, false); |
| 1877 | } | 1905 | } |
| 1878 | 1906 | ||
| 1907 | static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable) | ||
| 1908 | { | ||
| 1909 | if (enable) { | ||
| 1910 | u32 ocp_data; | ||
| 1911 | |||
| 1912 | __rtl_set_wol(tp, WAKE_ANY); | ||
| 1913 | |||
| 1914 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); | ||
| 1915 | |||
| 1916 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34); | ||
| 1917 | ocp_data |= LINK_OFF_WAKE_EN; | ||
| 1918 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data); | ||
| 1919 | |||
| 1920 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | ||
| 1921 | } else { | ||
| 1922 | __rtl_set_wol(tp, tp->saved_wolopts); | ||
| 1923 | } | ||
| 1924 | } | ||
| 1925 | |||
| 1879 | static void rtl_phy_reset(struct r8152 *tp) | 1926 | static void rtl_phy_reset(struct r8152 *tp) |
| 1880 | { | 1927 | { |
| 1881 | u16 data; | 1928 | u16 data; |
| @@ -2467,6 +2514,9 @@ static void rtl_work_func_t(struct work_struct *work) | |||
| 2467 | { | 2514 | { |
| 2468 | struct r8152 *tp = container_of(work, struct r8152, schedule.work); | 2515 | struct r8152 *tp = container_of(work, struct r8152, schedule.work); |
| 2469 | 2516 | ||
| 2517 | if (usb_autopm_get_interface(tp->intf) < 0) | ||
| 2518 | return; | ||
| 2519 | |||
| 2470 | if (!test_bit(WORK_ENABLE, &tp->flags)) | 2520 | if (!test_bit(WORK_ENABLE, &tp->flags)) |
| 2471 | goto out1; | 2521 | goto out1; |
| 2472 | 2522 | ||
| @@ -2479,12 +2529,14 @@ static void rtl_work_func_t(struct work_struct *work) | |||
| 2479 | if (test_bit(RTL8152_SET_RX_MODE, &tp->flags)) | 2529 | if (test_bit(RTL8152_SET_RX_MODE, &tp->flags)) |
| 2480 | _rtl8152_set_rx_mode(tp->netdev); | 2530 | _rtl8152_set_rx_mode(tp->netdev); |
| 2481 | 2531 | ||
| 2532 | if (tp->speed & LINK_STATUS) | ||
| 2533 | tx_bottom(tp); | ||
| 2482 | 2534 | ||
| 2483 | if (test_bit(PHY_RESET, &tp->flags)) | 2535 | if (test_bit(PHY_RESET, &tp->flags)) |
| 2484 | rtl_phy_reset(tp); | 2536 | rtl_phy_reset(tp); |
| 2485 | 2537 | ||
| 2486 | out1: | 2538 | out1: |
| 2487 | return; | 2539 | usb_autopm_put_interface(tp->intf); |
| 2488 | } | 2540 | } |
| 2489 | 2541 | ||
| 2490 | static int rtl8152_open(struct net_device *netdev) | 2542 | static int rtl8152_open(struct net_device *netdev) |
| @@ -2496,6 +2548,21 @@ static int rtl8152_open(struct net_device *netdev) | |||
| 2496 | if (res) | 2548 | if (res) |
| 2497 | goto out; | 2549 | goto out; |
| 2498 | 2550 | ||
| 2551 | res = usb_autopm_get_interface(tp->intf); | ||
| 2552 | if (res < 0) { | ||
| 2553 | free_all_mem(tp); | ||
| 2554 | goto out; | ||
| 2555 | } | ||
| 2556 | |||
| 2557 | /* The WORK_ENABLE may be set when autoresume occurs */ | ||
| 2558 | if (test_bit(WORK_ENABLE, &tp->flags)) { | ||
| 2559 | clear_bit(WORK_ENABLE, &tp->flags); | ||
| 2560 | usb_kill_urb(tp->intr_urb); | ||
| 2561 | cancel_delayed_work_sync(&tp->schedule); | ||
| 2562 | if (tp->speed & LINK_STATUS) | ||
| 2563 | tp->rtl_ops.disable(tp); | ||
| 2564 | } | ||
| 2565 | |||
| 2499 | tp->rtl_ops.up(tp); | 2566 | tp->rtl_ops.up(tp); |
| 2500 | 2567 | ||
| 2501 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | 2568 | rtl8152_set_speed(tp, AUTONEG_ENABLE, |
| @@ -2514,6 +2581,7 @@ static int rtl8152_open(struct net_device *netdev) | |||
| 2514 | free_all_mem(tp); | 2581 | free_all_mem(tp); |
| 2515 | } | 2582 | } |
| 2516 | 2583 | ||
| 2584 | usb_autopm_put_interface(tp->intf); | ||
| 2517 | 2585 | ||
| 2518 | out: | 2586 | out: |
| 2519 | return res; | 2587 | return res; |
| @@ -2528,9 +2596,26 @@ static int rtl8152_close(struct net_device *netdev) | |||
| 2528 | usb_kill_urb(tp->intr_urb); | 2596 | usb_kill_urb(tp->intr_urb); |
| 2529 | cancel_delayed_work_sync(&tp->schedule); | 2597 | cancel_delayed_work_sync(&tp->schedule); |
| 2530 | netif_stop_queue(netdev); | 2598 | netif_stop_queue(netdev); |
| 2531 | tasklet_disable(&tp->tl); | 2599 | |
| 2532 | tp->rtl_ops.down(tp); | 2600 | res = usb_autopm_get_interface(tp->intf); |
| 2533 | tasklet_enable(&tp->tl); | 2601 | if (res < 0) { |
| 2602 | rtl_drop_queued_tx(tp); | ||
| 2603 | } else { | ||
| 2604 | /* | ||
| 2605 | * The autosuspend may have been enabled and wouldn't | ||
| 2606 | * be disable when autoresume occurs, because the | ||
| 2607 | * netif_running() would be false. | ||
| 2608 | */ | ||
| 2609 | if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { | ||
| 2610 | rtl_runtime_suspend_enable(tp, false); | ||
| 2611 | clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
| 2612 | } | ||
| 2613 | |||
| 2614 | tasklet_disable(&tp->tl); | ||
| 2615 | tp->rtl_ops.down(tp); | ||
| 2616 | tasklet_enable(&tp->tl); | ||
| 2617 | usb_autopm_put_interface(tp->intf); | ||
| 2618 | } | ||
| 2534 | 2619 | ||
| 2535 | free_all_mem(tp); | 2620 | free_all_mem(tp); |
| 2536 | 2621 | ||
| @@ -2684,15 +2769,22 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 2684 | { | 2769 | { |
| 2685 | struct r8152 *tp = usb_get_intfdata(intf); | 2770 | struct r8152 *tp = usb_get_intfdata(intf); |
| 2686 | 2771 | ||
| 2687 | netif_device_detach(tp->netdev); | 2772 | if (PMSG_IS_AUTO(message)) |
| 2773 | set_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
| 2774 | else | ||
| 2775 | netif_device_detach(tp->netdev); | ||
| 2688 | 2776 | ||
| 2689 | if (netif_running(tp->netdev)) { | 2777 | if (netif_running(tp->netdev)) { |
| 2690 | clear_bit(WORK_ENABLE, &tp->flags); | 2778 | clear_bit(WORK_ENABLE, &tp->flags); |
| 2691 | usb_kill_urb(tp->intr_urb); | 2779 | usb_kill_urb(tp->intr_urb); |
| 2692 | cancel_delayed_work_sync(&tp->schedule); | 2780 | cancel_delayed_work_sync(&tp->schedule); |
| 2693 | tasklet_disable(&tp->tl); | 2781 | if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { |
| 2694 | tp->rtl_ops.down(tp); | 2782 | rtl_runtime_suspend_enable(tp, true); |
| 2695 | tasklet_enable(&tp->tl); | 2783 | } else { |
| 2784 | tasklet_disable(&tp->tl); | ||
| 2785 | tp->rtl_ops.down(tp); | ||
| 2786 | tasklet_enable(&tp->tl); | ||
| 2787 | } | ||
| 2696 | } | 2788 | } |
| 2697 | 2789 | ||
| 2698 | return 0; | 2790 | return 0; |
| @@ -2702,13 +2794,23 @@ static int rtl8152_resume(struct usb_interface *intf) | |||
| 2702 | { | 2794 | { |
| 2703 | struct r8152 *tp = usb_get_intfdata(intf); | 2795 | struct r8152 *tp = usb_get_intfdata(intf); |
| 2704 | 2796 | ||
| 2705 | tp->rtl_ops.init(tp); | 2797 | if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) { |
| 2706 | netif_device_attach(tp->netdev); | 2798 | tp->rtl_ops.init(tp); |
| 2799 | netif_device_attach(tp->netdev); | ||
| 2800 | } | ||
| 2801 | |||
| 2707 | if (netif_running(tp->netdev)) { | 2802 | if (netif_running(tp->netdev)) { |
| 2708 | tp->rtl_ops.up(tp); | 2803 | if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { |
| 2709 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | 2804 | rtl_runtime_suspend_enable(tp, false); |
| 2805 | clear_bit(SELECTIVE_SUSPEND, &tp->flags); | ||
| 2806 | if (tp->speed & LINK_STATUS) | ||
| 2807 | tp->rtl_ops.disable(tp); | ||
| 2808 | } else { | ||
| 2809 | tp->rtl_ops.up(tp); | ||
| 2810 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | ||
| 2710 | tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, | 2811 | tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, |
| 2711 | DUPLEX_FULL); | 2812 | DUPLEX_FULL); |
| 2813 | } | ||
| 2712 | tp->speed = 0; | 2814 | tp->speed = 0; |
| 2713 | netif_carrier_off(tp->netdev); | 2815 | netif_carrier_off(tp->netdev); |
| 2714 | set_bit(WORK_ENABLE, &tp->flags); | 2816 | set_bit(WORK_ENABLE, &tp->flags); |
| @@ -2722,18 +2824,31 @@ static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
| 2722 | { | 2824 | { |
| 2723 | struct r8152 *tp = netdev_priv(dev); | 2825 | struct r8152 *tp = netdev_priv(dev); |
| 2724 | 2826 | ||
| 2827 | if (usb_autopm_get_interface(tp->intf) < 0) | ||
| 2828 | return; | ||
| 2829 | |||
| 2725 | wol->supported = WAKE_ANY; | 2830 | wol->supported = WAKE_ANY; |
| 2726 | wol->wolopts = __rtl_get_wol(tp); | 2831 | wol->wolopts = __rtl_get_wol(tp); |
| 2832 | |||
| 2833 | usb_autopm_put_interface(tp->intf); | ||
| 2727 | } | 2834 | } |
| 2728 | 2835 | ||
| 2729 | static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | 2836 | static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) |
| 2730 | { | 2837 | { |
| 2731 | struct r8152 *tp = netdev_priv(dev); | 2838 | struct r8152 *tp = netdev_priv(dev); |
| 2839 | int ret; | ||
| 2840 | |||
| 2841 | ret = usb_autopm_get_interface(tp->intf); | ||
| 2842 | if (ret < 0) | ||
| 2843 | goto out_set_wol; | ||
| 2732 | 2844 | ||
| 2733 | __rtl_set_wol(tp, wol->wolopts); | 2845 | __rtl_set_wol(tp, wol->wolopts); |
| 2734 | tp->saved_wolopts = wol->wolopts & WAKE_ANY; | 2846 | tp->saved_wolopts = wol->wolopts & WAKE_ANY; |
| 2735 | 2847 | ||
| 2736 | return 0; | 2848 | usb_autopm_put_interface(tp->intf); |
| 2849 | |||
| 2850 | out_set_wol: | ||
| 2851 | return ret; | ||
| 2737 | } | 2852 | } |
| 2738 | 2853 | ||
| 2739 | static void rtl8152_get_drvinfo(struct net_device *netdev, | 2854 | static void rtl8152_get_drvinfo(struct net_device *netdev, |
| @@ -2760,8 +2875,18 @@ int rtl8152_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) | |||
| 2760 | static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 2875 | static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
| 2761 | { | 2876 | { |
| 2762 | struct r8152 *tp = netdev_priv(dev); | 2877 | struct r8152 *tp = netdev_priv(dev); |
| 2878 | int ret; | ||
| 2879 | |||
| 2880 | ret = usb_autopm_get_interface(tp->intf); | ||
| 2881 | if (ret < 0) | ||
| 2882 | goto out; | ||
| 2763 | 2883 | ||
| 2764 | return rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex); | 2884 | ret = rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex); |
| 2885 | |||
| 2886 | usb_autopm_put_interface(tp->intf); | ||
| 2887 | |||
| 2888 | out: | ||
| 2889 | return ret; | ||
| 2765 | } | 2890 | } |
| 2766 | 2891 | ||
| 2767 | static struct ethtool_ops ops = { | 2892 | static struct ethtool_ops ops = { |
| @@ -2777,7 +2902,11 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | |||
| 2777 | { | 2902 | { |
| 2778 | struct r8152 *tp = netdev_priv(netdev); | 2903 | struct r8152 *tp = netdev_priv(netdev); |
| 2779 | struct mii_ioctl_data *data = if_mii(rq); | 2904 | struct mii_ioctl_data *data = if_mii(rq); |
| 2780 | int res = 0; | 2905 | int res; |
| 2906 | |||
| 2907 | res = usb_autopm_get_interface(tp->intf); | ||
| 2908 | if (res < 0) | ||
| 2909 | goto out; | ||
| 2781 | 2910 | ||
| 2782 | switch (cmd) { | 2911 | switch (cmd) { |
| 2783 | case SIOCGMIIPHY: | 2912 | case SIOCGMIIPHY: |
| @@ -2800,6 +2929,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | |||
| 2800 | res = -EOPNOTSUPP; | 2929 | res = -EOPNOTSUPP; |
| 2801 | } | 2930 | } |
| 2802 | 2931 | ||
| 2932 | usb_autopm_put_interface(tp->intf); | ||
| 2933 | |||
| 2934 | out: | ||
| 2803 | return res; | 2935 | return res; |
| 2804 | } | 2936 | } |
| 2805 | 2937 | ||
| @@ -2962,6 +3094,8 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
| 2962 | tp->mii.phy_id = R8152_PHY_ID; | 3094 | tp->mii.phy_id = R8152_PHY_ID; |
| 2963 | tp->mii.supports_gmii = 0; | 3095 | tp->mii.supports_gmii = 0; |
| 2964 | 3096 | ||
| 3097 | intf->needs_remote_wakeup = 1; | ||
| 3098 | |||
| 2965 | r8152b_get_version(tp); | 3099 | r8152b_get_version(tp); |
| 2966 | tp->rtl_ops.init(tp); | 3100 | tp->rtl_ops.init(tp); |
| 2967 | set_ethernet_addr(tp); | 3101 | set_ethernet_addr(tp); |
| @@ -3023,6 +3157,7 @@ static struct usb_driver rtl8152_driver = { | |||
| 3023 | .suspend = rtl8152_suspend, | 3157 | .suspend = rtl8152_suspend, |
| 3024 | .resume = rtl8152_resume, | 3158 | .resume = rtl8152_resume, |
| 3025 | .reset_resume = rtl8152_resume, | 3159 | .reset_resume = rtl8152_resume, |
| 3160 | .supports_autosuspend = 1, | ||
| 3026 | }; | 3161 | }; |
| 3027 | 3162 | ||
| 3028 | module_usb_driver(rtl8152_driver); | 3163 | module_usb_driver(rtl8152_driver); |
