Blame view

drivers/net/sb1250-mac.c 65.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
2
   * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
3
   * Copyright (c) 2006, 2007  Maciej W. Rozycki
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
14
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
21
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   *
   *
   * This driver is designed for the Broadcom SiByte SOC built-in
   * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp.
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
22
23
24
   *
   * Updated to the driver model and the PHY abstraction layer
   * by Maciej W. Rozycki.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
   */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
26
27
  
  #include <linux/bug.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
32
33
34
35
36
37
38
39
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/timer.h>
  #include <linux/errno.h>
  #include <linux/ioport.h>
  #include <linux/slab.h>
  #include <linux/interrupt.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/skbuff.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <linux/bitops.h>
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
41
42
43
44
45
  #include <linux/err.h>
  #include <linux/ethtool.h>
  #include <linux/mii.h>
  #include <linux/phy.h>
  #include <linux/platform_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  #include <asm/cache.h>
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
47
48
  #include <asm/io.h>
  #include <asm/processor.h>	/* Processor type for cache alignment. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
  /* Operational parameters that usually are not changed. */
  
  #define CONFIG_SBMAC_COALESCE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  /* Time in jiffies before concluding the transmitter is hung. */
  #define TX_TIMEOUT  (2*HZ)
  
  
  MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
  MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
  
  /* A few user-configurable values which may be modified when a driver
     module is loaded. */
  
  /* 1 normal messages, 0 quiet .. 7 verbose. */
  static int debug = 1;
  module_param(debug, int, S_IRUGO);
  MODULE_PARM_DESC(debug, "Debug messages");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  #ifdef CONFIG_SBMAC_COALESCE
693aa9470   Mark Mason   add NAPI support ...
68
69
70
  static int int_pktcnt_tx = 255;
  module_param(int_pktcnt_tx, int, S_IRUGO);
  MODULE_PARM_DESC(int_pktcnt_tx, "TX packet count");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71

693aa9470   Mark Mason   add NAPI support ...
72
73
74
75
76
77
78
79
80
81
82
  static int int_timeout_tx = 255;
  module_param(int_timeout_tx, int, S_IRUGO);
  MODULE_PARM_DESC(int_timeout_tx, "TX timeout value");
  
  static int int_pktcnt_rx = 64;
  module_param(int_pktcnt_rx, int, S_IRUGO);
  MODULE_PARM_DESC(int_pktcnt_rx, "RX packet count");
  
  static int int_timeout_rx = 64;
  module_param(int_timeout_rx, int, S_IRUGO);
  MODULE_PARM_DESC(int_timeout_rx, "RX timeout value");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  #endif
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
84
  #include <asm/sibyte/board.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  #include <asm/sibyte/sb1250.h>
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
86
87
88
  #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
  #include <asm/sibyte/bcm1480_regs.h>
  #include <asm/sibyte/bcm1480_int.h>
693aa9470   Mark Mason   add NAPI support ...
89
  #define R_MAC_DMA_OODPKTLOST_RX	R_MAC_DMA_OODPKTLOST
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
90
  #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  #include <asm/sibyte/sb1250_regs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  #include <asm/sibyte/sb1250_int.h>
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
93
94
95
  #else
  #error invalid SiByte MAC configuation
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  #include <asm/sibyte/sb1250_scd.h>
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
97
98
  #include <asm/sibyte/sb1250_mac.h>
  #include <asm/sibyte/sb1250_dma.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
100
101
102
103
104
105
106
  #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
  #define UNIT_INT(n)		(K_BCM1480_INT_MAC_0 + ((n) * 2))
  #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
  #define UNIT_INT(n)		(K_INT_MAC_0 + (n))
  #else
  #error invalid SiByte MAC configuation
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
108
109
110
111
112
  #ifdef K_INT_PHY
  #define SBMAC_PHY_INT			K_INT_PHY
  #else
  #define SBMAC_PHY_INT			PHY_POLL
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
  /**********************************************************************
   *  Simple types
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
116
117
118
119
120
121
  enum sbmac_speed {
  	sbmac_speed_none = 0,
  	sbmac_speed_10 = SPEED_10,
  	sbmac_speed_100 = SPEED_100,
  	sbmac_speed_1000 = SPEED_1000,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
123
124
125
126
127
  enum sbmac_duplex {
  	sbmac_duplex_none = -1,
  	sbmac_duplex_half = DUPLEX_HALF,
  	sbmac_duplex_full = DUPLEX_FULL,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
129
130
131
132
133
134
135
  enum sbmac_fc {
  	sbmac_fc_none,
  	sbmac_fc_disabled,
  	sbmac_fc_frame,
  	sbmac_fc_collision,
  	sbmac_fc_carrier,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
137
138
139
140
141
142
  enum sbmac_state {
  	sbmac_state_uninit,
  	sbmac_state_off,
  	sbmac_state_on,
  	sbmac_state_broken,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
149
150
151
152
153
154
  
  
  /**********************************************************************
   *  Macros
   ********************************************************************* */
  
  
  #define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
  			  (d)->sbdma_dscrtable : (d)->f+1)
  
  
  #define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
693aa9470   Mark Mason   add NAPI support ...
155
156
  #define SBMAC_MAX_TXDESCR	256
  #define SBMAC_MAX_RXDESCR	256
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

789585e96   Stephen Hemminger   sb1250: use netde...
158
  #define ETHER_ADDR_LEN		6
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
159
160
  #define ENET_PACKET_SIZE	1518
  /*#define ENET_PACKET_SIZE	9216 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
  
  /**********************************************************************
   *  DMA Descriptor structure
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
165
  struct sbdmadscr {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  	uint64_t  dscr_a;
  	uint64_t  dscr_b;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
168
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
  
  /**********************************************************************
   *  DMA Controller structure
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
173
  struct sbmacdma {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
174
175
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
  	 * This stuff is used to identify the channel and the registers
  	 * associated with it.
  	 */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
179
180
181
182
183
184
  	struct sbmac_softc	*sbdma_eth;	/* back pointer to associated
  						   MAC */
  	int			sbdma_channel;	/* channel number */
  	int			sbdma_txdir;	/* direction (1=transmit) */
  	int			sbdma_maxdescr;	/* total # of descriptors
  						   in ring */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  #ifdef CONFIG_SBMAC_COALESCE
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
186
187
188
189
190
  	int			sbdma_int_pktcnt;
  						/* # descriptors rx/tx
  						   before interrupt */
  	int			sbdma_int_timeout;
  						/* # usec rx/tx interrupt */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  #endif
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
192
193
194
195
196
197
198
199
200
  	void __iomem		*sbdma_config0;	/* DMA config register 0 */
  	void __iomem		*sbdma_config1;	/* DMA config register 1 */
  	void __iomem		*sbdma_dscrbase;
  						/* descriptor base address */
  	void __iomem		*sbdma_dscrcnt;	/* descriptor count register */
  	void __iomem		*sbdma_curdscr;	/* current descriptor
  						   address */
  	void __iomem		*sbdma_oodpktlost;
  						/* pkt drop (rx only) */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
