077-02-bgmac-implement-GRO-and-use-build_skb.patch 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. From: Felix Fietkau <nbd@openwrt.org>
  2. Date: Mon, 23 Mar 2015 02:41:25 +0100
  3. Subject: [PATCH] bgmac: implement GRO and use build_skb
  4. This improves performance for routing and local rx
  5. Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  6. ---
  7. --- a/drivers/net/ethernet/broadcom/bgmac.c
  8. +++ b/drivers/net/ethernet/broadcom/bgmac.c
  9. @@ -276,31 +276,31 @@ static int bgmac_dma_rx_skb_for_slot(str
  10. struct bgmac_slot_info *slot)
  11. {
  12. struct device *dma_dev = bgmac->core->dma_dev;
  13. - struct sk_buff *skb;
  14. dma_addr_t dma_addr;
  15. struct bgmac_rx_header *rx;
  16. + void *buf;
  17. /* Alloc skb */
  18. - skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
  19. - if (!skb)
  20. + buf = netdev_alloc_frag(BGMAC_RX_ALLOC_SIZE);
  21. + if (!buf)
  22. return -ENOMEM;
  23. /* Poison - if everything goes fine, hardware will overwrite it */
  24. - rx = (struct bgmac_rx_header *)skb->data;
  25. + rx = buf;
  26. rx->len = cpu_to_le16(0xdead);
  27. rx->flags = cpu_to_le16(0xbeef);
  28. /* Map skb for the DMA */
  29. - dma_addr = dma_map_single(dma_dev, skb->data,
  30. - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  31. + dma_addr = dma_map_single(dma_dev, buf, BGMAC_RX_BUF_SIZE,
  32. + DMA_FROM_DEVICE);
  33. if (dma_mapping_error(dma_dev, dma_addr)) {
  34. bgmac_err(bgmac, "DMA mapping error\n");
  35. - dev_kfree_skb(skb);
  36. + put_page(virt_to_head_page(buf));
  37. return -ENOMEM;
  38. }
  39. /* Update the slot */
  40. - slot->skb = skb;
  41. + slot->buf = buf;
  42. slot->dma_addr = dma_addr;
  43. return 0;
  44. @@ -343,8 +343,9 @@ static int bgmac_dma_rx_read(struct bgma
  45. while (ring->start != ring->end) {
  46. struct device *dma_dev = bgmac->core->dma_dev;
  47. struct bgmac_slot_info *slot = &ring->slots[ring->start];
  48. - struct sk_buff *skb = slot->skb;
  49. - struct bgmac_rx_header *rx;
  50. + struct bgmac_rx_header *rx = slot->buf;
  51. + struct sk_buff *skb;
  52. + void *buf = slot->buf;
  53. u16 len, flags;
  54. /* Unmap buffer to make it accessible to the CPU */
  55. @@ -352,7 +353,6 @@ static int bgmac_dma_rx_read(struct bgma
  56. BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  57. /* Get info from the header */
  58. - rx = (struct bgmac_rx_header *)skb->data;
  59. len = le16_to_cpu(rx->len);
  60. flags = le16_to_cpu(rx->flags);
  61. @@ -393,12 +393,13 @@ static int bgmac_dma_rx_read(struct bgma
  62. dma_unmap_single(dma_dev, old_dma_addr,
  63. BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  64. + skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
  65. skb_put(skb, BGMAC_RX_FRAME_OFFSET + len);
  66. skb_pull(skb, BGMAC_RX_FRAME_OFFSET);
  67. skb_checksum_none_assert(skb);
  68. skb->protocol = eth_type_trans(skb, bgmac->net_dev);
  69. - netif_receive_skb(skb);
  70. + napi_gro_receive(&bgmac->napi, skb);
  71. handled++;
  72. } while (0);
  73. @@ -434,12 +435,11 @@ static bool bgmac_dma_unaligned(struct b
  74. return false;
  75. }
  76. -static void bgmac_dma_ring_free(struct bgmac *bgmac,
  77. - struct bgmac_dma_ring *ring)
  78. +static void bgmac_dma_tx_ring_free(struct bgmac *bgmac,
  79. + struct bgmac_dma_ring *ring)
  80. {
  81. struct device *dma_dev = bgmac->core->dma_dev;
  82. struct bgmac_slot_info *slot;
  83. - int size;
  84. int i;
  85. for (i = 0; i < ring->num_slots; i++) {
  86. @@ -451,23 +451,55 @@ static void bgmac_dma_ring_free(struct b
  87. dev_kfree_skb(slot->skb);
  88. }
  89. }
  90. +}
  91. +
  92. +static void bgmac_dma_rx_ring_free(struct bgmac *bgmac,
  93. + struct bgmac_dma_ring *ring)
  94. +{
  95. + struct device *dma_dev = bgmac->core->dma_dev;
  96. + struct bgmac_slot_info *slot;
  97. + int i;
  98. +
  99. + for (i = 0; i < ring->num_slots; i++) {
  100. + slot = &ring->slots[i];
  101. + if (!slot->buf)
  102. + continue;
  103. - if (ring->cpu_base) {
  104. - /* Free ring of descriptors */
  105. - size = ring->num_slots * sizeof(struct bgmac_dma_desc);
  106. - dma_free_coherent(dma_dev, size, ring->cpu_base,
  107. - ring->dma_base);
  108. + if (slot->dma_addr)
  109. + dma_unmap_single(dma_dev, slot->dma_addr,
  110. + BGMAC_RX_BUF_SIZE,
  111. + DMA_FROM_DEVICE);
  112. + put_page(virt_to_head_page(slot->buf));
  113. }
  114. }
  115. +static void bgmac_dma_ring_desc_free(struct bgmac *bgmac,
  116. + struct bgmac_dma_ring *ring)
  117. +{
  118. + struct device *dma_dev = bgmac->core->dma_dev;
  119. + int size;
  120. +
  121. + if (!ring->cpu_base)
  122. + return;
  123. +
  124. + /* Free ring of descriptors */
  125. + size = ring->num_slots * sizeof(struct bgmac_dma_desc);
  126. + dma_free_coherent(dma_dev, size, ring->cpu_base,
  127. + ring->dma_base);
  128. +}
  129. +
  130. static void bgmac_dma_free(struct bgmac *bgmac)
  131. {
  132. int i;
  133. - for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
  134. - bgmac_dma_ring_free(bgmac, &bgmac->tx_ring[i]);
  135. - for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
  136. - bgmac_dma_ring_free(bgmac, &bgmac->rx_ring[i]);
  137. + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
  138. + bgmac_dma_tx_ring_free(bgmac, &bgmac->tx_ring[i]);
  139. + bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]);
  140. + }
  141. + for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
  142. + bgmac_dma_rx_ring_free(bgmac, &bgmac->rx_ring[i]);
  143. + bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i]);
  144. + }
  145. }
  146. static int bgmac_dma_alloc(struct bgmac *bgmac)
  147. --- a/drivers/net/ethernet/broadcom/bgmac.h
  148. +++ b/drivers/net/ethernet/broadcom/bgmac.h
  149. @@ -362,6 +362,8 @@
  150. #define BGMAC_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */
  151. #define BGMAC_RX_MAX_FRAME_SIZE 1536 /* Copied from b44/tg3 */
  152. #define BGMAC_RX_BUF_SIZE (BGMAC_RX_FRAME_OFFSET + BGMAC_RX_MAX_FRAME_SIZE)
  153. +#define BGMAC_RX_ALLOC_SIZE (SKB_DATA_ALIGN(BGMAC_RX_BUF_SIZE) + \
  154. + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
  155. #define BGMAC_BFL_ENETROBO 0x0010 /* has ephy roboswitch spi */
  156. #define BGMAC_BFL_ENETADM 0x0080 /* has ADMtek switch */
  157. @@ -383,7 +385,10 @@
  158. #define ETHER_MAX_LEN 1518
  159. struct bgmac_slot_info {
  160. - struct sk_buff *skb;
  161. + union {
  162. + struct sk_buff *skb;
  163. + void *buf;
  164. + };
  165. dma_addr_t dma_addr;
  166. };