diff options
| -rw-r--r-- | drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 69c26f04d8ce..679db026f4be 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c | |||
| @@ -873,6 +873,10 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) | |||
| 873 | return -ENOMEM; | 873 | return -ENOMEM; |
| 874 | dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, | 874 | dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, |
| 875 | DMA_BIDIRECTIONAL); | 875 | DMA_BIDIRECTIONAL); |
| 876 | if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) { | ||
| 877 | __free_page(dmatest_page); | ||
| 878 | return -ENOMEM; | ||
| 879 | } | ||
| 876 | 880 | ||
| 877 | /* Run a small DMA test. | 881 | /* Run a small DMA test. |
| 878 | * The magic multipliers to the length tell the firmware | 882 | * The magic multipliers to the length tell the firmware |
| @@ -1294,6 +1298,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
| 1294 | int bytes, int watchdog) | 1298 | int bytes, int watchdog) |
| 1295 | { | 1299 | { |
| 1296 | struct page *page; | 1300 | struct page *page; |
| 1301 | dma_addr_t bus; | ||
| 1297 | int idx; | 1302 | int idx; |
| 1298 | #if MYRI10GE_ALLOC_SIZE > 4096 | 1303 | #if MYRI10GE_ALLOC_SIZE > 4096 |
| 1299 | int end_offset; | 1304 | int end_offset; |
| @@ -1318,11 +1323,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
| 1318 | rx->watchdog_needed = 1; | 1323 | rx->watchdog_needed = 1; |
| 1319 | return; | 1324 | return; |
| 1320 | } | 1325 | } |
| 1326 | |||
| 1327 | bus = pci_map_page(mgp->pdev, page, 0, | ||
| 1328 | MYRI10GE_ALLOC_SIZE, | ||
| 1329 | PCI_DMA_FROMDEVICE); | ||
| 1330 | if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { | ||
| 1331 | __free_pages(page, MYRI10GE_ALLOC_ORDER); | ||
| 1332 | if (rx->fill_cnt - rx->cnt < 16) | ||
| 1333 | rx->watchdog_needed = 1; | ||
| 1334 | return; | ||
| 1335 | } | ||
| 1336 | |||
| 1321 | rx->page = page; | 1337 | rx->page = page; |
| 1322 | rx->page_offset = 0; | 1338 | rx->page_offset = 0; |
| 1323 | rx->bus = pci_map_page(mgp->pdev, page, 0, | 1339 | rx->bus = bus; |
| 1324 | MYRI10GE_ALLOC_SIZE, | 1340 | |
| 1325 | PCI_DMA_FROMDEVICE); | ||
| 1326 | } | 1341 | } |
| 1327 | rx->info[idx].page = rx->page; | 1342 | rx->info[idx].page = rx->page; |
| 1328 | rx->info[idx].page_offset = rx->page_offset; | 1343 | rx->info[idx].page_offset = rx->page_offset; |
| @@ -2764,6 +2779,35 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, | |||
| 2764 | mb(); | 2779 | mb(); |
| 2765 | } | 2780 | } |
| 2766 | 2781 | ||
| 2782 | static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp, | ||
| 2783 | struct myri10ge_tx_buf *tx, int idx) | ||
| 2784 | { | ||
| 2785 | unsigned int len; | ||
| 2786 | int last_idx; | ||
| 2787 | |||
| 2788 | /* Free any DMA resources we've alloced and clear out the skb slot */ | ||
| 2789 | last_idx = (idx + 1) & tx->mask; | ||
| 2790 | idx = tx->req & tx->mask; | ||
| 2791 | do { | ||
| 2792 | len = dma_unmap_len(&tx->info[idx], len); | ||
| 2793 | if (len) { | ||
| 2794 | if (tx->info[idx].skb != NULL) | ||
| 2795 | pci_unmap_single(mgp->pdev, | ||
| 2796 | dma_unmap_addr(&tx->info[idx], | ||
| 2797 | bus), len, | ||
| 2798 | PCI_DMA_TODEVICE); | ||
| 2799 | else | ||
| 2800 | pci_unmap_page(mgp->pdev, | ||
| 2801 | dma_unmap_addr(&tx->info[idx], | ||
| 2802 | bus), len, | ||
| 2803 | PCI_DMA_TODEVICE); | ||
| 2804 | dma_unmap_len_set(&tx->info[idx], len, 0); | ||
| 2805 | tx->info[idx].skb = NULL; | ||
| 2806 | } | ||
| 2807 | idx = (idx + 1) & tx->mask; | ||
| 2808 | } while (idx != last_idx); | ||
| 2809 | } | ||
| 2810 | |||
| 2767 | /* | 2811 | /* |
| 2768 | * Transmit a packet. We need to split the packet so that a single | 2812 | * Transmit a packet. We need to split the packet so that a single |
| 2769 | * segment does not cross myri10ge->tx_boundary, so this makes segment | 2813 | * segment does not cross myri10ge->tx_boundary, so this makes segment |
| @@ -2787,7 +2831,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb, | |||
| 2787 | u32 low; | 2831 | u32 low; |
| 2788 | __be32 high_swapped; | 2832 | __be32 high_swapped; |
| 2789 | unsigned int len; | 2833 | unsigned int len; |
| 2790 | int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; | 2834 | int idx, avail, frag_cnt, frag_idx, count, mss, max_segments; |
| 2791 | u16 pseudo_hdr_offset, cksum_offset, queue; | 2835 | u16 pseudo_hdr_offset, cksum_offset, queue; |
| 2792 | int cum_len, seglen, boundary, rdma_count; | 2836 | int cum_len, seglen, boundary, rdma_count; |
| 2793 | u8 flags, odd_flag; | 2837 | u8 flags, odd_flag; |
| @@ -2884,9 +2928,12 @@ again: | |||
| 2884 | 2928 | ||
| 2885 | /* map the skb for DMA */ | 2929 | /* map the skb for DMA */ |
| 2886 | len = skb_headlen(skb); | 2930 | len = skb_headlen(skb); |
| 2931 | bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); | ||
| 2932 | if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) | ||
| 2933 | goto drop; | ||
| 2934 | |||
| 2887 | idx = tx->req & tx->mask; | 2935 | idx = tx->req & tx->mask; |
| 2888 | tx->info[idx].skb = skb; | 2936 | tx->info[idx].skb = skb; |
| 2889 | bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); | ||
| 2890 | dma_unmap_addr_set(&tx->info[idx], bus, bus); | 2937 | dma_unmap_addr_set(&tx->info[idx], bus, bus); |
| 2891 | dma_unmap_len_set(&tx->info[idx], len, len); | 2938 | dma_unmap_len_set(&tx->info[idx], len, len); |
| 2892 | 2939 | ||
| @@ -2985,12 +3032,16 @@ again: | |||
| 2985 | break; | 3032 | break; |
| 2986 | 3033 | ||
| 2987 | /* map next fragment for DMA */ | 3034 | /* map next fragment for DMA */ |
| 2988 | idx = (count + tx->req) & tx->mask; | ||
| 2989 | frag = &skb_shinfo(skb)->frags[frag_idx]; | 3035 | frag = &skb_shinfo(skb)->frags[frag_idx]; |
| 2990 | frag_idx++; | 3036 | frag_idx++; |
| 2991 | len = skb_frag_size(frag); | 3037 | len = skb_frag_size(frag); |
| 2992 | bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len, | 3038 | bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len, |
| 2993 | DMA_TO_DEVICE); | 3039 | DMA_TO_DEVICE); |
| 3040 | if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { | ||
| 3041 | myri10ge_unmap_tx_dma(mgp, tx, idx); | ||
| 3042 | goto drop; | ||
| 3043 | } | ||
| 3044 | idx = (count + tx->req) & tx->mask; | ||
| 2994 | dma_unmap_addr_set(&tx->info[idx], bus, bus); | 3045 | dma_unmap_addr_set(&tx->info[idx], bus, bus); |
| 2995 | dma_unmap_len_set(&tx->info[idx], len, len); | 3046 | dma_unmap_len_set(&tx->info[idx], len, len); |
| 2996 | } | 3047 | } |
| @@ -3021,31 +3072,8 @@ again: | |||
| 3021 | return NETDEV_TX_OK; | 3072 | return NETDEV_TX_OK; |
| 3022 | 3073 | ||
| 3023 | abort_linearize: | 3074 | abort_linearize: |
| 3024 | /* Free any DMA resources we've alloced and clear out the skb | 3075 | myri10ge_unmap_tx_dma(mgp, tx, idx); |
| 3025 | * slot so as to not trip up assertions, and to avoid a | ||
| 3026 | * double-free if linearizing fails */ | ||
| 3027 | 3076 | ||
| 3028 | last_idx = (idx + 1) & tx->mask; | ||
| 3029 | idx = tx->req & tx->mask; | ||
| 3030 | tx->info[idx].skb = NULL; | ||
| 3031 | do { | ||
| 3032 | len = dma_unmap_len(&tx->info[idx], len); | ||
| 3033 | if (len) { | ||
| 3034 | if (tx->info[idx].skb != NULL) | ||
| 3035 | pci_unmap_single(mgp->pdev, | ||
| 3036 | dma_unmap_addr(&tx->info[idx], | ||
| 3037 | bus), len, | ||
| 3038 | PCI_DMA_TODEVICE); | ||
| 3039 | else | ||
| 3040 | pci_unmap_page(mgp->pdev, | ||
| 3041 | dma_unmap_addr(&tx->info[idx], | ||
| 3042 | bus), len, | ||
| 3043 | PCI_DMA_TODEVICE); | ||
| 3044 | dma_unmap_len_set(&tx->info[idx], len, 0); | ||
| 3045 | tx->info[idx].skb = NULL; | ||
| 3046 | } | ||
| 3047 | idx = (idx + 1) & tx->mask; | ||
| 3048 | } while (idx != last_idx); | ||
| 3049 | if (skb_is_gso(skb)) { | 3077 | if (skb_is_gso(skb)) { |
| 3050 | netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); | 3078 | netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); |
| 3051 | goto drop; | 3079 | goto drop; |
