diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/sb1250-mac.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/sb1250-mac.c | 2690 |
1 files changed, 2690 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c new file mode 100644 index 000000000000..ea65f7ec360a --- /dev/null +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c | |||
@@ -0,0 +1,2690 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation | ||
3 | * Copyright (c) 2006, 2007 Maciej W. Rozycki | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | * | ||
19 | * | ||
20 | * This driver is designed for the Broadcom SiByte SOC built-in | ||
21 | * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp. | ||
22 | * | ||
23 | * Updated to the driver model and the PHY abstraction layer | ||
24 | * by Maciej W. Rozycki. | ||
25 | */ | ||
26 | |||
27 | #include <linux/bug.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/timer.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/ioport.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/bitops.h> | ||
41 | #include <linux/err.h> | ||
42 | #include <linux/ethtool.h> | ||
43 | #include <linux/mii.h> | ||
44 | #include <linux/phy.h> | ||
45 | #include <linux/platform_device.h> | ||
46 | #include <linux/prefetch.h> | ||
47 | |||
48 | #include <asm/cache.h> | ||
49 | #include <asm/io.h> | ||
50 | #include <asm/processor.h> /* Processor type for cache alignment. */ | ||
51 | |||
52 | /* Operational parameters that usually are not changed. */ | ||
53 | |||
54 | #define CONFIG_SBMAC_COALESCE | ||
55 | |||
56 | /* Time in jiffies before concluding the transmitter is hung. */ | ||
57 | #define TX_TIMEOUT (2*HZ) | ||
58 | |||
59 | |||
60 | MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)"); | ||
61 | MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver"); | ||
62 | |||
63 | /* A few user-configurable values which may be modified when a driver | ||
64 | module is loaded. */ | ||
65 | |||
66 | /* 1 normal messages, 0 quiet .. 7 verbose. */ | ||
67 | static int debug = 1; | ||
68 | module_param(debug, int, S_IRUGO); | ||
69 | MODULE_PARM_DESC(debug, "Debug messages"); | ||
70 | |||
71 | #ifdef CONFIG_SBMAC_COALESCE | ||
72 | static int int_pktcnt_tx = 255; | ||
73 | module_param(int_pktcnt_tx, int, S_IRUGO); | ||
74 | MODULE_PARM_DESC(int_pktcnt_tx, "TX packet count"); | ||
75 | |||
76 | static int int_timeout_tx = 255; | ||
77 | module_param(int_timeout_tx, int, S_IRUGO); | ||
78 | MODULE_PARM_DESC(int_timeout_tx, "TX timeout value"); | ||
79 | |||
80 | static int int_pktcnt_rx = 64; | ||
81 | module_param(int_pktcnt_rx, int, S_IRUGO); | ||
82 | MODULE_PARM_DESC(int_pktcnt_rx, "RX packet count"); | ||
83 | |||
84 | static int int_timeout_rx = 64; | ||
85 | module_param(int_timeout_rx, int, S_IRUGO); | ||
86 | MODULE_PARM_DESC(int_timeout_rx, "RX timeout value"); | ||
87 | #endif | ||
88 | |||
89 | #include <asm/sibyte/board.h> | ||
90 | #include <asm/sibyte/sb1250.h> | ||
91 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
92 | #include <asm/sibyte/bcm1480_regs.h> | ||
93 | #include <asm/sibyte/bcm1480_int.h> | ||
94 | #define R_MAC_DMA_OODPKTLOST_RX R_MAC_DMA_OODPKTLOST | ||
95 | #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) | ||
96 | #include <asm/sibyte/sb1250_regs.h> | ||
97 | #include <asm/sibyte/sb1250_int.h> | ||
98 | #else | ||
99 | #error invalid SiByte MAC configuration | ||
100 | #endif | ||
101 | #include <asm/sibyte/sb1250_scd.h> | ||
102 | #include <asm/sibyte/sb1250_mac.h> | ||
103 | #include <asm/sibyte/sb1250_dma.h> | ||
104 | |||
105 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
106 | #define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2)) | ||
107 | #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) | ||
108 | #define UNIT_INT(n) (K_INT_MAC_0 + (n)) | ||
109 | #else | ||
110 | #error invalid SiByte MAC configuration | ||
111 | #endif | ||
112 | |||
113 | #ifdef K_INT_PHY | ||
114 | #define SBMAC_PHY_INT K_INT_PHY | ||
115 | #else | ||
116 | #define SBMAC_PHY_INT PHY_POLL | ||
117 | #endif | ||
118 | |||
119 | /********************************************************************** | ||
120 | * Simple types | ||
121 | ********************************************************************* */ | ||
122 | |||
123 | enum sbmac_speed { | ||
124 | sbmac_speed_none = 0, | ||
125 | sbmac_speed_10 = SPEED_10, | ||
126 | sbmac_speed_100 = SPEED_100, | ||
127 | sbmac_speed_1000 = SPEED_1000, | ||
128 | }; | ||
129 | |||
130 | enum sbmac_duplex { | ||
131 | sbmac_duplex_none = -1, | ||
132 | sbmac_duplex_half = DUPLEX_HALF, | ||
133 | sbmac_duplex_full = DUPLEX_FULL, | ||
134 | }; | ||
135 | |||
136 | enum sbmac_fc { | ||
137 | sbmac_fc_none, | ||
138 | sbmac_fc_disabled, | ||
139 | sbmac_fc_frame, | ||
140 | sbmac_fc_collision, | ||
141 | sbmac_fc_carrier, | ||
142 | }; | ||
143 | |||
144 | enum sbmac_state { | ||
145 | sbmac_state_uninit, | ||
146 | sbmac_state_off, | ||
147 | sbmac_state_on, | ||
148 | sbmac_state_broken, | ||
149 | }; | ||
150 | |||
151 | |||
152 | /********************************************************************** | ||
153 | * Macros | ||
154 | ********************************************************************* */ | ||
155 | |||
156 | |||
157 | #define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \ | ||
158 | (d)->sbdma_dscrtable : (d)->f+1) | ||
159 | |||
160 | |||
161 | #define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES) | ||
162 | |||
163 | #define SBMAC_MAX_TXDESCR 256 | ||
164 | #define SBMAC_MAX_RXDESCR 256 | ||
165 | |||
166 | #define ETHER_ADDR_LEN 6 | ||
167 | #define ENET_PACKET_SIZE 1518 | ||
168 | /*#define ENET_PACKET_SIZE 9216 */ | ||
169 | |||
170 | /********************************************************************** | ||
171 | * DMA Descriptor structure | ||
172 | ********************************************************************* */ | ||
173 | |||
174 | struct sbdmadscr { | ||
175 | uint64_t dscr_a; | ||
176 | uint64_t dscr_b; | ||
177 | }; | ||
178 | |||
179 | /********************************************************************** | ||
180 | * DMA Controller structure | ||
181 | ********************************************************************* */ | ||
182 | |||
183 | struct sbmacdma { | ||
184 | |||
185 | /* | ||
186 | * This stuff is used to identify the channel and the registers | ||
187 | * associated with it. | ||
188 | */ | ||
189 | struct sbmac_softc *sbdma_eth; /* back pointer to associated | ||
190 | MAC */ | ||
191 | int sbdma_channel; /* channel number */ | ||
192 | int sbdma_txdir; /* direction (1=transmit) */ | ||
193 | int sbdma_maxdescr; /* total # of descriptors | ||
194 | in ring */ | ||
195 | #ifdef CONFIG_SBMAC_COALESCE | ||
196 | int sbdma_int_pktcnt; | ||
197 | /* # descriptors rx/tx | ||
198 | before interrupt */ | ||
199 | int sbdma_int_timeout; | ||
200 | /* # usec rx/tx interrupt */ | ||
201 | #endif | ||
202 | void __iomem *sbdma_config0; /* DMA config register 0 */ | ||
203 | void __iomem *sbdma_config1; /* DMA config register 1 */ | ||
204 | void __iomem *sbdma_dscrbase; | ||
205 | /* descriptor base address */ | ||
206 | void __iomem *sbdma_dscrcnt; /* descriptor count register */ | ||
207 | void __iomem *sbdma_curdscr; /* current descriptor | ||
208 | address */ | ||
209 | void __iomem *sbdma_oodpktlost; | ||
210 | /* pkt drop (rx only) */ | ||
211 | |||
212 | /* | ||
213 | * This stuff is for maintenance of the ring | ||
214 | */ | ||
215 | void *sbdma_dscrtable_unaligned; | ||
216 | struct sbdmadscr *sbdma_dscrtable; | ||
217 | /* base of descriptor table */ | ||
218 | struct sbdmadscr *sbdma_dscrtable_end; | ||
219 | /* end of descriptor table */ | ||
220 | struct sk_buff **sbdma_ctxtable; | ||
221 | /* context table, one | ||
222 | per descr */ | ||
223 | dma_addr_t sbdma_dscrtable_phys; | ||
224 | /* and also the phys addr */ | ||
225 | struct sbdmadscr *sbdma_addptr; /* next dscr for sw to add */ | ||
226 | struct sbdmadscr *sbdma_remptr; /* next dscr for sw | ||
227 | to remove */ | ||
228 | }; | ||
229 | |||
230 | |||
231 | /********************************************************************** | ||
232 | * Ethernet softc structure | ||
233 | ********************************************************************* */ | ||
234 | |||
235 | struct sbmac_softc { | ||
236 | |||
237 | /* | ||
238 | * Linux-specific things | ||
239 | */ | ||
240 | struct net_device *sbm_dev; /* pointer to linux device */ | ||
241 | struct napi_struct napi; | ||
242 | struct phy_device *phy_dev; /* the associated PHY device */ | ||
243 | struct mii_bus *mii_bus; /* the MII bus */ | ||
244 | int phy_irq[PHY_MAX_ADDR]; | ||
245 | spinlock_t sbm_lock; /* spin lock */ | ||
246 | int sbm_devflags; /* current device flags */ | ||
247 | |||
248 | /* | ||
249 | * Controller-specific things | ||
250 | */ | ||
251 | void __iomem *sbm_base; /* MAC's base address */ | ||
252 | enum sbmac_state sbm_state; /* current state */ | ||
253 | |||
254 | void __iomem *sbm_macenable; /* MAC Enable Register */ | ||
255 | void __iomem *sbm_maccfg; /* MAC Config Register */ | ||
256 | void __iomem *sbm_fifocfg; /* FIFO Config Register */ | ||
257 | void __iomem *sbm_framecfg; /* Frame Config Register */ | ||
258 | void __iomem *sbm_rxfilter; /* Receive Filter Register */ | ||
259 | void __iomem *sbm_isr; /* Interrupt Status Register */ | ||
260 | void __iomem *sbm_imr; /* Interrupt Mask Register */ | ||
261 | void __iomem *sbm_mdio; /* MDIO Register */ | ||
262 | |||
263 | enum sbmac_speed sbm_speed; /* current speed */ | ||
264 | enum sbmac_duplex sbm_duplex; /* current duplex */ | ||
265 | enum sbmac_fc sbm_fc; /* cur. flow control setting */ | ||
266 | int sbm_pause; /* current pause setting */ | ||
267 | int sbm_link; /* current link state */ | ||
268 | |||
269 | unsigned char sbm_hwaddr[ETHER_ADDR_LEN]; | ||
270 | |||
271 | struct sbmacdma sbm_txdma; /* only channel 0 for now */ | ||
272 | struct sbmacdma sbm_rxdma; | ||
273 | int rx_hw_checksum; | ||
274 | int sbe_idx; | ||
275 | }; | ||
276 | |||
277 | |||
278 | /********************************************************************** | ||
279 | * Externs | ||
280 | ********************************************************************* */ | ||
281 | |||
282 | /********************************************************************** | ||
283 | * Prototypes | ||
284 | ********************************************************************* */ | ||
285 | |||
286 | static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, | ||
287 | int txrx, int maxdescr); | ||
288 | static void sbdma_channel_start(struct sbmacdma *d, int rxtx); | ||
289 | static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, | ||
290 | struct sk_buff *m); | ||
291 | static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m); | ||
292 | static void sbdma_emptyring(struct sbmacdma *d); | ||
293 | static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d); | ||
294 | static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, | ||
295 | int work_to_do, int poll); | ||
296 | static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, | ||
297 | int poll); | ||
298 | static int sbmac_initctx(struct sbmac_softc *s); | ||
299 | static void sbmac_channel_start(struct sbmac_softc *s); | ||
300 | static void sbmac_channel_stop(struct sbmac_softc *s); | ||
301 | static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *, | ||
302 | enum sbmac_state); | ||
303 | static void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff); | ||
304 | static uint64_t sbmac_addr2reg(unsigned char *ptr); | ||
305 | static irqreturn_t sbmac_intr(int irq, void *dev_instance); | ||
306 | static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev); | ||
307 | static void sbmac_setmulti(struct sbmac_softc *sc); | ||
308 | static int sbmac_init(struct platform_device *pldev, long long base); | ||
309 | static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed); | ||
310 | static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, | ||
311 | enum sbmac_fc fc); | ||
312 | |||
313 | static int sbmac_open(struct net_device *dev); | ||
314 | static void sbmac_tx_timeout (struct net_device *dev); | ||
315 | static void sbmac_set_rx_mode(struct net_device *dev); | ||
316 | static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
317 | static int sbmac_close(struct net_device *dev); | ||
318 | static int sbmac_poll(struct napi_struct *napi, int budget); | ||
319 | |||
320 | static void sbmac_mii_poll(struct net_device *dev); | ||
321 | static int sbmac_mii_probe(struct net_device *dev); | ||
322 | |||
323 | static void sbmac_mii_sync(void __iomem *sbm_mdio); | ||
324 | static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, | ||
325 | int bitcnt); | ||
326 | static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx); | ||
327 | static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, | ||
328 | u16 val); | ||
329 | |||
330 | |||
331 | /********************************************************************** | ||
332 | * Globals | ||
333 | ********************************************************************* */ | ||
334 | |||
335 | static char sbmac_string[] = "sb1250-mac"; | ||
336 | |||
337 | static char sbmac_mdio_string[] = "sb1250-mac-mdio"; | ||
338 | |||
339 | |||
340 | /********************************************************************** | ||
341 | * MDIO constants | ||
342 | ********************************************************************* */ | ||
343 | |||
344 | #define MII_COMMAND_START 0x01 | ||
345 | #define MII_COMMAND_READ 0x02 | ||
346 | #define MII_COMMAND_WRITE 0x01 | ||
347 | #define MII_COMMAND_ACK 0x02 | ||
348 | |||
349 | #define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ | ||
350 | |||
351 | #define ENABLE 1 | ||
352 | #define DISABLE 0 | ||
353 | |||
354 | /********************************************************************** | ||
355 | * SBMAC_MII_SYNC(sbm_mdio) | ||
356 | * | ||
357 | * Synchronize with the MII - send a pattern of bits to the MII | ||
358 | * that will guarantee that it is ready to accept a command. | ||
359 | * | ||
360 | * Input parameters: | ||
361 | * sbm_mdio - address of the MAC's MDIO register | ||
362 | * | ||
363 | * Return value: | ||
364 | * nothing | ||
365 | ********************************************************************* */ | ||
366 | |||
367 | static void sbmac_mii_sync(void __iomem *sbm_mdio) | ||
368 | { | ||
369 | int cnt; | ||
370 | uint64_t bits; | ||
371 | int mac_mdio_genc; | ||
372 | |||
373 | mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; | ||
374 | |||
375 | bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT; | ||
376 | |||
377 | __raw_writeq(bits | mac_mdio_genc, sbm_mdio); | ||
378 | |||
379 | for (cnt = 0; cnt < 32; cnt++) { | ||
380 | __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); | ||
381 | __raw_writeq(bits | mac_mdio_genc, sbm_mdio); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | /********************************************************************** | ||
386 | * SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt) | ||
387 | * | ||
388 | * Send some bits to the MII. The bits to be sent are right- | ||
389 | * justified in the 'data' parameter. | ||
390 | * | ||
391 | * Input parameters: | ||
392 | * sbm_mdio - address of the MAC's MDIO register | ||
393 | * data - data to send | ||
394 | * bitcnt - number of bits to send | ||
395 | ********************************************************************* */ | ||
396 | |||
397 | static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, | ||
398 | int bitcnt) | ||
399 | { | ||
400 | int i; | ||
401 | uint64_t bits; | ||
402 | unsigned int curmask; | ||
403 | int mac_mdio_genc; | ||
404 | |||
405 | mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; | ||
406 | |||
407 | bits = M_MAC_MDIO_DIR_OUTPUT; | ||
408 | __raw_writeq(bits | mac_mdio_genc, sbm_mdio); | ||
409 | |||
410 | curmask = 1 << (bitcnt - 1); | ||
411 | |||
412 | for (i = 0; i < bitcnt; i++) { | ||
413 | if (data & curmask) | ||
414 | bits |= M_MAC_MDIO_OUT; | ||
415 | else bits &= ~M_MAC_MDIO_OUT; | ||
416 | __raw_writeq(bits | mac_mdio_genc, sbm_mdio); | ||
417 | __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); | ||
418 | __raw_writeq(bits | mac_mdio_genc, sbm_mdio); | ||
419 | curmask >>= 1; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | |||
424 | |||
425 | /********************************************************************** | ||
426 | * SBMAC_MII_READ(bus, phyaddr, regidx) | ||
427 | * Read a PHY register. | ||
428 | * | ||
429 | * Input parameters: | ||
430 | * bus - MDIO bus handle | ||
431 | * phyaddr - PHY's address | ||
432 | * regnum - index of register to read | ||
433 | * | ||
434 | * Return value: | ||
435 | * value read, or 0xffff if an error occurred. | ||
436 | ********************************************************************* */ | ||
437 | |||
438 | static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx) | ||
439 | { | ||
440 | struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; | ||
441 | void __iomem *sbm_mdio = sc->sbm_mdio; | ||
442 | int idx; | ||
443 | int error; | ||
444 | int regval; | ||
445 | int mac_mdio_genc; | ||
446 | |||
447 | /* | ||
448 | * Synchronize ourselves so that the PHY knows the next | ||
449 | * thing coming down is a command | ||
450 | */ | ||
451 | sbmac_mii_sync(sbm_mdio); | ||
452 | |||
453 | /* | ||
454 | * Send the data to the PHY. The sequence is | ||
455 | * a "start" command (2 bits) | ||
456 | * a "read" command (2 bits) | ||
457 | * the PHY addr (5 bits) | ||
458 | * the register index (5 bits) | ||
459 | */ | ||
460 | sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); | ||
461 | sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2); | ||
462 | sbmac_mii_senddata(sbm_mdio, phyaddr, 5); | ||
463 | sbmac_mii_senddata(sbm_mdio, regidx, 5); | ||
464 | |||
465 | mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; | ||
466 | |||
467 | /* | ||
468 | * Switch the port around without a clock transition. | ||
469 | */ | ||
470 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); | ||
471 | |||
472 | /* | ||
473 | * Send out a clock pulse to signal we want the status | ||
474 | */ | ||
475 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, | ||
476 | sbm_mdio); | ||
477 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); | ||
478 | |||
479 | /* | ||
480 | * If an error occurred, the PHY will signal '1' back | ||
481 | */ | ||
482 | error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN; | ||
483 | |||
484 | /* | ||
485 | * Issue an 'idle' clock pulse, but keep the direction | ||
486 | * the same. | ||
487 | */ | ||
488 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, | ||
489 | sbm_mdio); | ||
490 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); | ||
491 | |||
492 | regval = 0; | ||
493 | |||
494 | for (idx = 0; idx < 16; idx++) { | ||
495 | regval <<= 1; | ||
496 | |||
497 | if (error == 0) { | ||
498 | if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN) | ||
499 | regval |= 1; | ||
500 | } | ||
501 | |||
502 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, | ||
503 | sbm_mdio); | ||
504 | __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); | ||
505 | } | ||
506 | |||
507 | /* Switch back to output */ | ||
508 | __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); | ||
509 | |||
510 | if (error == 0) | ||
511 | return regval; | ||
512 | return 0xffff; | ||
513 | } | ||
514 | |||
515 | |||
516 | /********************************************************************** | ||
517 | * SBMAC_MII_WRITE(bus, phyaddr, regidx, regval) | ||
518 | * | ||
519 | * Write a value to a PHY register. | ||
520 | * | ||
521 | * Input parameters: | ||
522 | * bus - MDIO bus handle | ||
523 | * phyaddr - PHY to use | ||
524 | * regidx - register within the PHY | ||
525 | * regval - data to write to register | ||
526 | * | ||
527 | * Return value: | ||
528 | * 0 for success | ||
529 | ********************************************************************* */ | ||
530 | |||
531 | static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, | ||
532 | u16 regval) | ||
533 | { | ||
534 | struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; | ||
535 | void __iomem *sbm_mdio = sc->sbm_mdio; | ||
536 | int mac_mdio_genc; | ||
537 | |||
538 | sbmac_mii_sync(sbm_mdio); | ||
539 | |||
540 | sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); | ||
541 | sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2); | ||
542 | sbmac_mii_senddata(sbm_mdio, phyaddr, 5); | ||
543 | sbmac_mii_senddata(sbm_mdio, regidx, 5); | ||
544 | sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2); | ||
545 | sbmac_mii_senddata(sbm_mdio, regval, 16); | ||
546 | |||
547 | mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; | ||
548 | |||
549 | __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | |||
555 | |||
556 | /********************************************************************** | ||
557 | * SBDMA_INITCTX(d,s,chan,txrx,maxdescr) | ||
558 | * | ||
559 | * Initialize a DMA channel context. Since there are potentially | ||
560 | * eight DMA channels per MAC, it's nice to do this in a standard | ||
561 | * way. | ||
562 | * | ||
563 | * Input parameters: | ||
564 | * d - struct sbmacdma (DMA channel context) | ||
565 | * s - struct sbmac_softc (pointer to a MAC) | ||
566 | * chan - channel number (0..1 right now) | ||
567 | * txrx - Identifies DMA_TX or DMA_RX for channel direction | ||
568 | * maxdescr - number of descriptors | ||
569 | * | ||
570 | * Return value: | ||
571 | * nothing | ||
572 | ********************************************************************* */ | ||
573 | |||
574 | static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, | ||
575 | int txrx, int maxdescr) | ||
576 | { | ||
577 | #ifdef CONFIG_SBMAC_COALESCE | ||
578 | int int_pktcnt, int_timeout; | ||
579 | #endif | ||
580 | |||
581 | /* | ||
582 | * Save away interesting stuff in the structure | ||
583 | */ | ||
584 | |||
585 | d->sbdma_eth = s; | ||
586 | d->sbdma_channel = chan; | ||
587 | d->sbdma_txdir = txrx; | ||
588 | |||
589 | #if 0 | ||
590 | /* RMON clearing */ | ||
591 | s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING; | ||
592 | #endif | ||
593 | |||
594 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES); | ||
595 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS); | ||
596 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL); | ||
597 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL); | ||
598 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR); | ||
599 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT); | ||
600 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD); | ||
601 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD); | ||
602 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT); | ||
603 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE); | ||
604 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES); | ||
605 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST); | ||
606 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST); | ||
607 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD); | ||
608 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD); | ||
609 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT); | ||
610 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE); | ||
611 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR); | ||
612 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR); | ||
613 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR); | ||
614 | __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR); | ||
615 | |||
616 | /* | ||
617 | * initialize register pointers | ||
618 | */ | ||
619 | |||
620 | d->sbdma_config0 = | ||
621 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0); | ||
622 | d->sbdma_config1 = | ||
623 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1); | ||
624 | d->sbdma_dscrbase = | ||
625 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE); | ||
626 | d->sbdma_dscrcnt = | ||
627 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT); | ||
628 | d->sbdma_curdscr = | ||
629 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR); | ||
630 | if (d->sbdma_txdir) | ||
631 | d->sbdma_oodpktlost = NULL; | ||
632 | else | ||
633 | d->sbdma_oodpktlost = | ||
634 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_OODPKTLOST_RX); | ||
635 | |||
636 | /* | ||
637 | * Allocate memory for the ring | ||
638 | */ | ||
639 | |||
640 | d->sbdma_maxdescr = maxdescr; | ||
641 | |||
642 | d->sbdma_dscrtable_unaligned = kcalloc(d->sbdma_maxdescr + 1, | ||
643 | sizeof(*d->sbdma_dscrtable), | ||
644 | GFP_KERNEL); | ||
645 | |||
646 | /* | ||
647 | * The descriptor table must be aligned to at least 16 bytes or the | ||
648 | * MAC will corrupt it. | ||
649 | */ | ||
650 | d->sbdma_dscrtable = (struct sbdmadscr *) | ||
651 | ALIGN((unsigned long)d->sbdma_dscrtable_unaligned, | ||
652 | sizeof(*d->sbdma_dscrtable)); | ||
653 | |||
654 | d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr; | ||
655 | |||
656 | d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable); | ||
657 | |||
658 | /* | ||
659 | * And context table | ||
660 | */ | ||
661 | |||
662 | d->sbdma_ctxtable = kcalloc(d->sbdma_maxdescr, | ||
663 | sizeof(*d->sbdma_ctxtable), GFP_KERNEL); | ||
664 | |||
665 | #ifdef CONFIG_SBMAC_COALESCE | ||
666 | /* | ||
667 | * Setup Rx/Tx DMA coalescing defaults | ||
668 | */ | ||
669 | |||
670 | int_pktcnt = (txrx == DMA_TX) ? int_pktcnt_tx : int_pktcnt_rx; | ||
671 | if ( int_pktcnt ) { | ||
672 | d->sbdma_int_pktcnt = int_pktcnt; | ||
673 | } else { | ||
674 | d->sbdma_int_pktcnt = 1; | ||
675 | } | ||
676 | |||
677 | int_timeout = (txrx == DMA_TX) ? int_timeout_tx : int_timeout_rx; | ||
678 | if ( int_timeout ) { | ||
679 | d->sbdma_int_timeout = int_timeout; | ||
680 | } else { | ||
681 | d->sbdma_int_timeout = 0; | ||
682 | } | ||
683 | #endif | ||
684 | |||
685 | } | ||
686 | |||
687 | /********************************************************************** | ||
688 | * SBDMA_CHANNEL_START(d) | ||
689 | * | ||
690 | * Initialize the hardware registers for a DMA channel. | ||
691 | * | ||
692 | * Input parameters: | ||
693 | * d - DMA channel to init (context must be previously init'd | ||
694 | * rxtx - DMA_RX or DMA_TX depending on what type of channel | ||
695 | * | ||
696 | * Return value: | ||
697 | * nothing | ||
698 | ********************************************************************* */ | ||
699 | |||
700 | static void sbdma_channel_start(struct sbmacdma *d, int rxtx) | ||
701 | { | ||
702 | /* | ||
703 | * Turn on the DMA channel | ||
704 | */ | ||
705 | |||
706 | #ifdef CONFIG_SBMAC_COALESCE | ||
707 | __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) | | ||
708 | 0, d->sbdma_config1); | ||
709 | __raw_writeq(M_DMA_EOP_INT_EN | | ||
710 | V_DMA_RINGSZ(d->sbdma_maxdescr) | | ||
711 | V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) | | ||
712 | 0, d->sbdma_config0); | ||
713 | #else | ||
714 | __raw_writeq(0, d->sbdma_config1); | ||
715 | __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) | | ||
716 | 0, d->sbdma_config0); | ||
717 | #endif | ||
718 | |||
719 | __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase); | ||
720 | |||
721 | /* | ||
722 | * Initialize ring pointers | ||
723 | */ | ||
724 | |||
725 | d->sbdma_addptr = d->sbdma_dscrtable; | ||
726 | d->sbdma_remptr = d->sbdma_dscrtable; | ||
727 | } | ||
728 | |||
729 | /********************************************************************** | ||
730 | * SBDMA_CHANNEL_STOP(d) | ||
731 | * | ||
732 | * Initialize the hardware registers for a DMA channel. | ||
733 | * | ||
734 | * Input parameters: | ||
735 | * d - DMA channel to init (context must be previously init'd | ||
736 | * | ||
737 | * Return value: | ||
738 | * nothing | ||
739 | ********************************************************************* */ | ||
740 | |||
741 | static void sbdma_channel_stop(struct sbmacdma *d) | ||
742 | { | ||
743 | /* | ||
744 | * Turn off the DMA channel | ||
745 | */ | ||
746 | |||
747 | __raw_writeq(0, d->sbdma_config1); | ||
748 | |||
749 | __raw_writeq(0, d->sbdma_dscrbase); | ||
750 | |||
751 | __raw_writeq(0, d->sbdma_config0); | ||
752 | |||
753 | /* | ||
754 | * Zero ring pointers | ||
755 | */ | ||
756 | |||
757 | d->sbdma_addptr = NULL; | ||
758 | d->sbdma_remptr = NULL; | ||
759 | } | ||
760 | |||
761 | static inline void sbdma_align_skb(struct sk_buff *skb, | ||
762 | unsigned int power2, unsigned int offset) | ||
763 | { | ||
764 | unsigned char *addr = skb->data; | ||
765 | unsigned char *newaddr = PTR_ALIGN(addr, power2); | ||
766 | |||
767 | skb_reserve(skb, newaddr - addr + offset); | ||
768 | } | ||
769 | |||
770 | |||
771 | /********************************************************************** | ||
772 | * SBDMA_ADD_RCVBUFFER(d,sb) | ||
773 | * | ||
774 | * Add a buffer to the specified DMA channel. For receive channels, | ||
775 | * this queues a buffer for inbound packets. | ||
776 | * | ||
777 | * Input parameters: | ||
778 | * sc - softc structure | ||
779 | * d - DMA channel descriptor | ||
780 | * sb - sk_buff to add, or NULL if we should allocate one | ||
781 | * | ||
782 | * Return value: | ||
783 | * 0 if buffer could not be added (ring is full) | ||
784 | * 1 if buffer added successfully | ||
785 | ********************************************************************* */ | ||
786 | |||
787 | |||
788 | static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, | ||
789 | struct sk_buff *sb) | ||
790 | { | ||
791 | struct net_device *dev = sc->sbm_dev; | ||
792 | struct sbdmadscr *dsc; | ||
793 | struct sbdmadscr *nextdsc; | ||
794 | struct sk_buff *sb_new = NULL; | ||
795 | int pktsize = ENET_PACKET_SIZE; | ||
796 | |||
797 | /* get pointer to our current place in the ring */ | ||
798 | |||
799 | dsc = d->sbdma_addptr; | ||
800 | nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); | ||
801 | |||
802 | /* | ||
803 | * figure out if the ring is full - if the next descriptor | ||
804 | * is the same as the one that we're going to remove from | ||
805 | * the ring, the ring is full | ||
806 | */ | ||
807 | |||
808 | if (nextdsc == d->sbdma_remptr) { | ||
809 | return -ENOSPC; | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * Allocate a sk_buff if we don't already have one. | ||
814 | * If we do have an sk_buff, reset it so that it's empty. | ||
815 | * | ||
816 | * Note: sk_buffs don't seem to be guaranteed to have any sort | ||
817 | * of alignment when they are allocated. Therefore, allocate enough | ||
818 | * extra space to make sure that: | ||
819 | * | ||
820 | * 1. the data does not start in the middle of a cache line. | ||
821 | * 2. The data does not end in the middle of a cache line | ||
822 | * 3. The buffer can be aligned such that the IP addresses are | ||
823 | * naturally aligned. | ||
824 | * | ||
825 | * Remember, the SOCs MAC writes whole cache lines at a time, | ||
826 | * without reading the old contents first. So, if the sk_buff's | ||
827 | * data portion starts in the middle of a cache line, the SOC | ||
828 | * DMA will trash the beginning (and ending) portions. | ||
829 | */ | ||
830 | |||
831 | if (sb == NULL) { | ||
832 | sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE + | ||
833 | SMP_CACHE_BYTES * 2 + | ||
834 | NET_IP_ALIGN); | ||
835 | if (sb_new == NULL) { | ||
836 | pr_info("%s: sk_buff allocation failed\n", | ||
837 | d->sbdma_eth->sbm_dev->name); | ||
838 | return -ENOBUFS; | ||
839 | } | ||
840 | |||
841 | sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN); | ||
842 | } | ||
843 | else { | ||
844 | sb_new = sb; | ||
845 | /* | ||
846 | * nothing special to reinit buffer, it's already aligned | ||
847 | * and sb->data already points to a good place. | ||
848 | */ | ||
849 | } | ||
850 | |||
851 | /* | ||
852 | * fill in the descriptor | ||
853 | */ | ||
854 | |||
855 | #ifdef CONFIG_SBMAC_COALESCE | ||
856 | /* | ||
857 | * Do not interrupt per DMA transfer. | ||
858 | */ | ||
859 | dsc->dscr_a = virt_to_phys(sb_new->data) | | ||
860 | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0; | ||
861 | #else | ||
862 | dsc->dscr_a = virt_to_phys(sb_new->data) | | ||
863 | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | | ||
864 | M_DMA_DSCRA_INTERRUPT; | ||
865 | #endif | ||
866 | |||
867 | /* receiving: no options */ | ||
868 | dsc->dscr_b = 0; | ||
869 | |||
870 | /* | ||
871 | * fill in the context | ||
872 | */ | ||
873 | |||
874 | d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new; | ||
875 | |||
876 | /* | ||
877 | * point at next packet | ||
878 | */ | ||
879 | |||
880 | d->sbdma_addptr = nextdsc; | ||
881 | |||
882 | /* | ||
883 | * Give the buffer to the DMA engine. | ||
884 | */ | ||
885 | |||
886 | __raw_writeq(1, d->sbdma_dscrcnt); | ||
887 | |||
888 | return 0; /* we did it */ | ||
889 | } | ||
890 | |||
891 | /********************************************************************** | ||
892 | * SBDMA_ADD_TXBUFFER(d,sb) | ||
893 | * | ||
894 | * Add a transmit buffer to the specified DMA channel, causing a | ||
895 | * transmit to start. | ||
896 | * | ||
897 | * Input parameters: | ||
898 | * d - DMA channel descriptor | ||
899 | * sb - sk_buff to add | ||
900 | * | ||
901 | * Return value: | ||
902 | * 0 transmit queued successfully | ||
903 | * otherwise error code | ||
904 | ********************************************************************* */ | ||
905 | |||
906 | |||
907 | static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *sb) | ||
908 | { | ||
909 | struct sbdmadscr *dsc; | ||
910 | struct sbdmadscr *nextdsc; | ||
911 | uint64_t phys; | ||
912 | uint64_t ncb; | ||
913 | int length; | ||
914 | |||
915 | /* get pointer to our current place in the ring */ | ||
916 | |||
917 | dsc = d->sbdma_addptr; | ||
918 | nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); | ||
919 | |||
920 | /* | ||
921 | * figure out if the ring is full - if the next descriptor | ||
922 | * is the same as the one that we're going to remove from | ||
923 | * the ring, the ring is full | ||
924 | */ | ||
925 | |||
926 | if (nextdsc == d->sbdma_remptr) { | ||
927 | return -ENOSPC; | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * Under Linux, it's not necessary to copy/coalesce buffers | ||
932 | * like it is on NetBSD. We think they're all contiguous, | ||
933 | * but that may not be true for GBE. | ||
934 | */ | ||
935 | |||
936 | length = sb->len; | ||
937 | |||
938 | /* | ||
939 | * fill in the descriptor. Note that the number of cache | ||
940 | * blocks in the descriptor is the number of blocks | ||
941 | * *spanned*, so we need to add in the offset (if any) | ||
942 | * while doing the calculation. | ||
943 | */ | ||
944 | |||
945 | phys = virt_to_phys(sb->data); | ||
946 | ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1))); | ||
947 | |||
948 | dsc->dscr_a = phys | | ||
949 | V_DMA_DSCRA_A_SIZE(ncb) | | ||
950 | #ifndef CONFIG_SBMAC_COALESCE | ||
951 | M_DMA_DSCRA_INTERRUPT | | ||
952 | #endif | ||
953 | M_DMA_ETHTX_SOP; | ||
954 | |||
955 | /* transmitting: set outbound options and length */ | ||
956 | |||
957 | dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | | ||
958 | V_DMA_DSCRB_PKT_SIZE(length); | ||
959 | |||
960 | /* | ||
961 | * fill in the context | ||
962 | */ | ||
963 | |||
964 | d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb; | ||
965 | |||
966 | /* | ||
967 | * point at next packet | ||
968 | */ | ||
969 | |||
970 | d->sbdma_addptr = nextdsc; | ||
971 | |||
972 | /* | ||
973 | * Give the buffer to the DMA engine. | ||
974 | */ | ||
975 | |||
976 | __raw_writeq(1, d->sbdma_dscrcnt); | ||
977 | |||
978 | return 0; /* we did it */ | ||
979 | } | ||
980 | |||
981 | |||
982 | |||
983 | |||
984 | /********************************************************************** | ||
985 | * SBDMA_EMPTYRING(d) | ||
986 | * | ||
987 | * Free all allocated sk_buffs on the specified DMA channel; | ||
988 | * | ||
989 | * Input parameters: | ||
990 | * d - DMA channel | ||
991 | * | ||
992 | * Return value: | ||
993 | * nothing | ||
994 | ********************************************************************* */ | ||
995 | |||
996 | static void sbdma_emptyring(struct sbmacdma *d) | ||
997 | { | ||
998 | int idx; | ||
999 | struct sk_buff *sb; | ||
1000 | |||
1001 | for (idx = 0; idx < d->sbdma_maxdescr; idx++) { | ||
1002 | sb = d->sbdma_ctxtable[idx]; | ||
1003 | if (sb) { | ||
1004 | dev_kfree_skb(sb); | ||
1005 | d->sbdma_ctxtable[idx] = NULL; | ||
1006 | } | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /********************************************************************** | ||
1012 | * SBDMA_FILLRING(d) | ||
1013 | * | ||
1014 | * Fill the specified DMA channel (must be receive channel) | ||
1015 | * with sk_buffs | ||
1016 | * | ||
1017 | * Input parameters: | ||
1018 | * sc - softc structure | ||
1019 | * d - DMA channel | ||
1020 | * | ||
1021 | * Return value: | ||
1022 | * nothing | ||
1023 | ********************************************************************* */ | ||
1024 | |||
1025 | static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d) | ||
1026 | { | ||
1027 | int idx; | ||
1028 | |||
1029 | for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) { | ||
1030 | if (sbdma_add_rcvbuffer(sc, d, NULL) != 0) | ||
1031 | break; | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1036 | static void sbmac_netpoll(struct net_device *netdev) | ||
1037 | { | ||
1038 | struct sbmac_softc *sc = netdev_priv(netdev); | ||
1039 | int irq = sc->sbm_dev->irq; | ||
1040 | |||
1041 | __raw_writeq(0, sc->sbm_imr); | ||
1042 | |||
1043 | sbmac_intr(irq, netdev); | ||
1044 | |||
1045 | #ifdef CONFIG_SBMAC_COALESCE | ||
1046 | __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | | ||
1047 | ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), | ||
1048 | sc->sbm_imr); | ||
1049 | #else | ||
1050 | __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | | ||
1051 | (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); | ||
1052 | #endif | ||
1053 | } | ||
1054 | #endif | ||
1055 | |||
1056 | /********************************************************************** | ||
1057 | * SBDMA_RX_PROCESS(sc,d,work_to_do,poll) | ||
1058 | * | ||
1059 | * Process "completed" receive buffers on the specified DMA channel. | ||
1060 | * | ||
1061 | * Input parameters: | ||
1062 | * sc - softc structure | ||
1063 | * d - DMA channel context | ||
1064 | * work_to_do - no. of packets to process before enabling interrupt | ||
1065 | * again (for NAPI) | ||
1066 | * poll - 1: using polling (for NAPI) | ||
1067 | * | ||
1068 | * Return value: | ||
1069 | * nothing | ||
1070 | ********************************************************************* */ | ||
1071 | |||
1072 | static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, | ||
1073 | int work_to_do, int poll) | ||
1074 | { | ||
1075 | struct net_device *dev = sc->sbm_dev; | ||
1076 | int curidx; | ||
1077 | int hwidx; | ||
1078 | struct sbdmadscr *dsc; | ||
1079 | struct sk_buff *sb; | ||
1080 | int len; | ||
1081 | int work_done = 0; | ||
1082 | int dropped = 0; | ||
1083 | |||
1084 | prefetch(d); | ||
1085 | |||
1086 | again: | ||
1087 | /* Check if the HW dropped any frames */ | ||
1088 | dev->stats.rx_fifo_errors | ||
1089 | += __raw_readq(sc->sbm_rxdma.sbdma_oodpktlost) & 0xffff; | ||
1090 | __raw_writeq(0, sc->sbm_rxdma.sbdma_oodpktlost); | ||
1091 | |||
1092 | while (work_to_do-- > 0) { | ||
1093 | /* | ||
1094 | * figure out where we are (as an index) and where | ||
1095 | * the hardware is (also as an index) | ||
1096 | * | ||
1097 | * This could be done faster if (for example) the | ||
1098 | * descriptor table was page-aligned and contiguous in | ||
1099 | * both virtual and physical memory -- you could then | ||
1100 | * just compare the low-order bits of the virtual address | ||
1101 | * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) | ||
1102 | */ | ||
1103 | |||
1104 | dsc = d->sbdma_remptr; | ||
1105 | curidx = dsc - d->sbdma_dscrtable; | ||
1106 | |||
1107 | prefetch(dsc); | ||
1108 | prefetch(&d->sbdma_ctxtable[curidx]); | ||
1109 | |||
1110 | hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - | ||
1111 | d->sbdma_dscrtable_phys) / | ||
1112 | sizeof(*d->sbdma_dscrtable); | ||
1113 | |||
1114 | /* | ||
1115 | * If they're the same, that means we've processed all | ||
1116 | * of the descriptors up to (but not including) the one that | ||
1117 | * the hardware is working on right now. | ||
1118 | */ | ||
1119 | |||
1120 | if (curidx == hwidx) | ||
1121 | goto done; | ||
1122 | |||
1123 | /* | ||
1124 | * Otherwise, get the packet's sk_buff ptr back | ||
1125 | */ | ||
1126 | |||
1127 | sb = d->sbdma_ctxtable[curidx]; | ||
1128 | d->sbdma_ctxtable[curidx] = NULL; | ||
1129 | |||
1130 | len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4; | ||
1131 | |||
1132 | /* | ||
1133 | * Check packet status. If good, process it. | ||
1134 | * If not, silently drop it and put it back on the | ||
1135 | * receive ring. | ||
1136 | */ | ||
1137 | |||
1138 | if (likely (!(dsc->dscr_a & M_DMA_ETHRX_BAD))) { | ||
1139 | |||
1140 | /* | ||
1141 | * Add a new buffer to replace the old one. If we fail | ||
1142 | * to allocate a buffer, we're going to drop this | ||
1143 | * packet and put it right back on the receive ring. | ||
1144 | */ | ||
1145 | |||
1146 | if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) == | ||
1147 | -ENOBUFS)) { | ||
1148 | dev->stats.rx_dropped++; | ||
1149 | /* Re-add old buffer */ | ||
1150 | sbdma_add_rcvbuffer(sc, d, sb); | ||
1151 | /* No point in continuing at the moment */ | ||
1152 | printk(KERN_ERR "dropped packet (1)\n"); | ||
1153 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1154 | goto done; | ||
1155 | } else { | ||
1156 | /* | ||
1157 | * Set length into the packet | ||
1158 | */ | ||
1159 | skb_put(sb,len); | ||
1160 | |||
1161 | /* | ||
1162 | * Buffer has been replaced on the | ||
1163 | * receive ring. Pass the buffer to | ||
1164 | * the kernel | ||
1165 | */ | ||
1166 | sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); | ||
1167 | /* Check hw IPv4/TCP checksum if supported */ | ||
1168 | if (sc->rx_hw_checksum == ENABLE) { | ||
1169 | if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) && | ||
1170 | !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) { | ||
1171 | sb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1172 | /* don't need to set sb->csum */ | ||
1173 | } else { | ||
1174 | skb_checksum_none_assert(sb); | ||
1175 | } | ||
1176 | } | ||
1177 | prefetch(sb->data); | ||
1178 | prefetch((const void *)(((char *)sb->data)+32)); | ||
1179 | if (poll) | ||
1180 | dropped = netif_receive_skb(sb); | ||
1181 | else | ||
1182 | dropped = netif_rx(sb); | ||
1183 | |||
1184 | if (dropped == NET_RX_DROP) { | ||
1185 | dev->stats.rx_dropped++; | ||
1186 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1187 | goto done; | ||
1188 | } | ||
1189 | else { | ||
1190 | dev->stats.rx_bytes += len; | ||
1191 | dev->stats.rx_packets++; | ||
1192 | } | ||
1193 | } | ||
1194 | } else { | ||
1195 | /* | ||
1196 | * Packet was mangled somehow. Just drop it and | ||
1197 | * put it back on the receive ring. | ||
1198 | */ | ||
1199 | dev->stats.rx_errors++; | ||
1200 | sbdma_add_rcvbuffer(sc, d, sb); | ||
1201 | } | ||
1202 | |||
1203 | |||
1204 | /* | ||
1205 | * .. and advance to the next buffer. | ||
1206 | */ | ||
1207 | |||
1208 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1209 | work_done++; | ||
1210 | } | ||
1211 | if (!poll) { | ||
1212 | work_to_do = 32; | ||
1213 | goto again; /* collect fifo drop statistics again */ | ||
1214 | } | ||
1215 | done: | ||
1216 | return work_done; | ||
1217 | } | ||
1218 | |||
1219 | /********************************************************************** | ||
1220 | * SBDMA_TX_PROCESS(sc,d) | ||
1221 | * | ||
1222 | * Process "completed" transmit buffers on the specified DMA channel. | ||
1223 | * This is normally called within the interrupt service routine. | ||
1224 | * Note that this isn't really ideal for priority channels, since | ||
1225 | * it processes all of the packets on a given channel before | ||
1226 | * returning. | ||
1227 | * | ||
1228 | * Input parameters: | ||
1229 | * sc - softc structure | ||
1230 | * d - DMA channel context | ||
1231 | * poll - 1: using polling (for NAPI) | ||
1232 | * | ||
1233 | * Return value: | ||
1234 | * nothing | ||
1235 | ********************************************************************* */ | ||
1236 | |||
1237 | static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, | ||
1238 | int poll) | ||
1239 | { | ||
1240 | struct net_device *dev = sc->sbm_dev; | ||
1241 | int curidx; | ||
1242 | int hwidx; | ||
1243 | struct sbdmadscr *dsc; | ||
1244 | struct sk_buff *sb; | ||
1245 | unsigned long flags; | ||
1246 | int packets_handled = 0; | ||
1247 | |||
1248 | spin_lock_irqsave(&(sc->sbm_lock), flags); | ||
1249 | |||
1250 | if (d->sbdma_remptr == d->sbdma_addptr) | ||
1251 | goto end_unlock; | ||
1252 | |||
1253 | hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - | ||
1254 | d->sbdma_dscrtable_phys) / sizeof(*d->sbdma_dscrtable); | ||
1255 | |||
1256 | for (;;) { | ||
1257 | /* | ||
1258 | * figure out where we are (as an index) and where | ||
1259 | * the hardware is (also as an index) | ||
1260 | * | ||
1261 | * This could be done faster if (for example) the | ||
1262 | * descriptor table was page-aligned and contiguous in | ||
1263 | * both virtual and physical memory -- you could then | ||
1264 | * just compare the low-order bits of the virtual address | ||
1265 | * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) | ||
1266 | */ | ||
1267 | |||
1268 | curidx = d->sbdma_remptr - d->sbdma_dscrtable; | ||
1269 | |||
1270 | /* | ||
1271 | * If they're the same, that means we've processed all | ||
1272 | * of the descriptors up to (but not including) the one that | ||
1273 | * the hardware is working on right now. | ||
1274 | */ | ||
1275 | |||
1276 | if (curidx == hwidx) | ||
1277 | break; | ||
1278 | |||
1279 | /* | ||
1280 | * Otherwise, get the packet's sk_buff ptr back | ||
1281 | */ | ||
1282 | |||
1283 | dsc = &(d->sbdma_dscrtable[curidx]); | ||
1284 | sb = d->sbdma_ctxtable[curidx]; | ||
1285 | d->sbdma_ctxtable[curidx] = NULL; | ||
1286 | |||
1287 | /* | ||
1288 | * Stats | ||
1289 | */ | ||
1290 | |||
1291 | dev->stats.tx_bytes += sb->len; | ||
1292 | dev->stats.tx_packets++; | ||
1293 | |||
1294 | /* | ||
1295 | * for transmits, we just free buffers. | ||
1296 | */ | ||
1297 | |||
1298 | dev_kfree_skb_irq(sb); | ||
1299 | |||
1300 | /* | ||
1301 | * .. and advance to the next buffer. | ||
1302 | */ | ||
1303 | |||
1304 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1305 | |||
1306 | packets_handled++; | ||
1307 | |||
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * Decide if we should wake up the protocol or not. | ||
1312 | * Other drivers seem to do this when we reach a low | ||
1313 | * watermark on the transmit queue. | ||
1314 | */ | ||
1315 | |||
1316 | if (packets_handled) | ||
1317 | netif_wake_queue(d->sbdma_eth->sbm_dev); | ||
1318 | |||
1319 | end_unlock: | ||
1320 | spin_unlock_irqrestore(&(sc->sbm_lock), flags); | ||
1321 | |||
1322 | } | ||
1323 | |||
1324 | |||
1325 | |||
1326 | /********************************************************************** | ||
1327 | * SBMAC_INITCTX(s) | ||
1328 | * | ||
1329 | * Initialize an Ethernet context structure - this is called | ||
1330 | * once per MAC on the 1250. Memory is allocated here, so don't | ||
1331 | * call it again from inside the ioctl routines that bring the | ||
1332 | * interface up/down | ||
1333 | * | ||
1334 | * Input parameters: | ||
1335 | * s - sbmac context structure | ||
1336 | * | ||
1337 | * Return value: | ||
1338 | * 0 | ||
1339 | ********************************************************************* */ | ||
1340 | |||
1341 | static int sbmac_initctx(struct sbmac_softc *s) | ||
1342 | { | ||
1343 | |||
1344 | /* | ||
1345 | * figure out the addresses of some ports | ||
1346 | */ | ||
1347 | |||
1348 | s->sbm_macenable = s->sbm_base + R_MAC_ENABLE; | ||
1349 | s->sbm_maccfg = s->sbm_base + R_MAC_CFG; | ||
1350 | s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG; | ||
1351 | s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG; | ||
1352 | s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG; | ||
1353 | s->sbm_isr = s->sbm_base + R_MAC_STATUS; | ||
1354 | s->sbm_imr = s->sbm_base + R_MAC_INT_MASK; | ||
1355 | s->sbm_mdio = s->sbm_base + R_MAC_MDIO; | ||
1356 | |||
1357 | /* | ||
1358 | * Initialize the DMA channels. Right now, only one per MAC is used | ||
1359 | * Note: Only do this _once_, as it allocates memory from the kernel! | ||
1360 | */ | ||
1361 | |||
1362 | sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR); | ||
1363 | sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR); | ||
1364 | |||
1365 | /* | ||
1366 | * initial state is OFF | ||
1367 | */ | ||
1368 | |||
1369 | s->sbm_state = sbmac_state_off; | ||
1370 | |||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | |||
1375 | static void sbdma_uninitctx(struct sbmacdma *d) | ||
1376 | { | ||
1377 | if (d->sbdma_dscrtable_unaligned) { | ||
1378 | kfree(d->sbdma_dscrtable_unaligned); | ||
1379 | d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL; | ||
1380 | } | ||
1381 | |||
1382 | if (d->sbdma_ctxtable) { | ||
1383 | kfree(d->sbdma_ctxtable); | ||
1384 | d->sbdma_ctxtable = NULL; | ||
1385 | } | ||
1386 | } | ||
1387 | |||
1388 | |||
1389 | static void sbmac_uninitctx(struct sbmac_softc *sc) | ||
1390 | { | ||
1391 | sbdma_uninitctx(&(sc->sbm_txdma)); | ||
1392 | sbdma_uninitctx(&(sc->sbm_rxdma)); | ||
1393 | } | ||
1394 | |||
1395 | |||
1396 | /********************************************************************** | ||
1397 | * SBMAC_CHANNEL_START(s) | ||
1398 | * | ||
1399 | * Start packet processing on this MAC. | ||
1400 | * | ||
1401 | * Input parameters: | ||
1402 | * s - sbmac structure | ||
1403 | * | ||
1404 | * Return value: | ||
1405 | * nothing | ||
1406 | ********************************************************************* */ | ||
1407 | |||
1408 | static void sbmac_channel_start(struct sbmac_softc *s) | ||
1409 | { | ||
1410 | uint64_t reg; | ||
1411 | void __iomem *port; | ||
1412 | uint64_t cfg,fifo,framecfg; | ||
1413 | int idx, th_value; | ||
1414 | |||
1415 | /* | ||
1416 | * Don't do this if running | ||
1417 | */ | ||
1418 | |||
1419 | if (s->sbm_state == sbmac_state_on) | ||
1420 | return; | ||
1421 | |||
1422 | /* | ||
1423 | * Bring the controller out of reset, but leave it off. | ||
1424 | */ | ||
1425 | |||
1426 | __raw_writeq(0, s->sbm_macenable); | ||
1427 | |||
1428 | /* | ||
1429 | * Ignore all received packets | ||
1430 | */ | ||
1431 | |||
1432 | __raw_writeq(0, s->sbm_rxfilter); | ||
1433 | |||
1434 | /* | ||
1435 | * Calculate values for various control registers. | ||
1436 | */ | ||
1437 | |||
1438 | cfg = M_MAC_RETRY_EN | | ||
1439 | M_MAC_TX_HOLD_SOP_EN | | ||
1440 | V_MAC_TX_PAUSE_CNT_16K | | ||
1441 | M_MAC_AP_STAT_EN | | ||
1442 | M_MAC_FAST_SYNC | | ||
1443 | M_MAC_SS_EN | | ||
1444 | 0; | ||
1445 | |||
1446 | /* | ||
1447 | * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars | ||
1448 | * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above | ||
1449 | * Use a larger RD_THRSH for gigabit | ||
1450 | */ | ||
1451 | if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) | ||
1452 | th_value = 28; | ||
1453 | else | ||
1454 | th_value = 64; | ||
1455 | |||
1456 | fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ | ||
1457 | ((s->sbm_speed == sbmac_speed_1000) | ||
1458 | ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) | | ||
1459 | V_MAC_TX_RL_THRSH(4) | | ||
1460 | V_MAC_RX_PL_THRSH(4) | | ||
1461 | V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ | ||
1462 | V_MAC_RX_RL_THRSH(8) | | ||
1463 | 0; | ||
1464 | |||
1465 | framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | | ||
1466 | V_MAC_MAX_FRAMESZ_DEFAULT | | ||
1467 | V_MAC_BACKOFF_SEL(1); | ||
1468 | |||
1469 | /* | ||
1470 | * Clear out the hash address map | ||
1471 | */ | ||
1472 | |||
1473 | port = s->sbm_base + R_MAC_HASH_BASE; | ||
1474 | for (idx = 0; idx < MAC_HASH_COUNT; idx++) { | ||
1475 | __raw_writeq(0, port); | ||
1476 | port += sizeof(uint64_t); | ||
1477 | } | ||
1478 | |||
1479 | /* | ||
1480 | * Clear out the exact-match table | ||
1481 | */ | ||
1482 | |||
1483 | port = s->sbm_base + R_MAC_ADDR_BASE; | ||
1484 | for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { | ||
1485 | __raw_writeq(0, port); | ||
1486 | port += sizeof(uint64_t); | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | * Clear out the DMA Channel mapping table registers | ||
1491 | */ | ||
1492 | |||
1493 | port = s->sbm_base + R_MAC_CHUP0_BASE; | ||
1494 | for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { | ||
1495 | __raw_writeq(0, port); | ||
1496 | port += sizeof(uint64_t); | ||
1497 | } | ||
1498 | |||
1499 | |||
1500 | port = s->sbm_base + R_MAC_CHLO0_BASE; | ||
1501 | for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { | ||
1502 | __raw_writeq(0, port); | ||
1503 | port += sizeof(uint64_t); | ||
1504 | } | ||
1505 | |||
1506 | /* | ||
1507 | * Program the hardware address. It goes into the hardware-address | ||
1508 | * register as well as the first filter register. | ||
1509 | */ | ||
1510 | |||
1511 | reg = sbmac_addr2reg(s->sbm_hwaddr); | ||
1512 | |||
1513 | port = s->sbm_base + R_MAC_ADDR_BASE; | ||
1514 | __raw_writeq(reg, port); | ||
1515 | port = s->sbm_base + R_MAC_ETHERNET_ADDR; | ||
1516 | |||
1517 | #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS | ||
1518 | /* | ||
1519 | * Pass1 SOCs do not receive packets addressed to the | ||
1520 | * destination address in the R_MAC_ETHERNET_ADDR register. | ||
1521 | * Set the value to zero. | ||
1522 | */ | ||
1523 | __raw_writeq(0, port); | ||
1524 | #else | ||
1525 | __raw_writeq(reg, port); | ||
1526 | #endif | ||
1527 | |||
1528 | /* | ||
1529 | * Set the receive filter for no packets, and write values | ||
1530 | * to the various config registers | ||
1531 | */ | ||
1532 | |||
1533 | __raw_writeq(0, s->sbm_rxfilter); | ||
1534 | __raw_writeq(0, s->sbm_imr); | ||
1535 | __raw_writeq(framecfg, s->sbm_framecfg); | ||
1536 | __raw_writeq(fifo, s->sbm_fifocfg); | ||
1537 | __raw_writeq(cfg, s->sbm_maccfg); | ||
1538 | |||
1539 | /* | ||
1540 | * Initialize DMA channels (rings should be ok now) | ||
1541 | */ | ||
1542 | |||
1543 | sbdma_channel_start(&(s->sbm_rxdma), DMA_RX); | ||
1544 | sbdma_channel_start(&(s->sbm_txdma), DMA_TX); | ||
1545 | |||
1546 | /* | ||
1547 | * Configure the speed, duplex, and flow control | ||
1548 | */ | ||
1549 | |||
1550 | sbmac_set_speed(s,s->sbm_speed); | ||
1551 | sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc); | ||
1552 | |||
1553 | /* | ||
1554 | * Fill the receive ring | ||
1555 | */ | ||
1556 | |||
1557 | sbdma_fillring(s, &(s->sbm_rxdma)); | ||
1558 | |||
1559 | /* | ||
1560 | * Turn on the rest of the bits in the enable register | ||
1561 | */ | ||
1562 | |||
1563 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
1564 | __raw_writeq(M_MAC_RXDMA_EN0 | | ||
1565 | M_MAC_TXDMA_EN0, s->sbm_macenable); | ||
1566 | #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) | ||
1567 | __raw_writeq(M_MAC_RXDMA_EN0 | | ||
1568 | M_MAC_TXDMA_EN0 | | ||
1569 | M_MAC_RX_ENABLE | | ||
1570 | M_MAC_TX_ENABLE, s->sbm_macenable); | ||
1571 | #else | ||
1572 | #error invalid SiByte MAC configuration | ||
1573 | #endif | ||
1574 | |||
1575 | #ifdef CONFIG_SBMAC_COALESCE | ||
1576 | __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | | ||
1577 | ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr); | ||
1578 | #else | ||
1579 | __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | | ||
1580 | (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr); | ||
1581 | #endif | ||
1582 | |||
1583 | /* | ||
1584 | * Enable receiving unicasts and broadcasts | ||
1585 | */ | ||
1586 | |||
1587 | __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter); | ||
1588 | |||
1589 | /* | ||
1590 | * we're running now. | ||
1591 | */ | ||
1592 | |||
1593 | s->sbm_state = sbmac_state_on; | ||
1594 | |||
1595 | /* | ||
1596 | * Program multicast addresses | ||
1597 | */ | ||
1598 | |||
1599 | sbmac_setmulti(s); | ||
1600 | |||
1601 | /* | ||
1602 | * If channel was in promiscuous mode before, turn that on | ||
1603 | */ | ||
1604 | |||
1605 | if (s->sbm_devflags & IFF_PROMISC) { | ||
1606 | sbmac_promiscuous_mode(s,1); | ||
1607 | } | ||
1608 | |||
1609 | } | ||
1610 | |||
1611 | |||
1612 | /********************************************************************** | ||
1613 | * SBMAC_CHANNEL_STOP(s) | ||
1614 | * | ||
1615 | * Stop packet processing on this MAC. | ||
1616 | * | ||
1617 | * Input parameters: | ||
1618 | * s - sbmac structure | ||
1619 | * | ||
1620 | * Return value: | ||
1621 | * nothing | ||
1622 | ********************************************************************* */ | ||
1623 | |||
1624 | static void sbmac_channel_stop(struct sbmac_softc *s) | ||
1625 | { | ||
1626 | /* don't do this if already stopped */ | ||
1627 | |||
1628 | if (s->sbm_state == sbmac_state_off) | ||
1629 | return; | ||
1630 | |||
1631 | /* don't accept any packets, disable all interrupts */ | ||
1632 | |||
1633 | __raw_writeq(0, s->sbm_rxfilter); | ||
1634 | __raw_writeq(0, s->sbm_imr); | ||
1635 | |||
1636 | /* Turn off ticker */ | ||
1637 | |||
1638 | /* XXX */ | ||
1639 | |||
1640 | /* turn off receiver and transmitter */ | ||
1641 | |||
1642 | __raw_writeq(0, s->sbm_macenable); | ||
1643 | |||
1644 | /* We're stopped now. */ | ||
1645 | |||
1646 | s->sbm_state = sbmac_state_off; | ||
1647 | |||
1648 | /* | ||
1649 | * Stop DMA channels (rings should be ok now) | ||
1650 | */ | ||
1651 | |||
1652 | sbdma_channel_stop(&(s->sbm_rxdma)); | ||
1653 | sbdma_channel_stop(&(s->sbm_txdma)); | ||
1654 | |||
1655 | /* Empty the receive and transmit rings */ | ||
1656 | |||
1657 | sbdma_emptyring(&(s->sbm_rxdma)); | ||
1658 | sbdma_emptyring(&(s->sbm_txdma)); | ||
1659 | |||
1660 | } | ||
1661 | |||
1662 | /********************************************************************** | ||
1663 | * SBMAC_SET_CHANNEL_STATE(state) | ||
1664 | * | ||
1665 | * Set the channel's state ON or OFF | ||
1666 | * | ||
1667 | * Input parameters: | ||
1668 | * state - new state | ||
1669 | * | ||
1670 | * Return value: | ||
1671 | * old state | ||
1672 | ********************************************************************* */ | ||
1673 | static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *sc, | ||
1674 | enum sbmac_state state) | ||
1675 | { | ||
1676 | enum sbmac_state oldstate = sc->sbm_state; | ||
1677 | |||
1678 | /* | ||
1679 | * If same as previous state, return | ||
1680 | */ | ||
1681 | |||
1682 | if (state == oldstate) { | ||
1683 | return oldstate; | ||
1684 | } | ||
1685 | |||
1686 | /* | ||
1687 | * If new state is ON, turn channel on | ||
1688 | */ | ||
1689 | |||
1690 | if (state == sbmac_state_on) { | ||
1691 | sbmac_channel_start(sc); | ||
1692 | } | ||
1693 | else { | ||
1694 | sbmac_channel_stop(sc); | ||
1695 | } | ||
1696 | |||
1697 | /* | ||
1698 | * Return previous state | ||
1699 | */ | ||
1700 | |||
1701 | return oldstate; | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | /********************************************************************** | ||
1706 | * SBMAC_PROMISCUOUS_MODE(sc,onoff) | ||
1707 | * | ||
1708 | * Turn on or off promiscuous mode | ||
1709 | * | ||
1710 | * Input parameters: | ||
1711 | * sc - softc | ||
1712 | * onoff - 1 to turn on, 0 to turn off | ||
1713 | * | ||
1714 | * Return value: | ||
1715 | * nothing | ||
1716 | ********************************************************************* */ | ||
1717 | |||
1718 | static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff) | ||
1719 | { | ||
1720 | uint64_t reg; | ||
1721 | |||
1722 | if (sc->sbm_state != sbmac_state_on) | ||
1723 | return; | ||
1724 | |||
1725 | if (onoff) { | ||
1726 | reg = __raw_readq(sc->sbm_rxfilter); | ||
1727 | reg |= M_MAC_ALLPKT_EN; | ||
1728 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
1729 | } | ||
1730 | else { | ||
1731 | reg = __raw_readq(sc->sbm_rxfilter); | ||
1732 | reg &= ~M_MAC_ALLPKT_EN; | ||
1733 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | /********************************************************************** | ||
1738 | * SBMAC_SETIPHDR_OFFSET(sc,onoff) | ||
1739 | * | ||
1740 | * Set the iphdr offset as 15 assuming ethernet encapsulation | ||
1741 | * | ||
1742 | * Input parameters: | ||
1743 | * sc - softc | ||
1744 | * | ||
1745 | * Return value: | ||
1746 | * nothing | ||
1747 | ********************************************************************* */ | ||
1748 | |||
1749 | static void sbmac_set_iphdr_offset(struct sbmac_softc *sc) | ||
1750 | { | ||
1751 | uint64_t reg; | ||
1752 | |||
1753 | /* Hard code the off set to 15 for now */ | ||
1754 | reg = __raw_readq(sc->sbm_rxfilter); | ||
1755 | reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); | ||
1756 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
1757 | |||
1758 | /* BCM1250 pass1 didn't have hardware checksum. Everything | ||
1759 | later does. */ | ||
1760 | if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) { | ||
1761 | sc->rx_hw_checksum = DISABLE; | ||
1762 | } else { | ||
1763 | sc->rx_hw_checksum = ENABLE; | ||
1764 | } | ||
1765 | } | ||
1766 | |||
1767 | |||
1768 | /********************************************************************** | ||
1769 | * SBMAC_ADDR2REG(ptr) | ||
1770 | * | ||
1771 | * Convert six bytes into the 64-bit register value that | ||
1772 | * we typically write into the SBMAC's address/mcast registers | ||
1773 | * | ||
1774 | * Input parameters: | ||
1775 | * ptr - pointer to 6 bytes | ||
1776 | * | ||
1777 | * Return value: | ||
1778 | * register value | ||
1779 | ********************************************************************* */ | ||
1780 | |||
1781 | static uint64_t sbmac_addr2reg(unsigned char *ptr) | ||
1782 | { | ||
1783 | uint64_t reg = 0; | ||
1784 | |||
1785 | ptr += 6; | ||
1786 | |||
1787 | reg |= (uint64_t) *(--ptr); | ||
1788 | reg <<= 8; | ||
1789 | reg |= (uint64_t) *(--ptr); | ||
1790 | reg <<= 8; | ||
1791 | reg |= (uint64_t) *(--ptr); | ||
1792 | reg <<= 8; | ||
1793 | reg |= (uint64_t) *(--ptr); | ||
1794 | reg <<= 8; | ||
1795 | reg |= (uint64_t) *(--ptr); | ||
1796 | reg <<= 8; | ||
1797 | reg |= (uint64_t) *(--ptr); | ||
1798 | |||
1799 | return reg; | ||
1800 | } | ||
1801 | |||
1802 | |||
1803 | /********************************************************************** | ||
1804 | * SBMAC_SET_SPEED(s,speed) | ||
1805 | * | ||
1806 | * Configure LAN speed for the specified MAC. | ||
1807 | * Warning: must be called when MAC is off! | ||
1808 | * | ||
1809 | * Input parameters: | ||
1810 | * s - sbmac structure | ||
1811 | * speed - speed to set MAC to (see enum sbmac_speed) | ||
1812 | * | ||
1813 | * Return value: | ||
1814 | * 1 if successful | ||
1815 | * 0 indicates invalid parameters | ||
1816 | ********************************************************************* */ | ||
1817 | |||
1818 | static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed) | ||
1819 | { | ||
1820 | uint64_t cfg; | ||
1821 | uint64_t framecfg; | ||
1822 | |||
1823 | /* | ||
1824 | * Save new current values | ||
1825 | */ | ||
1826 | |||
1827 | s->sbm_speed = speed; | ||
1828 | |||
1829 | if (s->sbm_state == sbmac_state_on) | ||
1830 | return 0; /* save for next restart */ | ||
1831 | |||
1832 | /* | ||
1833 | * Read current register values | ||
1834 | */ | ||
1835 | |||
1836 | cfg = __raw_readq(s->sbm_maccfg); | ||
1837 | framecfg = __raw_readq(s->sbm_framecfg); | ||
1838 | |||
1839 | /* | ||
1840 | * Mask out the stuff we want to change | ||
1841 | */ | ||
1842 | |||
1843 | cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); | ||
1844 | framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | | ||
1845 | M_MAC_SLOT_SIZE); | ||
1846 | |||
1847 | /* | ||
1848 | * Now add in the new bits | ||
1849 | */ | ||
1850 | |||
1851 | switch (speed) { | ||
1852 | case sbmac_speed_10: | ||
1853 | framecfg |= V_MAC_IFG_RX_10 | | ||
1854 | V_MAC_IFG_TX_10 | | ||
1855 | K_MAC_IFG_THRSH_10 | | ||
1856 | V_MAC_SLOT_SIZE_10; | ||
1857 | cfg |= V_MAC_SPEED_SEL_10MBPS; | ||
1858 | break; | ||
1859 | |||
1860 | case sbmac_speed_100: | ||
1861 | framecfg |= V_MAC_IFG_RX_100 | | ||
1862 | V_MAC_IFG_TX_100 | | ||
1863 | V_MAC_IFG_THRSH_100 | | ||
1864 | V_MAC_SLOT_SIZE_100; | ||
1865 | cfg |= V_MAC_SPEED_SEL_100MBPS ; | ||
1866 | break; | ||
1867 | |||
1868 | case sbmac_speed_1000: | ||
1869 | framecfg |= V_MAC_IFG_RX_1000 | | ||
1870 | V_MAC_IFG_TX_1000 | | ||
1871 | V_MAC_IFG_THRSH_1000 | | ||
1872 | V_MAC_SLOT_SIZE_1000; | ||
1873 | cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; | ||
1874 | break; | ||
1875 | |||
1876 | default: | ||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | /* | ||
1881 | * Send the bits back to the hardware | ||
1882 | */ | ||
1883 | |||
1884 | __raw_writeq(framecfg, s->sbm_framecfg); | ||
1885 | __raw_writeq(cfg, s->sbm_maccfg); | ||
1886 | |||
1887 | return 1; | ||
1888 | } | ||
1889 | |||
1890 | /********************************************************************** | ||
1891 | * SBMAC_SET_DUPLEX(s,duplex,fc) | ||
1892 | * | ||
1893 | * Set Ethernet duplex and flow control options for this MAC | ||
1894 | * Warning: must be called when MAC is off! | ||
1895 | * | ||
1896 | * Input parameters: | ||
1897 | * s - sbmac structure | ||
1898 | * duplex - duplex setting (see enum sbmac_duplex) | ||
1899 | * fc - flow control setting (see enum sbmac_fc) | ||
1900 | * | ||
1901 | * Return value: | ||
1902 | * 1 if ok | ||
1903 | * 0 if an invalid parameter combination was specified | ||
1904 | ********************************************************************* */ | ||
1905 | |||
1906 | static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, | ||
1907 | enum sbmac_fc fc) | ||
1908 | { | ||
1909 | uint64_t cfg; | ||
1910 | |||
1911 | /* | ||
1912 | * Save new current values | ||
1913 | */ | ||
1914 | |||
1915 | s->sbm_duplex = duplex; | ||
1916 | s->sbm_fc = fc; | ||
1917 | |||
1918 | if (s->sbm_state == sbmac_state_on) | ||
1919 | return 0; /* save for next restart */ | ||
1920 | |||
1921 | /* | ||
1922 | * Read current register values | ||
1923 | */ | ||
1924 | |||
1925 | cfg = __raw_readq(s->sbm_maccfg); | ||
1926 | |||
1927 | /* | ||
1928 | * Mask off the stuff we're about to change | ||
1929 | */ | ||
1930 | |||
1931 | cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); | ||
1932 | |||
1933 | |||
1934 | switch (duplex) { | ||
1935 | case sbmac_duplex_half: | ||
1936 | switch (fc) { | ||
1937 | case sbmac_fc_disabled: | ||
1938 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; | ||
1939 | break; | ||
1940 | |||
1941 | case sbmac_fc_collision: | ||
1942 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; | ||
1943 | break; | ||
1944 | |||
1945 | case sbmac_fc_carrier: | ||
1946 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; | ||
1947 | break; | ||
1948 | |||
1949 | case sbmac_fc_frame: /* not valid in half duplex */ | ||
1950 | default: /* invalid selection */ | ||
1951 | return 0; | ||
1952 | } | ||
1953 | break; | ||
1954 | |||
1955 | case sbmac_duplex_full: | ||
1956 | switch (fc) { | ||
1957 | case sbmac_fc_disabled: | ||
1958 | cfg |= V_MAC_FC_CMD_DISABLED; | ||
1959 | break; | ||
1960 | |||
1961 | case sbmac_fc_frame: | ||
1962 | cfg |= V_MAC_FC_CMD_ENABLED; | ||
1963 | break; | ||
1964 | |||
1965 | case sbmac_fc_collision: /* not valid in full duplex */ | ||
1966 | case sbmac_fc_carrier: /* not valid in full duplex */ | ||
1967 | default: | ||
1968 | return 0; | ||
1969 | } | ||
1970 | break; | ||
1971 | default: | ||
1972 | return 0; | ||
1973 | } | ||
1974 | |||
1975 | /* | ||
1976 | * Send the bits back to the hardware | ||
1977 | */ | ||
1978 | |||
1979 | __raw_writeq(cfg, s->sbm_maccfg); | ||
1980 | |||
1981 | return 1; | ||
1982 | } | ||
1983 | |||
1984 | |||
1985 | |||
1986 | |||
1987 | /********************************************************************** | ||
1988 | * SBMAC_INTR() | ||
1989 | * | ||
1990 | * Interrupt handler for MAC interrupts | ||
1991 | * | ||
1992 | * Input parameters: | ||
1993 | * MAC structure | ||
1994 | * | ||
1995 | * Return value: | ||
1996 | * nothing | ||
1997 | ********************************************************************* */ | ||
1998 | static irqreturn_t sbmac_intr(int irq,void *dev_instance) | ||
1999 | { | ||
2000 | struct net_device *dev = (struct net_device *) dev_instance; | ||
2001 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2002 | uint64_t isr; | ||
2003 | int handled = 0; | ||
2004 | |||
2005 | /* | ||
2006 | * Read the ISR (this clears the bits in the real | ||
2007 | * register, except for counter addr) | ||
2008 | */ | ||
2009 | |||
2010 | isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR; | ||
2011 | |||
2012 | if (isr == 0) | ||
2013 | return IRQ_RETVAL(0); | ||
2014 | handled = 1; | ||
2015 | |||
2016 | /* | ||
2017 | * Transmits on channel 0 | ||
2018 | */ | ||
2019 | |||
2020 | if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) | ||
2021 | sbdma_tx_process(sc,&(sc->sbm_txdma), 0); | ||
2022 | |||
2023 | if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { | ||
2024 | if (napi_schedule_prep(&sc->napi)) { | ||
2025 | __raw_writeq(0, sc->sbm_imr); | ||
2026 | __napi_schedule(&sc->napi); | ||
2027 | /* Depend on the exit from poll to reenable intr */ | ||
2028 | } | ||
2029 | else { | ||
2030 | /* may leave some packets behind */ | ||
2031 | sbdma_rx_process(sc,&(sc->sbm_rxdma), | ||
2032 | SBMAC_MAX_RXDESCR * 2, 0); | ||
2033 | } | ||
2034 | } | ||
2035 | return IRQ_RETVAL(handled); | ||
2036 | } | ||
2037 | |||
2038 | /********************************************************************** | ||
2039 | * SBMAC_START_TX(skb,dev) | ||
2040 | * | ||
2041 | * Start output on the specified interface. Basically, we | ||
2042 | * queue as many buffers as we can until the ring fills up, or | ||
2043 | * we run off the end of the queue, whichever comes first. | ||
2044 | * | ||
2045 | * Input parameters: | ||
2046 | * | ||
2047 | * | ||
2048 | * Return value: | ||
2049 | * nothing | ||
2050 | ********************************************************************* */ | ||
2051 | static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) | ||
2052 | { | ||
2053 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2054 | unsigned long flags; | ||
2055 | |||
2056 | /* lock eth irq */ | ||
2057 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2058 | |||
2059 | /* | ||
2060 | * Put the buffer on the transmit ring. If we | ||
2061 | * don't have room, stop the queue. | ||
2062 | */ | ||
2063 | |||
2064 | if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { | ||
2065 | /* XXX save skb that we could not send */ | ||
2066 | netif_stop_queue(dev); | ||
2067 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2068 | |||
2069 | return NETDEV_TX_BUSY; | ||
2070 | } | ||
2071 | |||
2072 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2073 | |||
2074 | return NETDEV_TX_OK; | ||
2075 | } | ||
2076 | |||
2077 | /********************************************************************** | ||
2078 | * SBMAC_SETMULTI(sc) | ||
2079 | * | ||
2080 | * Reprogram the multicast table into the hardware, given | ||
2081 | * the list of multicasts associated with the interface | ||
2082 | * structure. | ||
2083 | * | ||
2084 | * Input parameters: | ||
2085 | * sc - softc | ||
2086 | * | ||
2087 | * Return value: | ||
2088 | * nothing | ||
2089 | ********************************************************************* */ | ||
2090 | |||
2091 | static void sbmac_setmulti(struct sbmac_softc *sc) | ||
2092 | { | ||
2093 | uint64_t reg; | ||
2094 | void __iomem *port; | ||
2095 | int idx; | ||
2096 | struct netdev_hw_addr *ha; | ||
2097 | struct net_device *dev = sc->sbm_dev; | ||
2098 | |||
2099 | /* | ||
2100 | * Clear out entire multicast table. We do this by nuking | ||
2101 | * the entire hash table and all the direct matches except | ||
2102 | * the first one, which is used for our station address | ||
2103 | */ | ||
2104 | |||
2105 | for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { | ||
2106 | port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)); | ||
2107 | __raw_writeq(0, port); | ||
2108 | } | ||
2109 | |||
2110 | for (idx = 0; idx < MAC_HASH_COUNT; idx++) { | ||
2111 | port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)); | ||
2112 | __raw_writeq(0, port); | ||
2113 | } | ||
2114 | |||
2115 | /* | ||
2116 | * Clear the filter to say we don't want any multicasts. | ||
2117 | */ | ||
2118 | |||
2119 | reg = __raw_readq(sc->sbm_rxfilter); | ||
2120 | reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN); | ||
2121 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
2122 | |||
2123 | if (dev->flags & IFF_ALLMULTI) { | ||
2124 | /* | ||
2125 | * Enable ALL multicasts. Do this by inverting the | ||
2126 | * multicast enable bit. | ||
2127 | */ | ||
2128 | reg = __raw_readq(sc->sbm_rxfilter); | ||
2129 | reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN); | ||
2130 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
2131 | return; | ||
2132 | } | ||
2133 | |||
2134 | |||
2135 | /* | ||
2136 | * Progam new multicast entries. For now, only use the | ||
2137 | * perfect filter. In the future we'll need to use the | ||
2138 | * hash filter if the perfect filter overflows | ||
2139 | */ | ||
2140 | |||
2141 | /* XXX only using perfect filter for now, need to use hash | ||
2142 | * XXX if the table overflows */ | ||
2143 | |||
2144 | idx = 1; /* skip station address */ | ||
2145 | netdev_for_each_mc_addr(ha, dev) { | ||
2146 | if (idx == MAC_ADDR_COUNT) | ||
2147 | break; | ||
2148 | reg = sbmac_addr2reg(ha->addr); | ||
2149 | port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); | ||
2150 | __raw_writeq(reg, port); | ||
2151 | idx++; | ||
2152 | } | ||
2153 | |||
2154 | /* | ||
2155 | * Enable the "accept multicast bits" if we programmed at least one | ||
2156 | * multicast. | ||
2157 | */ | ||
2158 | |||
2159 | if (idx > 1) { | ||
2160 | reg = __raw_readq(sc->sbm_rxfilter); | ||
2161 | reg |= M_MAC_MCAST_EN; | ||
2162 | __raw_writeq(reg, sc->sbm_rxfilter); | ||
2163 | } | ||
2164 | } | ||
2165 | |||
2166 | static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) | ||
2167 | { | ||
2168 | if (new_mtu > ENET_PACKET_SIZE) | ||
2169 | return -EINVAL; | ||
2170 | _dev->mtu = new_mtu; | ||
2171 | pr_info("changing the mtu to %d\n", new_mtu); | ||
2172 | return 0; | ||
2173 | } | ||
2174 | |||
2175 | static const struct net_device_ops sbmac_netdev_ops = { | ||
2176 | .ndo_open = sbmac_open, | ||
2177 | .ndo_stop = sbmac_close, | ||
2178 | .ndo_start_xmit = sbmac_start_tx, | ||
2179 | .ndo_set_multicast_list = sbmac_set_rx_mode, | ||
2180 | .ndo_tx_timeout = sbmac_tx_timeout, | ||
2181 | .ndo_do_ioctl = sbmac_mii_ioctl, | ||
2182 | .ndo_change_mtu = sb1250_change_mtu, | ||
2183 | .ndo_validate_addr = eth_validate_addr, | ||
2184 | .ndo_set_mac_address = eth_mac_addr, | ||
2185 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
2186 | .ndo_poll_controller = sbmac_netpoll, | ||
2187 | #endif | ||
2188 | }; | ||
2189 | |||
2190 | /********************************************************************** | ||
2191 | * SBMAC_INIT(dev) | ||
2192 | * | ||
2193 | * Attach routine - init hardware and hook ourselves into linux | ||
2194 | * | ||
2195 | * Input parameters: | ||
2196 | * dev - net_device structure | ||
2197 | * | ||
2198 | * Return value: | ||
2199 | * status | ||
2200 | ********************************************************************* */ | ||
2201 | |||
2202 | static int sbmac_init(struct platform_device *pldev, long long base) | ||
2203 | { | ||
2204 | struct net_device *dev = dev_get_drvdata(&pldev->dev); | ||
2205 | int idx = pldev->id; | ||
2206 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2207 | unsigned char *eaddr; | ||
2208 | uint64_t ea_reg; | ||
2209 | int i; | ||
2210 | int err; | ||
2211 | |||
2212 | sc->sbm_dev = dev; | ||
2213 | sc->sbe_idx = idx; | ||
2214 | |||
2215 | eaddr = sc->sbm_hwaddr; | ||
2216 | |||
2217 | /* | ||
2218 | * Read the ethernet address. The firmware left this programmed | ||
2219 | * for us in the ethernet address register for each mac. | ||
2220 | */ | ||
2221 | |||
2222 | ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR); | ||
2223 | __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR); | ||
2224 | for (i = 0; i < 6; i++) { | ||
2225 | eaddr[i] = (uint8_t) (ea_reg & 0xFF); | ||
2226 | ea_reg >>= 8; | ||
2227 | } | ||
2228 | |||
2229 | for (i = 0; i < 6; i++) { | ||
2230 | dev->dev_addr[i] = eaddr[i]; | ||
2231 | } | ||
2232 | |||
2233 | /* | ||
2234 | * Initialize context (get pointers to registers and stuff), then | ||
2235 | * allocate the memory for the descriptor tables. | ||
2236 | */ | ||
2237 | |||
2238 | sbmac_initctx(sc); | ||
2239 | |||
2240 | /* | ||
2241 | * Set up Linux device callins | ||
2242 | */ | ||
2243 | |||
2244 | spin_lock_init(&(sc->sbm_lock)); | ||
2245 | |||
2246 | dev->netdev_ops = &sbmac_netdev_ops; | ||
2247 | dev->watchdog_timeo = TX_TIMEOUT; | ||
2248 | |||
2249 | netif_napi_add(dev, &sc->napi, sbmac_poll, 16); | ||
2250 | |||
2251 | dev->irq = UNIT_INT(idx); | ||
2252 | |||
2253 | /* This is needed for PASS2 for Rx H/W checksum feature */ | ||
2254 | sbmac_set_iphdr_offset(sc); | ||
2255 | |||
2256 | sc->mii_bus = mdiobus_alloc(); | ||
2257 | if (sc->mii_bus == NULL) { | ||
2258 | err = -ENOMEM; | ||
2259 | goto uninit_ctx; | ||
2260 | } | ||
2261 | |||
2262 | sc->mii_bus->name = sbmac_mdio_string; | ||
2263 | snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); | ||
2264 | sc->mii_bus->priv = sc; | ||
2265 | sc->mii_bus->read = sbmac_mii_read; | ||
2266 | sc->mii_bus->write = sbmac_mii_write; | ||
2267 | sc->mii_bus->irq = sc->phy_irq; | ||
2268 | for (i = 0; i < PHY_MAX_ADDR; ++i) | ||
2269 | sc->mii_bus->irq[i] = SBMAC_PHY_INT; | ||
2270 | |||
2271 | sc->mii_bus->parent = &pldev->dev; | ||
2272 | /* | ||
2273 | * Probe PHY address | ||
2274 | */ | ||
2275 | err = mdiobus_register(sc->mii_bus); | ||
2276 | if (err) { | ||
2277 | printk(KERN_ERR "%s: unable to register MDIO bus\n", | ||
2278 | dev->name); | ||
2279 | goto free_mdio; | ||
2280 | } | ||
2281 | dev_set_drvdata(&pldev->dev, sc->mii_bus); | ||
2282 | |||
2283 | err = register_netdev(dev); | ||
2284 | if (err) { | ||
2285 | printk(KERN_ERR "%s.%d: unable to register netdev\n", | ||
2286 | sbmac_string, idx); | ||
2287 | goto unreg_mdio; | ||
2288 | } | ||
2289 | |||
2290 | pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); | ||
2291 | |||
2292 | if (sc->rx_hw_checksum == ENABLE) | ||
2293 | pr_info("%s: enabling TCP rcv checksum\n", dev->name); | ||
2294 | |||
2295 | /* | ||
2296 | * Display Ethernet address (this is called during the config | ||
2297 | * process so we need to finish off the config message that | ||
2298 | * was being displayed) | ||
2299 | */ | ||
2300 | pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", | ||
2301 | dev->name, base, eaddr); | ||
2302 | |||
2303 | return 0; | ||
2304 | unreg_mdio: | ||
2305 | mdiobus_unregister(sc->mii_bus); | ||
2306 | dev_set_drvdata(&pldev->dev, NULL); | ||
2307 | free_mdio: | ||
2308 | mdiobus_free(sc->mii_bus); | ||
2309 | uninit_ctx: | ||
2310 | sbmac_uninitctx(sc); | ||
2311 | return err; | ||
2312 | } | ||
2313 | |||
2314 | |||
2315 | static int sbmac_open(struct net_device *dev) | ||
2316 | { | ||
2317 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2318 | int err; | ||
2319 | |||
2320 | if (debug > 1) | ||
2321 | pr_debug("%s: sbmac_open() irq %d.\n", dev->name, dev->irq); | ||
2322 | |||
2323 | /* | ||
2324 | * map/route interrupt (clear status first, in case something | ||
2325 | * weird is pending; we haven't initialized the mac registers | ||
2326 | * yet) | ||
2327 | */ | ||
2328 | |||
2329 | __raw_readq(sc->sbm_isr); | ||
2330 | err = request_irq(dev->irq, sbmac_intr, IRQF_SHARED, dev->name, dev); | ||
2331 | if (err) { | ||
2332 | printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, | ||
2333 | dev->irq); | ||
2334 | goto out_err; | ||
2335 | } | ||
2336 | |||
2337 | sc->sbm_speed = sbmac_speed_none; | ||
2338 | sc->sbm_duplex = sbmac_duplex_none; | ||
2339 | sc->sbm_fc = sbmac_fc_none; | ||
2340 | sc->sbm_pause = -1; | ||
2341 | sc->sbm_link = 0; | ||
2342 | |||
2343 | /* | ||
2344 | * Attach to the PHY | ||
2345 | */ | ||
2346 | err = sbmac_mii_probe(dev); | ||
2347 | if (err) | ||
2348 | goto out_unregister; | ||
2349 | |||
2350 | /* | ||
2351 | * Turn on the channel | ||
2352 | */ | ||
2353 | |||
2354 | sbmac_set_channel_state(sc,sbmac_state_on); | ||
2355 | |||
2356 | netif_start_queue(dev); | ||
2357 | |||
2358 | sbmac_set_rx_mode(dev); | ||
2359 | |||
2360 | phy_start(sc->phy_dev); | ||
2361 | |||
2362 | napi_enable(&sc->napi); | ||
2363 | |||
2364 | return 0; | ||
2365 | |||
2366 | out_unregister: | ||
2367 | free_irq(dev->irq, dev); | ||
2368 | out_err: | ||
2369 | return err; | ||
2370 | } | ||
2371 | |||
2372 | static int sbmac_mii_probe(struct net_device *dev) | ||
2373 | { | ||
2374 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2375 | struct phy_device *phy_dev; | ||
2376 | int i; | ||
2377 | |||
2378 | for (i = 0; i < PHY_MAX_ADDR; i++) { | ||
2379 | phy_dev = sc->mii_bus->phy_map[i]; | ||
2380 | if (phy_dev) | ||
2381 | break; | ||
2382 | } | ||
2383 | if (!phy_dev) { | ||
2384 | printk(KERN_ERR "%s: no PHY found\n", dev->name); | ||
2385 | return -ENXIO; | ||
2386 | } | ||
2387 | |||
2388 | phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0, | ||
2389 | PHY_INTERFACE_MODE_GMII); | ||
2390 | if (IS_ERR(phy_dev)) { | ||
2391 | printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); | ||
2392 | return PTR_ERR(phy_dev); | ||
2393 | } | ||
2394 | |||
2395 | /* Remove any features not supported by the controller */ | ||
2396 | phy_dev->supported &= SUPPORTED_10baseT_Half | | ||
2397 | SUPPORTED_10baseT_Full | | ||
2398 | SUPPORTED_100baseT_Half | | ||
2399 | SUPPORTED_100baseT_Full | | ||
2400 | SUPPORTED_1000baseT_Half | | ||
2401 | SUPPORTED_1000baseT_Full | | ||
2402 | SUPPORTED_Autoneg | | ||
2403 | SUPPORTED_MII | | ||
2404 | SUPPORTED_Pause | | ||
2405 | SUPPORTED_Asym_Pause; | ||
2406 | phy_dev->advertising = phy_dev->supported; | ||
2407 | |||
2408 | pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", | ||
2409 | dev->name, phy_dev->drv->name, | ||
2410 | dev_name(&phy_dev->dev), phy_dev->irq); | ||
2411 | |||
2412 | sc->phy_dev = phy_dev; | ||
2413 | |||
2414 | return 0; | ||
2415 | } | ||
2416 | |||
2417 | |||
2418 | static void sbmac_mii_poll(struct net_device *dev) | ||
2419 | { | ||
2420 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2421 | struct phy_device *phy_dev = sc->phy_dev; | ||
2422 | unsigned long flags; | ||
2423 | enum sbmac_fc fc; | ||
2424 | int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg; | ||
2425 | |||
2426 | link_chg = (sc->sbm_link != phy_dev->link); | ||
2427 | speed_chg = (sc->sbm_speed != phy_dev->speed); | ||
2428 | duplex_chg = (sc->sbm_duplex != phy_dev->duplex); | ||
2429 | pause_chg = (sc->sbm_pause != phy_dev->pause); | ||
2430 | |||
2431 | if (!link_chg && !speed_chg && !duplex_chg && !pause_chg) | ||
2432 | return; /* Hmmm... */ | ||
2433 | |||
2434 | if (!phy_dev->link) { | ||
2435 | if (link_chg) { | ||
2436 | sc->sbm_link = phy_dev->link; | ||
2437 | sc->sbm_speed = sbmac_speed_none; | ||
2438 | sc->sbm_duplex = sbmac_duplex_none; | ||
2439 | sc->sbm_fc = sbmac_fc_disabled; | ||
2440 | sc->sbm_pause = -1; | ||
2441 | pr_info("%s: link unavailable\n", dev->name); | ||
2442 | } | ||
2443 | return; | ||
2444 | } | ||
2445 | |||
2446 | if (phy_dev->duplex == DUPLEX_FULL) { | ||
2447 | if (phy_dev->pause) | ||
2448 | fc = sbmac_fc_frame; | ||
2449 | else | ||
2450 | fc = sbmac_fc_disabled; | ||
2451 | } else | ||
2452 | fc = sbmac_fc_collision; | ||
2453 | fc_chg = (sc->sbm_fc != fc); | ||
2454 | |||
2455 | pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed, | ||
2456 | phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H'); | ||
2457 | |||
2458 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2459 | |||
2460 | sc->sbm_speed = phy_dev->speed; | ||
2461 | sc->sbm_duplex = phy_dev->duplex; | ||
2462 | sc->sbm_fc = fc; | ||
2463 | sc->sbm_pause = phy_dev->pause; | ||
2464 | sc->sbm_link = phy_dev->link; | ||
2465 | |||
2466 | if ((speed_chg || duplex_chg || fc_chg) && | ||
2467 | sc->sbm_state != sbmac_state_off) { | ||
2468 | /* | ||
2469 | * something changed, restart the channel | ||
2470 | */ | ||
2471 | if (debug > 1) | ||
2472 | pr_debug("%s: restarting channel " | ||
2473 | "because PHY state changed\n", dev->name); | ||
2474 | sbmac_channel_stop(sc); | ||
2475 | sbmac_channel_start(sc); | ||
2476 | } | ||
2477 | |||
2478 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2479 | } | ||
2480 | |||
2481 | |||
2482 | static void sbmac_tx_timeout (struct net_device *dev) | ||
2483 | { | ||
2484 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2485 | unsigned long flags; | ||
2486 | |||
2487 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2488 | |||
2489 | |||
2490 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
2491 | dev->stats.tx_errors++; | ||
2492 | |||
2493 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2494 | |||
2495 | printk (KERN_WARNING "%s: Transmit timed out\n",dev->name); | ||
2496 | } | ||
2497 | |||
2498 | |||
2499 | |||
2500 | |||
2501 | static void sbmac_set_rx_mode(struct net_device *dev) | ||
2502 | { | ||
2503 | unsigned long flags; | ||
2504 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2505 | |||
2506 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2507 | if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) { | ||
2508 | /* | ||
2509 | * Promiscuous changed. | ||
2510 | */ | ||
2511 | |||
2512 | if (dev->flags & IFF_PROMISC) { | ||
2513 | sbmac_promiscuous_mode(sc,1); | ||
2514 | } | ||
2515 | else { | ||
2516 | sbmac_promiscuous_mode(sc,0); | ||
2517 | } | ||
2518 | } | ||
2519 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2520 | |||
2521 | /* | ||
2522 | * Program the multicasts. Do this every time. | ||
2523 | */ | ||
2524 | |||
2525 | sbmac_setmulti(sc); | ||
2526 | |||
2527 | } | ||
2528 | |||
2529 | static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
2530 | { | ||
2531 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2532 | |||
2533 | if (!netif_running(dev) || !sc->phy_dev) | ||
2534 | return -EINVAL; | ||
2535 | |||
2536 | return phy_mii_ioctl(sc->phy_dev, rq, cmd); | ||
2537 | } | ||
2538 | |||
2539 | static int sbmac_close(struct net_device *dev) | ||
2540 | { | ||
2541 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2542 | |||
2543 | napi_disable(&sc->napi); | ||
2544 | |||
2545 | phy_stop(sc->phy_dev); | ||
2546 | |||
2547 | sbmac_set_channel_state(sc, sbmac_state_off); | ||
2548 | |||
2549 | netif_stop_queue(dev); | ||
2550 | |||
2551 | if (debug > 1) | ||
2552 | pr_debug("%s: Shutting down ethercard\n", dev->name); | ||
2553 | |||
2554 | phy_disconnect(sc->phy_dev); | ||
2555 | sc->phy_dev = NULL; | ||
2556 | free_irq(dev->irq, dev); | ||
2557 | |||
2558 | sbdma_emptyring(&(sc->sbm_txdma)); | ||
2559 | sbdma_emptyring(&(sc->sbm_rxdma)); | ||
2560 | |||
2561 | return 0; | ||
2562 | } | ||
2563 | |||
2564 | static int sbmac_poll(struct napi_struct *napi, int budget) | ||
2565 | { | ||
2566 | struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi); | ||
2567 | int work_done; | ||
2568 | |||
2569 | work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1); | ||
2570 | sbdma_tx_process(sc, &(sc->sbm_txdma), 1); | ||
2571 | |||
2572 | if (work_done < budget) { | ||
2573 | napi_complete(napi); | ||
2574 | |||
2575 | #ifdef CONFIG_SBMAC_COALESCE | ||
2576 | __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | | ||
2577 | ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), | ||
2578 | sc->sbm_imr); | ||
2579 | #else | ||
2580 | __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | | ||
2581 | (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); | ||
2582 | #endif | ||
2583 | } | ||
2584 | |||
2585 | return work_done; | ||
2586 | } | ||
2587 | |||
2588 | |||
2589 | static int __devinit sbmac_probe(struct platform_device *pldev) | ||
2590 | { | ||
2591 | struct net_device *dev; | ||
2592 | struct sbmac_softc *sc; | ||
2593 | void __iomem *sbm_base; | ||
2594 | struct resource *res; | ||
2595 | u64 sbmac_orig_hwaddr; | ||
2596 | int err; | ||
2597 | |||
2598 | res = platform_get_resource(pldev, IORESOURCE_MEM, 0); | ||
2599 | BUG_ON(!res); | ||
2600 | sbm_base = ioremap_nocache(res->start, resource_size(res)); | ||
2601 | if (!sbm_base) { | ||
2602 | printk(KERN_ERR "%s: unable to map device registers\n", | ||
2603 | dev_name(&pldev->dev)); | ||
2604 | err = -ENOMEM; | ||
2605 | goto out_out; | ||
2606 | } | ||
2607 | |||
2608 | /* | ||
2609 | * The R_MAC_ETHERNET_ADDR register will be set to some nonzero | ||
2610 | * value for us by the firmware if we're going to use this MAC. | ||
2611 | * If we find a zero, skip this MAC. | ||
2612 | */ | ||
2613 | sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); | ||
2614 | pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), | ||
2615 | sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); | ||
2616 | if (sbmac_orig_hwaddr == 0) { | ||
2617 | err = 0; | ||
2618 | goto out_unmap; | ||
2619 | } | ||
2620 | |||
2621 | /* | ||
2622 | * Okay, cool. Initialize this MAC. | ||
2623 | */ | ||
2624 | dev = alloc_etherdev(sizeof(struct sbmac_softc)); | ||
2625 | if (!dev) { | ||
2626 | printk(KERN_ERR "%s: unable to allocate etherdev\n", | ||
2627 | dev_name(&pldev->dev)); | ||
2628 | err = -ENOMEM; | ||
2629 | goto out_unmap; | ||
2630 | } | ||
2631 | |||
2632 | dev_set_drvdata(&pldev->dev, dev); | ||
2633 | SET_NETDEV_DEV(dev, &pldev->dev); | ||
2634 | |||
2635 | sc = netdev_priv(dev); | ||
2636 | sc->sbm_base = sbm_base; | ||
2637 | |||
2638 | err = sbmac_init(pldev, res->start); | ||
2639 | if (err) | ||
2640 | goto out_kfree; | ||
2641 | |||
2642 | return 0; | ||
2643 | |||
2644 | out_kfree: | ||
2645 | free_netdev(dev); | ||
2646 | __raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR); | ||
2647 | |||
2648 | out_unmap: | ||
2649 | iounmap(sbm_base); | ||
2650 | |||
2651 | out_out: | ||
2652 | return err; | ||
2653 | } | ||
2654 | |||
2655 | static int __exit sbmac_remove(struct platform_device *pldev) | ||
2656 | { | ||
2657 | struct net_device *dev = dev_get_drvdata(&pldev->dev); | ||
2658 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2659 | |||
2660 | unregister_netdev(dev); | ||
2661 | sbmac_uninitctx(sc); | ||
2662 | mdiobus_unregister(sc->mii_bus); | ||
2663 | mdiobus_free(sc->mii_bus); | ||
2664 | iounmap(sc->sbm_base); | ||
2665 | free_netdev(dev); | ||
2666 | |||
2667 | return 0; | ||
2668 | } | ||
2669 | |||
2670 | static struct platform_driver sbmac_driver = { | ||
2671 | .probe = sbmac_probe, | ||
2672 | .remove = __exit_p(sbmac_remove), | ||
2673 | .driver = { | ||
2674 | .name = sbmac_string, | ||
2675 | .owner = THIS_MODULE, | ||
2676 | }, | ||
2677 | }; | ||
2678 | |||
2679 | static int __init sbmac_init_module(void) | ||
2680 | { | ||
2681 | return platform_driver_register(&sbmac_driver); | ||
2682 | } | ||
2683 | |||
2684 | static void __exit sbmac_cleanup_module(void) | ||
2685 | { | ||
2686 | platform_driver_unregister(&sbmac_driver); | ||
2687 | } | ||
2688 | |||
2689 | module_init(sbmac_init_module); | ||
2690 | module_exit(sbmac_cleanup_module); | ||