flexcan-ethtool.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (c) 2022 Amarula Solutions, Dario Binacchi <[email protected]>
  3. * Copyright (c) 2022 Pengutronix, Marc Kleine-Budde <[email protected]>
  4. *
  5. */
  6. #include <linux/can/dev.h>
  7. #include <linux/ethtool.h>
  8. #include <linux/kernel.h>
  9. #include <linux/netdevice.h>
  10. #include <linux/platform_device.h>
  11. #include "flexcan.h"
  12. static const char flexcan_priv_flags_strings[][ETH_GSTRING_LEN] = {
  13. #define FLEXCAN_PRIV_FLAGS_RX_RTR BIT(0)
  14. "rx-rtr",
  15. };
  16. static void
  17. flexcan_get_ringparam(struct net_device *ndev, struct ethtool_ringparam *ring,
  18. struct kernel_ethtool_ringparam *kernel_ring,
  19. struct netlink_ext_ack *ext_ack)
  20. {
  21. const struct flexcan_priv *priv = netdev_priv(ndev);
  22. ring->rx_max_pending = priv->mb_count;
  23. ring->tx_max_pending = priv->mb_count;
  24. if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX)
  25. ring->rx_pending = priv->offload.mb_last -
  26. priv->offload.mb_first + 1;
  27. else
  28. ring->rx_pending = 6; /* RX-FIFO depth is fixed */
  29. /* the drive currently supports only on TX buffer */
  30. ring->tx_pending = 1;
  31. }
  32. static void
  33. flexcan_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
  34. {
  35. switch (stringset) {
  36. case ETH_SS_PRIV_FLAGS:
  37. memcpy(data, flexcan_priv_flags_strings,
  38. sizeof(flexcan_priv_flags_strings));
  39. }
  40. }
  41. static u32 flexcan_get_priv_flags(struct net_device *ndev)
  42. {
  43. const struct flexcan_priv *priv = netdev_priv(ndev);
  44. u32 priv_flags = 0;
  45. if (flexcan_active_rx_rtr(priv))
  46. priv_flags |= FLEXCAN_PRIV_FLAGS_RX_RTR;
  47. return priv_flags;
  48. }
  49. static int flexcan_set_priv_flags(struct net_device *ndev, u32 priv_flags)
  50. {
  51. struct flexcan_priv *priv = netdev_priv(ndev);
  52. u32 quirks = priv->devtype_data.quirks;
  53. if (priv_flags & FLEXCAN_PRIV_FLAGS_RX_RTR) {
  54. if (flexcan_supports_rx_mailbox_rtr(priv))
  55. quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
  56. else if (flexcan_supports_rx_fifo(priv))
  57. quirks &= ~FLEXCAN_QUIRK_USE_RX_MAILBOX;
  58. else
  59. quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
  60. } else {
  61. if (flexcan_supports_rx_mailbox(priv))
  62. quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
  63. else
  64. quirks &= ~FLEXCAN_QUIRK_USE_RX_MAILBOX;
  65. }
  66. if (quirks != priv->devtype_data.quirks && netif_running(ndev))
  67. return -EBUSY;
  68. priv->devtype_data.quirks = quirks;
  69. if (!(priv_flags & FLEXCAN_PRIV_FLAGS_RX_RTR) &&
  70. !flexcan_active_rx_rtr(priv))
  71. netdev_info(ndev,
  72. "Activating RX mailbox mode, cannot receive RTR frames.\n");
  73. return 0;
  74. }
  75. static int flexcan_get_sset_count(struct net_device *netdev, int sset)
  76. {
  77. switch (sset) {
  78. case ETH_SS_PRIV_FLAGS:
  79. return ARRAY_SIZE(flexcan_priv_flags_strings);
  80. default:
  81. return -EOPNOTSUPP;
  82. }
  83. }
  84. const struct ethtool_ops flexcan_ethtool_ops = {
  85. .get_ringparam = flexcan_get_ringparam,
  86. .get_strings = flexcan_get_strings,
  87. .get_priv_flags = flexcan_get_priv_flags,
  88. .set_priv_flags = flexcan_set_priv_flags,
  89. .get_sset_count = flexcan_get_sset_count,
  90. .get_ts_info = ethtool_op_get_ts_info,
  91. };