tg3.c 438 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
/*
 * tg3.c: Broadcom Tigon3 ethernet driver.
 *
 * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
 * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
 * Copyright (C) 2004 Sun Microsystems Inc.
Matt Carlson's avatar
Matt Carlson committed
7
 * Copyright (C) 2005-2012 Broadcom Corporation.
Linus Torvalds's avatar
Linus Torvalds committed
8
9
 *
 * Firmware is:
Michael Chan's avatar
Michael Chan committed
10
11
12
13
14
15
 *	Derived from proprietary unpublished source code,
 *	Copyright (C) 2000-2003 Broadcom Corporation.
 *
 *	Permission is hereby granted for the distribution of this firmware
 *	data in hexadecimal or equivalent format, provided this copyright
 *	notice is accompanying it.
Linus Torvalds's avatar
Linus Torvalds committed
16
17
18
19
20
 */


#include <linux/module.h>
#include <linux/moduleparam.h>
21
#include <linux/stringify.h>
Linus Torvalds's avatar
Linus Torvalds committed
22
23
24
25
26
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/slab.h>
#include <linux/delay.h>
27
#include <linux/in.h>
Linus Torvalds's avatar
Linus Torvalds committed
28
#include <linux/init.h>
29
#include <linux/interrupt.h>
Linus Torvalds's avatar
Linus Torvalds committed
30
31
32
33
34
35
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
36
#include <linux/mdio.h>
Linus Torvalds's avatar
Linus Torvalds committed
37
#include <linux/mii.h>
Matt Carlson's avatar
Matt Carlson committed
38
#include <linux/phy.h>
Matt Carlson's avatar
Matt Carlson committed
39
#include <linux/brcmphy.h>
Linus Torvalds's avatar
Linus Torvalds committed
40
41
42
43
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/workqueue.h>
44
#include <linux/prefetch.h>
45
#include <linux/dma-mapping.h>
46
#include <linux/firmware.h>
47
48
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
Linus Torvalds's avatar
Linus Torvalds committed
49
50

#include <net/checksum.h>
51
#include <net/ip.h>
Linus Torvalds's avatar
Linus Torvalds committed
52

53
#include <linux/io.h>
Linus Torvalds's avatar
Linus Torvalds committed
54
#include <asm/byteorder.h>
55
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
56

57
58
59
#include <uapi/linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>

60
#ifdef CONFIG_SPARC
Linus Torvalds's avatar
Linus Torvalds committed
61
#include <asm/idprom.h>
62
#include <asm/prom.h>
Linus Torvalds's avatar
Linus Torvalds committed
63
64
#endif

Matt Carlson's avatar
Matt Carlson committed
65
66
67
#define BAR_0	0
#define BAR_2	2

Linus Torvalds's avatar
Linus Torvalds committed
68
69
#include "tg3.h"

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* Functions & macros to verify TG3_FLAGS types */

static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits)
{
	return test_bit(flag, bits);
}

static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits)
{
	set_bit(flag, bits);
}

static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
{
	clear_bit(flag, bits);
}

#define tg3_flag(tp, flag)				\
	_tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags)
#define tg3_flag_set(tp, flag)				\
	_tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags)
#define tg3_flag_clear(tp, flag)			\
	_tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags)

Linus Torvalds's avatar
Linus Torvalds committed
94
#define DRV_MODULE_NAME		"tg3"
95
#define TG3_MAJ_NUM			3
96
#define TG3_MIN_NUM			128
97
98
#define DRV_MODULE_VERSION	\
	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
99
#define DRV_MODULE_RELDATE	"December 03, 2012"
Linus Torvalds's avatar
Linus Torvalds committed
100

101
102
103
104
#define RESET_KIND_SHUTDOWN	0
#define RESET_KIND_INIT		1
#define RESET_KIND_SUSPEND	2

Linus Torvalds's avatar
Linus Torvalds committed
105
106
107
108
109
110
111
112
113
114
115
116
#define TG3_DEF_RX_MODE		0
#define TG3_DEF_TX_MODE		0
#define TG3_DEF_MSG_ENABLE	  \
	(NETIF_MSG_DRV		| \
	 NETIF_MSG_PROBE	| \
	 NETIF_MSG_LINK		| \
	 NETIF_MSG_TIMER	| \
	 NETIF_MSG_IFDOWN	| \
	 NETIF_MSG_IFUP		| \
	 NETIF_MSG_RX_ERR	| \
	 NETIF_MSG_TX_ERR)

