OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * ar8216.c: AR8216 switch driver |
||
3 | * |
||
4 | * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name> |
||
5 | * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> |
||
6 | * |
||
7 | * This program is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU General Public License |
||
9 | * as published by the Free Software Foundation; either version 2 |
||
10 | * of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * This program is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | * GNU General Public License for more details. |
||
16 | */ |
||
17 | |||
18 | #include <linux/if.h> |
||
19 | #include <linux/module.h> |
||
20 | #include <linux/init.h> |
||
21 | #include <linux/list.h> |
||
22 | #include <linux/if_ether.h> |
||
23 | #include <linux/skbuff.h> |
||
24 | #include <linux/netdevice.h> |
||
25 | #include <linux/netlink.h> |
||
26 | #include <linux/bitops.h> |
||
27 | #include <net/genetlink.h> |
||
28 | #include <linux/switch.h> |
||
29 | #include <linux/delay.h> |
||
30 | #include <linux/phy.h> |
||
31 | #include <linux/netdevice.h> |
||
32 | #include <linux/etherdevice.h> |
||
33 | #include <linux/lockdep.h> |
||
34 | #include <linux/ar8216_platform.h> |
||
35 | #include <linux/workqueue.h> |
||
36 | #include <linux/version.h> |
||
37 | |||
38 | #include "ar8216.h" |
||
39 | |||
40 | extern const struct ar8xxx_chip ar8327_chip; |
||
41 | extern const struct ar8xxx_chip ar8337_chip; |
||
42 | |||
43 | #define AR8XXX_MIB_WORK_DELAY 2000 /* msecs */ |
||
44 | |||
45 | #define MIB_DESC(_s , _o, _n) \ |
||
46 | { \ |
||
47 | .size = (_s), \ |
||
48 | .offset = (_o), \ |
||
49 | .name = (_n), \ |
||
50 | } |
||
51 | |||
52 | static const struct ar8xxx_mib_desc ar8216_mibs[] = { |
||
53 | MIB_DESC(1, AR8216_STATS_RXBROAD, "RxBroad"), |
||
54 | MIB_DESC(1, AR8216_STATS_RXPAUSE, "RxPause"), |
||
55 | MIB_DESC(1, AR8216_STATS_RXMULTI, "RxMulti"), |
||
56 | MIB_DESC(1, AR8216_STATS_RXFCSERR, "RxFcsErr"), |
||
57 | MIB_DESC(1, AR8216_STATS_RXALIGNERR, "RxAlignErr"), |
||
58 | MIB_DESC(1, AR8216_STATS_RXRUNT, "RxRunt"), |
||
59 | MIB_DESC(1, AR8216_STATS_RXFRAGMENT, "RxFragment"), |
||
60 | MIB_DESC(1, AR8216_STATS_RX64BYTE, "Rx64Byte"), |
||
61 | MIB_DESC(1, AR8216_STATS_RX128BYTE, "Rx128Byte"), |
||
62 | MIB_DESC(1, AR8216_STATS_RX256BYTE, "Rx256Byte"), |
||
63 | MIB_DESC(1, AR8216_STATS_RX512BYTE, "Rx512Byte"), |
||
64 | MIB_DESC(1, AR8216_STATS_RX1024BYTE, "Rx1024Byte"), |
||
65 | MIB_DESC(1, AR8216_STATS_RXMAXBYTE, "RxMaxByte"), |
||
66 | MIB_DESC(1, AR8216_STATS_RXTOOLONG, "RxTooLong"), |
||
67 | MIB_DESC(2, AR8216_STATS_RXGOODBYTE, "RxGoodByte"), |
||
68 | MIB_DESC(2, AR8216_STATS_RXBADBYTE, "RxBadByte"), |
||
69 | MIB_DESC(1, AR8216_STATS_RXOVERFLOW, "RxOverFlow"), |
||
70 | MIB_DESC(1, AR8216_STATS_FILTERED, "Filtered"), |
||
71 | MIB_DESC(1, AR8216_STATS_TXBROAD, "TxBroad"), |
||
72 | MIB_DESC(1, AR8216_STATS_TXPAUSE, "TxPause"), |
||
73 | MIB_DESC(1, AR8216_STATS_TXMULTI, "TxMulti"), |
||
74 | MIB_DESC(1, AR8216_STATS_TXUNDERRUN, "TxUnderRun"), |
||
75 | MIB_DESC(1, AR8216_STATS_TX64BYTE, "Tx64Byte"), |
||
76 | MIB_DESC(1, AR8216_STATS_TX128BYTE, "Tx128Byte"), |
||
77 | MIB_DESC(1, AR8216_STATS_TX256BYTE, "Tx256Byte"), |
||
78 | MIB_DESC(1, AR8216_STATS_TX512BYTE, "Tx512Byte"), |
||
79 | MIB_DESC(1, AR8216_STATS_TX1024BYTE, "Tx1024Byte"), |
||
80 | MIB_DESC(1, AR8216_STATS_TXMAXBYTE, "TxMaxByte"), |
||
81 | MIB_DESC(1, AR8216_STATS_TXOVERSIZE, "TxOverSize"), |
||
82 | MIB_DESC(2, AR8216_STATS_TXBYTE, "TxByte"), |
||
83 | MIB_DESC(1, AR8216_STATS_TXCOLLISION, "TxCollision"), |
||
84 | MIB_DESC(1, AR8216_STATS_TXABORTCOL, "TxAbortCol"), |
||
85 | MIB_DESC(1, AR8216_STATS_TXMULTICOL, "TxMultiCol"), |
||
86 | MIB_DESC(1, AR8216_STATS_TXSINGLECOL, "TxSingleCol"), |
||
87 | MIB_DESC(1, AR8216_STATS_TXEXCDEFER, "TxExcDefer"), |
||
88 | MIB_DESC(1, AR8216_STATS_TXDEFER, "TxDefer"), |
||
89 | MIB_DESC(1, AR8216_STATS_TXLATECOL, "TxLateCol"), |
||
90 | }; |
||
91 | |||
92 | const struct ar8xxx_mib_desc ar8236_mibs[39] = { |
||
93 | MIB_DESC(1, AR8236_STATS_RXBROAD, "RxBroad"), |
||
94 | MIB_DESC(1, AR8236_STATS_RXPAUSE, "RxPause"), |
||
95 | MIB_DESC(1, AR8236_STATS_RXMULTI, "RxMulti"), |
||
96 | MIB_DESC(1, AR8236_STATS_RXFCSERR, "RxFcsErr"), |
||
97 | MIB_DESC(1, AR8236_STATS_RXALIGNERR, "RxAlignErr"), |
||
98 | MIB_DESC(1, AR8236_STATS_RXRUNT, "RxRunt"), |
||
99 | MIB_DESC(1, AR8236_STATS_RXFRAGMENT, "RxFragment"), |
||
100 | MIB_DESC(1, AR8236_STATS_RX64BYTE, "Rx64Byte"), |
||
101 | MIB_DESC(1, AR8236_STATS_RX128BYTE, "Rx128Byte"), |
||
102 | MIB_DESC(1, AR8236_STATS_RX256BYTE, "Rx256Byte"), |
||
103 | MIB_DESC(1, AR8236_STATS_RX512BYTE, "Rx512Byte"), |
||
104 | MIB_DESC(1, AR8236_STATS_RX1024BYTE, "Rx1024Byte"), |
||
105 | MIB_DESC(1, AR8236_STATS_RX1518BYTE, "Rx1518Byte"), |
||
106 | MIB_DESC(1, AR8236_STATS_RXMAXBYTE, "RxMaxByte"), |
||
107 | MIB_DESC(1, AR8236_STATS_RXTOOLONG, "RxTooLong"), |
||
108 | MIB_DESC(2, AR8236_STATS_RXGOODBYTE, "RxGoodByte"), |
||
109 | MIB_DESC(2, AR8236_STATS_RXBADBYTE, "RxBadByte"), |
||
110 | MIB_DESC(1, AR8236_STATS_RXOVERFLOW, "RxOverFlow"), |
||
111 | MIB_DESC(1, AR8236_STATS_FILTERED, "Filtered"), |
||
112 | MIB_DESC(1, AR8236_STATS_TXBROAD, "TxBroad"), |
||
113 | MIB_DESC(1, AR8236_STATS_TXPAUSE, "TxPause"), |
||
114 | MIB_DESC(1, AR8236_STATS_TXMULTI, "TxMulti"), |
||
115 | MIB_DESC(1, AR8236_STATS_TXUNDERRUN, "TxUnderRun"), |
||
116 | MIB_DESC(1, AR8236_STATS_TX64BYTE, "Tx64Byte"), |
||
117 | MIB_DESC(1, AR8236_STATS_TX128BYTE, "Tx128Byte"), |
||
118 | MIB_DESC(1, AR8236_STATS_TX256BYTE, "Tx256Byte"), |
||
119 | MIB_DESC(1, AR8236_STATS_TX512BYTE, "Tx512Byte"), |
||
120 | MIB_DESC(1, AR8236_STATS_TX1024BYTE, "Tx1024Byte"), |
||
121 | MIB_DESC(1, AR8236_STATS_TX1518BYTE, "Tx1518Byte"), |
||
122 | MIB_DESC(1, AR8236_STATS_TXMAXBYTE, "TxMaxByte"), |
||
123 | MIB_DESC(1, AR8236_STATS_TXOVERSIZE, "TxOverSize"), |
||
124 | MIB_DESC(2, AR8236_STATS_TXBYTE, "TxByte"), |
||
125 | MIB_DESC(1, AR8236_STATS_TXCOLLISION, "TxCollision"), |
||
126 | MIB_DESC(1, AR8236_STATS_TXABORTCOL, "TxAbortCol"), |
||
127 | MIB_DESC(1, AR8236_STATS_TXMULTICOL, "TxMultiCol"), |
||
128 | MIB_DESC(1, AR8236_STATS_TXSINGLECOL, "TxSingleCol"), |
||
129 | MIB_DESC(1, AR8236_STATS_TXEXCDEFER, "TxExcDefer"), |
||
130 | MIB_DESC(1, AR8236_STATS_TXDEFER, "TxDefer"), |
||
131 | MIB_DESC(1, AR8236_STATS_TXLATECOL, "TxLateCol"), |
||
132 | }; |
||
133 | |||
134 | static DEFINE_MUTEX(ar8xxx_dev_list_lock); |
||
135 | static LIST_HEAD(ar8xxx_dev_list); |
||
136 | |||
137 | /* inspired by phy_poll_reset in drivers/net/phy/phy_device.c */ |
||
138 | static int |
||
139 | ar8xxx_phy_poll_reset(struct mii_bus *bus) |
||
140 | { |
||
141 | unsigned int sleep_msecs = 20; |
||
142 | int ret, elapsed, i; |
||
143 | |||
144 | for (elapsed = sleep_msecs; elapsed <= 600; |
||
145 | elapsed += sleep_msecs) { |
||
146 | msleep(sleep_msecs); |
||
147 | for (i = 0; i < AR8XXX_NUM_PHYS; i++) { |
||
148 | ret = mdiobus_read(bus, i, MII_BMCR); |
||
149 | if (ret < 0) |
||
150 | return ret; |
||
151 | if (ret & BMCR_RESET) |
||
152 | break; |
||
153 | if (i == AR8XXX_NUM_PHYS - 1) { |
||
154 | usleep_range(1000, 2000); |
||
155 | return 0; |
||
156 | } |
||
157 | } |
||
158 | } |
||
159 | return -ETIMEDOUT; |
||
160 | } |
||
161 | |||
162 | static int |
||
163 | ar8xxx_phy_check_aneg(struct phy_device *phydev) |
||
164 | { |
||
165 | int ret; |
||
166 | |||
167 | if (phydev->autoneg != AUTONEG_ENABLE) |
||
168 | return 0; |
||
169 | /* |
||
170 | * BMCR_ANENABLE might have been cleared |
||
171 | * by phy_init_hw in certain kernel versions |
||
172 | * therefore check for it |
||
173 | */ |
||
174 | ret = phy_read(phydev, MII_BMCR); |
||
175 | if (ret < 0) |
||
176 | return ret; |
||
177 | if (ret & BMCR_ANENABLE) |
||
178 | return 0; |
||
179 | |||
180 | dev_info(&phydev->mdio.dev, "ANEG disabled, re-enabling ...\n"); |
||
181 | ret |= BMCR_ANENABLE | BMCR_ANRESTART; |
||
182 | return phy_write(phydev, MII_BMCR, ret); |
||
183 | } |
||
184 | |||
185 | void |
||
186 | ar8xxx_phy_init(struct ar8xxx_priv *priv) |
||
187 | { |
||
188 | int i; |
||
189 | struct mii_bus *bus; |
||
190 | |||
191 | bus = priv->mii_bus; |
||
192 | for (i = 0; i < AR8XXX_NUM_PHYS; i++) { |
||
193 | if (priv->chip->phy_fixup) |
||
194 | priv->chip->phy_fixup(priv, i); |
||
195 | |||
196 | /* initialize the port itself */ |
||
197 | mdiobus_write(bus, i, MII_ADVERTISE, |
||
198 | ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); |
||
199 | if (ar8xxx_has_gige(priv)) |
||
200 | mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); |
||
201 | mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); |
||
202 | } |
||
203 | |||
204 | ar8xxx_phy_poll_reset(bus); |
||
205 | } |
||
206 | |||
207 | u32 |
||
208 | ar8xxx_mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum) |
||
209 | { |
||
210 | struct mii_bus *bus = priv->mii_bus; |
||
211 | u16 lo, hi; |
||
212 | |||
213 | lo = bus->read(bus, phy_id, regnum); |
||
214 | hi = bus->read(bus, phy_id, regnum + 1); |
||
215 | |||
216 | return (hi << 16) | lo; |
||
217 | } |
||
218 | |||
219 | void |
||
220 | ar8xxx_mii_write32(struct ar8xxx_priv *priv, int phy_id, int regnum, u32 val) |
||
221 | { |
||
222 | struct mii_bus *bus = priv->mii_bus; |
||
223 | u16 lo, hi; |
||
224 | |||
225 | lo = val & 0xffff; |
||
226 | hi = (u16) (val >> 16); |
||
227 | |||
228 | if (priv->chip->mii_lo_first) |
||
229 | { |
||
230 | bus->write(bus, phy_id, regnum, lo); |
||
231 | bus->write(bus, phy_id, regnum + 1, hi); |
||
232 | } else { |
||
233 | bus->write(bus, phy_id, regnum + 1, hi); |
||
234 | bus->write(bus, phy_id, regnum, lo); |
||
235 | } |
||
236 | } |
||
237 | |||
238 | u32 |
||
239 | ar8xxx_read(struct ar8xxx_priv *priv, int reg) |
||
240 | { |
||
241 | struct mii_bus *bus = priv->mii_bus; |
||
242 | u16 r1, r2, page; |
||
243 | u32 val; |
||
244 | |||
245 | split_addr((u32) reg, &r1, &r2, &page); |
||
246 | |||
247 | mutex_lock(&bus->mdio_lock); |
||
248 | |||
249 | bus->write(bus, 0x18, 0, page); |
||
250 | wait_for_page_switch(); |
||
251 | val = ar8xxx_mii_read32(priv, 0x10 | r2, r1); |
||
252 | |||
253 | mutex_unlock(&bus->mdio_lock); |
||
254 | |||
255 | return val; |
||
256 | } |
||
257 | |||
258 | void |
||
259 | ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val) |
||
260 | { |
||
261 | struct mii_bus *bus = priv->mii_bus; |
||
262 | u16 r1, r2, page; |
||
263 | |||
264 | split_addr((u32) reg, &r1, &r2, &page); |
||
265 | |||
266 | mutex_lock(&bus->mdio_lock); |
||
267 | |||
268 | bus->write(bus, 0x18, 0, page); |
||
269 | wait_for_page_switch(); |
||
270 | ar8xxx_mii_write32(priv, 0x10 | r2, r1, val); |
||
271 | |||
272 | mutex_unlock(&bus->mdio_lock); |
||
273 | } |
||
274 | |||
275 | u32 |
||
276 | ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val) |
||
277 | { |
||
278 | struct mii_bus *bus = priv->mii_bus; |
||
279 | u16 r1, r2, page; |
||
280 | u32 ret; |
||
281 | |||
282 | split_addr((u32) reg, &r1, &r2, &page); |
||
283 | |||
284 | mutex_lock(&bus->mdio_lock); |
||
285 | |||
286 | bus->write(bus, 0x18, 0, page); |
||
287 | wait_for_page_switch(); |
||
288 | |||
289 | ret = ar8xxx_mii_read32(priv, 0x10 | r2, r1); |
||
290 | ret &= ~mask; |
||
291 | ret |= val; |
||
292 | ar8xxx_mii_write32(priv, 0x10 | r2, r1, ret); |
||
293 | |||
294 | mutex_unlock(&bus->mdio_lock); |
||
295 | |||
296 | return ret; |
||
297 | } |
||
298 | |||
299 | void |
||
300 | ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr, |
||
301 | u16 dbg_addr, u16 dbg_data) |
||
302 | { |
||
303 | struct mii_bus *bus = priv->mii_bus; |
||
304 | |||
305 | mutex_lock(&bus->mdio_lock); |
||
306 | bus->write(bus, phy_addr, MII_ATH_DBG_ADDR, dbg_addr); |
||
307 | bus->write(bus, phy_addr, MII_ATH_DBG_DATA, dbg_data); |
||
308 | mutex_unlock(&bus->mdio_lock); |
||
309 | } |
||
310 | |||
311 | static inline void |
||
312 | ar8xxx_phy_mmd_prep(struct mii_bus *bus, int phy_addr, u16 addr, u16 reg) |
||
313 | { |
||
314 | bus->write(bus, phy_addr, MII_ATH_MMD_ADDR, addr); |
||
315 | bus->write(bus, phy_addr, MII_ATH_MMD_DATA, reg); |
||
316 | bus->write(bus, phy_addr, MII_ATH_MMD_ADDR, addr | 0x4000); |
||
317 | } |
||
318 | |||
319 | void |
||
320 | ar8xxx_phy_mmd_write(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg, u16 data) |
||
321 | { |
||
322 | struct mii_bus *bus = priv->mii_bus; |
||
323 | |||
324 | mutex_lock(&bus->mdio_lock); |
||
325 | ar8xxx_phy_mmd_prep(bus, phy_addr, addr, reg); |
||
326 | bus->write(bus, phy_addr, MII_ATH_MMD_DATA, data); |
||
327 | mutex_unlock(&bus->mdio_lock); |
||
328 | } |
||
329 | |||
330 | u16 |
||
331 | ar8xxx_phy_mmd_read(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg) |
||
332 | { |
||
333 | struct mii_bus *bus = priv->mii_bus; |
||
334 | u16 data; |
||
335 | |||
336 | mutex_lock(&bus->mdio_lock); |
||
337 | ar8xxx_phy_mmd_prep(bus, phy_addr, addr, reg); |
||
338 | data = bus->read(bus, phy_addr, MII_ATH_MMD_DATA); |
||
339 | mutex_unlock(&bus->mdio_lock); |
||
340 | |||
341 | return data; |
||
342 | } |
||
343 | |||
344 | static int |
||
345 | ar8xxx_reg_wait(struct ar8xxx_priv *priv, u32 reg, u32 mask, u32 val, |
||
346 | unsigned timeout) |
||
347 | { |
||
348 | int i; |
||
349 | |||
350 | for (i = 0; i < timeout; i++) { |
||
351 | u32 t; |
||
352 | |||
353 | t = ar8xxx_read(priv, reg); |
||
354 | if ((t & mask) == val) |
||
355 | return 0; |
||
356 | |||
357 | usleep_range(1000, 2000); |
||
358 | cond_resched(); |
||
359 | } |
||
360 | |||
361 | return -ETIMEDOUT; |
||
362 | } |
||
363 | |||
364 | static int |
||
365 | ar8xxx_mib_op(struct ar8xxx_priv *priv, u32 op) |
||
366 | { |
||
367 | unsigned mib_func = priv->chip->mib_func; |
||
368 | int ret; |
||
369 | |||
370 | lockdep_assert_held(&priv->mib_lock); |
||
371 | |||
372 | /* Capture the hardware statistics for all ports */ |
||
373 | ar8xxx_rmw(priv, mib_func, AR8216_MIB_FUNC, (op << AR8216_MIB_FUNC_S)); |
||
374 | |||
375 | /* Wait for the capturing to complete. */ |
||
376 | ret = ar8xxx_reg_wait(priv, mib_func, AR8216_MIB_BUSY, 0, 10); |
||
377 | if (ret) |
||
378 | goto out; |
||
379 | |||
380 | ret = 0; |
||
381 | |||
382 | out: |
||
383 | return ret; |
||
384 | } |
||
385 | |||
386 | static int |
||
387 | ar8xxx_mib_capture(struct ar8xxx_priv *priv) |
||
388 | { |
||
389 | return ar8xxx_mib_op(priv, AR8216_MIB_FUNC_CAPTURE); |
||
390 | } |
||
391 | |||
392 | static int |
||
393 | ar8xxx_mib_flush(struct ar8xxx_priv *priv) |
||
394 | { |
||
395 | return ar8xxx_mib_op(priv, AR8216_MIB_FUNC_FLUSH); |
||
396 | } |
||
397 | |||
398 | static void |
||
399 | ar8xxx_mib_fetch_port_stat(struct ar8xxx_priv *priv, int port, bool flush) |
||
400 | { |
||
401 | unsigned int base; |
||
402 | u64 *mib_stats; |
||
403 | int i; |
||
404 | |||
405 | WARN_ON(port >= priv->dev.ports); |
||
406 | |||
407 | lockdep_assert_held(&priv->mib_lock); |
||
408 | |||
409 | base = priv->chip->reg_port_stats_start + |
||
410 | priv->chip->reg_port_stats_length * port; |
||
411 | |||
412 | mib_stats = &priv->mib_stats[port * priv->chip->num_mibs]; |
||
413 | for (i = 0; i < priv->chip->num_mibs; i++) { |
||
414 | const struct ar8xxx_mib_desc *mib; |
||
415 | u64 t; |
||
416 | |||
417 | mib = &priv->chip->mib_decs[i]; |
||
418 | t = ar8xxx_read(priv, base + mib->offset); |
||
419 | if (mib->size == 2) { |
||
420 | u64 hi; |
||
421 | |||
422 | hi = ar8xxx_read(priv, base + mib->offset + 4); |
||
423 | t |= hi << 32; |
||
424 | } |
||
425 | |||
426 | if (flush) |
||
427 | mib_stats[i] = 0; |
||
428 | else |
||
429 | mib_stats[i] += t; |
||
430 | cond_resched(); |
||
431 | } |
||
432 | } |
||
433 | |||
434 | static void |
||
435 | ar8216_read_port_link(struct ar8xxx_priv *priv, int port, |
||
436 | struct switch_port_link *link) |
||
437 | { |
||
438 | u32 status; |
||
439 | u32 speed; |
||
440 | |||
441 | memset(link, '\0', sizeof(*link)); |
||
442 | |||
443 | status = priv->chip->read_port_status(priv, port); |
||
444 | |||
445 | link->aneg = !!(status & AR8216_PORT_STATUS_LINK_AUTO); |
||
446 | if (link->aneg) { |
||
447 | link->link = !!(status & AR8216_PORT_STATUS_LINK_UP); |
||
448 | } else { |
||
449 | link->link = true; |
||
450 | |||
451 | if (priv->get_port_link) { |
||
452 | int err; |
||
453 | |||
454 | err = priv->get_port_link(port); |
||
455 | if (err >= 0) |
||
456 | link->link = !!err; |
||
457 | } |
||
458 | } |
||
459 | |||
460 | if (!link->link) |
||
461 | return; |
||
462 | |||
463 | link->duplex = !!(status & AR8216_PORT_STATUS_DUPLEX); |
||
464 | link->tx_flow = !!(status & AR8216_PORT_STATUS_TXFLOW); |
||
465 | link->rx_flow = !!(status & AR8216_PORT_STATUS_RXFLOW); |
||
466 | |||
467 | if (link->aneg && link->duplex && priv->chip->read_port_eee_status) |
||
468 | link->eee = priv->chip->read_port_eee_status(priv, port); |
||
469 | |||
470 | speed = (status & AR8216_PORT_STATUS_SPEED) >> |
||
471 | AR8216_PORT_STATUS_SPEED_S; |
||
472 | |||
473 | switch (speed) { |
||
474 | case AR8216_PORT_SPEED_10M: |
||
475 | link->speed = SWITCH_PORT_SPEED_10; |
||
476 | break; |
||
477 | case AR8216_PORT_SPEED_100M: |
||
478 | link->speed = SWITCH_PORT_SPEED_100; |
||
479 | break; |
||
480 | case AR8216_PORT_SPEED_1000M: |
||
481 | link->speed = SWITCH_PORT_SPEED_1000; |
||
482 | break; |
||
483 | default: |
||
484 | link->speed = SWITCH_PORT_SPEED_UNKNOWN; |
||
485 | break; |
||
486 | } |
||
487 | } |
||
488 | |||
489 | static struct sk_buff * |
||
490 | ar8216_mangle_tx(struct net_device *dev, struct sk_buff *skb) |
||
491 | { |
||
492 | struct ar8xxx_priv *priv = dev->phy_ptr; |
||
493 | unsigned char *buf; |
||
494 | |||
495 | if (unlikely(!priv)) |
||
496 | goto error; |
||
497 | |||
498 | if (!priv->vlan) |
||
499 | goto send; |
||
500 | |||
501 | if (unlikely(skb_headroom(skb) < 2)) { |
||
502 | if (pskb_expand_head(skb, 2, 0, GFP_ATOMIC) < 0) |
||
503 | goto error; |
||
504 | } |
||
505 | |||
506 | buf = skb_push(skb, 2); |
||
507 | buf[0] = 0x10; |
||
508 | buf[1] = 0x80; |
||
509 | |||
510 | send: |
||
511 | return skb; |
||
512 | |||
513 | error: |
||
514 | dev_kfree_skb_any(skb); |
||
515 | return NULL; |
||
516 | } |
||
517 | |||
518 | static void |
||
519 | ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb) |
||
520 | { |
||
521 | struct ar8xxx_priv *priv; |
||
522 | unsigned char *buf; |
||
523 | int port, vlan; |
||
524 | |||
525 | priv = dev->phy_ptr; |
||
526 | if (!priv) |
||
527 | return; |
||
528 | |||
529 | /* don't strip the header if vlan mode is disabled */ |
||
530 | if (!priv->vlan) |
||
531 | return; |
||
532 | |||
533 | /* strip header, get vlan id */ |
||
534 | buf = skb->data; |
||
535 | skb_pull(skb, 2); |
||
536 | |||
537 | /* check for vlan header presence */ |
||
538 | if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00)) |
||
539 | return; |
||
540 | |||
541 | port = buf[0] & 0x7; |
||
542 | |||
543 | /* no need to fix up packets coming from a tagged source */ |
||
544 | if (priv->vlan_tagged & (1 << port)) |
||
545 | return; |
||
546 | |||
547 | /* lookup port vid from local table, the switch passes an invalid vlan id */ |
||
548 | vlan = priv->vlan_id[priv->pvid[port]]; |
||
549 | |||
550 | buf[14 + 2] &= 0xf0; |
||
551 | buf[14 + 2] |= vlan >> 8; |
||
552 | buf[15 + 2] = vlan & 0xff; |
||
553 | } |
||
554 | |||
555 | int |
||
556 | ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val) |
||
557 | { |
||
558 | int timeout = 20; |
||
559 | u32 t = 0; |
||
560 | |||
561 | while (1) { |
||
562 | t = ar8xxx_read(priv, reg); |
||
563 | if ((t & mask) == val) |
||
564 | return 0; |
||
565 | |||
566 | if (timeout-- <= 0) |
||
567 | break; |
||
568 | |||
569 | udelay(10); |
||
570 | cond_resched(); |
||
571 | } |
||
572 | |||
573 | pr_err("ar8216: timeout on reg %08x: %08x & %08x != %08x\n", |
||
574 | (unsigned int) reg, t, mask, val); |
||
575 | return -ETIMEDOUT; |
||
576 | } |
||
577 | |||
578 | static void |
||
579 | ar8216_vtu_op(struct ar8xxx_priv *priv, u32 op, u32 val) |
||
580 | { |
||
581 | if (ar8216_wait_bit(priv, AR8216_REG_VTU, AR8216_VTU_ACTIVE, 0)) |
||
582 | return; |
||
583 | if ((op & AR8216_VTU_OP) == AR8216_VTU_OP_LOAD) { |
||
584 | val &= AR8216_VTUDATA_MEMBER; |
||
585 | val |= AR8216_VTUDATA_VALID; |
||
586 | ar8xxx_write(priv, AR8216_REG_VTU_DATA, val); |
||
587 | } |
||
588 | op |= AR8216_VTU_ACTIVE; |
||
589 | ar8xxx_write(priv, AR8216_REG_VTU, op); |
||
590 | } |
||
591 | |||
592 | static void |
||
593 | ar8216_vtu_flush(struct ar8xxx_priv *priv) |
||
594 | { |
||
595 | ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); |
||
596 | } |
||
597 | |||
598 | static void |
||
599 | ar8216_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) |
||
600 | { |
||
601 | u32 op; |
||
602 | |||
603 | op = AR8216_VTU_OP_LOAD | (vid << AR8216_VTU_VID_S); |
||
604 | ar8216_vtu_op(priv, op, port_mask); |
||
605 | } |
||
606 | |||
607 | static int |
||
608 | ar8216_atu_flush(struct ar8xxx_priv *priv) |
||
609 | { |
||
610 | int ret; |
||
611 | |||
612 | ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0); |
||
613 | if (!ret) |
||
614 | ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_OP_FLUSH | |
||
615 | AR8216_ATU_ACTIVE); |
||
616 | |||
617 | return ret; |
||
618 | } |
||
619 | |||
620 | static int |
||
621 | ar8216_atu_flush_port(struct ar8xxx_priv *priv, int port) |
||
622 | { |
||
623 | u32 t; |
||
624 | int ret; |
||
625 | |||
626 | ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0); |
||
627 | if (!ret) { |
||
628 | t = (port << AR8216_ATU_PORT_NUM_S) | AR8216_ATU_OP_FLUSH_PORT; |
||
629 | t |= AR8216_ATU_ACTIVE; |
||
630 | ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, t); |
||
631 | } |
||
632 | |||
633 | return ret; |
||
634 | } |
||
635 | |||
636 | static u32 |
||
637 | ar8216_read_port_status(struct ar8xxx_priv *priv, int port) |
||
638 | { |
||
639 | return ar8xxx_read(priv, AR8216_REG_PORT_STATUS(port)); |
||
640 | } |
||
641 | |||
642 | static void |
||
643 | ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members) |
||
644 | { |
||
645 | u32 header; |
||
646 | u32 egress, ingress; |
||
647 | u32 pvid; |
||
648 | |||
649 | if (priv->vlan) { |
||
650 | pvid = priv->vlan_id[priv->pvid[port]]; |
||
651 | if (priv->vlan_tagged & (1 << port)) |
||
652 | egress = AR8216_OUT_ADD_VLAN; |
||
653 | else |
||
654 | egress = AR8216_OUT_STRIP_VLAN; |
||
655 | ingress = AR8216_IN_SECURE; |
||
656 | } else { |
||
657 | pvid = port; |
||
658 | egress = AR8216_OUT_KEEP; |
||
659 | ingress = AR8216_IN_PORT_ONLY; |
||
660 | } |
||
661 | |||
662 | if (chip_is_ar8216(priv) && priv->vlan && port == AR8216_PORT_CPU) |
||
663 | header = AR8216_PORT_CTRL_HEADER; |
||
664 | else |
||
665 | header = 0; |
||
666 | |||
667 | ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), |
||
668 | AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | |
||
669 | AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | |
||
670 | AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, |
||
671 | AR8216_PORT_CTRL_LEARN | header | |
||
672 | (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | |
||
673 | (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); |
||
674 | |||
675 | ar8xxx_rmw(priv, AR8216_REG_PORT_VLAN(port), |
||
676 | AR8216_PORT_VLAN_DEST_PORTS | AR8216_PORT_VLAN_MODE | |
||
677 | AR8216_PORT_VLAN_DEFAULT_ID, |
||
678 | (members << AR8216_PORT_VLAN_DEST_PORTS_S) | |
||
679 | (ingress << AR8216_PORT_VLAN_MODE_S) | |
||
680 | (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S)); |
||
681 | } |
||
682 | |||
683 | static int |
||
684 | ar8216_hw_init(struct ar8xxx_priv *priv) |
||
685 | { |
||
686 | if (priv->initialized) |
||
687 | return 0; |
||
688 | |||
689 | ar8xxx_phy_init(priv); |
||
690 | |||
691 | priv->initialized = true; |
||
692 | return 0; |
||
693 | } |
||
694 | |||
695 | static void |
||
696 | ar8216_init_globals(struct ar8xxx_priv *priv) |
||
697 | { |
||
698 | /* standard atheros magic */ |
||
699 | ar8xxx_write(priv, 0x38, 0xc000050e); |
||
700 | |||
701 | ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, |
||
702 | AR8216_GCTRL_MTU, 1518 + 8 + 2); |
||
703 | } |
||
704 | |||
705 | static void |
||
706 | ar8216_init_port(struct ar8xxx_priv *priv, int port) |
||
707 | { |
||
708 | /* Enable port learning and tx */ |
||
709 | ar8xxx_write(priv, AR8216_REG_PORT_CTRL(port), |
||
710 | AR8216_PORT_CTRL_LEARN | |
||
711 | (4 << AR8216_PORT_CTRL_STATE_S)); |
||
712 | |||
713 | ar8xxx_write(priv, AR8216_REG_PORT_VLAN(port), 0); |
||
714 | |||
715 | if (port == AR8216_PORT_CPU) { |
||
716 | ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), |
||
717 | AR8216_PORT_STATUS_LINK_UP | |
||
718 | (ar8xxx_has_gige(priv) ? |
||
719 | AR8216_PORT_SPEED_1000M : AR8216_PORT_SPEED_100M) | |
||
720 | AR8216_PORT_STATUS_TXMAC | |
||
721 | AR8216_PORT_STATUS_RXMAC | |
||
722 | (chip_is_ar8316(priv) ? AR8216_PORT_STATUS_RXFLOW : 0) | |
||
723 | (chip_is_ar8316(priv) ? AR8216_PORT_STATUS_TXFLOW : 0) | |
||
724 | AR8216_PORT_STATUS_DUPLEX); |
||
725 | } else { |
||
726 | ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), |
||
727 | AR8216_PORT_STATUS_LINK_AUTO); |
||
728 | } |
||
729 | } |
||
730 | |||
731 | static void |
||
732 | ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) |
||
733 | { |
||
734 | int timeout = 20; |
||
735 | |||
736 | while (ar8xxx_mii_read32(priv, r2, r1) & AR8216_ATU_ACTIVE && --timeout) { |
||
737 | udelay(10); |
||
738 | cond_resched(); |
||
739 | } |
||
740 | |||
741 | if (!timeout) |
||
742 | pr_err("ar8216: timeout waiting for atu to become ready\n"); |
||
743 | } |
||
744 | |||
745 | static void ar8216_get_arl_entry(struct ar8xxx_priv *priv, |
||
746 | struct arl_entry *a, u32 *status, enum arl_op op) |
||
747 | { |
||
748 | struct mii_bus *bus = priv->mii_bus; |
||
749 | u16 r2, page; |
||
750 | u16 r1_func0, r1_func1, r1_func2; |
||
751 | u32 t, val0, val1, val2; |
||
3 | office | 752 | int i; |
1 | office | 753 | |
754 | split_addr(AR8216_REG_ATU_FUNC0, &r1_func0, &r2, &page); |
||
755 | r2 |= 0x10; |
||
756 | |||
757 | r1_func1 = (AR8216_REG_ATU_FUNC1 >> 1) & 0x1e; |
||
758 | r1_func2 = (AR8216_REG_ATU_FUNC2 >> 1) & 0x1e; |
||
759 | |||
760 | switch (op) { |
||
761 | case AR8XXX_ARL_INITIALIZE: |
||
762 | /* all ATU registers are on the same page |
||
763 | * therefore set page only once |
||
764 | */ |
||
765 | bus->write(bus, 0x18, 0, page); |
||
766 | wait_for_page_switch(); |
||
767 | |||
768 | ar8216_wait_atu_ready(priv, r2, r1_func0); |
||
769 | |||
770 | ar8xxx_mii_write32(priv, r2, r1_func0, AR8216_ATU_OP_GET_NEXT); |
||
771 | ar8xxx_mii_write32(priv, r2, r1_func1, 0); |
||
772 | ar8xxx_mii_write32(priv, r2, r1_func2, 0); |
||
773 | break; |
||
774 | case AR8XXX_ARL_GET_NEXT: |
||
775 | t = ar8xxx_mii_read32(priv, r2, r1_func0); |
||
776 | t |= AR8216_ATU_ACTIVE; |
||
777 | ar8xxx_mii_write32(priv, r2, r1_func0, t); |
||
778 | ar8216_wait_atu_ready(priv, r2, r1_func0); |
||
779 | |||
780 | val0 = ar8xxx_mii_read32(priv, r2, r1_func0); |
||
781 | val1 = ar8xxx_mii_read32(priv, r2, r1_func1); |
||
782 | val2 = ar8xxx_mii_read32(priv, r2, r1_func2); |
||
783 | |||
784 | *status = (val2 & AR8216_ATU_STATUS) >> AR8216_ATU_STATUS_S; |
||
785 | if (!*status) |
||
786 | break; |
||
787 | |||
3 | office | 788 | i = 0; |
789 | t = AR8216_ATU_PORT0; |
||
790 | while (!(val2 & t) && ++i < priv->dev.ports) |
||
791 | t <<= 1; |
||
792 | |||
793 | a->port = i; |
||
1 | office | 794 | a->mac[0] = (val0 & AR8216_ATU_ADDR5) >> AR8216_ATU_ADDR5_S; |
795 | a->mac[1] = (val0 & AR8216_ATU_ADDR4) >> AR8216_ATU_ADDR4_S; |
||
796 | a->mac[2] = (val1 & AR8216_ATU_ADDR3) >> AR8216_ATU_ADDR3_S; |
||
797 | a->mac[3] = (val1 & AR8216_ATU_ADDR2) >> AR8216_ATU_ADDR2_S; |
||
798 | a->mac[4] = (val1 & AR8216_ATU_ADDR1) >> AR8216_ATU_ADDR1_S; |
||
799 | a->mac[5] = (val1 & AR8216_ATU_ADDR0) >> AR8216_ATU_ADDR0_S; |
||
800 | break; |
||
801 | } |
||
802 | } |
||
803 | |||
804 | static void |
||
805 | ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) |
||
806 | { |
||
807 | u32 egress, ingress; |
||
808 | u32 pvid; |
||
809 | |||
810 | if (priv->vlan) { |
||
811 | pvid = priv->vlan_id[priv->pvid[port]]; |
||
812 | if (priv->vlan_tagged & (1 << port)) |
||
813 | egress = AR8216_OUT_ADD_VLAN; |
||
814 | else |
||
815 | egress = AR8216_OUT_STRIP_VLAN; |
||
816 | ingress = AR8216_IN_SECURE; |
||
817 | } else { |
||
818 | pvid = port; |
||
819 | egress = AR8216_OUT_KEEP; |
||
820 | ingress = AR8216_IN_PORT_ONLY; |
||
821 | } |
||
822 | |||
823 | ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), |
||
824 | AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | |
||
825 | AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | |
||
826 | AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, |
||
827 | AR8216_PORT_CTRL_LEARN | |
||
828 | (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | |
||
829 | (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); |
||
830 | |||
831 | ar8xxx_rmw(priv, AR8236_REG_PORT_VLAN(port), |
||
832 | AR8236_PORT_VLAN_DEFAULT_ID, |
||
833 | (pvid << AR8236_PORT_VLAN_DEFAULT_ID_S)); |
||
834 | |||
835 | ar8xxx_rmw(priv, AR8236_REG_PORT_VLAN2(port), |
||
836 | AR8236_PORT_VLAN2_VLAN_MODE | |
||
837 | AR8236_PORT_VLAN2_MEMBER, |
||
838 | (ingress << AR8236_PORT_VLAN2_VLAN_MODE_S) | |
||
839 | (members << AR8236_PORT_VLAN2_MEMBER_S)); |
||
840 | } |
||
841 | |||
842 | static void |
||
843 | ar8236_init_globals(struct ar8xxx_priv *priv) |
||
844 | { |
||
845 | /* enable jumbo frames */ |
||
846 | ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, |
||
847 | AR8316_GCTRL_MTU, 9018 + 8 + 2); |
||
848 | |||
849 | /* enable cpu port to receive arp frames */ |
||
850 | ar8xxx_reg_set(priv, AR8216_REG_ATU_CTRL, |
||
851 | AR8236_ATU_CTRL_RES); |
||
852 | |||
853 | /* enable cpu port to receive multicast and broadcast frames */ |
||
854 | ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK, |
||
855 | AR8236_FM_CPU_BROADCAST_EN | AR8236_FM_CPU_BCAST_FWD_EN); |
||
856 | |||
857 | /* Enable MIB counters */ |
||
858 | ar8xxx_rmw(priv, AR8216_REG_MIB_FUNC, AR8216_MIB_FUNC | AR8236_MIB_EN, |
||
859 | (AR8216_MIB_FUNC_NO_OP << AR8216_MIB_FUNC_S) | |
||
860 | AR8236_MIB_EN); |
||
861 | } |
||
862 | |||
863 | static int |
||
864 | ar8316_hw_init(struct ar8xxx_priv *priv) |
||
865 | { |
||
866 | u32 val, newval; |
||
867 | |||
868 | val = ar8xxx_read(priv, AR8316_REG_POSTRIP); |
||
869 | |||
870 | if (priv->phy->interface == PHY_INTERFACE_MODE_RGMII) { |
||
871 | if (priv->port4_phy) { |
||
872 | /* value taken from Ubiquiti RouterStation Pro */ |
||
873 | newval = 0x81461bea; |
||
874 | pr_info("ar8316: Using port 4 as PHY\n"); |
||
875 | } else { |
||
876 | newval = 0x01261be2; |
||
877 | pr_info("ar8316: Using port 4 as switch port\n"); |
||
878 | } |
||
879 | } else if (priv->phy->interface == PHY_INTERFACE_MODE_GMII) { |
||
880 | /* value taken from AVM Fritz!Box 7390 sources */ |
||
881 | newval = 0x010e5b71; |
||
882 | } else { |
||
883 | /* no known value for phy interface */ |
||
884 | pr_err("ar8316: unsupported mii mode: %d.\n", |
||
885 | priv->phy->interface); |
||
886 | return -EINVAL; |
||
887 | } |
||
888 | |||
889 | if (val == newval) |
||
890 | goto out; |
||
891 | |||
892 | ar8xxx_write(priv, AR8316_REG_POSTRIP, newval); |
||
893 | |||
894 | if (priv->port4_phy && |
||
895 | priv->phy->interface == PHY_INTERFACE_MODE_RGMII) { |
||
896 | /* work around for phy4 rgmii mode */ |
||
897 | ar8xxx_phy_dbg_write(priv, 4, 0x12, 0x480c); |
||
898 | /* rx delay */ |
||
899 | ar8xxx_phy_dbg_write(priv, 4, 0x0, 0x824e); |
||
900 | /* tx delay */ |
||
901 | ar8xxx_phy_dbg_write(priv, 4, 0x5, 0x3d47); |
||
902 | msleep(1000); |
||
903 | } |
||
904 | |||
905 | ar8xxx_phy_init(priv); |
||
906 | |||
907 | out: |
||
908 | priv->initialized = true; |
||
909 | return 0; |
||
910 | } |
||
911 | |||
912 | static void |
||
913 | ar8316_init_globals(struct ar8xxx_priv *priv) |
||
914 | { |
||
915 | /* standard atheros magic */ |
||
916 | ar8xxx_write(priv, 0x38, 0xc000050e); |
||
917 | |||
918 | /* enable cpu port to receive multicast and broadcast frames */ |
||
919 | ar8xxx_write(priv, AR8216_REG_FLOOD_MASK, 0x003f003f); |
||
920 | |||
921 | /* enable jumbo frames */ |
||
922 | ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, |
||
923 | AR8316_GCTRL_MTU, 9018 + 8 + 2); |
||
924 | |||
925 | /* Enable MIB counters */ |
||
926 | ar8xxx_rmw(priv, AR8216_REG_MIB_FUNC, AR8216_MIB_FUNC | AR8236_MIB_EN, |
||
927 | (AR8216_MIB_FUNC_NO_OP << AR8216_MIB_FUNC_S) | |
||
928 | AR8236_MIB_EN); |
||
929 | } |
||
930 | |||
931 | int |
||
932 | ar8xxx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, |
||
933 | struct switch_val *val) |
||
934 | { |
||
935 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
936 | priv->vlan = !!val->value.i; |
||
937 | return 0; |
||
938 | } |
||
939 | |||
940 | int |
||
941 | ar8xxx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, |
||
942 | struct switch_val *val) |
||
943 | { |
||
944 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
945 | val->value.i = priv->vlan; |
||
946 | return 0; |
||
947 | } |
||
948 | |||
949 | |||
950 | int |
||
951 | ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) |
||
952 | { |
||
953 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
954 | |||
955 | /* make sure no invalid PVIDs get set */ |
||
956 | |||
957 | if (vlan < 0 || vlan >= dev->vlans || |
||
958 | port < 0 || port >= AR8X16_MAX_PORTS) |
||
959 | return -EINVAL; |
||
960 | |||
961 | priv->pvid[port] = vlan; |
||
962 | return 0; |
||
963 | } |
||
964 | |||
965 | int |
||
966 | ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) |
||
967 | { |
||
968 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
969 | |||
970 | if (port < 0 || port >= AR8X16_MAX_PORTS) |
||
971 | return -EINVAL; |
||
972 | |||
973 | *vlan = priv->pvid[port]; |
||
974 | return 0; |
||
975 | } |
||
976 | |||
977 | static int |
||
978 | ar8xxx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, |
||
979 | struct switch_val *val) |
||
980 | { |
||
981 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
982 | |||
983 | if (val->port_vlan >= AR8X16_MAX_VLANS) |
||
984 | return -EINVAL; |
||
985 | |||
986 | priv->vlan_id[val->port_vlan] = val->value.i; |
||
987 | return 0; |
||
988 | } |
||
989 | |||
990 | static int |
||
991 | ar8xxx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, |
||
992 | struct switch_val *val) |
||
993 | { |
||
994 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
995 | val->value.i = priv->vlan_id[val->port_vlan]; |
||
996 | return 0; |
||
997 | } |
||
998 | |||
999 | int |
||
1000 | ar8xxx_sw_get_port_link(struct switch_dev *dev, int port, |
||
1001 | struct switch_port_link *link) |
||
1002 | { |
||
1003 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1004 | |||
1005 | ar8216_read_port_link(priv, port, link); |
||
1006 | return 0; |
||
1007 | } |
||
1008 | |||
1009 | static int |
||
1010 | ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) |
||
1011 | { |
||
1012 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1013 | u8 ports; |
||
1014 | int i; |
||
1015 | |||
1016 | if (val->port_vlan >= AR8X16_MAX_VLANS) |
||
1017 | return -EINVAL; |
||
1018 | |||
1019 | ports = priv->vlan_table[val->port_vlan]; |
||
1020 | val->len = 0; |
||
1021 | for (i = 0; i < dev->ports; i++) { |
||
1022 | struct switch_port *p; |
||
1023 | |||
1024 | if (!(ports & (1 << i))) |
||
1025 | continue; |
||
1026 | |||
1027 | p = &val->value.ports[val->len++]; |
||
1028 | p->id = i; |
||
1029 | if (priv->vlan_tagged & (1 << i)) |
||
1030 | p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); |
||
1031 | else |
||
1032 | p->flags = 0; |
||
1033 | } |
||
1034 | return 0; |
||
1035 | } |
||
1036 | |||
1037 | static int |
||
1038 | ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) |
||
1039 | { |
||
1040 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1041 | u8 *vt = &priv->vlan_table[val->port_vlan]; |
||
1042 | int i, j; |
||
1043 | |||
1044 | *vt = 0; |
||
1045 | for (i = 0; i < val->len; i++) { |
||
1046 | struct switch_port *p = &val->value.ports[i]; |
||
1047 | |||
1048 | if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { |
||
1049 | priv->vlan_tagged |= (1 << p->id); |
||
1050 | } else { |
||
1051 | priv->vlan_tagged &= ~(1 << p->id); |
||
1052 | priv->pvid[p->id] = val->port_vlan; |
||
1053 | |||
1054 | /* make sure that an untagged port does not |
||
1055 | * appear in other vlans */ |
||
1056 | for (j = 0; j < AR8X16_MAX_VLANS; j++) { |
||
1057 | if (j == val->port_vlan) |
||
1058 | continue; |
||
1059 | priv->vlan_table[j] &= ~(1 << p->id); |
||
1060 | } |
||
1061 | } |
||
1062 | |||
1063 | *vt |= 1 << p->id; |
||
1064 | } |
||
1065 | return 0; |
||
1066 | } |
||
1067 | |||
1068 | static void |
||
1069 | ar8216_set_mirror_regs(struct ar8xxx_priv *priv) |
||
1070 | { |
||
1071 | int port; |
||
1072 | |||
1073 | /* reset all mirror registers */ |
||
1074 | ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CPUPORT, |
||
1075 | AR8216_GLOBAL_CPUPORT_MIRROR_PORT, |
||
1076 | (0xF << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); |
||
1077 | for (port = 0; port < AR8216_NUM_PORTS; port++) { |
||
1078 | ar8xxx_reg_clear(priv, AR8216_REG_PORT_CTRL(port), |
||
1079 | AR8216_PORT_CTRL_MIRROR_RX); |
||
1080 | |||
1081 | ar8xxx_reg_clear(priv, AR8216_REG_PORT_CTRL(port), |
||
1082 | AR8216_PORT_CTRL_MIRROR_TX); |
||
1083 | } |
||
1084 | |||
1085 | /* now enable mirroring if necessary */ |
||
1086 | if (priv->source_port >= AR8216_NUM_PORTS || |
||
1087 | priv->monitor_port >= AR8216_NUM_PORTS || |
||
1088 | priv->source_port == priv->monitor_port) { |
||
1089 | return; |
||
1090 | } |
||
1091 | |||
1092 | ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CPUPORT, |
||
1093 | AR8216_GLOBAL_CPUPORT_MIRROR_PORT, |
||
1094 | (priv->monitor_port << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); |
||
1095 | |||
1096 | if (priv->mirror_rx) |
||
1097 | ar8xxx_reg_set(priv, AR8216_REG_PORT_CTRL(priv->source_port), |
||
1098 | AR8216_PORT_CTRL_MIRROR_RX); |
||
1099 | |||
1100 | if (priv->mirror_tx) |
||
1101 | ar8xxx_reg_set(priv, AR8216_REG_PORT_CTRL(priv->source_port), |
||
1102 | AR8216_PORT_CTRL_MIRROR_TX); |
||
1103 | } |
||
1104 | |||
1105 | static inline u32 |
||
1106 | ar8xxx_age_time_val(int age_time) |
||
1107 | { |
||
1108 | return (age_time + AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS / 2) / |
||
1109 | AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS; |
||
1110 | } |
||
1111 | |||
1112 | static inline void |
||
1113 | ar8xxx_set_age_time(struct ar8xxx_priv *priv, int reg) |
||
1114 | { |
||
1115 | u32 age_time = ar8xxx_age_time_val(priv->arl_age_time); |
||
1116 | ar8xxx_rmw(priv, reg, AR8216_ATU_CTRL_AGE_TIME, age_time << AR8216_ATU_CTRL_AGE_TIME_S); |
||
1117 | } |
||
1118 | |||
1119 | int |
||
1120 | ar8xxx_sw_hw_apply(struct switch_dev *dev) |
||
1121 | { |
||
1122 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1123 | const struct ar8xxx_chip *chip = priv->chip; |
||
1124 | u8 portmask[AR8X16_MAX_PORTS]; |
||
1125 | int i, j; |
||
1126 | |||
1127 | mutex_lock(&priv->reg_mutex); |
||
1128 | /* flush all vlan translation unit entries */ |
||
1129 | priv->chip->vtu_flush(priv); |
||
1130 | |||
1131 | memset(portmask, 0, sizeof(portmask)); |
||
1132 | if (!priv->init) { |
||
1133 | /* calculate the port destination masks and load vlans |
||
1134 | * into the vlan translation unit */ |
||
1135 | for (j = 0; j < AR8X16_MAX_VLANS; j++) { |
||
1136 | u8 vp = priv->vlan_table[j]; |
||
1137 | |||
1138 | if (!vp) |
||
1139 | continue; |
||
1140 | |||
1141 | for (i = 0; i < dev->ports; i++) { |
||
1142 | u8 mask = (1 << i); |
||
1143 | if (vp & mask) |
||
1144 | portmask[i] |= vp & ~mask; |
||
1145 | } |
||
1146 | |||
1147 | chip->vtu_load_vlan(priv, priv->vlan_id[j], |
||
1148 | priv->vlan_table[j]); |
||
1149 | } |
||
1150 | } else { |
||
1151 | /* vlan disabled: |
||
1152 | * isolate all ports, but connect them to the cpu port */ |
||
1153 | for (i = 0; i < dev->ports; i++) { |
||
1154 | if (i == AR8216_PORT_CPU) |
||
1155 | continue; |
||
1156 | |||
1157 | portmask[i] = 1 << AR8216_PORT_CPU; |
||
1158 | portmask[AR8216_PORT_CPU] |= (1 << i); |
||
1159 | } |
||
1160 | } |
||
1161 | |||
1162 | /* update the port destination mask registers and tag settings */ |
||
1163 | for (i = 0; i < dev->ports; i++) { |
||
1164 | chip->setup_port(priv, i, portmask[i]); |
||
1165 | } |
||
1166 | |||
1167 | chip->set_mirror_regs(priv); |
||
1168 | |||
1169 | /* set age time */ |
||
1170 | if (chip->reg_arl_ctrl) |
||
1171 | ar8xxx_set_age_time(priv, chip->reg_arl_ctrl); |
||
1172 | |||
1173 | mutex_unlock(&priv->reg_mutex); |
||
1174 | return 0; |
||
1175 | } |
||
1176 | |||
1177 | int |
||
1178 | ar8xxx_sw_reset_switch(struct switch_dev *dev) |
||
1179 | { |
||
1180 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1181 | const struct ar8xxx_chip *chip = priv->chip; |
||
1182 | int i; |
||
1183 | |||
1184 | mutex_lock(&priv->reg_mutex); |
||
1185 | memset(&priv->vlan, 0, sizeof(struct ar8xxx_priv) - |
||
1186 | offsetof(struct ar8xxx_priv, vlan)); |
||
1187 | |||
1188 | for (i = 0; i < AR8X16_MAX_VLANS; i++) |
||
1189 | priv->vlan_id[i] = i; |
||
1190 | |||
1191 | /* Configure all ports */ |
||
1192 | for (i = 0; i < dev->ports; i++) |
||
1193 | chip->init_port(priv, i); |
||
1194 | |||
1195 | priv->mirror_rx = false; |
||
1196 | priv->mirror_tx = false; |
||
1197 | priv->source_port = 0; |
||
1198 | priv->monitor_port = 0; |
||
1199 | priv->arl_age_time = AR8XXX_DEFAULT_ARL_AGE_TIME; |
||
1200 | |||
1201 | chip->init_globals(priv); |
||
1202 | chip->atu_flush(priv); |
||
1203 | |||
1204 | mutex_unlock(&priv->reg_mutex); |
||
1205 | |||
1206 | return chip->sw_hw_apply(dev); |
||
1207 | } |
||
1208 | |||
1209 | int |
||
1210 | ar8xxx_sw_set_reset_mibs(struct switch_dev *dev, |
||
1211 | const struct switch_attr *attr, |
||
1212 | struct switch_val *val) |
||
1213 | { |
||
1214 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1215 | unsigned int len; |
||
1216 | int ret; |
||
1217 | |||
1218 | if (!ar8xxx_has_mib_counters(priv)) |
||
1219 | return -EOPNOTSUPP; |
||
1220 | |||
1221 | mutex_lock(&priv->mib_lock); |
||
1222 | |||
1223 | len = priv->dev.ports * priv->chip->num_mibs * |
||
1224 | sizeof(*priv->mib_stats); |
||
1225 | memset(priv->mib_stats, '\0', len); |
||
1226 | ret = ar8xxx_mib_flush(priv); |
||
1227 | if (ret) |
||
1228 | goto unlock; |
||
1229 | |||
1230 | ret = 0; |
||
1231 | |||
1232 | unlock: |
||
1233 | mutex_unlock(&priv->mib_lock); |
||
1234 | return ret; |
||
1235 | } |
||
1236 | |||
1237 | int |
||
1238 | ar8xxx_sw_set_mirror_rx_enable(struct switch_dev *dev, |
||
1239 | const struct switch_attr *attr, |
||
1240 | struct switch_val *val) |
||
1241 | { |
||
1242 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1243 | |||
1244 | mutex_lock(&priv->reg_mutex); |
||
1245 | priv->mirror_rx = !!val->value.i; |
||
1246 | priv->chip->set_mirror_regs(priv); |
||
1247 | mutex_unlock(&priv->reg_mutex); |
||
1248 | |||
1249 | return 0; |
||
1250 | } |
||
1251 | |||
1252 | int |
||
1253 | ar8xxx_sw_get_mirror_rx_enable(struct switch_dev *dev, |
||
1254 | const struct switch_attr *attr, |
||
1255 | struct switch_val *val) |
||
1256 | { |
||
1257 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1258 | val->value.i = priv->mirror_rx; |
||
1259 | return 0; |
||
1260 | } |
||
1261 | |||
1262 | int |
||
1263 | ar8xxx_sw_set_mirror_tx_enable(struct switch_dev *dev, |
||
1264 | const struct switch_attr *attr, |
||
1265 | struct switch_val *val) |
||
1266 | { |
||
1267 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1268 | |||
1269 | mutex_lock(&priv->reg_mutex); |
||
1270 | priv->mirror_tx = !!val->value.i; |
||
1271 | priv->chip->set_mirror_regs(priv); |
||
1272 | mutex_unlock(&priv->reg_mutex); |
||
1273 | |||
1274 | return 0; |
||
1275 | } |
||
1276 | |||
1277 | int |
||
1278 | ar8xxx_sw_get_mirror_tx_enable(struct switch_dev *dev, |
||
1279 | const struct switch_attr *attr, |
||
1280 | struct switch_val *val) |
||
1281 | { |
||
1282 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1283 | val->value.i = priv->mirror_tx; |
||
1284 | return 0; |
||
1285 | } |
||
1286 | |||
1287 | int |
||
1288 | ar8xxx_sw_set_mirror_monitor_port(struct switch_dev *dev, |
||
1289 | const struct switch_attr *attr, |
||
1290 | struct switch_val *val) |
||
1291 | { |
||
1292 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1293 | |||
1294 | mutex_lock(&priv->reg_mutex); |
||
1295 | priv->monitor_port = val->value.i; |
||
1296 | priv->chip->set_mirror_regs(priv); |
||
1297 | mutex_unlock(&priv->reg_mutex); |
||
1298 | |||
1299 | return 0; |
||
1300 | } |
||
1301 | |||
1302 | int |
||
1303 | ar8xxx_sw_get_mirror_monitor_port(struct switch_dev *dev, |
||
1304 | const struct switch_attr *attr, |
||
1305 | struct switch_val *val) |
||
1306 | { |
||
1307 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1308 | val->value.i = priv->monitor_port; |
||
1309 | return 0; |
||
1310 | } |
||
1311 | |||
1312 | int |
||
1313 | ar8xxx_sw_set_mirror_source_port(struct switch_dev *dev, |
||
1314 | const struct switch_attr *attr, |
||
1315 | struct switch_val *val) |
||
1316 | { |
||
1317 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1318 | |||
1319 | mutex_lock(&priv->reg_mutex); |
||
1320 | priv->source_port = val->value.i; |
||
1321 | priv->chip->set_mirror_regs(priv); |
||
1322 | mutex_unlock(&priv->reg_mutex); |
||
1323 | |||
1324 | return 0; |
||
1325 | } |
||
1326 | |||
1327 | int |
||
1328 | ar8xxx_sw_get_mirror_source_port(struct switch_dev *dev, |
||
1329 | const struct switch_attr *attr, |
||
1330 | struct switch_val *val) |
||
1331 | { |
||
1332 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1333 | val->value.i = priv->source_port; |
||
1334 | return 0; |
||
1335 | } |
||
1336 | |||
1337 | int |
||
1338 | ar8xxx_sw_set_port_reset_mib(struct switch_dev *dev, |
||
1339 | const struct switch_attr *attr, |
||
1340 | struct switch_val *val) |
||
1341 | { |
||
1342 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1343 | int port; |
||
1344 | int ret; |
||
1345 | |||
1346 | if (!ar8xxx_has_mib_counters(priv)) |
||
1347 | return -EOPNOTSUPP; |
||
1348 | |||
1349 | port = val->port_vlan; |
||
1350 | if (port >= dev->ports) |
||
1351 | return -EINVAL; |
||
1352 | |||
1353 | mutex_lock(&priv->mib_lock); |
||
1354 | ret = ar8xxx_mib_capture(priv); |
||
1355 | if (ret) |
||
1356 | goto unlock; |
||
1357 | |||
1358 | ar8xxx_mib_fetch_port_stat(priv, port, true); |
||
1359 | |||
1360 | ret = 0; |
||
1361 | |||
1362 | unlock: |
||
1363 | mutex_unlock(&priv->mib_lock); |
||
1364 | return ret; |
||
1365 | } |
||
1366 | |||
1367 | static void |
||
1368 | ar8xxx_byte_to_str(char *buf, int len, u64 byte) |
||
1369 | { |
||
1370 | unsigned long b; |
||
1371 | const char *unit; |
||
1372 | |||
1373 | if (byte >= 0x40000000) { /* 1 GiB */ |
||
1374 | b = byte * 10 / 0x40000000; |
||
1375 | unit = "GiB"; |
||
1376 | } else if (byte >= 0x100000) { /* 1 MiB */ |
||
1377 | b = byte * 10 / 0x100000; |
||
1378 | unit = "MiB"; |
||
1379 | } else if (byte >= 0x400) { /* 1 KiB */ |
||
1380 | b = byte * 10 / 0x400; |
||
1381 | unit = "KiB"; |
||
1382 | } else { |
||
1383 | b = byte; |
||
1384 | unit = "Byte"; |
||
1385 | } |
||
1386 | if (strcmp(unit, "Byte")) |
||
1387 | snprintf(buf, len, "%lu.%lu %s", b / 10, b % 10, unit); |
||
1388 | else |
||
1389 | snprintf(buf, len, "%lu %s", b, unit); |
||
1390 | } |
||
1391 | |||
1392 | int |
||
1393 | ar8xxx_sw_get_port_mib(struct switch_dev *dev, |
||
1394 | const struct switch_attr *attr, |
||
1395 | struct switch_val *val) |
||
1396 | { |
||
1397 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1398 | const struct ar8xxx_chip *chip = priv->chip; |
||
1399 | u64 *mib_stats, mib_data; |
||
1400 | unsigned int port; |
||
1401 | int ret; |
||
1402 | char *buf = priv->buf; |
||
1403 | char buf1[64]; |
||
1404 | const char *mib_name; |
||
1405 | int i, len = 0; |
||
1406 | bool mib_stats_empty = true; |
||
1407 | |||
1408 | if (!ar8xxx_has_mib_counters(priv)) |
||
1409 | return -EOPNOTSUPP; |
||
1410 | |||
1411 | port = val->port_vlan; |
||
1412 | if (port >= dev->ports) |
||
1413 | return -EINVAL; |
||
1414 | |||
1415 | mutex_lock(&priv->mib_lock); |
||
1416 | ret = ar8xxx_mib_capture(priv); |
||
1417 | if (ret) |
||
1418 | goto unlock; |
||
1419 | |||
1420 | ar8xxx_mib_fetch_port_stat(priv, port, false); |
||
1421 | |||
1422 | len += snprintf(buf + len, sizeof(priv->buf) - len, |
||
1423 | "MIB counters\n"); |
||
1424 | |||
1425 | mib_stats = &priv->mib_stats[port * chip->num_mibs]; |
||
1426 | for (i = 0; i < chip->num_mibs; i++) { |
||
1427 | mib_name = chip->mib_decs[i].name; |
||
1428 | mib_data = mib_stats[i]; |
||
1429 | len += snprintf(buf + len, sizeof(priv->buf) - len, |
||
1430 | "%-12s: %llu\n", mib_name, mib_data); |
||
1431 | if ((!strcmp(mib_name, "TxByte") || |
||
1432 | !strcmp(mib_name, "RxGoodByte")) && |
||
1433 | mib_data >= 1024) { |
||
1434 | ar8xxx_byte_to_str(buf1, sizeof(buf1), mib_data); |
||
1435 | --len; /* discard newline at the end of buf */ |
||
1436 | len += snprintf(buf + len, sizeof(priv->buf) - len, |
||
1437 | " (%s)\n", buf1); |
||
1438 | } |
||
1439 | if (mib_stats_empty && mib_data) |
||
1440 | mib_stats_empty = false; |
||
1441 | } |
||
1442 | |||
1443 | if (mib_stats_empty) |
||
1444 | len = snprintf(buf, sizeof(priv->buf), "No MIB data"); |
||
1445 | |||
1446 | val->value.s = buf; |
||
1447 | val->len = len; |
||
1448 | |||
1449 | ret = 0; |
||
1450 | |||
1451 | unlock: |
||
1452 | mutex_unlock(&priv->mib_lock); |
||
1453 | return ret; |
||
1454 | } |
||
1455 | |||
1456 | int |
||
1457 | ar8xxx_sw_set_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, |
||
1458 | struct switch_val *val) |
||
1459 | { |
||
1460 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1461 | int age_time = val->value.i; |
||
1462 | u32 age_time_val; |
||
1463 | |||
1464 | if (age_time < 0) |
||
1465 | return -EINVAL; |
||
1466 | |||
1467 | age_time_val = ar8xxx_age_time_val(age_time); |
||
1468 | if (age_time_val == 0 || age_time_val > 0xffff) |
||
1469 | return -EINVAL; |
||
1470 | |||
1471 | priv->arl_age_time = age_time; |
||
1472 | return 0; |
||
1473 | } |
||
1474 | |||
1475 | int |
||
1476 | ar8xxx_sw_get_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, |
||
1477 | struct switch_val *val) |
||
1478 | { |
||
1479 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1480 | val->value.i = priv->arl_age_time; |
||
1481 | return 0; |
||
1482 | } |
||
1483 | |||
1484 | int |
||
1485 | ar8xxx_sw_get_arl_table(struct switch_dev *dev, |
||
1486 | const struct switch_attr *attr, |
||
1487 | struct switch_val *val) |
||
1488 | { |
||
1489 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1490 | struct mii_bus *bus = priv->mii_bus; |
||
1491 | const struct ar8xxx_chip *chip = priv->chip; |
||
1492 | char *buf = priv->arl_buf; |
||
1493 | int i, j, k, len = 0; |
||
1494 | struct arl_entry *a, *a1; |
||
1495 | u32 status; |
||
1496 | |||
1497 | if (!chip->get_arl_entry) |
||
1498 | return -EOPNOTSUPP; |
||
1499 | |||
1500 | mutex_lock(&priv->reg_mutex); |
||
1501 | mutex_lock(&bus->mdio_lock); |
||
1502 | |||
1503 | chip->get_arl_entry(priv, NULL, NULL, AR8XXX_ARL_INITIALIZE); |
||
1504 | |||
1505 | for(i = 0; i < AR8XXX_NUM_ARL_RECORDS; ++i) { |
||
1506 | a = &priv->arl_table[i]; |
||
1507 | duplicate: |
||
1508 | chip->get_arl_entry(priv, a, &status, AR8XXX_ARL_GET_NEXT); |
||
1509 | |||
1510 | if (!status) |
||
1511 | break; |
||
1512 | |||
1513 | /* avoid duplicates |
||
1514 | * ARL table can include multiple valid entries |
||
1515 | * per MAC, just with differing status codes |
||
1516 | */ |
||
1517 | for (j = 0; j < i; ++j) { |
||
1518 | a1 = &priv->arl_table[j]; |
||
3 | office | 1519 | if (a->port == a1->port && !memcmp(a->mac, a1->mac, sizeof(a->mac))) |
1520 | goto duplicate; |
||
1 | office | 1521 | } |
1522 | } |
||
1523 | |||
1524 | mutex_unlock(&bus->mdio_lock); |
||
1525 | |||
1526 | len += snprintf(buf + len, sizeof(priv->arl_buf) - len, |
||
1527 | "address resolution table\n"); |
||
1528 | |||
1529 | if (i == AR8XXX_NUM_ARL_RECORDS) |
||
1530 | len += snprintf(buf + len, sizeof(priv->arl_buf) - len, |
||
1531 | "Too many entries found, displaying the first %d only!\n", |
||
1532 | AR8XXX_NUM_ARL_RECORDS); |
||
1533 | |||
1534 | for (j = 0; j < priv->dev.ports; ++j) { |
||
1535 | for (k = 0; k < i; ++k) { |
||
1536 | a = &priv->arl_table[k]; |
||
3 | office | 1537 | if (a->port != j) |
1 | office | 1538 | continue; |
1539 | len += snprintf(buf + len, sizeof(priv->arl_buf) - len, |
||
1540 | "Port %d: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
||
1541 | j, |
||
1542 | a->mac[5], a->mac[4], a->mac[3], |
||
1543 | a->mac[2], a->mac[1], a->mac[0]); |
||
1544 | } |
||
1545 | } |
||
1546 | |||
1547 | val->value.s = buf; |
||
1548 | val->len = len; |
||
1549 | |||
1550 | mutex_unlock(&priv->reg_mutex); |
||
1551 | |||
1552 | return 0; |
||
1553 | } |
||
1554 | |||
1555 | int |
||
1556 | ar8xxx_sw_set_flush_arl_table(struct switch_dev *dev, |
||
1557 | const struct switch_attr *attr, |
||
1558 | struct switch_val *val) |
||
1559 | { |
||
1560 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1561 | int ret; |
||
1562 | |||
1563 | mutex_lock(&priv->reg_mutex); |
||
1564 | ret = priv->chip->atu_flush(priv); |
||
1565 | mutex_unlock(&priv->reg_mutex); |
||
1566 | |||
1567 | return ret; |
||
1568 | } |
||
1569 | |||
1570 | int |
||
1571 | ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev, |
||
1572 | const struct switch_attr *attr, |
||
1573 | struct switch_val *val) |
||
1574 | { |
||
1575 | struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); |
||
1576 | int port, ret; |
||
1577 | |||
1578 | port = val->port_vlan; |
||
1579 | if (port >= dev->ports) |
||
1580 | return -EINVAL; |
||
1581 | |||
1582 | mutex_lock(&priv->reg_mutex); |
||
1583 | ret = priv->chip->atu_flush_port(priv, port); |
||
1584 | mutex_unlock(&priv->reg_mutex); |
||
1585 | |||
1586 | return ret; |
||
1587 | } |
||
1588 | |||
1589 | static const struct switch_attr ar8xxx_sw_attr_globals[] = { |
||
1590 | { |
||
1591 | .type = SWITCH_TYPE_INT, |
||
1592 | .name = "enable_vlan", |
||
1593 | .description = "Enable VLAN mode", |
||
1594 | .set = ar8xxx_sw_set_vlan, |
||
1595 | .get = ar8xxx_sw_get_vlan, |
||
1596 | .max = 1 |
||
1597 | }, |
||
1598 | { |
||
1599 | .type = SWITCH_TYPE_NOVAL, |
||
1600 | .name = "reset_mibs", |
||
1601 | .description = "Reset all MIB counters", |
||
1602 | .set = ar8xxx_sw_set_reset_mibs, |
||
1603 | }, |
||
1604 | { |
||
1605 | .type = SWITCH_TYPE_INT, |
||
1606 | .name = "enable_mirror_rx", |
||
1607 | .description = "Enable mirroring of RX packets", |
||
1608 | .set = ar8xxx_sw_set_mirror_rx_enable, |
||
1609 | .get = ar8xxx_sw_get_mirror_rx_enable, |
||
1610 | .max = 1 |
||
1611 | }, |
||
1612 | { |
||
1613 | .type = SWITCH_TYPE_INT, |
||
1614 | .name = "enable_mirror_tx", |
||
1615 | .description = "Enable mirroring of TX packets", |
||
1616 | .set = ar8xxx_sw_set_mirror_tx_enable, |
||
1617 | .get = ar8xxx_sw_get_mirror_tx_enable, |
||
1618 | .max = 1 |
||
1619 | }, |
||
1620 | { |
||
1621 | .type = SWITCH_TYPE_INT, |
||
1622 | .name = "mirror_monitor_port", |
||
1623 | .description = "Mirror monitor port", |
||
1624 | .set = ar8xxx_sw_set_mirror_monitor_port, |
||
1625 | .get = ar8xxx_sw_get_mirror_monitor_port, |
||
1626 | .max = AR8216_NUM_PORTS - 1 |
||
1627 | }, |
||
1628 | { |
||
1629 | .type = SWITCH_TYPE_INT, |
||
1630 | .name = "mirror_source_port", |
||
1631 | .description = "Mirror source port", |
||
1632 | .set = ar8xxx_sw_set_mirror_source_port, |
||
1633 | .get = ar8xxx_sw_get_mirror_source_port, |
||
1634 | .max = AR8216_NUM_PORTS - 1 |
||
1635 | }, |
||
1636 | { |
||
1637 | .type = SWITCH_TYPE_STRING, |
||
1638 | .name = "arl_table", |
||
1639 | .description = "Get ARL table", |
||
1640 | .set = NULL, |
||
1641 | .get = ar8xxx_sw_get_arl_table, |
||
1642 | }, |
||
1643 | { |
||
1644 | .type = SWITCH_TYPE_NOVAL, |
||
1645 | .name = "flush_arl_table", |
||
1646 | .description = "Flush ARL table", |
||
1647 | .set = ar8xxx_sw_set_flush_arl_table, |
||
1648 | }, |
||
1649 | }; |
||
1650 | |||
1651 | const struct switch_attr ar8xxx_sw_attr_port[] = { |
||
1652 | { |
||
1653 | .type = SWITCH_TYPE_NOVAL, |
||
1654 | .name = "reset_mib", |
||
1655 | .description = "Reset single port MIB counters", |
||
1656 | .set = ar8xxx_sw_set_port_reset_mib, |
||
1657 | }, |
||
1658 | { |
||
1659 | .type = SWITCH_TYPE_STRING, |
||
1660 | .name = "mib", |
||
1661 | .description = "Get port's MIB counters", |
||
1662 | .set = NULL, |
||
1663 | .get = ar8xxx_sw_get_port_mib, |
||
1664 | }, |
||
1665 | { |
||
1666 | .type = SWITCH_TYPE_NOVAL, |
||
1667 | .name = "flush_arl_table", |
||
1668 | .description = "Flush port's ARL table entries", |
||
1669 | .set = ar8xxx_sw_set_flush_port_arl_table, |
||
1670 | }, |
||
1671 | }; |
||
1672 | |||
1673 | const struct switch_attr ar8xxx_sw_attr_vlan[1] = { |
||
1674 | { |
||
1675 | .type = SWITCH_TYPE_INT, |
||
1676 | .name = "vid", |
||
1677 | .description = "VLAN ID (0-4094)", |
||
1678 | .set = ar8xxx_sw_set_vid, |
||
1679 | .get = ar8xxx_sw_get_vid, |
||
1680 | .max = 4094, |
||
1681 | }, |
||
1682 | }; |
||
1683 | |||
1684 | static const struct switch_dev_ops ar8xxx_sw_ops = { |
||
1685 | .attr_global = { |
||
1686 | .attr = ar8xxx_sw_attr_globals, |
||
1687 | .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_globals), |
||
1688 | }, |
||
1689 | .attr_port = { |
||
1690 | .attr = ar8xxx_sw_attr_port, |
||
1691 | .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_port), |
||
1692 | }, |
||
1693 | .attr_vlan = { |
||
1694 | .attr = ar8xxx_sw_attr_vlan, |
||
1695 | .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_vlan), |
||
1696 | }, |
||
1697 | .get_port_pvid = ar8xxx_sw_get_pvid, |
||
1698 | .set_port_pvid = ar8xxx_sw_set_pvid, |
||
1699 | .get_vlan_ports = ar8xxx_sw_get_ports, |
||
1700 | .set_vlan_ports = ar8xxx_sw_set_ports, |
||
1701 | .apply_config = ar8xxx_sw_hw_apply, |
||
1702 | .reset_switch = ar8xxx_sw_reset_switch, |
||
1703 | .get_port_link = ar8xxx_sw_get_port_link, |
||
1704 | /* The following op is disabled as it hogs the CPU and degrades performance. |
||
1705 | An implementation has been attempted in 4d8a66d but reading MIB data is slow |
||
1706 | on ar8xxx switches. |
||
1707 | |||
1708 | The high CPU load has been traced down to the ar8xxx_reg_wait() call in |
||
1709 | ar8xxx_mib_op(), which has to usleep_range() till the MIB busy flag set by |
||
1710 | the request to update the MIB counter is cleared. */ |
||
1711 | #if 0 |
||
1712 | .get_port_stats = ar8xxx_sw_get_port_stats, |
||
1713 | #endif |
||
1714 | }; |
||
1715 | |||
1716 | static const struct ar8xxx_chip ar8216_chip = { |
||
1717 | .caps = AR8XXX_CAP_MIB_COUNTERS, |
||
1718 | |||
1719 | .reg_port_stats_start = 0x19000, |
||
1720 | .reg_port_stats_length = 0xa0, |
||
1721 | .reg_arl_ctrl = AR8216_REG_ATU_CTRL, |
||
1722 | |||
1723 | .name = "Atheros AR8216", |
||
1724 | .ports = AR8216_NUM_PORTS, |
||
1725 | .vlans = AR8216_NUM_VLANS, |
||
1726 | .swops = &ar8xxx_sw_ops, |
||
1727 | |||
1728 | .hw_init = ar8216_hw_init, |
||
1729 | .init_globals = ar8216_init_globals, |
||
1730 | .init_port = ar8216_init_port, |
||
1731 | .setup_port = ar8216_setup_port, |
||
1732 | .read_port_status = ar8216_read_port_status, |
||
1733 | .atu_flush = ar8216_atu_flush, |
||
1734 | .atu_flush_port = ar8216_atu_flush_port, |
||
1735 | .vtu_flush = ar8216_vtu_flush, |
||
1736 | .vtu_load_vlan = ar8216_vtu_load_vlan, |
||
1737 | .set_mirror_regs = ar8216_set_mirror_regs, |
||
1738 | .get_arl_entry = ar8216_get_arl_entry, |
||
1739 | .sw_hw_apply = ar8xxx_sw_hw_apply, |
||
1740 | |||
1741 | .num_mibs = ARRAY_SIZE(ar8216_mibs), |
||
1742 | .mib_decs = ar8216_mibs, |
||
1743 | .mib_func = AR8216_REG_MIB_FUNC |
||
1744 | }; |
||
1745 | |||
1746 | static const struct ar8xxx_chip ar8236_chip = { |
||
1747 | .caps = AR8XXX_CAP_MIB_COUNTERS, |
||
1748 | |||
1749 | .reg_port_stats_start = 0x20000, |
||
1750 | .reg_port_stats_length = 0x100, |
||
1751 | .reg_arl_ctrl = AR8216_REG_ATU_CTRL, |
||
1752 | |||
1753 | .name = "Atheros AR8236", |
||
1754 | .ports = AR8216_NUM_PORTS, |
||
1755 | .vlans = AR8216_NUM_VLANS, |
||
1756 | .swops = &ar8xxx_sw_ops, |
||
1757 | |||
1758 | .hw_init = ar8216_hw_init, |
||
1759 | .init_globals = ar8236_init_globals, |
||
1760 | .init_port = ar8216_init_port, |
||
1761 | .setup_port = ar8236_setup_port, |
||
1762 | .read_port_status = ar8216_read_port_status, |
||
1763 | .atu_flush = ar8216_atu_flush, |
||
1764 | .atu_flush_port = ar8216_atu_flush_port, |
||
1765 | .vtu_flush = ar8216_vtu_flush, |
||
1766 | .vtu_load_vlan = ar8216_vtu_load_vlan, |
||
1767 | .set_mirror_regs = ar8216_set_mirror_regs, |
||
1768 | .get_arl_entry = ar8216_get_arl_entry, |
||
1769 | .sw_hw_apply = ar8xxx_sw_hw_apply, |
||
1770 | |||
1771 | .num_mibs = ARRAY_SIZE(ar8236_mibs), |
||
1772 | .mib_decs = ar8236_mibs, |
||
1773 | .mib_func = AR8216_REG_MIB_FUNC |
||
1774 | }; |
||
1775 | |||
1776 | static const struct ar8xxx_chip ar8316_chip = { |
||
1777 | .caps = AR8XXX_CAP_GIGE | AR8XXX_CAP_MIB_COUNTERS, |
||
1778 | |||
1779 | .reg_port_stats_start = 0x20000, |
||
1780 | .reg_port_stats_length = 0x100, |
||
1781 | .reg_arl_ctrl = AR8216_REG_ATU_CTRL, |
||
1782 | |||
1783 | .name = "Atheros AR8316", |
||
1784 | .ports = AR8216_NUM_PORTS, |
||
1785 | .vlans = AR8X16_MAX_VLANS, |
||
1786 | .swops = &ar8xxx_sw_ops, |
||
1787 | |||
1788 | .hw_init = ar8316_hw_init, |
||
1789 | .init_globals = ar8316_init_globals, |
||
1790 | .init_port = ar8216_init_port, |
||
1791 | .setup_port = ar8216_setup_port, |
||
1792 | .read_port_status = ar8216_read_port_status, |
||
1793 | .atu_flush = ar8216_atu_flush, |
||
1794 | .atu_flush_port = ar8216_atu_flush_port, |
||
1795 | .vtu_flush = ar8216_vtu_flush, |
||
1796 | .vtu_load_vlan = ar8216_vtu_load_vlan, |
||
1797 | .set_mirror_regs = ar8216_set_mirror_regs, |
||
1798 | .get_arl_entry = ar8216_get_arl_entry, |
||
1799 | .sw_hw_apply = ar8xxx_sw_hw_apply, |
||
1800 | |||
1801 | .num_mibs = ARRAY_SIZE(ar8236_mibs), |
||
1802 | .mib_decs = ar8236_mibs, |
||
1803 | .mib_func = AR8216_REG_MIB_FUNC |
||
1804 | }; |
||
1805 | |||
1806 | static int |
||
1807 | ar8xxx_id_chip(struct ar8xxx_priv *priv) |
||
1808 | { |
||
1809 | u32 val; |
||
1810 | u16 id; |
||
1811 | int i; |
||
1812 | |||
1813 | val = ar8xxx_read(priv, AR8216_REG_CTRL); |
||
1814 | if (val == ~0) |
||
1815 | return -ENODEV; |
||
1816 | |||
1817 | id = val & (AR8216_CTRL_REVISION | AR8216_CTRL_VERSION); |
||
1818 | for (i = 0; i < AR8X16_PROBE_RETRIES; i++) { |
||
1819 | u16 t; |
||
1820 | |||
1821 | val = ar8xxx_read(priv, AR8216_REG_CTRL); |
||
1822 | if (val == ~0) |
||
1823 | return -ENODEV; |
||
1824 | |||
1825 | t = val & (AR8216_CTRL_REVISION | AR8216_CTRL_VERSION); |
||
1826 | if (t != id) |
||
1827 | return -ENODEV; |
||
1828 | } |
||
1829 | |||
1830 | priv->chip_ver = (id & AR8216_CTRL_VERSION) >> AR8216_CTRL_VERSION_S; |
||
1831 | priv->chip_rev = (id & AR8216_CTRL_REVISION); |
||
1832 | |||
1833 | switch (priv->chip_ver) { |
||
1834 | case AR8XXX_VER_AR8216: |
||
1835 | priv->chip = &ar8216_chip; |
||
1836 | break; |
||
1837 | case AR8XXX_VER_AR8236: |
||
1838 | priv->chip = &ar8236_chip; |
||
1839 | break; |
||
1840 | case AR8XXX_VER_AR8316: |
||
1841 | priv->chip = &ar8316_chip; |
||
1842 | break; |
||
1843 | case AR8XXX_VER_AR8327: |
||
1844 | priv->chip = &ar8327_chip; |
||
1845 | break; |
||
1846 | case AR8XXX_VER_AR8337: |
||
1847 | priv->chip = &ar8337_chip; |
||
1848 | break; |
||
1849 | default: |
||
1850 | pr_err("ar8216: Unknown Atheros device [ver=%d, rev=%d]\n", |
||
1851 | priv->chip_ver, priv->chip_rev); |
||
1852 | |||
1853 | return -ENODEV; |
||
1854 | } |
||
1855 | |||
1856 | return 0; |
||
1857 | } |
||
1858 | |||
1859 | static void |
||
1860 | ar8xxx_mib_work_func(struct work_struct *work) |
||
1861 | { |
||
1862 | struct ar8xxx_priv *priv; |
||
1863 | int err; |
||
1864 | |||
1865 | priv = container_of(work, struct ar8xxx_priv, mib_work.work); |
||
1866 | |||
1867 | mutex_lock(&priv->mib_lock); |
||
1868 | |||
1869 | err = ar8xxx_mib_capture(priv); |
||
1870 | if (err) |
||
1871 | goto next_port; |
||
1872 | |||
1873 | ar8xxx_mib_fetch_port_stat(priv, priv->mib_next_port, false); |
||
1874 | |||
1875 | next_port: |
||
1876 | priv->mib_next_port++; |
||
1877 | if (priv->mib_next_port >= priv->dev.ports) |
||
1878 | priv->mib_next_port = 0; |
||
1879 | |||
1880 | mutex_unlock(&priv->mib_lock); |
||
1881 | schedule_delayed_work(&priv->mib_work, |
||
1882 | msecs_to_jiffies(AR8XXX_MIB_WORK_DELAY)); |
||
1883 | } |
||
1884 | |||
1885 | static int |
||
1886 | ar8xxx_mib_init(struct ar8xxx_priv *priv) |
||
1887 | { |
||
1888 | unsigned int len; |
||
1889 | |||
1890 | if (!ar8xxx_has_mib_counters(priv)) |
||
1891 | return 0; |
||
1892 | |||
1893 | BUG_ON(!priv->chip->mib_decs || !priv->chip->num_mibs); |
||
1894 | |||
1895 | len = priv->dev.ports * priv->chip->num_mibs * |
||
1896 | sizeof(*priv->mib_stats); |
||
1897 | priv->mib_stats = kzalloc(len, GFP_KERNEL); |
||
1898 | |||
1899 | if (!priv->mib_stats) |
||
1900 | return -ENOMEM; |
||
1901 | |||
1902 | return 0; |
||
1903 | } |
||
1904 | |||
1905 | static void |
||
1906 | ar8xxx_mib_start(struct ar8xxx_priv *priv) |
||
1907 | { |
||
1908 | if (!ar8xxx_has_mib_counters(priv)) |
||
1909 | return; |
||
1910 | |||
1911 | schedule_delayed_work(&priv->mib_work, |
||
1912 | msecs_to_jiffies(AR8XXX_MIB_WORK_DELAY)); |
||
1913 | } |
||
1914 | |||
1915 | static void |
||
1916 | ar8xxx_mib_stop(struct ar8xxx_priv *priv) |
||
1917 | { |
||
1918 | if (!ar8xxx_has_mib_counters(priv)) |
||
1919 | return; |
||
1920 | |||
1921 | cancel_delayed_work_sync(&priv->mib_work); |
||
1922 | } |
||
1923 | |||
1924 | static struct ar8xxx_priv * |
||
1925 | ar8xxx_create(void) |
||
1926 | { |
||
1927 | struct ar8xxx_priv *priv; |
||
1928 | |||
1929 | priv = kzalloc(sizeof(struct ar8xxx_priv), GFP_KERNEL); |
||
1930 | if (priv == NULL) |
||
1931 | return NULL; |
||
1932 | |||
1933 | mutex_init(&priv->reg_mutex); |
||
1934 | mutex_init(&priv->mib_lock); |
||
1935 | INIT_DELAYED_WORK(&priv->mib_work, ar8xxx_mib_work_func); |
||
1936 | |||
1937 | return priv; |
||
1938 | } |
||
1939 | |||
1940 | static void |
||
1941 | ar8xxx_free(struct ar8xxx_priv *priv) |
||
1942 | { |
||
1943 | if (priv->chip && priv->chip->cleanup) |
||
1944 | priv->chip->cleanup(priv); |
||
1945 | |||
1946 | kfree(priv->chip_data); |
||
1947 | kfree(priv->mib_stats); |
||
1948 | kfree(priv); |
||
1949 | } |
||
1950 | |||
1951 | static int |
||
1952 | ar8xxx_probe_switch(struct ar8xxx_priv *priv) |
||
1953 | { |
||
1954 | const struct ar8xxx_chip *chip; |
||
1955 | struct switch_dev *swdev; |
||
1956 | int ret; |
||
1957 | |||
1958 | ret = ar8xxx_id_chip(priv); |
||
1959 | if (ret) |
||
1960 | return ret; |
||
1961 | |||
1962 | chip = priv->chip; |
||
1963 | |||
1964 | swdev = &priv->dev; |
||
1965 | swdev->cpu_port = AR8216_PORT_CPU; |
||
1966 | swdev->name = chip->name; |
||
1967 | swdev->vlans = chip->vlans; |
||
1968 | swdev->ports = chip->ports; |
||
1969 | swdev->ops = chip->swops; |
||
1970 | |||
1971 | ret = ar8xxx_mib_init(priv); |
||
1972 | if (ret) |
||
1973 | return ret; |
||
1974 | |||
1975 | return 0; |
||
1976 | } |
||
1977 | |||
1978 | static int |
||
1979 | ar8xxx_start(struct ar8xxx_priv *priv) |
||
1980 | { |
||
1981 | int ret; |
||
1982 | |||
1983 | priv->init = true; |
||
1984 | |||
1985 | ret = priv->chip->hw_init(priv); |
||
1986 | if (ret) |
||
1987 | return ret; |
||
1988 | |||
1989 | ret = ar8xxx_sw_reset_switch(&priv->dev); |
||
1990 | if (ret) |
||
1991 | return ret; |
||
1992 | |||
1993 | priv->init = false; |
||
1994 | |||
1995 | ar8xxx_mib_start(priv); |
||
1996 | |||
1997 | return 0; |
||
1998 | } |
||
1999 | |||
2000 | static int |
||
2001 | ar8xxx_phy_config_init(struct phy_device *phydev) |
||
2002 | { |
||
2003 | struct ar8xxx_priv *priv = phydev->priv; |
||
2004 | struct net_device *dev = phydev->attached_dev; |
||
2005 | int ret; |
||
2006 | |||
2007 | if (WARN_ON(!priv)) |
||
2008 | return -ENODEV; |
||
2009 | |||
2010 | if (priv->chip->config_at_probe) |
||
2011 | return ar8xxx_phy_check_aneg(phydev); |
||
2012 | |||
2013 | priv->phy = phydev; |
||
2014 | |||
2015 | if (phydev->mdio.addr != 0) { |
||
2016 | if (chip_is_ar8316(priv)) { |
||
2017 | /* switch device has been initialized, reinit */ |
||
2018 | priv->dev.ports = (AR8216_NUM_PORTS - 1); |
||
2019 | priv->initialized = false; |
||
2020 | priv->port4_phy = true; |
||
2021 | ar8316_hw_init(priv); |
||
2022 | return 0; |
||
2023 | } |
||
2024 | |||
2025 | return 0; |
||
2026 | } |
||
2027 | |||
2028 | ret = ar8xxx_start(priv); |
||
2029 | if (ret) |
||
2030 | return ret; |
||
2031 | |||
2032 | /* VID fixup only needed on ar8216 */ |
||
2033 | if (chip_is_ar8216(priv)) { |
||
2034 | dev->phy_ptr = priv; |
||
2035 | dev->priv_flags |= IFF_NO_IP_ALIGN; |
||
2036 | dev->eth_mangle_rx = ar8216_mangle_rx; |
||
2037 | dev->eth_mangle_tx = ar8216_mangle_tx; |
||
2038 | } |
||
2039 | |||
2040 | return 0; |
||
2041 | } |
||
2042 | |||
2043 | static bool |
||
2044 | ar8xxx_check_link_states(struct ar8xxx_priv *priv) |
||
2045 | { |
||
2046 | bool link_new, changed = false; |
||
2047 | u32 status; |
||
2048 | int i; |
||
2049 | |||
2050 | mutex_lock(&priv->reg_mutex); |
||
2051 | |||
2052 | for (i = 0; i < priv->dev.ports; i++) { |
||
2053 | status = priv->chip->read_port_status(priv, i); |
||
2054 | link_new = !!(status & AR8216_PORT_STATUS_LINK_UP); |
||
2055 | if (link_new == priv->link_up[i]) |
||
2056 | continue; |
||
2057 | |||
2058 | priv->link_up[i] = link_new; |
||
2059 | changed = true; |
||
2060 | /* flush ARL entries for this port if it went down*/ |
||
2061 | if (!link_new) |
||
2062 | priv->chip->atu_flush_port(priv, i); |
||
2063 | dev_info(&priv->phy->mdio.dev, "Port %d is %s\n", |
||
2064 | i, link_new ? "up" : "down"); |
||
2065 | } |
||
2066 | |||
2067 | mutex_unlock(&priv->reg_mutex); |
||
2068 | |||
2069 | return changed; |
||
2070 | } |
||
2071 | |||
2072 | static int |
||
2073 | ar8xxx_phy_read_status(struct phy_device *phydev) |
||
2074 | { |
||
2075 | struct ar8xxx_priv *priv = phydev->priv; |
||
2076 | struct switch_port_link link; |
||
2077 | |||
2078 | /* check for switch port link changes */ |
||
2079 | if (phydev->state == PHY_CHANGELINK) |
||
2080 | ar8xxx_check_link_states(priv); |
||
2081 | |||
2082 | if (phydev->mdio.addr != 0) |
||
2083 | return genphy_read_status(phydev); |
||
2084 | |||
2085 | ar8216_read_port_link(priv, phydev->mdio.addr, &link); |
||
2086 | phydev->link = !!link.link; |
||
2087 | if (!phydev->link) |
||
2088 | return 0; |
||
2089 | |||
2090 | switch (link.speed) { |
||
2091 | case SWITCH_PORT_SPEED_10: |
||
2092 | phydev->speed = SPEED_10; |
||
2093 | break; |
||
2094 | case SWITCH_PORT_SPEED_100: |
||
2095 | phydev->speed = SPEED_100; |
||
2096 | break; |
||
2097 | case SWITCH_PORT_SPEED_1000: |
||
2098 | phydev->speed = SPEED_1000; |
||
2099 | break; |
||
2100 | default: |
||
2101 | phydev->speed = 0; |
||
2102 | } |
||
2103 | phydev->duplex = link.duplex ? DUPLEX_FULL : DUPLEX_HALF; |
||
2104 | |||
2105 | phydev->state = PHY_RUNNING; |
||
2106 | netif_carrier_on(phydev->attached_dev); |
||
3 | office | 2107 | phydev->adjust_link(phydev->attached_dev); |
1 | office | 2108 | |
2109 | return 0; |
||
2110 | } |
||
2111 | |||
2112 | static int |
||
2113 | ar8xxx_phy_config_aneg(struct phy_device *phydev) |
||
2114 | { |
||
2115 | if (phydev->mdio.addr == 0) |
||
2116 | return 0; |
||
2117 | |||
2118 | return genphy_config_aneg(phydev); |
||
2119 | } |
||
2120 | |||
2121 | static const u32 ar8xxx_phy_ids[] = { |
||
2122 | 0x004dd033, |
||
2123 | 0x004dd034, /* AR8327 */ |
||
2124 | 0x004dd036, /* AR8337 */ |
||
2125 | 0x004dd041, |
||
2126 | 0x004dd042, |
||
2127 | 0x004dd043, /* AR8236 */ |
||
2128 | }; |
||
2129 | |||
2130 | static bool |
||
2131 | ar8xxx_phy_match(u32 phy_id) |
||
2132 | { |
||
2133 | int i; |
||
2134 | |||
2135 | for (i = 0; i < ARRAY_SIZE(ar8xxx_phy_ids); i++) |
||
2136 | if (phy_id == ar8xxx_phy_ids[i]) |
||
2137 | return true; |
||
2138 | |||
2139 | return false; |
||
2140 | } |
||
2141 | |||
2142 | static bool |
||
2143 | ar8xxx_is_possible(struct mii_bus *bus) |
||
2144 | { |
||
2145 | unsigned int i, found_phys = 0; |
||
2146 | |||
2147 | for (i = 0; i < 5; i++) { |
||
2148 | u32 phy_id; |
||
2149 | |||
2150 | phy_id = mdiobus_read(bus, i, MII_PHYSID1) << 16; |
||
2151 | phy_id |= mdiobus_read(bus, i, MII_PHYSID2); |
||
2152 | if (ar8xxx_phy_match(phy_id)) { |
||
2153 | found_phys++; |
||
2154 | } else if (phy_id) { |
||
2155 | pr_debug("ar8xxx: unknown PHY at %s:%02x id:%08x\n", |
||
2156 | dev_name(&bus->dev), i, phy_id); |
||
2157 | } |
||
2158 | } |
||
2159 | return !!found_phys; |
||
2160 | } |
||
2161 | |||
2162 | static int |
||
2163 | ar8xxx_phy_probe(struct phy_device *phydev) |
||
2164 | { |
||
2165 | struct ar8xxx_priv *priv; |
||
2166 | struct switch_dev *swdev; |
||
2167 | int ret; |
||
2168 | |||
2169 | /* skip PHYs at unused adresses */ |
||
3 | office | 2170 | if (phydev->mdio.addr != 0 && phydev->mdio.addr != 4) |
1 | office | 2171 | return -ENODEV; |
2172 | |||
2173 | if (!ar8xxx_is_possible(phydev->mdio.bus)) |
||
2174 | return -ENODEV; |
||
2175 | |||
2176 | mutex_lock(&ar8xxx_dev_list_lock); |
||
2177 | list_for_each_entry(priv, &ar8xxx_dev_list, list) |
||
2178 | if (priv->mii_bus == phydev->mdio.bus) |
||
2179 | goto found; |
||
2180 | |||
2181 | priv = ar8xxx_create(); |
||
2182 | if (priv == NULL) { |
||
2183 | ret = -ENOMEM; |
||
2184 | goto unlock; |
||
2185 | } |
||
2186 | |||
2187 | priv->mii_bus = phydev->mdio.bus; |
||
2188 | |||
2189 | ret = ar8xxx_probe_switch(priv); |
||
2190 | if (ret) |
||
2191 | goto free_priv; |
||
2192 | |||
2193 | swdev = &priv->dev; |
||
2194 | swdev->alias = dev_name(&priv->mii_bus->dev); |
||
2195 | ret = register_switch(swdev, NULL); |
||
2196 | if (ret) |
||
2197 | goto free_priv; |
||
2198 | |||
2199 | pr_info("%s: %s rev. %u switch registered on %s\n", |
||
2200 | swdev->devname, swdev->name, priv->chip_rev, |
||
2201 | dev_name(&priv->mii_bus->dev)); |
||
2202 | |||
2203 | list_add(&priv->list, &ar8xxx_dev_list); |
||
2204 | |||
2205 | found: |
||
2206 | priv->use_count++; |
||
2207 | |||
2208 | if (phydev->mdio.addr == 0) { |
||
2209 | if (ar8xxx_has_gige(priv)) { |
||
2210 | phydev->supported = SUPPORTED_1000baseT_Full; |
||
2211 | phydev->advertising = ADVERTISED_1000baseT_Full; |
||
2212 | } else { |
||
2213 | phydev->supported = SUPPORTED_100baseT_Full; |
||
2214 | phydev->advertising = ADVERTISED_100baseT_Full; |
||
2215 | } |
||
2216 | |||
2217 | if (priv->chip->config_at_probe) { |
||
2218 | priv->phy = phydev; |
||
2219 | |||
2220 | ret = ar8xxx_start(priv); |
||
2221 | if (ret) |
||
2222 | goto err_unregister_switch; |
||
2223 | } |
||
2224 | } else { |
||
2225 | if (ar8xxx_has_gige(priv)) { |
||
2226 | phydev->supported |= SUPPORTED_1000baseT_Full; |
||
2227 | phydev->advertising |= ADVERTISED_1000baseT_Full; |
||
2228 | } |
||
2229 | } |
||
2230 | |||
2231 | phydev->priv = priv; |
||
2232 | |||
2233 | mutex_unlock(&ar8xxx_dev_list_lock); |
||
2234 | |||
2235 | return 0; |
||
2236 | |||
2237 | err_unregister_switch: |
||
2238 | if (--priv->use_count) |
||
2239 | goto unlock; |
||
2240 | |||
2241 | unregister_switch(&priv->dev); |
||
2242 | |||
2243 | free_priv: |
||
2244 | ar8xxx_free(priv); |
||
2245 | unlock: |
||
2246 | mutex_unlock(&ar8xxx_dev_list_lock); |
||
2247 | return ret; |
||
2248 | } |
||
2249 | |||
2250 | static void |
||
2251 | ar8xxx_phy_detach(struct phy_device *phydev) |
||
2252 | { |
||
2253 | struct net_device *dev = phydev->attached_dev; |
||
2254 | |||
2255 | if (!dev) |
||
2256 | return; |
||
2257 | |||
2258 | dev->phy_ptr = NULL; |
||
2259 | dev->priv_flags &= ~IFF_NO_IP_ALIGN; |
||
2260 | dev->eth_mangle_rx = NULL; |
||
2261 | dev->eth_mangle_tx = NULL; |
||
2262 | } |
||
2263 | |||
2264 | static void |
||
2265 | ar8xxx_phy_remove(struct phy_device *phydev) |
||
2266 | { |
||
2267 | struct ar8xxx_priv *priv = phydev->priv; |
||
2268 | |||
2269 | if (WARN_ON(!priv)) |
||
2270 | return; |
||
2271 | |||
2272 | phydev->priv = NULL; |
||
2273 | |||
2274 | mutex_lock(&ar8xxx_dev_list_lock); |
||
2275 | |||
2276 | if (--priv->use_count > 0) { |
||
2277 | mutex_unlock(&ar8xxx_dev_list_lock); |
||
2278 | return; |
||
2279 | } |
||
2280 | |||
2281 | list_del(&priv->list); |
||
2282 | mutex_unlock(&ar8xxx_dev_list_lock); |
||
2283 | |||
2284 | unregister_switch(&priv->dev); |
||
2285 | ar8xxx_mib_stop(priv); |
||
2286 | ar8xxx_free(priv); |
||
2287 | } |
||
2288 | |||
2289 | static int |
||
2290 | ar8xxx_phy_soft_reset(struct phy_device *phydev) |
||
2291 | { |
||
2292 | /* we don't need an extra reset */ |
||
2293 | return 0; |
||
2294 | } |
||
2295 | |||
2296 | static struct phy_driver ar8xxx_phy_driver[] = { |
||
2297 | { |
||
2298 | .phy_id = 0x004d0000, |
||
2299 | .name = "Atheros AR8216/AR8236/AR8316", |
||
2300 | .phy_id_mask = 0xffff0000, |
||
2301 | .features = PHY_BASIC_FEATURES, |
||
2302 | .probe = ar8xxx_phy_probe, |
||
2303 | .remove = ar8xxx_phy_remove, |
||
2304 | .detach = ar8xxx_phy_detach, |
||
2305 | .config_init = ar8xxx_phy_config_init, |
||
2306 | .config_aneg = ar8xxx_phy_config_aneg, |
||
2307 | .read_status = ar8xxx_phy_read_status, |
||
2308 | .soft_reset = ar8xxx_phy_soft_reset, |
||
2309 | } |
||
2310 | }; |
||
2311 | |||
2312 | module_phy_driver(ar8xxx_phy_driver); |
||
2313 | MODULE_LICENSE("GPL"); |