]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/net/usb/r8152.c
Merge tag 'vfio-v3.18-rc1' of git://github.com/awilliam/linux-vfio
[linux-beck.git] / drivers / net / usb / r8152.c
index 604ef210a4dea5f8e8bd9b543b3dc4156b357286..5cfd414b9a3ea5cc59224cffe0dd675bef490930 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <uapi/linux/mdio.h>
+#include <linux/mdio.h>
 
 /* Version Information */
 #define DRIVER_VERSION "v1.06.1 (2014/10/01)"
 #define OCP_SRAM_ADDR          0xa436
 #define OCP_SRAM_DATA          0xa438
 #define OCP_DOWN_SPEED         0xa442
-#define OCP_EEE_CFG2           0xa5d0
+#define OCP_EEE_ABLE           0xa5c4
+#define OCP_EEE_ADV            0xa5d0
+#define OCP_EEE_LPABLE         0xa5d2
 #define OCP_ADC_CFG            0xbc06
 
 /* SRAM Register */
 #define EEE_NWAY_EN            0x1000
 #define TX_QUIET_EN            0x0200
 #define RX_QUIET_EN            0x0100
-#define SDRISETIME             0x0010  /* bit 4 ~ 6 */
+#define sd_rise_time_mask      0x0070
+#define sd_rise_time(x)                (min(x, 7) << 4)        /* bit 4 ~ 6 */
 #define RG_RXLPI_MSK_HFDUP     0x0008
 #define SDFALLTIME             0x0007  /* bit 0 ~ 2 */
 
 #define RG_EEEPRG_EN           0x0010
 
 /* OCP_EEE_CONFIG3 */
-#define FST_SNR_EYE_R          0x1500  /* bit 7 ~ 15 */
+#define fast_snr_mask          0xff80
+#define fast_snr(x)            (min(x, 0x1ff) << 7)    /* bit 7 ~ 15 */
 #define RG_LFS_SEL             0x0060  /* bit 6 ~ 5 */
 #define MSK_PH                 0x0006  /* bit 0 ~ 3 */
 
 #define FUN_ADDR               0x0000
 #define FUN_DATA               0x4000
 /* bit[4:0] device addr */
-#define DEVICE_ADDR            0x0007
-
-/* OCP_EEE_DATA */
-#define EEE_ADDR               0x003C
-#define EEE_DATA               0x0002
 
 /* OCP_EEE_CFG */
 #define CTAP_SHORT_EN          0x0040
 /* OCP_DOWN_SPEED */
 #define EN_10M_BGOFF           0x0080
 
-/* OCP_EEE_CFG2 */
-#define MY1000_EEE             0x0004
-#define MY100_EEE              0x0002
-
 /* OCP_ADC_CFG */
 #define CKADSEL_L              0x0100
 #define ADC_EN                 0x0080
@@ -424,7 +421,7 @@ enum rtl_register_content {
        FULL_DUP        = 0x01,
 };
 
-#define RTL8152_MAX_TX         10
+#define RTL8152_MAX_TX         4
 #define RTL8152_MAX_RX         10
 #define INTBUFSIZE             2
 #define CRC_SIZE               4