117
118
#define TG3_GRC_LCLCTL_PWRSW_DELAY	100

Linus Torvalds's avatar
Linus Torvalds committed
119
120
121
/* length of time before we decide the hardware is borked,
 * and dev->tx_timeout() should be called to fix the problem
 */
122

Linus Torvalds's avatar
Linus Torvalds committed
123
124
125
126
127
#define TG3_TX_TIMEOUT			(5 * HZ)

/* hardware minimum and maximum for a single frame's data payload */
#define TG3_MIN_MTU			60
#define TG3_MAX_MTU(tp)	\
128
	(tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500)
Linus Torvalds's avatar
Linus Torvalds committed
129
130
131
132
133

/* These numbers seem to be hard coded in the NIC firmware somehow.
 * You can't change the ring sizes, but you can change where you place
 * them in the NIC onboard memory.
 */
134
#define TG3_RX_STD_RING_SIZE(tp) \
135
	(tg3_flag(tp, LRG_PROD_RING_CAP) ? \
136
	 TG3_RX_STD_MAX_SIZE_5717 : TG3_RX_STD_MAX_SIZE_5700)
Linus Torvalds's avatar
Linus Torvalds committed
137
#define TG3_DEF_RX_RING_PENDING		200
138
#define TG3_RX_JMB_RING_SIZE(tp) \
139
	(tg3_flag(tp, LRG_PROD_RING_CAP) ? \
140
	 TG3_RX_JMB_MAX_SIZE_5717 : TG3_RX_JMB_MAX_SIZE_5700)
Linus Torvalds's avatar
Linus Torvalds committed
141
142
143
144
145
146
147
148
149
150
151
152
#define TG3_DEF_RX_JUMBO_RING_PENDING	100

/* Do not place this n-ring entries value into the tp struct itself,
 * we really want to expose these constants to GCC so that modulo et
 * al.  operations are done with shifts and masks instead of with
 * hw multiply/modulo instructions.  Another solution would be to
 * replace things like '% foo' with '& (foo - 1)'.
 */

#define TG3_TX_RING_SIZE		512
#define TG3_DEF_TX_RING_PENDING		(TG3_TX_RING_SIZE - 1)

