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