spl2sw_desc.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright Sunplus Technology Co., Ltd.
  3. * All rights reserved.
  4. */
  5. #include <linux/platform_device.h>
  6. #include <linux/netdevice.h>
  7. #include <linux/of_mdio.h>
  8. #include "spl2sw_define.h"
  9. #include "spl2sw_desc.h"
  10. void spl2sw_rx_descs_flush(struct spl2sw_common *comm)
  11. {
  12. struct spl2sw_skb_info *rx_skbinfo;
  13. struct spl2sw_mac_desc *rx_desc;
  14. u32 i, j;
  15. for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
  16. rx_desc = comm->rx_desc[i];
  17. rx_skbinfo = comm->rx_skb_info[i];
  18. for (j = 0; j < comm->rx_desc_num[i]; j++) {
  19. rx_desc[j].addr1 = rx_skbinfo[j].mapping;
  20. rx_desc[j].cmd2 = (j == comm->rx_desc_num[i] - 1) ?
  21. RXD_EOR | comm->rx_desc_buff_size :
  22. comm->rx_desc_buff_size;
  23. wmb(); /* Set RXD_OWN after other fields are ready. */
  24. rx_desc[j].cmd1 = RXD_OWN;
  25. }
  26. }
  27. }
  28. void spl2sw_tx_descs_clean(struct spl2sw_common *comm)
  29. {
  30. u32 i;
  31. if (!comm->tx_desc)
  32. return;
  33. for (i = 0; i < TX_DESC_NUM; i++) {
  34. comm->tx_desc[i].cmd1 = 0;
  35. wmb(); /* Clear TXD_OWN and then set other fields. */
  36. comm->tx_desc[i].cmd2 = 0;
  37. comm->tx_desc[i].addr1 = 0;
  38. comm->tx_desc[i].addr2 = 0;
  39. if (comm->tx_temp_skb_info[i].mapping) {
  40. dma_unmap_single(&comm->pdev->dev, comm->tx_temp_skb_info[i].mapping,
  41. comm->tx_temp_skb_info[i].skb->len, DMA_TO_DEVICE);
  42. comm->tx_temp_skb_info[i].mapping = 0;
  43. }
  44. if (comm->tx_temp_skb_info[i].skb) {
  45. dev_kfree_skb_any(comm->tx_temp_skb_info[i].skb);
  46. comm->tx_temp_skb_info[i].skb = NULL;
  47. }
  48. }
  49. }
  50. void spl2sw_rx_descs_clean(struct spl2sw_common *comm)
  51. {
  52. struct spl2sw_skb_info *rx_skbinfo;
  53. struct spl2sw_mac_desc *rx_desc;
  54. u32 i, j;
  55. for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
  56. if (!comm->rx_skb_info[i])
  57. continue;
  58. rx_desc = comm->rx_desc[i];
  59. rx_skbinfo = comm->rx_skb_info[i];
  60. for (j = 0; j < comm->rx_desc_num[i]; j++) {
  61. rx_desc[j].cmd1 = 0;
  62. wmb(); /* Clear RXD_OWN and then set other fields. */
  63. rx_desc[j].cmd2 = 0;
  64. rx_desc[j].addr1 = 0;
  65. if (rx_skbinfo[j].skb) {
  66. dma_unmap_single(&comm->pdev->dev, rx_skbinfo[j].mapping,
  67. comm->rx_desc_buff_size, DMA_FROM_DEVICE);
  68. dev_kfree_skb_any(rx_skbinfo[j].skb);
  69. rx_skbinfo[j].skb = NULL;
  70. rx_skbinfo[j].mapping = 0;
  71. }
  72. }
  73. kfree(rx_skbinfo);
  74. comm->rx_skb_info[i] = NULL;
  75. }
  76. }
  77. void spl2sw_descs_clean(struct spl2sw_common *comm)
  78. {
  79. spl2sw_rx_descs_clean(comm);
  80. spl2sw_tx_descs_clean(comm);
  81. }
  82. void spl2sw_descs_free(struct spl2sw_common *comm)
  83. {
  84. u32 i;
  85. spl2sw_descs_clean(comm);
  86. comm->tx_desc = NULL;
  87. for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
  88. comm->rx_desc[i] = NULL;
  89. /* Free descriptor area */
  90. if (comm->desc_base) {
  91. dma_free_coherent(&comm->pdev->dev, comm->desc_size, comm->desc_base,
  92. comm->desc_dma);
  93. comm->desc_base = NULL;
  94. comm->desc_dma = 0;
  95. comm->desc_size = 0;
  96. }
  97. }
  98. void spl2sw_tx_descs_init(struct spl2sw_common *comm)
  99. {
  100. memset(comm->tx_desc, '\0', sizeof(struct spl2sw_mac_desc) *
  101. (TX_DESC_NUM + MAC_GUARD_DESC_NUM));
  102. }
  103. int spl2sw_rx_descs_init(struct spl2sw_common *comm)
  104. {
  105. struct spl2sw_skb_info *rx_skbinfo;
  106. struct spl2sw_mac_desc *rx_desc;
  107. struct sk_buff *skb;
  108. u32 mapping;
  109. u32 i, j;
  110. for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
  111. comm->rx_skb_info[i] = kcalloc(comm->rx_desc_num[i], sizeof(*rx_skbinfo),
  112. GFP_KERNEL | GFP_DMA);
  113. if (!comm->rx_skb_info[i])
  114. goto mem_alloc_fail;
  115. rx_skbinfo = comm->rx_skb_info[i];
  116. rx_desc = comm->rx_desc[i];
  117. for (j = 0; j < comm->rx_desc_num[i]; j++) {
  118. skb = netdev_alloc_skb(NULL, comm->rx_desc_buff_size);
  119. if (!skb)
  120. goto mem_alloc_fail;
  121. rx_skbinfo[j].skb = skb;
  122. mapping = dma_map_single(&comm->pdev->dev, skb->data,
  123. comm->rx_desc_buff_size,
  124. DMA_FROM_DEVICE);
  125. if (dma_mapping_error(&comm->pdev->dev, mapping))
  126. goto mem_alloc_fail;
  127. rx_skbinfo[j].mapping = mapping;
  128. rx_desc[j].addr1 = mapping;
  129. rx_desc[j].addr2 = 0;
  130. rx_desc[j].cmd2 = (j == comm->rx_desc_num[i] - 1) ?
  131. RXD_EOR | comm->rx_desc_buff_size :
  132. comm->rx_desc_buff_size;
  133. wmb(); /* Set RXD_OWN after other fields are effective. */
  134. rx_desc[j].cmd1 = RXD_OWN;
  135. }
  136. }
  137. return 0;
  138. mem_alloc_fail:
  139. spl2sw_rx_descs_clean(comm);
  140. return -ENOMEM;
  141. }
  142. int spl2sw_descs_alloc(struct spl2sw_common *comm)
  143. {
  144. s32 desc_size;
  145. u32 i;
  146. /* Alloc descriptor area */
  147. desc_size = (TX_DESC_NUM + MAC_GUARD_DESC_NUM) * sizeof(struct spl2sw_mac_desc);
  148. for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
  149. desc_size += comm->rx_desc_num[i] * sizeof(struct spl2sw_mac_desc);
  150. comm->desc_base = dma_alloc_coherent(&comm->pdev->dev, desc_size, &comm->desc_dma,
  151. GFP_KERNEL);
  152. if (!comm->desc_base)
  153. return -ENOMEM;
  154. comm->desc_size = desc_size;
  155. /* Setup Tx descriptor */
  156. comm->tx_desc = comm->desc_base;
  157. /* Setup Rx descriptor */
  158. comm->rx_desc[0] = &comm->tx_desc[TX_DESC_NUM + MAC_GUARD_DESC_NUM];
  159. for (i = 1; i < RX_DESC_QUEUE_NUM; i++)
  160. comm->rx_desc[i] = comm->rx_desc[i - 1] + comm->rx_desc_num[i - 1];
  161. return 0;
  162. }
  163. int spl2sw_descs_init(struct spl2sw_common *comm)
  164. {
  165. u32 i, ret;
  166. /* Initialize rx descriptor's data */
  167. comm->rx_desc_num[0] = RX_QUEUE0_DESC_NUM;
  168. comm->rx_desc_num[1] = RX_QUEUE1_DESC_NUM;
  169. for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
  170. comm->rx_desc[i] = NULL;
  171. comm->rx_skb_info[i] = NULL;
  172. comm->rx_pos[i] = 0;
  173. }
  174. comm->rx_desc_buff_size = MAC_RX_LEN_MAX;
  175. /* Initialize tx descriptor's data */
  176. comm->tx_done_pos = 0;
  177. comm->tx_desc = NULL;
  178. comm->tx_pos = 0;
  179. comm->tx_desc_full = 0;
  180. for (i = 0; i < TX_DESC_NUM; i++)
  181. comm->tx_temp_skb_info[i].skb = NULL;
  182. /* Allocate tx & rx descriptors. */
  183. ret = spl2sw_descs_alloc(comm);
  184. if (ret)
  185. return ret;
  186. spl2sw_tx_descs_init(comm);
  187. return spl2sw_rx_descs_init(comm);
  188. }