153
154
155
156
157
#define TG3_RX_STD_RING_BYTES(tp) \
	(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
#define TG3_RX_JMB_RING_BYTES(tp) \
	(sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
#define TG3_RX_RCB_RING_BYTES(tp) \
158
	(sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
Linus Torvalds's avatar
Linus Torvalds committed
159
160
161
162
#define TG3_TX_RING_BYTES	(sizeof(struct tg3_tx_buffer_desc) * \
				 TG3_TX_RING_SIZE)
#define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))

163
164
165
166
167
168
169
170
171
#define TG3_DMA_BYTE_ENAB		64

#define TG3_RX_STD_DMA_SZ		1536
#define TG3_RX_JMB_DMA_SZ		9046

#define TG3_RX_DMA_TO_MAP_SZ(x)		((x) + TG3_DMA_BYTE_ENAB)

#define TG3_RX_STD_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
#define TG3_RX_JMB_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
Linus Torvalds's avatar
Linus Torvalds committed
172

173
174
#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
	(sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
175

176
177
#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
	(sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* Due to a hardware bug, the 5701 can only DMA to memory addresses
 * that are at least dword aligned when used in PCIX mode.  The driver
 * works around this bug by double copying the packet.  This workaround
 * is built into the normal double copy length check for efficiency.
 *
 * However, the double copy is only necessary on those architectures
 * where unaligned memory accesses are inefficient.  For those architectures
 * where unaligned memory accesses incur little penalty, we can reintegrate
 * the 5701 in the normal rx path.  Doing so saves a device structure
 * dereference by hardcoding the double copy threshold in place.
 */
#define TG3_RX_COPY_THRESHOLD		256
#if NET_IP_ALIGN == 0 || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
	#define TG3_RX_COPY_THRESH(tp)	TG3_RX_COPY_THRESHOLD
#else
	#define TG3_RX_COPY_THRESH(tp)	((tp)->rx_copy_thresh)
#endif

197
198
199
#if (NET_IP_ALIGN != 0)
#define TG3_RX_OFFSET(tp)	((tp)->rx_offset)
#else
200
#define TG3_RX_OFFSET(tp)	(NET_SKB_PAD)
201
202
#endif

Linus Torvalds's avatar
Linus Torvalds committed
203
/* minimum number of free TX descriptors required to wake up TX process */
204
#define TG3_TX_WAKEUP_THRESH(tnapi)		((tnapi)->tx_pending / 4)
Matt Carlson's avatar
Matt Carlson committed
205
#define TG3_TX_BD_DMA_MAX_2K		2048
206
#define TG3_TX_BD_DMA_MAX_4K		4096
Linus Torvalds's avatar
Linus Torvalds committed
207

Matt Carlson's avatar
Matt Carlson committed
208
209
#define TG3_RAW_IP_ALIGN 2

210
#define TG3_FW_UPDATE_TIMEOUT_SEC	5
211
#define TG3_FW_UPDATE_FREQ_SEC		(TG3_FW_UPDATE_TIMEOUT_SEC / 2)
212

213
214
215
216
#define FIRMWARE_TG3		"tigon/tg3.bin"
#define FIRMWARE_TG3TSO		"tigon/tg3_tso.bin"
#define FIRMWARE_TG3TSO5	"tigon/tg3_tso5.bin"

Bill Pemberton's avatar
Bill Pemberton committed
217
static char version[] =
218
	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
Linus Torvalds's avatar
Linus Torvalds committed
219
220
221
222
223

MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
224
225
226
227
MODULE_FIRMWARE(FIRMWARE_TG3);
MODULE_FIRMWARE(FIRMWARE_TG3TSO);
MODULE_FIRMWARE(FIRMWARE_TG3TSO5);

Linus Torvalds's avatar
Linus Torvalds committed
228
229
230
231
static int tg3_debug = -1;	/* -1 == use TG3_DEF_MSG_ENABLE as value */
module_param(tg3_debug, int, 0);
MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");

232
233
234
#define TG3_DRV_DATA_FLAG_10_100_ONLY	0x0001
#define TG3_DRV_DATA_FLAG_5705_10_100	0x0002

235
static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
254
255
256
257
258
259
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
			TG3_DRV_DATA_FLAG_5705_10_100},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
			TG3_DRV_DATA_FLAG_5705_10_100},
260
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
261
262
263
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
			TG3_DRV_DATA_FLAG_5705_10_100},
264
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
265
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
266
267
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
268
269
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
270
271
272
273
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
274
275
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
276
277
278
279
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
280
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
281
282
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
283
284
285
286
	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M,
			PCI_VENDOR_ID_LENOVO,
			TG3PCI_SUBDEVICE_ID_LENOVO_5787M),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
287
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
288
289
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
290
291
292
293
294
295
296
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
Michael Chan's avatar
Michael Chan committed
297
298
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
299
300
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
Matt Carlson's avatar
Matt Carlson committed
301
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
Matt Carlson's avatar
Matt Carlson committed
302
303
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
Matt Carlson's avatar
Matt Carlson committed
304
305
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
306
307
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
308
309
310
311
312
313
	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
			PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
	{PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
			PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
Matt Carlson's avatar
Matt Carlson committed
314
315
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
316
317
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
Matt Carlson's avatar
Matt Carlson committed
318
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
319
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
Michael Chan's avatar
Michael Chan committed
320
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)},
321
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
322
323
324
325
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
326
327
328
329
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
	 .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
330
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
Matt Carlson's avatar
Matt Carlson committed
331
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
332
	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
333
334
335
336
337
338
339
	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)},
	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)},
	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)},
	{PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)},
340
	{PCI_DEVICE(0x10cf, 0x11a2)}, /* Fujitsu 1000base-SX with BCM5703SKHB */
341
	{}
Linus Torvalds's avatar
Linus Torvalds committed
342
343
344
345
};

MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);

