diff options
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 100 |
1 files changed, 85 insertions, 15 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e8afa101433e..64c8151f2004 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -75,7 +75,7 @@ | |||
75 | #include "myri10ge_mcp.h" | 75 | #include "myri10ge_mcp.h" |
76 | #include "myri10ge_mcp_gen_header.h" | 76 | #include "myri10ge_mcp_gen_header.h" |
77 | 77 | ||
78 | #define MYRI10GE_VERSION_STR "1.3.2-1.269" | 78 | #define MYRI10GE_VERSION_STR "1.3.2-1.287" |
79 | 79 | ||
80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
81 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
@@ -214,6 +214,8 @@ struct myri10ge_priv { | |||
214 | unsigned long serial_number; | 214 | unsigned long serial_number; |
215 | int vendor_specific_offset; | 215 | int vendor_specific_offset; |
216 | int fw_multicast_support; | 216 | int fw_multicast_support; |
217 | unsigned long features; | ||
218 | u32 max_tso6; | ||
217 | u32 read_dma; | 219 | u32 read_dma; |
218 | u32 write_dma; | 220 | u32 write_dma; |
219 | u32 read_write_dma; | 221 | u32 read_write_dma; |
@@ -311,6 +313,7 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); | |||
311 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) | 313 | #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) |
312 | 314 | ||
313 | static void myri10ge_set_multicast_list(struct net_device *dev); | 315 | static void myri10ge_set_multicast_list(struct net_device *dev); |
316 | static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev); | ||
314 | 317 | ||
315 | static inline void put_be32(__be32 val, __be32 __iomem * p) | 318 | static inline void put_be32(__be32 val, __be32 __iomem * p) |
316 | { | 319 | { |
@@ -612,6 +615,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) | |||
612 | __be32 buf[16]; | 615 | __be32 buf[16]; |
613 | u32 dma_low, dma_high, size; | 616 | u32 dma_low, dma_high, size; |
614 | int status, i; | 617 | int status, i; |
618 | struct myri10ge_cmd cmd; | ||
615 | 619 | ||
616 | size = 0; | 620 | size = 0; |
617 | status = myri10ge_load_hotplug_firmware(mgp, &size); | 621 | status = myri10ge_load_hotplug_firmware(mgp, &size); |
@@ -688,6 +692,14 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) | |||
688 | dev_info(&mgp->pdev->dev, "handoff confirmed\n"); | 692 | dev_info(&mgp->pdev->dev, "handoff confirmed\n"); |
689 | myri10ge_dummy_rdma(mgp, 1); | 693 | myri10ge_dummy_rdma(mgp, 1); |
690 | 694 | ||
695 | /* probe for IPv6 TSO support */ | ||
696 | mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; | ||
697 | status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, | ||
698 | &cmd, 0); | ||
699 | if (status == 0) { | ||
700 | mgp->max_tso6 = cmd.data0; | ||
701 | mgp->features |= NETIF_F_TSO6; | ||
702 | } | ||
691 | return 0; | 703 | return 0; |
692 | } | 704 | } |
693 | 705 | ||
@@ -1047,7 +1059,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
1047 | 1059 | ||
1048 | hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; | 1060 | hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; |
1049 | 1061 | ||
1050 | /* allocate an skb to attach the page(s) to. */ | 1062 | /* allocate an skb to attach the page(s) to. This is done |
1063 | * after trying LRO, so as to avoid skb allocation overheads */ | ||
1051 | 1064 | ||
1052 | skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); | 1065 | skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); |
1053 | if (unlikely(skb == NULL)) { | 1066 | if (unlikely(skb == NULL)) { |
@@ -1217,7 +1230,8 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) | |||
1217 | 1230 | ||
1218 | static int myri10ge_poll(struct napi_struct *napi, int budget) | 1231 | static int myri10ge_poll(struct napi_struct *napi, int budget) |
1219 | { | 1232 | { |
1220 | struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi); | 1233 | struct myri10ge_priv *mgp = |
1234 | container_of(napi, struct myri10ge_priv, napi); | ||
1221 | struct net_device *netdev = mgp->dev; | 1235 | struct net_device *netdev = mgp->dev; |
1222 | struct myri10ge_rx_done *rx_done = &mgp->rx_done; | 1236 | struct myri10ge_rx_done *rx_done = &mgp->rx_done; |
1223 | int work_done; | 1237 | int work_done; |
@@ -1382,6 +1396,18 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) | |||
1382 | return 0; | 1396 | return 0; |
1383 | } | 1397 | } |
1384 | 1398 | ||
1399 | static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) | ||
1400 | { | ||
1401 | struct myri10ge_priv *mgp = netdev_priv(netdev); | ||
1402 | unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO); | ||
1403 | |||
1404 | if (tso_enabled) | ||
1405 | netdev->features |= flags; | ||
1406 | else | ||
1407 | netdev->features &= ~flags; | ||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1385 | static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { | 1411 | static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { |
1386 | "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", | 1412 | "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", |
1387 | "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", | 1413 | "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", |
@@ -1506,7 +1532,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { | |||
1506 | .set_rx_csum = myri10ge_set_rx_csum, | 1532 | .set_rx_csum = myri10ge_set_rx_csum, |
1507 | .set_tx_csum = ethtool_op_set_tx_hw_csum, | 1533 | .set_tx_csum = ethtool_op_set_tx_hw_csum, |
1508 | .set_sg = ethtool_op_set_sg, | 1534 | .set_sg = ethtool_op_set_sg, |
1509 | .set_tso = ethtool_op_set_tso, | 1535 | .set_tso = myri10ge_set_tso, |
1510 | .get_link = ethtool_op_get_link, | 1536 | .get_link = ethtool_op_get_link, |
1511 | .get_strings = myri10ge_get_strings, | 1537 | .get_strings = myri10ge_get_strings, |
1512 | .get_sset_count = myri10ge_get_sset_count, | 1538 | .get_sset_count = myri10ge_get_sset_count, |
@@ -2164,7 +2190,8 @@ again: | |||
2164 | pseudo_hdr_offset = cksum_offset + skb->csum_offset; | 2190 | pseudo_hdr_offset = cksum_offset + skb->csum_offset; |
2165 | /* If the headers are excessively large, then we must | 2191 | /* If the headers are excessively large, then we must |
2166 | * fall back to a software checksum */ | 2192 | * fall back to a software checksum */ |
2167 | if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { | 2193 | if (unlikely(!mss && (cksum_offset > 255 || |
2194 | pseudo_hdr_offset > 127))) { | ||
2168 | if (skb_checksum_help(skb)) | 2195 | if (skb_checksum_help(skb)) |
2169 | goto drop; | 2196 | goto drop; |
2170 | cksum_offset = 0; | 2197 | cksum_offset = 0; |
@@ -2184,9 +2211,18 @@ again: | |||
2184 | /* negative cum_len signifies to the | 2211 | /* negative cum_len signifies to the |
2185 | * send loop that we are still in the | 2212 | * send loop that we are still in the |
2186 | * header portion of the TSO packet. | 2213 | * header portion of the TSO packet. |
2187 | * TSO header must be at most 134 bytes long */ | 2214 | * TSO header can be at most 1KB long */ |
2188 | cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); | 2215 | cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); |
2189 | 2216 | ||
2217 | /* for IPv6 TSO, the checksum offset stores the | ||
2218 | * TCP header length, to save the firmware from | ||
2219 | * the need to parse the headers */ | ||
2220 | if (skb_is_gso_v6(skb)) { | ||
2221 | cksum_offset = tcp_hdrlen(skb); | ||
2222 | /* Can only handle headers <= max_tso6 long */ | ||
2223 | if (unlikely(-cum_len > mgp->max_tso6)) | ||
2224 | return myri10ge_sw_tso(skb, dev); | ||
2225 | } | ||
2190 | /* for TSO, pseudo_hdr_offset holds mss. | 2226 | /* for TSO, pseudo_hdr_offset holds mss. |
2191 | * The firmware figures out where to put | 2227 | * The firmware figures out where to put |
2192 | * the checksum by parsing the header. */ | 2228 | * the checksum by parsing the header. */ |
@@ -2301,10 +2337,12 @@ again: | |||
2301 | req++; | 2337 | req++; |
2302 | count++; | 2338 | count++; |
2303 | rdma_count++; | 2339 | rdma_count++; |
2304 | if (unlikely(cksum_offset > seglen)) | 2340 | if (cksum_offset != 0 && !(mss && skb_is_gso_v6(skb))) { |
2305 | cksum_offset -= seglen; | 2341 | if (unlikely(cksum_offset > seglen)) |
2306 | else | 2342 | cksum_offset -= seglen; |
2307 | cksum_offset = 0; | 2343 | else |
2344 | cksum_offset = 0; | ||
2345 | } | ||
2308 | } | 2346 | } |
2309 | if (frag_idx == frag_cnt) | 2347 | if (frag_idx == frag_cnt) |
2310 | break; | 2348 | break; |
@@ -2387,6 +2425,41 @@ drop: | |||
2387 | 2425 | ||
2388 | } | 2426 | } |
2389 | 2427 | ||
2428 | static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev) | ||
2429 | { | ||
2430 | struct sk_buff *segs, *curr; | ||
2431 | struct myri10ge_priv *mgp = dev->priv; | ||
2432 | int status; | ||
2433 | |||
2434 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6); | ||
2435 | if (unlikely(IS_ERR(segs))) | ||
2436 | goto drop; | ||
2437 | |||
2438 | while (segs) { | ||
2439 | curr = segs; | ||
2440 | segs = segs->next; | ||
2441 | curr->next = NULL; | ||
2442 | status = myri10ge_xmit(curr, dev); | ||
2443 | if (status != 0) { | ||
2444 | dev_kfree_skb_any(curr); | ||
2445 | if (segs != NULL) { | ||
2446 | curr = segs; | ||
2447 | segs = segs->next; | ||
2448 | curr->next = NULL; | ||
2449 | dev_kfree_skb_any(segs); | ||
2450 | } | ||
2451 | goto drop; | ||
2452 | } | ||
2453 | } | ||
2454 | dev_kfree_skb_any(skb); | ||
2455 | return 0; | ||
2456 | |||
2457 | drop: | ||
2458 | dev_kfree_skb_any(skb); | ||
2459 | mgp->stats.tx_dropped += 1; | ||
2460 | return 0; | ||
2461 | } | ||
2462 | |||
2390 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) | 2463 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) |
2391 | { | 2464 | { |
2392 | struct myri10ge_priv *mgp = netdev_priv(dev); | 2465 | struct myri10ge_priv *mgp = netdev_priv(dev); |
@@ -2706,7 +2779,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
2706 | } | 2779 | } |
2707 | 2780 | ||
2708 | #ifdef CONFIG_PM | 2781 | #ifdef CONFIG_PM |
2709 | |||
2710 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) | 2782 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) |
2711 | { | 2783 | { |
2712 | struct myri10ge_priv *mgp; | 2784 | struct myri10ge_priv *mgp; |
@@ -2787,7 +2859,6 @@ abort_with_enabled: | |||
2787 | return -EIO; | 2859 | return -EIO; |
2788 | 2860 | ||
2789 | } | 2861 | } |
2790 | |||
2791 | #endif /* CONFIG_PM */ | 2862 | #endif /* CONFIG_PM */ |
2792 | 2863 | ||
2793 | static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) | 2864 | static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) |
@@ -2954,8 +3025,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2954 | 3025 | ||
2955 | mgp = netdev_priv(netdev); | 3026 | mgp = netdev_priv(netdev); |
2956 | mgp->dev = netdev; | 3027 | mgp->dev = netdev; |
2957 | netif_napi_add(netdev, &mgp->napi, | 3028 | netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight); |
2958 | myri10ge_poll, myri10ge_napi_weight); | ||
2959 | mgp->pdev = pdev; | 3029 | mgp->pdev = pdev; |
2960 | mgp->csum_flag = MXGEFW_FLAGS_CKSUM; | 3030 | mgp->csum_flag = MXGEFW_FLAGS_CKSUM; |
2961 | mgp->pause = myri10ge_flow_control; | 3031 | mgp->pause = myri10ge_flow_control; |
@@ -3077,7 +3147,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3077 | netdev->change_mtu = myri10ge_change_mtu; | 3147 | netdev->change_mtu = myri10ge_change_mtu; |
3078 | netdev->set_multicast_list = myri10ge_set_multicast_list; | 3148 | netdev->set_multicast_list = myri10ge_set_multicast_list; |
3079 | netdev->set_mac_address = myri10ge_set_mac_address; | 3149 | netdev->set_mac_address = myri10ge_set_mac_address; |
3080 | netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; | 3150 | netdev->features = mgp->features; |
3081 | if (dac_enabled) | 3151 | if (dac_enabled) |
3082 | netdev->features |= NETIF_F_HIGHDMA; | 3152 | netdev->features |= NETIF_F_HIGHDMA; |
3083 | 3153 | ||