@@ -506,6 +503,7 @@ struct rx_desc {
 #define IPF                            (1 << 23) /* IP checksum fail */
 #define UDPF                           (1 << 22) /* UDP checksum fail */
 #define TCPF                           (1 << 21) /* TCP checksum fail */
+#define RX_VLAN_TAG                    (1 << 16)
 
        __le32 opts4;
        __le32 opts5;
@@ -531,6 +529,7 @@ struct tx_desc {
 #define MSS_MAX                        0x7ffU
 #define TCPHO_SHIFT            17
 #define TCPHO_MAX              0x7ffU
+#define TX_VLAN_TAG                    (1 << 16)
 };
 
 struct r8152;
@@ -575,6 +574,8 @@ struct r8152 {
                void (*up)(struct r8152 *);
                void (*down)(struct r8152 *);
                void (*unload)(struct r8152 *);
+               int (*eee_get)(struct r8152 *, struct ethtool_eee *);
+               int (*eee_set)(struct r8152 *, struct ethtool_eee *);
        } rtl_ops;
 
        int intr_interval;
@@ -607,9 +608,9 @@ enum tx_csum_stat {
  * The RTL chips use a 64 element hash table based on the Ethernet CRC.
  */
 static const int multicast_filter_limit = 32;
-static unsigned int rx_buf_sz = 16384;
+static unsigned int agg_buf_sz = 16384;
 
-#define RTL_LIMITED_TSO_SIZE   (rx_buf_sz - sizeof(struct tx_desc) - \
+#define RTL_LIMITED_TSO_SIZE   (agg_buf_sz - sizeof(struct tx_desc) - \
                                 VLAN_ETH_HLEN - VLAN_HLEN)
 
 static
@@ -623,8 +624,8 @@ int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
                return -ENOMEM;
 
        ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
-                              RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
-                              value, index, tmp, size, 500);
+                             RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
+                             value, index, tmp, size, 500);
 
        memcpy(data, tmp, size);
        kfree(tmp);
@@ -643,8 +644,8 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
                return -ENOMEM;
 
        ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
-                              RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
-                              value, index, tmp, size, 500);
+                             RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
+                             value, index, tmp, size, 500);
 
        kfree(tmp);
 
@@ -652,7 +653,7 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
 }
 
 static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
-                               void *data, u16 type)
+                           void *data, u16 type)
 {
        u16 limit = 64;
        int ret = 0;
@@ -692,7 +693,7 @@ static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
 }
 
 static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
-                               u16 size, void *data, u16 type)
+                            u16 size, void *data, u16 type)
 {
        int ret;
        u16 byteen_start, byteen_end, byen;
@@ -726,8 +727,8 @@ static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
                while (size) {
                        if (size > limit) {
                                ret = set_registers(tp, index,
-                                       type | BYTE_EN_DWORD,
-                                       limit, data);
+                                                   type | BYTE_EN_DWORD,
+                                                   limit, data);
                                if (ret < 0)
                                        goto error1;
 
@@ -736,8 +737,8 @@ static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
                                size -= limit;
                        } else {
                                ret = set_registers(tp, index,
-                                       type | BYTE_EN_DWORD,
-                                       size, data);
+                                                   type | BYTE_EN_DWORD,
+                                                   size, data);
                                if (ret < 0)
                                        goto error1;
 
@@ -972,44 +973,21 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
        usb_autopm_put_interface(tp->intf);
 }
 
-static
-int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
-
-static inline void set_ethernet_addr(struct r8152 *tp)
-{
-       struct net_device *dev = tp->netdev;
-       int ret;
-       u8 node_id[8] = {0};
-
-       if (tp->version == RTL_VER_01)
-               ret = pla_ocp_read(tp, PLA_IDR, sizeof(node_id), node_id);
-       else
-               ret = pla_ocp_read(tp, PLA_BACKUP, sizeof(node_id), node_id);
-
-       if (ret < 0) {
-               netif_notice(tp, probe, dev, "inet addr fail\n");
-       } else {
-               if (tp->version != RTL_VER_01) {
-                       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR,
-                                      CRWECR_CONFIG);
-                       pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES,
-                                     sizeof(node_id), node_id);
-                       ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR,
-                                      CRWECR_NORAML);
-               }
-
-               memcpy(dev->dev_addr, node_id, dev->addr_len);
-               memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-       }
-}
+static int
+r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
 
 static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
 {
        struct r8152 *tp = netdev_priv(netdev);
        struct sockaddr *addr = p;
+       int ret = -EADDRNOTAVAIL;
 
        if (!is_valid_ether_addr(addr->sa_data))
-               return -EADDRNOTAVAIL;
+               goto out1;
+
+       ret = usb_autopm_get_interface(tp->intf);
+       if (ret < 0)
+               goto out1;
 
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
@@ -1017,7 +995,40 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
        pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data);
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
 