346
static const struct {
Linus Torvalds's avatar
Linus Torvalds committed
347
	const char string[ETH_GSTRING_LEN];
348
} ethtool_stats_keys[] = {
Linus Torvalds's avatar
Linus Torvalds committed
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	{ "rx_octets" },
	{ "rx_fragments" },
	{ "rx_ucast_packets" },
	{ "rx_mcast_packets" },
	{ "rx_bcast_packets" },
	{ "rx_fcs_errors" },
	{ "rx_align_errors" },
	{ "rx_xon_pause_rcvd" },
	{ "rx_xoff_pause_rcvd" },
	{ "rx_mac_ctrl_rcvd" },
	{ "rx_xoff_entered" },
	{ "rx_frame_too_long_errors" },
	{ "rx_jabbers" },
	{ "rx_undersize_packets" },
	{ "rx_in_length_errors" },
	{ "rx_out_length_errors" },
	{ "rx_64_or_less_octet_packets" },
	{ "rx_65_to_127_octet_packets" },
	{ "rx_128_to_255_octet_packets" },
	{ "rx_256_to_511_octet_packets" },
	{ "rx_512_to_1023_octet_packets" },
	{ "rx_1024_to_1522_octet_packets" },
	{ "rx_1523_to_2047_octet_packets" },
	{ "rx_2048_to_4095_octet_packets" },
	{ "rx_4096_to_8191_octet_packets" },
	{ "rx_8192_to_9022_octet_packets" },

	{ "tx_octets" },
	{ "tx_collisions" },

	{ "tx_xon_sent" },
	{ "tx_xoff_sent" },
	{ "tx_flow_control" },
	{ "tx_mac_errors" },
	{ "tx_single_collisions" },
	{ "tx_mult_collisions" },
	{ "tx_deferred" },
	{ "tx_excessive_collisions" },
	{ "tx_late_collisions" },
	{ "tx_collide_2times" },
	{ "tx_collide_3times" },
	{ "tx_collide_4times" },
	{ "tx_collide_5times" },
	{ "tx_collide_6times" },
	{ "tx_collide_7times" },
	{ "tx_collide_8times" },
	{ "tx_collide_9times" },
	{ "tx_collide_10times" },
	{ "tx_collide_11times" },
	{ "tx_collide_12times" },
	{ "tx_collide_13times" },
	{ "tx_collide_14times" },
	{ "tx_collide_15times" },
	{ "tx_ucast_packets" },
	{ "tx_mcast_packets" },
	{ "tx_bcast_packets" },
	{ "tx_carrier_sense_errors" },
	{ "tx_discards" },
	{ "tx_errors" },

	{ "dma_writeq_full" },
	{ "dma_write_prioq_full" },
	{ "rxbds_empty" },
	{ "rx_discards" },
	{ "rx_errors" },
	{ "rx_threshold_hit" },

	{ "dma_readq_full" },
	{ "dma_read_prioq_full" },
	{ "tx_comp_queue_full" },

	{ "ring_set_send_prod_index" },
	{ "ring_status_update" },
	{ "nic_irqs" },
	{ "nic_avoided_irqs" },
424
425
426
	{ "nic_tx_threshold_hit" },

	{ "mbuf_lwm_thresh_hit" },
Linus Torvalds's avatar
Linus Torvalds committed
427
428
};

429
#define TG3_NUM_STATS	ARRAY_SIZE(ethtool_stats_keys)
430
431
432
433
434
435
436
437
#define TG3_NVRAM_TEST		0
#define TG3_LINK_TEST		1
#define TG3_REGISTER_TEST	2
#define TG3_MEMORY_TEST		3
#define TG3_MAC_LOOPB_TEST	4
#define TG3_PHY_LOOPB_TEST	5
#define TG3_EXT_LOOPB_TEST	6
#define TG3_INTERRUPT_TEST	7
438
439


440
static const struct {
441
	const char string[ETH_GSTRING_LEN];
442
} ethtool_test_keys[] = {
443
444
445
446
447
448
449
450
	[TG3_NVRAM_TEST]	= { "nvram test        (online) " },
	[TG3_LINK_TEST]		= { "link test         (online) " },
	[TG3_REGISTER_TEST]	= { "register test     (offline)" },
	[TG3_MEMORY_TEST]	= { "memory test       (offline)" },
	[TG3_MAC_LOOPB_TEST]	= { "mac loopback test (offline)" },
	[TG3_PHY_LOOPB_TEST]	= { "phy loopback test (offline)" },
	[TG3_EXT_LOOPB_TEST]	= { "ext loopback test (offline)" },
	[TG3_INTERRUPT_TEST]	= { "interrupt test    (offline)" },
451
452
};

453
454
455
#define TG3_NUM_TEST	ARRAY_SIZE(ethtool_test_keys)


456
457
458
459
460
461
462
static void tg3_write32(struct tg3 *tp, u32 off, u32 val)
{
	writel(val, tp->regs + off);
}

static u32 tg3_read32(struct tg3 *tp, u32 off)
{
463
	return readl(tp->regs + off);
464
465
}