201

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
  	/*
  	 * This stuff is for maintenance of the ring
  	 */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  	void			*sbdma_dscrtable_unaligned;
  	struct sbdmadscr	*sbdma_dscrtable;
  						/* base of descriptor table */
  	struct sbdmadscr	*sbdma_dscrtable_end;
  						/* end of descriptor table */
  	struct sk_buff		**sbdma_ctxtable;
  						/* context table, one
  						   per descr */
  	dma_addr_t		sbdma_dscrtable_phys;
  						/* and also the phys addr */
  	struct sbdmadscr	*sbdma_addptr;	/* next dscr for sw to add */
  	struct sbdmadscr	*sbdma_remptr;	/* next dscr for sw
  						   to remove */
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
224
225
  
  
  /**********************************************************************
   *  Ethernet softc structure
   ********************************************************************* */
  
  struct sbmac_softc {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
226

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
  	/*
  	 * Linux-specific things
  	 */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
230
231
  	struct net_device	*sbm_dev;	/* pointer to linux device */
  	struct napi_struct	napi;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
232
  	struct phy_device	*phy_dev;	/* the associated PHY device */
298cf9beb   Lennert Buytenhek   phylib: move to d...
233
  	struct mii_bus		*mii_bus;	/* the MII bus */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
234
  	int			phy_irq[PHY_MAX_ADDR];
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
235
  	spinlock_t		sbm_lock;	/* spin lock */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
236
  	int			sbm_devflags;	/* current device flags */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
237

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
  	/*
  	 * Controller-specific things
  	 */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
241
242
  	void __iomem		*sbm_base;	/* MAC's base address */
  	enum sbmac_state	sbm_state;	/* current state */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
243

73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
244
245
246
247
248
249
250
251
  	void __iomem		*sbm_macenable;	/* MAC Enable Register */
  	void __iomem		*sbm_maccfg;	/* MAC Config Register */
  	void __iomem		*sbm_fifocfg;	/* FIFO Config Register */
  	void __iomem		*sbm_framecfg;	/* Frame Config Register */
  	void __iomem		*sbm_rxfilter;	/* Receive Filter Register */
  	void __iomem		*sbm_isr;	/* Interrupt Status Register */
  	void __iomem		*sbm_imr;	/* Interrupt Mask Register */
  	void __iomem		*sbm_mdio;	/* MDIO Register */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
252

73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
253
254
255
  	enum sbmac_speed	sbm_speed;	/* current speed */
  	enum sbmac_duplex	sbm_duplex;	/* current duplex */
  	enum sbmac_fc		sbm_fc;		/* cur. flow control setting */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
256
257
  	int			sbm_pause;	/* current pause setting */
  	int			sbm_link;	/* current link state */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
258

73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
259
  	unsigned char		sbm_hwaddr[ETHER_ADDR_LEN];
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
260

73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
261
262
263
264
  	struct sbmacdma		sbm_txdma;	/* only channel 0 for now */
  	struct sbmacdma		sbm_rxdma;
  	int			rx_hw_checksum;
  	int			sbe_idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
272
273
274
  };
  
  
  /**********************************************************************
   *  Externs
   ********************************************************************* */
  
  /**********************************************************************
   *  Prototypes
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
275
276
277
  static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan,
  			  int txrx, int maxdescr);
  static void sbdma_channel_start(struct sbmacdma *d, int rxtx);
789585e96   Stephen Hemminger   sb1250: use netde...
278
279
  static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
  			       struct sk_buff *m);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
280
281
  static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m);
  static void sbdma_emptyring(struct sbmacdma *d);
789585e96   Stephen Hemminger   sb1250: use netde...
282
  static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
283
284
285
286
  static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d,
  			    int work_to_do, int poll);
  static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
  			     int poll);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
  static int sbmac_initctx(struct sbmac_softc *s);
  static void sbmac_channel_start(struct sbmac_softc *s);
  static void sbmac_channel_stop(struct sbmac_softc *s);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
290
291
292
  static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *,
  						enum sbmac_state);
  static void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  static uint64_t sbmac_addr2reg(unsigned char *ptr);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
294
  static irqreturn_t sbmac_intr(int irq, void *dev_instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
  static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
  static void sbmac_setmulti(struct sbmac_softc *sc);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
297
  static int sbmac_init(struct platform_device *pldev, long long base);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
298
299
300
  static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed);
  static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex,
  			    enum sbmac_fc fc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
  
  static int sbmac_open(struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  static void sbmac_tx_timeout (struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
  static void sbmac_set_rx_mode(struct net_device *dev);
  static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
  static int sbmac_close(struct net_device *dev);
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
307
  static int sbmac_poll(struct napi_struct *napi, int budget);
693aa9470   Mark Mason   add NAPI support ...
308

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
309
  static void sbmac_mii_poll(struct net_device *dev);
59b818270   Ralf Baechle   [PATCH] sb1250-ma...
310
  static int sbmac_mii_probe(struct net_device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
312
313
  static void sbmac_mii_sync(void __iomem *sbm_mdio);
  static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
314
  			       int bitcnt);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
315
316
317
  static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx);
  static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
  			   u16 val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
  
  
  /**********************************************************************
   *  Globals
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
323
  static char sbmac_string[] = "sb1250-mac";
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
324
325
  
  static char sbmac_mdio_string[] = "sb1250-mac-mdio";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
330
331
332
333
334
335
  
  
  /**********************************************************************
   *  MDIO constants
   ********************************************************************* */
  
  #define	MII_COMMAND_START	0x01
  #define	MII_COMMAND_READ	0x02
  #define	MII_COMMAND_WRITE	0x01
  #define	MII_COMMAND_ACK		0x02
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
341
  #define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity */
  
  #define ENABLE 		1
  #define DISABLE		0
  
  /**********************************************************************
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
342
   *  SBMAC_MII_SYNC(sbm_mdio)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
343
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
   *  Synchronize with the MII - send a pattern of bits to the MII
   *  that will guarantee that it is ready to accept a command.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
346
347
   *
   *  Input parameters:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
348
   *  	   sbm_mdio - address of the MAC's MDIO register
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
349
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
   *  Return value:
   *  	   nothing
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
353
  static void sbmac_mii_sync(void __iomem *sbm_mdio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
  {
  	int cnt;
  	uint64_t bits;
  	int mac_mdio_genc;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
358
  	mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
359

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  	bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
361

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
362
  	__raw_writeq(bits | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
363

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  	for (cnt = 0; cnt < 32; cnt++) {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
365
366
  		__raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
  		__raw_writeq(bits | mac_mdio_genc, sbm_mdio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
  	}
  }
  
  /**********************************************************************
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
371
   *  SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
372
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
   *  Send some bits to the MII.  The bits to be sent are right-
   *  justified in the 'data' parameter.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
375
376
   *
   *  Input parameters:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
377
378
379
   *  	   sbm_mdio - address of the MAC's MDIO register
   *  	   data     - data to send
   *  	   bitcnt   - number of bits to send
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
381
382
  static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
  			       int bitcnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
  {
  	int i;
  	uint64_t bits;
  	unsigned int curmask;
  	int mac_mdio_genc;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
388
  	mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
389

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  	bits = M_MAC_MDIO_DIR_OUTPUT;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
391
  	__raw_writeq(bits | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
392

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  	curmask = 1 << (bitcnt - 1);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
394

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
398
  	for (i = 0; i < bitcnt; i++) {
  		if (data & curmask)
  			bits |= M_MAC_MDIO_OUT;
  		else bits &= ~M_MAC_MDIO_OUT;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
399
400
401
  		__raw_writeq(bits | mac_mdio_genc, sbm_mdio);
  		__raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
  		__raw_writeq(bits | mac_mdio_genc, sbm_mdio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
403
404
405
406
407
408
  		curmask >>= 1;
  	}
  }
  
  
  
  /**********************************************************************
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
409
   *  SBMAC_MII_READ(bus, phyaddr, regidx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
   *  Read a PHY register.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
411
412
   *
   *  Input parameters:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
413
   *  	   bus     - MDIO bus handle
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
   *  	   phyaddr - PHY's address
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
415
   *  	   regnum  - index of register to read
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
416
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
   *  Return value:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
418
   *  	   value read, or 0xffff if an error occurred.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
420
  static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
422
423
  	struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
  	void __iomem *sbm_mdio = sc->sbm_mdio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
  	int idx;
  	int error;
  	int regval;
  	int mac_mdio_genc;
  
  	/*
  	 * Synchronize ourselves so that the PHY knows the next
  	 * thing coming down is a command
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
433
  	sbmac_mii_sync(sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
434

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
439
440
441
  	/*
  	 * Send the data to the PHY.  The sequence is
  	 * a "start" command (2 bits)
  	 * a "read" command (2 bits)
  	 * the PHY addr (5 bits)
  	 * the register index (5 bits)
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
442
443
444
445
  	sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
  	sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2);
  	sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
  	sbmac_mii_senddata(sbm_mdio, regidx, 5);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
446

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
447
  	mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
448
449
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  	 * Switch the port around without a clock transition.
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
452
  	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
453

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
  	/*
  	 * Send out a clock pulse to signal we want the status
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
457
458
459
  	__raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
  		     sbm_mdio);
  	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
460
461
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
  	 * If an error occurred, the PHY will signal '1' back
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
464
  	error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
465
466
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
  	 * Issue an 'idle' clock pulse, but keep the direction
  	 * the same.
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
470
471
472
  	__raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
  		     sbm_mdio);
  	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
473

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  	regval = 0;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
475

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
  	for (idx = 0; idx < 16; idx++) {
  		regval <<= 1;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
478

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  		if (error == 0) {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
480
  			if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
  				regval |= 1;
  		}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
483

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
484
485
486
  		__raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
  			     sbm_mdio);
  		__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
488

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  	/* Switch back to output */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
490
  	__raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
491

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
  	if (error == 0)
  		return regval;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
494
  	return 0xffff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
  }
  
  
  /**********************************************************************
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
499
   *  SBMAC_MII_WRITE(bus, phyaddr, regidx, regval)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
500
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
   *  Write a value to a PHY register.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
502
503
   *
   *  Input parameters:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
504
   *  	   bus     - MDIO bus handle
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
   *  	   phyaddr - PHY to use
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
506
507
   *  	   regidx  - register within the PHY
   *  	   regval  - data to write to register
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
508
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
   *  Return value:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
510
   *  	   0 for success
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
512
513
  static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
  			   u16 regval)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
515
516
  	struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
  	void __iomem *sbm_mdio = sc->sbm_mdio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  	int mac_mdio_genc;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
518
  	sbmac_mii_sync(sbm_mdio);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
519

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
520
521
522
523
524
525
  	sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
  	sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2);
  	sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
  	sbmac_mii_senddata(sbm_mdio, regidx, 5);
  	sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2);
  	sbmac_mii_senddata(sbm_mdio, regval, 16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
527
  	mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
529
530
531
  	__raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
536
537
  }
  
  
  
  /**********************************************************************
   *  SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
538
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
   *  Initialize a DMA channel context.  Since there are potentially
   *  eight DMA channels per MAC, it's nice to do this in a standard
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
541
542
543
   *  way.
   *
   *  Input parameters:
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
544
545
   *  	   d - struct sbmacdma (DMA channel context)
   *  	   s - struct sbmac_softc (pointer to a MAC)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
   *  	   chan - channel number (0..1 right now)
   *  	   txrx - Identifies DMA_TX or DMA_RX for channel direction
   *      maxdescr - number of descriptors
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
549
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
553
554
  static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan,
  			  int txrx, int maxdescr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  {
693aa9470   Mark Mason   add NAPI support ...
556
557
558
  #ifdef CONFIG_SBMAC_COALESCE
  	int int_pktcnt, int_timeout;
  #endif
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
559
560
  	/*
  	 * Save away interesting stuff in the structure
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
562

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
  	d->sbdma_eth       = s;
  	d->sbdma_channel   = chan;
  	d->sbdma_txdir     = txrx;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
566

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
  #if 0
  	/* RMON clearing */
  	s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
  #endif
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR);
  	__raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592

74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
593
594
  	/*
  	 * initialize register pointers
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
596
597
  
  	d->sbdma_config0 =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
599
  	d->sbdma_config1 =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
601
  	d->sbdma_dscrbase =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
603
  	d->sbdma_dscrcnt =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
605
  	d->sbdma_curdscr =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
693aa9470   Mark Mason   add NAPI support ...
607
608
609
610
611
  	if (d->sbdma_txdir)
  		d->sbdma_oodpktlost = NULL;
  	else
  		d->sbdma_oodpktlost =
  			s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_OODPKTLOST_RX);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
612

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
  	/*
  	 * Allocate memory for the ring
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
616

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  	d->sbdma_maxdescr = maxdescr;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
618

73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
619
620
621
  	d->sbdma_dscrtable_unaligned = kcalloc(d->sbdma_maxdescr + 1,
  					       sizeof(*d->sbdma_dscrtable),
  					       GFP_KERNEL);
04115def6   Ralf Baechle   [PATCH] sb1250-ma...
622
623
624
625
626
  
  	/*
  	 * The descriptor table must be aligned to at least 16 bytes or the
  	 * MAC will corrupt it.
  	 */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
627
628
629
  	d->sbdma_dscrtable = (struct sbdmadscr *)
  			     ALIGN((unsigned long)d->sbdma_dscrtable_unaligned,
  				   sizeof(*d->sbdma_dscrtable));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
630

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  	d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
632

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
  	d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
634

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
  	/*
  	 * And context table
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
638

c477f3348   Mariusz Kozlowski   drivers/net/sb125...
639
  	d->sbdma_ctxtable = kcalloc(d->sbdma_maxdescr,
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
640
  				    sizeof(*d->sbdma_ctxtable), GFP_KERNEL);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
641

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
  #ifdef CONFIG_SBMAC_COALESCE
  	/*
  	 * Setup Rx/Tx DMA coalescing defaults
  	 */
693aa9470   Mark Mason   add NAPI support ...
646
  	int_pktcnt = (txrx == DMA_TX) ? int_pktcnt_tx : int_pktcnt_rx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