-       return 0;
+       usb_autopm_put_interface(tp->intf);
+out1:
+       return ret;
+}
+
+static int set_ethernet_addr(struct r8152 *tp)
+{
+       struct net_device *dev = tp->netdev;
+       struct sockaddr sa;
+       int ret;
+
+       if (tp->version == RTL_VER_01)
+               ret = pla_ocp_read(tp, PLA_IDR, 8, sa.sa_data);
+       else
+               ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data);
+
+       if (ret < 0) {
+               netif_err(tp, probe, dev, "Get ether addr fail\n");
+       } else if (!is_valid_ether_addr(sa.sa_data)) {
+               netif_err(tp, probe, dev, "Invalid ether addr %pM\n",
+                         sa.sa_data);
+               eth_hw_addr_random(dev);
+               ether_addr_copy(sa.sa_data, dev->dev_addr);
+               ret = rtl8152_set_mac_address(dev, &sa);
+               netif_info(tp, probe, dev, "Random ether addr %pM\n",
+                          sa.sa_data);
+       } else {
+               if (tp->version == RTL_VER_01)
+                       ether_addr_copy(dev->dev_addr, sa.sa_data);
+               else
+                       ret = rtl8152_set_mac_address(dev, &sa);
+       }
+
+       return ret;
 }
 
 static void read_bulk_callback(struct urb *urb)
@@ -1248,13 +1259,13 @@ static int alloc_all_mem(struct r8152 *tp)
        skb_queue_head_init(&tp->tx_queue);
 
        for (i = 0; i < RTL8152_MAX_RX; i++) {
-               buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+               buf = kmalloc_node(agg_buf_sz, GFP_KERNEL, node);
                if (!buf)
                        goto err1;
 
                if (buf != rx_agg_align(buf)) {
                        kfree(buf);
-                       buf = kmalloc_node(rx_buf_sz + RX_ALIGN, GFP_KERNEL,
+                       buf = kmalloc_node(agg_buf_sz + RX_ALIGN, GFP_KERNEL,
                                           node);
                        if (!buf)
                                goto err1;
@@ -1274,13 +1285,13 @@ static int alloc_all_mem(struct r8152 *tp)
        }
 
        for (i = 0; i < RTL8152_MAX_TX; i++) {
-               buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+               buf = kmalloc_node(agg_buf_sz, GFP_KERNEL, node);
                if (!buf)
                        goto err1;
 
                if (buf != tx_agg_align(buf)) {
                        kfree(buf);
-                       buf = kmalloc_node(rx_buf_sz + TX_ALIGN, GFP_KERNEL,
+                       buf = kmalloc_node(agg_buf_sz + TX_ALIGN, GFP_KERNEL,
                                           node);
                        if (!buf)
                                goto err1;
@@ -1311,8 +1322,8 @@ static int alloc_all_mem(struct r8152 *tp)
 
        tp->intr_interval = (int)ep_intr->desc.bInterval;
        usb_fill_int_urb(tp->intr_urb, tp->udev, usb_rcvintpipe(tp->udev, 3),
-                    tp->intr_buff, INTBUFSIZE, intr_callback,
-                    tp, tp->intr_interval);
+                        tp->intr_buff, INTBUFSIZE, intr_callback,
+                        tp, tp->intr_interval);
 
        return 0;
 
@@ -1354,8 +1365,7 @@ static inline __be16 get_protocol(struct sk_buff *skb)
        return protocol;
 }
 
-/*
- * r8152_csum_workaround()
+/* r8152_csum_workaround()
  * The hw limites the value the transport offset. When the offset is out of the
  * range, calculate the checksum by sw.
  */
@@ -1398,8 +1408,7 @@ drop:
        }
 }
 
-/*
- * msdn_giant_send_check()
+/* msdn_giant_send_check()
  * According to the document of microsoft, the TCP Pseudo Header excludes the
  * packet length for IPv6 TCP large packets.
  */
@@ -1422,6 +1431,25 @@ static int msdn_giant_send_check(struct sk_buff *skb)
        return ret;
 }
 
