spl2sw_int.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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/etherdevice.h>
  7. #include <linux/netdevice.h>
  8. #include <linux/bitfield.h>
  9. #include <linux/spinlock.h>
  10. #include <linux/of_mdio.h>
  11. #include "spl2sw_register.h"
  12. #include "spl2sw_define.h"
  13. #include "spl2sw_int.h"
  14. int spl2sw_rx_poll(struct napi_struct *napi, int budget)
  15. {
  16. struct spl2sw_common *comm = container_of(napi, struct spl2sw_common, rx_napi);
  17. struct spl2sw_mac_desc *desc, *h_desc;
  18. struct net_device_stats *stats;
  19. struct sk_buff *skb, *new_skb;
  20. struct spl2sw_skb_info *sinfo;
  21. int budget_left = budget;
  22. unsigned long flags;
  23. u32 rx_pos, pkg_len;
  24. u32 num, rx_count;
  25. s32 queue;
  26. u32 mask;
  27. int port;
  28. u32 cmd;
  29. u32 len;
  30. /* Process high-priority queue and then low-priority queue. */
  31. for (queue = 0; queue < RX_DESC_QUEUE_NUM; queue++) {
  32. rx_pos = comm->rx_pos[queue];
  33. rx_count = comm->rx_desc_num[queue];
  34. for (num = 0; num < rx_count && budget_left; num++) {
  35. sinfo = comm->rx_skb_info[queue] + rx_pos;
  36. desc = comm->rx_desc[queue] + rx_pos;
  37. cmd = desc->cmd1;
  38. if (cmd & RXD_OWN)
  39. break;
  40. port = FIELD_GET(RXD_PKT_SP, cmd);
  41. if (port < MAX_NETDEV_NUM && comm->ndev[port])
  42. stats = &comm->ndev[port]->stats;
  43. else
  44. goto spl2sw_rx_poll_rec_err;
  45. pkg_len = FIELD_GET(RXD_PKT_LEN, cmd);
  46. if (unlikely((cmd & RXD_ERR_CODE) || pkg_len < ETH_ZLEN + 4)) {
  47. stats->rx_length_errors++;
  48. stats->rx_dropped++;
  49. goto spl2sw_rx_poll_rec_err;
  50. }
  51. dma_unmap_single(&comm->pdev->dev, sinfo->mapping,
  52. comm->rx_desc_buff_size, DMA_FROM_DEVICE);
  53. skb = sinfo->skb;
  54. skb_put(skb, pkg_len - 4); /* Minus FCS */
  55. skb->ip_summed = CHECKSUM_NONE;
  56. skb->protocol = eth_type_trans(skb, comm->ndev[port]);
  57. len = skb->len;
  58. netif_receive_skb(skb);
  59. stats->rx_packets++;
  60. stats->rx_bytes += len;
  61. /* Allocate a new skb for receiving. */
  62. new_skb = netdev_alloc_skb(NULL, comm->rx_desc_buff_size);
  63. if (unlikely(!new_skb)) {
  64. desc->cmd2 = (rx_pos == comm->rx_desc_num[queue] - 1) ?
  65. RXD_EOR : 0;
  66. sinfo->skb = NULL;
  67. sinfo->mapping = 0;
  68. desc->addr1 = 0;
  69. goto spl2sw_rx_poll_alloc_err;
  70. }
  71. sinfo->mapping = dma_map_single(&comm->pdev->dev, new_skb->data,
  72. comm->rx_desc_buff_size,
  73. DMA_FROM_DEVICE);
  74. if (dma_mapping_error(&comm->pdev->dev, sinfo->mapping)) {
  75. dev_kfree_skb_irq(new_skb);
  76. desc->cmd2 = (rx_pos == comm->rx_desc_num[queue] - 1) ?
  77. RXD_EOR : 0;
  78. sinfo->skb = NULL;
  79. sinfo->mapping = 0;
  80. desc->addr1 = 0;
  81. goto spl2sw_rx_poll_alloc_err;
  82. }
  83. sinfo->skb = new_skb;
  84. desc->addr1 = sinfo->mapping;
  85. spl2sw_rx_poll_rec_err:
  86. desc->cmd2 = (rx_pos == comm->rx_desc_num[queue] - 1) ?
  87. RXD_EOR | comm->rx_desc_buff_size :
  88. comm->rx_desc_buff_size;
  89. wmb(); /* Set RXD_OWN after other fields are effective. */
  90. desc->cmd1 = RXD_OWN;
  91. spl2sw_rx_poll_alloc_err:
  92. /* Move rx_pos to next position */
  93. rx_pos = ((rx_pos + 1) == comm->rx_desc_num[queue]) ? 0 : rx_pos + 1;
  94. budget_left--;
  95. /* If there are packets in high-priority queue,
  96. * stop processing low-priority queue.
  97. */
  98. if (queue == 1 && !(h_desc->cmd1 & RXD_OWN))
  99. break;
  100. }
  101. comm->rx_pos[queue] = rx_pos;
  102. /* Save pointer to last rx descriptor of high-priority queue. */
  103. if (queue == 0)
  104. h_desc = comm->rx_desc[queue] + rx_pos;
  105. }
  106. spin_lock_irqsave(&comm->int_mask_lock, flags);
  107. mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  108. mask &= ~MAC_INT_RX;
  109. writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  110. spin_unlock_irqrestore(&comm->int_mask_lock, flags);
  111. napi_complete(napi);
  112. return budget - budget_left;
  113. }
  114. int spl2sw_tx_poll(struct napi_struct *napi, int budget)
  115. {
  116. struct spl2sw_common *comm = container_of(napi, struct spl2sw_common, tx_napi);
  117. struct spl2sw_skb_info *skbinfo;
  118. struct net_device_stats *stats;
  119. int budget_left = budget;
  120. unsigned long flags;
  121. u32 tx_done_pos;
  122. u32 mask;
  123. u32 cmd;
  124. int i;
  125. spin_lock(&comm->tx_lock);
  126. tx_done_pos = comm->tx_done_pos;
  127. while (((tx_done_pos != comm->tx_pos) || (comm->tx_desc_full == 1)) && budget_left) {
  128. cmd = comm->tx_desc[tx_done_pos].cmd1;
  129. if (cmd & TXD_OWN)
  130. break;
  131. skbinfo = &comm->tx_temp_skb_info[tx_done_pos];
  132. if (unlikely(!skbinfo->skb))
  133. goto spl2sw_tx_poll_next;
  134. i = ffs(FIELD_GET(TXD_VLAN, cmd)) - 1;
  135. if (i < MAX_NETDEV_NUM && comm->ndev[i])
  136. stats = &comm->ndev[i]->stats;
  137. else
  138. goto spl2sw_tx_poll_unmap;
  139. if (unlikely(cmd & (TXD_ERR_CODE))) {
  140. stats->tx_errors++;
  141. } else {
  142. stats->tx_packets++;
  143. stats->tx_bytes += skbinfo->len;
  144. }
  145. spl2sw_tx_poll_unmap:
  146. dma_unmap_single(&comm->pdev->dev, skbinfo->mapping, skbinfo->len,
  147. DMA_TO_DEVICE);
  148. skbinfo->mapping = 0;
  149. dev_kfree_skb_irq(skbinfo->skb);
  150. skbinfo->skb = NULL;
  151. spl2sw_tx_poll_next:
  152. /* Move tx_done_pos to next position */
  153. tx_done_pos = ((tx_done_pos + 1) == TX_DESC_NUM) ? 0 : tx_done_pos + 1;
  154. if (comm->tx_desc_full == 1)
  155. comm->tx_desc_full = 0;
  156. budget_left--;
  157. }
  158. comm->tx_done_pos = tx_done_pos;
  159. if (!comm->tx_desc_full)
  160. for (i = 0; i < MAX_NETDEV_NUM; i++)
  161. if (comm->ndev[i])
  162. if (netif_queue_stopped(comm->ndev[i]))
  163. netif_wake_queue(comm->ndev[i]);
  164. spin_unlock(&comm->tx_lock);
  165. spin_lock_irqsave(&comm->int_mask_lock, flags);
  166. mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  167. mask &= ~MAC_INT_TX;
  168. writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  169. spin_unlock_irqrestore(&comm->int_mask_lock, flags);
  170. napi_complete(napi);
  171. return budget - budget_left;
  172. }
  173. irqreturn_t spl2sw_ethernet_interrupt(int irq, void *dev_id)
  174. {
  175. struct spl2sw_common *comm = (struct spl2sw_common *)dev_id;
  176. u32 status;
  177. u32 mask;
  178. int i;
  179. status = readl(comm->l2sw_reg_base + L2SW_SW_INT_STATUS_0);
  180. if (unlikely(!status)) {
  181. dev_dbg(&comm->pdev->dev, "Interrupt status is null!\n");
  182. goto spl2sw_ethernet_int_out;
  183. }
  184. writel(status, comm->l2sw_reg_base + L2SW_SW_INT_STATUS_0);
  185. if (status & MAC_INT_RX) {
  186. /* Disable RX interrupts. */
  187. spin_lock(&comm->int_mask_lock);
  188. mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  189. mask |= MAC_INT_RX;
  190. writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  191. spin_unlock(&comm->int_mask_lock);
  192. if (unlikely(status & MAC_INT_RX_DES_ERR)) {
  193. for (i = 0; i < MAX_NETDEV_NUM; i++)
  194. if (comm->ndev[i]) {
  195. comm->ndev[i]->stats.rx_fifo_errors++;
  196. break;
  197. }
  198. dev_dbg(&comm->pdev->dev, "Illegal RX Descriptor!\n");
  199. }
  200. napi_schedule(&comm->rx_napi);
  201. }
  202. if (status & MAC_INT_TX) {
  203. /* Disable TX interrupts. */
  204. spin_lock(&comm->int_mask_lock);
  205. mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  206. mask |= MAC_INT_TX;
  207. writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  208. spin_unlock(&comm->int_mask_lock);
  209. if (unlikely(status & MAC_INT_TX_DES_ERR)) {
  210. for (i = 0; i < MAX_NETDEV_NUM; i++)
  211. if (comm->ndev[i]) {
  212. comm->ndev[i]->stats.tx_fifo_errors++;
  213. break;
  214. }
  215. dev_dbg(&comm->pdev->dev, "Illegal TX Descriptor Error\n");
  216. spin_lock(&comm->int_mask_lock);
  217. mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  218. mask &= ~MAC_INT_TX;
  219. writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
  220. spin_unlock(&comm->int_mask_lock);
  221. } else {
  222. napi_schedule(&comm->tx_napi);
  223. }
  224. }
  225. spl2sw_ethernet_int_out:
  226. return IRQ_HANDLED;
  227. }