master.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * Handling of a master device, switching frames via its switch fabric CPU port
  3. *
  4. * Copyright (c) 2017 Savoir-faire Linux Inc.
  5. * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include "dsa_priv.h"
  13. static void dsa_master_get_ethtool_stats(struct net_device *dev,
  14. struct ethtool_stats *stats,
  15. uint64_t *data)
  16. {
  17. struct dsa_port *cpu_dp = dev->dsa_ptr;
  18. const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
  19. struct dsa_switch *ds = cpu_dp->ds;
  20. int port = cpu_dp->index;
  21. int count = 0;
  22. if (ops->get_sset_count && ops->get_ethtool_stats) {
  23. count = ops->get_sset_count(dev, ETH_SS_STATS);
  24. ops->get_ethtool_stats(dev, stats, data);
  25. }
  26. if (ds->ops->get_ethtool_stats)
  27. ds->ops->get_ethtool_stats(ds, port, data + count);
  28. }
  29. static void dsa_master_get_ethtool_phy_stats(struct net_device *dev,
  30. struct ethtool_stats *stats,
  31. uint64_t *data)
  32. {
  33. struct dsa_port *cpu_dp = dev->dsa_ptr;
  34. const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
  35. struct dsa_switch *ds = cpu_dp->ds;
  36. int port = cpu_dp->index;
  37. int count = 0;
  38. if (dev->phydev && !ops->get_ethtool_phy_stats) {
  39. count = phy_ethtool_get_sset_count(dev->phydev);
  40. if (count >= 0)
  41. phy_ethtool_get_stats(dev->phydev, stats, data);
  42. } else if (ops->get_sset_count && ops->get_ethtool_phy_stats) {
  43. count = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
  44. ops->get_ethtool_phy_stats(dev, stats, data);
  45. }
  46. if (count < 0)
  47. count = 0;
  48. if (ds->ops->get_ethtool_phy_stats)
  49. ds->ops->get_ethtool_phy_stats(ds, port, data + count);
  50. }
  51. static int dsa_master_get_sset_count(struct net_device *dev, int sset)
  52. {
  53. struct dsa_port *cpu_dp = dev->dsa_ptr;
  54. const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
  55. struct dsa_switch *ds = cpu_dp->ds;
  56. int count = 0;
  57. if (sset == ETH_SS_PHY_STATS && dev->phydev &&
  58. !ops->get_ethtool_phy_stats)
  59. count = phy_ethtool_get_sset_count(dev->phydev);
  60. else if (ops->get_sset_count)
  61. count = ops->get_sset_count(dev, sset);
  62. if (count < 0)
  63. count = 0;
  64. if (ds->ops->get_sset_count)
  65. count += ds->ops->get_sset_count(ds, cpu_dp->index, sset);
  66. return count;
  67. }
  68. static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
  69. uint8_t *data)
  70. {
  71. struct dsa_port *cpu_dp = dev->dsa_ptr;
  72. const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops;
  73. struct dsa_switch *ds = cpu_dp->ds;
  74. int port = cpu_dp->index;
  75. int len = ETH_GSTRING_LEN;
  76. int mcount = 0, count;
  77. unsigned int i;
  78. uint8_t pfx[4];
  79. uint8_t *ndata;
  80. snprintf(pfx, sizeof(pfx), "p%.2d", port);
  81. /* We do not want to be NULL-terminated, since this is a prefix */
  82. pfx[sizeof(pfx) - 1] = '_';
  83. if (stringset == ETH_SS_PHY_STATS && dev->phydev &&
  84. !ops->get_ethtool_phy_stats) {
  85. mcount = phy_ethtool_get_sset_count(dev->phydev);
  86. if (mcount < 0)
  87. mcount = 0;
  88. else
  89. phy_ethtool_get_strings(dev->phydev, data);
  90. } else if (ops->get_sset_count && ops->get_strings) {
  91. mcount = ops->get_sset_count(dev, stringset);
  92. if (mcount < 0)
  93. mcount = 0;
  94. ops->get_strings(dev, stringset, data);
  95. }
  96. if (ds->ops->get_strings) {
  97. ndata = data + mcount * len;
  98. /* This function copies ETH_GSTRINGS_LEN bytes, we will mangle
  99. * the output after to prepend our CPU port prefix we
  100. * constructed earlier
  101. */
  102. ds->ops->get_strings(ds, port, stringset, ndata);
  103. count = ds->ops->get_sset_count(ds, port, stringset);
  104. for (i = 0; i < count; i++) {
  105. memmove(ndata + (i * len + sizeof(pfx)),
  106. ndata + i * len, len - sizeof(pfx));
  107. memcpy(ndata + i * len, pfx, sizeof(pfx));
  108. }
  109. }
  110. }
  111. static int dsa_master_ethtool_setup(struct net_device *dev)
  112. {
  113. struct dsa_port *cpu_dp = dev->dsa_ptr;
  114. struct dsa_switch *ds = cpu_dp->ds;
  115. struct ethtool_ops *ops;
  116. ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL);
  117. if (!ops)
  118. return -ENOMEM;
  119. cpu_dp->orig_ethtool_ops = dev->ethtool_ops;
  120. if (cpu_dp->orig_ethtool_ops)
  121. memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops));
  122. ops->get_sset_count = dsa_master_get_sset_count;
  123. ops->get_ethtool_stats = dsa_master_get_ethtool_stats;
  124. ops->get_strings = dsa_master_get_strings;
  125. ops->get_ethtool_phy_stats = dsa_master_get_ethtool_phy_stats;
  126. dev->ethtool_ops = ops;
  127. return 0;
  128. }
  129. static void dsa_master_ethtool_teardown(struct net_device *dev)
  130. {
  131. struct dsa_port *cpu_dp = dev->dsa_ptr;
  132. dev->ethtool_ops = cpu_dp->orig_ethtool_ops;
  133. cpu_dp->orig_ethtool_ops = NULL;
  134. }
  135. static struct lock_class_key dsa_master_addr_list_lock_key;
  136. int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
  137. {
  138. /* If we use a tagging format that doesn't have an ethertype
  139. * field, make sure that all packets from this point on get
  140. * sent to the tag format's receive function.
  141. */
  142. wmb();
  143. dev->dsa_ptr = cpu_dp;
  144. lockdep_set_class(&dev->addr_list_lock,
  145. &dsa_master_addr_list_lock_key);
  146. return dsa_master_ethtool_setup(dev);
  147. }
  148. void dsa_master_teardown(struct net_device *dev)
  149. {
  150. dsa_master_ethtool_teardown(dev);
  151. dev->dsa_ptr = NULL;
  152. /* If we used a tagging format that doesn't have an ethertype
  153. * field, make sure that all packets from this point get sent
  154. * without the tag and go through the regular receive path.
  155. */
  156. wmb();
  157. }