+static inline void rtl_tx_vlan_tag(struct tx_desc *desc, struct sk_buff *skb)
+{
+       if (vlan_tx_tag_present(skb)) {
+               u32 opts2;
+
+               opts2 = TX_VLAN_TAG | swab16(vlan_tx_tag_get(skb));
+               desc->opts2 |= cpu_to_le32(opts2);
+       }
+}
+
+static inline void rtl_rx_vlan_tag(struct rx_desc *desc, struct sk_buff *skb)
+{
+       u32 opts2 = le32_to_cpu(desc->opts2);
+
+       if (opts2 & RX_VLAN_TAG)
+               __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+                                      swab16(opts2 & 0xffff));
+}
+
 static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
                         struct sk_buff *skb, u32 len, u32 transport_offset)
 {
@@ -1518,8 +1546,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
        spin_unlock(&tx_queue->lock);
 
        tx_data = agg->head;
-       agg->skb_num = agg->skb_len = 0;
-       remain = rx_buf_sz;
+       agg->skb_num = 0;
+       agg->skb_len = 0;
+       remain = agg_buf_sz;
 
        while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
                struct tx_desc *tx_desc;
@@ -1548,6 +1577,8 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
                        continue;
                }
 
+               rtl_tx_vlan_tag(tx_desc, skb);
+
                tx_data += sizeof(*tx_desc);
 
                len = skb->len;
@@ -1566,7 +1597,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 
                dev_kfree_skb_any(skb);
 
-               remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
+               remain = agg_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
        }
 
        if (!skb_queue_empty(&skb_head)) {
@@ -1689,6 +1720,7 @@ static void rx_bottom(struct r8152 *tp)
                        memcpy(skb->data, rx_data, pkt_len);
                        skb_put(skb, pkt_len);
                        skb->protocol = eth_type_trans(skb, netdev);
+                       rtl_rx_vlan_tag(rx_desc, skb);
                        netif_receive_skb(skb);
                        stats->rx_packets++;
                        stats->rx_bytes += pkt_len;
@@ -1772,8 +1804,8 @@ static
 int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags)
 {
        usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
-                     agg->head, rx_buf_sz,
-                     (usb_complete_t)read_bulk_callback, agg);
+                         agg->head, agg_buf_sz,
+                         (usb_complete_t)read_bulk_callback, agg);
 
        return usb_submit_urb(agg->urb, mem_flags);
 }
@@ -1835,18 +1867,22 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)
                /* Unconditionally log net taps. */
                netif_notice(tp, link, netdev, "Promiscuous mode enabled\n");
                ocp_data |= RCR_AM | RCR_AAP;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
+               mc_filter[1] = 0xffffffff;
+               mc_filter[0] = 0xffffffff;
        } else if ((netdev_mc_count(netdev) > multicast_filter_limit) ||
                   (netdev->flags & IFF_ALLMULTI)) {
                /* Too many to filter perfectly -- accept all multicasts. */
                ocp_data |= RCR_AM;
-               mc_filter[1] = mc_filter[0] = 0xffffffff;
+               mc_filter[1] = 0xffffffff;
+               mc_filter[0] = 0xffffffff;
        } else {
                struct netdev_hw_addr *ha;
 
-               mc_filter[1] = mc_filter[0] = 0;
+               mc_filter[1] = 0;
+               mc_filter[0] = 0;
                netdev_for_each_mc_addr(ha, netdev) {
                        int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
+
                        mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
                        ocp_data |= RCR_AM;
                }
@@ -1861,7 +1897,7 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)
 }
 
 static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
-                                       struct net_device *netdev)
+                                     struct net_device *netdev)
 {
        struct r8152 *tp = netdev_priv(netdev);
 
@@ -1877,8 +1913,9 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
                        usb_mark_last_busy(tp->udev);
                        tasklet_schedule(&tp->tl);
                }
