diff options
Diffstat (limited to 'drivers/net/usb/r8152.c')
-rw-r--r-- | drivers/net/usb/r8152.c | 250 |
1 files changed, 166 insertions, 84 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2470d9c2e4f..3d5c39a1e46 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -424,7 +424,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 +506,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 +532,7 @@ struct tx_desc { #define MSS_MAX 0x7ffU #define TCPHO_SHIFT 17 #define TCPHO_MAX 0x7ffU +#define TX_VLAN_TAG (1 << 16) }; struct r8152; @@ -607,9 +609,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 @@ -975,34 +977,6 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val) 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 rtl8152_set_mac_address(struct net_device *netdev, void *p) { struct r8152 *tp = netdev_priv(netdev); @@ -1020,6 +994,37 @@ static int rtl8152_set_mac_address(struct net_device *netdev, void *p) return 0; } +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) { struct net_device *netdev; @@ -1248,13 +1253,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 +1279,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; @@ -1420,6 +1425,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,7 +1542,7 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) tx_data = agg->head; agg->skb_num = 0; agg->skb_len = 0; - remain = rx_buf_sz; + remain = agg_buf_sz; while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) { struct tx_desc *tx_desc; @@ -1547,6 +1571,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; @@ -1565,7 +1591,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)) { @@ -1688,6 +1714,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; @@ -1771,7 +1798,7 @@ 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, + agg->head, agg_buf_sz, (usb_complete_t)read_bulk_callback, agg); return usb_submit_urb(agg->urb, mem_flags); @@ -1915,8 +1942,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) @@ -2023,7 +2050,7 @@ static int rtl8153_enable(struct r8152 *tp) return rtl_enable(tp); } -static void rtl8152_disable(struct r8152 *tp) +static void rtl_disable(struct r8152 *tp) { u32 ocp_data; int i; @@ -2048,13 +2075,13 @@ static void rtl8152_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); } for (i = 0; i < RTL8152_MAX_RX; i++) @@ -2079,6 +2106,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) @@ -2199,7 +2254,7 @@ static void rtl_clear_bp(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0); ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0); ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0); - mdelay(3); + usleep_range(3000, 6000); ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0); ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0); } @@ -2236,6 +2291,13 @@ static inline void r8152b_enable_aldps(struct r8152 *tp) LINKENA | DIS_SDSAVE); } +static void rtl8152_disable(struct r8152 *tp) +{ + r8152b_disable_aldps(tp); + rtl_disable(tp); + r8152b_enable_aldps(tp); +} + static void r8152b_hw_phy_cfg(struct r8152 *tp) { u16 data; @@ -2246,11 +2308,8 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp) r8152_mdio_write(tp, MII_BMCR, data); } - r8152b_disable_aldps(tp); - rtl_clear_bp(tp); - r8152b_enable_aldps(tp); set_bit(PHY_RESET, &tp->flags); } @@ -2259,9 +2318,6 @@ static void r8152b_exit_oob(struct r8152 *tp) u32 ocp_data; int i; - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return; - ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ocp_data &= ~RCR_ACPT_ALL; ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); @@ -2285,7 +2341,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); @@ -2296,7 +2352,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); @@ -2327,9 +2383,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); @@ -2351,13 +2405,13 @@ static void r8152b_enter_oob(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB); ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB); - rtl8152_disable(tp); + rtl_disable(tp); for (i = 0; i < 1000; i++) { 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); @@ -2368,14 +2422,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; @@ -2489,9 +2541,6 @@ static void r8153_first_init(struct r8152 *tp) u32 ocp_data; int i; - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return; - rxdy_gated_en(tp, true); r8153_teredo_off(tp); @@ -2515,7 +2564,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); @@ -2526,12 +2575,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); @@ -2564,13 +2611,13 @@ static void r8153_enter_oob(struct r8152 *tp) ocp_data &= ~NOW_IS_OOB; ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); - rtl8152_disable(tp); + rtl_disable(tp); for (i = 0; i < 1000; i++) { 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); @@ -2581,7 +2628,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); @@ -2590,9 +2637,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; @@ -2628,6 +2673,13 @@ static void r8153_enable_aldps(struct r8152 *tp) ocp_reg_write(tp, OCP_POWER_CFG, data); } +static void rtl8153_disable(struct r8152 *tp) +{ + r8153_disable_aldps(tp); + rtl_disable(tp); + r8153_enable_aldps(tp); +} + static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) { u16 bmcr, anar, gbcr; @@ -2718,6 +2770,16 @@ out: return ret; } +static void rtl8152_up(struct r8152 *tp) +{ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + + r8152b_disable_aldps(tp); + r8152b_exit_oob(tp); + r8152b_enable_aldps(tp); +} + static void rtl8152_down(struct r8152 *tp) { if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2731,6 +2793,16 @@ static void rtl8152_down(struct r8152 *tp) r8152b_enable_aldps(tp); } +static void rtl8153_up(struct r8152 *tp) +{ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + + r8153_disable_aldps(tp); + r8153_first_init(tp); + r8153_enable_aldps(tp); +} + static void rtl8153_down(struct r8152 *tp) { if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2949,6 +3021,8 @@ static void r8152b_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; + r8152b_disable_aldps(tp); + if (tp->version == RTL_VER_01) { ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); ocp_data &= ~LED_MODE_MASK; @@ -2987,6 +3061,7 @@ static void r8153_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; + r8153_disable_aldps(tp); r8153_u1u2en(tp, false); for (i = 0; i < 500; i++) { @@ -3151,8 +3226,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)); } @@ -3327,6 +3402,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, @@ -3396,7 +3472,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) ops->init = r8152b_init; ops->enable = rtl8152_enable; ops->disable = rtl8152_disable; - ops->up = r8152b_exit_oob; + ops->up = rtl8152_up; ops->down = rtl8152_down; ops->unload = rtl8152_unload; ret = 0; @@ -3404,8 +3480,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) case PRODUCT_ID_RTL8153: ops->init = r8153_init; ops->enable = rtl8153_enable; - ops->disable = rtl8152_disable; - ops->up = r8153_first_init; + ops->disable = rtl8153_disable; + ops->up = rtl8153_up; ops->down = rtl8153_down; ops->unload = rtl8153_unload; ret = 0; @@ -3420,8 +3496,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) case PRODUCT_ID_SAMSUNG: ops->init = r8153_init; ops->enable = rtl8153_enable; - ops->disable = rtl8152_disable; - ops->up = r8153_first_init; + ops->disable = rtl8153_disable; + ops->up = rtl8153_up; ops->down = rtl8153_down; ops->unload = rtl8153_unload; ret = 0; @@ -3481,10 +3557,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); |