diff options
-rw-r--r-- | drivers/net/usb/r8152.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 1d2fc8effda6..864159eb744e 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/mdio.h> | 26 | #include <linux/mdio.h> |
27 | 27 | ||
28 | /* Version Information */ | 28 | /* Version Information */ |
29 | #define DRIVER_VERSION "v1.06.1 (2014/10/01)" | 29 | #define DRIVER_VERSION "v1.07.0 (2014/10/09)" |
30 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" | 30 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
31 | #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" | 31 | #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" |
32 | #define MODULENAME "r8152" | 32 | #define MODULENAME "r8152" |
@@ -566,6 +566,7 @@ struct r8152 { | |||
566 | spinlock_t rx_lock, tx_lock; | 566 | spinlock_t rx_lock, tx_lock; |
567 | struct delayed_work schedule; | 567 | struct delayed_work schedule; |
568 | struct mii_if_info mii; | 568 | struct mii_if_info mii; |
569 | struct mutex control; /* use for hw setting */ | ||
569 | 570 | ||
570 | struct rtl_ops { | 571 | struct rtl_ops { |
571 | void (*init)(struct r8152 *); | 572 | void (*init)(struct r8152 *); |
@@ -977,12 +978,16 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p) | |||
977 | if (ret < 0) | 978 | if (ret < 0) |
978 | goto out1; | 979 | goto out1; |
979 | 980 | ||
981 | mutex_lock(&tp->control); | ||
982 | |||
980 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 983 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
981 | 984 | ||
982 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); | 985 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); |
983 | pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data); | 986 | pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data); |
984 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | 987 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); |
985 | 988 | ||
989 | mutex_unlock(&tp->control); | ||
990 | |||
986 | usb_autopm_put_interface(tp->intf); | 991 | usb_autopm_put_interface(tp->intf); |
987 | out1: | 992 | out1: |
988 | return ret; | 993 | return ret; |
@@ -2139,6 +2144,8 @@ static int rtl8152_set_features(struct net_device *dev, | |||
2139 | if (ret < 0) | 2144 | if (ret < 0) |
2140 | goto out; | 2145 | goto out; |
2141 | 2146 | ||
2147 | mutex_lock(&tp->control); | ||
2148 | |||
2142 | if (changed & NETIF_F_HW_VLAN_CTAG_RX) { | 2149 | if (changed & NETIF_F_HW_VLAN_CTAG_RX) { |
2143 | if (features & NETIF_F_HW_VLAN_CTAG_RX) | 2150 | if (features & NETIF_F_HW_VLAN_CTAG_RX) |
2144 | rtl_rx_vlan_en(tp, true); | 2151 | rtl_rx_vlan_en(tp, true); |
@@ -2146,6 +2153,8 @@ static int rtl8152_set_features(struct net_device *dev, | |||
2146 | rtl_rx_vlan_en(tp, false); | 2153 | rtl_rx_vlan_en(tp, false); |
2147 | } | 2154 | } |
2148 | 2155 | ||
2156 | mutex_unlock(&tp->control); | ||
2157 | |||
2149 | usb_autopm_put_interface(tp->intf); | 2158 | usb_autopm_put_interface(tp->intf); |
2150 | 2159 | ||
2151 | out: | 2160 | out: |
@@ -2847,6 +2856,11 @@ static void rtl_work_func_t(struct work_struct *work) | |||
2847 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) | 2856 | if (test_bit(RTL8152_UNPLUG, &tp->flags)) |
2848 | goto out1; | 2857 | goto out1; |
2849 | 2858 | ||
2859 | if (!mutex_trylock(&tp->control)) { | ||
2860 | schedule_delayed_work(&tp->schedule, 0); | ||
2861 | goto out1; | ||
2862 | } | ||
2863 | |||
2850 | if (test_bit(RTL8152_LINK_CHG, &tp->flags)) | 2864 | if (test_bit(RTL8152_LINK_CHG, &tp->flags)) |
2851 | set_carrier(tp); | 2865 | set_carrier(tp); |
2852 | 2866 | ||
@@ -2862,6 +2876,8 @@ static void rtl_work_func_t(struct work_struct *work) | |||
2862 | if (test_bit(PHY_RESET, &tp->flags)) | 2876 | if (test_bit(PHY_RESET, &tp->flags)) |
2863 | rtl_phy_reset(tp); | 2877 | rtl_phy_reset(tp); |
2864 | 2878 | ||
2879 | mutex_unlock(&tp->control); | ||
2880 | |||
2865 | out1: | 2881 | out1: |
2866 | usb_autopm_put_interface(tp->intf); | 2882 | usb_autopm_put_interface(tp->intf); |
2867 | } | 2883 | } |
@@ -2881,6 +2897,8 @@ static int rtl8152_open(struct net_device *netdev) | |||
2881 | goto out; | 2897 | goto out; |
2882 | } | 2898 | } |
2883 | 2899 | ||
2900 | mutex_lock(&tp->control); | ||
2901 | |||
2884 | /* The WORK_ENABLE may be set when autoresume occurs */ | 2902 | /* The WORK_ENABLE may be set when autoresume occurs */ |
2885 | if (test_bit(WORK_ENABLE, &tp->flags)) { | 2903 | if (test_bit(WORK_ENABLE, &tp->flags)) { |
2886 | clear_bit(WORK_ENABLE, &tp->flags); | 2904 | clear_bit(WORK_ENABLE, &tp->flags); |
@@ -2909,6 +2927,8 @@ static int rtl8152_open(struct net_device *netdev) | |||
2909 | free_all_mem(tp); | 2927 | free_all_mem(tp); |
2910 | } | 2928 | } |
2911 | 2929 | ||
2930 | mutex_unlock(&tp->control); | ||
2931 | |||
2912 | usb_autopm_put_interface(tp->intf); | 2932 | usb_autopm_put_interface(tp->intf); |
2913 | 2933 | ||
2914 | out: | 2934 | out: |
@@ -2929,6 +2949,8 @@ static int rtl8152_close(struct net_device *netdev) | |||
2929 | if (res < 0) { | 2949 | if (res < 0) { |
2930 | rtl_drop_queued_tx(tp); | 2950 | rtl_drop_queued_tx(tp); |
2931 | } else { | 2951 | } else { |
2952 | mutex_lock(&tp->control); | ||
2953 | |||
2932 | /* The autosuspend may have been enabled and wouldn't | 2954 | /* The autosuspend may have been enabled and wouldn't |
2933 | * be disable when autoresume occurs, because the | 2955 | * be disable when autoresume occurs, because the |
2934 | * netif_running() would be false. | 2956 | * netif_running() would be false. |
@@ -2941,6 +2963,9 @@ static int rtl8152_close(struct net_device *netdev) | |||
2941 | tasklet_disable(&tp->tl); | 2963 | tasklet_disable(&tp->tl); |
2942 | tp->rtl_ops.down(tp); | 2964 | tp->rtl_ops.down(tp); |
2943 | tasklet_enable(&tp->tl); | 2965 | tasklet_enable(&tp->tl); |
2966 | |||
2967 | mutex_unlock(&tp->control); | ||
2968 | |||
2944 | usb_autopm_put_interface(tp->intf); | 2969 | usb_autopm_put_interface(tp->intf); |
2945 | } | 2970 | } |
2946 | 2971 | ||
@@ -3165,6 +3190,8 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) | |||
3165 | { | 3190 | { |
3166 | struct r8152 *tp = usb_get_intfdata(intf); | 3191 | struct r8152 *tp = usb_get_intfdata(intf); |
3167 | 3192 | ||
3193 | mutex_lock(&tp->control); | ||
3194 | |||
3168 | if (PMSG_IS_AUTO(message)) | 3195 | if (PMSG_IS_AUTO(message)) |
3169 | set_bit(SELECTIVE_SUSPEND, &tp->flags); | 3196 | set_bit(SELECTIVE_SUSPEND, &tp->flags); |
3170 | else | 3197 | else |
@@ -3184,6 +3211,8 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) | |||
3184 | tasklet_enable(&tp->tl); | 3211 | tasklet_enable(&tp->tl); |
3185 | } | 3212 | } |
3186 | 3213 | ||
3214 | mutex_unlock(&tp->control); | ||
3215 | |||
3187 | return 0; | 3216 | return 0; |
3188 | } | 3217 | } |
3189 | 3218 | ||
@@ -3191,6 +3220,8 @@ static int rtl8152_resume(struct usb_interface *intf) | |||
3191 | { | 3220 | { |
3192 | struct r8152 *tp = usb_get_intfdata(intf); | 3221 | struct r8152 *tp = usb_get_intfdata(intf); |
3193 | 3222 | ||
3223 | mutex_lock(&tp->control); | ||
3224 | |||
3194 | if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) { | 3225 | if (!test_bit(SELECTIVE_SUSPEND, &tp->flags)) { |
3195 | tp->rtl_ops.init(tp); | 3226 | tp->rtl_ops.init(tp); |
3196 | netif_device_attach(tp->netdev); | 3227 | netif_device_attach(tp->netdev); |
@@ -3216,6 +3247,8 @@ static int rtl8152_resume(struct usb_interface *intf) | |||
3216 | usb_submit_urb(tp->intr_urb, GFP_KERNEL); | 3247 | usb_submit_urb(tp->intr_urb, GFP_KERNEL); |
3217 | } | 3248 | } |
3218 | 3249 | ||
3250 | mutex_unlock(&tp->control); | ||
3251 | |||
3219 | return 0; | 3252 | return 0; |
3220 | } | 3253 | } |
3221 | 3254 | ||
@@ -3226,9 +3259,13 @@ static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
3226 | if (usb_autopm_get_interface(tp->intf) < 0) | 3259 | if (usb_autopm_get_interface(tp->intf) < 0) |
3227 | return; | 3260 | return; |
3228 | 3261 | ||
3262 | mutex_lock(&tp->control); | ||
3263 | |||
3229 | wol->supported = WAKE_ANY; | 3264 | wol->supported = WAKE_ANY; |
3230 | wol->wolopts = __rtl_get_wol(tp); | 3265 | wol->wolopts = __rtl_get_wol(tp); |
3231 | 3266 | ||
3267 | mutex_unlock(&tp->control); | ||
3268 | |||
3232 | usb_autopm_put_interface(tp->intf); | 3269 | usb_autopm_put_interface(tp->intf); |
3233 | } | 3270 | } |
3234 | 3271 | ||
@@ -3241,9 +3278,13 @@ static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
3241 | if (ret < 0) | 3278 | if (ret < 0) |
3242 | goto out_set_wol; | 3279 | goto out_set_wol; |
3243 | 3280 | ||
3281 | mutex_lock(&tp->control); | ||
3282 | |||
3244 | __rtl_set_wol(tp, wol->wolopts); | 3283 | __rtl_set_wol(tp, wol->wolopts); |
3245 | tp->saved_wolopts = wol->wolopts & WAKE_ANY; | 3284 | tp->saved_wolopts = wol->wolopts & WAKE_ANY; |
3246 | 3285 | ||
3286 | mutex_unlock(&tp->control); | ||
3287 | |||
3247 | usb_autopm_put_interface(tp->intf); | 3288 | usb_autopm_put_interface(tp->intf); |
3248 | 3289 | ||
3249 | out_set_wol: | 3290 | out_set_wol: |
@@ -3287,8 +3328,12 @@ int rtl8152_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) | |||
3287 | if (ret < 0) | 3328 | if (ret < 0) |
3288 | goto out; | 3329 | goto out; |
3289 | 3330 | ||
3331 | mutex_lock(&tp->control); | ||
3332 | |||
3290 | ret = mii_ethtool_gset(&tp->mii, cmd); | 3333 | ret = mii_ethtool_gset(&tp->mii, cmd); |
3291 | 3334 | ||
3335 | mutex_unlock(&tp->control); | ||
3336 | |||
3292 | usb_autopm_put_interface(tp->intf); | 3337 | usb_autopm_put_interface(tp->intf); |
3293 | 3338 | ||
3294 | out: | 3339 | out: |
@@ -3304,8 +3349,12 @@ static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
3304 | if (ret < 0) | 3349 | if (ret < 0) |
3305 | goto out; | 3350 | goto out; |
3306 | 3351 | ||
3352 | mutex_lock(&tp->control); | ||
3353 | |||
3307 | ret = rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex); | 3354 | ret = rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex); |
3308 | 3355 | ||
3356 | mutex_unlock(&tp->control); | ||
3357 | |||
3309 | usb_autopm_put_interface(tp->intf); | 3358 | usb_autopm_put_interface(tp->intf); |
3310 | 3359 | ||
3311 | out: | 3360 | out: |
@@ -3465,8 +3514,12 @@ rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) | |||
3465 | if (ret < 0) | 3514 | if (ret < 0) |
3466 | goto out; | 3515 | goto out; |
3467 | 3516 | ||
3517 | mutex_lock(&tp->control); | ||
3518 | |||
3468 | ret = tp->rtl_ops.eee_get(tp, edata); | 3519 | ret = tp->rtl_ops.eee_get(tp, edata); |
3469 | 3520 | ||
3521 | mutex_unlock(&tp->control); | ||
3522 | |||
3470 | usb_autopm_put_interface(tp->intf); | 3523 | usb_autopm_put_interface(tp->intf); |
3471 | 3524 | ||
3472 | out: | 3525 | out: |
@@ -3483,10 +3536,14 @@ rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) | |||
3483 | if (ret < 0) | 3536 | if (ret < 0) |
3484 | goto out; | 3537 | goto out; |
3485 | 3538 | ||
3539 | mutex_lock(&tp->control); | ||
3540 | |||
3486 | ret = tp->rtl_ops.eee_set(tp, edata); | 3541 | ret = tp->rtl_ops.eee_set(tp, edata); |
3487 | if (!ret) | 3542 | if (!ret) |
3488 | ret = mii_nway_restart(&tp->mii); | 3543 | ret = mii_nway_restart(&tp->mii); |
3489 | 3544 | ||
3545 | mutex_unlock(&tp->control); | ||
3546 | |||
3490 | usb_autopm_put_interface(tp->intf); | 3547 | usb_autopm_put_interface(tp->intf); |
3491 | 3548 | ||
3492 | out: | 3549 | out: |
@@ -3528,7 +3585,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | |||
3528 | break; | 3585 | break; |
3529 | 3586 | ||
3530 | case SIOCGMIIREG: | 3587 | case SIOCGMIIREG: |
3588 | mutex_lock(&tp->control); | ||
3531 | data->val_out = r8152_mdio_read(tp, data->reg_num); | 3589 | data->val_out = r8152_mdio_read(tp, data->reg_num); |
3590 | mutex_unlock(&tp->control); | ||
3532 | break; | 3591 | break; |
3533 | 3592 | ||
3534 | case SIOCSMIIREG: | 3593 | case SIOCSMIIREG: |
@@ -3536,7 +3595,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | |||
3536 | res = -EPERM; | 3595 | res = -EPERM; |
3537 | break; | 3596 | break; |
3538 | } | 3597 | } |
3598 | mutex_lock(&tp->control); | ||
3539 | r8152_mdio_write(tp, data->reg_num, data->val_in); | 3599 | r8152_mdio_write(tp, data->reg_num, data->val_in); |
3600 | mutex_unlock(&tp->control); | ||
3540 | break; | 3601 | break; |
3541 | 3602 | ||
3542 | default: | 3603 | default: |
@@ -3729,6 +3790,7 @@ static int rtl8152_probe(struct usb_interface *intf, | |||
3729 | goto out; | 3790 | goto out; |
3730 | 3791 | ||
3731 | tasklet_init(&tp->tl, bottom_half, (unsigned long)tp); | 3792 | tasklet_init(&tp->tl, bottom_half, (unsigned long)tp); |
3793 | mutex_init(&tp->control); | ||
3732 | INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); | 3794 | INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); |
3733 | 3795 | ||
3734 | netdev->netdev_ops = &rtl8152_netdev_ops; | 3796 | netdev->netdev_ops = &rtl8152_netdev_ops; |