-       } else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
+       } else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen) {
                netif_stop_queue(netdev);
+       }
 
        return NETDEV_TX_OK;
 }
@@ -1903,7 +1940,7 @@ static void rtl8152_nic_reset(struct r8152 *tp)
        for (i = 0; i < 1000; i++) {
                if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
                        break;
-               udelay(100);
+               usleep_range(100, 400);
        }
 }
 
@@ -1911,8 +1948,8 @@ static void set_tx_qlen(struct r8152 *tp)
 {
        struct net_device *netdev = tp->netdev;
 
-       tp->tx_qlen = rx_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN +
-                                  sizeof(struct tx_desc));
+       tp->tx_qlen = agg_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN +
+                                   sizeof(struct tx_desc));
 }
 
 static inline u8 rtl8152_get_speed(struct r8152 *tp)
@@ -2061,13 +2098,13 @@ static void rtl_disable(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        for (i = 0; i < 1000; i++) {
                if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        rtl_stop_rx(tp);
@@ -2091,6 +2128,34 @@ static void r8152_power_cut_en(struct r8152 *tp, bool enable)
        ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
 }
 
+static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
+{
+       u32 ocp_data;
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
+       if (enable)
+               ocp_data |= CPCR_RX_VLAN;
+       else
+               ocp_data &= ~CPCR_RX_VLAN;
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+}
+
+static int rtl8152_set_features(struct net_device *dev,
+                               netdev_features_t features)
+{
+       netdev_features_t changed = features ^ dev->features;
+       struct r8152 *tp = netdev_priv(dev);
+
+       if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
+               if (features & NETIF_F_HW_VLAN_CTAG_RX)
+                       rtl_rx_vlan_en(tp, true);
+               else
+                       rtl_rx_vlan_en(tp, false);
+       }
+
+       return 0;
+}
+
 #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
 
 static u32 __rtl_get_wol(struct r8152 *tp)
