412-net-phy-move-phy_lookup_setting-and-guts-of-phy_supp.patch 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. From: Russell King <[email protected]>
  2. Date: Thu, 5 Jan 2017 16:47:39 +0000
  3. Subject: [PATCH] net: phy: move phy_lookup_setting() and guts of
  4. phy_supported_speeds() to phy-core
  5. phy_lookup_setting() provides useful functionality in ethtool code
  6. outside phylib. Move it to phy-core and allow it to be re-used (eg,
  7. in phylink) rather than duplicated elsewhere. Note that this supports
  8. the larger linkmode space.
  9. As we move the phy settings table, we also need to move the guts of
  10. phy_supported_speeds() as well.
  11. Signed-off-by: Russell King <[email protected]>
  12. ---
  13. --- a/drivers/net/phy/phy.c
  14. +++ b/drivers/net/phy/phy.c
  15. @@ -149,125 +149,6 @@ static inline int phy_aneg_done(struct p
  16. return genphy_aneg_done(phydev);
  17. }
  18. -/* A structure for mapping a particular speed and duplex
  19. - * combination to a particular SUPPORTED and ADVERTISED value
  20. - */
  21. -struct phy_setting {
  22. - int speed;
  23. - int duplex;
  24. - int bit;
  25. -};
  26. -
  27. -/* A mapping of all SUPPORTED settings to speed/duplex. This table
  28. - * must be grouped by speed and sorted in descending match priority
  29. - * - iow, descending speed. */
  30. -static const struct phy_setting settings[] = {
  31. - {
  32. - .speed = SPEED_10000,
  33. - .duplex = DUPLEX_FULL,
  34. - .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  35. - },
  36. - {
  37. - .speed = SPEED_10000,
  38. - .duplex = DUPLEX_FULL,
  39. - .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
  40. - },
  41. - {
  42. - .speed = SPEED_10000,
  43. - .duplex = DUPLEX_FULL,
  44. - .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
  45. - },
  46. - {
  47. - .speed = SPEED_2500,
  48. - .duplex = DUPLEX_FULL,
  49. - .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
  50. - },
  51. - {
  52. - .speed = SPEED_1000,
  53. - .duplex = DUPLEX_FULL,
  54. - .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
  55. - },
  56. - {
  57. - .speed = SPEED_1000,
  58. - .duplex = DUPLEX_FULL,
  59. - .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
  60. - },
  61. - {
  62. - .speed = SPEED_1000,
  63. - .duplex = DUPLEX_HALF,
  64. - .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
  65. - },
  66. - {
  67. - .speed = SPEED_100,
  68. - .duplex = DUPLEX_FULL,
  69. - .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
  70. - },
  71. - {
  72. - .speed = SPEED_100,
  73. - .duplex = DUPLEX_HALF,
  74. - .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
  75. - },
  76. - {
  77. - .speed = SPEED_10,
  78. - .duplex = DUPLEX_FULL,
  79. - .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
  80. - },
  81. - {
  82. - .speed = SPEED_10,
  83. - .duplex = DUPLEX_HALF,
  84. - .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
  85. - },
  86. -};
  87. -
  88. -/**
  89. - * phy_lookup_setting - lookup a PHY setting
  90. - * @speed: speed to match
  91. - * @duplex: duplex to match
  92. - * @mask: allowed link modes
  93. - * @maxbit: bit size of link modes
  94. - * @exact: an exact match is required
  95. - *
  96. - * Search the settings array for a setting that matches the speed and
  97. - * duplex, and which is supported.
  98. - *
  99. - * If @exact is unset, either an exact match or %NULL for no match will
  100. - * be returned.
  101. - *
  102. - * If @exact is set, an exact match, the fastest supported setting at
  103. - * or below the specified speed, the slowest supported setting, or if
  104. - * they all fail, %NULL will be returned.
  105. - */
  106. -static const struct phy_setting *
  107. -phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
  108. - size_t maxbit, bool exact)
  109. -{
  110. - const struct phy_setting *p, *match = NULL, *last = NULL;
  111. - int i;
  112. -
  113. - for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
  114. - if (p->bit < maxbit && test_bit(p->bit, mask)) {
  115. - last = p;
  116. - if (p->speed == speed && p->duplex == duplex) {
  117. - /* Exact match for speed and duplex */
  118. - match = p;
  119. - break;
  120. - } else if (!exact) {
  121. - if (!match && p->speed <= speed)
  122. - /* Candidate */
  123. - match = p;
  124. -
  125. - if (p->speed < speed)
  126. - break;
  127. - }
  128. - }
  129. - }
  130. -
  131. - if (!match && !exact)
  132. - match = last;
  133. -
  134. - return match;
  135. -}
  136. -
  137. /**
  138. * phy_find_valid - find a PHY setting that matches the requested parameters
  139. * @speed: desired speed
  140. @@ -290,6 +171,25 @@ phy_find_valid(int speed, int duplex, u3
  141. }
  142. /**
  143. + * phy_supported_speeds - return all speeds currently supported by a phy device
  144. + * @phy: The phy device to return supported speeds of.
  145. + * @speeds: buffer to store supported speeds in.
  146. + * @size: size of speeds buffer.
  147. + *
  148. + * Description: Returns the number of supported speeds, and fills the speeds
  149. + * buffer with the supported speeds. If speeds buffer is too small to contain
  150. + * all currently supported speeds, will return as many speeds as can fit.
  151. + */
  152. +unsigned int phy_supported_speeds(struct phy_device *phy,
  153. + unsigned int *speeds,
  154. + unsigned int size)
  155. +{
  156. + unsigned long supported = phy->supported;
  157. +
  158. + return phy_speeds(speeds, size, &supported, BITS_PER_LONG);
  159. +}
  160. +
  161. +/**
  162. * phy_check_valid - check if there is a valid PHY setting which matches
  163. * speed, duplex, and feature mask
  164. * @speed: speed to match
  165. --- a/drivers/net/phy/phy-core.c
  166. +++ b/drivers/net/phy/phy-core.c
  167. @@ -42,6 +42,132 @@ const char *phy_duplex_to_str(unsigned i
  168. }
  169. EXPORT_SYMBOL_GPL(phy_duplex_to_str);
  170. +/* A mapping of all SUPPORTED settings to speed/duplex. This table
  171. + * must be grouped by speed and sorted in descending match priority
  172. + * - iow, descending speed. */
  173. +static const struct phy_setting settings[] = {
  174. + {
  175. + .speed = SPEED_10000,
  176. + .duplex = DUPLEX_FULL,
  177. + .bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
  178. + },
  179. + {
  180. + .speed = SPEED_10000,
  181. + .duplex = DUPLEX_FULL,
  182. + .bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
  183. + },
  184. + {
  185. + .speed = SPEED_10000,
  186. + .duplex = DUPLEX_FULL,
  187. + .bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
  188. + },
  189. + {
  190. + .speed = SPEED_2500,
  191. + .duplex = DUPLEX_FULL,
  192. + .bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
  193. + },
  194. + {
  195. + .speed = SPEED_1000,
  196. + .duplex = DUPLEX_FULL,
  197. + .bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
  198. + },
  199. + {
  200. + .speed = SPEED_1000,
  201. + .duplex = DUPLEX_FULL,
  202. + .bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
  203. + },
  204. + {
  205. + .speed = SPEED_1000,
  206. + .duplex = DUPLEX_HALF,
  207. + .bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
  208. + },
  209. + {
  210. + .speed = SPEED_100,
  211. + .duplex = DUPLEX_FULL,
  212. + .bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
  213. + },
  214. + {
  215. + .speed = SPEED_100,
  216. + .duplex = DUPLEX_HALF,
  217. + .bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
  218. + },
  219. + {
  220. + .speed = SPEED_10,
  221. + .duplex = DUPLEX_FULL,
  222. + .bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
  223. + },
  224. + {
  225. + .speed = SPEED_10,
  226. + .duplex = DUPLEX_HALF,
  227. + .bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
  228. + },
  229. +};
  230. +
  231. +/**
  232. + * phy_lookup_setting - lookup a PHY setting
  233. + * @speed: speed to match
  234. + * @duplex: duplex to match
  235. + * @mask: allowed link modes
  236. + * @maxbit: bit size of link modes
  237. + * @exact: an exact match is required
  238. + *
  239. + * Search the settings array for a setting that matches the speed and
  240. + * duplex, and which is supported.
  241. + *
  242. + * If @exact is unset, either an exact match or %NULL for no match will
  243. + * be returned.
  244. + *
  245. + * If @exact is set, an exact match, the fastest supported setting at
  246. + * or below the specified speed, the slowest supported setting, or if
  247. + * they all fail, %NULL will be returned.
  248. + */
  249. +const struct phy_setting *
  250. +phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
  251. + size_t maxbit, bool exact)
  252. +{
  253. + const struct phy_setting *p, *match = NULL, *last = NULL;
  254. + int i;
  255. +
  256. + for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
  257. + if (p->bit < maxbit && test_bit(p->bit, mask)) {
  258. + last = p;
  259. + if (p->speed == speed && p->duplex == duplex) {
  260. + /* Exact match for speed and duplex */
  261. + match = p;
  262. + break;
  263. + } else if (!exact) {
  264. + if (!match && p->speed <= speed)
  265. + /* Candidate */
  266. + match = p;
  267. +
  268. + if (p->speed < speed)
  269. + break;
  270. + }
  271. + }
  272. + }
  273. +
  274. + if (!match && !exact)
  275. + match = last;
  276. +
  277. + return match;
  278. +}
  279. +EXPORT_SYMBOL_GPL(phy_lookup_setting);
  280. +
  281. +size_t phy_speeds(unsigned int *speeds, size_t size,
  282. + unsigned long *mask, size_t maxbit)
  283. +{
  284. + size_t count;
  285. + int i;
  286. +
  287. + for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
  288. + if (settings[i].bit < maxbit &&
  289. + test_bit(settings[i].bit, mask) &&
  290. + (count == 0 || speeds[count - 1] != settings[i].speed))
  291. + speeds[count++] = settings[i].speed;
  292. +
  293. + return count;
  294. +}
  295. +
  296. static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
  297. int addr)
  298. {
  299. --- a/include/linux/phy.h
  300. +++ b/include/linux/phy.h
  301. @@ -648,6 +648,21 @@ struct phy_fixup {
  302. const char *phy_speed_to_str(int speed);
  303. const char *phy_duplex_to_str(unsigned int duplex);
  304. +/* A structure for mapping a particular speed and duplex
  305. + * combination to a particular SUPPORTED and ADVERTISED value
  306. + */
  307. +struct phy_setting {
  308. + u32 speed;
  309. + u8 duplex;
  310. + u8 bit;
  311. +};
  312. +
  313. +const struct phy_setting *
  314. +phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
  315. + size_t maxbit, bool exact);
  316. +size_t phy_speeds(unsigned int *speeds, size_t size,
  317. + unsigned long *mask, size_t maxbit);
  318. +
  319. /**
  320. * phy_read_mmd - Convenience function for reading a register
  321. * from an MMD on a given PHY.