Matt Carlson's avatar
Matt Carlson committed
466
467
468
469
470
471
472
static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val)
{
	writel(val, tp->aperegs + off);
}

static u32 tg3_ape_read32(struct tg3 *tp, u32 off)
{
473
	return readl(tp->aperegs + off);
Matt Carlson's avatar
Matt Carlson committed
474
475
}

Linus Torvalds's avatar
Linus Torvalds committed
476
477
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{
478
479
480
	unsigned long flags;

	spin_lock_irqsave(&tp->indirect_lock, flags);
481
482
	pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
	pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
483
	spin_unlock_irqrestore(&tp->indirect_lock, flags);
484
485
486
487
488
489
}

static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val)
{
	writel(val, tp->regs + off);
	readl(tp->regs + off);
Linus Torvalds's avatar
Linus Torvalds committed
490
491
}

492
static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
Linus Torvalds's avatar
Linus Torvalds committed
493
{
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&tp->indirect_lock, flags);
	pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
	pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
	spin_unlock_irqrestore(&tp->indirect_lock, flags);
	return val;
}

static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
{
	unsigned long flags;

	if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
		pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
				       TG3_64BIT_REG_LOW, val);
		return;
	}
513
	if (off == TG3_RX_STD_PROD_IDX_REG) {
514
515
516
		pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
				       TG3_64BIT_REG_LOW, val);
		return;
Linus Torvalds's avatar
Linus Torvalds committed
517
	}
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545

	spin_lock_irqsave(&tp->indirect_lock, flags);
	pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
	pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
	spin_unlock_irqrestore(&tp->indirect_lock, flags);

	/* In indirect mode when disabling interrupts, we also need
	 * to clear the interrupt bit in the GRC local ctrl register.
	 */
	if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
	    (val == 0x1)) {
		pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
				       tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
	}
}

static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
{
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(&tp->indirect_lock, flags);
	pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
	pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
	spin_unlock_irqrestore(&tp->indirect_lock, flags);
	return val;
}

546
547
548
549
550
551
/* usec_wait specifies the wait time in usec when writing to certain registers
 * where it is unsafe to read back the register without some delay.
 * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power.
 * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed.
 */
static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)
552
{
553
	if (tg3_flag(tp, PCIX_TARGET_HWBUG) || tg3_flag(tp, ICH_WORKAROUND))
554
555
556
557
558
559
560
561
562
563
564
565
566
567
		/* Non-posted methods */
		tp->write32(tp, off, val);
	else {
		/* Posted method */
		tg3_write32(tp, off, val);
		if (usec_wait)
			udelay(usec_wait);
		tp->read32(tp, off);
	}
	/* Wait again after the read for the posted method to guarantee that
	 * the wait time is met.
	 */
	if (usec_wait)
		udelay(usec_wait);
Linus Torvalds's avatar
Linus Torvalds committed
568
569
}

Michael Chan's avatar
Michael Chan committed
570
571
572
static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
{
	tp->write32_mbox(tp, off, val);
573
	if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND))
574
		tp->read32_mbox(tp, off);
Michael Chan's avatar
Michael Chan committed
575
576
}

577
static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
Linus Torvalds's avatar
Linus Torvalds committed
578
579
580
{
	void __iomem *mbox = tp->regs + off;
	writel(val, mbox);
581
	if (tg3_flag(tp, TXD_MBOX_HWBUG))
Linus Torvalds's avatar
Linus Torvalds committed
582
		writel(val, mbox);
583
	if (tg3_flag(tp, MBOX_WRITE_REORDER))
Linus Torvalds's avatar
Linus Torvalds committed
584
585
586
		readl(mbox);
}

Michael Chan's avatar
Michael Chan committed
587
588
static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
{
589
	return readl(tp->regs + off + GRCMBOX_BASE);
Michael Chan's avatar
Michael Chan committed
590
591
592
593
594
595
596
}

static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
{
	writel(val, tp->regs + off + GRCMBOX_BASE);
}

597
#define tw32_mailbox(reg, val)		tp->write32_mbox(tp, reg, val)
Michael Chan's avatar
Michael Chan committed
598
#define tw32_mailbox_f(reg, val)	tw32_mailbox_flush(tp, (reg), (val))
599
600
601
#define tw32_rx_mbox(reg, val)		tp->write32_rx_mbox(tp, reg, val)
#define tw32_tx_mbox(reg, val)		tp->write32_tx_mbox(tp, reg, val)
#define tr32_mailbox(reg)		tp->read32_mbox(tp, reg)
602