@@ -2274,7 +2339,7 @@ static void r8152b_exit_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
@@ -2285,7 +2350,7 @@ static void r8152b_exit_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        rtl8152_nic_reset(tp);
@@ -2316,9 +2381,7 @@ static void r8152b_exit_oob(struct r8152 *tp)
        ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
                        TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-       ocp_data &= ~CPCR_RX_VLAN;
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+       rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
 
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
@@ -2346,7 +2409,7 @@ static void r8152b_enter_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
@@ -2357,14 +2420,12 @@ static void r8152b_enter_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-       ocp_data |= CPCR_RX_VLAN;
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+       rtl_rx_vlan_en(tp, true);
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
@@ -2499,7 +2560,7 @@ static void r8153_first_init(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
@@ -2510,12 +2571,10 @@ static void r8153_first_init(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-       ocp_data &= ~CPCR_RX_VLAN;
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+       rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
 
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
@@ -2554,7 +2613,7 @@ static void r8153_enter_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
@@ -2565,7 +2624,7 @@ static void r8153_enter_oob(struct r8152 *tp)
                ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
                if (ocp_data & LINK_LIST_READY)
                        break;
-               mdelay(1);
+               usleep_range(1000, 2000);
        }
 
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
@@ -2574,9 +2633,7 @@ static void r8153_enter_oob(struct r8152 *tp)
        ocp_data &= ~TEREDO_WAKE_MASK;
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-       ocp_data |= CPCR_RX_VLAN;
-       ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
+       rtl_rx_vlan_en(tp, true);
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
@@ -2876,8 +2933,7 @@ static int rtl8152_close(struct net_device *netdev)
        if (res < 0) {
                rtl_drop_queued_tx(tp);
        } else {
-               /*
-                * The autosuspend may have been enabled and wouldn't
+               /* The autosuspend may have been enabled and wouldn't
                 * be disable when autoresume occurs, because the
                 * netif_running() would be false.
                 */
@@ -2897,43 +2953,92 @@ static int rtl8152_close(struct net_device *netdev)
        return res;
 }
 
-static void r8152b_enable_eee(struct r8152 *tp)
+static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg)
+{
+       ocp_reg_write(tp, OCP_EEE_AR, FUN_ADDR | dev);
+       ocp_reg_write(tp, OCP_EEE_DATA, reg);
+       ocp_reg_write(tp, OCP_EEE_AR, FUN_DATA | dev);
+}
+
+static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg)
+{
+       u16 data;
+
+       r8152_mmd_indirect(tp, dev, reg);
+       data = ocp_reg_read(tp, OCP_EEE_DATA);
+       ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
+
+       return data;
+}
+
+static void r8152_mmd_write(struct r8152 *tp, u16 dev, u16 reg, u16 data)
 {
+       r8152_mmd_indirect(tp, dev, reg);
+       ocp_reg_write(tp, OCP_EEE_DATA, data);
+       ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
+}
+
+static void r8152_eee_en(struct r8152 *tp, bool enable)
+{
+       u16 config1, config2, config3;
        u32 ocp_data;
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
-       ocp_data |= EEE_RX_EN | EEE_TX_EN;
+       config1 = ocp_reg_read(tp, OCP_EEE_CONFIG1) & ~sd_rise_time_mask;
+       config2 = ocp_reg_read(tp, OCP_EEE_CONFIG2);
+       config3 = ocp_reg_read(tp, OCP_EEE_CONFIG3) & ~fast_snr_mask;
+
+       if (enable) {
+               ocp_data |= EEE_RX_EN | EEE_TX_EN;
+               config1 |= EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN | RX_QUIET_EN;
+               config1 |= sd_rise_time(1);
+               config2 |= RG_DACQUIET_EN | RG_LDVQUIET_EN;
+               config3 |= fast_snr(42);
+       } else {
+               ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
+               config1 &= ~(EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN |
+                            RX_QUIET_EN);
+               config1 |= sd_rise_time(7);
+               config2 &= ~(RG_DACQUIET_EN | RG_LDVQUIET_EN);
+               config3 |= fast_snr(511);
+       }
+
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
-       ocp_reg_write(tp, OCP_EEE_CONFIG1, RG_TXLPI_MSK_HFDUP | RG_MATCLR_EN |
-                                          EEE_10_CAP | EEE_NWAY_EN |
-                                          TX_QUIET_EN | RX_QUIET_EN |
-                                          SDRISETIME | RG_RXLPI_MSK_HFDUP |
-                                          SDFALLTIME);
-       ocp_reg_write(tp, OCP_EEE_CONFIG2, RG_LPIHYS_NUM | RG_DACQUIET_EN |
-                                          RG_LDVQUIET_EN | RG_CKRSEL |
-                                          RG_EEEPRG_EN);
-       ocp_reg_write(tp, OCP_EEE_CONFIG3, FST_SNR_EYE_R | RG_LFS_SEL | MSK_PH);
-       ocp_reg_write(tp, OCP_EEE_AR, FUN_ADDR | DEVICE_ADDR);
-       ocp_reg_write(tp, OCP_EEE_DATA, EEE_ADDR);
-       ocp_reg_write(tp, OCP_EEE_AR, FUN_DATA | DEVICE_ADDR);
-       ocp_reg_write(tp, OCP_EEE_DATA, EEE_DATA);
-       ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
+       ocp_reg_write(tp, OCP_EEE_CONFIG1, config1);
+       ocp_reg_write(tp, OCP_EEE_CONFIG2, config2);
+       ocp_reg_write(tp, OCP_EEE_CONFIG3, config3);
 }
 
