Skip to content

Commit 0ccb4fc

Browse files
Russell Kingdavem330
authored andcommitted
net: phy: move phy_lookup_setting() and guts of phy_supported_speeds() to phy-core
phy_lookup_setting() provides useful functionality in ethtool code outside phylib. Move it to phy-core and allow it to be re-used (eg, in phylink) rather than duplicated elsewhere. Note that this supports the larger linkmode space. As we move the phy settings table, we also need to move the guts of phy_supported_speeds() as well. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent da4625a commit 0ccb4fc

File tree

3 files changed

+142
-129
lines changed

3 files changed

+142
-129
lines changed

drivers/net/phy/phy-core.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,132 @@ const char *phy_duplex_to_str(unsigned int duplex)
5858
}
5959
EXPORT_SYMBOL_GPL(phy_duplex_to_str);
6060

61+
/* A mapping of all SUPPORTED settings to speed/duplex. This table
62+
* must be grouped by speed and sorted in descending match priority
63+
* - iow, descending speed. */
64+
static const struct phy_setting settings[] = {
65+
{
66+
.speed = SPEED_10000,
67+
.duplex = DUPLEX_FULL,
68+
.bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
69+
},
70+
{
71+
.speed = SPEED_10000,
72+
.duplex = DUPLEX_FULL,
73+
.bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
74+
},
75+
{
76+
.speed = SPEED_10000,
77+
.duplex = DUPLEX_FULL,
78+
.bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
79+
},
80+
{
81+
.speed = SPEED_2500,
82+
.duplex = DUPLEX_FULL,
83+
.bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
84+
},
85+
{
86+
.speed = SPEED_1000,
87+
.duplex = DUPLEX_FULL,
88+
.bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
89+
},
90+
{
91+
.speed = SPEED_1000,
92+
.duplex = DUPLEX_FULL,
93+
.bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
94+
},
95+
{
96+
.speed = SPEED_1000,
97+
.duplex = DUPLEX_HALF,
98+
.bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
99+
},
100+
{
101+
.speed = SPEED_100,
102+
.duplex = DUPLEX_FULL,
103+
.bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
104+
},
105+
{
106+
.speed = SPEED_100,
107+
.duplex = DUPLEX_HALF,
108+
.bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
109+
},
110+
{
111+
.speed = SPEED_10,
112+
.duplex = DUPLEX_FULL,
113+
.bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
114+
},
115+
{
116+
.speed = SPEED_10,
117+
.duplex = DUPLEX_HALF,
118+
.bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
119+
},
120+
};
121+
122+
/**
123+
* phy_lookup_setting - lookup a PHY setting
124+
* @speed: speed to match
125+
* @duplex: duplex to match
126+
* @mask: allowed link modes
127+
* @maxbit: bit size of link modes
128+
* @exact: an exact match is required
129+
*
130+
* Search the settings array for a setting that matches the speed and
131+
* duplex, and which is supported.
132+
*
133+
* If @exact is unset, either an exact match or %NULL for no match will
134+
* be returned.
135+
*
136+
* If @exact is set, an exact match, the fastest supported setting at
137+
* or below the specified speed, the slowest supported setting, or if
138+
* they all fail, %NULL will be returned.
139+
*/
140+
const struct phy_setting *
141+
phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
142+
size_t maxbit, bool exact)
143+
{
144+
const struct phy_setting *p, *match = NULL, *last = NULL;
145+
int i;
146+
147+
for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
148+
if (p->bit < maxbit && test_bit(p->bit, mask)) {
149+
last = p;
150+
if (p->speed == speed && p->duplex == duplex) {
151+
/* Exact match for speed and duplex */
152+
match = p;
153+
break;
154+
} else if (!exact) {
155+
if (!match && p->speed <= speed)
156+
/* Candidate */
157+
match = p;
158+
159+
if (p->speed < speed)
160+
break;
161+
}
162+
}
163+
}
164+
165+
if (!match && !exact)
166+
match = last;
167+
168+
return match;
169+
}
170+
EXPORT_SYMBOL_GPL(phy_lookup_setting);
171+
172+
size_t phy_speeds(unsigned int *speeds, size_t size,
173+
unsigned long *mask, size_t maxbit)
174+
{
175+
size_t count;
176+
int i;
177+
178+
for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
179+
if (settings[i].bit < maxbit &&
180+
test_bit(settings[i].bit, mask) &&
181+
(count == 0 || speeds[count - 1] != settings[i].speed))
182+
speeds[count++] = settings[i].speed;
183+
184+
return count;
185+
}
186+
61187
static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
62188
u16 regnum)
63189
{

drivers/net/phy/phy.c

Lines changed: 1 addition & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -157,125 +157,6 @@ int phy_aneg_done(struct phy_device *phydev)
157157
}
158158
EXPORT_SYMBOL(phy_aneg_done);
159159

