143-net-mvneta-add-EEE-support.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. From b7dacf514e41d6efff0ccc170f660cc6dc2aeae2 Mon Sep 17 00:00:00 2001
  2. From: Russell King <rmk+kernel@arm.linux.org.uk>
  3. Date: Tue, 29 Sep 2015 15:17:39 +0100
  4. Subject: [PATCH 731/744] net: mvneta: add EEE support
  5. Add EEE support to mvneta. This allows us to enable the low power idle
  6. support at MAC level if there is a PHY attached through phylink which
  7. supports LPI. The appropriate ethtool support is provided to allow the
  8. feature to be controlled, including ethtool statistics for EEE wakeup
  9. errors.
  10. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  11. ---
  12. drivers/net/ethernet/marvell/mvneta.c | 87 +++++++++++++++++++++++++++++++++++
  13. 1 file changed, 87 insertions(+)
  14. --- a/drivers/net/ethernet/marvell/mvneta.c
  15. +++ b/drivers/net/ethernet/marvell/mvneta.c
  16. @@ -243,6 +243,12 @@
  17. #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2))
  18. #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff
  19. +#define MVNETA_LPI_CTRL_0 0x2cc0
  20. +#define MVNETA_LPI_CTRL_1 0x2cc4
  21. +#define MVNETA_LPI_REQUEST_ENABLE BIT(0)
  22. +#define MVNETA_LPI_CTRL_2 0x2cc8
  23. +#define MVNETA_LPI_STATUS 0x2ccc
  24. +
  25. #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
  26. /* Descriptor ring Macros */
  27. @@ -316,6 +322,11 @@
  28. #define MVNETA_RX_GET_BM_POOL_ID(rxd) \
  29. (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
  30. +enum {
  31. + ETHTOOL_STAT_EEE_WAKEUP,
  32. + ETHTOOL_MAX_STATS,
  33. +};
  34. +
  35. struct mvneta_statistic {
  36. unsigned short offset;
  37. unsigned short type;
  38. @@ -324,6 +335,7 @@ struct mvneta_statistic {
  39. #define T_REG_32 32
  40. #define T_REG_64 64
  41. +#define T_SW 1
  42. static const struct mvneta_statistic mvneta_statistics[] = {
  43. { 0x3000, T_REG_64, "good_octets_received", },
  44. @@ -358,6 +370,7 @@ static const struct mvneta_statistic mvn
  45. { 0x304c, T_REG_32, "broadcast_frames_sent", },
  46. { 0x3054, T_REG_32, "fc_sent", },
  47. { 0x300c, T_REG_32, "internal_mac_transmit_err", },
  48. + { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", },
  49. };
  50. struct mvneta_pcpu_stats {
  51. @@ -413,6 +426,10 @@ struct mvneta_port {
  52. struct mvneta_bm_pool *pool_short;
  53. int bm_win_id;
  54. + bool eee_enabled;
  55. + bool eee_active;
  56. + bool tx_lpi_enabled;
  57. +
  58. u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
  59. u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
  60. @@ -3276,6 +3293,18 @@ static void mvneta_mac_config(struct net
  61. mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an);
  62. }
  63. +static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
  64. +{
  65. + u32 lpi_ctl1;
  66. +
  67. + lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
  68. + if (enable)
  69. + lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE;
  70. + else
  71. + lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE;
  72. + mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
  73. +}
  74. +
  75. static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
  76. {
  77. struct mvneta_port *pp = netdev_priv(ndev);
  78. @@ -3289,6 +3318,9 @@ static void mvneta_mac_link_down(struct
  79. val |= MVNETA_GMAC_FORCE_LINK_DOWN;
  80. mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
  81. }
  82. +
  83. + pp->eee_active = false;
  84. + mvneta_set_eee(pp, false);
  85. }
  86. static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
  87. @@ -3305,6 +3337,11 @@ static void mvneta_mac_link_up(struct ne
  88. }
  89. mvneta_port_up(pp);
  90. +
  91. + if (phy && pp->eee_enabled) {
  92. + pp->eee_active = phy_init_eee(phy, 0) >= 0;
  93. + mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled);
  94. + }
  95. }
  96. static const struct phylink_mac_ops mvneta_phylink_ops = {
  97. @@ -3744,6 +3781,13 @@ static void mvneta_ethtool_update_stats(
  98. val64 = (u64)high << 32 | low;
  99. pp->ethtool_stats[i] += val64;
  100. break;
  101. + case T_SW:
  102. + switch (s->offset) {
  103. + case ETHTOOL_STAT_EEE_WAKEUP:
  104. + val = phylink_get_eee_err(pp->phylink);
  105. + break;
  106. + }
  107. + break;
  108. }
  109. }
  110. }
  111. @@ -3867,6 +3911,47 @@ static int mvneta_ethtool_get_rxfh(struc
  112. return 0;
  113. }
  114. +static int mvneta_ethtool_get_eee(struct net_device *dev,
  115. + struct ethtool_eee *eee)
  116. +{
  117. + struct mvneta_port *pp = netdev_priv(dev);
  118. + u32 lpi_ctl0;
  119. +
  120. + lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
  121. +
  122. + eee->eee_enabled = pp->eee_enabled;
  123. + eee->eee_active = pp->eee_active;
  124. + eee->tx_lpi_enabled = pp->tx_lpi_enabled;
  125. + eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale;
  126. +
  127. + return phylink_ethtool_get_eee(pp->phylink, eee);
  128. +}
  129. +
  130. +static int mvneta_ethtool_set_eee(struct net_device *dev,
  131. + struct ethtool_eee *eee)
  132. +{
  133. + struct mvneta_port *pp = netdev_priv(dev);
  134. + u32 lpi_ctl0;
  135. +
  136. + /* The Armada 37x documents do not give limits for this other than
  137. + * it being an 8-bit register. */
  138. + if (eee->tx_lpi_enabled &&
  139. + (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255))
  140. + return -EINVAL;
  141. +
  142. + lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
  143. + lpi_ctl0 &= ~(0xff << 8);
  144. + lpi_ctl0 |= eee->tx_lpi_timer << 8;
  145. + mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0);
  146. +
  147. + pp->eee_enabled = eee->eee_enabled;
  148. + pp->tx_lpi_enabled = eee->tx_lpi_enabled;
  149. +
  150. + mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled);
  151. +
  152. + return phylink_ethtool_set_eee(pp->phylink, eee);
  153. +}
  154. +
  155. static const struct net_device_ops mvneta_netdev_ops = {
  156. .ndo_open = mvneta_open,
  157. .ndo_stop = mvneta_stop,
  158. @@ -3898,6 +3983,8 @@ const struct ethtool_ops mvneta_eth_tool
  159. .get_rxnfc = mvneta_ethtool_get_rxnfc,
  160. .get_rxfh = mvneta_ethtool_get_rxfh,
  161. .set_rxfh = mvneta_ethtool_set_rxfh,
  162. + .get_eee = mvneta_ethtool_get_eee,
  163. + .set_eee = mvneta_ethtool_set_eee,
  164. };
  165. /* Initialize hw */