diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-04-09 21:15:25 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-04-10 16:03:57 -0400 |
| commit | 6db7470445f0757d2e8f23f57d86611338717ebe (patch) | |
| tree | b83d89e89ed9b20beadb6667059c5a557f52a945 /drivers/net/ethernet/faraday | |
| parent | e92455397237c4e680302950fe1d7970b6c063a0 (diff) | |
ftgmac100: Add support for fragmented tx
Add NETIF_F_SG and create multiple TX ring entries for skb fragments.
On reclaim, the skb is only freed on the segment marked as "last".
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/faraday')
| -rw-r--r-- | drivers/net/ethernet/faraday/ftgmac100.c | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index d303c597e9b8..abe2442673a0 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c | |||
| @@ -47,7 +47,7 @@ | |||
| 47 | #define RX_BUF_SIZE MAX_PKT_SIZE /* must be smaller than 0x3fff */ | 47 | #define RX_BUF_SIZE MAX_PKT_SIZE /* must be smaller than 0x3fff */ |
| 48 | 48 | ||
| 49 | /* Min number of tx ring entries before stopping queue */ | 49 | /* Min number of tx ring entries before stopping queue */ |
| 50 | #define TX_THRESHOLD (1) | 50 | #define TX_THRESHOLD (MAX_SKB_FRAGS + 1) |
| 51 | 51 | ||
| 52 | struct ftgmac100_descs { | 52 | struct ftgmac100_descs { |
| 53 | struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES]; | 53 | struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES]; |
| @@ -489,20 +489,30 @@ static void ftgmac100_txdes_set_first_segment(struct ftgmac100_txdes *txdes) | |||
| 489 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS); | 489 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS); |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | static inline bool ftgmac100_txdes_get_first_segment(struct ftgmac100_txdes *txdes) | ||
| 493 | { | ||
| 494 | return (txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_FTS)) != 0; | ||
| 495 | } | ||
| 496 | |||
| 492 | static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes) | 497 | static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes) |
| 493 | { | 498 | { |
| 494 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS); | 499 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS); |
| 495 | } | 500 | } |
| 496 | 501 | ||
| 502 | static inline bool ftgmac100_txdes_get_last_segment(struct ftgmac100_txdes *txdes) | ||
| 503 | { | ||
| 504 | return (txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_LTS)) != 0; | ||
| 505 | } | ||
| 506 | |||
| 497 | static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes, | 507 | static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes, |
| 498 | unsigned int len) | 508 | unsigned int len) |
| 499 | { | 509 | { |
| 500 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len)); | 510 | txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len)); |
| 501 | } | 511 | } |
| 502 | 512 | ||
| 503 | static void ftgmac100_txdes_set_txint(struct ftgmac100_txdes *txdes) | 513 | static inline unsigned int ftgmac100_txdes_get_buffer_size(struct ftgmac100_txdes *txdes) |
| 504 | { | 514 | { |
| 505 | txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TXIC); | 515 | return FTGMAC100_TXDES0_TXBUF_SIZE(cpu_to_le32(txdes->txdes0)); |
| 506 | } | 516 | } |
| 507 | 517 | ||
| 508 | static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes) | 518 | static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes) |
| @@ -528,7 +538,7 @@ static void ftgmac100_txdes_set_dma_addr(struct ftgmac100_txdes *txdes, | |||
| 528 | 538 | ||
| 529 | static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes) | 539 | static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes) |
| 530 | { | 540 | { |
| 531 | return le32_to_cpu(txdes->txdes3); | 541 | return (dma_addr_t)le32_to_cpu(txdes->txdes3); |
| 532 | } | 542 | } |
| 533 | 543 | ||
| 534 | static int ftgmac100_next_tx_pointer(int pointer) | 544 | static int ftgmac100_next_tx_pointer(int pointer) |
| @@ -558,13 +568,19 @@ static void ftgmac100_free_tx_packet(struct ftgmac100 *priv, | |||
| 558 | struct sk_buff *skb, | 568 | struct sk_buff *skb, |
| 559 | struct ftgmac100_txdes *txdes) | 569 | struct ftgmac100_txdes *txdes) |
| 560 | { | 570 | { |
| 561 | dma_addr_t map; | 571 | dma_addr_t map = ftgmac100_txdes_get_dma_addr(txdes); |
| 562 | 572 | ||
| 563 | map = ftgmac100_txdes_get_dma_addr(txdes); | 573 | if (ftgmac100_txdes_get_first_segment(txdes)) { |
| 564 | 574 | dma_unmap_single(priv->dev, map, skb_headlen(skb), | |
| 565 | dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE); | 575 | DMA_TO_DEVICE); |
| 576 | } else { | ||
| 577 | dma_unmap_page(priv->dev, map, | ||
| 578 | ftgmac100_txdes_get_buffer_size(txdes), | ||
| 579 | DMA_TO_DEVICE); | ||
| 580 | } | ||
| 566 | 581 | ||
| 567 | dev_kfree_skb(skb); | 582 | if (ftgmac100_txdes_get_last_segment(txdes)) |
| 583 | dev_kfree_skb(skb); | ||
| 568 | priv->tx_skbs[pointer] = NULL; | 584 | priv->tx_skbs[pointer] = NULL; |
| 569 | 585 | ||
| 570 | /* Clear txdes0 except end of ring bit, clear txdes1 as we | 586 | /* Clear txdes0 except end of ring bit, clear txdes1 as we |
| @@ -626,8 +642,8 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb, | |||
| 626 | struct net_device *netdev) | 642 | struct net_device *netdev) |
| 627 | { | 643 | { |
| 628 | struct ftgmac100 *priv = netdev_priv(netdev); | 644 | struct ftgmac100 *priv = netdev_priv(netdev); |
| 629 | struct ftgmac100_txdes *txdes; | 645 | struct ftgmac100_txdes *txdes, *first; |
| 630 | unsigned int pointer; | 646 | unsigned int pointer, nfrags, len, i, j; |
| 631 | dma_addr_t map; | 647 | dma_addr_t map; |
| 632 | 648 | ||
| 633 | /* The HW doesn't pad small frames */ | 649 | /* The HW doesn't pad small frames */ |
| @@ -643,26 +659,33 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb, | |||
| 643 | goto drop; | 659 | goto drop; |
| 644 | } | 660 | } |
| 645 | 661 | ||
| 646 | map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | 662 | /* Do we have a limit on #fragments ? I yet have to get a reply |
| 647 | if (unlikely(dma_mapping_error(priv->dev, map))) { | 663 | * from Aspeed. If there's one I haven't hit it. |
| 648 | /* drop packet */ | 664 | */ |
| 665 | nfrags = skb_shinfo(skb)->nr_frags; | ||
| 666 | |||
| 667 | /* Get header len */ | ||
| 668 | len = skb_headlen(skb); | ||
| 669 | |||
| 670 | /* Map the packet head */ | ||
| 671 | map = dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE); | ||
| 672 | if (dma_mapping_error(priv->dev, map)) { | ||
| 649 | if (net_ratelimit()) | 673 | if (net_ratelimit()) |
| 650 | netdev_err(netdev, "map socket buffer failed\n"); | 674 | netdev_err(netdev, "map tx packet head failed\n"); |
| 651 | goto drop; | 675 | goto drop; |
| 652 | } | 676 | } |
| 653 | 677 | ||
| 654 | /* Grab the next free tx descriptor */ | 678 | /* Grab the next free tx descriptor */ |
| 655 | pointer = priv->tx_pointer; | 679 | pointer = priv->tx_pointer; |
| 656 | txdes = &priv->descs->txdes[pointer]; | 680 | txdes = first = &priv->descs->txdes[pointer]; |
| 657 | 681 | ||
| 658 | /* setup TX descriptor */ | 682 | /* Setup it up with the packet head. We don't set the OWN bit yet. */ |
| 659 | priv->tx_skbs[pointer] = skb; | 683 | priv->tx_skbs[pointer] = skb; |
| 660 | ftgmac100_txdes_set_dma_addr(txdes, map); | 684 | ftgmac100_txdes_set_dma_addr(txdes, map); |
| 661 | ftgmac100_txdes_set_buffer_size(txdes, skb->len); | 685 | ftgmac100_txdes_set_buffer_size(txdes, len); |
| 662 | |||
| 663 | ftgmac100_txdes_set_first_segment(txdes); | 686 | ftgmac100_txdes_set_first_segment(txdes); |
| 664 | ftgmac100_txdes_set_last_segment(txdes); | 687 | |
| 665 | ftgmac100_txdes_set_txint(txdes); | 688 | /* Setup HW checksumming */ |
| 666 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 689 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 667 | __be16 protocol = skb->protocol; | 690 | __be16 protocol = skb->protocol; |
| 668 | 691 | ||
| @@ -677,14 +700,41 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb, | |||
| 677 | } | 700 | } |
| 678 | } | 701 | } |
| 679 | 702 | ||
| 703 | /* Next descriptor */ | ||
| 704 | pointer = ftgmac100_next_tx_pointer(pointer); | ||
| 705 | |||
| 706 | /* Add the fragments */ | ||
| 707 | for (i = 0; i < nfrags; i++) { | ||
| 708 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
| 709 | |||
| 710 | len = frag->size; | ||
| 711 | |||
| 712 | /* Map it */ | ||
| 713 | map = skb_frag_dma_map(priv->dev, frag, 0, len, | ||
| 714 | DMA_TO_DEVICE); | ||
| 715 | if (dma_mapping_error(priv->dev, map)) | ||
| 716 | goto dma_err; | ||
| 717 | |||
| 718 | /* Setup descriptor */ | ||
| 719 | priv->tx_skbs[pointer] = skb; | ||
| 720 | txdes = &priv->descs->txdes[pointer]; | ||
| 721 | ftgmac100_txdes_set_dma_addr(txdes, map); | ||
| 722 | ftgmac100_txdes_set_buffer_size(txdes, len); | ||
| 723 | ftgmac100_txdes_set_dma_own(txdes); | ||
| 724 | pointer = ftgmac100_next_tx_pointer(pointer); | ||
| 725 | } | ||
| 726 | |||
| 727 | /* Tag last fragment */ | ||
| 728 | ftgmac100_txdes_set_last_segment(txdes); | ||
| 729 | |||
| 680 | /* Order the previous packet and descriptor udpates | 730 | /* Order the previous packet and descriptor udpates |
| 681 | * before setting the OWN bit. | 731 | * before setting the OWN bit. |
| 682 | */ | 732 | */ |
| 683 | dma_wmb(); | 733 | dma_wmb(); |
| 684 | ftgmac100_txdes_set_dma_own(txdes); | 734 | ftgmac100_txdes_set_dma_own(first); |
| 685 | 735 | ||
| 686 | /* Update next TX pointer */ | 736 | /* Update next TX pointer */ |
| 687 | priv->tx_pointer = ftgmac100_next_tx_pointer(pointer); | 737 | priv->tx_pointer = pointer; |
| 688 | 738 | ||
| 689 | /* If there isn't enough room for all the fragments of a new packet | 739 | /* If there isn't enough room for all the fragments of a new packet |
| 690 | * in the TX ring, stop the queue. The sequence below is race free | 740 | * in the TX ring, stop the queue. The sequence below is race free |
| @@ -702,6 +752,25 @@ static int ftgmac100_hard_start_xmit(struct sk_buff *skb, | |||
| 702 | 752 | ||
| 703 | return NETDEV_TX_OK; | 753 | return NETDEV_TX_OK; |
| 704 | 754 | ||
| 755 | dma_err: | ||
| 756 | if (net_ratelimit()) | ||
| 757 | netdev_err(netdev, "map tx fragment failed\n"); | ||
| 758 | |||
| 759 | /* Free head */ | ||
| 760 | pointer = priv->tx_pointer; | ||
| 761 | ftgmac100_free_tx_packet(priv, pointer, skb, first); | ||
| 762 | |||
| 763 | /* Then all fragments */ | ||
| 764 | for (j = 0; j < i; j++) { | ||
| 765 | pointer = ftgmac100_next_tx_pointer(pointer); | ||
| 766 | txdes = &priv->descs->txdes[pointer]; | ||
| 767 | ftgmac100_free_tx_packet(priv, pointer, skb, txdes); | ||
| 768 | } | ||
| 769 | |||
| 770 | /* This cannot be reached if we successfully mapped the | ||
| 771 | * last fragment, so we know ftgmac100_free_tx_packet() | ||
| 772 | * hasn't freed the skb yet. | ||
| 773 | */ | ||
| 705 | drop: | 774 | drop: |
| 706 | /* Drop the packet */ | 775 | /* Drop the packet */ |
| 707 | dev_kfree_skb_any(skb); | 776 | dev_kfree_skb_any(skb); |
| @@ -1441,12 +1510,12 @@ static int ftgmac100_probe(struct platform_device *pdev) | |||
| 1441 | * when NCSI is enabled on the interface. It doesn't work | 1510 | * when NCSI is enabled on the interface. It doesn't work |
| 1442 | * in that case. | 1511 | * in that case. |
| 1443 | */ | 1512 | */ |
| 1444 | netdev->features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_GRO; | 1513 | netdev->features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | |
| 1514 | NETIF_F_GRO | NETIF_F_SG; | ||
| 1445 | if (priv->use_ncsi && | 1515 | if (priv->use_ncsi && |
| 1446 | of_get_property(pdev->dev.of_node, "no-hw-checksum", NULL)) | 1516 | of_get_property(pdev->dev.of_node, "no-hw-checksum", NULL)) |
| 1447 | netdev->features &= ~NETIF_F_IP_CSUM; | 1517 | netdev->features &= ~NETIF_F_IP_CSUM; |
| 1448 | 1518 | ||
| 1449 | |||
| 1450 | /* register network device */ | 1519 | /* register network device */ |
| 1451 | err = register_netdev(netdev); | 1520 | err = register_netdev(netdev); |
| 1452 | if (err) { | 1521 | if (err) { |