603
604
605
606
#define tw32(reg, val)			tp->write32(tp, reg, val)
#define tw32_f(reg, val)		_tw32_flush(tp, (reg), (val), 0)
#define tw32_wait_f(reg, val, us)	_tw32_flush(tp, (reg), (val), (us))
#define tr32(reg)			tp->read32(tp, reg)
Linus Torvalds's avatar
Linus Torvalds committed
607
608
609

static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
{
610
611
	unsigned long flags;

612
	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
Michael Chan's avatar
Michael Chan committed
613
614
615
	    (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
		return;

616
	spin_lock_irqsave(&tp->indirect_lock, flags);
617
	if (tg3_flag(tp, SRAM_USE_CONFIG)) {
618
619
		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
Linus Torvalds's avatar
Linus Torvalds committed
620

621
622
623
624
625
		/* Always leave this as zero. */
		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
	} else {
		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
		tw32_f(TG3PCI_MEM_WIN_DATA, val);
Michael Chan's avatar
Michael Chan committed
626

627
628
629
630
		/* Always leave this as zero. */
		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
	}
	spin_unlock_irqrestore(&tp->indirect_lock, flags);
631
632
}

Linus Torvalds's avatar
Linus Torvalds committed
633
634
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
{
635
636
	unsigned long flags;

637
	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
Michael Chan's avatar
Michael Chan committed
638
639
640
641
642
	    (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
		*val = 0;
		return;
	}

643
	spin_lock_irqsave(&tp->indirect_lock, flags);
644
	if (tg3_flag(tp, SRAM_USE_CONFIG)) {
645
646
		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
		pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
Linus Torvalds's avatar
Linus Torvalds committed
647

648
649
650
651
652
653
654
655
656
		/* Always leave this as zero. */
		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
	} else {
		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
		*val = tr32(TG3PCI_MEM_WIN_DATA);

		/* Always leave this as zero. */
		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
	}
657
	spin_unlock_irqrestore(&tp->indirect_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
658
659
}

Matt Carlson's avatar
Matt Carlson committed
660
661
662
static void tg3_ape_lock_init(struct tg3 *tp)
{
	int i;
663
	u32 regbase, bit;
664
665
666
667
668

	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
		regbase = TG3_APE_LOCK_GRANT;
	else
		regbase = TG3_APE_PER_LOCK_GRANT;
Matt Carlson's avatar
Matt Carlson committed
669
670

	/* Make sure the driver hasn't any stale locks. */
Matt Carlson's avatar
Matt Carlson committed
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
	for (i = TG3_APE_LOCK_PHY0; i <= TG3_APE_LOCK_GPIO; i++) {
		switch (i) {
		case TG3_APE_LOCK_PHY0:
		case TG3_APE_LOCK_PHY1:
		case TG3_APE_LOCK_PHY2:
		case TG3_APE_LOCK_PHY3:
			bit = APE_LOCK_GRANT_DRIVER;
			break;
		default:
			if (!tp->pci_fn)
				bit = APE_LOCK_GRANT_DRIVER;
			else
				bit = 1 << tp->pci_fn;
		}
		tg3_ape_write32(tp, regbase + 4 * i, bit);
686
687
	}

Matt Carlson's avatar
Matt Carlson committed
688
689
690
691
692
693
}

static int tg3_ape_lock(struct tg3 *tp, int locknum)
{
	int i, off;
	int ret = 0;
694
	u32 status, req, gnt, bit;
Matt Carlson's avatar
Matt Carlson committed
695

696
	if (!tg3_flag(tp, ENABLE_APE))
Matt Carlson's avatar
Matt Carlson committed
697
698
699
		return 0;

	switch (locknum) {
700
701
702
	case TG3_APE_LOCK_GPIO:
		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
			return 0;
Matt Carlson's avatar
Matt Carlson committed
703
704
	case TG3_APE_LOCK_GRC:
	case TG3_APE_LOCK_MEM:
Matt Carlson's avatar
Matt Carlson committed
705
706
707
708
		if (!tp->pci_fn)
			bit = APE_LOCK_REQ_DRIVER;
		else
			bit = 1 << tp->pci_fn;
Matt Carlson's avatar
Matt Carlson committed
709
		break;
710
711
712
713
714
715
	case TG3_APE_LOCK_PHY0:
	case TG3_APE_LOCK_PHY1:
	case TG3_APE_LOCK_PHY2:
	case TG3_APE_LOCK_PHY3:
		bit = APE_LOCK_REQ_DRIVER;
		break;
Matt Carlson's avatar
Matt Carlson committed
716
717
	default:
		return -EINVAL;
Matt Carlson's avatar
Matt Carlson committed
718
719
	}

720
721
722
723
724
725
726
727
	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
		req = TG3_APE_LOCK_REQ;
		gnt = TG3_APE_LOCK_GRANT;
	} else {
		req = TG3_APE_PER_LOCK_REQ;
		gnt = TG3_APE_PER_LOCK_GRANT;
	}

Matt Carlson's avatar
Matt Carlson committed
728
729
	off = 4 * locknum;

730
	tg3_ape_write32(tp, req + off, bit);
Matt Carlson's avatar
Matt Carlson committed
731
732
733

	/* Wait for up to 1 millisecond to acquire lock. */
	for (i = 0; i < 100; i++) {
734
		status = tg3_ape_read32(tp, gnt + off);
735
		if (status == bit)
Matt Carlson's avatar
Matt Carlson committed
736
737
738
739
			break;
		udelay(10);
	}

740
	if (status != bit) {
Matt Carlson's avatar
Matt Carlson committed
741
		/* Revoke the lock request. */
742
		tg3_ape_write32(tp, gnt + off, bit);
Matt Carlson's avatar
Matt Carlson committed
743
744
745
746
747
748
749
750
		ret = -EBUSY;
	}

	return ret;
}

static void tg3_ape_unlock(struct tg3 *tp, int locknum)
{
751
	u32 gnt, bit;
Matt Carlson's avatar
Matt Carlson committed
752

753
	if (!tg3_flag(tp, ENABLE_APE))
Matt Carlson's avatar
Matt Carlson committed
754
755
756
		return;

	switch (locknum) {
757
758
759
	case TG3_APE_LOCK_GPIO:
		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
			return;
Matt Carlson's avatar
Matt Carlson committed
760
761
	case TG3_APE_LOCK_GRC:
	case TG3_APE_LOCK_MEM:
Matt Carlson's avatar
Matt Carlson committed
762
763
764
765
		if (!tp->pci_fn)
			bit = APE_LOCK_GRANT_DRIVER;
		else
			bit = 1 << tp->pci_fn;
Matt Carlson's avatar
Matt Carlson committed
766
		break;
767
768
769
770
771
772
	case TG3_APE_LOCK_PHY0:
	case TG3_APE_LOCK_PHY1:
	case TG3_APE_LOCK_PHY2:
	case TG3_APE_LOCK_PHY3:
		bit = APE_LOCK_GRANT_DRIVER;
		break;
Matt Carlson's avatar
Matt Carlson committed
773
774
	default:
		return;
Matt Carlson's avatar
Matt Carlson committed
775
776
	}

777
778
779
780
781
	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
		gnt = TG3_APE_LOCK_GRANT;
	else
		gnt = TG3_APE_PER_LOCK_GRANT;

782
	tg3_ape_write32(tp, gnt + 4 * locknum, bit);
Matt Carlson's avatar
Matt Carlson committed
783
784
}

785
static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)
786
787
788
{
	u32 apedata;

789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
	while (timeout_us) {
		if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
			return -EBUSY;

		apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
			break;

		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);

		udelay(10);
		timeout_us -= (timeout_us > 10) ? 10 : timeout_us;
	}

	return timeout_us ? 0 : -EBUSY;
}

