OpenWrt – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 36f29e6cf8071fed3854d9825217ed2a3c83b990 Mon Sep 17 00:00:00 2001 |
2 | From: Russell King <rmk+kernel@arm.linux.org.uk> |
||
3 | Date: Wed, 16 Sep 2015 21:27:10 +0100 |
||
4 | Subject: net: mvneta: convert to phylink |
||
5 | |||
6 | Convert mvneta to use phylink, which models the MAC to PHY link in |
||
7 | a generic, reusable form. |
||
8 | |||
9 | Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> |
||
10 | |||
11 | - remove unused sync status |
||
12 | --- |
||
13 | drivers/net/ethernet/marvell/Kconfig | 2 +- |
||
14 | drivers/net/ethernet/marvell/mvneta.c | 594 ++++++++++++++++++++-------------- |
||
15 | 2 files changed, 349 insertions(+), 247 deletions(-) |
||
16 | |||
17 | --- a/drivers/net/ethernet/marvell/Kconfig |
||
18 | +++ b/drivers/net/ethernet/marvell/Kconfig |
||
19 | @@ -60,7 +60,7 @@ config MVNETA |
||
20 | depends on ARCH_MVEBU || COMPILE_TEST |
||
21 | depends on HAS_DMA |
||
22 | select MVMDIO |
||
23 | - select FIXED_PHY |
||
24 | + select PHYLINK |
||
25 | ---help--- |
||
26 | This driver supports the network interface units in the |
||
27 | Marvell ARMADA XP, ARMADA 370, ARMADA 38x and |
||
28 | --- a/drivers/net/ethernet/marvell/mvneta.c |
||
29 | +++ b/drivers/net/ethernet/marvell/mvneta.c |
||
30 | @@ -28,7 +28,7 @@ |
||
31 | #include <linux/of_mdio.h> |
||
32 | #include <linux/of_net.h> |
||
33 | #include <linux/phy.h> |
||
34 | -#include <linux/phy_fixed.h> |
||
35 | +#include <linux/phylink.h> |
||
36 | #include <linux/platform_device.h> |
||
37 | #include <linux/skbuff.h> |
||
38 | #include <net/hwbm.h> |
||
39 | @@ -189,6 +189,7 @@ |
||
40 | #define MVNETA_GMAC_CTRL_0 0x2c00 |
||
41 | #define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2 |
||
42 | #define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc |
||
43 | +#define MVNETA_GMAC0_PORT_1000BASE_X BIT(1) |
||
44 | #define MVNETA_GMAC0_PORT_ENABLE BIT(0) |
||
45 | #define MVNETA_GMAC_CTRL_2 0x2c08 |
||
46 | #define MVNETA_GMAC2_INBAND_AN_ENABLE BIT(0) |
||
47 | @@ -204,13 +205,19 @@ |
||
48 | #define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5) |
||
49 | #define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6) |
||
50 | #define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7) |
||
51 | +#define MVNETA_GMAC_AN_COMPLETE BIT(11) |
||
52 | +#define MVNETA_GMAC_SYNC_OK BIT(14) |
||
53 | #define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c |
||
54 | #define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0) |
||
55 | #define MVNETA_GMAC_FORCE_LINK_PASS BIT(1) |
||
56 | #define MVNETA_GMAC_INBAND_AN_ENABLE BIT(2) |
||
57 | +#define MVNETA_GMAC_AN_BYPASS_ENABLE BIT(3) |
||
58 | +#define MVNETA_GMAC_INBAND_RESTART_AN BIT(4) |
||
59 | #define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5) |
||
60 | #define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6) |
||
61 | #define MVNETA_GMAC_AN_SPEED_EN BIT(7) |
||
62 | +#define MVNETA_GMAC_CONFIG_FLOW_CTRL BIT(8) |
||
63 | +#define MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL BIT(9) |
||
64 | #define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11) |
||
65 | #define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) |
||
66 | #define MVNETA_GMAC_AN_DUPLEX_EN BIT(13) |
||
67 | @@ -237,6 +244,12 @@ |
||
68 | #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) |
||
69 | #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff |
||
70 | |||
71 | +#define MVNETA_LPI_CTRL_0 0x2cc0 |
||
72 | +#define MVNETA_LPI_CTRL_1 0x2cc4 |
||
73 | +#define MVNETA_LPI_REQUEST_ENABLE BIT(0) |
||
74 | +#define MVNETA_LPI_CTRL_2 0x2cc8 |
||
75 | +#define MVNETA_LPI_STATUS 0x2ccc |
||
76 | + |
||
77 | #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff |
||
78 | |||
79 | /* Descriptor ring Macros */ |
||
80 | @@ -313,6 +326,11 @@ |
||
81 | #define MVNETA_RX_GET_BM_POOL_ID(rxd) \ |
||
82 | (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT) |
||
83 | |||
84 | +enum { |
||
85 | + ETHTOOL_STAT_EEE_WAKEUP, |
||
86 | + ETHTOOL_MAX_STATS, |
||
87 | +}; |
||
88 | + |
||
89 | struct mvneta_statistic { |
||
90 | unsigned short offset; |
||
91 | unsigned short type; |
||
92 | @@ -321,6 +339,7 @@ struct mvneta_statistic { |
||
93 | |||
94 | #define T_REG_32 32 |
||
95 | #define T_REG_64 64 |
||
96 | +#define T_SW 1 |
||
97 | |||
98 | static const struct mvneta_statistic mvneta_statistics[] = { |
||
99 | { 0x3000, T_REG_64, "good_octets_received", }, |
||
100 | @@ -355,6 +374,7 @@ static const struct mvneta_statistic mvn |
||
101 | { 0x304c, T_REG_32, "broadcast_frames_sent", }, |
||
102 | { 0x3054, T_REG_32, "fc_sent", }, |
||
103 | { 0x300c, T_REG_32, "internal_mac_transmit_err", }, |
||
104 | + { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", }, |
||
105 | }; |
||
106 | |||
107 | struct mvneta_pcpu_stats { |
||
108 | @@ -407,20 +427,19 @@ struct mvneta_port { |
||
109 | u16 tx_ring_size; |
||
110 | u16 rx_ring_size; |
||
111 | |||
112 | - struct mii_bus *mii_bus; |
||
113 | - phy_interface_t phy_interface; |
||
114 | - struct device_node *phy_node; |
||
115 | - unsigned int link; |
||
116 | - unsigned int duplex; |
||
117 | - unsigned int speed; |
||
118 | + struct device_node *dn; |
||
119 | unsigned int tx_csum_limit; |
||
120 | - unsigned int use_inband_status:1; |
||
121 | + struct phylink *phylink; |
||
122 | |||
123 | struct mvneta_bm *bm_priv; |
||
124 | struct mvneta_bm_pool *pool_long; |
||
125 | struct mvneta_bm_pool *pool_short; |
||
126 | int bm_win_id; |
||
127 | |||
128 | + bool eee_enabled; |
||
129 | + bool eee_active; |
||
130 | + bool tx_lpi_enabled; |
||
131 | + |
||
132 | u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; |
||
133 | |||
134 | u32 indir[MVNETA_RSS_LU_TABLE_SIZE]; |
||
135 | @@ -1215,10 +1234,6 @@ static void mvneta_port_disable(struct m |
||
136 | val &= ~MVNETA_GMAC0_PORT_ENABLE; |
||
137 | mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); |
||
138 | |||
139 | - pp->link = 0; |
||
140 | - pp->duplex = -1; |
||
141 | - pp->speed = 0; |
||
142 | - |
||
143 | udelay(200); |
||
144 | } |
||
145 | |||
146 | @@ -1278,44 +1293,6 @@ static void mvneta_set_other_mcast_table |
||
147 | mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val); |
||
148 | } |
||
149 | |||
150 | -static void mvneta_set_autoneg(struct mvneta_port *pp, int enable) |
||
151 | -{ |
||
152 | - u32 val; |
||
153 | - |
||
154 | - if (enable) { |
||
155 | - val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
156 | - val &= ~(MVNETA_GMAC_FORCE_LINK_PASS | |
||
157 | - MVNETA_GMAC_FORCE_LINK_DOWN | |
||
158 | - MVNETA_GMAC_AN_FLOW_CTRL_EN); |
||
159 | - val |= MVNETA_GMAC_INBAND_AN_ENABLE | |
||
160 | - MVNETA_GMAC_AN_SPEED_EN | |
||
161 | - MVNETA_GMAC_AN_DUPLEX_EN; |
||
162 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
163 | - |
||
164 | - val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); |
||
165 | - val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; |
||
166 | - mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); |
||
167 | - |
||
168 | - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
||
169 | - val |= MVNETA_GMAC2_INBAND_AN_ENABLE; |
||
170 | - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); |
||
171 | - } else { |
||
172 | - val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
173 | - val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | |
||
174 | - MVNETA_GMAC_AN_SPEED_EN | |
||
175 | - MVNETA_GMAC_AN_DUPLEX_EN); |
||
176 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
177 | - |
||
178 | - val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); |
||
179 | - val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; |
||
180 | - mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); |
||
181 | - |
||
182 | - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
||
183 | - val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; |
||
184 | - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); |
||
185 | - } |
||
186 | -} |
||
187 | - |
||
188 | static void mvneta_percpu_unmask_interrupt(void *arg) |
||
189 | { |
||
190 | struct mvneta_port *pp = arg; |
||
191 | @@ -1468,7 +1445,6 @@ static void mvneta_defaults_set(struct m |
||
192 | val &= ~MVNETA_PHY_POLLING_ENABLE; |
||
193 | mvreg_write(pp, MVNETA_UNIT_CONTROL, val); |
||
194 | |||
195 | - mvneta_set_autoneg(pp, pp->use_inband_status); |
||
196 | mvneta_set_ucast_table(pp, -1); |
||
197 | mvneta_set_special_mcast_table(pp, -1); |
||
198 | mvneta_set_other_mcast_table(pp, -1); |
||
199 | @@ -2693,26 +2669,11 @@ static irqreturn_t mvneta_percpu_isr(int |
||
200 | return IRQ_HANDLED; |
||
201 | } |
||
202 | |||
203 | -static int mvneta_fixed_link_update(struct mvneta_port *pp, |
||
204 | - struct phy_device *phy) |
||
205 | +static void mvneta_link_change(struct mvneta_port *pp) |
||
206 | { |
||
207 | - struct fixed_phy_status status; |
||
208 | - struct fixed_phy_status changed = {}; |
||
209 | u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); |
||
210 | |||
211 | - status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); |
||
212 | - if (gmac_stat & MVNETA_GMAC_SPEED_1000) |
||
213 | - status.speed = SPEED_1000; |
||
214 | - else if (gmac_stat & MVNETA_GMAC_SPEED_100) |
||
215 | - status.speed = SPEED_100; |
||
216 | - else |
||
217 | - status.speed = SPEED_10; |
||
218 | - status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); |
||
219 | - changed.link = 1; |
||
220 | - changed.speed = 1; |
||
221 | - changed.duplex = 1; |
||
222 | - fixed_phy_update_state(phy, &status, &changed); |
||
223 | - return 0; |
||
224 | + phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP)); |
||
225 | } |
||
226 | |||
227 | /* NAPI handler |
||
228 | @@ -2728,7 +2689,6 @@ static int mvneta_poll(struct napi_struc |
||
229 | u32 cause_rx_tx; |
||
230 | int rx_queue; |
||
231 | struct mvneta_port *pp = netdev_priv(napi->dev); |
||
232 | - struct net_device *ndev = pp->dev; |
||
233 | struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports); |
||
234 | |||
235 | if (!netif_running(pp->dev)) { |
||
236 | @@ -2742,12 +2702,11 @@ static int mvneta_poll(struct napi_struc |
||
237 | u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE); |
||
238 | |||
239 | mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); |
||
240 | - if (pp->use_inband_status && (cause_misc & |
||
241 | - (MVNETA_CAUSE_PHY_STATUS_CHANGE | |
||
242 | - MVNETA_CAUSE_LINK_CHANGE | |
||
243 | - MVNETA_CAUSE_PSC_SYNC_CHANGE))) { |
||
244 | - mvneta_fixed_link_update(pp, ndev->phydev); |
||
245 | - } |
||
246 | + |
||
247 | + if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE | |
||
248 | + MVNETA_CAUSE_LINK_CHANGE | |
||
249 | + MVNETA_CAUSE_PSC_SYNC_CHANGE)) |
||
250 | + mvneta_link_change(pp); |
||
251 | } |
||
252 | |||
253 | /* Release Tx descriptors */ |
||
254 | @@ -3061,7 +3020,6 @@ static int mvneta_setup_txqs(struct mvne |
||
255 | static void mvneta_start_dev(struct mvneta_port *pp) |
||
256 | { |
||
257 | int cpu; |
||
258 | - struct net_device *ndev = pp->dev; |
||
259 | |||
260 | mvneta_max_rx_size_set(pp, pp->pkt_size); |
||
261 | mvneta_txq_max_tx_size_set(pp, pp->pkt_size); |
||
262 | @@ -3089,16 +3047,15 @@ static void mvneta_start_dev(struct mvne |
||
263 | MVNETA_CAUSE_LINK_CHANGE | |
||
264 | MVNETA_CAUSE_PSC_SYNC_CHANGE); |
||
265 | |||
266 | - phy_start(ndev->phydev); |
||
267 | + phylink_start(pp->phylink); |
||
268 | netif_tx_start_all_queues(pp->dev); |
||
269 | } |
||
270 | |||
271 | static void mvneta_stop_dev(struct mvneta_port *pp) |
||
272 | { |
||
273 | unsigned int cpu; |
||
274 | - struct net_device *ndev = pp->dev; |
||
275 | |||
276 | - phy_stop(ndev->phydev); |
||
277 | + phylink_stop(pp->phylink); |
||
278 | |||
279 | if (!pp->neta_armada3700) { |
||
280 | for_each_online_cpu(cpu) { |
||
281 | @@ -3251,103 +3208,232 @@ static int mvneta_set_mac_addr(struct ne |
||
282 | return 0; |
||
283 | } |
||
284 | |||
285 | -static void mvneta_adjust_link(struct net_device *ndev) |
||
286 | +static void mvneta_validate(struct net_device *ndev, unsigned long *supported, |
||
287 | + struct phylink_link_state *state) |
||
288 | +{ |
||
289 | + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; |
||
290 | + |
||
291 | + /* Allow all the expected bits */ |
||
292 | + phylink_set(mask, Autoneg); |
||
293 | + phylink_set_port_modes(mask); |
||
294 | + |
||
295 | + /* Asymmetric pause is unsupported */ |
||
296 | + phylink_set(mask, Pause); |
||
297 | + /* Half-duplex at speeds higher than 100Mbit is unsupported */ |
||
298 | + phylink_set(mask, 1000baseT_Full); |
||
299 | + phylink_set(mask, 1000baseX_Full); |
||
300 | + |
||
301 | + if (state->interface != PHY_INTERFACE_MODE_1000BASEX) { |
||
302 | + /* 10M and 100M are only supported in non-802.3z mode */ |
||
303 | + phylink_set(mask, 10baseT_Half); |
||
304 | + phylink_set(mask, 10baseT_Full); |
||
305 | + phylink_set(mask, 100baseT_Half); |
||
306 | + phylink_set(mask, 100baseT_Full); |
||
307 | + } |
||
308 | + |
||
309 | + bitmap_and(supported, supported, mask, |
||
310 | + __ETHTOOL_LINK_MODE_MASK_NBITS); |
||
311 | + bitmap_and(state->advertising, state->advertising, mask, |
||
312 | + __ETHTOOL_LINK_MODE_MASK_NBITS); |
||
313 | +} |
||
314 | + |
||
315 | +static int mvneta_mac_link_state(struct net_device *ndev, |
||
316 | + struct phylink_link_state *state) |
||
317 | { |
||
318 | struct mvneta_port *pp = netdev_priv(ndev); |
||
319 | - struct phy_device *phydev = ndev->phydev; |
||
320 | - int status_change = 0; |
||
321 | + u32 gmac_stat; |
||
322 | |||
323 | - if (phydev->link) { |
||
324 | - if ((pp->speed != phydev->speed) || |
||
325 | - (pp->duplex != phydev->duplex)) { |
||
326 | - u32 val; |
||
327 | - |
||
328 | - val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
329 | - val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | |
||
330 | - MVNETA_GMAC_CONFIG_GMII_SPEED | |
||
331 | - MVNETA_GMAC_CONFIG_FULL_DUPLEX); |
||
332 | - |
||
333 | - if (phydev->duplex) |
||
334 | - val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; |
||
335 | - |
||
336 | - if (phydev->speed == SPEED_1000) |
||
337 | - val |= MVNETA_GMAC_CONFIG_GMII_SPEED; |
||
338 | - else if (phydev->speed == SPEED_100) |
||
339 | - val |= MVNETA_GMAC_CONFIG_MII_SPEED; |
||
340 | + gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); |
||
341 | |||
342 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
343 | + if (gmac_stat & MVNETA_GMAC_SPEED_1000) |
||
344 | + state->speed = SPEED_1000; |
||
345 | + else if (gmac_stat & MVNETA_GMAC_SPEED_100) |
||
346 | + state->speed = SPEED_100; |
||
347 | + else |
||
348 | + state->speed = SPEED_10; |
||
349 | |||
350 | - pp->duplex = phydev->duplex; |
||
351 | - pp->speed = phydev->speed; |
||
352 | - } |
||
353 | + state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); |
||
354 | + state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); |
||
355 | + state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); |
||
356 | + |
||
357 | + state->pause = 0; |
||
358 | + if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) |
||
359 | + state->pause |= MLO_PAUSE_RX; |
||
360 | + if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) |
||
361 | + state->pause |= MLO_PAUSE_TX; |
||
362 | + |
||
363 | + return 1; |
||
364 | +} |
||
365 | + |
||
366 | +static void mvneta_mac_an_restart(struct net_device *ndev) |
||
367 | +{ |
||
368 | + struct mvneta_port *pp = netdev_priv(ndev); |
||
369 | + u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
370 | + |
||
371 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, |
||
372 | + gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); |
||
373 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, |
||
374 | + gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); |
||
375 | +} |
||
376 | + |
||
377 | +static void mvneta_mac_config(struct net_device *ndev, unsigned int mode, |
||
378 | + const struct phylink_link_state *state) |
||
379 | +{ |
||
380 | + struct mvneta_port *pp = netdev_priv(ndev); |
||
381 | + u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); |
||
382 | + u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
||
383 | + u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); |
||
384 | + u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
385 | + |
||
386 | + new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; |
||
387 | + new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE; |
||
388 | + new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE; |
||
389 | + new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | |
||
390 | + MVNETA_GMAC_INBAND_RESTART_AN | |
||
391 | + MVNETA_GMAC_CONFIG_MII_SPEED | |
||
392 | + MVNETA_GMAC_CONFIG_GMII_SPEED | |
||
393 | + MVNETA_GMAC_AN_SPEED_EN | |
||
394 | + MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL | |
||
395 | + MVNETA_GMAC_CONFIG_FLOW_CTRL | |
||
396 | + MVNETA_GMAC_AN_FLOW_CTRL_EN | |
||
397 | + MVNETA_GMAC_CONFIG_FULL_DUPLEX | |
||
398 | + MVNETA_GMAC_AN_DUPLEX_EN); |
||
399 | + |
||
400 | + if (phylink_test(state->advertising, Pause)) |
||
401 | + new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; |
||
402 | + if (state->pause & MLO_PAUSE_TXRX_MASK) |
||
403 | + new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL; |
||
404 | + |
||
405 | + if (!phylink_autoneg_inband(mode)) { |
||
406 | + /* Phy or fixed speed */ |
||
407 | + if (state->duplex) |
||
408 | + new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; |
||
409 | + |
||
410 | + if (state->speed == SPEED_1000) |
||
411 | + new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED; |
||
412 | + else if (state->speed == SPEED_100) |
||
413 | + new_an |= MVNETA_GMAC_CONFIG_MII_SPEED; |
||
414 | + } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { |
||
415 | + /* SGMII mode receives the state from the PHY */ |
||
416 | + new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; |
||
417 | + new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; |
||
418 | + new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | |
||
419 | + MVNETA_GMAC_FORCE_LINK_PASS)) | |
||
420 | + MVNETA_GMAC_INBAND_AN_ENABLE | |
||
421 | + MVNETA_GMAC_AN_SPEED_EN | |
||
422 | + MVNETA_GMAC_AN_DUPLEX_EN; |
||
423 | + } else { |
||
424 | + /* 802.3z negotiation - only 1000base-X */ |
||
425 | + new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; |
||
426 | + new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; |
||
427 | + new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | |
||
428 | + MVNETA_GMAC_FORCE_LINK_PASS)) | |
||
429 | + MVNETA_GMAC_INBAND_AN_ENABLE | |
||
430 | + MVNETA_GMAC_CONFIG_GMII_SPEED | |
||
431 | + /* The MAC only supports FD mode */ |
||
432 | + MVNETA_GMAC_CONFIG_FULL_DUPLEX; |
||
433 | + |
||
434 | + if (state->pause & MLO_PAUSE_AN && state->an_enabled) |
||
435 | + new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; |
||
436 | + } |
||
437 | + |
||
438 | + /* Armada 370 documentation says we can only change the port mode |
||
439 | + * and in-band enable when the link is down, so force it down |
||
440 | + * while making these changes. We also do this for GMAC_CTRL2 */ |
||
441 | + if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X || |
||
442 | + (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE || |
||
443 | + (new_an ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) { |
||
444 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, |
||
445 | + (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) | |
||
446 | + MVNETA_GMAC_FORCE_LINK_DOWN); |
||
447 | + } |
||
448 | + |
||
449 | + if (new_ctrl0 != gmac_ctrl0) |
||
450 | + mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); |
||
451 | + if (new_ctrl2 != gmac_ctrl2) |
||
452 | + mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); |
||
453 | + if (new_clk != gmac_clk) |
||
454 | + mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk); |
||
455 | + if (new_an != gmac_an) |
||
456 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); |
||
457 | +} |
||
458 | + |
||
459 | +static void mvneta_set_eee(struct mvneta_port *pp, bool enable) |
||
460 | +{ |
||
461 | + u32 lpi_ctl1; |
||
462 | + |
||
463 | + lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1); |
||
464 | + if (enable) |
||
465 | + lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE; |
||
466 | + else |
||
467 | + lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE; |
||
468 | + mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1); |
||
469 | +} |
||
470 | + |
||
471 | +static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode) |
||
472 | +{ |
||
473 | + struct mvneta_port *pp = netdev_priv(ndev); |
||
474 | + u32 val; |
||
475 | + |
||
476 | + mvneta_port_down(pp); |
||
477 | + |
||
478 | + if (!phylink_autoneg_inband(mode)) { |
||
479 | + val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
480 | + val &= ~MVNETA_GMAC_FORCE_LINK_PASS; |
||
481 | + val |= MVNETA_GMAC_FORCE_LINK_DOWN; |
||
482 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
483 | } |
||
484 | |||
485 | - if (phydev->link != pp->link) { |
||
486 | - if (!phydev->link) { |
||
487 | - pp->duplex = -1; |
||
488 | - pp->speed = 0; |
||
489 | - } |
||
490 | + pp->eee_active = false; |
||
491 | + mvneta_set_eee(pp, false); |
||
492 | +} |
||
493 | + |
||
494 | +static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode, |
||
495 | + struct phy_device *phy) |
||
496 | +{ |
||
497 | + struct mvneta_port *pp = netdev_priv(ndev); |
||
498 | + u32 val; |
||
499 | |||
500 | - pp->link = phydev->link; |
||
501 | - status_change = 1; |
||
502 | + if (!phylink_autoneg_inband(mode)) { |
||
503 | + val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
504 | + val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; |
||
505 | + val |= MVNETA_GMAC_FORCE_LINK_PASS; |
||
506 | + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
507 | } |
||
508 | |||
509 | - if (status_change) { |
||
510 | - if (phydev->link) { |
||
511 | - if (!pp->use_inband_status) { |
||
512 | - u32 val = mvreg_read(pp, |
||
513 | - MVNETA_GMAC_AUTONEG_CONFIG); |
||
514 | - val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; |
||
515 | - val |= MVNETA_GMAC_FORCE_LINK_PASS; |
||
516 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, |
||
517 | - val); |
||
518 | - } |
||
519 | - mvneta_port_up(pp); |
||
520 | - } else { |
||
521 | - if (!pp->use_inband_status) { |
||
522 | - u32 val = mvreg_read(pp, |
||
523 | - MVNETA_GMAC_AUTONEG_CONFIG); |
||
524 | - val &= ~MVNETA_GMAC_FORCE_LINK_PASS; |
||
525 | - val |= MVNETA_GMAC_FORCE_LINK_DOWN; |
||
526 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, |
||
527 | - val); |
||
528 | - } |
||
529 | - mvneta_port_down(pp); |
||
530 | - } |
||
531 | - phy_print_status(phydev); |
||
532 | + mvneta_port_up(pp); |
||
533 | + |
||
534 | + if (phy && pp->eee_enabled) { |
||
535 | + pp->eee_active = phy_init_eee(phy, 0) >= 0; |
||
536 | + mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled); |
||
537 | } |
||
538 | } |
||
539 | |||
540 | +static const struct phylink_mac_ops mvneta_phylink_ops = { |
||
541 | + .validate = mvneta_validate, |
||
542 | + .mac_link_state = mvneta_mac_link_state, |
||
543 | + .mac_an_restart = mvneta_mac_an_restart, |
||
544 | + .mac_config = mvneta_mac_config, |
||
545 | + .mac_link_down = mvneta_mac_link_down, |
||
546 | + .mac_link_up = mvneta_mac_link_up, |
||
547 | +}; |
||
548 | + |
||
549 | static int mvneta_mdio_probe(struct mvneta_port *pp) |
||
550 | { |
||
551 | - struct phy_device *phy_dev; |
||
552 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
||
553 | + int err = phylink_of_phy_connect(pp->phylink, pp->dn); |
||
554 | + if (err) |
||
555 | + netdev_err(pp->dev, "could not attach PHY\n"); |
||
556 | |||
557 | - phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0, |
||
558 | - pp->phy_interface); |
||
559 | - if (!phy_dev) { |
||
560 | - netdev_err(pp->dev, "could not find the PHY\n"); |
||
561 | - return -ENODEV; |
||
562 | - } |
||
563 | - |
||
564 | - phy_ethtool_get_wol(phy_dev, &wol); |
||
565 | + phylink_ethtool_get_wol(pp->phylink, &wol); |
||
566 | device_set_wakeup_capable(&pp->dev->dev, !!wol.supported); |
||
567 | |||
568 | - phy_dev->supported &= PHY_GBIT_FEATURES; |
||
569 | - phy_dev->advertising = phy_dev->supported; |
||
570 | - |
||
571 | - pp->link = 0; |
||
572 | - pp->duplex = 0; |
||
573 | - pp->speed = 0; |
||
574 | - |
||
575 | - return 0; |
||
576 | + return err; |
||
577 | } |
||
578 | |||
579 | static void mvneta_mdio_remove(struct mvneta_port *pp) |
||
580 | { |
||
581 | - struct net_device *ndev = pp->dev; |
||
582 | - |
||
583 | - phy_disconnect(ndev->phydev); |
||
584 | + phylink_disconnect_phy(pp->phylink); |
||
585 | } |
||
586 | |||
587 | /* Electing a CPU must be done in an atomic way: it should be done |
||
588 | @@ -3626,10 +3712,9 @@ static int mvneta_stop(struct net_device |
||
589 | |||
590 | static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
||
591 | { |
||
592 | - if (!dev->phydev) |
||
593 | - return -ENOTSUPP; |
||
594 | + struct mvneta_port *pp = netdev_priv(dev); |
||
595 | |||
596 | - return phy_mii_ioctl(dev->phydev, ifr, cmd); |
||
597 | + return phylink_mii_ioctl(pp->phylink, ifr, cmd); |
||
598 | } |
||
599 | |||
600 | /* Ethtool methods */ |
||
601 | @@ -3640,44 +3725,25 @@ mvneta_ethtool_set_link_ksettings(struct |
||
602 | const struct ethtool_link_ksettings *cmd) |
||
603 | { |
||
604 | struct mvneta_port *pp = netdev_priv(ndev); |
||
605 | - struct phy_device *phydev = ndev->phydev; |
||
606 | |||
607 | - if (!phydev) |
||
608 | - return -ENODEV; |
||
609 | - |
||
610 | - if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) { |
||
611 | - u32 val; |
||
612 | - |
||
613 | - mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE); |
||
614 | - |
||
615 | - if (cmd->base.autoneg == AUTONEG_DISABLE) { |
||
616 | - val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); |
||
617 | - val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | |
||
618 | - MVNETA_GMAC_CONFIG_GMII_SPEED | |
||
619 | - MVNETA_GMAC_CONFIG_FULL_DUPLEX); |
||
620 | - |
||
621 | - if (phydev->duplex) |
||
622 | - val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; |
||
623 | + return phylink_ethtool_ksettings_set(pp->phylink, cmd); |
||
624 | +} |
||
625 | |||
626 | - if (phydev->speed == SPEED_1000) |
||
627 | - val |= MVNETA_GMAC_CONFIG_GMII_SPEED; |
||
628 | - else if (phydev->speed == SPEED_100) |
||
629 | - val |= MVNETA_GMAC_CONFIG_MII_SPEED; |
||
630 | +/* Get link ksettings for ethtools */ |
||
631 | +static int |
||
632 | +mvneta_ethtool_get_link_ksettings(struct net_device *ndev, |
||
633 | + struct ethtool_link_ksettings *cmd) |
||
634 | +{ |
||
635 | + struct mvneta_port *pp = netdev_priv(ndev); |
||
636 | |||
637 | - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); |
||
638 | - } |
||
639 | + return phylink_ethtool_ksettings_get(pp->phylink, cmd); |
||
640 | +} |
||
641 | |||
642 | - pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE); |
||
643 | - netdev_info(pp->dev, "autoneg status set to %i\n", |
||
644 | - pp->use_inband_status); |
||
645 | - |
||
646 | - if (netif_running(ndev)) { |
||
647 | - mvneta_port_down(pp); |
||
648 | - mvneta_port_up(pp); |
||
649 | - } |
||
650 | - } |
||
651 | +static int mvneta_ethtool_nway_reset(struct net_device *dev) |
||
652 | +{ |
||
653 | + struct mvneta_port *pp = netdev_priv(dev); |
||
654 | |||
655 | - return phy_ethtool_ksettings_set(ndev->phydev, cmd); |
||
656 | + return phylink_ethtool_nway_reset(pp->phylink); |
||
657 | } |
||
658 | |||
659 | /* Set interrupt coalescing for ethtools */ |
||
660 | @@ -3769,6 +3835,22 @@ static int mvneta_ethtool_set_ringparam( |
||
661 | return 0; |
||
662 | } |
||
663 | |||
664 | +static void mvneta_ethtool_get_pauseparam(struct net_device *dev, |
||
665 | + struct ethtool_pauseparam *pause) |
||
666 | +{ |
||
667 | + struct mvneta_port *pp = netdev_priv(dev); |
||
668 | + |
||
669 | + phylink_ethtool_get_pauseparam(pp->phylink, pause); |
||
670 | +} |
||
671 | + |
||
672 | +static int mvneta_ethtool_set_pauseparam(struct net_device *dev, |
||
673 | + struct ethtool_pauseparam *pause) |
||
674 | +{ |
||
675 | + struct mvneta_port *pp = netdev_priv(dev); |
||
676 | + |
||
677 | + return phylink_ethtool_set_pauseparam(pp->phylink, pause); |
||
678 | +} |
||
679 | + |
||
680 | static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset, |
||
681 | u8 *data) |
||
682 | { |
||
683 | @@ -3785,26 +3867,35 @@ static void mvneta_ethtool_update_stats( |
||
684 | { |
||
685 | const struct mvneta_statistic *s; |
||
686 | void __iomem *base = pp->base; |
||
687 | - u32 high, low, val; |
||
688 | - u64 val64; |
||
689 | + u32 high, low; |
||
690 | + u64 val; |
||
691 | int i; |
||
692 | |||
693 | for (i = 0, s = mvneta_statistics; |
||
694 | s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); |
||
695 | s++, i++) { |
||
696 | + val = 0; |
||
697 | + |
||
698 | switch (s->type) { |
||
699 | case T_REG_32: |
||
700 | val = readl_relaxed(base + s->offset); |
||
701 | - pp->ethtool_stats[i] += val; |
||
702 | break; |
||
703 | case T_REG_64: |
||
704 | /* Docs say to read low 32-bit then high */ |
||
705 | low = readl_relaxed(base + s->offset); |
||
706 | high = readl_relaxed(base + s->offset + 4); |
||
707 | - val64 = (u64)high << 32 | low; |
||
708 | - pp->ethtool_stats[i] += val64; |
||
709 | + val = (u64)high << 32 | low; |
||
710 | + break; |
||
711 | + case T_SW: |
||
712 | + switch (s->offset) { |
||
713 | + case ETHTOOL_STAT_EEE_WAKEUP: |
||
714 | + val = phylink_get_eee_err(pp->phylink); |
||
715 | + break; |
||
716 | + } |
||
717 | break; |
||
718 | } |
||
719 | + |
||
720 | + pp->ethtool_stats[i] += val; |
||
721 | } |
||
722 | } |
||
723 | |||
724 | @@ -3939,28 +4030,65 @@ static int mvneta_ethtool_get_rxfh(struc |
||
725 | static void mvneta_ethtool_get_wol(struct net_device *dev, |
||
726 | struct ethtool_wolinfo *wol) |
||
727 | { |
||
728 | - wol->supported = 0; |
||
729 | - wol->wolopts = 0; |
||
730 | + struct mvneta_port *pp = netdev_priv(dev); |
||
731 | |||
732 | - if (dev->phydev) |
||
733 | - phy_ethtool_get_wol(dev->phydev, wol); |
||
734 | + phylink_ethtool_get_wol(pp->phylink, wol); |
||
735 | } |
||
736 | |||
737 | static int mvneta_ethtool_set_wol(struct net_device *dev, |
||
738 | struct ethtool_wolinfo *wol) |
||
739 | { |
||
740 | + struct mvneta_port *pp = netdev_priv(dev); |
||
741 | int ret; |
||
742 | |||
743 | - if (!dev->phydev) |
||
744 | - return -EOPNOTSUPP; |
||
745 | - |
||
746 | - ret = phy_ethtool_set_wol(dev->phydev, wol); |
||
747 | + ret = phylink_ethtool_set_wol(pp->phylink, wol); |
||
748 | if (!ret) |
||
749 | device_set_wakeup_enable(&dev->dev, !!wol->wolopts); |
||
750 | |||
751 | return ret; |
||
752 | } |
||
753 | |||
754 | +static int mvneta_ethtool_get_eee(struct net_device *dev, |
||
755 | + struct ethtool_eee *eee) |
||
756 | +{ |
||
757 | + struct mvneta_port *pp = netdev_priv(dev); |
||
758 | + u32 lpi_ctl0; |
||
759 | + |
||
760 | + lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); |
||
761 | + |
||
762 | + eee->eee_enabled = pp->eee_enabled; |
||
763 | + eee->eee_active = pp->eee_active; |
||
764 | + eee->tx_lpi_enabled = pp->tx_lpi_enabled; |
||
765 | + eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale; |
||
766 | + |
||
767 | + return phylink_ethtool_get_eee(pp->phylink, eee); |
||
768 | +} |
||
769 | + |
||
770 | +static int mvneta_ethtool_set_eee(struct net_device *dev, |
||
771 | + struct ethtool_eee *eee) |
||
772 | +{ |
||
773 | + struct mvneta_port *pp = netdev_priv(dev); |
||
774 | + u32 lpi_ctl0; |
||
775 | + |
||
776 | + /* The Armada 37x documents do not give limits for this other than |
||
777 | + * it being an 8-bit register. */ |
||
778 | + if (eee->tx_lpi_enabled && |
||
779 | + (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255)) |
||
780 | + return -EINVAL; |
||
781 | + |
||
782 | + lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); |
||
783 | + lpi_ctl0 &= ~(0xff << 8); |
||
784 | + lpi_ctl0 |= eee->tx_lpi_timer << 8; |
||
785 | + mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0); |
||
786 | + |
||
787 | + pp->eee_enabled = eee->eee_enabled; |
||
788 | + pp->tx_lpi_enabled = eee->tx_lpi_enabled; |
||
789 | + |
||
790 | + mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled); |
||
791 | + |
||
792 | + return phylink_ethtool_set_eee(pp->phylink, eee); |
||
793 | +} |
||
794 | + |
||
795 | static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, |
||
796 | void *accel_priv, |
||
797 | select_queue_fallback_t fallback) |
||
798 | @@ -3984,13 +4112,15 @@ static const struct net_device_ops mvnet |
||
799 | }; |
||
800 | |||
801 | static const struct ethtool_ops mvneta_eth_tool_ops = { |
||
802 | - .nway_reset = phy_ethtool_nway_reset, |
||
803 | + .nway_reset = mvneta_ethtool_nway_reset, |
||
804 | .get_link = ethtool_op_get_link, |
||
805 | .set_coalesce = mvneta_ethtool_set_coalesce, |
||
806 | .get_coalesce = mvneta_ethtool_get_coalesce, |
||
807 | .get_drvinfo = mvneta_ethtool_get_drvinfo, |
||
808 | .get_ringparam = mvneta_ethtool_get_ringparam, |
||
809 | .set_ringparam = mvneta_ethtool_set_ringparam, |
||
810 | + .get_pauseparam = mvneta_ethtool_get_pauseparam, |
||
811 | + .set_pauseparam = mvneta_ethtool_set_pauseparam, |
||
812 | .get_strings = mvneta_ethtool_get_strings, |
||
813 | .get_ethtool_stats = mvneta_ethtool_get_stats, |
||
814 | .get_sset_count = mvneta_ethtool_get_sset_count, |
||
815 | @@ -3998,10 +4128,12 @@ static const struct ethtool_ops mvneta_e |
||
816 | .get_rxnfc = mvneta_ethtool_get_rxnfc, |
||
817 | .get_rxfh = mvneta_ethtool_get_rxfh, |
||
818 | .set_rxfh = mvneta_ethtool_set_rxfh, |
||
819 | - .get_link_ksettings = phy_ethtool_get_link_ksettings, |
||
820 | + .get_link_ksettings = mvneta_ethtool_get_link_ksettings, |
||
821 | .set_link_ksettings = mvneta_ethtool_set_link_ksettings, |
||
822 | .get_wol = mvneta_ethtool_get_wol, |
||
823 | .set_wol = mvneta_ethtool_set_wol, |
||
824 | + .get_eee = mvneta_ethtool_get_eee, |
||
825 | + .set_eee = mvneta_ethtool_set_eee, |
||
826 | }; |
||
827 | |||
828 | /* Initialize hw */ |
||
829 | @@ -4146,14 +4278,13 @@ static int mvneta_probe(struct platform_ |
||
830 | { |
||
831 | struct resource *res; |
||
832 | struct device_node *dn = pdev->dev.of_node; |
||
833 | - struct device_node *phy_node; |
||
834 | struct device_node *bm_node; |
||
835 | struct mvneta_port *pp; |
||
836 | struct net_device *dev; |
||
837 | + struct phylink *phylink; |
||
838 | const char *dt_mac_addr; |
||
839 | char hw_mac_addr[ETH_ALEN]; |
||
840 | const char *mac_from; |
||
841 | - const char *managed; |
||
842 | int tx_csum_limit; |
||
843 | int phy_mode; |
||
844 | int err; |
||
845 | @@ -4169,31 +4300,11 @@ static int mvneta_probe(struct platform_ |
||
846 | goto err_free_netdev; |
||
847 | } |
||
848 | |||
849 | - phy_node = of_parse_phandle(dn, "phy", 0); |
||
850 | - if (!phy_node) { |
||
851 | - if (!of_phy_is_fixed_link(dn)) { |
||
852 | - dev_err(&pdev->dev, "no PHY specified\n"); |
||
853 | - err = -ENODEV; |
||
854 | - goto err_free_irq; |
||
855 | - } |
||
856 | - |
||
857 | - err = of_phy_register_fixed_link(dn); |
||
858 | - if (err < 0) { |
||
859 | - dev_err(&pdev->dev, "cannot register fixed PHY\n"); |
||
860 | - goto err_free_irq; |
||
861 | - } |
||
862 | - |
||
863 | - /* In the case of a fixed PHY, the DT node associated |
||
864 | - * to the PHY is the Ethernet MAC DT node. |
||
865 | - */ |
||
866 | - phy_node = of_node_get(dn); |
||
867 | - } |
||
868 | - |
||
869 | phy_mode = of_get_phy_mode(dn); |
||
870 | if (phy_mode < 0) { |
||
871 | dev_err(&pdev->dev, "incorrect phy-mode\n"); |
||
872 | err = -EINVAL; |
||
873 | - goto err_put_phy_node; |
||
874 | + goto err_free_irq; |
||
875 | } |
||
876 | |||
877 | dev->tx_queue_len = MVNETA_MAX_TXD; |
||
878 | @@ -4204,12 +4315,7 @@ static int mvneta_probe(struct platform_ |
||
879 | |||
880 | pp = netdev_priv(dev); |
||
881 | spin_lock_init(&pp->lock); |
||
882 | - pp->phy_node = phy_node; |
||
883 | - pp->phy_interface = phy_mode; |
||
884 | - |
||
885 | - err = of_property_read_string(dn, "managed", &managed); |
||
886 | - pp->use_inband_status = (err == 0 && |
||
887 | - strcmp(managed, "in-band-status") == 0); |
||
888 | + pp->dn = dn; |
||
889 | |||
890 | pp->rxq_def = rxq_def; |
||
891 | |||
892 | @@ -4231,7 +4337,7 @@ static int mvneta_probe(struct platform_ |
||
893 | pp->clk = devm_clk_get(&pdev->dev, NULL); |
||
894 | if (IS_ERR(pp->clk)) { |
||
895 | err = PTR_ERR(pp->clk); |
||
896 | - goto err_put_phy_node; |
||
897 | + goto err_free_irq; |
||
898 | } |
||
899 | |||
900 | clk_prepare_enable(pp->clk); |
||
901 | @@ -4357,6 +4463,14 @@ static int mvneta_probe(struct platform_ |
||
902 | /* 9676 == 9700 - 20 and rounding to 8 */ |
||
903 | dev->max_mtu = 9676; |
||
904 | |||
905 | + phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops); |
||
906 | + if (IS_ERR(phylink)) { |
||
907 | + err = PTR_ERR(phylink); |
||
908 | + goto err_free_stats; |
||
909 | + } |
||
910 | + |
||
911 | + pp->phylink = phylink; |
||
912 | + |
||
913 | err = register_netdev(dev); |
||
914 | if (err < 0) { |
||
915 | dev_err(&pdev->dev, "failed to register\n"); |
||
916 | @@ -4368,14 +4482,6 @@ static int mvneta_probe(struct platform_ |
||
917 | |||
918 | platform_set_drvdata(pdev, pp->dev); |
||
919 | |||
920 | - if (pp->use_inband_status) { |
||
921 | - struct phy_device *phy = of_phy_find_device(dn); |
||
922 | - |
||
923 | - mvneta_fixed_link_update(pp, phy); |
||
924 | - |
||
925 | - put_device(&phy->mdio.dev); |
||
926 | - } |
||
927 | - |
||
928 | return 0; |
||
929 | |||
930 | err_netdev: |
||
931 | @@ -4386,16 +4492,14 @@ err_netdev: |
||
932 | 1 << pp->id); |
||
933 | } |
||
934 | err_free_stats: |
||
935 | + if (pp->phylink) |
||
936 | + phylink_destroy(pp->phylink); |
||
937 | free_percpu(pp->stats); |
||
938 | err_free_ports: |
||
939 | free_percpu(pp->ports); |
||
940 | err_clk: |
||
941 | clk_disable_unprepare(pp->clk_bus); |
||
942 | clk_disable_unprepare(pp->clk); |
||
943 | -err_put_phy_node: |
||
944 | - of_node_put(phy_node); |
||
945 | - if (of_phy_is_fixed_link(dn)) |
||
946 | - of_phy_deregister_fixed_link(dn); |
||
947 | err_free_irq: |
||
948 | irq_dispose_mapping(dev->irq); |
||
949 | err_free_netdev: |
||
950 | @@ -4407,7 +4511,6 @@ err_free_netdev: |
||
951 | static int mvneta_remove(struct platform_device *pdev) |
||
952 | { |
||
953 | struct net_device *dev = platform_get_drvdata(pdev); |
||
954 | - struct device_node *dn = pdev->dev.of_node; |
||
955 | struct mvneta_port *pp = netdev_priv(dev); |
||
956 | |||
957 | unregister_netdev(dev); |
||
958 | @@ -4415,10 +4518,8 @@ static int mvneta_remove(struct platform |
||
959 | clk_disable_unprepare(pp->clk); |
||
960 | free_percpu(pp->ports); |
||
961 | free_percpu(pp->stats); |
||
962 | - if (of_phy_is_fixed_link(dn)) |
||
963 | - of_phy_deregister_fixed_link(dn); |
||
964 | irq_dispose_mapping(dev->irq); |
||
965 | - of_node_put(pp->phy_node); |
||
966 | + phylink_destroy(pp->phylink); |
||
967 | free_netdev(dev); |
||
968 | |||
969 | if (pp->bm_priv) { |
||
970 | @@ -4470,9 +4571,6 @@ static int mvneta_resume(struct device * |
||
971 | return err; |
||
972 | } |
||
973 | |||
974 | - if (pp->use_inband_status) |
||
975 | - mvneta_fixed_link_update(pp, dev->phydev); |
||
976 | - |
||
977 | netif_device_attach(dev); |
||
978 | if (netif_running(dev)) { |
||
979 | mvneta_open(dev); |