650
651
  	if ( int_pktcnt ) {
  		d->sbdma_int_pktcnt = int_pktcnt;
  	} else {
  		d->sbdma_int_pktcnt = 1;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
652

693aa9470   Mark Mason   add NAPI support ...
653
  	int_timeout = (txrx == DMA_TX) ? int_timeout_tx : int_timeout_rx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
659
660
661
662
663
664
  	if ( int_timeout ) {
  		d->sbdma_int_timeout = int_timeout;
  	} else {
  		d->sbdma_int_timeout = 0;
  	}
  #endif
  
  }
  
  /**********************************************************************
   *  SBDMA_CHANNEL_START(d)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
665
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
   *  Initialize the hardware registers for a DMA channel.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
667
668
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
   *  	   d - DMA channel to init (context must be previously init'd
   *         rxtx - DMA_RX or DMA_TX depending on what type of channel
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
671
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
675
  static void sbdma_channel_start(struct sbmacdma *d, int rxtx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
  {
  	/*
  	 * Turn on the DMA channel
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
680

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  #ifdef CONFIG_SBMAC_COALESCE
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
682
683
684
  	__raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
  		       0, d->sbdma_config1);
  	__raw_writeq(M_DMA_EOP_INT_EN |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
  		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
  		       V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
687
  		       0, d->sbdma_config0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
  #else
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
689
690
691
  	__raw_writeq(0, d->sbdma_config1);
  	__raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
  		       0, d->sbdma_config0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  #endif
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
693
  	__raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
699
700
701
702
703
704
  
  	/*
  	 * Initialize ring pointers
  	 */
  
  	d->sbdma_addptr = d->sbdma_dscrtable;
  	d->sbdma_remptr = d->sbdma_dscrtable;
  }
  
  /**********************************************************************
   *  SBDMA_CHANNEL_STOP(d)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
705
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
   *  Initialize the hardware registers for a DMA channel.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
707
708
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
   *  	   d - DMA channel to init (context must be previously init'd
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
710
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
712
713
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
714
  static void sbdma_channel_stop(struct sbmacdma *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
  {
  	/*
  	 * Turn off the DMA channel
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
719

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
720
  	__raw_writeq(0, d->sbdma_config1);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
721

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
722
  	__raw_writeq(0, d->sbdma_dscrbase);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
723

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
724
  	__raw_writeq(0, d->sbdma_config0);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
725

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
728
  	/*
  	 * Zero ring pointers
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
729

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
730
731
  	d->sbdma_addptr = NULL;
  	d->sbdma_remptr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  }
789585e96   Stephen Hemminger   sb1250: use netde...
733
734
  static inline void sbdma_align_skb(struct sk_buff *skb,
  				   unsigned int power2, unsigned int offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  {
789585e96   Stephen Hemminger   sb1250: use netde...
736
737
  	unsigned char *addr = skb->data;
  	unsigned char *newaddr = PTR_ALIGN(addr, power2);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
738

789585e96   Stephen Hemminger   sb1250: use netde...
739
  	skb_reserve(skb, newaddr - addr + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
742
743
744
  }
  
  
  /**********************************************************************
   *  SBDMA_ADD_RCVBUFFER(d,sb)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
745
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
   *  Add a buffer to the specified DMA channel.   For receive channels,
   *  this queues a buffer for inbound packets.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
748
749
   *
   *  Input parameters:
789585e96   Stephen Hemminger   sb1250: use netde...
750
751
   *	   sc - softc structure
   *  	    d - DMA channel descriptor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
   * 	   sb - sk_buff to add, or NULL if we should allocate one
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
753
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
   *  Return value:
   *  	   0 if buffer could not be added (ring is full)
   *  	   1 if buffer added successfully
   ********************************************************************* */
789585e96   Stephen Hemminger   sb1250: use netde...
758
759
  static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
  			       struct sk_buff *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
  {
789585e96   Stephen Hemminger   sb1250: use netde...
761
  	struct net_device *dev = sc->sbm_dev;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
762
763
  	struct sbdmadscr *dsc;
  	struct sbdmadscr *nextdsc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
  	struct sk_buff *sb_new = NULL;
  	int pktsize = ENET_PACKET_SIZE;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
766

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  	/* get pointer to our current place in the ring */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
768

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
  	dsc = d->sbdma_addptr;
  	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
771

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
773
774
775
776
  	/*
  	 * figure out if the ring is full - if the next descriptor
  	 * is the same as the one that we're going to remove from
  	 * the ring, the ring is full
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
777

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
  	if (nextdsc == d->sbdma_remptr) {
  		return -ENOSPC;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
781
782
  	/*
  	 * Allocate a sk_buff if we don't already have one.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
784
785
786
787
788
789
790
  	 * If we do have an sk_buff, reset it so that it's empty.
  	 *
  	 * Note: sk_buffs don't seem to be guaranteed to have any sort
  	 * of alignment when they are allocated.  Therefore, allocate enough
  	 * extra space to make sure that:
  	 *
  	 *    1. the data does not start in the middle of a cache line.
  	 *    2. The data does not end in the middle of a cache line
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
791
  	 *    3. The buffer can be aligned such that the IP addresses are
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
795
796
797
798
  	 *       naturally aligned.
  	 *
  	 *  Remember, the SOCs MAC writes whole cache lines at a time,
  	 *  without reading the old contents first.  So, if the sk_buff's
  	 *  data portion starts in the middle of a cache line, the SOC
  	 *  DMA will trash the beginning (and ending) portions.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
799

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  	if (sb == NULL) {
789585e96   Stephen Hemminger   sb1250: use netde...
801
802
803
  		sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
  					       SMP_CACHE_BYTES * 2 +
  					       NET_IP_ALIGN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
  		if (sb_new == NULL) {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
805
806
  			pr_info("%s: sk_buff allocation failed
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
  			       d->sbdma_eth->sbm_dev->name);
  			return -ENOBUFS;
  		}
789585e96   Stephen Hemminger   sb1250: use netde...
810
  		sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
813
  	}
  	else {
  		sb_new = sb;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
814
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
818
  		 * nothing special to reinit buffer, it's already aligned
  		 * and sb->data already points to a good place.
  		 */
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
819

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
821
  	 * fill in the descriptor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
823

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
826
827
  #ifdef CONFIG_SBMAC_COALESCE
  	/*
  	 * Do not interrupt per DMA transfer.
  	 */
689be4394   David S. Miller   [NET]: Remove gra...
828
  	dsc->dscr_a = virt_to_phys(sb_new->data) |
789585e96   Stephen Hemminger   sb1250: use netde...
829
  		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
  #else
689be4394   David S. Miller   [NET]: Remove gra...
831
  	dsc->dscr_a = virt_to_phys(sb_new->data) |
789585e96   Stephen Hemminger   sb1250: use netde...
832
  		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
834
835
836
837
  		M_DMA_DSCRA_INTERRUPT;
  #endif
  
  	/* receiving: no options */
  	dsc->dscr_b = 0;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
838

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
840
  	 * fill in the context
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
842

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
844
845
846
  
  	/*
  	 * point at next packet
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
848

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  	d->sbdma_addptr = nextdsc;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
850
851
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
  	 * Give the buffer to the DMA engine.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
854

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
855
  	__raw_writeq(1, d->sbdma_dscrcnt);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
856

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
859
860
861
  	return 0;					/* we did it */
  }
  
  /**********************************************************************
   *  SBDMA_ADD_TXBUFFER(d,sb)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
862
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
   *  Add a transmit buffer to the specified DMA channel, causing a
   *  transmit to start.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
865
866
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
   *  	   d - DMA channel descriptor
   * 	   sb - sk_buff to add
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
869
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
871
872
873
   *  Return value:
   *  	   0 transmit queued successfully
   *  	   otherwise error code
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
874
  static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  {
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
876
877
  	struct sbdmadscr *dsc;
  	struct sbdmadscr *nextdsc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
879
880
  	uint64_t phys;
  	uint64_t ncb;
  	int length;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
881

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  	/* get pointer to our current place in the ring */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
883

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
  	dsc = d->sbdma_addptr;
  	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
886

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
888
889
890
891
  	/*
  	 * figure out if the ring is full - if the next descriptor
  	 * is the same as the one that we're going to remove from
  	 * the ring, the ring is full
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
892

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
894
895
  	if (nextdsc == d->sbdma_remptr) {
  		return -ENOSPC;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
896

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
  	/*
  	 * Under Linux, it's not necessary to copy/coalesce buffers
  	 * like it is on NetBSD.  We think they're all contiguous,
  	 * but that may not be true for GBE.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
902

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  	length = sb->len;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
904

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
909
910
  	/*
  	 * fill in the descriptor.  Note that the number of cache
  	 * blocks in the descriptor is the number of blocks
  	 * *spanned*, so we need to add in the offset (if any)
  	 * while doing the calculation.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
911

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
  	phys = virt_to_phys(sb->data);
  	ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
914
  	dsc->dscr_a = phys |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
917
918
919
  		V_DMA_DSCRA_A_SIZE(ncb) |
  #ifndef CONFIG_SBMAC_COALESCE
  		M_DMA_DSCRA_INTERRUPT |
  #endif
  		M_DMA_ETHTX_SOP;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
920

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
923
924
  	/* transmitting: set outbound options and length */
  
  	dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
  		V_DMA_DSCRB_PKT_SIZE(length);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
925

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
927
  	 * fill in the context
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
929

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
931
932
933
  
  	/*
  	 * point at next packet
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
935

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
  	d->sbdma_addptr = nextdsc;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
937
938
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
  	 * Give the buffer to the DMA engine.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
941

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
942
  	__raw_writeq(1, d->sbdma_dscrcnt);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
943

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
951
  	return 0;					/* we did it */
  }
  
  
  
  
  /**********************************************************************
   *  SBDMA_EMPTYRING(d)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
952
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
   *  Free all allocated sk_buffs on the specified DMA channel;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
954
955
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
   *  	   d  - DMA channel
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
957
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
961
  static void sbdma_emptyring(struct sbmacdma *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
964
  {
  	int idx;
  	struct sk_buff *sb;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
965

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
969
970
971
972
973
974
975
976
977
  	for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
  		sb = d->sbdma_ctxtable[idx];
  		if (sb) {
  			dev_kfree_skb(sb);
  			d->sbdma_ctxtable[idx] = NULL;
  		}
  	}
  }
  
  
  /**********************************************************************
   *  SBDMA_FILLRING(d)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
978
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
   *  Fill the specified DMA channel (must be receive channel)
   *  with sk_buffs
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
981
982
   *
   *  Input parameters:
789585e96   Stephen Hemminger   sb1250: use netde...
983
984
   *	   sc - softc structure
   *  	    d - DMA channel
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
985
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
988
   *  Return value:
   *  	   nothing
   ********************************************************************* */
789585e96   Stephen Hemminger   sb1250: use netde...
989
  static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
  {
  	int idx;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
992

789585e96   Stephen Hemminger   sb1250: use netde...
993
994
  	for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) {
  		if (sbdma_add_rcvbuffer(sc, d, NULL) != 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
  			break;
  	}
  }