-static void r8153_enable_eee(struct r8152 *tp)
+static void r8152b_enable_eee(struct r8152 *tp)
+{
+       r8152_eee_en(tp, true);
+       r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, MDIO_EEE_100TX);
+}
+
+static void r8153_eee_en(struct r8152 *tp, bool enable)
 {
        u32 ocp_data;
-       u16 data;
+       u16 config;
 
        ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
-       ocp_data |= EEE_RX_EN | EEE_TX_EN;
+       config = ocp_reg_read(tp, OCP_EEE_CFG);
+
+       if (enable) {
+               ocp_data |= EEE_RX_EN | EEE_TX_EN;
+               config |= EEE10_EN;
+       } else {
+               ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
+               config &= ~EEE10_EN;
+       }
+
        ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
-       data = ocp_reg_read(tp, OCP_EEE_CFG);
-       data |= EEE10_EN;
-       ocp_reg_write(tp, OCP_EEE_CFG, data);
-       data = ocp_reg_read(tp, OCP_EEE_CFG2);
-       data |= MY1000_EEE | MY100_EEE;
-       ocp_reg_write(tp, OCP_EEE_CFG2, data);
+       ocp_reg_write(tp, OCP_EEE_CFG, config);
+}
+
+static void r8153_enable_eee(struct r8152 *tp)
+{
+       r8153_eee_en(tp, true);
+       ocp_reg_write(tp, OCP_EEE_ADV, MDIO_EEE_1000T | MDIO_EEE_100TX);
 }
 
 static void r8152b_enable_fc(struct r8152 *tp)
@@ -3105,8 +3210,9 @@ static int rtl8152_resume(struct usb_interface *intf)
                } else {
                        tp->rtl_ops.up(tp);
                        rtl8152_set_speed(tp, AUTONEG_ENABLE,
-                               tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
-                               DUPLEX_FULL);
+                                         tp->mii.supports_gmii ?
+                                         SPEED_1000 : SPEED_100,
+                                         DUPLEX_FULL);
                        tp->speed = 0;
                        netif_carrier_off(tp->netdev);
                        set_bit(WORK_ENABLE, &tp->flags);
@@ -3167,8 +3273,8 @@ static void rtl8152_get_drvinfo(struct net_device *netdev,
 {
        struct r8152 *tp = netdev_priv(netdev);
 
-       strncpy(info->driver, MODULENAME, ETHTOOL_BUSINFO_LEN);
-       strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+       strlcpy(info->driver, MODULENAME, sizeof(info->driver));
+       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
        usb_make_path(tp->udev, info->bus_info, sizeof(info->bus_info));
 }
 
@@ -3263,6 +3369,124 @@ static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data)
        }
 }
 
