rockchip_canfd-tx.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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_tx_tail_is_eff(const struct rkcanfd_priv *priv)
  9. {
  10. const struct canfd_frame *cfd;
  11. const struct sk_buff *skb;
  12. unsigned int tx_tail;
  13. if (!rkcanfd_get_tx_pending(priv))
  14. return false;
  15. tx_tail = rkcanfd_get_tx_tail(priv);
  16. skb = priv->can.echo_skb[tx_tail];
  17. if (!skb) {
  18. netdev_err(priv->ndev,
  19. "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
  20. __func__, tx_tail,
  21. priv->tx_head, priv->tx_tail);
  22. return false;
  23. }
  24. cfd = (struct canfd_frame *)skb->data;
  25. return cfd->can_id & CAN_EFF_FLAG;
  26. }
  27. unsigned int rkcanfd_get_effective_tx_free(const struct rkcanfd_priv *priv)
  28. {
  29. if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_6 &&
  30. rkcanfd_tx_tail_is_eff(priv))
  31. return 0;
  32. return rkcanfd_get_tx_free(priv);
  33. }
  34. static void rkcanfd_start_xmit_write_cmd(const struct rkcanfd_priv *priv,
  35. const u32 reg_cmd)
  36. {
  37. if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
  38. rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default |
  39. RKCANFD_REG_MODE_SPACE_RX_MODE);
  40. rkcanfd_write(priv, RKCANFD_REG_CMD, reg_cmd);
  41. if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
  42. rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default);
  43. }
  44. void rkcanfd_xmit_retry(struct rkcanfd_priv *priv)
  45. {
  46. const unsigned int tx_head = rkcanfd_get_tx_head(priv);
  47. const u32 reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);
  48. rkcanfd_start_xmit_write_cmd(priv, reg_cmd);
  49. }
  50. netdev_tx_t rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev)
  51. {
  52. struct rkcanfd_priv *priv = netdev_priv(ndev);
  53. u32 reg_frameinfo, reg_id, reg_cmd;
  54. unsigned int tx_head, frame_len;
  55. const struct canfd_frame *cfd;
  56. int err;
  57. u8 i;
  58. if (can_dev_dropped_skb(ndev, skb))
  59. return NETDEV_TX_OK;
  60. if (!netif_subqueue_maybe_stop(priv->ndev, 0,
  61. rkcanfd_get_effective_tx_free(priv),
  62. RKCANFD_TX_STOP_THRESHOLD,
  63. RKCANFD_TX_START_THRESHOLD)) {
  64. if (net_ratelimit())
  65. netdev_info(priv->ndev,
  66. "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, tx_pending=%d)\n",
  67. priv->tx_head, priv->tx_tail,
  68. rkcanfd_get_tx_pending(priv));
  69. return NETDEV_TX_BUSY;
  70. }
  71. cfd = (struct canfd_frame *)skb->data;
  72. if (cfd->can_id & CAN_EFF_FLAG) {
  73. reg_frameinfo = RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT;
  74. reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_EFF, cfd->can_id);
  75. } else {
  76. reg_frameinfo = 0;
  77. reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_SFF, cfd->can_id);
  78. }
  79. if (cfd->can_id & CAN_RTR_FLAG)
  80. reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_RTR;
  81. if (can_is_canfd_skb(skb)) {
  82. reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_FDF;
  83. if (cfd->flags & CANFD_BRS)
  84. reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_BRS;
  85. reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
  86. can_fd_len2dlc(cfd->len));
  87. } else {
  88. reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
  89. cfd->len);
  90. }
  91. tx_head = rkcanfd_get_tx_head(priv);
  92. reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);
  93. rkcanfd_write(priv, RKCANFD_REG_FD_TXFRAMEINFO, reg_frameinfo);
  94. rkcanfd_write(priv, RKCANFD_REG_FD_TXID, reg_id);
  95. for (i = 0; i < cfd->len; i += 4)
  96. rkcanfd_write(priv, RKCANFD_REG_FD_TXDATA0 + i,
  97. *(u32 *)(cfd->data + i));
  98. frame_len = can_skb_get_frame_len(skb);
  99. err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
  100. if (!err)
  101. netdev_sent_queue(priv->ndev, frame_len);
  102. WRITE_ONCE(priv->tx_head, priv->tx_head + 1);
  103. rkcanfd_start_xmit_write_cmd(priv, reg_cmd);
  104. netif_subqueue_maybe_stop(priv->ndev, 0,
  105. rkcanfd_get_effective_tx_free(priv),
  106. RKCANFD_TX_STOP_THRESHOLD,
  107. RKCANFD_TX_START_THRESHOLD);
  108. return NETDEV_TX_OK;
  109. }
  110. void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts,
  111. unsigned int *frame_len_p)
  112. {
  113. struct net_device_stats *stats = &priv->ndev->stats;
  114. unsigned int tx_tail;
  115. struct sk_buff *skb;
  116. tx_tail = rkcanfd_get_tx_tail(priv);
  117. skb = priv->can.echo_skb[tx_tail];
  118. /* Manual handling of CAN Bus Error counters. See
  119. * rkcanfd_get_corrected_berr_counter() for detailed
  120. * explanation.
  121. */
  122. if (priv->bec.txerr)
  123. priv->bec.txerr--;
  124. if (skb)
  125. rkcanfd_skb_set_timestamp(priv, skb, ts);
  126. stats->tx_bytes +=
  127. can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
  128. tx_tail, ts,
  129. frame_len_p);
  130. stats->tx_packets++;
  131. }