d68300182   Deepak Saxena   Netpoll support f...
998
999
1000
1001
1002
1003
1004
  #ifdef CONFIG_NET_POLL_CONTROLLER
  static void sbmac_netpoll(struct net_device *netdev)
  {
  	struct sbmac_softc *sc = netdev_priv(netdev);
  	int irq = sc->sbm_dev->irq;
  
  	__raw_writeq(0, sc->sbm_imr);
0da2f0f16   Yoann Padioleau   potential compile...
1005
  	sbmac_intr(irq, netdev);
d68300182   Deepak Saxena   Netpoll support f...
1006
1007
1008
1009
1010
1011
  
  #ifdef CONFIG_SBMAC_COALESCE
  	__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
  	((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0),
  	sc->sbm_imr);
  #else
7d2e3cb70   Jeff Garzik   [netdrvr] Trim tr...
1012
  	__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
d68300182   Deepak Saxena   Netpoll support f...
1013
1014
1015
1016
  	(M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr);
  #endif
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
1018
  
  /**********************************************************************
693aa9470   Mark Mason   add NAPI support ...
1019
   *  SBDMA_RX_PROCESS(sc,d,work_to_do,poll)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1020
1021
   *
   *  Process "completed" receive buffers on the specified DMA channel.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
   *
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1023
   *  Input parameters:
693aa9470   Mark Mason   add NAPI support ...
1024
1025
1026
1027
1028
   *            sc - softc structure
   *  	       d - DMA channel context
   *    work_to_do - no. of packets to process before enabling interrupt
   *                 again (for NAPI)
   *          poll - 1: using polling (for NAPI)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1029
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
1032
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1033
1034
  static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d,
  			    int work_to_do, int poll)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1036
  	struct net_device *dev = sc->sbm_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
  	int curidx;
  	int hwidx;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1039
  	struct sbdmadscr *dsc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
  	struct sk_buff *sb;
  	int len;
693aa9470   Mark Mason   add NAPI support ...
1042
1043
  	int work_done = 0;
  	int dropped = 0;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1044

693aa9470   Mark Mason   add NAPI support ...
1045
1046
1047
1048
  	prefetch(d);
  
  again:
  	/* Check if the HW dropped any frames */
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1049
  	dev->stats.rx_fifo_errors
693aa9470   Mark Mason   add NAPI support ...
1050
1051
1052
1053
  	    += __raw_readq(sc->sbm_rxdma.sbdma_oodpktlost) & 0xffff;
  	__raw_writeq(0, sc->sbm_rxdma.sbdma_oodpktlost);
  
  	while (work_to_do-- > 0) {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1054
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
1057
  		 * figure out where we are (as an index) and where
  		 * the hardware is (also as an index)
  		 *
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1058
  		 * This could be done faster if (for example) the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
1060
1061
1062
1063
  		 * descriptor table was page-aligned and contiguous in
  		 * both virtual and physical memory -- you could then
  		 * just compare the low-order bits of the virtual address
  		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1064

693aa9470   Mark Mason   add NAPI support ...
1065
1066
1067
1068
1069
  		dsc = d->sbdma_remptr;
  		curidx = dsc - d->sbdma_dscrtable;
  
  		prefetch(dsc);
  		prefetch(&d->sbdma_ctxtable[curidx]);
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1070
1071
1072
  		hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
  			 d->sbdma_dscrtable_phys) /
  			sizeof(*d->sbdma_dscrtable);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1073

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
1075
1076
1077
1078
  		/*
  		 * If they're the same, that means we've processed all
  		 * of the descriptors up to (but not including) the one that
  		 * the hardware is working on right now.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1079

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
  		if (curidx == hwidx)
693aa9470   Mark Mason   add NAPI support ...
1081
  			goto done;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1082

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
  		/*
  		 * Otherwise, get the packet's sk_buff ptr back
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1086

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
  		sb = d->sbdma_ctxtable[curidx];
  		d->sbdma_ctxtable[curidx] = NULL;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1089

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
  		len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1091

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
1095
1096
  		/*
  		 * Check packet status.  If good, process it.
  		 * If not, silently drop it and put it back on the
  		 * receive ring.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1097

693aa9470   Mark Mason   add NAPI support ...
1098
  		if (likely (!(dsc->dscr_a & M_DMA_ETHRX_BAD))) {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1099

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
1102
1103
1104
  			/*
  			 * Add a new buffer to replace the old one.  If we fail
  			 * to allocate a buffer, we're going to drop this
  			 * packet and put it right back on the receive ring.
  			 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1105

789585e96   Stephen Hemminger   sb1250: use netde...
1106
1107
  			if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) ==
  				     -ENOBUFS)) {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1108
  				dev->stats.rx_dropped++;
789585e96   Stephen Hemminger   sb1250: use netde...
1109
1110
  				/* Re-add old buffer */
  				sbdma_add_rcvbuffer(sc, d, sb);
693aa9470   Mark Mason   add NAPI support ...
1111
1112
1113
1114
1115
  				/* No point in continuing at the moment */
  				printk(KERN_ERR "dropped packet (1)
  ");
  				d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
  				goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
1118
1119
1120
  			} else {
  				/*
  				 * Set length into the packet
  				 */
  				skb_put(sb,len);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1121

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
1123
1124
1125
1126
  				/*
  				 * Buffer has been replaced on the
  				 * receive ring.  Pass the buffer to
  				 * the kernel
  				 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
  				sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
  				/* Check hw IPv4/TCP checksum if supported */
  				if (sc->rx_hw_checksum == ENABLE) {
  					if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) &&
  					    !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) {
  						sb->ip_summed = CHECKSUM_UNNECESSARY;
  						/* don't need to set sb->csum */
  					} else {
  						sb->ip_summed = CHECKSUM_NONE;
  					}
  				}
693aa9470   Mark Mason   add NAPI support ...
1138
1139
1140
1141
1142
1143
1144
1145
  				prefetch(sb->data);
  				prefetch((const void *)(((char *)sb->data)+32));
  				if (poll)
  					dropped = netif_receive_skb(sb);
  				else
  					dropped = netif_rx(sb);
  
  				if (dropped == NET_RX_DROP) {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1146
  					dev->stats.rx_dropped++;
693aa9470   Mark Mason   add NAPI support ...
1147
1148
1149
1150
  					d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
  					goto done;
  				}
  				else {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1151
1152
  					dev->stats.rx_bytes += len;
  					dev->stats.rx_packets++;
693aa9470   Mark Mason   add NAPI support ...
1153
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
1155
1156
1157
1158
1159
  			}
  		} else {
  			/*
  			 * Packet was mangled somehow.  Just drop it and
  			 * put it back on the receive ring.
  			 */
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1160
  			dev->stats.rx_errors++;
789585e96   Stephen Hemminger   sb1250: use netde...
1161
  			sbdma_add_rcvbuffer(sc, d, sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  		}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1163
1164
1165
  
  
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  		 * .. and advance to the next buffer.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1168

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
693aa9470   Mark Mason   add NAPI support ...
1170
1171
1172
1173
1174
  		work_done++;
  	}
  	if (!poll) {
  		work_to_do = 32;
  		goto again; /* collect fifo drop statistics again */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
  	}
693aa9470   Mark Mason   add NAPI support ...
1176
1177
  done:
  	return work_done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
  /**********************************************************************
   *  SBDMA_TX_PROCESS(sc,d)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1181
1182
   *
   *  Process "completed" transmit buffers on the specified DMA channel.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
1184
   *  This is normally called within the interrupt service routine.
   *  Note that this isn't really ideal for priority channels, since
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1185
1186
   *  it processes all of the packets on a given channel before
   *  returning.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
   *
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1188
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
   *      sc - softc structure
693aa9470   Mark Mason   add NAPI support ...
1190
1191
   *  	 d - DMA channel context
   *    poll - 1: using polling (for NAPI)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1192
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
1194
1195
   *  Return value:
   *  	   nothing
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1196
1197
  static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
  			     int poll)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
1199
  	struct net_device *dev = sc->sbm_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
1201
  	int curidx;
  	int hwidx;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1202
  	struct sbdmadscr *dsc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203
1204
  	struct sk_buff *sb;
  	unsigned long flags;
693aa9470   Mark Mason   add NAPI support ...
1205
  	int packets_handled = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
  
  	spin_lock_irqsave(&(sc->sbm_lock), flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1208

693aa9470   Mark Mason   add NAPI support ...
1209
1210
  	if (d->sbdma_remptr == d->sbdma_addptr)
  	  goto end_unlock;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1211
1212
  	hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
  		 d->sbdma_dscrtable_phys) / sizeof(*d->sbdma_dscrtable);
693aa9470   Mark Mason   add NAPI support ...
1213

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
  	for (;;) {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1215
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
1217
1218
  		 * figure out where we are (as an index) and where
  		 * the hardware is (also as an index)
  		 *
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1219
  		 * This could be done faster if (for example) the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
1221
1222
1223
1224
  		 * descriptor table was page-aligned and contiguous in
  		 * both virtual and physical memory -- you could then
  		 * just compare the low-order bits of the virtual address
  		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1225

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
1229
1230
1231
1232
  
  		/*
  		 * If they're the same, that means we've processed all
  		 * of the descriptors up to (but not including) the one that
  		 * the hardware is working on right now.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1233

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
1235
  		if (curidx == hwidx)
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1236

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
  		/*
  		 * Otherwise, get the packet's sk_buff ptr back
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1240

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
  		dsc = &(d->sbdma_dscrtable[curidx]);
  		sb = d->sbdma_ctxtable[curidx];
  		d->sbdma_ctxtable[curidx] = NULL;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1244

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
1246
1247
  		/*
  		 * Stats
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1248

09f75cd7b   Jeff Garzik   [NET] drivers/net...
1249
1250
  		dev->stats.tx_bytes += sb->len;
  		dev->stats.tx_packets++;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1251

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
1253
1254
  		/*
  		 * for transmits, we just free buffers.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1255

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  		dev_kfree_skb_irq(sb);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1257
1258
  
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
1261
1262
  		 * .. and advance to the next buffer.
  		 */
  
  		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1263

