spl2sw_desc.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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] = kzalloc_objs(*rx_skbinfo,
  112. comm->rx_desc_num[i],
  113. GFP_KERNEL | GFP_DMA);
  114. if (!comm->rx_skb_info[i])
  115. goto mem_alloc_fail;
  116. rx_skbinfo = comm->rx_skb_info[i];
  117. rx_desc = comm->rx_desc[i];
  118. for (j = 0; j < comm->rx_desc_num[i]; j++) {
  119. skb = netdev_alloc_skb(NULL, comm->rx_desc_buff_size);
  120. if (!skb)
  121. goto mem_alloc_fail;
  122. rx_skbinfo[j].skb = skb;
  123. mapping = dma_map_single(&comm->pdev->dev, skb->data,
  124. comm->rx_desc_buff_size,
  125. DMA_FROM_DEVICE);
  126. if (dma_mapping_error(&comm->pdev->dev, mapping))
  127. goto mem_alloc_fail;
  128. rx_skbinfo[j].mapping = mapping;
  129. rx_desc[j].addr1 = mapping;
  130. rx_desc[j].addr2 = 0;
  131. rx_desc[j].cmd2 = (j == comm->rx_desc_num[i] - 1) ?
  132. RXD_EOR | comm->rx_desc_buff_size :
  133. comm->rx_desc_buff_size;
  134. wmb(); /* Set RXD_OWN after other fields are effective. */
  135. rx_desc[j].cmd1 = RXD_OWN;
  136. }
  137. }
  138. return 0;
  139. mem_alloc_fail:
  140. spl2sw_rx_descs_clean(comm);
  141. return -ENOMEM;
  142. }
  143. int spl2sw_descs_alloc(struct spl2sw_common *comm)
  144. {
  145. s32 desc_size;
  146. u32 i;
  147. /* Alloc descriptor area */
  148. desc_size = (TX_DESC_NUM + MAC_GUARD_DESC_NUM) * sizeof(struct spl2sw_mac_desc);
  149. for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
  150. desc_size += comm->rx_desc_num[i] * sizeof(struct spl2sw_mac_desc);
  151. comm->desc_base = dma_alloc_coherent(&comm->pdev->dev, desc_size, &comm->desc_dma,
  152. GFP_KERNEL);
  153. if (!comm->desc_base)
  154. return -ENOMEM;
  155. comm->desc_size = desc_size;
  156. /* Setup Tx descriptor */
  157. comm->tx_desc = comm->desc_base;
  158. /* Setup Rx descriptor */
  159. comm->rx_desc[0] = &comm->tx_desc[TX_DESC_NUM + MAC_GUARD_DESC_NUM];
  160. for (i = 1; i < RX_DESC_QUEUE_NUM; i++)
  161. comm->rx_desc[i] = comm->rx_desc[i - 1] + comm->rx_desc_num[i - 1];
  162. return 0;
  163. }
  164. int spl2sw_descs_init(struct spl2sw_common *comm)
  165. {
  166. u32 i, ret;
  167. /* Initialize rx descriptor's data */
  168. comm->rx_desc_num[0] = RX_QUEUE0_DESC_NUM;
  169. comm->rx_desc_num[1] = RX_QUEUE1_DESC_NUM;
  170. for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
  171. comm->rx_desc[i] = NULL;
  172. comm->rx_skb_info[i] = NULL;
  173. comm->rx_pos[i] = 0;
  174. }
  175. comm->rx_desc_buff_size = MAC_RX_LEN_MAX;
  176. /* Initialize tx descriptor's data */
  177. comm->tx_done_pos = 0;
  178. comm->tx_desc = NULL;
  179. comm->tx_pos = 0;
  180. comm->tx_desc_full = 0;
  181. for (i = 0; i < TX_DESC_NUM; i++)
  182. comm->tx_temp_skb_info[i].skb = NULL;
  183. /* Allocate tx & rx descriptors. */
  184. ret = spl2sw_descs_alloc(comm);
  185. if (ret)
  186. return ret;
  187. spl2sw_tx_descs_init(comm);
  188. return spl2sw_rx_descs_init(comm);
  189. }