+static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
+{
+       u32 ocp_data, lp, adv, supported = 0;
+       u16 val;
+
+       val = r8152_mmd_read(tp, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+       supported = mmd_eee_cap_to_ethtool_sup_t(val);
+
+       val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
+       adv = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
+       lp = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
+       ocp_data &= EEE_RX_EN | EEE_TX_EN;
+
+       eee->eee_enabled = !!ocp_data;
+       eee->eee_active = !!(supported & adv & lp);
+       eee->supported = supported;
+       eee->advertised = adv;
+       eee->lp_advertised = lp;
+
+       return 0;
+}
+
+static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
+{
+       u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
+
+       r8152_eee_en(tp, eee->eee_enabled);
+
+       if (!eee->eee_enabled)
+               val = 0;
+
+       r8152_mmd_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+
+       return 0;
+}
+
+static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
+{
+       u32 ocp_data, lp, adv, supported = 0;
+       u16 val;
+
+       val = ocp_reg_read(tp, OCP_EEE_ABLE);
+       supported = mmd_eee_cap_to_ethtool_sup_t(val);
+
+       val = ocp_reg_read(tp, OCP_EEE_ADV);
+       adv = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       val = ocp_reg_read(tp, OCP_EEE_LPABLE);
+       lp = mmd_eee_adv_to_ethtool_adv_t(val);
+
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
+       ocp_data &= EEE_RX_EN | EEE_TX_EN;
+
+       eee->eee_enabled = !!ocp_data;
+       eee->eee_active = !!(supported & adv & lp);
+       eee->supported = supported;
+       eee->advertised = adv;
+       eee->lp_advertised = lp;
+
+       return 0;
+}
+
+static int r8153_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
+{
+       u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
+
+       r8153_eee_en(tp, eee->eee_enabled);
+
+       if (!eee->eee_enabled)
+               val = 0;
+
+       ocp_reg_write(tp, OCP_EEE_ADV, val);
+
+       return 0;
+}
+
+static int
+rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+       struct r8152 *tp = netdev_priv(net);
+       int ret;
+
+       ret = usb_autopm_get_interface(tp->intf);
+       if (ret < 0)
+               goto out;
+
+       ret = tp->rtl_ops.eee_get(tp, edata);
+
+       usb_autopm_put_interface(tp->intf);
+
+out:
+       return ret;
+}
+
+static int
+rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+       struct r8152 *tp = netdev_priv(net);
+       int ret;
+
+       ret = usb_autopm_get_interface(tp->intf);
+       if (ret < 0)
+               goto out;
+
+       ret = tp->rtl_ops.eee_set(tp, edata);
+       if (!ret)
+               ret = mii_nway_restart(&tp->mii);
+
+       usb_autopm_put_interface(tp->intf);
+
+out:
+       return ret;
+}
+
 static struct ethtool_ops ops = {
        .get_drvinfo = rtl8152_get_drvinfo,
        .get_settings = rtl8152_get_settings,
@@ -3275,6 +3499,8 @@ static struct ethtool_ops ops = {
        .get_strings = rtl8152_get_strings,
        .get_sset_count = rtl8152_get_sset_count,
        .get_ethtool_stats = rtl8152_get_ethtool_stats,
+       .get_eee = rtl_ethtool_get_eee,
+       .set_eee = rtl_ethtool_set_eee,
 };
 
 static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -3343,6 +3569,7 @@ static const struct net_device_ops rtl8152_netdev_ops = {
        .ndo_do_ioctl           = rtl8152_ioctl,
        .ndo_start_xmit         = rtl8152_start_xmit,
        .ndo_tx_timeout         = rtl8152_tx_timeout,
+       .ndo_set_features       = rtl8152_set_features,
        .ndo_set_rx_mode        = rtl8152_set_rx_mode,
        .ndo_set_mac_address    = rtl8152_set_mac_address,
        .ndo_change_mtu         = rtl8152_change_mtu,
@@ -3415,6 +3642,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
                        ops->up                 = rtl8152_up;
                        ops->down               = rtl8152_down;
                        ops->unload             = rtl8152_unload;
+                       ops->eee_get            = r8152_get_eee;
+                       ops->eee_set            = r8152_set_eee;
                        ret = 0;
                        break;
                case PRODUCT_ID_RTL8153:
@@ -3424,6 +3653,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
                        ops->up                 = rtl8153_up;
                        ops->down               = rtl8153_down;
                        ops->unload             = rtl8153_unload;
+                       ops->eee_get            = r8153_get_eee;
+                       ops->eee_set            = r8153_set_eee;
                        ret = 0;
                        break;
                default:
@@ -3440,6 +3671,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
                        ops->up                 = rtl8153_up;
                        ops->down               = rtl8153_down;
                        ops->unload             = rtl8153_unload;
+                       ops->eee_get            = r8153_get_eee;
+                       ops->eee_set            = r8153_set_eee;
                        ret = 0;
                        break;
                default:
@@ -3497,10 +3730,16 @@ static int rtl8152_probe(struct usb_interface *intf,
 
        netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
                            NETIF_F_TSO | NETIF_F_FRAGLIST | NETIF_F_IPV6_CSUM |
-                           NETIF_F_TSO6;
+                           NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_RX |
+                           NETIF_F_HW_VLAN_CTAG_TX;
        netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_SG |
                              NETIF_F_TSO | NETIF_F_FRAGLIST |
-                             NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+                             NETIF_F_IPV6_CSUM | NETIF_F_TSO6 |
+                             NETIF_F_HW_VLAN_CTAG_RX |
+                             NETIF_F_HW_VLAN_CTAG_TX;
+       netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+                               NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
+                               NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
        netdev->ethtool_ops = &ops;
        netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);