693aa9470   Mark Mason   add NAPI support ...
1264
  		packets_handled++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1266

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
1270
1271
  	/*
  	 * Decide if we should wake up the protocol or not.
  	 * Other drivers seem to do this when we reach a low
  	 * watermark on the transmit queue.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1272

693aa9470   Mark Mason   add NAPI support ...
1273
1274
  	if (packets_handled)
  		netif_wake_queue(d->sbdma_eth->sbm_dev);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1275

693aa9470   Mark Mason   add NAPI support ...
1276
  end_unlock:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
  	spin_unlock_irqrestore(&(sc->sbm_lock), flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1278

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279
1280
1281
1282
1283
1284
  }
  
  
  
  /**********************************************************************
   *  SBMAC_INITCTX(s)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1285
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
1287
1288
1289
   *  Initialize an Ethernet context structure - this is called
   *  once per MAC on the 1250.  Memory is allocated here, so don't
   *  call it again from inside the ioctl routines that bring the
   *  interface up/down
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1290
1291
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
   *  	   s - sbmac context structure
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1293
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
1295
1296
1297
1298
1299
   *  Return value:
   *  	   0
   ********************************************************************* */
  
  static int sbmac_initctx(struct sbmac_softc *s)
  {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1300
1301
1302
  
  	/*
  	 * figure out the addresses of some ports
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1304

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
1307
1308
1309
1310
1311
1312
  	s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
  	s->sbm_maccfg    = s->sbm_base + R_MAC_CFG;
  	s->sbm_fifocfg   = s->sbm_base + R_MAC_THRSH_CFG;
  	s->sbm_framecfg  = s->sbm_base + R_MAC_FRAMECFG;
  	s->sbm_rxfilter  = s->sbm_base + R_MAC_ADFILTER_CFG;
  	s->sbm_isr       = s->sbm_base + R_MAC_STATUS;
  	s->sbm_imr       = s->sbm_base + R_MAC_INT_MASK;
  	s->sbm_mdio      = s->sbm_base + R_MAC_MDIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
1315
1316
  	/*
  	 * Initialize the DMA channels.  Right now, only one per MAC is used
  	 * Note: Only do this _once_, as it allocates memory from the kernel!
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1317

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
  	sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
  	sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
1322
1323
  	/*
  	 * initial state is OFF
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1324

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
  	s->sbm_state = sbmac_state_off;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1326

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
  	return 0;
  }
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1329
  static void sbdma_uninitctx(struct sbmacdma *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
  {
693aa9470   Mark Mason   add NAPI support ...
1331
1332
1333
  	if (d->sbdma_dscrtable_unaligned) {
  		kfree(d->sbdma_dscrtable_unaligned);
  		d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1335

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
  	if (d->sbdma_ctxtable) {
  		kfree(d->sbdma_ctxtable);
  		d->sbdma_ctxtable = NULL;
  	}
  }
  
  
  static void sbmac_uninitctx(struct sbmac_softc *sc)
  {
  	sbdma_uninitctx(&(sc->sbm_txdma));
  	sbdma_uninitctx(&(sc->sbm_rxdma));
  }
  
  
  /**********************************************************************
   *  SBMAC_CHANNEL_START(s)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1352
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
   *  Start packet processing on this MAC.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1354
1355
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
   *  	   s - sbmac structure
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1357
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1358
1359
1360
1361
1362
1363
1364
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  
  static void sbmac_channel_start(struct sbmac_softc *s)
  {
  	uint64_t reg;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1365
  	void __iomem *port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
  	uint64_t cfg,fifo,framecfg;
  	int idx, th_value;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1368

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369
1370
1371
1372
1373
1374
  	/*
  	 * Don't do this if running
  	 */
  
  	if (s->sbm_state == sbmac_state_on)
  		return;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1375

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
1377
1378
  	/*
  	 * Bring the controller out of reset, but leave it off.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1379

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1380
  	__raw_writeq(0, s->sbm_macenable);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1381

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
1384
  	/*
  	 * Ignore all received packets
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1385

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1386
  	__raw_writeq(0, s->sbm_rxfilter);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1387
1388
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
  	 * Calculate values for various control registers.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1391

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
  	cfg = M_MAC_RETRY_EN |
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1393
  		M_MAC_TX_HOLD_SOP_EN |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
1396
1397
1398
  		V_MAC_TX_PAUSE_CNT_16K |
  		M_MAC_AP_STAT_EN |
  		M_MAC_FAST_SYNC |
  		M_MAC_SS_EN |
  		0;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1399
1400
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
1402
1403
1404
  	 * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
  	 * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
  	 * Use a larger RD_THRSH for gigabit
  	 */
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1405
  	if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
  		th_value = 28;
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1407
1408
  	else
  		th_value = 64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
1411
1412
1413
1414
1415
  
  	fifo = V_MAC_TX_WR_THRSH(4) |	/* Must be '4' or '8' */
  		((s->sbm_speed == sbmac_speed_1000)
  		 ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) |
  		V_MAC_TX_RL_THRSH(4) |
  		V_MAC_RX_PL_THRSH(4) |
  		V_MAC_RX_RD_THRSH(4) |	/* Must be '4' */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416
1417
1418
1419
1420
1421
1422
1423
  		V_MAC_RX_RL_THRSH(8) |
  		0;
  
  	framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
  		V_MAC_MAX_FRAMESZ_DEFAULT |
  		V_MAC_BACKOFF_SEL(1);
  
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1424
  	 * Clear out the hash address map
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1426

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
  	port = s->sbm_base + R_MAC_HASH_BASE;
  	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1429
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
  		port += sizeof(uint64_t);
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1432

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
1435
  	/*
  	 * Clear out the exact-match table
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1436

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
  	port = s->sbm_base + R_MAC_ADDR_BASE;
  	for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1439
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1440
1441
  		port += sizeof(uint64_t);
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1442

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
1445
  	/*
  	 * Clear out the DMA Channel mapping table registers
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1446

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
1448
  	port = s->sbm_base + R_MAC_CHUP0_BASE;
  	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1449
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
1452
1453
1454
1455
  		port += sizeof(uint64_t);
  	}
  
  
  	port = s->sbm_base + R_MAC_CHLO0_BASE;
  	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1456
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
1458
  		port += sizeof(uint64_t);
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1459

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
1462
1463
  	/*
  	 * Program the hardware address.  It goes into the hardware-address
  	 * register as well as the first filter register.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1464

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
  	reg = sbmac_addr2reg(s->sbm_hwaddr);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1466

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
  	port = s->sbm_base + R_MAC_ADDR_BASE;
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1468
  	__raw_writeq(reg, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
1470
1471
1472
1473
1474
1475
1476
  	port = s->sbm_base + R_MAC_ETHERNET_ADDR;
  
  #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
  	/*
  	 * Pass1 SOCs do not receive packets addressed to the
  	 * destination address in the R_MAC_ETHERNET_ADDR register.
  	 * Set the value to zero.
  	 */
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1477
  	__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  #else
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1479
  	__raw_writeq(reg, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
  #endif
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
1483
1484
1485
  	/*
  	 * Set the receive filter for no packets, and write values
  	 * to the various config registers
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1486

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1487
1488
1489
1490
1491
  	__raw_writeq(0, s->sbm_rxfilter);
  	__raw_writeq(0, s->sbm_imr);
  	__raw_writeq(framecfg, s->sbm_framecfg);
  	__raw_writeq(fifo, s->sbm_fifocfg);
  	__raw_writeq(cfg, s->sbm_maccfg);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1492

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493
1494
1495
  	/*
  	 * Initialize DMA channels (rings should be ok now)
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1496

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1497
1498
  	sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
  	sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1499

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
1501
1502
1503
1504
1505
  	/*
  	 * Configure the speed, duplex, and flow control
  	 */
  
  	sbmac_set_speed(s,s->sbm_speed);
  	sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1506

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507
1508
1509
  	/*
  	 * Fill the receive ring
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1510

789585e96   Stephen Hemminger   sb1250: use netde...
1511
  	sbdma_fillring(s, &(s->sbm_rxdma));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1512
1513
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514
  	 * Turn on the rest of the bits in the enable register
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1515
  	 */
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1516
1517
1518
1519
  #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
  	__raw_writeq(M_MAC_RXDMA_EN0 |
  		       M_MAC_TXDMA_EN0, s->sbm_macenable);
  #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1520
  	__raw_writeq(M_MAC_RXDMA_EN0 |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
  		       M_MAC_TXDMA_EN0 |
  		       M_MAC_RX_ENABLE |
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1523
  		       M_MAC_TX_ENABLE, s->sbm_macenable);
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1524
1525
1526
  #else
  #error invalid SiByte MAC configuation
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1527
1528
  
  #ifdef CONFIG_SBMAC_COALESCE
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1529
1530
  	__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
  		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1531
  #else
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1532
1533
  	__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
  		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
  #endif
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1535
1536
1537
  
  	/*
  	 * Enable receiving unicasts and broadcasts
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1539

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1540
  	__raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1541

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1543
  	 * we're running now.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1544
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1545

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  	s->sbm_state = sbmac_state_on;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1547
1548
1549
  
  	/*
  	 * Program multicast addresses
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1551

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
  	sbmac_setmulti(s);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1553
1554
1555
  
  	/*
  	 * If channel was in promiscuous mode before, turn that on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1557

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
1559
1560
  	if (s->sbm_devflags & IFF_PROMISC) {
  		sbmac_promiscuous_mode(s,1);
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1561

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
1563
1564
1565
1566
  }
  
  
  /**********************************************************************
   *  SBMAC_CHANNEL_STOP(s)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1567
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
   *  Stop packet processing on this MAC.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1569
1570
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
   *  	   s - sbmac structure
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1572
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
1574
1575
1576
1577
1578
1579
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  
  static void sbmac_channel_stop(struct sbmac_softc *s)
  {
  	/* don't do this if already stopped */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1580

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1581
1582
  	if (s->sbm_state == sbmac_state_off)
  		return;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1583

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1584
  	/* don't accept any packets, disable all interrupts */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1585

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1586
1587
  	__raw_writeq(0, s->sbm_rxfilter);
  	__raw_writeq(0, s->sbm_imr);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1588

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  	/* Turn off ticker */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1590

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
  	/* XXX */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1592

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
  	/* turn off receiver and transmitter */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1594

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1595
  	__raw_writeq(0, s->sbm_macenable);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1596

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
  	/* We're stopped now. */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1598

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
  	s->sbm_state = sbmac_state_off;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1600

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
1602
1603
  	/*
  	 * Stop DMA channels (rings should be ok now)
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1604

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
1606
  	sbdma_channel_stop(&(s->sbm_rxdma));
  	sbdma_channel_stop(&(s->sbm_txdma));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1607

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  	/* Empty the receive and transmit rings */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1609

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610
1611
  	sbdma_emptyring(&(s->sbm_rxdma));
  	sbdma_emptyring(&(s->sbm_txdma));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1612

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613
1614
1615
1616
  }
  
  /**********************************************************************
   *  SBMAC_SET_CHANNEL_STATE(state)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1617
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
   *  Set the channel's state ON or OFF
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1619
1620
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1621
   *  	   state - new state
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1622
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
1624
1625
   *  Return value:
   *  	   old state
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1626
1627
  static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *sc,
  						enum sbmac_state state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628
  {
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1629
  	enum sbmac_state oldstate = sc->sbm_state;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1630

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
1632
1633
  	/*
  	 * If same as previous state, return
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1634

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
1637
  	if (state == oldstate) {
  		return oldstate;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1638

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1640
  	 * If new state is ON, turn channel on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1642

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
1644
1645
1646
1647
1648
  	if (state == sbmac_state_on) {
  		sbmac_channel_start(sc);
  	}
  	else {
  		sbmac_channel_stop(sc);
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1649

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
1651
1652
  	/*
  	 * Return previous state
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1653

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
1655
1656
1657
1658
1659
  	return oldstate;
  }
  
  
  /**********************************************************************
   *  SBMAC_PROMISCUOUS_MODE(sc,onoff)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1660
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
   *  Turn on or off promiscuous mode
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1662
1663
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
   *  	   sc - softc
   *      onoff - 1 to turn on, 0 to turn off
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1666
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
1669
1670
1671
1672
1673
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  
  static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
  {
  	uint64_t reg;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1674

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
1676
  	if (sc->sbm_state != sbmac_state_on)
  		return;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1677

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  	if (onoff) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1679
  		reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680
  		reg |= M_MAC_ALLPKT_EN;
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1681
  		__raw_writeq(reg, sc->sbm_rxfilter);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1682
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
  	else {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1684
  		reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
  		reg &= ~M_MAC_ALLPKT_EN;
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1686
  		__raw_writeq(reg, sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
1688
1689
1690
1691
  	}
  }
  
  /**********************************************************************
   *  SBMAC_SETIPHDR_OFFSET(sc,onoff)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1692
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
   *  Set the iphdr offset as 15 assuming ethernet encapsulation
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1694
1695
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1696
   *  	   sc - softc
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1697
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698
1699
1700
1701
1702
1703
1704
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  
  static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
  {
  	uint64_t reg;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1705

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
  	/* Hard code the off set to 15 for now */
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1707
  	reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1708
  	reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1709
  	__raw_writeq(reg, sc->sbm_rxfilter);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1710

f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1711
1712
1713
  	/* BCM1250 pass1 didn't have hardware checksum.  Everything
  	   later does.  */
  	if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  		sc->rx_hw_checksum = DISABLE;
f90fdc3cc   Ralf Baechle   [PATCH] sb1250-ma...
1715
1716
  	} else {
  		sc->rx_hw_checksum = ENABLE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1717
1718
1719
1720
1721
1722
  	}
  }
  
  
  /**********************************************************************
   *  SBMAC_ADDR2REG(ptr)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1723
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
1725
   *  Convert six bytes into the 64-bit register value that
   *  we typically write into the SBMAC's address/mcast registers
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1726
1727
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
   *  	   ptr - pointer to 6 bytes
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1729
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
1731
1732
1733
1734
1735
1736
   *  Return value:
   *  	   register value
   ********************************************************************* */
  
  static uint64_t sbmac_addr2reg(unsigned char *ptr)
  {
  	uint64_t reg = 0;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1737

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1738
  	ptr += 6;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1739
1740
  
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
  	reg <<= 8;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1742
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
  	reg <<= 8;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1744
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
  	reg <<= 8;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1746
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
  	reg <<= 8;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1748
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
  	reg <<= 8;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1750
  	reg |= (uint64_t) *(--ptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
1752
1753
1754
1755
1756
  	return reg;
  }
  
  
  /**********************************************************************
   *  SBMAC_SET_SPEED(s,speed)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1757
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
1759
   *  Configure LAN speed for the specified MAC.
   *  Warning: must be called when MAC is off!
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1760
1761
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1762
   *  	   s - sbmac structure
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1763
   *  	   speed - speed to set MAC to (see enum sbmac_speed)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1764
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765
1766
1767
1768
   *  Return value:
   *  	   1 if successful
   *      0 indicates invalid parameters
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1769
  static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1770
1771
1772
1773
1774
1775
1776
  {
  	uint64_t cfg;
  	uint64_t framecfg;
  
  	/*
  	 * Save new current values
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1777

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1778
  	s->sbm_speed = speed;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1779

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
1782
1783
  	if (s->sbm_state == sbmac_state_on)
  		return 0;	/* save for next restart */
  
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1784
  	 * Read current register values
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1786

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1787
1788
  	cfg = __raw_readq(s->sbm_maccfg);
  	framecfg = __raw_readq(s->sbm_framecfg);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1789

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790
1791
1792
  	/*
  	 * Mask out the stuff we want to change
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1793

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
1795
1796
  	cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
  	framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
  		      M_MAC_SLOT_SIZE);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1797

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
1799
1800
  	/*
  	 * Now add in the new bits
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1801

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
1803
1804
1805
1806
1807
1808
1809
  	switch (speed) {
  	case sbmac_speed_10:
  		framecfg |= V_MAC_IFG_RX_10 |
  			V_MAC_IFG_TX_10 |
  			K_MAC_IFG_THRSH_10 |
  			V_MAC_SLOT_SIZE_10;
  		cfg |= V_MAC_SPEED_SEL_10MBPS;
  		break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1810

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
1812
1813
1814
1815
1816
1817
  	case sbmac_speed_100:
  		framecfg |= V_MAC_IFG_RX_100 |
  			V_MAC_IFG_TX_100 |
  			V_MAC_IFG_THRSH_100 |
  			V_MAC_SLOT_SIZE_100;
  		cfg |= V_MAC_SPEED_SEL_100MBPS ;
  		break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1818

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
1822
1823
1824
1825
  	case sbmac_speed_1000:
  		framecfg |= V_MAC_IFG_RX_1000 |
  			V_MAC_IFG_TX_1000 |
  			V_MAC_IFG_THRSH_1000 |
  			V_MAC_SLOT_SIZE_1000;
  		cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
  		break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1826

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1827
1828
1829
  	default:
  		return 0;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1830

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1832
  	 * Send the bits back to the hardware
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1834

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1835
1836
  	__raw_writeq(framecfg, s->sbm_framecfg);
  	__raw_writeq(cfg, s->sbm_maccfg);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1837

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
1840
1841
1842
  	return 1;
  }
  
  /**********************************************************************
   *  SBMAC_SET_DUPLEX(s,duplex,fc)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1843
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
1845
   *  Set Ethernet duplex and flow control options for this MAC
   *  Warning: must be called when MAC is off!
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1846
1847
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1848
   *  	   s - sbmac structure
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1849
1850
   *  	   duplex - duplex setting (see enum sbmac_duplex)
   *  	   fc - flow control setting (see enum sbmac_fc)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1851
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
1853
1854
1855
   *  Return value:
   *  	   1 if ok
   *  	   0 if an invalid parameter combination was specified
   ********************************************************************* */
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
1856
1857
  static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex,
  			    enum sbmac_fc fc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
1859
  {
  	uint64_t cfg;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1860

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
1862
1863
  	/*
  	 * Save new current values
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1864

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1865
1866
  	s->sbm_duplex = duplex;
  	s->sbm_fc = fc;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1867

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
1869
  	if (s->sbm_state == sbmac_state_on)
  		return 0;	/* save for next restart */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1870

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1872
  	 * Read current register values
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1873
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1874

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1875
  	cfg = __raw_readq(s->sbm_maccfg);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1876

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877
1878
1879
  	/*
  	 * Mask off the stuff we're about to change
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1880

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
  	cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1882

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
1884
1885
1886
1887
1888
  	switch (duplex) {
  	case sbmac_duplex_half:
  		switch (fc) {
  		case sbmac_fc_disabled:
  			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1889

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
1891
1892
  		case sbmac_fc_collision:
  			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1893

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1894
1895
1896
  		case sbmac_fc_carrier:
  			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1897

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898
1899
1900
1901
1902
  		case sbmac_fc_frame:		/* not valid in half duplex */
  		default:			/* invalid selection */
  			return 0;
  		}
  		break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1903

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
1905
1906
1907
1908
  	case sbmac_duplex_full:
  		switch (fc) {
  		case sbmac_fc_disabled:
  			cfg |= V_MAC_FC_CMD_DISABLED;
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1909

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
1911
1912
  		case sbmac_fc_frame:
  			cfg |= V_MAC_FC_CMD_ENABLED;
  			break;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1913

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
  		case sbmac_fc_collision:	/* not valid in full duplex */
  		case sbmac_fc_carrier:		/* not valid in full duplex */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
1917
1918
1919
  		default:
  			return 0;
  		}
  		break;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
1920
1921
  	default:
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1922
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1923

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1925
  	 * Send the bits back to the hardware
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1927

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
1928
  	__raw_writeq(cfg, s->sbm_maccfg);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1929

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
1933
1934
1935
1936
1937
  	return 1;
  }
  
  
  
  
  /**********************************************************************
   *  SBMAC_INTR()
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1938
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
   *  Interrupt handler for MAC interrupts
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1940
1941
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
   *  	   MAC structure
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1943
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944
1945
1946
   *  Return value:
   *  	   nothing
   ********************************************************************* */
