701-net-0205-dpaa2-eth-Add-Rx-error-queue.patch 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. From 73b0aa73b401810424afa90bf58663a56ad9d51a Mon Sep 17 00:00:00 2001
  2. From: Ioana Radulescu <[email protected]>
  3. Date: Fri, 5 May 2017 19:07:50 +0300
  4. Subject: [PATCH] dpaa2-eth: Add Rx error queue
  5. Until now all error frames on the ingress path were discarded
  6. in hardware. For debug purposes, add an option to have these
  7. frames delivered to the cpu, on a dedicated queue.
  8. TODO: Remove Kconfig option, find another way to enable
  9. Rx error queue support
  10. Signed-off-by: Ioana Radulescu <[email protected]>
  11. ---
  12. drivers/net/ethernet/freescale/dpaa2/Kconfig | 10 +++
  13. drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 97 ++++++++++++++++++++++++
  14. drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 5 +-
  15. 3 files changed, 111 insertions(+), 1 deletion(-)
  16. --- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
  17. +++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
  18. @@ -15,6 +15,16 @@ config FSL_DPAA2_ETH_DCB
  19. depends on DCB
  20. help
  21. Enable Priority-Based Flow Control (PFC) support in the driver
  22. +
  23. +config FSL_DPAA2_ETH_USE_ERR_QUEUE
  24. + bool "Enable Rx error queue"
  25. + default n
  26. + help
  27. + Allow Rx error frames to be enqueued on an error queue
  28. + and processed by the driver (by default they are dropped
  29. + in hardware).
  30. + This may impact performance, recommended for debugging
  31. + purposes only.
  32. endif
  33. config FSL_DPAA2_PTP_CLOCK
  34. --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
  35. +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
  36. @@ -449,6 +449,53 @@ err_frame_format:
  37. percpu_stats->rx_dropped++;
  38. }
  39. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  40. +/* Processing of Rx frames received on the error FQ
  41. + * We check and print the error bits and then free the frame
  42. + */
  43. +static void dpaa2_eth_rx_err(struct dpaa2_eth_priv *priv,
  44. + struct dpaa2_eth_channel *ch,
  45. + const struct dpaa2_fd *fd,
  46. + struct dpaa2_eth_fq *fq __always_unused)
  47. +{
  48. + struct device *dev = priv->net_dev->dev.parent;
  49. + dma_addr_t addr = dpaa2_fd_get_addr(fd);
  50. + void *vaddr;
  51. + struct rtnl_link_stats64 *percpu_stats;
  52. + struct dpaa2_fas *fas;
  53. + u32 status = 0;
  54. + u32 fd_errors;
  55. + bool has_fas_errors = false;
  56. +
  57. + vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
  58. + dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_BIDIRECTIONAL);
  59. +
  60. + /* check frame errors in the FD field */
  61. + fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_RX_ERR_MASK;
  62. + if (likely(fd_errors)) {
  63. + has_fas_errors = (fd_errors & FD_CTRL_FAERR) &&
  64. + !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
  65. + if (net_ratelimit())
  66. + netdev_dbg(priv->net_dev, "RX frame FD err: %08x\n",
  67. + fd_errors);
  68. + }
  69. +
  70. + /* check frame errors in the FAS field */
  71. + if (has_fas_errors) {
  72. + fas = dpaa2_get_fas(vaddr, false);
  73. + status = le32_to_cpu(fas->status);
  74. + if (net_ratelimit())
  75. + netdev_dbg(priv->net_dev, "Rx frame FAS err: 0x%08x\n",
  76. + status & DPAA2_FAS_RX_ERR_MASK);
  77. + }
  78. + free_rx_fd(priv, fd, vaddr);
  79. +
  80. + percpu_stats = this_cpu_ptr(priv->percpu_stats);
  81. + percpu_stats->rx_errors++;
  82. + ch->buf_count--;
  83. +}
  84. +#endif
  85. +
  86. /* Consume all frames pull-dequeued into the store. This is the simplest way to
  87. * make sure we don't accidentally issue another volatile dequeue which would
  88. * overwrite (leak) frames already in the store.
  89. @@ -2351,6 +2398,7 @@ static void set_fq_affinity(struct dpaa2
  90. fq = &priv->fq[i];
  91. switch (fq->type) {
  92. case DPAA2_RX_FQ:
  93. + case DPAA2_RX_ERR_FQ:
  94. fq->target_cpu = rx_cpu;
  95. rx_cpu = cpumask_next(rx_cpu, &priv->dpio_cpumask);
  96. if (rx_cpu >= nr_cpu_ids)
  97. @@ -2394,6 +2442,12 @@ static void setup_fqs(struct dpaa2_eth_p
  98. }
  99. }
  100. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  101. + /* We have exactly one Rx error queue per DPNI */
  102. + priv->fq[priv->num_fqs].type = DPAA2_RX_ERR_FQ;
  103. + priv->fq[priv->num_fqs++].consume = dpaa2_eth_rx_err;
  104. +#endif
  105. +
  106. /* For each FQ, decide on which core to process incoming frames */
  107. set_fq_affinity(priv);
  108. }
  109. @@ -2944,6 +2998,40 @@ static int setup_tx_flow(struct dpaa2_et
  110. return 0;
  111. }
  112. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  113. +static int setup_rx_err_flow(struct dpaa2_eth_priv *priv,
  114. + struct dpaa2_eth_fq *fq)
  115. +{
  116. + struct device *dev = priv->net_dev->dev.parent;
  117. + struct dpni_queue q = { { 0 } };
  118. + struct dpni_queue_id qid;
  119. + u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST;
  120. + int err;
  121. +
  122. + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
  123. + DPNI_QUEUE_RX_ERR, 0, 0, &q, &qid);
  124. + if (err) {
  125. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  126. + return err;
  127. + }
  128. +
  129. + fq->fqid = qid.fqid;
  130. +
  131. + q.destination.id = fq->channel->dpcon_id;
  132. + q.destination.type = DPNI_DEST_DPCON;
  133. + q.destination.priority = 1;
  134. + q.user_context = (u64)fq;
  135. + err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
  136. + DPNI_QUEUE_RX_ERR, 0, 0, q_opt, &q);
  137. + if (err) {
  138. + dev_err(dev, "dpni_set_queue() failed (%d)\n", err);
  139. + return err;
  140. + }
  141. +
  142. + return 0;
  143. +}
  144. +#endif
  145. +
  146. /* Supported header fields for Rx hash distribution key */
  147. static const struct dpaa2_eth_dist_fields dist_fields[] = {
  148. {
  149. @@ -3313,7 +3401,11 @@ static int bind_dpni(struct dpaa2_eth_pr
  150. /* Configure handling of error frames */
  151. err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
  152. err_cfg.set_frame_annotation = 1;
  153. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  154. + err_cfg.error_action = DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE;
  155. +#else
  156. err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
  157. +#endif
  158. err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
  159. &err_cfg);
  160. if (err) {
  161. @@ -3330,6 +3422,11 @@ static int bind_dpni(struct dpaa2_eth_pr
  162. case DPAA2_TX_CONF_FQ:
  163. err = setup_tx_flow(priv, &priv->fq[i]);
  164. break;
  165. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  166. + case DPAA2_RX_ERR_FQ:
  167. + err = setup_rx_err_flow(priv, &priv->fq[i]);
  168. + break;
  169. +#endif
  170. default:
  171. dev_err(dev, "Invalid FQ type %d\n", priv->fq[i].type);
  172. return -EINVAL;
  173. --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
  174. +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
  175. @@ -318,8 +318,10 @@ struct dpaa2_eth_ch_stats {
  176. #define DPAA2_ETH_MAX_RX_QUEUES \
  177. (DPAA2_ETH_MAX_RX_QUEUES_PER_TC * DPAA2_ETH_MAX_TCS)
  178. #define DPAA2_ETH_MAX_TX_QUEUES 16
  179. +#define DPAA2_ETH_MAX_RX_ERR_QUEUES 1
  180. #define DPAA2_ETH_MAX_QUEUES (DPAA2_ETH_MAX_RX_QUEUES + \
  181. - DPAA2_ETH_MAX_TX_QUEUES)
  182. + DPAA2_ETH_MAX_TX_QUEUES + \
  183. + DPAA2_ETH_MAX_RX_ERR_QUEUES)
  184. #define DPAA2_ETH_MAX_NETDEV_QUEUES \
  185. (DPAA2_ETH_MAX_TX_QUEUES * DPAA2_ETH_MAX_TCS)
  186. @@ -328,6 +330,7 @@ struct dpaa2_eth_ch_stats {
  187. enum dpaa2_eth_fq_type {
  188. DPAA2_RX_FQ = 0,
  189. DPAA2_TX_CONF_FQ,
  190. + DPAA2_RX_ERR_FQ
  191. };
  192. struct dpaa2_eth_priv;