806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us)
{
	u32 i, apedata;

	for (i = 0; i < timeout_us / 10; i++) {
		apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);

		if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
			break;

		udelay(10);
	}

	return i == timeout_us / 10;
}

Michael Chan's avatar
Michael Chan committed
822
823
static int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off,
				   u32 len)
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
{
	int err;
	u32 i, bufoff, msgoff, maxlen, apedata;

	if (!tg3_flag(tp, APE_HAS_NCSI))
		return 0;

	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
	if (apedata != APE_SEG_SIG_MAGIC)
		return -ENODEV;

	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
	if (!(apedata & APE_FW_STATUS_READY))
		return -EAGAIN;

	bufoff = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_OFF) +
		 TG3_APE_SHMEM_BASE;
	msgoff = bufoff + 2 * sizeof(u32);
	maxlen = tg3_ape_read32(tp, TG3_APE_SEG_MSG_BUF_LEN);

	while (len) {
		u32 length;

		/* Cap xfer sizes to scratchpad limits. */
		length = (len > maxlen) ? maxlen : len;
		len -= length;

		apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
		if (!(apedata & APE_FW_STATUS_READY))
			return -EAGAIN;

		/* Wait for up to 1 msec for APE to service previous event. */
		err = tg3_ape_event_lock(tp, 1000);
		if (err)
			return err;

		apedata = APE_EVENT_STATUS_DRIVER_EVNT |
			  APE_EVENT_STATUS_SCRTCHPD_READ |
			  APE_EVENT_STATUS_EVENT_PENDING;
		tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, apedata);

		tg3_ape_write32(tp, bufoff, base_off);
		tg3_ape_write32(tp, bufoff + sizeof(u32), length);

		tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
		tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);

		base_off += length;

		if (tg3_ape_wait_for_event(tp, 30000))
			return -EAGAIN;

		for (i = 0; length; i += 4, length -= 4) {
			u32 val = tg3_ape_read32(tp, msgoff + i);
			memcpy(data, &val, sizeof(u32));
			data++;
		}
	}

	return 0;
}