7d12e780e   David Howells   IRQ: Maintain reg...
1947
  static irqreturn_t sbmac_intr(int irq,void *dev_instance)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
1949
1950
1951
1952
  {
  	struct net_device *dev = (struct net_device *) dev_instance;
  	struct sbmac_softc *sc = netdev_priv(dev);
  	uint64_t isr;
  	int handled = 0;
693aa9470   Mark Mason   add NAPI support ...
1953
1954
1955
1956
  	/*
  	 * Read the ISR (this clears the bits in the real
  	 * register, except for counter addr)
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1957

693aa9470   Mark Mason   add NAPI support ...
1958
  	isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1959

693aa9470   Mark Mason   add NAPI support ...
1960
1961
1962
  	if (isr == 0)
  		return IRQ_RETVAL(0);
  	handled = 1;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1963

693aa9470   Mark Mason   add NAPI support ...
1964
1965
1966
  	/*
  	 * Transmits on channel 0
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1967

bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
1968
  	if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0))
693aa9470   Mark Mason   add NAPI support ...
1969
  		sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1970

693aa9470   Mark Mason   add NAPI support ...
1971
  	if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
288379f05   Ben Hutchings   net: Remove redun...
1972
  		if (napi_schedule_prep(&sc->napi)) {
693aa9470   Mark Mason   add NAPI support ...
1973
  			__raw_writeq(0, sc->sbm_imr);
288379f05   Ben Hutchings   net: Remove redun...
1974
  			__napi_schedule(&sc->napi);
693aa9470   Mark Mason   add NAPI support ...
1975
1976
1977
1978
1979
1980
  			/* Depend on the exit from poll to reenable intr */
  		}
  		else {
  			/* may leave some packets behind */
  			sbdma_rx_process(sc,&(sc->sbm_rxdma),
  					 SBMAC_MAX_RXDESCR * 2, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1981
1982
1983
1984
  		}
  	}
  	return IRQ_RETVAL(handled);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1985
1986
  /**********************************************************************
   *  SBMAC_START_TX(skb,dev)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1987
1988
   *
   *  Start output on the specified interface.  Basically, we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1989
1990
   *  queue as many buffers as we can until the ring fills up, or
   *  we run off the end of the queue, whichever comes first.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
1991
1992
1993
1994
   *
   *  Input parameters:
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995
1996
1997
1998
1999
2000
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
  {
  	struct sbmac_softc *sc = netdev_priv(dev);
be61ea529   Weiwei Wang   [netdrvr] convert...
2001
  	unsigned long flags;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2002

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003
  	/* lock eth irq */
