rockchip_canfd-rx.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (c) 2023, 2024 Pengutronix,
  4. // Marc Kleine-Budde <kernel@pengutronix.de>
  5. //
  6. #include <net/netdev_queues.h>
  7. #include "rockchip_canfd.h"
  8. static bool rkcanfd_can_frame_header_equal(const struct canfd_frame *const cfd1,
  9. const struct canfd_frame *const cfd2,
  10. const bool is_canfd)
  11. {
  12. const u8 mask_flags = CANFD_BRS | CANFD_ESI | CANFD_FDF;
  13. canid_t mask = CAN_EFF_FLAG;
  14. if (canfd_sanitize_len(cfd1->len) != canfd_sanitize_len(cfd2->len))
  15. return false;
  16. if (!is_canfd)
  17. mask |= CAN_RTR_FLAG;
  18. if (cfd1->can_id & CAN_EFF_FLAG)
  19. mask |= CAN_EFF_MASK;
  20. else
  21. mask |= CAN_SFF_MASK;
  22. if ((cfd1->can_id & mask) != (cfd2->can_id & mask))
  23. return false;
  24. if (is_canfd &&
  25. (cfd1->flags & mask_flags) != (cfd2->flags & mask_flags))
  26. return false;
  27. return true;
  28. }
  29. static bool rkcanfd_can_frame_data_equal(const struct canfd_frame *cfd1,
  30. const struct canfd_frame *cfd2,
  31. const bool is_canfd)
  32. {
  33. u8 len;
  34. if (!is_canfd && (cfd1->can_id & CAN_RTR_FLAG))
  35. return true;
  36. len = canfd_sanitize_len(cfd1->len);
  37. return !memcmp(cfd1->data, cfd2->data, len);
  38. }
  39. static unsigned int
  40. rkcanfd_fifo_header_to_cfd_header(const struct rkcanfd_priv *priv,
  41. const struct rkcanfd_fifo_header *header,
  42. struct canfd_frame *cfd)
  43. {
  44. unsigned int len = sizeof(*cfd) - sizeof(cfd->data);
  45. u8 dlc;
  46. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT)
  47. cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_EFF, header->id) |
  48. CAN_EFF_FLAG;
  49. else
  50. cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_SFF, header->id);
  51. dlc = FIELD_GET(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
  52. header->frameinfo);
  53. /* CAN-FD */
  54. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF) {
  55. cfd->len = can_fd_dlc2len(dlc);
  56. /* The cfd is not allocated by alloc_canfd_skb(), so
  57. * set CANFD_FDF here.
  58. */
  59. cfd->flags |= CANFD_FDF;
  60. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_BRS)
  61. cfd->flags |= CANFD_BRS;
  62. } else {
  63. cfd->len = can_cc_dlc2len(dlc);
  64. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_RTR) {
  65. cfd->can_id |= CAN_RTR_FLAG;
  66. return len;
  67. }
  68. }
  69. return len + cfd->len;
  70. }
  71. static int rkcanfd_rxstx_filter(struct rkcanfd_priv *priv,
  72. const struct canfd_frame *cfd_rx, const u32 ts,
  73. bool *tx_done)
  74. {
  75. struct net_device_stats *stats = &priv->ndev->stats;
  76. struct rkcanfd_stats *rkcanfd_stats = &priv->stats;
  77. const struct canfd_frame *cfd_nominal;
  78. const struct sk_buff *skb;
  79. unsigned int tx_tail;
  80. tx_tail = rkcanfd_get_tx_tail(priv);
  81. skb = priv->can.echo_skb[tx_tail];
  82. if (!skb) {
  83. netdev_err(priv->ndev,
  84. "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
  85. __func__, tx_tail,
  86. priv->tx_head, priv->tx_tail);
  87. return -ENOMSG;
  88. }
  89. cfd_nominal = (struct canfd_frame *)skb->data;
  90. /* We RX'ed a frame identical to our pending TX frame. */
  91. if (rkcanfd_can_frame_header_equal(cfd_rx, cfd_nominal,
  92. cfd_rx->flags & CANFD_FDF) &&
  93. rkcanfd_can_frame_data_equal(cfd_rx, cfd_nominal,
  94. cfd_rx->flags & CANFD_FDF)) {
  95. unsigned int frame_len;
  96. rkcanfd_handle_tx_done_one(priv, ts, &frame_len);
  97. WRITE_ONCE(priv->tx_tail, priv->tx_tail + 1);
  98. netif_subqueue_completed_wake(priv->ndev, 0, 1, frame_len,
  99. rkcanfd_get_effective_tx_free(priv),
  100. RKCANFD_TX_START_THRESHOLD);
  101. *tx_done = true;
  102. return 0;
  103. }
  104. if (!(priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_6))
  105. return 0;
  106. /* Erratum 6: Extended frames may be send as standard frames.
  107. *
  108. * Not affected if:
  109. * - TX'ed a standard frame -or-
  110. * - RX'ed an extended frame
  111. */
  112. if (!(cfd_nominal->can_id & CAN_EFF_FLAG) ||
  113. (cfd_rx->can_id & CAN_EFF_FLAG))
  114. return 0;
  115. /* Not affected if:
  116. * - standard part and RTR flag of the TX'ed frame
  117. * is not equal the CAN-ID and RTR flag of the RX'ed frame.
  118. */
  119. if ((cfd_nominal->can_id & (CAN_RTR_FLAG | CAN_SFF_MASK)) !=
  120. (cfd_rx->can_id & (CAN_RTR_FLAG | CAN_SFF_MASK)))
  121. return 0;
  122. /* Not affected if:
  123. * - length is not the same
  124. */
  125. if (cfd_nominal->len != cfd_rx->len)
  126. return 0;
  127. /* Not affected if:
  128. * - the data of non RTR frames is different
  129. */
  130. if (!(cfd_nominal->can_id & CAN_RTR_FLAG) &&
  131. memcmp(cfd_nominal->data, cfd_rx->data, cfd_nominal->len))
  132. return 0;
  133. /* Affected by Erratum 6 */
  134. u64_stats_update_begin(&rkcanfd_stats->syncp);
  135. u64_stats_inc(&rkcanfd_stats->tx_extended_as_standard_errors);
  136. u64_stats_update_end(&rkcanfd_stats->syncp);
  137. /* Manual handling of CAN Bus Error counters. See
  138. * rkcanfd_get_corrected_berr_counter() for detailed
  139. * explanation.
  140. */
  141. if (priv->bec.txerr)
  142. priv->bec.txerr--;
  143. *tx_done = true;
  144. stats->tx_packets++;
  145. stats->tx_errors++;
  146. rkcanfd_xmit_retry(priv);
  147. return 0;
  148. }
  149. static inline bool
  150. rkcanfd_fifo_header_empty(const struct rkcanfd_fifo_header *header)
  151. {
  152. /* Erratum 5: If the FIFO is empty, we read the same value for
  153. * all elements.
  154. */
  155. return header->frameinfo == header->id &&
  156. header->frameinfo == header->ts;
  157. }
  158. static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv)
  159. {
  160. struct net_device_stats *stats = &priv->ndev->stats;
  161. struct canfd_frame cfd[1] = { }, *skb_cfd;
  162. struct rkcanfd_fifo_header header[1] = { };
  163. struct sk_buff *skb;
  164. unsigned int len;
  165. int err;
  166. /* read header into separate struct and convert it later */
  167. rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA,
  168. header, sizeof(*header));
  169. /* read data directly into cfd */
  170. rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA,
  171. cfd->data, sizeof(cfd->data));
  172. /* Erratum 5: Counters for TXEFIFO and RXFIFO may be wrong */
  173. if (rkcanfd_fifo_header_empty(header)) {
  174. struct rkcanfd_stats *rkcanfd_stats = &priv->stats;
  175. u64_stats_update_begin(&rkcanfd_stats->syncp);
  176. u64_stats_inc(&rkcanfd_stats->rx_fifo_empty_errors);
  177. u64_stats_update_end(&rkcanfd_stats->syncp);
  178. return 0;
  179. }
  180. len = rkcanfd_fifo_header_to_cfd_header(priv, header, cfd);
  181. /* Drop any received CAN-FD frames if CAN-FD mode is not
  182. * requested.
  183. */
  184. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF &&
  185. !(priv->can.ctrlmode & CAN_CTRLMODE_FD)) {
  186. stats->rx_dropped++;
  187. return 0;
  188. }
  189. if (rkcanfd_get_tx_pending(priv)) {
  190. bool tx_done = false;
  191. err = rkcanfd_rxstx_filter(priv, cfd, header->ts, &tx_done);
  192. if (err)
  193. return err;
  194. if (tx_done && !(priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK))
  195. return 0;
  196. }
  197. /* Manual handling of CAN Bus Error counters. See
  198. * rkcanfd_get_corrected_berr_counter() for detailed
  199. * explanation.
  200. */
  201. if (priv->bec.rxerr)
  202. priv->bec.rxerr = min(CAN_ERROR_PASSIVE_THRESHOLD,
  203. priv->bec.rxerr) - 1;
  204. if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF)
  205. skb = alloc_canfd_skb(priv->ndev, &skb_cfd);
  206. else
  207. skb = alloc_can_skb(priv->ndev, (struct can_frame **)&skb_cfd);
  208. if (!skb) {
  209. stats->rx_dropped++;
  210. return 0;
  211. }
  212. memcpy(skb_cfd, cfd, len);
  213. rkcanfd_skb_set_timestamp(priv, skb, header->ts);
  214. err = can_rx_offload_queue_timestamp(&priv->offload, skb, header->ts);
  215. if (err)
  216. stats->rx_fifo_errors++;
  217. return 0;
  218. }
  219. static inline unsigned int
  220. rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *priv)
  221. {
  222. const u32 reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
  223. return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg);
  224. }
  225. int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv)
  226. {
  227. unsigned int len;
  228. int err;
  229. while ((len = rkcanfd_rx_fifo_get_len(priv))) {
  230. err = rkcanfd_handle_rx_int_one(priv);
  231. if (err)
  232. return err;
  233. }
  234. return 0;
  235. }