886
887
888
889
static int tg3_ape_send_event(struct tg3 *tp, u32 event)
{
	int err;
	u32 apedata;
890
891
892

	apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
	if (apedata != APE_SEG_SIG_MAGIC)
893
		return -EAGAIN;
894
895
896

	apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
	if (!(apedata & APE_FW_STATUS_READY))
897
		return -EAGAIN;
898
899

	/* Wait for up to 1 millisecond for APE to service previous event. */
900
901
902
	err = tg3_ape_event_lock(tp, 1000);
	if (err)
		return err;
903

904
905
	tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
			event | APE_EVENT_STATUS_EVENT_PENDING);
906

907
908
	tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
	tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
909

910
	return 0;
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
}

static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
{
	u32 event;
	u32 apedata;

	if (!tg3_flag(tp, ENABLE_APE))
		return;

	switch (kind) {
	case RESET_KIND_INIT:
		tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
				APE_HOST_SEG_SIG_MAGIC);
		tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
				APE_HOST_SEG_LEN_MAGIC);
		apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
		tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
		tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
			APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
		tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
				APE_HOST_BEHAV_NO_PHYLOCK);
		tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
				    TG3_APE_HOST_DRVR_STATE_START);

		event = APE_EVENT_STATUS_STATE_START;
		break;
	case RESET_KIND_SHUTDOWN:
		/* With the interface we are currently using,
		 * APE does not track driver state.  Wiping
		 * out the HOST SEGMENT SIGNATURE forces
		 * the APE to assume OS absent status.
		 */
		tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);

		if (device_may_wakeup(&tp->pdev->dev) &&
		    tg3_flag(tp, WOL_ENABLE)) {
			tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
					    TG3_APE_HOST_WOL_SPEED_AUTO);
			apedata = TG3_APE_HOST_DRVR_STATE_WOL;
		} else
			apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;

		tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);

		event = APE_EVENT_STATUS_STATE_UNLOAD;
		break;
	case RESET_KIND_SUSPEND:
		event = APE_EVENT_STATUS_STATE_SUSPEND;
		break;
	default:
		return;
	}

	event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;

	tg3_ape_send_event(tp, event);
}

Linus Torvalds's avatar
Linus Torvalds committed
970
971
static void tg3_disable_ints(struct tg3 *tp)
{
972
973
	int i;

Linus Torvalds's avatar
Linus Torvalds committed
974
975
	tw32(TG3PCI_MISC_HOST_CTRL,
	     (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
976
977
	for (i = 0; i < tp->irq_max; i++)
		tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001);
Linus Torvalds's avatar
Linus Torvalds committed
978
979
980
981
}

static void tg3_enable_ints(struct tg3 *tp)
{
982
983
	int i;

984
985
986
	tp->irq_sync = 0;
	wmb();

Linus Torvalds's avatar
Linus Torvalds committed
987
988
	tw32(TG3PCI_MISC_HOST_CTRL,
	     (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
989

990
	tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
991
992
	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];
993

994
		tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
995
		if (tg3_flag(tp, 1SHOT_MSI))
996
			tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
Matt Carlson's avatar
Matt Carlson committed
997

998
		tp->coal_now |= tnapi->coal_now;
999
	}
Matt Carlson's avatar
Matt Carlson committed
1000