160-
/* A structure for mapping a particular speed and duplex
161-
* combination to a particular SUPPORTED and ADVERTISED value
162-
*/
163-
struct phy_setting {
164-
int speed;
165-
int duplex;
166-
int bit;
167-
};
168-
169-
/* A mapping of all SUPPORTED settings to speed/duplex. This table
170-
* must be grouped by speed and sorted in descending match priority
171-
* - iow, descending speed. */
172-
static const struct phy_setting settings[] = {
173-
{
174-
.speed = SPEED_10000,
175-
.duplex = DUPLEX_FULL,
176-
.bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
177-
},
178-
{
179-
.speed = SPEED_10000,
180-
.duplex = DUPLEX_FULL,
181-
.bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
182-
},
183-
{
184-
.speed = SPEED_10000,
185-
.duplex = DUPLEX_FULL,
186-
.bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
187-
},
188-
{
189-
.speed = SPEED_2500,
190-
.duplex = DUPLEX_FULL,
191-
.bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
192-
},
193-
{
194-
.speed = SPEED_1000,
195-
.duplex = DUPLEX_FULL,
196-
.bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
197-
},
198-
{
199-
.speed = SPEED_1000,
200-
.duplex = DUPLEX_FULL,
201-
.bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
202-
},
203-
{
204-
.speed = SPEED_1000,
205-
.duplex = DUPLEX_HALF,
206-
.bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
207-
},
208-
{
209-
.speed = SPEED_100,
210-
.duplex = DUPLEX_FULL,
211-
.bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
212-
},
213-
{
214-
.speed = SPEED_100,
215-
.duplex = DUPLEX_HALF,
216-
.bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
217-
},
218-
{
219-
.speed = SPEED_10,
220-
.duplex = DUPLEX_FULL,
221-
.bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
222-
},
223-
{
224-
.speed = SPEED_10,
225-
.duplex = DUPLEX_HALF,
226-
.bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
227-
},
228-
};
229-
230-
/**
231-
* phy_lookup_setting - lookup a PHY setting
232-
* @speed: speed to match
233-
* @duplex: duplex to match
234-
* @mask: allowed link modes
235-
* @maxbit: bit size of link modes
236-
* @exact: an exact match is required
237-
*
238-
* Search the settings array for a setting that matches the speed and
239-
* duplex, and which is supported.
240-
*
241-
* If @exact is unset, either an exact match or %NULL for no match will
242-
* be returned.
243-
*
244-
* If @exact is set, an exact match, the fastest supported setting at
245-
* or below the specified speed, the slowest supported setting, or if
246-
* they all fail, %NULL will be returned.
247-
*/
248-
static const struct phy_setting *
249-
phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
250-
size_t maxbit, bool exact)
251-
{
252-
const struct phy_setting *p, *match = NULL, *last = NULL;
253-
int i;
254-
255-
for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
256-
if (p->bit < maxbit && test_bit(p->bit, mask)) {
257-
last = p;
258-
if (p->speed == speed && p->duplex == duplex) {
259-
/* Exact match for speed and duplex */
260-
match = p;
261-
break;
262-
} else if (!exact) {
263-
if (!match && p->speed <= speed)
264-
/* Candidate */
265-
match = p;
266-
267-
if (p->speed < speed)
268-
break;
269-
}
270-
}
271-
}
272-
273-
if (!match && !exact)
274-
match = last;
275-
276-
return match;
277-
}
278-
279160
/**
280161
* phy_find_valid - find a PHY setting that matches the requested parameters
281162
* @speed: desired speed
@@ -312,17 +193,8 @@ unsigned int phy_supported_speeds(struct phy_device *phy,
312193
unsigned int size)
313194
{
314195
unsigned long supported = phy->supported;
315-
unsigned int count = 0;
316-
unsigned int idx = 0;
317-
318-
for (idx = 0; idx < ARRAY_SIZE(settings) && count < size; idx++)
319-
/* Assumes settings are grouped by speed */
320-
if (settings[idx].bit < BITS_PER_LONG &&
321-
!test_bit(settings[idx].bit, &supported) &&
322-
(count == 0 || speeds[count - 1] != settings[idx].speed))
323-
speeds[count++] = settings[idx].speed;
324196

325-
return count;
197+
return phy_speeds(speeds, size, &supported, BITS_PER_LONG);
326198
}
327199

328200
/**

include/linux/phy.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,21 @@ struct phy_fixup {
670670
const char *phy_speed_to_str(int speed);
671671
const char *phy_duplex_to_str(unsigned int duplex);
672672

673+
/* A structure for mapping a particular speed and duplex
674+
* combination to a particular SUPPORTED and ADVERTISED value
675+
*/
676+
struct phy_setting {
677+
u32 speed;
678+
u8 duplex;
679+
u8 bit;
680+
};
681+
682+
const struct phy_setting *
683+
phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
684+
size_t maxbit, bool exact);
685+
size_t phy_speeds(unsigned int *speeds, size_t size,
686+
unsigned long *mask, size_t maxbit);
687+
673688
/**
674689
* phy_read_mmd - Convenience function for reading a register
675690
* from an MMD on a given PHY.

0 commit comments

Comments
 (0)