be61ea529   Weiwei Wang   [netdrvr] convert...
2004
  	spin_lock_irqsave(&sc->sbm_lock, flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2005

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
  	/*
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2007
  	 * Put the buffer on the transmit ring.  If we
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008
2009
  	 * don't have room, stop the queue.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2010

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
2012
2013
  	if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
  		/* XXX save skb that we could not send */
  		netif_stop_queue(dev);
be61ea529   Weiwei Wang   [netdrvr] convert...
2014
  		spin_unlock_irqrestore(&sc->sbm_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015

5b5481402   Patrick McHardy   net: use symbolic...
2016
  		return NETDEV_TX_BUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2017
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2018

be61ea529   Weiwei Wang   [netdrvr] convert...
2019
  	spin_unlock_irqrestore(&sc->sbm_lock, flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2020

6ed106549   Patrick McHardy   net: use NETDEV_T...
2021
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
2023
2024
2025
  }
  
  /**********************************************************************
   *  SBMAC_SETMULTI(sc)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2026
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2027
2028
2029
   *  Reprogram the multicast table into the hardware, given
   *  the list of multicasts associated with the interface
   *  structure.
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2030
2031
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2032
   *  	   sc - softc
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2033
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2034
2035
2036
2037
2038
2039
2040
   *  Return value:
   *  	   nothing
   ********************************************************************* */
  
  static void sbmac_setmulti(struct sbmac_softc *sc)
  {
  	uint64_t reg;
73d739698   Maciej W. Rozycki   sb1250-mac.c: De-...
2041
  	void __iomem *port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042
  	int idx;
22bedad3c   Jiri Pirko   net: convert mult...
2043
  	struct netdev_hw_addr *ha;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
  	struct net_device *dev = sc->sbm_dev;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2045
2046
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047
2048
  	 * Clear out entire multicast table.  We do this by nuking
  	 * the entire hash table and all the direct matches except
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2049
  	 * the first one, which is used for our station address
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2050
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2051

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
2053
  	for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
  		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2054
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2055
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2056

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2057
2058
  	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
  		port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2059
  		__raw_writeq(0, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2060
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2061

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2062
2063
2064
  	/*
  	 * Clear the filter to say we don't want any multicasts.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2065

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2066
  	reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067
  	reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2068
  	__raw_writeq(reg, sc->sbm_rxfilter);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2069

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
  	if (dev->flags & IFF_ALLMULTI) {
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2071
2072
2073
  		/*
  		 * Enable ALL multicasts.  Do this by inverting the
  		 * multicast enable bit.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2074
  		 */
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2075
  		reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
  		reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2077
  		__raw_writeq(reg, sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
2079
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2080

74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2081
2082
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2083
2084
2085
2086
  	 * Progam new multicast entries.  For now, only use the
  	 * perfect filter.  In the future we'll need to use the
  	 * hash filter if the perfect filter overflows
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2087

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
2089
  	/* XXX only using perfect filter for now, need to use hash
  	 * XXX if the table overflows */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2090

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091
  	idx = 1;		/* skip station address */
22bedad3c   Jiri Pirko   net: convert mult...
2092
  	netdev_for_each_mc_addr(ha, dev) {
5508590c1   Jiri Pirko   net: convert mult...
2093
2094
  		if (idx == MAC_ADDR_COUNT)
  			break;
22bedad3c   Jiri Pirko   net: convert mult...
2095
  		reg = sbmac_addr2reg(ha->addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2096
  		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2097
  		__raw_writeq(reg, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2098
  		idx++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2099
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2100
2101
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2102
  	 * Enable the "accept multicast bits" if we programmed at least one
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2103
  	 * multicast.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2104
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2105

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2106
  	if (idx > 1) {
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2107
  		reg = __raw_readq(sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2108
  		reg |= M_MAC_MCAST_EN;
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2109
  		__raw_writeq(reg, sc->sbm_rxfilter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2110
2111
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2112
2113
2114
2115
2116
  static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
  {
  	if (new_mtu >  ENET_PACKET_SIZE)
  		return -EINVAL;
  	_dev->mtu = new_mtu;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2117
2118
  	pr_info("changing the mtu to %d
  ", new_mtu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2119
2120
  	return 0;
  }
b4cf3421a   Alexander Beregalov   sb1250-mac: conve...
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
  static const struct net_device_ops sbmac_netdev_ops = {
  	.ndo_open		= sbmac_open,
  	.ndo_stop		= sbmac_close,
  	.ndo_start_xmit		= sbmac_start_tx,
  	.ndo_set_multicast_list	= sbmac_set_rx_mode,
  	.ndo_tx_timeout		= sbmac_tx_timeout,
  	.ndo_do_ioctl		= sbmac_mii_ioctl,
  	.ndo_change_mtu		= sb1250_change_mtu,
  	.ndo_validate_addr	= eth_validate_addr,
  	.ndo_set_mac_address	= eth_mac_addr,
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller	= sbmac_netpoll,
  #endif
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
2136
  /**********************************************************************
   *  SBMAC_INIT(dev)
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2137
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
   *  Attach routine - init hardware and hook ourselves into linux
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2139
2140
   *
   *  Input parameters:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
   *  	   dev - net_device structure
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2142
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2143
2144
2145
   *  Return value:
   *  	   status
   ********************************************************************* */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2146
  static int sbmac_init(struct platform_device *pldev, long long base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2147
  {
c7ae011dc   Greg Kroah-Hartman   net: remove drive...
2148
  	struct net_device *dev = dev_get_drvdata(&pldev->dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2149
2150
  	int idx = pldev->id;
  	struct sbmac_softc *sc = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2151
2152
2153
2154
  	unsigned char *eaddr;
  	uint64_t ea_reg;
  	int i;
  	int err;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2155

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2156
2157
  	sc->sbm_dev = dev;
  	sc->sbe_idx = idx;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2158

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2159
  	eaddr = sc->sbm_hwaddr;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2160
2161
  
  	/*
877d03105   Nick Andrew   trivial: Fix miss...
2162
  	 * Read the ethernet address.  The firmware left this programmed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2163
2164
  	 * for us in the ethernet address register for each mac.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2165

2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2166
2167
  	ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
  	__raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2168
2169
2170
2171
  	for (i = 0; i < 6; i++) {
  		eaddr[i] = (uint8_t) (ea_reg & 0xFF);
  		ea_reg >>= 8;
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2172

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2173
2174
2175
  	for (i = 0; i < 6; i++) {
  		dev->dev_addr[i] = eaddr[i];
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2176

74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2177
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2178
2179
2180
  	 * Initialize context (get pointers to registers and stuff), then
  	 * allocate the memory for the descriptor tables.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2181

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2182
  	sbmac_initctx(sc);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2183

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2184
2185
2186
  	/*
  	 * Set up Linux device callins
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2187

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2188
  	spin_lock_init(&(sc->sbm_lock));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2189

b4cf3421a   Alexander Beregalov   sb1250-mac: conve...
2190
2191
  	dev->netdev_ops = &sbmac_netdev_ops;
  	dev->watchdog_timeo = TX_TIMEOUT;
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2192
2193
  
  	netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2194

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2195
  	dev->irq		= UNIT_INT(idx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2196
2197
  	/* This is needed for PASS2 for Rx H/W checksum feature */
  	sbmac_set_iphdr_offset(sc);
298cf9beb   Lennert Buytenhek   phylib: move to d...
2198
2199
  	sc->mii_bus = mdiobus_alloc();
  	if (sc->mii_bus == NULL) {
03f80cc3f   Sebastian Siewior   net/sb1250: regis...
2200
2201
  		err = -ENOMEM;
  		goto uninit_ctx;
298cf9beb   Lennert Buytenhek   phylib: move to d...
2202
  	}
03f80cc3f   Sebastian Siewior   net/sb1250: regis...
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
  	sc->mii_bus->name = sbmac_mdio_string;
  	snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
  	sc->mii_bus->priv = sc;
  	sc->mii_bus->read = sbmac_mii_read;
  	sc->mii_bus->write = sbmac_mii_write;
  	sc->mii_bus->irq = sc->phy_irq;
  	for (i = 0; i < PHY_MAX_ADDR; ++i)
  		sc->mii_bus->irq[i] = SBMAC_PHY_INT;
  
  	sc->mii_bus->parent = &pldev->dev;
  	/*
  	 * Probe PHY address
  	 */
  	err = mdiobus_register(sc->mii_bus);
  	if (err) {
  		printk(KERN_ERR "%s: unable to register MDIO bus
  ",
  		       dev->name);
  		goto free_mdio;
  	}
  	dev_set_drvdata(&pldev->dev, sc->mii_bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2224
  	err = register_netdev(dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2225
2226
2227
2228
  	if (err) {
  		printk(KERN_ERR "%s.%d: unable to register netdev
  ",
  		       sbmac_string, idx);
03f80cc3f   Sebastian Siewior   net/sb1250: regis...
2229
  		goto unreg_mdio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230
  	}
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2231
2232
2233
2234
2235
2236
  	pr_info("%s.%d: registered as %s
  ", sbmac_string, idx, dev->name);
  
  	if (sc->rx_hw_checksum == ENABLE)
  		pr_info("%s: enabling TCP rcv checksum
  ", dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2237
2238
2239
2240
2241
  	/*
  	 * Display Ethernet address (this is called during the config
  	 * process so we need to finish off the config message that
  	 * was being displayed)
  	 */
e174961ca   Johannes Berg   net: convert prin...
2242
2243
2244
  	pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM
  ",
  	       dev->name, base, eaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2246
  	return 0;
03f80cc3f   Sebastian Siewior   net/sb1250: regis...
2247
2248
2249
2250
2251
2252
2253
2254
  unreg_mdio:
  	mdiobus_unregister(sc->mii_bus);
  	dev_set_drvdata(&pldev->dev, NULL);
  free_mdio:
  	mdiobus_free(sc->mii_bus);
  uninit_ctx:
  	sbmac_uninitctx(sc);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2255
2256
2257
2258
2259
2260
  }
  
  
  static int sbmac_open(struct net_device *dev)
  {
  	struct sbmac_softc *sc = netdev_priv(dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2261
  	int err;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2262

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2263
2264
2265
  	if (debug > 1)
  		pr_debug("%s: sbmac_open() irq %d.
  ", dev->name, dev->irq);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2266
2267
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
2269
2270
2271
  	 * map/route interrupt (clear status first, in case something
  	 * weird is pending; we haven't initialized the mac registers
  	 * yet)
  	 */
2039973af   Ralf Baechle   [PATCH] sb1250-ma...
2272
  	__raw_readq(sc->sbm_isr);
a0607fd3a   Joe Perches   drivers/net: requ...
2273
  	err = request_irq(dev->irq, sbmac_intr, IRQF_SHARED, dev->name, dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2274
2275
2276
2277
2278
2279
  	if (err) {
  		printk(KERN_ERR "%s: unable to get IRQ %d
  ", dev->name,
  		       dev->irq);
  		goto out_err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2281
2282
2283
2284
2285
  	sc->sbm_speed = sbmac_speed_none;
  	sc->sbm_duplex = sbmac_duplex_none;
  	sc->sbm_fc = sbmac_fc_none;
  	sc->sbm_pause = -1;
  	sc->sbm_link = 0;
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2286

59b818270   Ralf Baechle   [PATCH] sb1250-ma...
2287
  	/*
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2288
  	 * Attach to the PHY
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2289
  	 */
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2290
2291
2292
  	err = sbmac_mii_probe(dev);
  	if (err)
  		goto out_unregister;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2293

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2294
2295
2296
2297
2298
  	/*
  	 * Turn on the channel
  	 */
  
  	sbmac_set_channel_state(sc,sbmac_state_on);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2299

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2300
  	netif_start_queue(dev);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2301

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2302
  	sbmac_set_rx_mode(dev);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2303

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2304
2305
2306
  	phy_start(sc->phy_dev);
  
  	napi_enable(&sc->napi);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2307

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
  	return 0;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2309
2310
  
  out_unregister:
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2311
  	free_irq(dev->irq, dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2312
2313
  out_err:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2314
  }
59b818270   Ralf Baechle   [PATCH] sb1250-ma...
2315
2316
  static int sbmac_mii_probe(struct net_device *dev)
  {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2317
2318
  	struct sbmac_softc *sc = netdev_priv(dev);
  	struct phy_device *phy_dev;
59b818270   Ralf Baechle   [PATCH] sb1250-ma...
2319
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2320

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2321
  	for (i = 0; i < PHY_MAX_ADDR; i++) {
298cf9beb   Lennert Buytenhek   phylib: move to d...
2322
  		phy_dev = sc->mii_bus->phy_map[i];
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2323
2324
  		if (phy_dev)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
  	}
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2326
2327
2328
2329
  	if (!phy_dev) {
  		printk(KERN_ERR "%s: no PHY found
  ", dev->name);
  		return -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2330
  	}
db1d7bf70   Kay Sievers   net: struct devic...
2331
  	phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0,
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2332
2333
2334
2335
2336
  			      PHY_INTERFACE_MODE_GMII);
  	if (IS_ERR(phy_dev)) {
  		printk(KERN_ERR "%s: could not attach to PHY
  ", dev->name);
  		return PTR_ERR(phy_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2337
  	}
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
  	/* Remove any features not supported by the controller */
  	phy_dev->supported &= SUPPORTED_10baseT_Half |
  			      SUPPORTED_10baseT_Full |
  			      SUPPORTED_100baseT_Half |
  			      SUPPORTED_100baseT_Full |
  			      SUPPORTED_1000baseT_Half |
  			      SUPPORTED_1000baseT_Full |
  			      SUPPORTED_Autoneg |
  			      SUPPORTED_MII |
  			      SUPPORTED_Pause |
  			      SUPPORTED_Asym_Pause;
  	phy_dev->advertising = phy_dev->supported;
  
  	pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)
  ",
  		dev->name, phy_dev->drv->name,
db1d7bf70   Kay Sievers   net: struct devic...
2354
  		dev_name(&phy_dev->dev), phy_dev->irq);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2355
2356
  
  	sc->phy_dev = phy_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2357

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2358
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2359
  }
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2360
  static void sbmac_mii_poll(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
  	struct sbmac_softc *sc = netdev_priv(dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
  	struct phy_device *phy_dev = sc->phy_dev;
  	unsigned long flags;
  	enum sbmac_fc fc;
  	int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg;
  
  	link_chg = (sc->sbm_link != phy_dev->link);
  	speed_chg = (sc->sbm_speed != phy_dev->speed);
  	duplex_chg = (sc->sbm_duplex != phy_dev->duplex);
  	pause_chg = (sc->sbm_pause != phy_dev->pause);
  
  	if (!link_chg && !speed_chg && !duplex_chg && !pause_chg)
  		return;					/* Hmmm... */
  
  	if (!phy_dev->link) {
  		if (link_chg) {
  			sc->sbm_link = phy_dev->link;
  			sc->sbm_speed = sbmac_speed_none;
  			sc->sbm_duplex = sbmac_duplex_none;
  			sc->sbm_fc = sbmac_fc_disabled;
  			sc->sbm_pause = -1;
  			pr_info("%s: link unavailable
  ", dev->name);
  		}
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2388

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2389
2390
2391
2392
2393
2394
2395
2396
  	if (phy_dev->duplex == DUPLEX_FULL) {
  		if (phy_dev->pause)
  			fc = sbmac_fc_frame;
  		else
  			fc = sbmac_fc_disabled;
  	} else
  		fc = sbmac_fc_collision;
  	fc_chg = (sc->sbm_fc != fc);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2397

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2398
2399
2400
  	pr_info("%s: link available: %dbase-%cD
  ", dev->name, phy_dev->speed,
  		phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H');
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2401

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2402
  	spin_lock_irqsave(&sc->sbm_lock, flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2403

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2404
2405
2406
2407
2408
  	sc->sbm_speed = phy_dev->speed;
  	sc->sbm_duplex = phy_dev->duplex;
  	sc->sbm_fc = fc;
  	sc->sbm_pause = phy_dev->pause;
  	sc->sbm_link = phy_dev->link;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2409

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
  	if ((speed_chg || duplex_chg || fc_chg) &&
  	    sc->sbm_state != sbmac_state_off) {
  		/*
  		 * something changed, restart the channel
  		 */
  		if (debug > 1)
  			pr_debug("%s: restarting channel "
  				 "because PHY state changed
  ", dev->name);
  		sbmac_channel_stop(sc);
  		sbmac_channel_start(sc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421
  	}
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2422

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2423
  	spin_unlock_irqrestore(&sc->sbm_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2424
2425
2426
2427
2428
2429
  }
  
  
  static void sbmac_tx_timeout (struct net_device *dev)
  {
  	struct sbmac_softc *sc = netdev_priv(dev);
be61ea529   Weiwei Wang   [netdrvr] convert...
2430
  	unsigned long flags;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2431

be61ea529   Weiwei Wang   [netdrvr] convert...
2432
  	spin_lock_irqsave(&sc->sbm_lock, flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2433

1ae5dc342   Eric Dumazet   net: trans_start ...
2434
  	dev->trans_start = jiffies; /* prevent tx timeout */
09f75cd7b   Jeff Garzik   [NET] drivers/net...
2435
  	dev->stats.tx_errors++;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2436

be61ea529   Weiwei Wang   [netdrvr] convert...
2437
  	spin_unlock_irqrestore(&sc->sbm_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2438
2439
2440
2441
  
  	printk (KERN_WARNING "%s: Transmit timed out
  ",dev->name);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2442
2443
2444
  static void sbmac_set_rx_mode(struct net_device *dev)
  {
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
2446
2447
2448
2449
2450
2451
  	struct sbmac_softc *sc = netdev_priv(dev);
  
  	spin_lock_irqsave(&sc->sbm_lock, flags);
  	if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) {
  		/*
  		 * Promiscuous changed.
  		 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2452
2453
  
  		if (dev->flags & IFF_PROMISC) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2454
2455
2456
  			sbmac_promiscuous_mode(sc,1);
  		}
  		else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2457
2458
2459
2460
  			sbmac_promiscuous_mode(sc,0);
  		}
  	}
  	spin_unlock_irqrestore(&sc->sbm_lock, flags);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2461

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2462
2463
2464
  	/*
  	 * Program the multicasts.  Do this every time.
  	 */
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2465

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2466
  	sbmac_setmulti(sc);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2467

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2468
2469
2470
2471
2472
  }
  
  static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  {
  	struct sbmac_softc *sc = netdev_priv(dev);
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2473

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2474
2475
  	if (!netif_running(dev) || !sc->phy_dev)
  		return -EINVAL;
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2476

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2477
  	return phy_mii_ioctl(sc->phy_dev, if_mii(rq), cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2478
2479
2480
2481
2482
  }
  
  static int sbmac_close(struct net_device *dev)
  {
  	struct sbmac_softc *sc = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2483

bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2484
  	napi_disable(&sc->napi);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2485
  	phy_stop(sc->phy_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2486

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2487
  	sbmac_set_channel_state(sc, sbmac_state_off);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2488
2489
  
  	netif_stop_queue(dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2490
2491
2492
  	if (debug > 1)
  		pr_debug("%s: Shutting down ethercard
  ", dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2493

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2494
2495
  	phy_disconnect(sc->phy_dev);
  	sc->phy_dev = NULL;
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2496
  	free_irq(dev->irq, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2497
2498
2499
  
  	sbdma_emptyring(&(sc->sbm_txdma));
  	sbdma_emptyring(&(sc->sbm_rxdma));
74b0247fb   Ralf Baechle   [PATCH] sb1250-ma...
2500

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2501
2502
  	return 0;
  }
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2503
  static int sbmac_poll(struct napi_struct *napi, int budget)
693aa9470   Mark Mason   add NAPI support ...
2504
  {
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2505
  	struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi);
693aa9470   Mark Mason   add NAPI support ...
2506
  	int work_done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2507

bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2508
  	work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1);
693aa9470   Mark Mason   add NAPI support ...
2509
  	sbdma_tx_process(sc, &(sc->sbm_txdma), 1);
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2510
  	if (work_done < budget) {
288379f05   Ben Hutchings   net: Remove redun...
2511
  		napi_complete(napi);
693aa9470   Mark Mason   add NAPI support ...
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
  
  #ifdef CONFIG_SBMAC_COALESCE
  		__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
  			     ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0),
  			     sc->sbm_imr);
  #else
  		__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
  			     (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr);
  #endif
  	}
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
2522
  	return work_done;
693aa9470   Mark Mason   add NAPI support ...
2523
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2525

ffe8553f8   Uwe Kleine-König   net: move sb1250-...
2526
  static int __devinit sbmac_probe(struct platform_device *pldev)
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
  {
  	struct net_device *dev;
  	struct sbmac_softc *sc;
  	void __iomem *sbm_base;
  	struct resource *res;
  	u64 sbmac_orig_hwaddr;
  	int err;
  
  	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
  	BUG_ON(!res);
  	sbm_base = ioremap_nocache(res->start, res->end - res->start + 1);
  	if (!sbm_base) {
  		printk(KERN_ERR "%s: unable to map device registers
  ",
db1d7bf70   Kay Sievers   net: struct devic...
2541
  		       dev_name(&pldev->dev));
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
  		err = -ENOMEM;
  		goto out_out;
  	}
  
  	/*
  	 * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
  	 * value for us by the firmware if we're going to use this MAC.
  	 * If we find a zero, skip this MAC.
  	 */
  	sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR);
db1d7bf70   Kay Sievers   net: struct devic...
2552
2553
  	pr_debug("%s: %sconfiguring MAC at 0x%08Lx
  ", dev_name(&pldev->dev),
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
  		 sbmac_orig_hwaddr ? "" : "not ", (long long)res->start);
  	if (sbmac_orig_hwaddr == 0) {
  		err = 0;
  		goto out_unmap;
  	}
  
  	/*
  	 * Okay, cool.  Initialize this MAC.
  	 */
  	dev = alloc_etherdev(sizeof(struct sbmac_softc));
  	if (!dev) {
  		printk(KERN_ERR "%s: unable to allocate etherdev
  ",
db1d7bf70   Kay Sievers   net: struct devic...
2567
  		       dev_name(&pldev->dev));
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2568
2569
2570
  		err = -ENOMEM;
  		goto out_unmap;
  	}
c7ae011dc   Greg Kroah-Hartman   net: remove drive...
2571
  	dev_set_drvdata(&pldev->dev, dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
  	SET_NETDEV_DEV(dev, &pldev->dev);
  
  	sc = netdev_priv(dev);
  	sc->sbm_base = sbm_base;
  
  	err = sbmac_init(pldev, res->start);
  	if (err)
  		goto out_kfree;
  
  	return 0;
  
  out_kfree:
  	free_netdev(dev);
  	__raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR);
  
  out_unmap:
  	iounmap(sbm_base);
  
  out_out:
  	return err;
  }
  
  static int __exit sbmac_remove(struct platform_device *pldev)
  {
c7ae011dc   Greg Kroah-Hartman   net: remove drive...
2596
  	struct net_device *dev = dev_get_drvdata(&pldev->dev);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2597
2598
2599
2600
  	struct sbmac_softc *sc = netdev_priv(dev);
  
  	unregister_netdev(dev);
  	sbmac_uninitctx(sc);
03f80cc3f   Sebastian Siewior   net/sb1250: regis...
2601
  	mdiobus_unregister(sc->mii_bus);
298cf9beb   Lennert Buytenhek   phylib: move to d...
2602
  	mdiobus_free(sc->mii_bus);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2603
2604
2605
2606
2607
  	iounmap(sc->sbm_base);
  	free_netdev(dev);
  
  	return 0;
  }
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2608
2609
2610
2611
2612
  static struct platform_driver sbmac_driver = {
  	.probe = sbmac_probe,
  	.remove = __exit_p(sbmac_remove),
  	.driver = {
  		.name = sbmac_string,
33b665eee   Ralf Baechle   NET: SB1250: Init...
2613
  		.owner  = THIS_MODULE,
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2614
2615
  	},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2616

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2617
2618
  static int __init sbmac_init_module(void)
  {
8cd9b1320   Sebastian Andrzej Siewior   net/sb1250: setup...
2619
  	return platform_driver_register(&sbmac_driver);
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2620
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2621

f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2622
  static void __exit sbmac_cleanup_module(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2623
  {
f5279ffdc   Maciej W. Rozycki   sb1250-mac: Drive...
2624
  	platform_driver_unregister(&sbmac_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2625
2626
2627
2628
  }
  
  module_init(sbmac_init_module);
  module_exit(sbmac_cleanup_module);