077-07-bgmac-simplify-rx-DMA-error-handling.patch 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. From: Felix Fietkau <nbd@nbd.name>
  2. Date: Sun, 12 Apr 2015 22:23:07 +0200
  3. Subject: [PATCH] bgmac: simplify/optimize rx DMA error handling
  4. Allocate a new buffer before processing the completed one. If allocation
  5. fails, reuse the old buffer.
  6. Signed-off-by: Felix Fietkau <nbd@nbd.name>
  7. ---
  8. --- a/drivers/net/ethernet/broadcom/bgmac.c
  9. +++ b/drivers/net/ethernet/broadcom/bgmac.c
  10. @@ -386,6 +386,19 @@ static void bgmac_dma_rx_setup_desc(stru
  11. dma_desc->ctl1 = cpu_to_le32(ctl1);
  12. }
  13. +static void bgmac_dma_rx_poison_buf(struct device *dma_dev,
  14. + struct bgmac_slot_info *slot)
  15. +{
  16. + struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;
  17. +
  18. + dma_sync_single_for_cpu(dma_dev, slot->dma_addr, BGMAC_RX_BUF_SIZE,
  19. + DMA_FROM_DEVICE);
  20. + rx->len = cpu_to_le16(0xdead);
  21. + rx->flags = cpu_to_le16(0xbeef);
  22. + dma_sync_single_for_device(dma_dev, slot->dma_addr, BGMAC_RX_BUF_SIZE,
  23. + DMA_FROM_DEVICE);
  24. +}
  25. +
  26. static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
  27. int weight)
  28. {
  29. @@ -406,53 +419,35 @@ static int bgmac_dma_rx_read(struct bgma
  30. struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;
  31. struct sk_buff *skb;
  32. void *buf = slot->buf;
  33. + dma_addr_t dma_addr = slot->dma_addr;
  34. u16 len, flags;
  35. - /* Unmap buffer to make it accessible to the CPU */
  36. - dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
  37. - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  38. -
  39. - /* Get info from the header */
  40. - len = le16_to_cpu(rx->len);
  41. - flags = le16_to_cpu(rx->flags);
  42. -
  43. do {
  44. - dma_addr_t old_dma_addr = slot->dma_addr;
  45. - int err;
  46. + /* Prepare new skb as replacement */
  47. + if (bgmac_dma_rx_skb_for_slot(bgmac, slot)) {
  48. + bgmac_dma_rx_poison_buf(dma_dev, slot);
  49. + break;
  50. + }
  51. +
  52. + /* Unmap buffer to make it accessible to the CPU */
  53. + dma_unmap_single(dma_dev, dma_addr,
  54. + BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  55. +
  56. + /* Get info from the header */
  57. + len = le16_to_cpu(rx->len);
  58. + flags = le16_to_cpu(rx->flags);
  59. /* Check for poison and drop or pass the packet */
  60. if (len == 0xdead && flags == 0xbeef) {
  61. bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
  62. ring->start);
  63. - dma_sync_single_for_device(dma_dev,
  64. - slot->dma_addr,
  65. - BGMAC_RX_BUF_SIZE,
  66. - DMA_FROM_DEVICE);
  67. + put_page(virt_to_head_page(buf));
  68. break;
  69. }
  70. /* Omit CRC. */
  71. len -= ETH_FCS_LEN;
  72. - /* Prepare new skb as replacement */
  73. - err = bgmac_dma_rx_skb_for_slot(bgmac, slot);
  74. - if (err) {
  75. - /* Poison the old skb */
  76. - rx->len = cpu_to_le16(0xdead);
  77. - rx->flags = cpu_to_le16(0xbeef);
  78. -
  79. - dma_sync_single_for_device(dma_dev,
  80. - slot->dma_addr,
  81. - BGMAC_RX_BUF_SIZE,
  82. - DMA_FROM_DEVICE);
  83. - break;
  84. - }
  85. - bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
  86. -
  87. - /* Unmap old skb, we'll pass it to the netfif */
  88. - dma_unmap_single(dma_dev, old_dma_addr,
  89. - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
  90. -
  91. skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
  92. skb_put(skb, BGMAC_RX_FRAME_OFFSET +
  93. BGMAC_RX_BUF_OFFSET + len);
  94. @@ -465,6 +460,8 @@ static int bgmac_dma_rx_read(struct bgma
  95. handled++;
  96. } while (0);
  97. + bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
  98. +
  99. if (++ring->start >= BGMAC_RX_RING_SLOTS)
  100. ring->start = 0;
  101. @@ -532,14 +529,14 @@ static void bgmac_dma_rx_ring_free(struc
  102. for (i = 0; i < ring->num_slots; i++) {
  103. slot = &ring->slots[i];
  104. - if (!slot->buf)
  105. + if (!slot->dma_addr)
  106. continue;
  107. - if (slot->dma_addr)
  108. - dma_unmap_single(dma_dev, slot->dma_addr,
  109. - BGMAC_RX_BUF_SIZE,
  110. - DMA_FROM_DEVICE);
  111. + dma_unmap_single(dma_dev, slot->dma_addr,
  112. + BGMAC_RX_BUF_SIZE,
  113. + DMA_FROM_DEVICE);
  114. put_page(virt_to_head_page(slot->buf));
  115. + slot->dma_addr = 0;
  116. }
  117. }