From 391587c3447d99b842a647f8e701895c9eea050b Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:48:11 -0800 Subject: netxen: fix ipv6 offload and tx cleanup o fix the ip/tcp hdr offset in tx descriptors for ipv6. o cleanup xmit function, move the tso checks into separate function, this reduces unnecessary endian conversions back and forth. o optimize macros to initialize tx descriptors. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 101 ++++++++++++++++------------------- 1 file changed, 45 insertions(+), 56 deletions(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index ba01524b5531..cb3912381802 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -39,6 +39,7 @@ #include "netxen_nic_phan_reg.h" #include +#include #include MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); @@ -1137,29 +1138,46 @@ static int netxen_nic_close(struct net_device *netdev) return 0; } -void netxen_tso_check(struct netxen_adapter *adapter, +static bool netxen_tso_check(struct net_device *netdev, struct cmd_desc_type0 *desc, struct sk_buff *skb) { - if (desc->mss) { - desc->total_hdr_length = (sizeof(struct ethhdr) + - ip_hdrlen(skb) + tcp_hdrlen(skb)); + bool tso = false; + u8 opcode = TX_ETHER_PKT; - if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) && - (skb->protocol == htons(ETH_P_IPV6))) - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6); - else - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); + if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + skb_shinfo(skb)->gso_size > 0) { + + desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + desc->total_hdr_length = + skb_transport_offset(skb) + tcp_hdrlen(skb); + + opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + TX_TCP_LSO6 : TX_TCP_LSO; + tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); - else if (ip_hdr(skb)->protocol == IPPROTO_UDP) - netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); - else - return; + u8 l4proto; + + if (skb->protocol == htons(ETH_P_IP)) { + l4proto = ip_hdr(skb)->protocol; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCP_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDP_PKT; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + l4proto = ipv6_hdr(skb)->nexthdr; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCPV6_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDPV6_PKT; + } } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); + netxen_set_tx_flags_opcode(desc, 0, opcode); + return tso; } static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -1167,33 +1185,20 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_hardware_context *hw = &adapter->ahw; unsigned int first_seg_len = skb->len - skb->data_len; + struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; - unsigned int i; + struct cmd_desc_type0 *hwdesc; + int i, k; u32 producer, consumer; - u32 saved_producer = 0; - struct cmd_desc_type0 *hwdesc; - int k; - struct netxen_cmd_buffer *pbuf = NULL; - int frag_count; - int no_of_desc; + int frag_count, no_of_desc; u32 num_txd = adapter->max_tx_desc_count; + bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; - if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { - if (skb_shinfo(skb)->gso_size > 0) { - - no_of_desc++; - if ((ip_hdrlen(skb) + tcp_hdrlen(skb) + - sizeof(struct ethhdr)) > - (sizeof(struct cmd_desc_type0) - 2)) { - no_of_desc++; - } - } - } producer = adapter->cmd_producer; smp_mb(); @@ -1205,34 +1210,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* Copy the descriptors into the hardware */ - saved_producer = producer; hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; - if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && - skb_shinfo(skb)->gso_size > 0) { - pbuf->mss = skb_shinfo(skb)->gso_size; - hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - } else { - pbuf->mss = 0; - hwdesc->mss = 0; - } - pbuf->total_length = skb->len; + + is_tso = netxen_tso_check(netdev, hwdesc, skb); + pbuf->skb = skb; - pbuf->cmd = TX_ETHER_PKT; pbuf->frag_count = frag_count; - pbuf->port = adapter->portnum; buffrag = &pbuf->frag_array[0]; buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); buffrag->length = first_seg_len; - netxen_set_cmd_desc_totallength(hwdesc, skb->len); - netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); - netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT); + netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); + netxen_set_tx_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum); hwdesc->buffer1_length = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); @@ -1285,16 +1278,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } producer = get_next_index(producer, num_txd); - /* might change opcode to TX_TCP_LSO */ - netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); - /* For LSO, we need to copy the MAC/IP/TCP headers into * the descriptor ring */ - if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) - == TX_TCP_LSO) { + if (is_tso) { int hdr_len, first_hdr_len, more_hdr; - hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { first_hdr_len = sizeof(struct cmd_desc_type0) - 2; more_hdr = 1; -- cgit v1.2.3 From c7860a2aec571ea95d3ad19b8d9775b27828baac Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:48:32 -0800 Subject: netxen: fix link speed reporting for some boards o Read negotiated link speed when link state changes. o Fix link speed reporting for hybrid nic boards, which have both 1Gbps and 10Gbps ports. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cb3912381802..2c6ce6ffde09 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -243,7 +243,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; case NETXEN_BRDTYPE_P2_SB35_4G: @@ -252,6 +252,14 @@ static void netxen_check_options(struct netxen_adapter *adapter) adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; + case NETXEN_BRDTYPE_P3_10G_TP: + adapter->msix_supported = !!use_msi_x; + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + else + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; + break; + default: adapter->msix_supported = 0; adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; @@ -1396,6 +1404,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1404,6 +1414,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_on(netdev); netif_wake_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } } -- cgit v1.2.3 From 27c915a4d843b90eb4065298969578d15e5e6ab0 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:49:00 -0800 Subject: netxen: firmware init fix o Fix order or rom register writes. o Reduce udelays when writing rom registers. This cuts the firmware init time by 40%. o Do not reset core/memory clocks when reinitializing driver. Firmware willl handle this when initialized. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 47 +++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2c6ce6ffde09..cbe2b3e814dd 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -280,10 +280,15 @@ static void netxen_check_options(struct netxen_adapter *adapter) static int netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) { - int ret = 0; + u32 val, timeout; if (first_boot == 0x55555555) { /* This is the first boot after power up */ + adapter->pci_write_normalize(adapter, + NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; /* PCI bus master workaround */ adapter->hw_read_wx(adapter, @@ -303,18 +308,26 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) /* clear the register for future unloads/loads */ adapter->pci_write_normalize(adapter, NETXEN_CAM_RAM(0x1fc), 0); - ret = -1; + return -EIO; } - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - /* Start P2 boot loader */ - adapter->pci_write_normalize(adapter, - NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } + /* Start P2 boot loader */ + val = adapter->pci_read_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE); + adapter->pci_write_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); + timeout = 0; + do { + msleep(1); + val = adapter->pci_read_normalize(adapter, + NETXEN_CAM_RAM(0x1fc)); + + if (++timeout > 5000) + return -EIO; + + } while (val == NETXEN_BDINFO_MAGIC); } - return ret; + return 0; } static void netxen_set_port_mode(struct netxen_adapter *adapter) @@ -793,8 +806,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); - netxen_load_firmware(adapter); } + netxen_load_firmware(adapter); if (NX_IS_REVISION_P3(revision_id)) netxen_pcie_strap_init(adapter); @@ -810,13 +823,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } - if ((first_boot == 0x55555555) && - (NX_IS_REVISION_P2(revision_id))) { - /* Unlock the HW, prompting the boot sequence */ - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } - err = netxen_initialize_adapter_offload(adapter); if (err) goto err_out_iounmap; @@ -830,7 +836,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i); /* Handshake with the card before we register the devices. */ - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + if (err) + goto err_out_free_offload; } /* first_driver */ @@ -934,6 +942,7 @@ err_out_disable_msi: if (adapter->flags & NETXEN_NIC_MSI_ENABLED) pci_disable_msi(pdev); +err_out_free_offload: if (first_driver) netxen_free_adapter_offload(adapter); -- cgit v1.2.3 From 06e9d9f9783860fe4c602ef491f47211804ccc96 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:49:22 -0800 Subject: netxen: cleanup mac list on driver unload This fixes a tiny memory leak when driver is unloaded. The mac address list maintained in netxen_adapter needs to deleted when driver is going down. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cbe2b3e814dd..9268fd2fbacf 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -986,6 +986,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_free_sw_resources(adapter); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_p3_free_mac_list(adapter); } if (adapter->portnum == 0) -- cgit v1.2.3 From 6f70340698333f14b1d9c9e913c5de8f66b72c55 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Wed, 14 Jan 2009 20:50:00 -0800 Subject: netxen: handle dma mapping failures o Bail out if pci_map_single() fails while replenishing rx ring. o Drop packet if pci_map_{single,page}() fail in tx. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 38 +++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9268fd2fbacf..86867405a367 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1200,6 +1200,24 @@ static bool netxen_tso_check(struct net_device *netdev, return tso; } +static void +netxen_clean_tx_dma_mapping(struct pci_dev *pdev, + struct netxen_cmd_buffer *pbuf, int last) +{ + int k; + struct netxen_skb_frag *buffrag; + + buffrag = &pbuf->frag_array[0]; + pci_unmap_single(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + + for (k = 1; k < last; k++) { + buffrag = &pbuf->frag_array[k]; + pci_unmap_page(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + } +} + static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); @@ -1208,6 +1226,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; struct cmd_desc_type0 *hwdesc; + struct pci_dev *pdev = adapter->pdev; + dma_addr_t temp_dma; int i, k; u32 producer, consumer; @@ -1240,8 +1260,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pbuf->skb = skb; pbuf->frag_count = frag_count; buffrag = &pbuf->frag_array[0]; - buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, + temp_dma = pci_map_single(pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) + goto drop_packet; + + buffrag->dma = temp_dma; buffrag->length = first_seg_len; netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_port(hwdesc, adapter->portnum); @@ -1253,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct skb_frag_struct *frag; int len, temp_len; unsigned long offset; - dma_addr_t temp_dma; /* move to next desc. if there is a need */ if ((i & 0x3) == 0) { @@ -1269,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) offset = frag->page_offset; temp_len = len; - temp_dma = pci_map_page(adapter->pdev, frag->page, offset, + temp_dma = pci_map_page(pdev, frag->page, offset, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) { + netxen_clean_tx_dma_mapping(pdev, pbuf, i); + goto drop_packet; + } buffrag++; buffrag->dma = temp_dma; @@ -1345,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; return NETDEV_TX_OK; + +drop_packet: + adapter->stats.txdropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } static int netxen_nic_check_temp(struct netxen_adapter *adapter) -- cgit v1.2.3 From 3bfafd6b136bea2de9bd96c01b7e3808635a15b2 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 16 Jan 2009 11:03:01 -0800 Subject: netxen: avoid invalid iounmap For NX3031 only one I/O range is mapped, so unmapping other two which are used by older chips, causes this warning on ppc64. "Attempt to iounmap early bolted mapping at 0x0000000000000000" Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 86867405a367..f8e26290a22f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1004,8 +1004,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); - iounmap(adapter->ahw.pci_base1); - iounmap(adapter->ahw.pci_base2); + if (adapter->ahw.pci_base1 != NULL) + iounmap(adapter->ahw.pci_base1); + if (adapter->ahw.pci_base2 != NULL) + iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); pci_disable_device(pdev); -- cgit v1.2.3 From 009777846165fcc49352c0f1487e3a96102884c3 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 16 Jan 2009 11:03:25 -0800 Subject: netxen: include ipv6.h (fixes build failure) Fixes a build error in absence of CONFIG_IPV6: drivers/net/netxen/netxen_nic_main.c:1189: error: implicit declaration of function 'ipv6_hdr' drivers/net/netxen/netxen_nic_main.c:1189: error: invalid type argument of '->' Reported-by: Ingo Molnar Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f8e26290a22f..d854f07ef4d3 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -41,6 +41,7 @@ #include #include #include +#include MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cdff1036492ac97b4213aeab2546914a633a7de7 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Mon, 26 Jan 2009 12:34:57 -0800 Subject: netxen: fix vlan tso/checksum offload o set netdev->vlan_features appropriately. o fix tso descriptor initialization for vlan case. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/net/netxen/netxen_nic_main.c') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index d854f07ef4d3..645d384fe87e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -735,17 +735,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - /* ScatterGather support */ - netdev->features = NETIF_F_SG; - netdev->features |= NETIF_F_IP_CSUM; - netdev->features |= NETIF_F_TSO; + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + if (NX_IS_REVISION_P3(revision_id)) { - netdev->features |= NETIF_F_IPV6_CSUM; - netdev->features |= NETIF_F_TSO6; + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); } - if (adapter->pci_using_dac) + if (adapter->pci_using_dac) { netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } /* * Set the CRB window to invalid. If any register in window 0 is @@ -1166,6 +1167,14 @@ static bool netxen_tso_check(struct net_device *netdev, { bool tso = false; u8 opcode = TX_ETHER_PKT; + __be16 protocol = skb->protocol; + u16 flags = 0; + + if (protocol == __constant_htons(ETH_P_8021Q)) { + struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; + protocol = vh->h_vlan_encapsulated_proto; + flags = FLAGS_VLAN_TAGGED; + } if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { @@ -1174,21 +1183,21 @@ static bool netxen_tso_check(struct net_device *netdev, desc->total_hdr_length = skb_transport_offset(skb) + tcp_hdrlen(skb); - opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + opcode = (protocol == __constant_htons(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (skb->protocol == htons(ETH_P_IP)) { + if (protocol == __constant_htons(ETH_P_IP)) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if(l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (skb->protocol == htons(ETH_P_IPV6)) { + } else if (protocol == __constant_htons(ETH_P_IPV6)) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) @@ -1199,7 +1208,7 @@ static bool netxen_tso_check(struct net_device *netdev, } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); - netxen_set_tx_flags_opcode(desc, 0, opcode); + netxen_set_tx_flags_opcode(desc, flags, opcode); return tso; } -- cgit v1.2.3