1adfc5217SJeff Kirsher /* bnx2.c: Broadcom NX2 network driver.
2adfc5217SJeff Kirsher  *
3adfc5217SJeff Kirsher  * Copyright (c) 2004-2011 Broadcom Corporation
4adfc5217SJeff Kirsher  *
5adfc5217SJeff Kirsher  * This program is free software; you can redistribute it and/or modify
6adfc5217SJeff Kirsher  * it under the terms of the GNU General Public License as published by
7adfc5217SJeff Kirsher  * the Free Software Foundation.
8adfc5217SJeff Kirsher  *
9adfc5217SJeff Kirsher  * Written by: Michael Chan  (mchan@broadcom.com)
10adfc5217SJeff Kirsher  */
11adfc5217SJeff Kirsher 
12adfc5217SJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13adfc5217SJeff Kirsher 
14adfc5217SJeff Kirsher #include <linux/module.h>
15adfc5217SJeff Kirsher #include <linux/moduleparam.h>
16adfc5217SJeff Kirsher 
17adfc5217SJeff Kirsher #include <linux/kernel.h>
18adfc5217SJeff Kirsher #include <linux/timer.h>
19adfc5217SJeff Kirsher #include <linux/errno.h>
20adfc5217SJeff Kirsher #include <linux/ioport.h>
21adfc5217SJeff Kirsher #include <linux/slab.h>
22adfc5217SJeff Kirsher #include <linux/vmalloc.h>
23adfc5217SJeff Kirsher #include <linux/interrupt.h>
24adfc5217SJeff Kirsher #include <linux/pci.h>
25adfc5217SJeff Kirsher #include <linux/init.h>
26adfc5217SJeff Kirsher #include <linux/netdevice.h>
27adfc5217SJeff Kirsher #include <linux/etherdevice.h>
28adfc5217SJeff Kirsher #include <linux/skbuff.h>
29adfc5217SJeff Kirsher #include <linux/dma-mapping.h>
30adfc5217SJeff Kirsher #include <linux/bitops.h>
31adfc5217SJeff Kirsher #include <asm/io.h>
32adfc5217SJeff Kirsher #include <asm/irq.h>
33adfc5217SJeff Kirsher #include <linux/delay.h>
34adfc5217SJeff Kirsher #include <asm/byteorder.h>
35adfc5217SJeff Kirsher #include <asm/page.h>
36adfc5217SJeff Kirsher #include <linux/time.h>
37adfc5217SJeff Kirsher #include <linux/ethtool.h>
38adfc5217SJeff Kirsher #include <linux/mii.h>
3901789349SJiri Pirko #include <linux/if.h>
40adfc5217SJeff Kirsher #include <linux/if_vlan.h>
41adfc5217SJeff Kirsher #include <net/ip.h>
42adfc5217SJeff Kirsher #include <net/tcp.h>
43adfc5217SJeff Kirsher #include <net/checksum.h>
44adfc5217SJeff Kirsher #include <linux/workqueue.h>
45adfc5217SJeff Kirsher #include <linux/crc32.h>
46adfc5217SJeff Kirsher #include <linux/prefetch.h>
47adfc5217SJeff Kirsher #include <linux/cache.h>
48adfc5217SJeff Kirsher #include <linux/firmware.h>
49adfc5217SJeff Kirsher #include <linux/log2.h>
50adfc5217SJeff Kirsher #include <linux/aer.h>
51adfc5217SJeff Kirsher 
52adfc5217SJeff Kirsher #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
53adfc5217SJeff Kirsher #define BCM_CNIC 1
54adfc5217SJeff Kirsher #include "cnic_if.h"
55adfc5217SJeff Kirsher #endif
56adfc5217SJeff Kirsher #include "bnx2.h"
57adfc5217SJeff Kirsher #include "bnx2_fw.h"
58adfc5217SJeff Kirsher 
59adfc5217SJeff Kirsher #define DRV_MODULE_NAME		"bnx2"
60adfc5217SJeff Kirsher #define DRV_MODULE_VERSION	"2.1.11"
61adfc5217SJeff Kirsher #define DRV_MODULE_RELDATE	"July 20, 2011"
62adfc5217SJeff Kirsher #define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-6.2.1.fw"
63adfc5217SJeff Kirsher #define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-6.0.15.fw"
64adfc5217SJeff Kirsher #define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.2.1a.fw"
65adfc5217SJeff Kirsher #define FW_RV2P_FILE_09_Ax	"bnx2/bnx2-rv2p-09ax-6.0.17.fw"
66adfc5217SJeff Kirsher #define FW_RV2P_FILE_09		"bnx2/bnx2-rv2p-09-6.0.17.fw"
67adfc5217SJeff Kirsher 
68adfc5217SJeff Kirsher #define RUN_AT(x) (jiffies + (x))
69adfc5217SJeff Kirsher 
70adfc5217SJeff Kirsher /* Time in jiffies before concluding the transmitter is hung. */
71adfc5217SJeff Kirsher #define TX_TIMEOUT  (5*HZ)
72adfc5217SJeff Kirsher 
73adfc5217SJeff Kirsher static char version[] __devinitdata =
74adfc5217SJeff Kirsher 	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
75adfc5217SJeff Kirsher 
76adfc5217SJeff Kirsher MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
77adfc5217SJeff Kirsher MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
78adfc5217SJeff Kirsher MODULE_LICENSE("GPL");
79adfc5217SJeff Kirsher MODULE_VERSION(DRV_MODULE_VERSION);
80adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_MIPS_FILE_06);
81adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_06);
82adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_MIPS_FILE_09);
83adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_09);
84adfc5217SJeff Kirsher MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
85adfc5217SJeff Kirsher 
86adfc5217SJeff Kirsher static int disable_msi = 0;
87adfc5217SJeff Kirsher 
88adfc5217SJeff Kirsher module_param(disable_msi, int, 0);
89adfc5217SJeff Kirsher MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
90adfc5217SJeff Kirsher 
91adfc5217SJeff Kirsher typedef enum {
92adfc5217SJeff Kirsher 	BCM5706 = 0,
93adfc5217SJeff Kirsher 	NC370T,
94adfc5217SJeff Kirsher 	NC370I,
95adfc5217SJeff Kirsher 	BCM5706S,
96adfc5217SJeff Kirsher 	NC370F,
97adfc5217SJeff Kirsher 	BCM5708,
98adfc5217SJeff Kirsher 	BCM5708S,
99adfc5217SJeff Kirsher 	BCM5709,
100adfc5217SJeff Kirsher 	BCM5709S,
101adfc5217SJeff Kirsher 	BCM5716,
102adfc5217SJeff Kirsher 	BCM5716S,
103adfc5217SJeff Kirsher } board_t;
104adfc5217SJeff Kirsher 
105adfc5217SJeff Kirsher /* indexed by board_t, above */
106adfc5217SJeff Kirsher static struct {
107adfc5217SJeff Kirsher 	char *name;
108adfc5217SJeff Kirsher } board_info[] __devinitdata = {
109adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5706 1000Base-T" },
110adfc5217SJeff Kirsher 	{ "HP NC370T Multifunction Gigabit Server Adapter" },
111adfc5217SJeff Kirsher 	{ "HP NC370i Multifunction Gigabit Server Adapter" },
112adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5706 1000Base-SX" },
113adfc5217SJeff Kirsher 	{ "HP NC370F Multifunction Gigabit Server Adapter" },
114adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5708 1000Base-T" },
115adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
116adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5709 1000Base-T" },
117adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5709 1000Base-SX" },
118adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5716 1000Base-T" },
119adfc5217SJeff Kirsher 	{ "Broadcom NetXtreme II BCM5716 1000Base-SX" },
120adfc5217SJeff Kirsher 	};
121adfc5217SJeff Kirsher 
122adfc5217SJeff Kirsher static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
123adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
124adfc5217SJeff Kirsher 	  PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
125adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
126adfc5217SJeff Kirsher 	  PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I },
127adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
128adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 },
129adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708,
130adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 },
131adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
132adfc5217SJeff Kirsher 	  PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F },
133adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
134adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S },
135adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S,
136adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
137adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
138adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
139adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
140adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
141adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, 0x163b,
142adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 },
143adfc5217SJeff Kirsher 	{ PCI_VENDOR_ID_BROADCOM, 0x163c,
144adfc5217SJeff Kirsher 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716S },
145adfc5217SJeff Kirsher 	{ 0, }
146adfc5217SJeff Kirsher };
147adfc5217SJeff Kirsher 
148adfc5217SJeff Kirsher static const struct flash_spec flash_table[] =
149adfc5217SJeff Kirsher {
150adfc5217SJeff Kirsher #define BUFFERED_FLAGS		(BNX2_NV_BUFFERED | BNX2_NV_TRANSLATE)
151adfc5217SJeff Kirsher #define NONBUFFERED_FLAGS	(BNX2_NV_WREN)
152adfc5217SJeff Kirsher 	/* Slow EEPROM */
153adfc5217SJeff Kirsher 	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
154adfc5217SJeff Kirsher 	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
155adfc5217SJeff Kirsher 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
156adfc5217SJeff Kirsher 	 "EEPROM - slow"},
157adfc5217SJeff Kirsher 	/* Expansion entry 0001 */
158adfc5217SJeff Kirsher 	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
159adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
160adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
161adfc5217SJeff Kirsher 	 "Entry 0001"},
162adfc5217SJeff Kirsher 	/* Saifun SA25F010 (non-buffered flash) */
163adfc5217SJeff Kirsher 	/* strap, cfg1, & write1 need updates */
164adfc5217SJeff Kirsher 	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
165adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
166adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
167adfc5217SJeff Kirsher 	 "Non-buffered flash (128kB)"},
168adfc5217SJeff Kirsher 	/* Saifun SA25F020 (non-buffered flash) */
169adfc5217SJeff Kirsher 	/* strap, cfg1, & write1 need updates */
170adfc5217SJeff Kirsher 	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
171adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
172adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
173adfc5217SJeff Kirsher 	 "Non-buffered flash (256kB)"},
174adfc5217SJeff Kirsher 	/* Expansion entry 0100 */
175adfc5217SJeff Kirsher 	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
176adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
177adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
178adfc5217SJeff Kirsher 	 "Entry 0100"},
179adfc5217SJeff Kirsher 	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
180adfc5217SJeff Kirsher 	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
181adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
182adfc5217SJeff Kirsher 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
183adfc5217SJeff Kirsher 	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
184adfc5217SJeff Kirsher 	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
185adfc5217SJeff Kirsher 	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
186adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
187adfc5217SJeff Kirsher 	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
188adfc5217SJeff Kirsher 	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
189adfc5217SJeff Kirsher 	/* Saifun SA25F005 (non-buffered flash) */
190adfc5217SJeff Kirsher 	/* strap, cfg1, & write1 need updates */
191adfc5217SJeff Kirsher 	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
192adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
193adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
194adfc5217SJeff Kirsher 	 "Non-buffered flash (64kB)"},
195adfc5217SJeff Kirsher 	/* Fast EEPROM */
196adfc5217SJeff Kirsher 	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
197adfc5217SJeff Kirsher 	 BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
198adfc5217SJeff Kirsher 	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
199adfc5217SJeff Kirsher 	 "EEPROM - fast"},
200adfc5217SJeff Kirsher 	/* Expansion entry 1001 */
201adfc5217SJeff Kirsher 	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
202adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
203adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
204adfc5217SJeff Kirsher 	 "Entry 1001"},
205adfc5217SJeff Kirsher 	/* Expansion entry 1010 */
206adfc5217SJeff Kirsher 	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
207adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
208adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
209adfc5217SJeff Kirsher 	 "Entry 1010"},
210adfc5217SJeff Kirsher 	/* ATMEL AT45DB011B (buffered flash) */
211adfc5217SJeff Kirsher 	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
212adfc5217SJeff Kirsher 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
213adfc5217SJeff Kirsher 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
214adfc5217SJeff Kirsher 	 "Buffered flash (128kB)"},
215adfc5217SJeff Kirsher 	/* Expansion entry 1100 */
216adfc5217SJeff Kirsher 	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
217adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
218adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
219adfc5217SJeff Kirsher 	 "Entry 1100"},
220adfc5217SJeff Kirsher 	/* Expansion entry 1101 */
221adfc5217SJeff Kirsher 	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
222adfc5217SJeff Kirsher 	 NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
223adfc5217SJeff Kirsher 	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
224adfc5217SJeff Kirsher 	 "Entry 1101"},
225adfc5217SJeff Kirsher 	/* Ateml Expansion entry 1110 */
226adfc5217SJeff Kirsher 	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
227adfc5217SJeff Kirsher 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
228adfc5217SJeff Kirsher 	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
229adfc5217SJeff Kirsher 	 "Entry 1110 (Atmel)"},
230adfc5217SJeff Kirsher 	/* ATMEL AT45DB021B (buffered flash) */
231adfc5217SJeff Kirsher 	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
232adfc5217SJeff Kirsher 	 BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
233adfc5217SJeff Kirsher 	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
234adfc5217SJeff Kirsher 	 "Buffered flash (256kB)"},
235adfc5217SJeff Kirsher };
236adfc5217SJeff Kirsher 
237adfc5217SJeff Kirsher static const struct flash_spec flash_5709 = {
238adfc5217SJeff Kirsher 	.flags		= BNX2_NV_BUFFERED,
239adfc5217SJeff Kirsher 	.page_bits	= BCM5709_FLASH_PAGE_BITS,
240adfc5217SJeff Kirsher 	.page_size	= BCM5709_FLASH_PAGE_SIZE,
241adfc5217SJeff Kirsher 	.addr_mask	= BCM5709_FLASH_BYTE_ADDR_MASK,
242adfc5217SJeff Kirsher 	.total_size	= BUFFERED_FLASH_TOTAL_SIZE*2,
243adfc5217SJeff Kirsher 	.name		= "5709 Buffered flash (256kB)",
244adfc5217SJeff Kirsher };
245adfc5217SJeff Kirsher 
246adfc5217SJeff Kirsher MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
247adfc5217SJeff Kirsher 
248adfc5217SJeff Kirsher static void bnx2_init_napi(struct bnx2 *bp);
249adfc5217SJeff Kirsher static void bnx2_del_napi(struct bnx2 *bp);
250adfc5217SJeff Kirsher 
251adfc5217SJeff Kirsher static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
252adfc5217SJeff Kirsher {
253adfc5217SJeff Kirsher 	u32 diff;
254adfc5217SJeff Kirsher 
255adfc5217SJeff Kirsher 	/* Tell compiler to fetch tx_prod and tx_cons from memory. */
256adfc5217SJeff Kirsher 	barrier();
257adfc5217SJeff Kirsher 
258adfc5217SJeff Kirsher 	/* The ring uses 256 indices for 255 entries, one of them
259adfc5217SJeff Kirsher 	 * needs to be skipped.
260adfc5217SJeff Kirsher 	 */
261adfc5217SJeff Kirsher 	diff = txr->tx_prod - txr->tx_cons;
262adfc5217SJeff Kirsher 	if (unlikely(diff >= TX_DESC_CNT)) {
263adfc5217SJeff Kirsher 		diff &= 0xffff;
264adfc5217SJeff Kirsher 		if (diff == TX_DESC_CNT)
265adfc5217SJeff Kirsher 			diff = MAX_TX_DESC_CNT;
266adfc5217SJeff Kirsher 	}
267adfc5217SJeff Kirsher 	return bp->tx_ring_size - diff;
268adfc5217SJeff Kirsher }
269adfc5217SJeff Kirsher 
270adfc5217SJeff Kirsher static u32
271adfc5217SJeff Kirsher bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
272adfc5217SJeff Kirsher {
273adfc5217SJeff Kirsher 	u32 val;
274adfc5217SJeff Kirsher 
275adfc5217SJeff Kirsher 	spin_lock_bh(&bp->indirect_lock);
276adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
277adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
278adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->indirect_lock);
279adfc5217SJeff Kirsher 	return val;
280adfc5217SJeff Kirsher }
281adfc5217SJeff Kirsher 
282adfc5217SJeff Kirsher static void
283adfc5217SJeff Kirsher bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
284adfc5217SJeff Kirsher {
285adfc5217SJeff Kirsher 	spin_lock_bh(&bp->indirect_lock);
286adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
287adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
288adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->indirect_lock);
289adfc5217SJeff Kirsher }
290adfc5217SJeff Kirsher 
291adfc5217SJeff Kirsher static void
292adfc5217SJeff Kirsher bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val)
293adfc5217SJeff Kirsher {
294adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, bp->shmem_base + offset, val);
295adfc5217SJeff Kirsher }
296adfc5217SJeff Kirsher 
297adfc5217SJeff Kirsher static u32
298adfc5217SJeff Kirsher bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
299adfc5217SJeff Kirsher {
300adfc5217SJeff Kirsher 	return bnx2_reg_rd_ind(bp, bp->shmem_base + offset);
301adfc5217SJeff Kirsher }
302adfc5217SJeff Kirsher 
303adfc5217SJeff Kirsher static void
304adfc5217SJeff Kirsher bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
305adfc5217SJeff Kirsher {
306adfc5217SJeff Kirsher 	offset += cid_addr;
307adfc5217SJeff Kirsher 	spin_lock_bh(&bp->indirect_lock);
308adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
309adfc5217SJeff Kirsher 		int i;
310adfc5217SJeff Kirsher 
311adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_CTX_DATA, val);
312adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_CTX_CTRL,
313adfc5217SJeff Kirsher 		       offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
314adfc5217SJeff Kirsher 		for (i = 0; i < 5; i++) {
315adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
316adfc5217SJeff Kirsher 			if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
317adfc5217SJeff Kirsher 				break;
318adfc5217SJeff Kirsher 			udelay(5);
319adfc5217SJeff Kirsher 		}
320adfc5217SJeff Kirsher 	} else {
321adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
322adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_DATA, val);
323adfc5217SJeff Kirsher 	}
324adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->indirect_lock);
325adfc5217SJeff Kirsher }
326adfc5217SJeff Kirsher 
327adfc5217SJeff Kirsher #ifdef BCM_CNIC
328adfc5217SJeff Kirsher static int
329adfc5217SJeff Kirsher bnx2_drv_ctl(struct net_device *dev, struct drv_ctl_info *info)
330adfc5217SJeff Kirsher {
331adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
332adfc5217SJeff Kirsher 	struct drv_ctl_io *io = &info->data.io;
333adfc5217SJeff Kirsher 
334adfc5217SJeff Kirsher 	switch (info->cmd) {
335adfc5217SJeff Kirsher 	case DRV_CTL_IO_WR_CMD:
336adfc5217SJeff Kirsher 		bnx2_reg_wr_ind(bp, io->offset, io->data);
337adfc5217SJeff Kirsher 		break;
338adfc5217SJeff Kirsher 	case DRV_CTL_IO_RD_CMD:
339adfc5217SJeff Kirsher 		io->data = bnx2_reg_rd_ind(bp, io->offset);
340adfc5217SJeff Kirsher 		break;
341adfc5217SJeff Kirsher 	case DRV_CTL_CTX_WR_CMD:
342adfc5217SJeff Kirsher 		bnx2_ctx_wr(bp, io->cid_addr, io->offset, io->data);
343adfc5217SJeff Kirsher 		break;
344adfc5217SJeff Kirsher 	default:
345adfc5217SJeff Kirsher 		return -EINVAL;
346adfc5217SJeff Kirsher 	}
347adfc5217SJeff Kirsher 	return 0;
348adfc5217SJeff Kirsher }
349adfc5217SJeff Kirsher 
350adfc5217SJeff Kirsher static void bnx2_setup_cnic_irq_info(struct bnx2 *bp)
351adfc5217SJeff Kirsher {
352adfc5217SJeff Kirsher 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
353adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
354adfc5217SJeff Kirsher 	int sb_id;
355adfc5217SJeff Kirsher 
356adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSIX) {
357adfc5217SJeff Kirsher 		cp->drv_state |= CNIC_DRV_STATE_USING_MSIX;
358adfc5217SJeff Kirsher 		bnapi->cnic_present = 0;
359adfc5217SJeff Kirsher 		sb_id = bp->irq_nvecs;
360adfc5217SJeff Kirsher 		cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX;
361adfc5217SJeff Kirsher 	} else {
362adfc5217SJeff Kirsher 		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
363adfc5217SJeff Kirsher 		bnapi->cnic_tag = bnapi->last_status_idx;
364adfc5217SJeff Kirsher 		bnapi->cnic_present = 1;
365adfc5217SJeff Kirsher 		sb_id = 0;
366adfc5217SJeff Kirsher 		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
367adfc5217SJeff Kirsher 	}
368adfc5217SJeff Kirsher 
369adfc5217SJeff Kirsher 	cp->irq_arr[0].vector = bp->irq_tbl[sb_id].vector;
370adfc5217SJeff Kirsher 	cp->irq_arr[0].status_blk = (void *)
371adfc5217SJeff Kirsher 		((unsigned long) bnapi->status_blk.msi +
372adfc5217SJeff Kirsher 		(BNX2_SBLK_MSIX_ALIGN_SIZE * sb_id));
373adfc5217SJeff Kirsher 	cp->irq_arr[0].status_blk_num = sb_id;
374adfc5217SJeff Kirsher 	cp->num_irq = 1;
375adfc5217SJeff Kirsher }
376adfc5217SJeff Kirsher 
377adfc5217SJeff Kirsher static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
378adfc5217SJeff Kirsher 			      void *data)
379adfc5217SJeff Kirsher {
380adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
381adfc5217SJeff Kirsher 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
382adfc5217SJeff Kirsher 
383adfc5217SJeff Kirsher 	if (ops == NULL)
384adfc5217SJeff Kirsher 		return -EINVAL;
385adfc5217SJeff Kirsher 
386adfc5217SJeff Kirsher 	if (cp->drv_state & CNIC_DRV_STATE_REGD)
387adfc5217SJeff Kirsher 		return -EBUSY;
388adfc5217SJeff Kirsher 
389adfc5217SJeff Kirsher 	if (!bnx2_reg_rd_ind(bp, BNX2_FW_MAX_ISCSI_CONN))
390adfc5217SJeff Kirsher 		return -ENODEV;
391adfc5217SJeff Kirsher 
392adfc5217SJeff Kirsher 	bp->cnic_data = data;
393adfc5217SJeff Kirsher 	rcu_assign_pointer(bp->cnic_ops, ops);
394adfc5217SJeff Kirsher 
395adfc5217SJeff Kirsher 	cp->num_irq = 0;
396adfc5217SJeff Kirsher 	cp->drv_state = CNIC_DRV_STATE_REGD;
397adfc5217SJeff Kirsher 
398adfc5217SJeff Kirsher 	bnx2_setup_cnic_irq_info(bp);
399adfc5217SJeff Kirsher 
400adfc5217SJeff Kirsher 	return 0;
401adfc5217SJeff Kirsher }
402adfc5217SJeff Kirsher 
403adfc5217SJeff Kirsher static int bnx2_unregister_cnic(struct net_device *dev)
404adfc5217SJeff Kirsher {
405adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
406adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
407adfc5217SJeff Kirsher 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
408adfc5217SJeff Kirsher 
409adfc5217SJeff Kirsher 	mutex_lock(&bp->cnic_lock);
410adfc5217SJeff Kirsher 	cp->drv_state = 0;
411adfc5217SJeff Kirsher 	bnapi->cnic_present = 0;
412adfc5217SJeff Kirsher 	rcu_assign_pointer(bp->cnic_ops, NULL);
413adfc5217SJeff Kirsher 	mutex_unlock(&bp->cnic_lock);
414adfc5217SJeff Kirsher 	synchronize_rcu();
415adfc5217SJeff Kirsher 	return 0;
416adfc5217SJeff Kirsher }
417adfc5217SJeff Kirsher 
418adfc5217SJeff Kirsher struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
419adfc5217SJeff Kirsher {
420adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
421adfc5217SJeff Kirsher 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
422adfc5217SJeff Kirsher 
423adfc5217SJeff Kirsher 	if (!cp->max_iscsi_conn)
424adfc5217SJeff Kirsher 		return NULL;
425adfc5217SJeff Kirsher 
426adfc5217SJeff Kirsher 	cp->drv_owner = THIS_MODULE;
427adfc5217SJeff Kirsher 	cp->chip_id = bp->chip_id;
428adfc5217SJeff Kirsher 	cp->pdev = bp->pdev;
429adfc5217SJeff Kirsher 	cp->io_base = bp->regview;
430adfc5217SJeff Kirsher 	cp->drv_ctl = bnx2_drv_ctl;
431adfc5217SJeff Kirsher 	cp->drv_register_cnic = bnx2_register_cnic;
432adfc5217SJeff Kirsher 	cp->drv_unregister_cnic = bnx2_unregister_cnic;
433adfc5217SJeff Kirsher 
434adfc5217SJeff Kirsher 	return cp;
435adfc5217SJeff Kirsher }
436adfc5217SJeff Kirsher EXPORT_SYMBOL(bnx2_cnic_probe);
437adfc5217SJeff Kirsher 
438adfc5217SJeff Kirsher static void
439adfc5217SJeff Kirsher bnx2_cnic_stop(struct bnx2 *bp)
440adfc5217SJeff Kirsher {
441adfc5217SJeff Kirsher 	struct cnic_ops *c_ops;
442adfc5217SJeff Kirsher 	struct cnic_ctl_info info;
443adfc5217SJeff Kirsher 
444adfc5217SJeff Kirsher 	mutex_lock(&bp->cnic_lock);
445adfc5217SJeff Kirsher 	c_ops = rcu_dereference_protected(bp->cnic_ops,
446adfc5217SJeff Kirsher 					  lockdep_is_held(&bp->cnic_lock));
447adfc5217SJeff Kirsher 	if (c_ops) {
448adfc5217SJeff Kirsher 		info.cmd = CNIC_CTL_STOP_CMD;
449adfc5217SJeff Kirsher 		c_ops->cnic_ctl(bp->cnic_data, &info);
450adfc5217SJeff Kirsher 	}
451adfc5217SJeff Kirsher 	mutex_unlock(&bp->cnic_lock);
452adfc5217SJeff Kirsher }
453adfc5217SJeff Kirsher 
454adfc5217SJeff Kirsher static void
455adfc5217SJeff Kirsher bnx2_cnic_start(struct bnx2 *bp)
456adfc5217SJeff Kirsher {
457adfc5217SJeff Kirsher 	struct cnic_ops *c_ops;
458adfc5217SJeff Kirsher 	struct cnic_ctl_info info;
459adfc5217SJeff Kirsher 
460adfc5217SJeff Kirsher 	mutex_lock(&bp->cnic_lock);
461adfc5217SJeff Kirsher 	c_ops = rcu_dereference_protected(bp->cnic_ops,
462adfc5217SJeff Kirsher 					  lockdep_is_held(&bp->cnic_lock));
463adfc5217SJeff Kirsher 	if (c_ops) {
464adfc5217SJeff Kirsher 		if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
465adfc5217SJeff Kirsher 			struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
466adfc5217SJeff Kirsher 
467adfc5217SJeff Kirsher 			bnapi->cnic_tag = bnapi->last_status_idx;
468adfc5217SJeff Kirsher 		}
469adfc5217SJeff Kirsher 		info.cmd = CNIC_CTL_START_CMD;
470adfc5217SJeff Kirsher 		c_ops->cnic_ctl(bp->cnic_data, &info);
471adfc5217SJeff Kirsher 	}
472adfc5217SJeff Kirsher 	mutex_unlock(&bp->cnic_lock);
473adfc5217SJeff Kirsher }
474adfc5217SJeff Kirsher 
475adfc5217SJeff Kirsher #else
476adfc5217SJeff Kirsher 
477adfc5217SJeff Kirsher static void
478adfc5217SJeff Kirsher bnx2_cnic_stop(struct bnx2 *bp)
479adfc5217SJeff Kirsher {
480adfc5217SJeff Kirsher }
481adfc5217SJeff Kirsher 
482adfc5217SJeff Kirsher static void
483adfc5217SJeff Kirsher bnx2_cnic_start(struct bnx2 *bp)
484adfc5217SJeff Kirsher {
485adfc5217SJeff Kirsher }
486adfc5217SJeff Kirsher 
487adfc5217SJeff Kirsher #endif
488adfc5217SJeff Kirsher 
489adfc5217SJeff Kirsher static int
490adfc5217SJeff Kirsher bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
491adfc5217SJeff Kirsher {
492adfc5217SJeff Kirsher 	u32 val1;
493adfc5217SJeff Kirsher 	int i, ret;
494adfc5217SJeff Kirsher 
495adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
496adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
497adfc5217SJeff Kirsher 		val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
498adfc5217SJeff Kirsher 
499adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
500adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
501adfc5217SJeff Kirsher 
502adfc5217SJeff Kirsher 		udelay(40);
503adfc5217SJeff Kirsher 	}
504adfc5217SJeff Kirsher 
505adfc5217SJeff Kirsher 	val1 = (bp->phy_addr << 21) | (reg << 16) |
506adfc5217SJeff Kirsher 		BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
507adfc5217SJeff Kirsher 		BNX2_EMAC_MDIO_COMM_START_BUSY;
508adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
509adfc5217SJeff Kirsher 
510adfc5217SJeff Kirsher 	for (i = 0; i < 50; i++) {
511adfc5217SJeff Kirsher 		udelay(10);
512adfc5217SJeff Kirsher 
513adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
514adfc5217SJeff Kirsher 		if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
515adfc5217SJeff Kirsher 			udelay(5);
516adfc5217SJeff Kirsher 
517adfc5217SJeff Kirsher 			val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
518adfc5217SJeff Kirsher 			val1 &= BNX2_EMAC_MDIO_COMM_DATA;
519adfc5217SJeff Kirsher 
520adfc5217SJeff Kirsher 			break;
521adfc5217SJeff Kirsher 		}
522adfc5217SJeff Kirsher 	}
523adfc5217SJeff Kirsher 
524adfc5217SJeff Kirsher 	if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
525adfc5217SJeff Kirsher 		*val = 0x0;
526adfc5217SJeff Kirsher 		ret = -EBUSY;
527adfc5217SJeff Kirsher 	}
528adfc5217SJeff Kirsher 	else {
529adfc5217SJeff Kirsher 		*val = val1;
530adfc5217SJeff Kirsher 		ret = 0;
531adfc5217SJeff Kirsher 	}
532adfc5217SJeff Kirsher 
533adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
534adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
535adfc5217SJeff Kirsher 		val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
536adfc5217SJeff Kirsher 
537adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
538adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
539adfc5217SJeff Kirsher 
540adfc5217SJeff Kirsher 		udelay(40);
541adfc5217SJeff Kirsher 	}
542adfc5217SJeff Kirsher 
543adfc5217SJeff Kirsher 	return ret;
544adfc5217SJeff Kirsher }
545adfc5217SJeff Kirsher 
546adfc5217SJeff Kirsher static int
547adfc5217SJeff Kirsher bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
548adfc5217SJeff Kirsher {
549adfc5217SJeff Kirsher 	u32 val1;
550adfc5217SJeff Kirsher 	int i, ret;
551adfc5217SJeff Kirsher 
552adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
553adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
554adfc5217SJeff Kirsher 		val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
555adfc5217SJeff Kirsher 
556adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
557adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
558adfc5217SJeff Kirsher 
559adfc5217SJeff Kirsher 		udelay(40);
560adfc5217SJeff Kirsher 	}
561adfc5217SJeff Kirsher 
562adfc5217SJeff Kirsher 	val1 = (bp->phy_addr << 21) | (reg << 16) | val |
563adfc5217SJeff Kirsher 		BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
564adfc5217SJeff Kirsher 		BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
565adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
566adfc5217SJeff Kirsher 
567adfc5217SJeff Kirsher 	for (i = 0; i < 50; i++) {
568adfc5217SJeff Kirsher 		udelay(10);
569adfc5217SJeff Kirsher 
570adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
571adfc5217SJeff Kirsher 		if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
572adfc5217SJeff Kirsher 			udelay(5);
573adfc5217SJeff Kirsher 			break;
574adfc5217SJeff Kirsher 		}
575adfc5217SJeff Kirsher 	}
576adfc5217SJeff Kirsher 
577adfc5217SJeff Kirsher 	if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
578adfc5217SJeff Kirsher         	ret = -EBUSY;
579adfc5217SJeff Kirsher 	else
580adfc5217SJeff Kirsher 		ret = 0;
581adfc5217SJeff Kirsher 
582adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
583adfc5217SJeff Kirsher 		val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
584adfc5217SJeff Kirsher 		val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
585adfc5217SJeff Kirsher 
586adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
587adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_EMAC_MDIO_MODE);
588adfc5217SJeff Kirsher 
589adfc5217SJeff Kirsher 		udelay(40);
590adfc5217SJeff Kirsher 	}
591adfc5217SJeff Kirsher 
592adfc5217SJeff Kirsher 	return ret;
593adfc5217SJeff Kirsher }
594adfc5217SJeff Kirsher 
595adfc5217SJeff Kirsher static void
596adfc5217SJeff Kirsher bnx2_disable_int(struct bnx2 *bp)
597adfc5217SJeff Kirsher {
598adfc5217SJeff Kirsher 	int i;
599adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
600adfc5217SJeff Kirsher 
601adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
602adfc5217SJeff Kirsher 		bnapi = &bp->bnx2_napi[i];
603adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
604adfc5217SJeff Kirsher 		       BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
605adfc5217SJeff Kirsher 	}
606adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
607adfc5217SJeff Kirsher }
608adfc5217SJeff Kirsher 
609adfc5217SJeff Kirsher static void
610adfc5217SJeff Kirsher bnx2_enable_int(struct bnx2 *bp)
611adfc5217SJeff Kirsher {
612adfc5217SJeff Kirsher 	int i;
613adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
614adfc5217SJeff Kirsher 
615adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
616adfc5217SJeff Kirsher 		bnapi = &bp->bnx2_napi[i];
617adfc5217SJeff Kirsher 
618adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
619adfc5217SJeff Kirsher 		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
620adfc5217SJeff Kirsher 		       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
621adfc5217SJeff Kirsher 		       bnapi->last_status_idx);
622adfc5217SJeff Kirsher 
623adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
624adfc5217SJeff Kirsher 		       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
625adfc5217SJeff Kirsher 		       bnapi->last_status_idx);
626adfc5217SJeff Kirsher 	}
627adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
628adfc5217SJeff Kirsher }
629adfc5217SJeff Kirsher 
630adfc5217SJeff Kirsher static void
631adfc5217SJeff Kirsher bnx2_disable_int_sync(struct bnx2 *bp)
632adfc5217SJeff Kirsher {
633adfc5217SJeff Kirsher 	int i;
634adfc5217SJeff Kirsher 
635adfc5217SJeff Kirsher 	atomic_inc(&bp->intr_sem);
636adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
637adfc5217SJeff Kirsher 		return;
638adfc5217SJeff Kirsher 
639adfc5217SJeff Kirsher 	bnx2_disable_int(bp);
640adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++)
641adfc5217SJeff Kirsher 		synchronize_irq(bp->irq_tbl[i].vector);
642adfc5217SJeff Kirsher }
643adfc5217SJeff Kirsher 
644adfc5217SJeff Kirsher static void
645adfc5217SJeff Kirsher bnx2_napi_disable(struct bnx2 *bp)
646adfc5217SJeff Kirsher {
647adfc5217SJeff Kirsher 	int i;
648adfc5217SJeff Kirsher 
649adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++)
650adfc5217SJeff Kirsher 		napi_disable(&bp->bnx2_napi[i].napi);
651adfc5217SJeff Kirsher }
652adfc5217SJeff Kirsher 
653adfc5217SJeff Kirsher static void
654adfc5217SJeff Kirsher bnx2_napi_enable(struct bnx2 *bp)
655adfc5217SJeff Kirsher {
656adfc5217SJeff Kirsher 	int i;
657adfc5217SJeff Kirsher 
658adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++)
659adfc5217SJeff Kirsher 		napi_enable(&bp->bnx2_napi[i].napi);
660adfc5217SJeff Kirsher }
661adfc5217SJeff Kirsher 
662adfc5217SJeff Kirsher static void
663adfc5217SJeff Kirsher bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic)
664adfc5217SJeff Kirsher {
665adfc5217SJeff Kirsher 	if (stop_cnic)
666adfc5217SJeff Kirsher 		bnx2_cnic_stop(bp);
667adfc5217SJeff Kirsher 	if (netif_running(bp->dev)) {
668adfc5217SJeff Kirsher 		bnx2_napi_disable(bp);
669adfc5217SJeff Kirsher 		netif_tx_disable(bp->dev);
670adfc5217SJeff Kirsher 	}
671adfc5217SJeff Kirsher 	bnx2_disable_int_sync(bp);
672adfc5217SJeff Kirsher 	netif_carrier_off(bp->dev);	/* prevent tx timeout */
673adfc5217SJeff Kirsher }
674adfc5217SJeff Kirsher 
675adfc5217SJeff Kirsher static void
676adfc5217SJeff Kirsher bnx2_netif_start(struct bnx2 *bp, bool start_cnic)
677adfc5217SJeff Kirsher {
678adfc5217SJeff Kirsher 	if (atomic_dec_and_test(&bp->intr_sem)) {
679adfc5217SJeff Kirsher 		if (netif_running(bp->dev)) {
680adfc5217SJeff Kirsher 			netif_tx_wake_all_queues(bp->dev);
681adfc5217SJeff Kirsher 			spin_lock_bh(&bp->phy_lock);
682adfc5217SJeff Kirsher 			if (bp->link_up)
683adfc5217SJeff Kirsher 				netif_carrier_on(bp->dev);
684adfc5217SJeff Kirsher 			spin_unlock_bh(&bp->phy_lock);
685adfc5217SJeff Kirsher 			bnx2_napi_enable(bp);
686adfc5217SJeff Kirsher 			bnx2_enable_int(bp);
687adfc5217SJeff Kirsher 			if (start_cnic)
688adfc5217SJeff Kirsher 				bnx2_cnic_start(bp);
689adfc5217SJeff Kirsher 		}
690adfc5217SJeff Kirsher 	}
691adfc5217SJeff Kirsher }
692adfc5217SJeff Kirsher 
693adfc5217SJeff Kirsher static void
694adfc5217SJeff Kirsher bnx2_free_tx_mem(struct bnx2 *bp)
695adfc5217SJeff Kirsher {
696adfc5217SJeff Kirsher 	int i;
697adfc5217SJeff Kirsher 
698adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_tx_rings; i++) {
699adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
700adfc5217SJeff Kirsher 		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
701adfc5217SJeff Kirsher 
702adfc5217SJeff Kirsher 		if (txr->tx_desc_ring) {
703adfc5217SJeff Kirsher 			dma_free_coherent(&bp->pdev->dev, TXBD_RING_SIZE,
704adfc5217SJeff Kirsher 					  txr->tx_desc_ring,
705adfc5217SJeff Kirsher 					  txr->tx_desc_mapping);
706adfc5217SJeff Kirsher 			txr->tx_desc_ring = NULL;
707adfc5217SJeff Kirsher 		}
708adfc5217SJeff Kirsher 		kfree(txr->tx_buf_ring);
709adfc5217SJeff Kirsher 		txr->tx_buf_ring = NULL;
710adfc5217SJeff Kirsher 	}
711adfc5217SJeff Kirsher }
712adfc5217SJeff Kirsher 
713adfc5217SJeff Kirsher static void
714adfc5217SJeff Kirsher bnx2_free_rx_mem(struct bnx2 *bp)
715adfc5217SJeff Kirsher {
716adfc5217SJeff Kirsher 	int i;
717adfc5217SJeff Kirsher 
718adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_rx_rings; i++) {
719adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
720adfc5217SJeff Kirsher 		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
721adfc5217SJeff Kirsher 		int j;
722adfc5217SJeff Kirsher 
723adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_ring; j++) {
724adfc5217SJeff Kirsher 			if (rxr->rx_desc_ring[j])
725adfc5217SJeff Kirsher 				dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE,
726adfc5217SJeff Kirsher 						  rxr->rx_desc_ring[j],
727adfc5217SJeff Kirsher 						  rxr->rx_desc_mapping[j]);
728adfc5217SJeff Kirsher 			rxr->rx_desc_ring[j] = NULL;
729adfc5217SJeff Kirsher 		}
730adfc5217SJeff Kirsher 		vfree(rxr->rx_buf_ring);
731adfc5217SJeff Kirsher 		rxr->rx_buf_ring = NULL;
732adfc5217SJeff Kirsher 
733adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_pg_ring; j++) {
734adfc5217SJeff Kirsher 			if (rxr->rx_pg_desc_ring[j])
735adfc5217SJeff Kirsher 				dma_free_coherent(&bp->pdev->dev, RXBD_RING_SIZE,
736adfc5217SJeff Kirsher 						  rxr->rx_pg_desc_ring[j],
737adfc5217SJeff Kirsher 						  rxr->rx_pg_desc_mapping[j]);
738adfc5217SJeff Kirsher 			rxr->rx_pg_desc_ring[j] = NULL;
739adfc5217SJeff Kirsher 		}
740adfc5217SJeff Kirsher 		vfree(rxr->rx_pg_ring);
741adfc5217SJeff Kirsher 		rxr->rx_pg_ring = NULL;
742adfc5217SJeff Kirsher 	}
743adfc5217SJeff Kirsher }
744adfc5217SJeff Kirsher 
745adfc5217SJeff Kirsher static int
746adfc5217SJeff Kirsher bnx2_alloc_tx_mem(struct bnx2 *bp)
747adfc5217SJeff Kirsher {
748adfc5217SJeff Kirsher 	int i;
749adfc5217SJeff Kirsher 
750adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_tx_rings; i++) {
751adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
752adfc5217SJeff Kirsher 		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
753adfc5217SJeff Kirsher 
754adfc5217SJeff Kirsher 		txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
755adfc5217SJeff Kirsher 		if (txr->tx_buf_ring == NULL)
756adfc5217SJeff Kirsher 			return -ENOMEM;
757adfc5217SJeff Kirsher 
758adfc5217SJeff Kirsher 		txr->tx_desc_ring =
759adfc5217SJeff Kirsher 			dma_alloc_coherent(&bp->pdev->dev, TXBD_RING_SIZE,
760adfc5217SJeff Kirsher 					   &txr->tx_desc_mapping, GFP_KERNEL);
761adfc5217SJeff Kirsher 		if (txr->tx_desc_ring == NULL)
762adfc5217SJeff Kirsher 			return -ENOMEM;
763adfc5217SJeff Kirsher 	}
764adfc5217SJeff Kirsher 	return 0;
765adfc5217SJeff Kirsher }
766adfc5217SJeff Kirsher 
767adfc5217SJeff Kirsher static int
768adfc5217SJeff Kirsher bnx2_alloc_rx_mem(struct bnx2 *bp)
769adfc5217SJeff Kirsher {
770adfc5217SJeff Kirsher 	int i;
771adfc5217SJeff Kirsher 
772adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_rx_rings; i++) {
773adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
774adfc5217SJeff Kirsher 		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
775adfc5217SJeff Kirsher 		int j;
776adfc5217SJeff Kirsher 
777adfc5217SJeff Kirsher 		rxr->rx_buf_ring =
778adfc5217SJeff Kirsher 			vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
779adfc5217SJeff Kirsher 		if (rxr->rx_buf_ring == NULL)
780adfc5217SJeff Kirsher 			return -ENOMEM;
781adfc5217SJeff Kirsher 
782adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_ring; j++) {
783adfc5217SJeff Kirsher 			rxr->rx_desc_ring[j] =
784adfc5217SJeff Kirsher 				dma_alloc_coherent(&bp->pdev->dev,
785adfc5217SJeff Kirsher 						   RXBD_RING_SIZE,
786adfc5217SJeff Kirsher 						   &rxr->rx_desc_mapping[j],
787adfc5217SJeff Kirsher 						   GFP_KERNEL);
788adfc5217SJeff Kirsher 			if (rxr->rx_desc_ring[j] == NULL)
789adfc5217SJeff Kirsher 				return -ENOMEM;
790adfc5217SJeff Kirsher 
791adfc5217SJeff Kirsher 		}
792adfc5217SJeff Kirsher 
793adfc5217SJeff Kirsher 		if (bp->rx_pg_ring_size) {
794adfc5217SJeff Kirsher 			rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
795adfc5217SJeff Kirsher 						  bp->rx_max_pg_ring);
796adfc5217SJeff Kirsher 			if (rxr->rx_pg_ring == NULL)
797adfc5217SJeff Kirsher 				return -ENOMEM;
798adfc5217SJeff Kirsher 
799adfc5217SJeff Kirsher 		}
800adfc5217SJeff Kirsher 
801adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_pg_ring; j++) {
802adfc5217SJeff Kirsher 			rxr->rx_pg_desc_ring[j] =
803adfc5217SJeff Kirsher 				dma_alloc_coherent(&bp->pdev->dev,
804adfc5217SJeff Kirsher 						   RXBD_RING_SIZE,
805adfc5217SJeff Kirsher 						   &rxr->rx_pg_desc_mapping[j],
806adfc5217SJeff Kirsher 						   GFP_KERNEL);
807adfc5217SJeff Kirsher 			if (rxr->rx_pg_desc_ring[j] == NULL)
808adfc5217SJeff Kirsher 				return -ENOMEM;
809adfc5217SJeff Kirsher 
810adfc5217SJeff Kirsher 		}
811adfc5217SJeff Kirsher 	}
812adfc5217SJeff Kirsher 	return 0;
813adfc5217SJeff Kirsher }
814adfc5217SJeff Kirsher 
815adfc5217SJeff Kirsher static void
816adfc5217SJeff Kirsher bnx2_free_mem(struct bnx2 *bp)
817adfc5217SJeff Kirsher {
818adfc5217SJeff Kirsher 	int i;
819adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
820adfc5217SJeff Kirsher 
821adfc5217SJeff Kirsher 	bnx2_free_tx_mem(bp);
822adfc5217SJeff Kirsher 	bnx2_free_rx_mem(bp);
823adfc5217SJeff Kirsher 
824adfc5217SJeff Kirsher 	for (i = 0; i < bp->ctx_pages; i++) {
825adfc5217SJeff Kirsher 		if (bp->ctx_blk[i]) {
826adfc5217SJeff Kirsher 			dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE,
827adfc5217SJeff Kirsher 					  bp->ctx_blk[i],
828adfc5217SJeff Kirsher 					  bp->ctx_blk_mapping[i]);
829adfc5217SJeff Kirsher 			bp->ctx_blk[i] = NULL;
830adfc5217SJeff Kirsher 		}
831adfc5217SJeff Kirsher 	}
832adfc5217SJeff Kirsher 	if (bnapi->status_blk.msi) {
833adfc5217SJeff Kirsher 		dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
834adfc5217SJeff Kirsher 				  bnapi->status_blk.msi,
835adfc5217SJeff Kirsher 				  bp->status_blk_mapping);
836adfc5217SJeff Kirsher 		bnapi->status_blk.msi = NULL;
837adfc5217SJeff Kirsher 		bp->stats_blk = NULL;
838adfc5217SJeff Kirsher 	}
839adfc5217SJeff Kirsher }
840adfc5217SJeff Kirsher 
841adfc5217SJeff Kirsher static int
842adfc5217SJeff Kirsher bnx2_alloc_mem(struct bnx2 *bp)
843adfc5217SJeff Kirsher {
844adfc5217SJeff Kirsher 	int i, status_blk_size, err;
845adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
846adfc5217SJeff Kirsher 	void *status_blk;
847adfc5217SJeff Kirsher 
848adfc5217SJeff Kirsher 	/* Combine status and statistics blocks into one allocation. */
849adfc5217SJeff Kirsher 	status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
850adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_MSIX_CAP)
851adfc5217SJeff Kirsher 		status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
852adfc5217SJeff Kirsher 						 BNX2_SBLK_MSIX_ALIGN_SIZE);
853adfc5217SJeff Kirsher 	bp->status_stats_size = status_blk_size +
854adfc5217SJeff Kirsher 				sizeof(struct statistics_block);
855adfc5217SJeff Kirsher 
856adfc5217SJeff Kirsher 	status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
857adfc5217SJeff Kirsher 					&bp->status_blk_mapping, GFP_KERNEL);
858adfc5217SJeff Kirsher 	if (status_blk == NULL)
859adfc5217SJeff Kirsher 		goto alloc_mem_err;
860adfc5217SJeff Kirsher 
861adfc5217SJeff Kirsher 	memset(status_blk, 0, bp->status_stats_size);
862adfc5217SJeff Kirsher 
863adfc5217SJeff Kirsher 	bnapi = &bp->bnx2_napi[0];
864adfc5217SJeff Kirsher 	bnapi->status_blk.msi = status_blk;
865adfc5217SJeff Kirsher 	bnapi->hw_tx_cons_ptr =
866adfc5217SJeff Kirsher 		&bnapi->status_blk.msi->status_tx_quick_consumer_index0;
867adfc5217SJeff Kirsher 	bnapi->hw_rx_cons_ptr =
868adfc5217SJeff Kirsher 		&bnapi->status_blk.msi->status_rx_quick_consumer_index0;
869adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_MSIX_CAP) {
870adfc5217SJeff Kirsher 		for (i = 1; i < bp->irq_nvecs; i++) {
871adfc5217SJeff Kirsher 			struct status_block_msix *sblk;
872adfc5217SJeff Kirsher 
873adfc5217SJeff Kirsher 			bnapi = &bp->bnx2_napi[i];
874adfc5217SJeff Kirsher 
875adfc5217SJeff Kirsher 			sblk = (void *) (status_blk +
876adfc5217SJeff Kirsher 					 BNX2_SBLK_MSIX_ALIGN_SIZE * i);
877adfc5217SJeff Kirsher 			bnapi->status_blk.msix = sblk;
878adfc5217SJeff Kirsher 			bnapi->hw_tx_cons_ptr =
879adfc5217SJeff Kirsher 				&sblk->status_tx_quick_consumer_index;
880adfc5217SJeff Kirsher 			bnapi->hw_rx_cons_ptr =
881adfc5217SJeff Kirsher 				&sblk->status_rx_quick_consumer_index;
882adfc5217SJeff Kirsher 			bnapi->int_num = i << 24;
883adfc5217SJeff Kirsher 		}
884adfc5217SJeff Kirsher 	}
885adfc5217SJeff Kirsher 
886adfc5217SJeff Kirsher 	bp->stats_blk = status_blk + status_blk_size;
887adfc5217SJeff Kirsher 
888adfc5217SJeff Kirsher 	bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
889adfc5217SJeff Kirsher 
890adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
891adfc5217SJeff Kirsher 		bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
892adfc5217SJeff Kirsher 		if (bp->ctx_pages == 0)
893adfc5217SJeff Kirsher 			bp->ctx_pages = 1;
894adfc5217SJeff Kirsher 		for (i = 0; i < bp->ctx_pages; i++) {
895adfc5217SJeff Kirsher 			bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev,
896adfc5217SJeff Kirsher 						BCM_PAGE_SIZE,
897adfc5217SJeff Kirsher 						&bp->ctx_blk_mapping[i],
898adfc5217SJeff Kirsher 						GFP_KERNEL);
899adfc5217SJeff Kirsher 			if (bp->ctx_blk[i] == NULL)
900adfc5217SJeff Kirsher 				goto alloc_mem_err;
901adfc5217SJeff Kirsher 		}
902adfc5217SJeff Kirsher 	}
903adfc5217SJeff Kirsher 
904adfc5217SJeff Kirsher 	err = bnx2_alloc_rx_mem(bp);
905adfc5217SJeff Kirsher 	if (err)
906adfc5217SJeff Kirsher 		goto alloc_mem_err;
907adfc5217SJeff Kirsher 
908adfc5217SJeff Kirsher 	err = bnx2_alloc_tx_mem(bp);
909adfc5217SJeff Kirsher 	if (err)
910adfc5217SJeff Kirsher 		goto alloc_mem_err;
911adfc5217SJeff Kirsher 
912adfc5217SJeff Kirsher 	return 0;
913adfc5217SJeff Kirsher 
914adfc5217SJeff Kirsher alloc_mem_err:
915adfc5217SJeff Kirsher 	bnx2_free_mem(bp);
916adfc5217SJeff Kirsher 	return -ENOMEM;
917adfc5217SJeff Kirsher }
918adfc5217SJeff Kirsher 
919adfc5217SJeff Kirsher static void
920adfc5217SJeff Kirsher bnx2_report_fw_link(struct bnx2 *bp)
921adfc5217SJeff Kirsher {
922adfc5217SJeff Kirsher 	u32 fw_link_status = 0;
923adfc5217SJeff Kirsher 
924adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
925adfc5217SJeff Kirsher 		return;
926adfc5217SJeff Kirsher 
927adfc5217SJeff Kirsher 	if (bp->link_up) {
928adfc5217SJeff Kirsher 		u32 bmsr;
929adfc5217SJeff Kirsher 
930adfc5217SJeff Kirsher 		switch (bp->line_speed) {
931adfc5217SJeff Kirsher 		case SPEED_10:
932adfc5217SJeff Kirsher 			if (bp->duplex == DUPLEX_HALF)
933adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_10HALF;
934adfc5217SJeff Kirsher 			else
935adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_10FULL;
936adfc5217SJeff Kirsher 			break;
937adfc5217SJeff Kirsher 		case SPEED_100:
938adfc5217SJeff Kirsher 			if (bp->duplex == DUPLEX_HALF)
939adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_100HALF;
940adfc5217SJeff Kirsher 			else
941adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_100FULL;
942adfc5217SJeff Kirsher 			break;
943adfc5217SJeff Kirsher 		case SPEED_1000:
944adfc5217SJeff Kirsher 			if (bp->duplex == DUPLEX_HALF)
945adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_1000HALF;
946adfc5217SJeff Kirsher 			else
947adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_1000FULL;
948adfc5217SJeff Kirsher 			break;
949adfc5217SJeff Kirsher 		case SPEED_2500:
950adfc5217SJeff Kirsher 			if (bp->duplex == DUPLEX_HALF)
951adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_2500HALF;
952adfc5217SJeff Kirsher 			else
953adfc5217SJeff Kirsher 				fw_link_status = BNX2_LINK_STATUS_2500FULL;
954adfc5217SJeff Kirsher 			break;
955adfc5217SJeff Kirsher 		}
956adfc5217SJeff Kirsher 
957adfc5217SJeff Kirsher 		fw_link_status |= BNX2_LINK_STATUS_LINK_UP;
958adfc5217SJeff Kirsher 
959adfc5217SJeff Kirsher 		if (bp->autoneg) {
960adfc5217SJeff Kirsher 			fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
961adfc5217SJeff Kirsher 
962adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
963adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
964adfc5217SJeff Kirsher 
965adfc5217SJeff Kirsher 			if (!(bmsr & BMSR_ANEGCOMPLETE) ||
966adfc5217SJeff Kirsher 			    bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)
967adfc5217SJeff Kirsher 				fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET;
968adfc5217SJeff Kirsher 			else
969adfc5217SJeff Kirsher 				fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE;
970adfc5217SJeff Kirsher 		}
971adfc5217SJeff Kirsher 	}
972adfc5217SJeff Kirsher 	else
973adfc5217SJeff Kirsher 		fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
974adfc5217SJeff Kirsher 
975adfc5217SJeff Kirsher 	bnx2_shmem_wr(bp, BNX2_LINK_STATUS, fw_link_status);
976adfc5217SJeff Kirsher }
977adfc5217SJeff Kirsher 
978adfc5217SJeff Kirsher static char *
979adfc5217SJeff Kirsher bnx2_xceiver_str(struct bnx2 *bp)
980adfc5217SJeff Kirsher {
981adfc5217SJeff Kirsher 	return (bp->phy_port == PORT_FIBRE) ? "SerDes" :
982adfc5217SJeff Kirsher 		((bp->phy_flags & BNX2_PHY_FLAG_SERDES) ? "Remote Copper" :
983adfc5217SJeff Kirsher 		 "Copper");
984adfc5217SJeff Kirsher }
985adfc5217SJeff Kirsher 
986adfc5217SJeff Kirsher static void
987adfc5217SJeff Kirsher bnx2_report_link(struct bnx2 *bp)
988adfc5217SJeff Kirsher {
989adfc5217SJeff Kirsher 	if (bp->link_up) {
990adfc5217SJeff Kirsher 		netif_carrier_on(bp->dev);
991adfc5217SJeff Kirsher 		netdev_info(bp->dev, "NIC %s Link is Up, %d Mbps %s duplex",
992adfc5217SJeff Kirsher 			    bnx2_xceiver_str(bp),
993adfc5217SJeff Kirsher 			    bp->line_speed,
994adfc5217SJeff Kirsher 			    bp->duplex == DUPLEX_FULL ? "full" : "half");
995adfc5217SJeff Kirsher 
996adfc5217SJeff Kirsher 		if (bp->flow_ctrl) {
997adfc5217SJeff Kirsher 			if (bp->flow_ctrl & FLOW_CTRL_RX) {
998adfc5217SJeff Kirsher 				pr_cont(", receive ");
999adfc5217SJeff Kirsher 				if (bp->flow_ctrl & FLOW_CTRL_TX)
1000adfc5217SJeff Kirsher 					pr_cont("& transmit ");
1001adfc5217SJeff Kirsher 			}
1002adfc5217SJeff Kirsher 			else {
1003adfc5217SJeff Kirsher 				pr_cont(", transmit ");
1004adfc5217SJeff Kirsher 			}
1005adfc5217SJeff Kirsher 			pr_cont("flow control ON");
1006adfc5217SJeff Kirsher 		}
1007adfc5217SJeff Kirsher 		pr_cont("\n");
1008adfc5217SJeff Kirsher 	} else {
1009adfc5217SJeff Kirsher 		netif_carrier_off(bp->dev);
1010adfc5217SJeff Kirsher 		netdev_err(bp->dev, "NIC %s Link is Down\n",
1011adfc5217SJeff Kirsher 			   bnx2_xceiver_str(bp));
1012adfc5217SJeff Kirsher 	}
1013adfc5217SJeff Kirsher 
1014adfc5217SJeff Kirsher 	bnx2_report_fw_link(bp);
1015adfc5217SJeff Kirsher }
1016adfc5217SJeff Kirsher 
1017adfc5217SJeff Kirsher static void
1018adfc5217SJeff Kirsher bnx2_resolve_flow_ctrl(struct bnx2 *bp)
1019adfc5217SJeff Kirsher {
1020adfc5217SJeff Kirsher 	u32 local_adv, remote_adv;
1021adfc5217SJeff Kirsher 
1022adfc5217SJeff Kirsher 	bp->flow_ctrl = 0;
1023adfc5217SJeff Kirsher 	if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
1024adfc5217SJeff Kirsher 		(AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
1025adfc5217SJeff Kirsher 
1026adfc5217SJeff Kirsher 		if (bp->duplex == DUPLEX_FULL) {
1027adfc5217SJeff Kirsher 			bp->flow_ctrl = bp->req_flow_ctrl;
1028adfc5217SJeff Kirsher 		}
1029adfc5217SJeff Kirsher 		return;
1030adfc5217SJeff Kirsher 	}
1031adfc5217SJeff Kirsher 
1032adfc5217SJeff Kirsher 	if (bp->duplex != DUPLEX_FULL) {
1033adfc5217SJeff Kirsher 		return;
1034adfc5217SJeff Kirsher 	}
1035adfc5217SJeff Kirsher 
1036adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
1037adfc5217SJeff Kirsher 	    (CHIP_NUM(bp) == CHIP_NUM_5708)) {
1038adfc5217SJeff Kirsher 		u32 val;
1039adfc5217SJeff Kirsher 
1040adfc5217SJeff Kirsher 		bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
1041adfc5217SJeff Kirsher 		if (val & BCM5708S_1000X_STAT1_TX_PAUSE)
1042adfc5217SJeff Kirsher 			bp->flow_ctrl |= FLOW_CTRL_TX;
1043adfc5217SJeff Kirsher 		if (val & BCM5708S_1000X_STAT1_RX_PAUSE)
1044adfc5217SJeff Kirsher 			bp->flow_ctrl |= FLOW_CTRL_RX;
1045adfc5217SJeff Kirsher 		return;
1046adfc5217SJeff Kirsher 	}
1047adfc5217SJeff Kirsher 
1048adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
1049adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
1050adfc5217SJeff Kirsher 
1051adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1052adfc5217SJeff Kirsher 		u32 new_local_adv = 0;
1053adfc5217SJeff Kirsher 		u32 new_remote_adv = 0;
1054adfc5217SJeff Kirsher 
1055adfc5217SJeff Kirsher 		if (local_adv & ADVERTISE_1000XPAUSE)
1056adfc5217SJeff Kirsher 			new_local_adv |= ADVERTISE_PAUSE_CAP;
1057adfc5217SJeff Kirsher 		if (local_adv & ADVERTISE_1000XPSE_ASYM)
1058adfc5217SJeff Kirsher 			new_local_adv |= ADVERTISE_PAUSE_ASYM;
1059adfc5217SJeff Kirsher 		if (remote_adv & ADVERTISE_1000XPAUSE)
1060adfc5217SJeff Kirsher 			new_remote_adv |= ADVERTISE_PAUSE_CAP;
1061adfc5217SJeff Kirsher 		if (remote_adv & ADVERTISE_1000XPSE_ASYM)
1062adfc5217SJeff Kirsher 			new_remote_adv |= ADVERTISE_PAUSE_ASYM;
1063adfc5217SJeff Kirsher 
1064adfc5217SJeff Kirsher 		local_adv = new_local_adv;
1065adfc5217SJeff Kirsher 		remote_adv = new_remote_adv;
1066adfc5217SJeff Kirsher 	}
1067adfc5217SJeff Kirsher 
1068adfc5217SJeff Kirsher 	/* See Table 28B-3 of 802.3ab-1999 spec. */
1069adfc5217SJeff Kirsher 	if (local_adv & ADVERTISE_PAUSE_CAP) {
1070adfc5217SJeff Kirsher 		if(local_adv & ADVERTISE_PAUSE_ASYM) {
1071adfc5217SJeff Kirsher 	                if (remote_adv & ADVERTISE_PAUSE_CAP) {
1072adfc5217SJeff Kirsher 				bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
1073adfc5217SJeff Kirsher 			}
1074adfc5217SJeff Kirsher 			else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
1075adfc5217SJeff Kirsher 				bp->flow_ctrl = FLOW_CTRL_RX;
1076adfc5217SJeff Kirsher 			}
1077adfc5217SJeff Kirsher 		}
1078adfc5217SJeff Kirsher 		else {
1079adfc5217SJeff Kirsher 			if (remote_adv & ADVERTISE_PAUSE_CAP) {
1080adfc5217SJeff Kirsher 				bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
1081adfc5217SJeff Kirsher 			}
1082adfc5217SJeff Kirsher 		}
1083adfc5217SJeff Kirsher 	}
1084adfc5217SJeff Kirsher 	else if (local_adv & ADVERTISE_PAUSE_ASYM) {
1085adfc5217SJeff Kirsher 		if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
1086adfc5217SJeff Kirsher 			(remote_adv & ADVERTISE_PAUSE_ASYM)) {
1087adfc5217SJeff Kirsher 
1088adfc5217SJeff Kirsher 			bp->flow_ctrl = FLOW_CTRL_TX;
1089adfc5217SJeff Kirsher 		}
1090adfc5217SJeff Kirsher 	}
1091adfc5217SJeff Kirsher }
1092adfc5217SJeff Kirsher 
1093adfc5217SJeff Kirsher static int
1094adfc5217SJeff Kirsher bnx2_5709s_linkup(struct bnx2 *bp)
1095adfc5217SJeff Kirsher {
1096adfc5217SJeff Kirsher 	u32 val, speed;
1097adfc5217SJeff Kirsher 
1098adfc5217SJeff Kirsher 	bp->link_up = 1;
1099adfc5217SJeff Kirsher 
1100adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS);
1101adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val);
1102adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1103adfc5217SJeff Kirsher 
1104adfc5217SJeff Kirsher 	if ((bp->autoneg & AUTONEG_SPEED) == 0) {
1105adfc5217SJeff Kirsher 		bp->line_speed = bp->req_line_speed;
1106adfc5217SJeff Kirsher 		bp->duplex = bp->req_duplex;
1107adfc5217SJeff Kirsher 		return 0;
1108adfc5217SJeff Kirsher 	}
1109adfc5217SJeff Kirsher 	speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK;
1110adfc5217SJeff Kirsher 	switch (speed) {
1111adfc5217SJeff Kirsher 		case MII_BNX2_GP_TOP_AN_SPEED_10:
1112adfc5217SJeff Kirsher 			bp->line_speed = SPEED_10;
1113adfc5217SJeff Kirsher 			break;
1114adfc5217SJeff Kirsher 		case MII_BNX2_GP_TOP_AN_SPEED_100:
1115adfc5217SJeff Kirsher 			bp->line_speed = SPEED_100;
1116adfc5217SJeff Kirsher 			break;
1117adfc5217SJeff Kirsher 		case MII_BNX2_GP_TOP_AN_SPEED_1G:
1118adfc5217SJeff Kirsher 		case MII_BNX2_GP_TOP_AN_SPEED_1GKV:
1119adfc5217SJeff Kirsher 			bp->line_speed = SPEED_1000;
1120adfc5217SJeff Kirsher 			break;
1121adfc5217SJeff Kirsher 		case MII_BNX2_GP_TOP_AN_SPEED_2_5G:
1122adfc5217SJeff Kirsher 			bp->line_speed = SPEED_2500;
1123adfc5217SJeff Kirsher 			break;
1124adfc5217SJeff Kirsher 	}
1125adfc5217SJeff Kirsher 	if (val & MII_BNX2_GP_TOP_AN_FD)
1126adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_FULL;
1127adfc5217SJeff Kirsher 	else
1128adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_HALF;
1129adfc5217SJeff Kirsher 	return 0;
1130adfc5217SJeff Kirsher }
1131adfc5217SJeff Kirsher 
1132adfc5217SJeff Kirsher static int
1133adfc5217SJeff Kirsher bnx2_5708s_linkup(struct bnx2 *bp)
1134adfc5217SJeff Kirsher {
1135adfc5217SJeff Kirsher 	u32 val;
1136adfc5217SJeff Kirsher 
1137adfc5217SJeff Kirsher 	bp->link_up = 1;
1138adfc5217SJeff Kirsher 	bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
1139adfc5217SJeff Kirsher 	switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) {
1140adfc5217SJeff Kirsher 		case BCM5708S_1000X_STAT1_SPEED_10:
1141adfc5217SJeff Kirsher 			bp->line_speed = SPEED_10;
1142adfc5217SJeff Kirsher 			break;
1143adfc5217SJeff Kirsher 		case BCM5708S_1000X_STAT1_SPEED_100:
1144adfc5217SJeff Kirsher 			bp->line_speed = SPEED_100;
1145adfc5217SJeff Kirsher 			break;
1146adfc5217SJeff Kirsher 		case BCM5708S_1000X_STAT1_SPEED_1G:
1147adfc5217SJeff Kirsher 			bp->line_speed = SPEED_1000;
1148adfc5217SJeff Kirsher 			break;
1149adfc5217SJeff Kirsher 		case BCM5708S_1000X_STAT1_SPEED_2G5:
1150adfc5217SJeff Kirsher 			bp->line_speed = SPEED_2500;
1151adfc5217SJeff Kirsher 			break;
1152adfc5217SJeff Kirsher 	}
1153adfc5217SJeff Kirsher 	if (val & BCM5708S_1000X_STAT1_FD)
1154adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_FULL;
1155adfc5217SJeff Kirsher 	else
1156adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_HALF;
1157adfc5217SJeff Kirsher 
1158adfc5217SJeff Kirsher 	return 0;
1159adfc5217SJeff Kirsher }
1160adfc5217SJeff Kirsher 
1161adfc5217SJeff Kirsher static int
1162adfc5217SJeff Kirsher bnx2_5706s_linkup(struct bnx2 *bp)
1163adfc5217SJeff Kirsher {
1164adfc5217SJeff Kirsher 	u32 bmcr, local_adv, remote_adv, common;
1165adfc5217SJeff Kirsher 
1166adfc5217SJeff Kirsher 	bp->link_up = 1;
1167adfc5217SJeff Kirsher 	bp->line_speed = SPEED_1000;
1168adfc5217SJeff Kirsher 
1169adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1170adfc5217SJeff Kirsher 	if (bmcr & BMCR_FULLDPLX) {
1171adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_FULL;
1172adfc5217SJeff Kirsher 	}
1173adfc5217SJeff Kirsher 	else {
1174adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_HALF;
1175adfc5217SJeff Kirsher 	}
1176adfc5217SJeff Kirsher 
1177adfc5217SJeff Kirsher 	if (!(bmcr & BMCR_ANENABLE)) {
1178adfc5217SJeff Kirsher 		return 0;
1179adfc5217SJeff Kirsher 	}
1180adfc5217SJeff Kirsher 
1181adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_adv, &local_adv);
1182adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
1183adfc5217SJeff Kirsher 
1184adfc5217SJeff Kirsher 	common = local_adv & remote_adv;
1185adfc5217SJeff Kirsher 	if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
1186adfc5217SJeff Kirsher 
1187adfc5217SJeff Kirsher 		if (common & ADVERTISE_1000XFULL) {
1188adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_FULL;
1189adfc5217SJeff Kirsher 		}
1190adfc5217SJeff Kirsher 		else {
1191adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_HALF;
1192adfc5217SJeff Kirsher 		}
1193adfc5217SJeff Kirsher 	}
1194adfc5217SJeff Kirsher 
1195adfc5217SJeff Kirsher 	return 0;
1196adfc5217SJeff Kirsher }
1197adfc5217SJeff Kirsher 
1198adfc5217SJeff Kirsher static int
1199adfc5217SJeff Kirsher bnx2_copper_linkup(struct bnx2 *bp)
1200adfc5217SJeff Kirsher {
1201adfc5217SJeff Kirsher 	u32 bmcr;
1202adfc5217SJeff Kirsher 
1203adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1204adfc5217SJeff Kirsher 	if (bmcr & BMCR_ANENABLE) {
1205adfc5217SJeff Kirsher 		u32 local_adv, remote_adv, common;
1206adfc5217SJeff Kirsher 
1207adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
1208adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
1209adfc5217SJeff Kirsher 
1210adfc5217SJeff Kirsher 		common = local_adv & (remote_adv >> 2);
1211adfc5217SJeff Kirsher 		if (common & ADVERTISE_1000FULL) {
1212adfc5217SJeff Kirsher 			bp->line_speed = SPEED_1000;
1213adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_FULL;
1214adfc5217SJeff Kirsher 		}
1215adfc5217SJeff Kirsher 		else if (common & ADVERTISE_1000HALF) {
1216adfc5217SJeff Kirsher 			bp->line_speed = SPEED_1000;
1217adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_HALF;
1218adfc5217SJeff Kirsher 		}
1219adfc5217SJeff Kirsher 		else {
1220adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_adv, &local_adv);
1221adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
1222adfc5217SJeff Kirsher 
1223adfc5217SJeff Kirsher 			common = local_adv & remote_adv;
1224adfc5217SJeff Kirsher 			if (common & ADVERTISE_100FULL) {
1225adfc5217SJeff Kirsher 				bp->line_speed = SPEED_100;
1226adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_FULL;
1227adfc5217SJeff Kirsher 			}
1228adfc5217SJeff Kirsher 			else if (common & ADVERTISE_100HALF) {
1229adfc5217SJeff Kirsher 				bp->line_speed = SPEED_100;
1230adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1231adfc5217SJeff Kirsher 			}
1232adfc5217SJeff Kirsher 			else if (common & ADVERTISE_10FULL) {
1233adfc5217SJeff Kirsher 				bp->line_speed = SPEED_10;
1234adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_FULL;
1235adfc5217SJeff Kirsher 			}
1236adfc5217SJeff Kirsher 			else if (common & ADVERTISE_10HALF) {
1237adfc5217SJeff Kirsher 				bp->line_speed = SPEED_10;
1238adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1239adfc5217SJeff Kirsher 			}
1240adfc5217SJeff Kirsher 			else {
1241adfc5217SJeff Kirsher 				bp->line_speed = 0;
1242adfc5217SJeff Kirsher 				bp->link_up = 0;
1243adfc5217SJeff Kirsher 			}
1244adfc5217SJeff Kirsher 		}
1245adfc5217SJeff Kirsher 	}
1246adfc5217SJeff Kirsher 	else {
1247adfc5217SJeff Kirsher 		if (bmcr & BMCR_SPEED100) {
1248adfc5217SJeff Kirsher 			bp->line_speed = SPEED_100;
1249adfc5217SJeff Kirsher 		}
1250adfc5217SJeff Kirsher 		else {
1251adfc5217SJeff Kirsher 			bp->line_speed = SPEED_10;
1252adfc5217SJeff Kirsher 		}
1253adfc5217SJeff Kirsher 		if (bmcr & BMCR_FULLDPLX) {
1254adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_FULL;
1255adfc5217SJeff Kirsher 		}
1256adfc5217SJeff Kirsher 		else {
1257adfc5217SJeff Kirsher 			bp->duplex = DUPLEX_HALF;
1258adfc5217SJeff Kirsher 		}
1259adfc5217SJeff Kirsher 	}
1260adfc5217SJeff Kirsher 
1261adfc5217SJeff Kirsher 	return 0;
1262adfc5217SJeff Kirsher }
1263adfc5217SJeff Kirsher 
1264adfc5217SJeff Kirsher static void
1265adfc5217SJeff Kirsher bnx2_init_rx_context(struct bnx2 *bp, u32 cid)
1266adfc5217SJeff Kirsher {
1267adfc5217SJeff Kirsher 	u32 val, rx_cid_addr = GET_CID_ADDR(cid);
1268adfc5217SJeff Kirsher 
1269adfc5217SJeff Kirsher 	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
1270adfc5217SJeff Kirsher 	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
1271adfc5217SJeff Kirsher 	val |= 0x02 << 8;
1272adfc5217SJeff Kirsher 
1273adfc5217SJeff Kirsher 	if (bp->flow_ctrl & FLOW_CTRL_TX)
1274adfc5217SJeff Kirsher 		val |= BNX2_L2CTX_FLOW_CTRL_ENABLE;
1275adfc5217SJeff Kirsher 
1276adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
1277adfc5217SJeff Kirsher }
1278adfc5217SJeff Kirsher 
1279adfc5217SJeff Kirsher static void
1280adfc5217SJeff Kirsher bnx2_init_all_rx_contexts(struct bnx2 *bp)
1281adfc5217SJeff Kirsher {
1282adfc5217SJeff Kirsher 	int i;
1283adfc5217SJeff Kirsher 	u32 cid;
1284adfc5217SJeff Kirsher 
1285adfc5217SJeff Kirsher 	for (i = 0, cid = RX_CID; i < bp->num_rx_rings; i++, cid++) {
1286adfc5217SJeff Kirsher 		if (i == 1)
1287adfc5217SJeff Kirsher 			cid = RX_RSS_CID;
1288adfc5217SJeff Kirsher 		bnx2_init_rx_context(bp, cid);
1289adfc5217SJeff Kirsher 	}
1290adfc5217SJeff Kirsher }
1291adfc5217SJeff Kirsher 
1292adfc5217SJeff Kirsher static void
1293adfc5217SJeff Kirsher bnx2_set_mac_link(struct bnx2 *bp)
1294adfc5217SJeff Kirsher {
1295adfc5217SJeff Kirsher 	u32 val;
1296adfc5217SJeff Kirsher 
1297adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
1298adfc5217SJeff Kirsher 	if (bp->link_up && (bp->line_speed == SPEED_1000) &&
1299adfc5217SJeff Kirsher 		(bp->duplex == DUPLEX_HALF)) {
1300adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
1301adfc5217SJeff Kirsher 	}
1302adfc5217SJeff Kirsher 
1303adfc5217SJeff Kirsher 	/* Configure the EMAC mode register. */
1304adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_EMAC_MODE);
1305adfc5217SJeff Kirsher 
1306adfc5217SJeff Kirsher 	val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
1307adfc5217SJeff Kirsher 		BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
1308adfc5217SJeff Kirsher 		BNX2_EMAC_MODE_25G_MODE);
1309adfc5217SJeff Kirsher 
1310adfc5217SJeff Kirsher 	if (bp->link_up) {
1311adfc5217SJeff Kirsher 		switch (bp->line_speed) {
1312adfc5217SJeff Kirsher 			case SPEED_10:
1313adfc5217SJeff Kirsher 				if (CHIP_NUM(bp) != CHIP_NUM_5706) {
1314adfc5217SJeff Kirsher 					val |= BNX2_EMAC_MODE_PORT_MII_10M;
1315adfc5217SJeff Kirsher 					break;
1316adfc5217SJeff Kirsher 				}
1317adfc5217SJeff Kirsher 				/* fall through */
1318adfc5217SJeff Kirsher 			case SPEED_100:
1319adfc5217SJeff Kirsher 				val |= BNX2_EMAC_MODE_PORT_MII;
1320adfc5217SJeff Kirsher 				break;
1321adfc5217SJeff Kirsher 			case SPEED_2500:
1322adfc5217SJeff Kirsher 				val |= BNX2_EMAC_MODE_25G_MODE;
1323adfc5217SJeff Kirsher 				/* fall through */
1324adfc5217SJeff Kirsher 			case SPEED_1000:
1325adfc5217SJeff Kirsher 				val |= BNX2_EMAC_MODE_PORT_GMII;
1326adfc5217SJeff Kirsher 				break;
1327adfc5217SJeff Kirsher 		}
1328adfc5217SJeff Kirsher 	}
1329adfc5217SJeff Kirsher 	else {
1330adfc5217SJeff Kirsher 		val |= BNX2_EMAC_MODE_PORT_GMII;
1331adfc5217SJeff Kirsher 	}
1332adfc5217SJeff Kirsher 
1333adfc5217SJeff Kirsher 	/* Set the MAC to operate in the appropriate duplex mode. */
1334adfc5217SJeff Kirsher 	if (bp->duplex == DUPLEX_HALF)
1335adfc5217SJeff Kirsher 		val |= BNX2_EMAC_MODE_HALF_DUPLEX;
1336adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MODE, val);
1337adfc5217SJeff Kirsher 
1338adfc5217SJeff Kirsher 	/* Enable/disable rx PAUSE. */
1339adfc5217SJeff Kirsher 	bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
1340adfc5217SJeff Kirsher 
1341adfc5217SJeff Kirsher 	if (bp->flow_ctrl & FLOW_CTRL_RX)
1342adfc5217SJeff Kirsher 		bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
1343adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
1344adfc5217SJeff Kirsher 
1345adfc5217SJeff Kirsher 	/* Enable/disable tx PAUSE. */
1346adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_EMAC_TX_MODE);
1347adfc5217SJeff Kirsher 	val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
1348adfc5217SJeff Kirsher 
1349adfc5217SJeff Kirsher 	if (bp->flow_ctrl & FLOW_CTRL_TX)
1350adfc5217SJeff Kirsher 		val |= BNX2_EMAC_TX_MODE_FLOW_EN;
1351adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_TX_MODE, val);
1352adfc5217SJeff Kirsher 
1353adfc5217SJeff Kirsher 	/* Acknowledge the interrupt. */
1354adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
1355adfc5217SJeff Kirsher 
1356adfc5217SJeff Kirsher 	bnx2_init_all_rx_contexts(bp);
1357adfc5217SJeff Kirsher }
1358adfc5217SJeff Kirsher 
1359adfc5217SJeff Kirsher static void
1360adfc5217SJeff Kirsher bnx2_enable_bmsr1(struct bnx2 *bp)
1361adfc5217SJeff Kirsher {
1362adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
1363adfc5217SJeff Kirsher 	    (CHIP_NUM(bp) == CHIP_NUM_5709))
1364adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1365adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_GP_STATUS);
1366adfc5217SJeff Kirsher }
1367adfc5217SJeff Kirsher 
1368adfc5217SJeff Kirsher static void
1369adfc5217SJeff Kirsher bnx2_disable_bmsr1(struct bnx2 *bp)
1370adfc5217SJeff Kirsher {
1371adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
1372adfc5217SJeff Kirsher 	    (CHIP_NUM(bp) == CHIP_NUM_5709))
1373adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1374adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1375adfc5217SJeff Kirsher }
1376adfc5217SJeff Kirsher 
1377adfc5217SJeff Kirsher static int
1378adfc5217SJeff Kirsher bnx2_test_and_enable_2g5(struct bnx2 *bp)
1379adfc5217SJeff Kirsher {
1380adfc5217SJeff Kirsher 	u32 up1;
1381adfc5217SJeff Kirsher 	int ret = 1;
1382adfc5217SJeff Kirsher 
1383adfc5217SJeff Kirsher 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
1384adfc5217SJeff Kirsher 		return 0;
1385adfc5217SJeff Kirsher 
1386adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED)
1387adfc5217SJeff Kirsher 		bp->advertising |= ADVERTISED_2500baseX_Full;
1388adfc5217SJeff Kirsher 
1389adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
1390adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
1391adfc5217SJeff Kirsher 
1392adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_up1, &up1);
1393adfc5217SJeff Kirsher 	if (!(up1 & BCM5708S_UP1_2G5)) {
1394adfc5217SJeff Kirsher 		up1 |= BCM5708S_UP1_2G5;
1395adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_up1, up1);
1396adfc5217SJeff Kirsher 		ret = 0;
1397adfc5217SJeff Kirsher 	}
1398adfc5217SJeff Kirsher 
1399adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
1400adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1401adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1402adfc5217SJeff Kirsher 
1403adfc5217SJeff Kirsher 	return ret;
1404adfc5217SJeff Kirsher }
1405adfc5217SJeff Kirsher 
1406adfc5217SJeff Kirsher static int
1407adfc5217SJeff Kirsher bnx2_test_and_disable_2g5(struct bnx2 *bp)
1408adfc5217SJeff Kirsher {
1409adfc5217SJeff Kirsher 	u32 up1;
1410adfc5217SJeff Kirsher 	int ret = 0;
1411adfc5217SJeff Kirsher 
1412adfc5217SJeff Kirsher 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
1413adfc5217SJeff Kirsher 		return 0;
1414adfc5217SJeff Kirsher 
1415adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
1416adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
1417adfc5217SJeff Kirsher 
1418adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_up1, &up1);
1419adfc5217SJeff Kirsher 	if (up1 & BCM5708S_UP1_2G5) {
1420adfc5217SJeff Kirsher 		up1 &= ~BCM5708S_UP1_2G5;
1421adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_up1, up1);
1422adfc5217SJeff Kirsher 		ret = 1;
1423adfc5217SJeff Kirsher 	}
1424adfc5217SJeff Kirsher 
1425adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
1426adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1427adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1428adfc5217SJeff Kirsher 
1429adfc5217SJeff Kirsher 	return ret;
1430adfc5217SJeff Kirsher }
1431adfc5217SJeff Kirsher 
1432adfc5217SJeff Kirsher static void
1433adfc5217SJeff Kirsher bnx2_enable_forced_2g5(struct bnx2 *bp)
1434adfc5217SJeff Kirsher {
1435adfc5217SJeff Kirsher 	u32 uninitialized_var(bmcr);
1436adfc5217SJeff Kirsher 	int err;
1437adfc5217SJeff Kirsher 
1438adfc5217SJeff Kirsher 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
1439adfc5217SJeff Kirsher 		return;
1440adfc5217SJeff Kirsher 
1441adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
1442adfc5217SJeff Kirsher 		u32 val;
1443adfc5217SJeff Kirsher 
1444adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1445adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_SERDES_DIG);
1446adfc5217SJeff Kirsher 		if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
1447adfc5217SJeff Kirsher 			val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
1448adfc5217SJeff Kirsher 			val |= MII_BNX2_SD_MISC1_FORCE |
1449adfc5217SJeff Kirsher 				MII_BNX2_SD_MISC1_FORCE_2_5G;
1450adfc5217SJeff Kirsher 			bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
1451adfc5217SJeff Kirsher 		}
1452adfc5217SJeff Kirsher 
1453adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1454adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1455adfc5217SJeff Kirsher 		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1456adfc5217SJeff Kirsher 
1457adfc5217SJeff Kirsher 	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
1458adfc5217SJeff Kirsher 		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1459adfc5217SJeff Kirsher 		if (!err)
1460adfc5217SJeff Kirsher 			bmcr |= BCM5708S_BMCR_FORCE_2500;
1461adfc5217SJeff Kirsher 	} else {
1462adfc5217SJeff Kirsher 		return;
1463adfc5217SJeff Kirsher 	}
1464adfc5217SJeff Kirsher 
1465adfc5217SJeff Kirsher 	if (err)
1466adfc5217SJeff Kirsher 		return;
1467adfc5217SJeff Kirsher 
1468adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED) {
1469adfc5217SJeff Kirsher 		bmcr &= ~BMCR_ANENABLE;
1470adfc5217SJeff Kirsher 		if (bp->req_duplex == DUPLEX_FULL)
1471adfc5217SJeff Kirsher 			bmcr |= BMCR_FULLDPLX;
1472adfc5217SJeff Kirsher 	}
1473adfc5217SJeff Kirsher 	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
1474adfc5217SJeff Kirsher }
1475adfc5217SJeff Kirsher 
1476adfc5217SJeff Kirsher static void
1477adfc5217SJeff Kirsher bnx2_disable_forced_2g5(struct bnx2 *bp)
1478adfc5217SJeff Kirsher {
1479adfc5217SJeff Kirsher 	u32 uninitialized_var(bmcr);
1480adfc5217SJeff Kirsher 	int err;
1481adfc5217SJeff Kirsher 
1482adfc5217SJeff Kirsher 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
1483adfc5217SJeff Kirsher 		return;
1484adfc5217SJeff Kirsher 
1485adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
1486adfc5217SJeff Kirsher 		u32 val;
1487adfc5217SJeff Kirsher 
1488adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1489adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_SERDES_DIG);
1490adfc5217SJeff Kirsher 		if (!bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val)) {
1491adfc5217SJeff Kirsher 			val &= ~MII_BNX2_SD_MISC1_FORCE;
1492adfc5217SJeff Kirsher 			bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
1493adfc5217SJeff Kirsher 		}
1494adfc5217SJeff Kirsher 
1495adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
1496adfc5217SJeff Kirsher 			       MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
1497adfc5217SJeff Kirsher 		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1498adfc5217SJeff Kirsher 
1499adfc5217SJeff Kirsher 	} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
1500adfc5217SJeff Kirsher 		err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1501adfc5217SJeff Kirsher 		if (!err)
1502adfc5217SJeff Kirsher 			bmcr &= ~BCM5708S_BMCR_FORCE_2500;
1503adfc5217SJeff Kirsher 	} else {
1504adfc5217SJeff Kirsher 		return;
1505adfc5217SJeff Kirsher 	}
1506adfc5217SJeff Kirsher 
1507adfc5217SJeff Kirsher 	if (err)
1508adfc5217SJeff Kirsher 		return;
1509adfc5217SJeff Kirsher 
1510adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED)
1511adfc5217SJeff Kirsher 		bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART;
1512adfc5217SJeff Kirsher 	bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
1513adfc5217SJeff Kirsher }
1514adfc5217SJeff Kirsher 
1515adfc5217SJeff Kirsher static void
1516adfc5217SJeff Kirsher bnx2_5706s_force_link_dn(struct bnx2 *bp, int start)
1517adfc5217SJeff Kirsher {
1518adfc5217SJeff Kirsher 	u32 val;
1519adfc5217SJeff Kirsher 
1520adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_SERDES_CTL);
1521adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
1522adfc5217SJeff Kirsher 	if (start)
1523adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val & 0xff0f);
1524adfc5217SJeff Kirsher 	else
1525adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val | 0xc0);
1526adfc5217SJeff Kirsher }
1527adfc5217SJeff Kirsher 
1528adfc5217SJeff Kirsher static int
1529adfc5217SJeff Kirsher bnx2_set_link(struct bnx2 *bp)
1530adfc5217SJeff Kirsher {
1531adfc5217SJeff Kirsher 	u32 bmsr;
1532adfc5217SJeff Kirsher 	u8 link_up;
1533adfc5217SJeff Kirsher 
1534adfc5217SJeff Kirsher 	if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) {
1535adfc5217SJeff Kirsher 		bp->link_up = 1;
1536adfc5217SJeff Kirsher 		return 0;
1537adfc5217SJeff Kirsher 	}
1538adfc5217SJeff Kirsher 
1539adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
1540adfc5217SJeff Kirsher 		return 0;
1541adfc5217SJeff Kirsher 
1542adfc5217SJeff Kirsher 	link_up = bp->link_up;
1543adfc5217SJeff Kirsher 
1544adfc5217SJeff Kirsher 	bnx2_enable_bmsr1(bp);
1545adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
1546adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
1547adfc5217SJeff Kirsher 	bnx2_disable_bmsr1(bp);
1548adfc5217SJeff Kirsher 
1549adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
1550adfc5217SJeff Kirsher 	    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
1551adfc5217SJeff Kirsher 		u32 val, an_dbg;
1552adfc5217SJeff Kirsher 
1553adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) {
1554adfc5217SJeff Kirsher 			bnx2_5706s_force_link_dn(bp, 0);
1555adfc5217SJeff Kirsher 			bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN;
1556adfc5217SJeff Kirsher 		}
1557adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_EMAC_STATUS);
1558adfc5217SJeff Kirsher 
1559adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
1560adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
1561adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
1562adfc5217SJeff Kirsher 
1563adfc5217SJeff Kirsher 		if ((val & BNX2_EMAC_STATUS_LINK) &&
1564adfc5217SJeff Kirsher 		    !(an_dbg & MISC_SHDW_AN_DBG_NOSYNC))
1565adfc5217SJeff Kirsher 			bmsr |= BMSR_LSTATUS;
1566adfc5217SJeff Kirsher 		else
1567adfc5217SJeff Kirsher 			bmsr &= ~BMSR_LSTATUS;
1568adfc5217SJeff Kirsher 	}
1569adfc5217SJeff Kirsher 
1570adfc5217SJeff Kirsher 	if (bmsr & BMSR_LSTATUS) {
1571adfc5217SJeff Kirsher 		bp->link_up = 1;
1572adfc5217SJeff Kirsher 
1573adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1574adfc5217SJeff Kirsher 			if (CHIP_NUM(bp) == CHIP_NUM_5706)
1575adfc5217SJeff Kirsher 				bnx2_5706s_linkup(bp);
1576adfc5217SJeff Kirsher 			else if (CHIP_NUM(bp) == CHIP_NUM_5708)
1577adfc5217SJeff Kirsher 				bnx2_5708s_linkup(bp);
1578adfc5217SJeff Kirsher 			else if (CHIP_NUM(bp) == CHIP_NUM_5709)
1579adfc5217SJeff Kirsher 				bnx2_5709s_linkup(bp);
1580adfc5217SJeff Kirsher 		}
1581adfc5217SJeff Kirsher 		else {
1582adfc5217SJeff Kirsher 			bnx2_copper_linkup(bp);
1583adfc5217SJeff Kirsher 		}
1584adfc5217SJeff Kirsher 		bnx2_resolve_flow_ctrl(bp);
1585adfc5217SJeff Kirsher 	}
1586adfc5217SJeff Kirsher 	else {
1587adfc5217SJeff Kirsher 		if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
1588adfc5217SJeff Kirsher 		    (bp->autoneg & AUTONEG_SPEED))
1589adfc5217SJeff Kirsher 			bnx2_disable_forced_2g5(bp);
1590adfc5217SJeff Kirsher 
1591adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT) {
1592adfc5217SJeff Kirsher 			u32 bmcr;
1593adfc5217SJeff Kirsher 
1594adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1595adfc5217SJeff Kirsher 			bmcr |= BMCR_ANENABLE;
1596adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
1597adfc5217SJeff Kirsher 
1598adfc5217SJeff Kirsher 			bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
1599adfc5217SJeff Kirsher 		}
1600adfc5217SJeff Kirsher 		bp->link_up = 0;
1601adfc5217SJeff Kirsher 	}
1602adfc5217SJeff Kirsher 
1603adfc5217SJeff Kirsher 	if (bp->link_up != link_up) {
1604adfc5217SJeff Kirsher 		bnx2_report_link(bp);
1605adfc5217SJeff Kirsher 	}
1606adfc5217SJeff Kirsher 
1607adfc5217SJeff Kirsher 	bnx2_set_mac_link(bp);
1608adfc5217SJeff Kirsher 
1609adfc5217SJeff Kirsher 	return 0;
1610adfc5217SJeff Kirsher }
1611adfc5217SJeff Kirsher 
1612adfc5217SJeff Kirsher static int
1613adfc5217SJeff Kirsher bnx2_reset_phy(struct bnx2 *bp)
1614adfc5217SJeff Kirsher {
1615adfc5217SJeff Kirsher 	int i;
1616adfc5217SJeff Kirsher 	u32 reg;
1617adfc5217SJeff Kirsher 
1618adfc5217SJeff Kirsher         bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET);
1619adfc5217SJeff Kirsher 
1620adfc5217SJeff Kirsher #define PHY_RESET_MAX_WAIT 100
1621adfc5217SJeff Kirsher 	for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
1622adfc5217SJeff Kirsher 		udelay(10);
1623adfc5217SJeff Kirsher 
1624adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmcr, &reg);
1625adfc5217SJeff Kirsher 		if (!(reg & BMCR_RESET)) {
1626adfc5217SJeff Kirsher 			udelay(20);
1627adfc5217SJeff Kirsher 			break;
1628adfc5217SJeff Kirsher 		}
1629adfc5217SJeff Kirsher 	}
1630adfc5217SJeff Kirsher 	if (i == PHY_RESET_MAX_WAIT) {
1631adfc5217SJeff Kirsher 		return -EBUSY;
1632adfc5217SJeff Kirsher 	}
1633adfc5217SJeff Kirsher 	return 0;
1634adfc5217SJeff Kirsher }
1635adfc5217SJeff Kirsher 
1636adfc5217SJeff Kirsher static u32
1637adfc5217SJeff Kirsher bnx2_phy_get_pause_adv(struct bnx2 *bp)
1638adfc5217SJeff Kirsher {
1639adfc5217SJeff Kirsher 	u32 adv = 0;
1640adfc5217SJeff Kirsher 
1641adfc5217SJeff Kirsher 	if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
1642adfc5217SJeff Kirsher 		(FLOW_CTRL_RX | FLOW_CTRL_TX)) {
1643adfc5217SJeff Kirsher 
1644adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1645adfc5217SJeff Kirsher 			adv = ADVERTISE_1000XPAUSE;
1646adfc5217SJeff Kirsher 		}
1647adfc5217SJeff Kirsher 		else {
1648adfc5217SJeff Kirsher 			adv = ADVERTISE_PAUSE_CAP;
1649adfc5217SJeff Kirsher 		}
1650adfc5217SJeff Kirsher 	}
1651adfc5217SJeff Kirsher 	else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
1652adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1653adfc5217SJeff Kirsher 			adv = ADVERTISE_1000XPSE_ASYM;
1654adfc5217SJeff Kirsher 		}
1655adfc5217SJeff Kirsher 		else {
1656adfc5217SJeff Kirsher 			adv = ADVERTISE_PAUSE_ASYM;
1657adfc5217SJeff Kirsher 		}
1658adfc5217SJeff Kirsher 	}
1659adfc5217SJeff Kirsher 	else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
1660adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1661adfc5217SJeff Kirsher 			adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
1662adfc5217SJeff Kirsher 		}
1663adfc5217SJeff Kirsher 		else {
1664adfc5217SJeff Kirsher 			adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1665adfc5217SJeff Kirsher 		}
1666adfc5217SJeff Kirsher 	}
1667adfc5217SJeff Kirsher 	return adv;
1668adfc5217SJeff Kirsher }
1669adfc5217SJeff Kirsher 
1670adfc5217SJeff Kirsher static int bnx2_fw_sync(struct bnx2 *, u32, int, int);
1671adfc5217SJeff Kirsher 
1672adfc5217SJeff Kirsher static int
1673adfc5217SJeff Kirsher bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
1674adfc5217SJeff Kirsher __releases(&bp->phy_lock)
1675adfc5217SJeff Kirsher __acquires(&bp->phy_lock)
1676adfc5217SJeff Kirsher {
1677adfc5217SJeff Kirsher 	u32 speed_arg = 0, pause_adv;
1678adfc5217SJeff Kirsher 
1679adfc5217SJeff Kirsher 	pause_adv = bnx2_phy_get_pause_adv(bp);
1680adfc5217SJeff Kirsher 
1681adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED) {
1682adfc5217SJeff Kirsher 		speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG;
1683adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_10baseT_Half)
1684adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF;
1685adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_10baseT_Full)
1686adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL;
1687adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_100baseT_Half)
1688adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF;
1689adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_100baseT_Full)
1690adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL;
1691adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_1000baseT_Full)
1692adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
1693adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_2500baseX_Full)
1694adfc5217SJeff Kirsher 			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
1695adfc5217SJeff Kirsher 	} else {
1696adfc5217SJeff Kirsher 		if (bp->req_line_speed == SPEED_2500)
1697adfc5217SJeff Kirsher 			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
1698adfc5217SJeff Kirsher 		else if (bp->req_line_speed == SPEED_1000)
1699adfc5217SJeff Kirsher 			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
1700adfc5217SJeff Kirsher 		else if (bp->req_line_speed == SPEED_100) {
1701adfc5217SJeff Kirsher 			if (bp->req_duplex == DUPLEX_FULL)
1702adfc5217SJeff Kirsher 				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL;
1703adfc5217SJeff Kirsher 			else
1704adfc5217SJeff Kirsher 				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF;
1705adfc5217SJeff Kirsher 		} else if (bp->req_line_speed == SPEED_10) {
1706adfc5217SJeff Kirsher 			if (bp->req_duplex == DUPLEX_FULL)
1707adfc5217SJeff Kirsher 				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL;
1708adfc5217SJeff Kirsher 			else
1709adfc5217SJeff Kirsher 				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF;
1710adfc5217SJeff Kirsher 		}
1711adfc5217SJeff Kirsher 	}
1712adfc5217SJeff Kirsher 
1713adfc5217SJeff Kirsher 	if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
1714adfc5217SJeff Kirsher 		speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
1715adfc5217SJeff Kirsher 	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_PAUSE_ASYM))
1716adfc5217SJeff Kirsher 		speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
1717adfc5217SJeff Kirsher 
1718adfc5217SJeff Kirsher 	if (port == PORT_TP)
1719adfc5217SJeff Kirsher 		speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
1720adfc5217SJeff Kirsher 			     BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
1721adfc5217SJeff Kirsher 
1722adfc5217SJeff Kirsher 	bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg);
1723adfc5217SJeff Kirsher 
1724adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
1725adfc5217SJeff Kirsher 	bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 1, 0);
1726adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
1727adfc5217SJeff Kirsher 
1728adfc5217SJeff Kirsher 	return 0;
1729adfc5217SJeff Kirsher }
1730adfc5217SJeff Kirsher 
1731adfc5217SJeff Kirsher static int
1732adfc5217SJeff Kirsher bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
1733adfc5217SJeff Kirsher __releases(&bp->phy_lock)
1734adfc5217SJeff Kirsher __acquires(&bp->phy_lock)
1735adfc5217SJeff Kirsher {
1736adfc5217SJeff Kirsher 	u32 adv, bmcr;
1737adfc5217SJeff Kirsher 	u32 new_adv = 0;
1738adfc5217SJeff Kirsher 
1739adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
1740adfc5217SJeff Kirsher 		return bnx2_setup_remote_phy(bp, port);
1741adfc5217SJeff Kirsher 
1742adfc5217SJeff Kirsher 	if (!(bp->autoneg & AUTONEG_SPEED)) {
1743adfc5217SJeff Kirsher 		u32 new_bmcr;
1744adfc5217SJeff Kirsher 		int force_link_down = 0;
1745adfc5217SJeff Kirsher 
1746adfc5217SJeff Kirsher 		if (bp->req_line_speed == SPEED_2500) {
1747adfc5217SJeff Kirsher 			if (!bnx2_test_and_enable_2g5(bp))
1748adfc5217SJeff Kirsher 				force_link_down = 1;
1749adfc5217SJeff Kirsher 		} else if (bp->req_line_speed == SPEED_1000) {
1750adfc5217SJeff Kirsher 			if (bnx2_test_and_disable_2g5(bp))
1751adfc5217SJeff Kirsher 				force_link_down = 1;
1752adfc5217SJeff Kirsher 		}
1753adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_adv, &adv);
1754adfc5217SJeff Kirsher 		adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
1755adfc5217SJeff Kirsher 
1756adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1757adfc5217SJeff Kirsher 		new_bmcr = bmcr & ~BMCR_ANENABLE;
1758adfc5217SJeff Kirsher 		new_bmcr |= BMCR_SPEED1000;
1759adfc5217SJeff Kirsher 
1760adfc5217SJeff Kirsher 		if (CHIP_NUM(bp) == CHIP_NUM_5709) {
1761adfc5217SJeff Kirsher 			if (bp->req_line_speed == SPEED_2500)
1762adfc5217SJeff Kirsher 				bnx2_enable_forced_2g5(bp);
1763adfc5217SJeff Kirsher 			else if (bp->req_line_speed == SPEED_1000) {
1764adfc5217SJeff Kirsher 				bnx2_disable_forced_2g5(bp);
1765adfc5217SJeff Kirsher 				new_bmcr &= ~0x2000;
1766adfc5217SJeff Kirsher 			}
1767adfc5217SJeff Kirsher 
1768adfc5217SJeff Kirsher 		} else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
1769adfc5217SJeff Kirsher 			if (bp->req_line_speed == SPEED_2500)
1770adfc5217SJeff Kirsher 				new_bmcr |= BCM5708S_BMCR_FORCE_2500;
1771adfc5217SJeff Kirsher 			else
1772adfc5217SJeff Kirsher 				new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500;
1773adfc5217SJeff Kirsher 		}
1774adfc5217SJeff Kirsher 
1775adfc5217SJeff Kirsher 		if (bp->req_duplex == DUPLEX_FULL) {
1776adfc5217SJeff Kirsher 			adv |= ADVERTISE_1000XFULL;
1777adfc5217SJeff Kirsher 			new_bmcr |= BMCR_FULLDPLX;
1778adfc5217SJeff Kirsher 		}
1779adfc5217SJeff Kirsher 		else {
1780adfc5217SJeff Kirsher 			adv |= ADVERTISE_1000XHALF;
1781adfc5217SJeff Kirsher 			new_bmcr &= ~BMCR_FULLDPLX;
1782adfc5217SJeff Kirsher 		}
1783adfc5217SJeff Kirsher 		if ((new_bmcr != bmcr) || (force_link_down)) {
1784adfc5217SJeff Kirsher 			/* Force a link down visible on the other side */
1785adfc5217SJeff Kirsher 			if (bp->link_up) {
1786adfc5217SJeff Kirsher 				bnx2_write_phy(bp, bp->mii_adv, adv &
1787adfc5217SJeff Kirsher 					       ~(ADVERTISE_1000XFULL |
1788adfc5217SJeff Kirsher 						 ADVERTISE_1000XHALF));
1789adfc5217SJeff Kirsher 				bnx2_write_phy(bp, bp->mii_bmcr, bmcr |
1790adfc5217SJeff Kirsher 					BMCR_ANRESTART | BMCR_ANENABLE);
1791adfc5217SJeff Kirsher 
1792adfc5217SJeff Kirsher 				bp->link_up = 0;
1793adfc5217SJeff Kirsher 				netif_carrier_off(bp->dev);
1794adfc5217SJeff Kirsher 				bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
1795adfc5217SJeff Kirsher 				bnx2_report_link(bp);
1796adfc5217SJeff Kirsher 			}
1797adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_adv, adv);
1798adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
1799adfc5217SJeff Kirsher 		} else {
1800adfc5217SJeff Kirsher 			bnx2_resolve_flow_ctrl(bp);
1801adfc5217SJeff Kirsher 			bnx2_set_mac_link(bp);
1802adfc5217SJeff Kirsher 		}
1803adfc5217SJeff Kirsher 		return 0;
1804adfc5217SJeff Kirsher 	}
1805adfc5217SJeff Kirsher 
1806adfc5217SJeff Kirsher 	bnx2_test_and_enable_2g5(bp);
1807adfc5217SJeff Kirsher 
1808adfc5217SJeff Kirsher 	if (bp->advertising & ADVERTISED_1000baseT_Full)
1809adfc5217SJeff Kirsher 		new_adv |= ADVERTISE_1000XFULL;
1810adfc5217SJeff Kirsher 
1811adfc5217SJeff Kirsher 	new_adv |= bnx2_phy_get_pause_adv(bp);
1812adfc5217SJeff Kirsher 
1813adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_adv, &adv);
1814adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
1815adfc5217SJeff Kirsher 
1816adfc5217SJeff Kirsher 	bp->serdes_an_pending = 0;
1817adfc5217SJeff Kirsher 	if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
1818adfc5217SJeff Kirsher 		/* Force a link down visible on the other side */
1819adfc5217SJeff Kirsher 		if (bp->link_up) {
1820adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
1821adfc5217SJeff Kirsher 			spin_unlock_bh(&bp->phy_lock);
1822adfc5217SJeff Kirsher 			msleep(20);
1823adfc5217SJeff Kirsher 			spin_lock_bh(&bp->phy_lock);
1824adfc5217SJeff Kirsher 		}
1825adfc5217SJeff Kirsher 
1826adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_adv, new_adv);
1827adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART |
1828adfc5217SJeff Kirsher 			BMCR_ANENABLE);
1829adfc5217SJeff Kirsher 		/* Speed up link-up time when the link partner
1830adfc5217SJeff Kirsher 		 * does not autonegotiate which is very common
1831adfc5217SJeff Kirsher 		 * in blade servers. Some blade servers use
1832adfc5217SJeff Kirsher 		 * IPMI for kerboard input and it's important
1833adfc5217SJeff Kirsher 		 * to minimize link disruptions. Autoneg. involves
1834adfc5217SJeff Kirsher 		 * exchanging base pages plus 3 next pages and
1835adfc5217SJeff Kirsher 		 * normally completes in about 120 msec.
1836adfc5217SJeff Kirsher 		 */
1837adfc5217SJeff Kirsher 		bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
1838adfc5217SJeff Kirsher 		bp->serdes_an_pending = 1;
1839adfc5217SJeff Kirsher 		mod_timer(&bp->timer, jiffies + bp->current_interval);
1840adfc5217SJeff Kirsher 	} else {
1841adfc5217SJeff Kirsher 		bnx2_resolve_flow_ctrl(bp);
1842adfc5217SJeff Kirsher 		bnx2_set_mac_link(bp);
1843adfc5217SJeff Kirsher 	}
1844adfc5217SJeff Kirsher 
1845adfc5217SJeff Kirsher 	return 0;
1846adfc5217SJeff Kirsher }
1847adfc5217SJeff Kirsher 
1848adfc5217SJeff Kirsher #define ETHTOOL_ALL_FIBRE_SPEED						\
1849adfc5217SJeff Kirsher 	(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) ?			\
1850adfc5217SJeff Kirsher 		(ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\
1851adfc5217SJeff Kirsher 		(ADVERTISED_1000baseT_Full)
1852adfc5217SJeff Kirsher 
1853adfc5217SJeff Kirsher #define ETHTOOL_ALL_COPPER_SPEED					\
1854adfc5217SJeff Kirsher 	(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |		\
1855adfc5217SJeff Kirsher 	ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |		\
1856adfc5217SJeff Kirsher 	ADVERTISED_1000baseT_Full)
1857adfc5217SJeff Kirsher 
1858adfc5217SJeff Kirsher #define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
1859adfc5217SJeff Kirsher 	ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
1860adfc5217SJeff Kirsher 
1861adfc5217SJeff Kirsher #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
1862adfc5217SJeff Kirsher 
1863adfc5217SJeff Kirsher static void
1864adfc5217SJeff Kirsher bnx2_set_default_remote_link(struct bnx2 *bp)
1865adfc5217SJeff Kirsher {
1866adfc5217SJeff Kirsher 	u32 link;
1867adfc5217SJeff Kirsher 
1868adfc5217SJeff Kirsher 	if (bp->phy_port == PORT_TP)
1869adfc5217SJeff Kirsher 		link = bnx2_shmem_rd(bp, BNX2_RPHY_COPPER_LINK);
1870adfc5217SJeff Kirsher 	else
1871adfc5217SJeff Kirsher 		link = bnx2_shmem_rd(bp, BNX2_RPHY_SERDES_LINK);
1872adfc5217SJeff Kirsher 
1873adfc5217SJeff Kirsher 	if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
1874adfc5217SJeff Kirsher 		bp->req_line_speed = 0;
1875adfc5217SJeff Kirsher 		bp->autoneg |= AUTONEG_SPEED;
1876adfc5217SJeff Kirsher 		bp->advertising = ADVERTISED_Autoneg;
1877adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
1878adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_10baseT_Half;
1879adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL)
1880adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_10baseT_Full;
1881adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
1882adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_100baseT_Half;
1883adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL)
1884adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_100baseT_Full;
1885adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
1886adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_1000baseT_Full;
1887adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
1888adfc5217SJeff Kirsher 			bp->advertising |= ADVERTISED_2500baseX_Full;
1889adfc5217SJeff Kirsher 	} else {
1890adfc5217SJeff Kirsher 		bp->autoneg = 0;
1891adfc5217SJeff Kirsher 		bp->advertising = 0;
1892adfc5217SJeff Kirsher 		bp->req_duplex = DUPLEX_FULL;
1893adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_10) {
1894adfc5217SJeff Kirsher 			bp->req_line_speed = SPEED_10;
1895adfc5217SJeff Kirsher 			if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
1896adfc5217SJeff Kirsher 				bp->req_duplex = DUPLEX_HALF;
1897adfc5217SJeff Kirsher 		}
1898adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_100) {
1899adfc5217SJeff Kirsher 			bp->req_line_speed = SPEED_100;
1900adfc5217SJeff Kirsher 			if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
1901adfc5217SJeff Kirsher 				bp->req_duplex = DUPLEX_HALF;
1902adfc5217SJeff Kirsher 		}
1903adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
1904adfc5217SJeff Kirsher 			bp->req_line_speed = SPEED_1000;
1905adfc5217SJeff Kirsher 		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
1906adfc5217SJeff Kirsher 			bp->req_line_speed = SPEED_2500;
1907adfc5217SJeff Kirsher 	}
1908adfc5217SJeff Kirsher }
1909adfc5217SJeff Kirsher 
1910adfc5217SJeff Kirsher static void
1911adfc5217SJeff Kirsher bnx2_set_default_link(struct bnx2 *bp)
1912adfc5217SJeff Kirsher {
1913adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
1914adfc5217SJeff Kirsher 		bnx2_set_default_remote_link(bp);
1915adfc5217SJeff Kirsher 		return;
1916adfc5217SJeff Kirsher 	}
1917adfc5217SJeff Kirsher 
1918adfc5217SJeff Kirsher 	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
1919adfc5217SJeff Kirsher 	bp->req_line_speed = 0;
1920adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
1921adfc5217SJeff Kirsher 		u32 reg;
1922adfc5217SJeff Kirsher 
1923adfc5217SJeff Kirsher 		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
1924adfc5217SJeff Kirsher 
1925adfc5217SJeff Kirsher 		reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG);
1926adfc5217SJeff Kirsher 		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
1927adfc5217SJeff Kirsher 		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
1928adfc5217SJeff Kirsher 			bp->autoneg = 0;
1929adfc5217SJeff Kirsher 			bp->req_line_speed = bp->line_speed = SPEED_1000;
1930adfc5217SJeff Kirsher 			bp->req_duplex = DUPLEX_FULL;
1931adfc5217SJeff Kirsher 		}
1932adfc5217SJeff Kirsher 	} else
1933adfc5217SJeff Kirsher 		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
1934adfc5217SJeff Kirsher }
1935adfc5217SJeff Kirsher 
1936adfc5217SJeff Kirsher static void
1937adfc5217SJeff Kirsher bnx2_send_heart_beat(struct bnx2 *bp)
1938adfc5217SJeff Kirsher {
1939adfc5217SJeff Kirsher 	u32 msg;
1940adfc5217SJeff Kirsher 	u32 addr;
1941adfc5217SJeff Kirsher 
1942adfc5217SJeff Kirsher 	spin_lock(&bp->indirect_lock);
1943adfc5217SJeff Kirsher 	msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
1944adfc5217SJeff Kirsher 	addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
1945adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
1946adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
1947adfc5217SJeff Kirsher 	spin_unlock(&bp->indirect_lock);
1948adfc5217SJeff Kirsher }
1949adfc5217SJeff Kirsher 
1950adfc5217SJeff Kirsher static void
1951adfc5217SJeff Kirsher bnx2_remote_phy_event(struct bnx2 *bp)
1952adfc5217SJeff Kirsher {
1953adfc5217SJeff Kirsher 	u32 msg;
1954adfc5217SJeff Kirsher 	u8 link_up = bp->link_up;
1955adfc5217SJeff Kirsher 	u8 old_port;
1956adfc5217SJeff Kirsher 
1957adfc5217SJeff Kirsher 	msg = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
1958adfc5217SJeff Kirsher 
1959adfc5217SJeff Kirsher 	if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
1960adfc5217SJeff Kirsher 		bnx2_send_heart_beat(bp);
1961adfc5217SJeff Kirsher 
1962adfc5217SJeff Kirsher 	msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED;
1963adfc5217SJeff Kirsher 
1964adfc5217SJeff Kirsher 	if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN)
1965adfc5217SJeff Kirsher 		bp->link_up = 0;
1966adfc5217SJeff Kirsher 	else {
1967adfc5217SJeff Kirsher 		u32 speed;
1968adfc5217SJeff Kirsher 
1969adfc5217SJeff Kirsher 		bp->link_up = 1;
1970adfc5217SJeff Kirsher 		speed = msg & BNX2_LINK_STATUS_SPEED_MASK;
1971adfc5217SJeff Kirsher 		bp->duplex = DUPLEX_FULL;
1972adfc5217SJeff Kirsher 		switch (speed) {
1973adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_10HALF:
1974adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1975adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_10FULL:
1976adfc5217SJeff Kirsher 				bp->line_speed = SPEED_10;
1977adfc5217SJeff Kirsher 				break;
1978adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_100HALF:
1979adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1980adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_100BASE_T4:
1981adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_100FULL:
1982adfc5217SJeff Kirsher 				bp->line_speed = SPEED_100;
1983adfc5217SJeff Kirsher 				break;
1984adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_1000HALF:
1985adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1986adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_1000FULL:
1987adfc5217SJeff Kirsher 				bp->line_speed = SPEED_1000;
1988adfc5217SJeff Kirsher 				break;
1989adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_2500HALF:
1990adfc5217SJeff Kirsher 				bp->duplex = DUPLEX_HALF;
1991adfc5217SJeff Kirsher 			case BNX2_LINK_STATUS_2500FULL:
1992adfc5217SJeff Kirsher 				bp->line_speed = SPEED_2500;
1993adfc5217SJeff Kirsher 				break;
1994adfc5217SJeff Kirsher 			default:
1995adfc5217SJeff Kirsher 				bp->line_speed = 0;
1996adfc5217SJeff Kirsher 				break;
1997adfc5217SJeff Kirsher 		}
1998adfc5217SJeff Kirsher 
1999adfc5217SJeff Kirsher 		bp->flow_ctrl = 0;
2000adfc5217SJeff Kirsher 		if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
2001adfc5217SJeff Kirsher 		    (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
2002adfc5217SJeff Kirsher 			if (bp->duplex == DUPLEX_FULL)
2003adfc5217SJeff Kirsher 				bp->flow_ctrl = bp->req_flow_ctrl;
2004adfc5217SJeff Kirsher 		} else {
2005adfc5217SJeff Kirsher 			if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED)
2006adfc5217SJeff Kirsher 				bp->flow_ctrl |= FLOW_CTRL_TX;
2007adfc5217SJeff Kirsher 			if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED)
2008adfc5217SJeff Kirsher 				bp->flow_ctrl |= FLOW_CTRL_RX;
2009adfc5217SJeff Kirsher 		}
2010adfc5217SJeff Kirsher 
2011adfc5217SJeff Kirsher 		old_port = bp->phy_port;
2012adfc5217SJeff Kirsher 		if (msg & BNX2_LINK_STATUS_SERDES_LINK)
2013adfc5217SJeff Kirsher 			bp->phy_port = PORT_FIBRE;
2014adfc5217SJeff Kirsher 		else
2015adfc5217SJeff Kirsher 			bp->phy_port = PORT_TP;
2016adfc5217SJeff Kirsher 
2017adfc5217SJeff Kirsher 		if (old_port != bp->phy_port)
2018adfc5217SJeff Kirsher 			bnx2_set_default_link(bp);
2019adfc5217SJeff Kirsher 
2020adfc5217SJeff Kirsher 	}
2021adfc5217SJeff Kirsher 	if (bp->link_up != link_up)
2022adfc5217SJeff Kirsher 		bnx2_report_link(bp);
2023adfc5217SJeff Kirsher 
2024adfc5217SJeff Kirsher 	bnx2_set_mac_link(bp);
2025adfc5217SJeff Kirsher }
2026adfc5217SJeff Kirsher 
2027adfc5217SJeff Kirsher static int
2028adfc5217SJeff Kirsher bnx2_set_remote_link(struct bnx2 *bp)
2029adfc5217SJeff Kirsher {
2030adfc5217SJeff Kirsher 	u32 evt_code;
2031adfc5217SJeff Kirsher 
2032adfc5217SJeff Kirsher 	evt_code = bnx2_shmem_rd(bp, BNX2_FW_EVT_CODE_MB);
2033adfc5217SJeff Kirsher 	switch (evt_code) {
2034adfc5217SJeff Kirsher 		case BNX2_FW_EVT_CODE_LINK_EVENT:
2035adfc5217SJeff Kirsher 			bnx2_remote_phy_event(bp);
2036adfc5217SJeff Kirsher 			break;
2037adfc5217SJeff Kirsher 		case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT:
2038adfc5217SJeff Kirsher 		default:
2039adfc5217SJeff Kirsher 			bnx2_send_heart_beat(bp);
2040adfc5217SJeff Kirsher 			break;
2041adfc5217SJeff Kirsher 	}
2042adfc5217SJeff Kirsher 	return 0;
2043adfc5217SJeff Kirsher }
2044adfc5217SJeff Kirsher 
2045adfc5217SJeff Kirsher static int
2046adfc5217SJeff Kirsher bnx2_setup_copper_phy(struct bnx2 *bp)
2047adfc5217SJeff Kirsher __releases(&bp->phy_lock)
2048adfc5217SJeff Kirsher __acquires(&bp->phy_lock)
2049adfc5217SJeff Kirsher {
2050adfc5217SJeff Kirsher 	u32 bmcr;
2051adfc5217SJeff Kirsher 	u32 new_bmcr;
2052adfc5217SJeff Kirsher 
2053adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
2054adfc5217SJeff Kirsher 
2055adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED) {
2056adfc5217SJeff Kirsher 		u32 adv_reg, adv1000_reg;
2057adfc5217SJeff Kirsher 		u32 new_adv_reg = 0;
2058adfc5217SJeff Kirsher 		u32 new_adv1000_reg = 0;
2059adfc5217SJeff Kirsher 
2060adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
2061adfc5217SJeff Kirsher 		adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
2062adfc5217SJeff Kirsher 			ADVERTISE_PAUSE_ASYM);
2063adfc5217SJeff Kirsher 
2064adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
2065adfc5217SJeff Kirsher 		adv1000_reg &= PHY_ALL_1000_SPEED;
2066adfc5217SJeff Kirsher 
2067adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_10baseT_Half)
2068adfc5217SJeff Kirsher 			new_adv_reg |= ADVERTISE_10HALF;
2069adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_10baseT_Full)
2070adfc5217SJeff Kirsher 			new_adv_reg |= ADVERTISE_10FULL;
2071adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_100baseT_Half)
2072adfc5217SJeff Kirsher 			new_adv_reg |= ADVERTISE_100HALF;
2073adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_100baseT_Full)
2074adfc5217SJeff Kirsher 			new_adv_reg |= ADVERTISE_100FULL;
2075adfc5217SJeff Kirsher 		if (bp->advertising & ADVERTISED_1000baseT_Full)
2076adfc5217SJeff Kirsher 			new_adv1000_reg |= ADVERTISE_1000FULL;
2077adfc5217SJeff Kirsher 
2078adfc5217SJeff Kirsher 		new_adv_reg |= ADVERTISE_CSMA;
2079adfc5217SJeff Kirsher 
2080adfc5217SJeff Kirsher 		new_adv_reg |= bnx2_phy_get_pause_adv(bp);
2081adfc5217SJeff Kirsher 
2082adfc5217SJeff Kirsher 		if ((adv1000_reg != new_adv1000_reg) ||
2083adfc5217SJeff Kirsher 			(adv_reg != new_adv_reg) ||
2084adfc5217SJeff Kirsher 			((bmcr & BMCR_ANENABLE) == 0)) {
2085adfc5217SJeff Kirsher 
2086adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_adv, new_adv_reg);
2087adfc5217SJeff Kirsher 			bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
2088adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART |
2089adfc5217SJeff Kirsher 				BMCR_ANENABLE);
2090adfc5217SJeff Kirsher 		}
2091adfc5217SJeff Kirsher 		else if (bp->link_up) {
2092adfc5217SJeff Kirsher 			/* Flow ctrl may have changed from auto to forced */
2093adfc5217SJeff Kirsher 			/* or vice-versa. */
2094adfc5217SJeff Kirsher 
2095adfc5217SJeff Kirsher 			bnx2_resolve_flow_ctrl(bp);
2096adfc5217SJeff Kirsher 			bnx2_set_mac_link(bp);
2097adfc5217SJeff Kirsher 		}
2098adfc5217SJeff Kirsher 		return 0;
2099adfc5217SJeff Kirsher 	}
2100adfc5217SJeff Kirsher 
2101adfc5217SJeff Kirsher 	new_bmcr = 0;
2102adfc5217SJeff Kirsher 	if (bp->req_line_speed == SPEED_100) {
2103adfc5217SJeff Kirsher 		new_bmcr |= BMCR_SPEED100;
2104adfc5217SJeff Kirsher 	}
2105adfc5217SJeff Kirsher 	if (bp->req_duplex == DUPLEX_FULL) {
2106adfc5217SJeff Kirsher 		new_bmcr |= BMCR_FULLDPLX;
2107adfc5217SJeff Kirsher 	}
2108adfc5217SJeff Kirsher 	if (new_bmcr != bmcr) {
2109adfc5217SJeff Kirsher 		u32 bmsr;
2110adfc5217SJeff Kirsher 
2111adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
2112adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
2113adfc5217SJeff Kirsher 
2114adfc5217SJeff Kirsher 		if (bmsr & BMSR_LSTATUS) {
2115adfc5217SJeff Kirsher 			/* Force link down */
2116adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
2117adfc5217SJeff Kirsher 			spin_unlock_bh(&bp->phy_lock);
2118adfc5217SJeff Kirsher 			msleep(50);
2119adfc5217SJeff Kirsher 			spin_lock_bh(&bp->phy_lock);
2120adfc5217SJeff Kirsher 
2121adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
2122adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
2123adfc5217SJeff Kirsher 		}
2124adfc5217SJeff Kirsher 
2125adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
2126adfc5217SJeff Kirsher 
2127adfc5217SJeff Kirsher 		/* Normally, the new speed is setup after the link has
2128adfc5217SJeff Kirsher 		 * gone down and up again. In some cases, link will not go
2129adfc5217SJeff Kirsher 		 * down so we need to set up the new speed here.
2130adfc5217SJeff Kirsher 		 */
2131adfc5217SJeff Kirsher 		if (bmsr & BMSR_LSTATUS) {
2132adfc5217SJeff Kirsher 			bp->line_speed = bp->req_line_speed;
2133adfc5217SJeff Kirsher 			bp->duplex = bp->req_duplex;
2134adfc5217SJeff Kirsher 			bnx2_resolve_flow_ctrl(bp);
2135adfc5217SJeff Kirsher 			bnx2_set_mac_link(bp);
2136adfc5217SJeff Kirsher 		}
2137adfc5217SJeff Kirsher 	} else {
2138adfc5217SJeff Kirsher 		bnx2_resolve_flow_ctrl(bp);
2139adfc5217SJeff Kirsher 		bnx2_set_mac_link(bp);
2140adfc5217SJeff Kirsher 	}
2141adfc5217SJeff Kirsher 	return 0;
2142adfc5217SJeff Kirsher }
2143adfc5217SJeff Kirsher 
2144adfc5217SJeff Kirsher static int
2145adfc5217SJeff Kirsher bnx2_setup_phy(struct bnx2 *bp, u8 port)
2146adfc5217SJeff Kirsher __releases(&bp->phy_lock)
2147adfc5217SJeff Kirsher __acquires(&bp->phy_lock)
2148adfc5217SJeff Kirsher {
2149adfc5217SJeff Kirsher 	if (bp->loopback == MAC_LOOPBACK)
2150adfc5217SJeff Kirsher 		return 0;
2151adfc5217SJeff Kirsher 
2152adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
2153adfc5217SJeff Kirsher 		return bnx2_setup_serdes_phy(bp, port);
2154adfc5217SJeff Kirsher 	}
2155adfc5217SJeff Kirsher 	else {
2156adfc5217SJeff Kirsher 		return bnx2_setup_copper_phy(bp);
2157adfc5217SJeff Kirsher 	}
2158adfc5217SJeff Kirsher }
2159adfc5217SJeff Kirsher 
2160adfc5217SJeff Kirsher static int
2161adfc5217SJeff Kirsher bnx2_init_5709s_phy(struct bnx2 *bp, int reset_phy)
2162adfc5217SJeff Kirsher {
2163adfc5217SJeff Kirsher 	u32 val;
2164adfc5217SJeff Kirsher 
2165adfc5217SJeff Kirsher 	bp->mii_bmcr = MII_BMCR + 0x10;
2166adfc5217SJeff Kirsher 	bp->mii_bmsr = MII_BMSR + 0x10;
2167adfc5217SJeff Kirsher 	bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1;
2168adfc5217SJeff Kirsher 	bp->mii_adv = MII_ADVERTISE + 0x10;
2169adfc5217SJeff Kirsher 	bp->mii_lpa = MII_LPA + 0x10;
2170adfc5217SJeff Kirsher 	bp->mii_up1 = MII_BNX2_OVER1G_UP1;
2171adfc5217SJeff Kirsher 
2172adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER);
2173adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
2174adfc5217SJeff Kirsher 
2175adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
2176adfc5217SJeff Kirsher 	if (reset_phy)
2177adfc5217SJeff Kirsher 		bnx2_reset_phy(bp);
2178adfc5217SJeff Kirsher 
2179adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
2180adfc5217SJeff Kirsher 
2181adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val);
2182adfc5217SJeff Kirsher 	val &= ~MII_BNX2_SD_1000XCTL1_AUTODET;
2183adfc5217SJeff Kirsher 	val |= MII_BNX2_SD_1000XCTL1_FIBER;
2184adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val);
2185adfc5217SJeff Kirsher 
2186adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
2187adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val);
2188adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
2189adfc5217SJeff Kirsher 		val |= BCM5708S_UP1_2G5;
2190adfc5217SJeff Kirsher 	else
2191adfc5217SJeff Kirsher 		val &= ~BCM5708S_UP1_2G5;
2192adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val);
2193adfc5217SJeff Kirsher 
2194adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG);
2195adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val);
2196adfc5217SJeff Kirsher 	val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM;
2197adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val);
2198adfc5217SJeff Kirsher 
2199adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0);
2200adfc5217SJeff Kirsher 
2201adfc5217SJeff Kirsher 	val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN |
2202adfc5217SJeff Kirsher 	      MII_BNX2_CL73_BAM_NP_AFT_BP_EN;
2203adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val);
2204adfc5217SJeff Kirsher 
2205adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
2206adfc5217SJeff Kirsher 
2207adfc5217SJeff Kirsher 	return 0;
2208adfc5217SJeff Kirsher }
2209adfc5217SJeff Kirsher 
2210adfc5217SJeff Kirsher static int
2211adfc5217SJeff Kirsher bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
2212adfc5217SJeff Kirsher {
2213adfc5217SJeff Kirsher 	u32 val;
2214adfc5217SJeff Kirsher 
2215adfc5217SJeff Kirsher 	if (reset_phy)
2216adfc5217SJeff Kirsher 		bnx2_reset_phy(bp);
2217adfc5217SJeff Kirsher 
2218adfc5217SJeff Kirsher 	bp->mii_up1 = BCM5708S_UP1;
2219adfc5217SJeff Kirsher 
2220adfc5217SJeff Kirsher 	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
2221adfc5217SJeff Kirsher 	bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
2222adfc5217SJeff Kirsher 	bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
2223adfc5217SJeff Kirsher 
2224adfc5217SJeff Kirsher 	bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val);
2225adfc5217SJeff Kirsher 	val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN;
2226adfc5217SJeff Kirsher 	bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val);
2227adfc5217SJeff Kirsher 
2228adfc5217SJeff Kirsher 	bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val);
2229adfc5217SJeff Kirsher 	val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN;
2230adfc5217SJeff Kirsher 	bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val);
2231adfc5217SJeff Kirsher 
2232adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) {
2233adfc5217SJeff Kirsher 		bnx2_read_phy(bp, BCM5708S_UP1, &val);
2234adfc5217SJeff Kirsher 		val |= BCM5708S_UP1_2G5;
2235adfc5217SJeff Kirsher 		bnx2_write_phy(bp, BCM5708S_UP1, val);
2236adfc5217SJeff Kirsher 	}
2237adfc5217SJeff Kirsher 
2238adfc5217SJeff Kirsher 	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
2239adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
2240adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
2241adfc5217SJeff Kirsher 		/* increase tx signal amplitude */
2242adfc5217SJeff Kirsher 		bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
2243adfc5217SJeff Kirsher 			       BCM5708S_BLK_ADDR_TX_MISC);
2244adfc5217SJeff Kirsher 		bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val);
2245adfc5217SJeff Kirsher 		val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM;
2246adfc5217SJeff Kirsher 		bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val);
2247adfc5217SJeff Kirsher 		bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
2248adfc5217SJeff Kirsher 	}
2249adfc5217SJeff Kirsher 
2250adfc5217SJeff Kirsher 	val = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_CONFIG) &
2251adfc5217SJeff Kirsher 	      BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
2252adfc5217SJeff Kirsher 
2253adfc5217SJeff Kirsher 	if (val) {
2254adfc5217SJeff Kirsher 		u32 is_backplane;
2255adfc5217SJeff Kirsher 
2256adfc5217SJeff Kirsher 		is_backplane = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
2257adfc5217SJeff Kirsher 		if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
2258adfc5217SJeff Kirsher 			bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
2259adfc5217SJeff Kirsher 				       BCM5708S_BLK_ADDR_TX_MISC);
2260adfc5217SJeff Kirsher 			bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val);
2261adfc5217SJeff Kirsher 			bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
2262adfc5217SJeff Kirsher 				       BCM5708S_BLK_ADDR_DIG);
2263adfc5217SJeff Kirsher 		}
2264adfc5217SJeff Kirsher 	}
2265adfc5217SJeff Kirsher 	return 0;
2266adfc5217SJeff Kirsher }
2267adfc5217SJeff Kirsher 
2268adfc5217SJeff Kirsher static int
2269adfc5217SJeff Kirsher bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
2270adfc5217SJeff Kirsher {
2271adfc5217SJeff Kirsher 	if (reset_phy)
2272adfc5217SJeff Kirsher 		bnx2_reset_phy(bp);
2273adfc5217SJeff Kirsher 
2274adfc5217SJeff Kirsher 	bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
2275adfc5217SJeff Kirsher 
2276adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5706)
2277adfc5217SJeff Kirsher         	REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
2278adfc5217SJeff Kirsher 
2279adfc5217SJeff Kirsher 	if (bp->dev->mtu > 1500) {
2280adfc5217SJeff Kirsher 		u32 val;
2281adfc5217SJeff Kirsher 
2282adfc5217SJeff Kirsher 		/* Set extended packet length bit */
2283adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x7);
2284adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x18, &val);
2285adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, (val & 0xfff8) | 0x4000);
2286adfc5217SJeff Kirsher 
2287adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x1c, 0x6c00);
2288adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x1c, &val);
2289adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x1c, (val & 0x3ff) | 0xec02);
2290adfc5217SJeff Kirsher 	}
2291adfc5217SJeff Kirsher 	else {
2292adfc5217SJeff Kirsher 		u32 val;
2293adfc5217SJeff Kirsher 
2294adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x7);
2295adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x18, &val);
2296adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, val & ~0x4007);
2297adfc5217SJeff Kirsher 
2298adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x1c, 0x6c00);
2299adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x1c, &val);
2300adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
2301adfc5217SJeff Kirsher 	}
2302adfc5217SJeff Kirsher 
2303adfc5217SJeff Kirsher 	return 0;
2304adfc5217SJeff Kirsher }
2305adfc5217SJeff Kirsher 
2306adfc5217SJeff Kirsher static int
2307adfc5217SJeff Kirsher bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
2308adfc5217SJeff Kirsher {
2309adfc5217SJeff Kirsher 	u32 val;
2310adfc5217SJeff Kirsher 
2311adfc5217SJeff Kirsher 	if (reset_phy)
2312adfc5217SJeff Kirsher 		bnx2_reset_phy(bp);
2313adfc5217SJeff Kirsher 
2314adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_CRC_FIX) {
2315adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x0c00);
2316adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x17, 0x000a);
2317adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x15, 0x310b);
2318adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x17, 0x201f);
2319adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x15, 0x9506);
2320adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x17, 0x401f);
2321adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x15, 0x14e2);
2322adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x0400);
2323adfc5217SJeff Kirsher 	}
2324adfc5217SJeff Kirsher 
2325adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_DIS_EARLY_DAC) {
2326adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS,
2327adfc5217SJeff Kirsher 			       MII_BNX2_DSP_EXPAND_REG | 0x8);
2328adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
2329adfc5217SJeff Kirsher 		val &= ~(1 << 8);
2330adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
2331adfc5217SJeff Kirsher 	}
2332adfc5217SJeff Kirsher 
2333adfc5217SJeff Kirsher 	if (bp->dev->mtu > 1500) {
2334adfc5217SJeff Kirsher 		/* Set extended packet length bit */
2335adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x7);
2336adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x18, &val);
2337adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, val | 0x4000);
2338adfc5217SJeff Kirsher 
2339adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x10, &val);
2340adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x10, val | 0x1);
2341adfc5217SJeff Kirsher 	}
2342adfc5217SJeff Kirsher 	else {
2343adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, 0x7);
2344adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x18, &val);
2345adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x18, val & ~0x4007);
2346adfc5217SJeff Kirsher 
2347adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x10, &val);
2348adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x10, val & ~0x1);
2349adfc5217SJeff Kirsher 	}
2350adfc5217SJeff Kirsher 
2351adfc5217SJeff Kirsher 	/* ethernet@wirespeed */
2352adfc5217SJeff Kirsher 	bnx2_write_phy(bp, 0x18, 0x7007);
2353adfc5217SJeff Kirsher 	bnx2_read_phy(bp, 0x18, &val);
2354adfc5217SJeff Kirsher 	bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
2355adfc5217SJeff Kirsher 	return 0;
2356adfc5217SJeff Kirsher }
2357adfc5217SJeff Kirsher 
2358adfc5217SJeff Kirsher 
2359adfc5217SJeff Kirsher static int
2360adfc5217SJeff Kirsher bnx2_init_phy(struct bnx2 *bp, int reset_phy)
2361adfc5217SJeff Kirsher __releases(&bp->phy_lock)
2362adfc5217SJeff Kirsher __acquires(&bp->phy_lock)
2363adfc5217SJeff Kirsher {
2364adfc5217SJeff Kirsher 	u32 val;
2365adfc5217SJeff Kirsher 	int rc = 0;
2366adfc5217SJeff Kirsher 
2367adfc5217SJeff Kirsher 	bp->phy_flags &= ~BNX2_PHY_FLAG_INT_MODE_MASK;
2368adfc5217SJeff Kirsher 	bp->phy_flags |= BNX2_PHY_FLAG_INT_MODE_LINK_READY;
2369adfc5217SJeff Kirsher 
2370adfc5217SJeff Kirsher 	bp->mii_bmcr = MII_BMCR;
2371adfc5217SJeff Kirsher 	bp->mii_bmsr = MII_BMSR;
2372adfc5217SJeff Kirsher 	bp->mii_bmsr1 = MII_BMSR;
2373adfc5217SJeff Kirsher 	bp->mii_adv = MII_ADVERTISE;
2374adfc5217SJeff Kirsher 	bp->mii_lpa = MII_LPA;
2375adfc5217SJeff Kirsher 
2376adfc5217SJeff Kirsher         REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
2377adfc5217SJeff Kirsher 
2378adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
2379adfc5217SJeff Kirsher 		goto setup_phy;
2380adfc5217SJeff Kirsher 
2381adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_PHYSID1, &val);
2382adfc5217SJeff Kirsher 	bp->phy_id = val << 16;
2383adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_PHYSID2, &val);
2384adfc5217SJeff Kirsher 	bp->phy_id |= val & 0xffff;
2385adfc5217SJeff Kirsher 
2386adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
2387adfc5217SJeff Kirsher 		if (CHIP_NUM(bp) == CHIP_NUM_5706)
2388adfc5217SJeff Kirsher 			rc = bnx2_init_5706s_phy(bp, reset_phy);
2389adfc5217SJeff Kirsher 		else if (CHIP_NUM(bp) == CHIP_NUM_5708)
2390adfc5217SJeff Kirsher 			rc = bnx2_init_5708s_phy(bp, reset_phy);
2391adfc5217SJeff Kirsher 		else if (CHIP_NUM(bp) == CHIP_NUM_5709)
2392adfc5217SJeff Kirsher 			rc = bnx2_init_5709s_phy(bp, reset_phy);
2393adfc5217SJeff Kirsher 	}
2394adfc5217SJeff Kirsher 	else {
2395adfc5217SJeff Kirsher 		rc = bnx2_init_copper_phy(bp, reset_phy);
2396adfc5217SJeff Kirsher 	}
2397adfc5217SJeff Kirsher 
2398adfc5217SJeff Kirsher setup_phy:
2399adfc5217SJeff Kirsher 	if (!rc)
2400adfc5217SJeff Kirsher 		rc = bnx2_setup_phy(bp, bp->phy_port);
2401adfc5217SJeff Kirsher 
2402adfc5217SJeff Kirsher 	return rc;
2403adfc5217SJeff Kirsher }
2404adfc5217SJeff Kirsher 
2405adfc5217SJeff Kirsher static int
2406adfc5217SJeff Kirsher bnx2_set_mac_loopback(struct bnx2 *bp)
2407adfc5217SJeff Kirsher {
2408adfc5217SJeff Kirsher 	u32 mac_mode;
2409adfc5217SJeff Kirsher 
2410adfc5217SJeff Kirsher 	mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
2411adfc5217SJeff Kirsher 	mac_mode &= ~BNX2_EMAC_MODE_PORT;
2412adfc5217SJeff Kirsher 	mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK;
2413adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
2414adfc5217SJeff Kirsher 	bp->link_up = 1;
2415adfc5217SJeff Kirsher 	return 0;
2416adfc5217SJeff Kirsher }
2417adfc5217SJeff Kirsher 
2418adfc5217SJeff Kirsher static int bnx2_test_link(struct bnx2 *);
2419adfc5217SJeff Kirsher 
2420adfc5217SJeff Kirsher static int
2421adfc5217SJeff Kirsher bnx2_set_phy_loopback(struct bnx2 *bp)
2422adfc5217SJeff Kirsher {
2423adfc5217SJeff Kirsher 	u32 mac_mode;
2424adfc5217SJeff Kirsher 	int rc, i;
2425adfc5217SJeff Kirsher 
2426adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
2427adfc5217SJeff Kirsher 	rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX |
2428adfc5217SJeff Kirsher 			    BMCR_SPEED1000);
2429adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
2430adfc5217SJeff Kirsher 	if (rc)
2431adfc5217SJeff Kirsher 		return rc;
2432adfc5217SJeff Kirsher 
2433adfc5217SJeff Kirsher 	for (i = 0; i < 10; i++) {
2434adfc5217SJeff Kirsher 		if (bnx2_test_link(bp) == 0)
2435adfc5217SJeff Kirsher 			break;
2436adfc5217SJeff Kirsher 		msleep(100);
2437adfc5217SJeff Kirsher 	}
2438adfc5217SJeff Kirsher 
2439adfc5217SJeff Kirsher 	mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
2440adfc5217SJeff Kirsher 	mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
2441adfc5217SJeff Kirsher 		      BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
2442adfc5217SJeff Kirsher 		      BNX2_EMAC_MODE_25G_MODE);
2443adfc5217SJeff Kirsher 
2444adfc5217SJeff Kirsher 	mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
2445adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
2446adfc5217SJeff Kirsher 	bp->link_up = 1;
2447adfc5217SJeff Kirsher 	return 0;
2448adfc5217SJeff Kirsher }
2449adfc5217SJeff Kirsher 
2450adfc5217SJeff Kirsher static void
2451adfc5217SJeff Kirsher bnx2_dump_mcp_state(struct bnx2 *bp)
2452adfc5217SJeff Kirsher {
2453adfc5217SJeff Kirsher 	struct net_device *dev = bp->dev;
2454adfc5217SJeff Kirsher 	u32 mcp_p0, mcp_p1;
2455adfc5217SJeff Kirsher 
2456adfc5217SJeff Kirsher 	netdev_err(dev, "<--- start MCP states dump --->\n");
2457adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
2458adfc5217SJeff Kirsher 		mcp_p0 = BNX2_MCP_STATE_P0;
2459adfc5217SJeff Kirsher 		mcp_p1 = BNX2_MCP_STATE_P1;
2460adfc5217SJeff Kirsher 	} else {
2461adfc5217SJeff Kirsher 		mcp_p0 = BNX2_MCP_STATE_P0_5708;
2462adfc5217SJeff Kirsher 		mcp_p1 = BNX2_MCP_STATE_P1_5708;
2463adfc5217SJeff Kirsher 	}
2464adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n",
2465adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, mcp_p0), bnx2_reg_rd_ind(bp, mcp_p1));
2466adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: MCP mode[%08x] state[%08x] evt_mask[%08x]\n",
2467adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_MODE),
2468adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_STATE),
2469adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_EVENT_MASK));
2470adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: pc[%08x] pc[%08x] instr[%08x]\n",
2471adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
2472adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_PROGRAM_COUNTER),
2473adfc5217SJeff Kirsher 		   bnx2_reg_rd_ind(bp, BNX2_MCP_CPU_INSTRUCTION));
2474adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: shmem states:\n");
2475adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: drv_mb[%08x] fw_mb[%08x] link_status[%08x]",
2476adfc5217SJeff Kirsher 		   bnx2_shmem_rd(bp, BNX2_DRV_MB),
2477adfc5217SJeff Kirsher 		   bnx2_shmem_rd(bp, BNX2_FW_MB),
2478adfc5217SJeff Kirsher 		   bnx2_shmem_rd(bp, BNX2_LINK_STATUS));
2479adfc5217SJeff Kirsher 	pr_cont(" drv_pulse_mb[%08x]\n", bnx2_shmem_rd(bp, BNX2_DRV_PULSE_MB));
2480adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: dev_info_signature[%08x] reset_type[%08x]",
2481adfc5217SJeff Kirsher 		   bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE),
2482adfc5217SJeff Kirsher 		   bnx2_shmem_rd(bp, BNX2_BC_STATE_RESET_TYPE));
2483adfc5217SJeff Kirsher 	pr_cont(" condition[%08x]\n",
2484adfc5217SJeff Kirsher 		bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION));
2485adfc5217SJeff Kirsher 	DP_SHMEM_LINE(bp, 0x3cc);
2486adfc5217SJeff Kirsher 	DP_SHMEM_LINE(bp, 0x3dc);
2487adfc5217SJeff Kirsher 	DP_SHMEM_LINE(bp, 0x3ec);
2488adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: 0x3fc[%08x]\n", bnx2_shmem_rd(bp, 0x3fc));
2489adfc5217SJeff Kirsher 	netdev_err(dev, "<--- end MCP states dump --->\n");
2490adfc5217SJeff Kirsher }
2491adfc5217SJeff Kirsher 
2492adfc5217SJeff Kirsher static int
2493adfc5217SJeff Kirsher bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
2494adfc5217SJeff Kirsher {
2495adfc5217SJeff Kirsher 	int i;
2496adfc5217SJeff Kirsher 	u32 val;
2497adfc5217SJeff Kirsher 
2498adfc5217SJeff Kirsher 	bp->fw_wr_seq++;
2499adfc5217SJeff Kirsher 	msg_data |= bp->fw_wr_seq;
2500adfc5217SJeff Kirsher 
2501adfc5217SJeff Kirsher 	bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
2502adfc5217SJeff Kirsher 
2503adfc5217SJeff Kirsher 	if (!ack)
2504adfc5217SJeff Kirsher 		return 0;
2505adfc5217SJeff Kirsher 
2506adfc5217SJeff Kirsher 	/* wait for an acknowledgement. */
2507adfc5217SJeff Kirsher 	for (i = 0; i < (BNX2_FW_ACK_TIME_OUT_MS / 10); i++) {
2508adfc5217SJeff Kirsher 		msleep(10);
2509adfc5217SJeff Kirsher 
2510adfc5217SJeff Kirsher 		val = bnx2_shmem_rd(bp, BNX2_FW_MB);
2511adfc5217SJeff Kirsher 
2512adfc5217SJeff Kirsher 		if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
2513adfc5217SJeff Kirsher 			break;
2514adfc5217SJeff Kirsher 	}
2515adfc5217SJeff Kirsher 	if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
2516adfc5217SJeff Kirsher 		return 0;
2517adfc5217SJeff Kirsher 
2518adfc5217SJeff Kirsher 	/* If we timed out, inform the firmware that this is the case. */
2519adfc5217SJeff Kirsher 	if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
2520adfc5217SJeff Kirsher 		msg_data &= ~BNX2_DRV_MSG_CODE;
2521adfc5217SJeff Kirsher 		msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
2522adfc5217SJeff Kirsher 
2523adfc5217SJeff Kirsher 		bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
2524adfc5217SJeff Kirsher 		if (!silent) {
2525adfc5217SJeff Kirsher 			pr_err("fw sync timeout, reset code = %x\n", msg_data);
2526adfc5217SJeff Kirsher 			bnx2_dump_mcp_state(bp);
2527adfc5217SJeff Kirsher 		}
2528adfc5217SJeff Kirsher 
2529adfc5217SJeff Kirsher 		return -EBUSY;
2530adfc5217SJeff Kirsher 	}
2531adfc5217SJeff Kirsher 
2532adfc5217SJeff Kirsher 	if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
2533adfc5217SJeff Kirsher 		return -EIO;
2534adfc5217SJeff Kirsher 
2535adfc5217SJeff Kirsher 	return 0;
2536adfc5217SJeff Kirsher }
2537adfc5217SJeff Kirsher 
2538adfc5217SJeff Kirsher static int
2539adfc5217SJeff Kirsher bnx2_init_5709_context(struct bnx2 *bp)
2540adfc5217SJeff Kirsher {
2541adfc5217SJeff Kirsher 	int i, ret = 0;
2542adfc5217SJeff Kirsher 	u32 val;
2543adfc5217SJeff Kirsher 
2544adfc5217SJeff Kirsher 	val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
2545adfc5217SJeff Kirsher 	val |= (BCM_PAGE_BITS - 8) << 16;
2546adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_CTX_COMMAND, val);
2547adfc5217SJeff Kirsher 	for (i = 0; i < 10; i++) {
2548adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_CTX_COMMAND);
2549adfc5217SJeff Kirsher 		if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
2550adfc5217SJeff Kirsher 			break;
2551adfc5217SJeff Kirsher 		udelay(2);
2552adfc5217SJeff Kirsher 	}
2553adfc5217SJeff Kirsher 	if (val & BNX2_CTX_COMMAND_MEM_INIT)
2554adfc5217SJeff Kirsher 		return -EBUSY;
2555adfc5217SJeff Kirsher 
2556adfc5217SJeff Kirsher 	for (i = 0; i < bp->ctx_pages; i++) {
2557adfc5217SJeff Kirsher 		int j;
2558adfc5217SJeff Kirsher 
2559adfc5217SJeff Kirsher 		if (bp->ctx_blk[i])
2560adfc5217SJeff Kirsher 			memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE);
2561adfc5217SJeff Kirsher 		else
2562adfc5217SJeff Kirsher 			return -ENOMEM;
2563adfc5217SJeff Kirsher 
2564adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
2565adfc5217SJeff Kirsher 		       (bp->ctx_blk_mapping[i] & 0xffffffff) |
2566adfc5217SJeff Kirsher 		       BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
2567adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
2568adfc5217SJeff Kirsher 		       (u64) bp->ctx_blk_mapping[i] >> 32);
2569adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
2570adfc5217SJeff Kirsher 		       BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
2571adfc5217SJeff Kirsher 		for (j = 0; j < 10; j++) {
2572adfc5217SJeff Kirsher 
2573adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
2574adfc5217SJeff Kirsher 			if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
2575adfc5217SJeff Kirsher 				break;
2576adfc5217SJeff Kirsher 			udelay(5);
2577adfc5217SJeff Kirsher 		}
2578adfc5217SJeff Kirsher 		if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) {
2579adfc5217SJeff Kirsher 			ret = -EBUSY;
2580adfc5217SJeff Kirsher 			break;
2581adfc5217SJeff Kirsher 		}
2582adfc5217SJeff Kirsher 	}
2583adfc5217SJeff Kirsher 	return ret;
2584adfc5217SJeff Kirsher }
2585adfc5217SJeff Kirsher 
2586adfc5217SJeff Kirsher static void
2587adfc5217SJeff Kirsher bnx2_init_context(struct bnx2 *bp)
2588adfc5217SJeff Kirsher {
2589adfc5217SJeff Kirsher 	u32 vcid;
2590adfc5217SJeff Kirsher 
2591adfc5217SJeff Kirsher 	vcid = 96;
2592adfc5217SJeff Kirsher 	while (vcid) {
2593adfc5217SJeff Kirsher 		u32 vcid_addr, pcid_addr, offset;
2594adfc5217SJeff Kirsher 		int i;
2595adfc5217SJeff Kirsher 
2596adfc5217SJeff Kirsher 		vcid--;
2597adfc5217SJeff Kirsher 
2598adfc5217SJeff Kirsher 		if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
2599adfc5217SJeff Kirsher 			u32 new_vcid;
2600adfc5217SJeff Kirsher 
2601adfc5217SJeff Kirsher 			vcid_addr = GET_PCID_ADDR(vcid);
2602adfc5217SJeff Kirsher 			if (vcid & 0x8) {
2603adfc5217SJeff Kirsher 				new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
2604adfc5217SJeff Kirsher 			}
2605adfc5217SJeff Kirsher 			else {
2606adfc5217SJeff Kirsher 				new_vcid = vcid;
2607adfc5217SJeff Kirsher 			}
2608adfc5217SJeff Kirsher 			pcid_addr = GET_PCID_ADDR(new_vcid);
2609adfc5217SJeff Kirsher 		}
2610adfc5217SJeff Kirsher 		else {
2611adfc5217SJeff Kirsher 	    		vcid_addr = GET_CID_ADDR(vcid);
2612adfc5217SJeff Kirsher 			pcid_addr = vcid_addr;
2613adfc5217SJeff Kirsher 		}
2614adfc5217SJeff Kirsher 
2615adfc5217SJeff Kirsher 		for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
2616adfc5217SJeff Kirsher 			vcid_addr += (i << PHY_CTX_SHIFT);
2617adfc5217SJeff Kirsher 			pcid_addr += (i << PHY_CTX_SHIFT);
2618adfc5217SJeff Kirsher 
2619adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
2620adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
2621adfc5217SJeff Kirsher 
2622adfc5217SJeff Kirsher 			/* Zero out the context. */
2623adfc5217SJeff Kirsher 			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
2624adfc5217SJeff Kirsher 				bnx2_ctx_wr(bp, vcid_addr, offset, 0);
2625adfc5217SJeff Kirsher 		}
2626adfc5217SJeff Kirsher 	}
2627adfc5217SJeff Kirsher }
2628adfc5217SJeff Kirsher 
2629adfc5217SJeff Kirsher static int
2630adfc5217SJeff Kirsher bnx2_alloc_bad_rbuf(struct bnx2 *bp)
2631adfc5217SJeff Kirsher {
2632adfc5217SJeff Kirsher 	u16 *good_mbuf;
2633adfc5217SJeff Kirsher 	u32 good_mbuf_cnt;
2634adfc5217SJeff Kirsher 	u32 val;
2635adfc5217SJeff Kirsher 
2636adfc5217SJeff Kirsher 	good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
2637adfc5217SJeff Kirsher 	if (good_mbuf == NULL) {
2638adfc5217SJeff Kirsher 		pr_err("Failed to allocate memory in %s\n", __func__);
2639adfc5217SJeff Kirsher 		return -ENOMEM;
2640adfc5217SJeff Kirsher 	}
2641adfc5217SJeff Kirsher 
2642adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
2643adfc5217SJeff Kirsher 		BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
2644adfc5217SJeff Kirsher 
2645adfc5217SJeff Kirsher 	good_mbuf_cnt = 0;
2646adfc5217SJeff Kirsher 
2647adfc5217SJeff Kirsher 	/* Allocate a bunch of mbufs and save the good ones in an array. */
2648adfc5217SJeff Kirsher 	val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
2649adfc5217SJeff Kirsher 	while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
2650adfc5217SJeff Kirsher 		bnx2_reg_wr_ind(bp, BNX2_RBUF_COMMAND,
2651adfc5217SJeff Kirsher 				BNX2_RBUF_COMMAND_ALLOC_REQ);
2652adfc5217SJeff Kirsher 
2653adfc5217SJeff Kirsher 		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_FW_BUF_ALLOC);
2654adfc5217SJeff Kirsher 
2655adfc5217SJeff Kirsher 		val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
2656adfc5217SJeff Kirsher 
2657adfc5217SJeff Kirsher 		/* The addresses with Bit 9 set are bad memory blocks. */
2658adfc5217SJeff Kirsher 		if (!(val & (1 << 9))) {
2659adfc5217SJeff Kirsher 			good_mbuf[good_mbuf_cnt] = (u16) val;
2660adfc5217SJeff Kirsher 			good_mbuf_cnt++;
2661adfc5217SJeff Kirsher 		}
2662adfc5217SJeff Kirsher 
2663adfc5217SJeff Kirsher 		val = bnx2_reg_rd_ind(bp, BNX2_RBUF_STATUS1);
2664adfc5217SJeff Kirsher 	}
2665adfc5217SJeff Kirsher 
2666adfc5217SJeff Kirsher 	/* Free the good ones back to the mbuf pool thus discarding
2667adfc5217SJeff Kirsher 	 * all the bad ones. */
2668adfc5217SJeff Kirsher 	while (good_mbuf_cnt) {
2669adfc5217SJeff Kirsher 		good_mbuf_cnt--;
2670adfc5217SJeff Kirsher 
2671adfc5217SJeff Kirsher 		val = good_mbuf[good_mbuf_cnt];
2672adfc5217SJeff Kirsher 		val = (val << 9) | val | 1;
2673adfc5217SJeff Kirsher 
2674adfc5217SJeff Kirsher 		bnx2_reg_wr_ind(bp, BNX2_RBUF_FW_BUF_FREE, val);
2675adfc5217SJeff Kirsher 	}
2676adfc5217SJeff Kirsher 	kfree(good_mbuf);
2677adfc5217SJeff Kirsher 	return 0;
2678adfc5217SJeff Kirsher }
2679adfc5217SJeff Kirsher 
2680adfc5217SJeff Kirsher static void
2681adfc5217SJeff Kirsher bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
2682adfc5217SJeff Kirsher {
2683adfc5217SJeff Kirsher 	u32 val;
2684adfc5217SJeff Kirsher 
2685adfc5217SJeff Kirsher 	val = (mac_addr[0] << 8) | mac_addr[1];
2686adfc5217SJeff Kirsher 
2687adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
2688adfc5217SJeff Kirsher 
2689adfc5217SJeff Kirsher 	val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
2690adfc5217SJeff Kirsher 		(mac_addr[4] << 8) | mac_addr[5];
2691adfc5217SJeff Kirsher 
2692adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
2693adfc5217SJeff Kirsher }
2694adfc5217SJeff Kirsher 
2695adfc5217SJeff Kirsher static inline int
2696adfc5217SJeff Kirsher bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
2697adfc5217SJeff Kirsher {
2698adfc5217SJeff Kirsher 	dma_addr_t mapping;
2699adfc5217SJeff Kirsher 	struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
2700adfc5217SJeff Kirsher 	struct rx_bd *rxbd =
2701adfc5217SJeff Kirsher 		&rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
2702adfc5217SJeff Kirsher 	struct page *page = alloc_page(gfp);
2703adfc5217SJeff Kirsher 
2704adfc5217SJeff Kirsher 	if (!page)
2705adfc5217SJeff Kirsher 		return -ENOMEM;
2706adfc5217SJeff Kirsher 	mapping = dma_map_page(&bp->pdev->dev, page, 0, PAGE_SIZE,
2707adfc5217SJeff Kirsher 			       PCI_DMA_FROMDEVICE);
2708adfc5217SJeff Kirsher 	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
2709adfc5217SJeff Kirsher 		__free_page(page);
2710adfc5217SJeff Kirsher 		return -EIO;
2711adfc5217SJeff Kirsher 	}
2712adfc5217SJeff Kirsher 
2713adfc5217SJeff Kirsher 	rx_pg->page = page;
2714adfc5217SJeff Kirsher 	dma_unmap_addr_set(rx_pg, mapping, mapping);
2715adfc5217SJeff Kirsher 	rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
2716adfc5217SJeff Kirsher 	rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
2717adfc5217SJeff Kirsher 	return 0;
2718adfc5217SJeff Kirsher }
2719adfc5217SJeff Kirsher 
2720adfc5217SJeff Kirsher static void
2721adfc5217SJeff Kirsher bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
2722adfc5217SJeff Kirsher {
2723adfc5217SJeff Kirsher 	struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
2724adfc5217SJeff Kirsher 	struct page *page = rx_pg->page;
2725adfc5217SJeff Kirsher 
2726adfc5217SJeff Kirsher 	if (!page)
2727adfc5217SJeff Kirsher 		return;
2728adfc5217SJeff Kirsher 
2729adfc5217SJeff Kirsher 	dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(rx_pg, mapping),
2730adfc5217SJeff Kirsher 		       PAGE_SIZE, PCI_DMA_FROMDEVICE);
2731adfc5217SJeff Kirsher 
2732adfc5217SJeff Kirsher 	__free_page(page);
2733adfc5217SJeff Kirsher 	rx_pg->page = NULL;
2734adfc5217SJeff Kirsher }
2735adfc5217SJeff Kirsher 
2736adfc5217SJeff Kirsher static inline int
2737adfc5217SJeff Kirsher bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
2738adfc5217SJeff Kirsher {
2739adfc5217SJeff Kirsher 	struct sk_buff *skb;
2740adfc5217SJeff Kirsher 	struct sw_bd *rx_buf = &rxr->rx_buf_ring[index];
2741adfc5217SJeff Kirsher 	dma_addr_t mapping;
2742adfc5217SJeff Kirsher 	struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
2743adfc5217SJeff Kirsher 	unsigned long align;
2744adfc5217SJeff Kirsher 
2745adfc5217SJeff Kirsher 	skb = __netdev_alloc_skb(bp->dev, bp->rx_buf_size, gfp);
2746adfc5217SJeff Kirsher 	if (skb == NULL) {
2747adfc5217SJeff Kirsher 		return -ENOMEM;
2748adfc5217SJeff Kirsher 	}
2749adfc5217SJeff Kirsher 
2750adfc5217SJeff Kirsher 	if (unlikely((align = (unsigned long) skb->data & (BNX2_RX_ALIGN - 1))))
2751adfc5217SJeff Kirsher 		skb_reserve(skb, BNX2_RX_ALIGN - align);
2752adfc5217SJeff Kirsher 
2753adfc5217SJeff Kirsher 	mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_use_size,
2754adfc5217SJeff Kirsher 				 PCI_DMA_FROMDEVICE);
2755adfc5217SJeff Kirsher 	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
2756adfc5217SJeff Kirsher 		dev_kfree_skb(skb);
2757adfc5217SJeff Kirsher 		return -EIO;
2758adfc5217SJeff Kirsher 	}
2759adfc5217SJeff Kirsher 
2760adfc5217SJeff Kirsher 	rx_buf->skb = skb;
2761adfc5217SJeff Kirsher 	rx_buf->desc = (struct l2_fhdr *) skb->data;
2762adfc5217SJeff Kirsher 	dma_unmap_addr_set(rx_buf, mapping, mapping);
2763adfc5217SJeff Kirsher 
2764adfc5217SJeff Kirsher 	rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
2765adfc5217SJeff Kirsher 	rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
2766adfc5217SJeff Kirsher 
2767adfc5217SJeff Kirsher 	rxr->rx_prod_bseq += bp->rx_buf_use_size;
2768adfc5217SJeff Kirsher 
2769adfc5217SJeff Kirsher 	return 0;
2770adfc5217SJeff Kirsher }
2771adfc5217SJeff Kirsher 
2772adfc5217SJeff Kirsher static int
2773adfc5217SJeff Kirsher bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
2774adfc5217SJeff Kirsher {
2775adfc5217SJeff Kirsher 	struct status_block *sblk = bnapi->status_blk.msi;
2776adfc5217SJeff Kirsher 	u32 new_link_state, old_link_state;
2777adfc5217SJeff Kirsher 	int is_set = 1;
2778adfc5217SJeff Kirsher 
2779adfc5217SJeff Kirsher 	new_link_state = sblk->status_attn_bits & event;
2780adfc5217SJeff Kirsher 	old_link_state = sblk->status_attn_bits_ack & event;
2781adfc5217SJeff Kirsher 	if (new_link_state != old_link_state) {
2782adfc5217SJeff Kirsher 		if (new_link_state)
2783adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
2784adfc5217SJeff Kirsher 		else
2785adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
2786adfc5217SJeff Kirsher 	} else
2787adfc5217SJeff Kirsher 		is_set = 0;
2788adfc5217SJeff Kirsher 
2789adfc5217SJeff Kirsher 	return is_set;
2790adfc5217SJeff Kirsher }
2791adfc5217SJeff Kirsher 
2792adfc5217SJeff Kirsher static void
2793adfc5217SJeff Kirsher bnx2_phy_int(struct bnx2 *bp, struct bnx2_napi *bnapi)
2794adfc5217SJeff Kirsher {
2795adfc5217SJeff Kirsher 	spin_lock(&bp->phy_lock);
2796adfc5217SJeff Kirsher 
2797adfc5217SJeff Kirsher 	if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_LINK_STATE))
2798adfc5217SJeff Kirsher 		bnx2_set_link(bp);
2799adfc5217SJeff Kirsher 	if (bnx2_phy_event_is_set(bp, bnapi, STATUS_ATTN_BITS_TIMER_ABORT))
2800adfc5217SJeff Kirsher 		bnx2_set_remote_link(bp);
2801adfc5217SJeff Kirsher 
2802adfc5217SJeff Kirsher 	spin_unlock(&bp->phy_lock);
2803adfc5217SJeff Kirsher 
2804adfc5217SJeff Kirsher }
2805adfc5217SJeff Kirsher 
2806adfc5217SJeff Kirsher static inline u16
2807adfc5217SJeff Kirsher bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
2808adfc5217SJeff Kirsher {
2809adfc5217SJeff Kirsher 	u16 cons;
2810adfc5217SJeff Kirsher 
2811adfc5217SJeff Kirsher 	/* Tell compiler that status block fields can change. */
2812adfc5217SJeff Kirsher 	barrier();
2813adfc5217SJeff Kirsher 	cons = *bnapi->hw_tx_cons_ptr;
2814adfc5217SJeff Kirsher 	barrier();
2815adfc5217SJeff Kirsher 	if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
2816adfc5217SJeff Kirsher 		cons++;
2817adfc5217SJeff Kirsher 	return cons;
2818adfc5217SJeff Kirsher }
2819adfc5217SJeff Kirsher 
2820adfc5217SJeff Kirsher static int
2821adfc5217SJeff Kirsher bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
2822adfc5217SJeff Kirsher {
2823adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
2824adfc5217SJeff Kirsher 	u16 hw_cons, sw_cons, sw_ring_cons;
2825adfc5217SJeff Kirsher 	int tx_pkt = 0, index;
2826adfc5217SJeff Kirsher 	struct netdev_queue *txq;
2827adfc5217SJeff Kirsher 
2828adfc5217SJeff Kirsher 	index = (bnapi - bp->bnx2_napi);
2829adfc5217SJeff Kirsher 	txq = netdev_get_tx_queue(bp->dev, index);
2830adfc5217SJeff Kirsher 
2831adfc5217SJeff Kirsher 	hw_cons = bnx2_get_hw_tx_cons(bnapi);
2832adfc5217SJeff Kirsher 	sw_cons = txr->tx_cons;
2833adfc5217SJeff Kirsher 
2834adfc5217SJeff Kirsher 	while (sw_cons != hw_cons) {
2835adfc5217SJeff Kirsher 		struct sw_tx_bd *tx_buf;
2836adfc5217SJeff Kirsher 		struct sk_buff *skb;
2837adfc5217SJeff Kirsher 		int i, last;
2838adfc5217SJeff Kirsher 
2839adfc5217SJeff Kirsher 		sw_ring_cons = TX_RING_IDX(sw_cons);
2840adfc5217SJeff Kirsher 
2841adfc5217SJeff Kirsher 		tx_buf = &txr->tx_buf_ring[sw_ring_cons];
2842adfc5217SJeff Kirsher 		skb = tx_buf->skb;
2843adfc5217SJeff Kirsher 
2844adfc5217SJeff Kirsher 		/* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */
2845adfc5217SJeff Kirsher 		prefetch(&skb->end);
2846adfc5217SJeff Kirsher 
2847adfc5217SJeff Kirsher 		/* partial BD completions possible with TSO packets */
2848adfc5217SJeff Kirsher 		if (tx_buf->is_gso) {
2849adfc5217SJeff Kirsher 			u16 last_idx, last_ring_idx;
2850adfc5217SJeff Kirsher 
2851adfc5217SJeff Kirsher 			last_idx = sw_cons + tx_buf->nr_frags + 1;
2852adfc5217SJeff Kirsher 			last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
2853adfc5217SJeff Kirsher 			if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
2854adfc5217SJeff Kirsher 				last_idx++;
2855adfc5217SJeff Kirsher 			}
2856adfc5217SJeff Kirsher 			if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) {
2857adfc5217SJeff Kirsher 				break;
2858adfc5217SJeff Kirsher 			}
2859adfc5217SJeff Kirsher 		}
2860adfc5217SJeff Kirsher 
2861adfc5217SJeff Kirsher 		dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
2862adfc5217SJeff Kirsher 			skb_headlen(skb), PCI_DMA_TODEVICE);
2863adfc5217SJeff Kirsher 
2864adfc5217SJeff Kirsher 		tx_buf->skb = NULL;
2865adfc5217SJeff Kirsher 		last = tx_buf->nr_frags;
2866adfc5217SJeff Kirsher 
2867adfc5217SJeff Kirsher 		for (i = 0; i < last; i++) {
2868adfc5217SJeff Kirsher 			sw_cons = NEXT_TX_BD(sw_cons);
2869adfc5217SJeff Kirsher 
2870adfc5217SJeff Kirsher 			dma_unmap_page(&bp->pdev->dev,
2871adfc5217SJeff Kirsher 				dma_unmap_addr(
2872adfc5217SJeff Kirsher 					&txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
2873adfc5217SJeff Kirsher 					mapping),
2874adfc5217SJeff Kirsher 				skb_shinfo(skb)->frags[i].size,
2875adfc5217SJeff Kirsher 				PCI_DMA_TODEVICE);
2876adfc5217SJeff Kirsher 		}
2877adfc5217SJeff Kirsher 
2878adfc5217SJeff Kirsher 		sw_cons = NEXT_TX_BD(sw_cons);
2879adfc5217SJeff Kirsher 
2880adfc5217SJeff Kirsher 		dev_kfree_skb(skb);
2881adfc5217SJeff Kirsher 		tx_pkt++;
2882adfc5217SJeff Kirsher 		if (tx_pkt == budget)
2883adfc5217SJeff Kirsher 			break;
2884adfc5217SJeff Kirsher 
2885adfc5217SJeff Kirsher 		if (hw_cons == sw_cons)
2886adfc5217SJeff Kirsher 			hw_cons = bnx2_get_hw_tx_cons(bnapi);
2887adfc5217SJeff Kirsher 	}
2888adfc5217SJeff Kirsher 
2889adfc5217SJeff Kirsher 	txr->hw_tx_cons = hw_cons;
2890adfc5217SJeff Kirsher 	txr->tx_cons = sw_cons;
2891adfc5217SJeff Kirsher 
2892adfc5217SJeff Kirsher 	/* Need to make the tx_cons update visible to bnx2_start_xmit()
2893adfc5217SJeff Kirsher 	 * before checking for netif_tx_queue_stopped().  Without the
2894adfc5217SJeff Kirsher 	 * memory barrier, there is a small possibility that bnx2_start_xmit()
2895adfc5217SJeff Kirsher 	 * will miss it and cause the queue to be stopped forever.
2896adfc5217SJeff Kirsher 	 */
2897adfc5217SJeff Kirsher 	smp_mb();
2898adfc5217SJeff Kirsher 
2899adfc5217SJeff Kirsher 	if (unlikely(netif_tx_queue_stopped(txq)) &&
2900adfc5217SJeff Kirsher 		     (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
2901adfc5217SJeff Kirsher 		__netif_tx_lock(txq, smp_processor_id());
2902adfc5217SJeff Kirsher 		if ((netif_tx_queue_stopped(txq)) &&
2903adfc5217SJeff Kirsher 		    (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh))
2904adfc5217SJeff Kirsher 			netif_tx_wake_queue(txq);
2905adfc5217SJeff Kirsher 		__netif_tx_unlock(txq);
2906adfc5217SJeff Kirsher 	}
2907adfc5217SJeff Kirsher 
2908adfc5217SJeff Kirsher 	return tx_pkt;
2909adfc5217SJeff Kirsher }
2910adfc5217SJeff Kirsher 
2911adfc5217SJeff Kirsher static void
2912adfc5217SJeff Kirsher bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
2913adfc5217SJeff Kirsher 			struct sk_buff *skb, int count)
2914adfc5217SJeff Kirsher {
2915adfc5217SJeff Kirsher 	struct sw_pg *cons_rx_pg, *prod_rx_pg;
2916adfc5217SJeff Kirsher 	struct rx_bd *cons_bd, *prod_bd;
2917adfc5217SJeff Kirsher 	int i;
2918adfc5217SJeff Kirsher 	u16 hw_prod, prod;
2919adfc5217SJeff Kirsher 	u16 cons = rxr->rx_pg_cons;
2920adfc5217SJeff Kirsher 
2921adfc5217SJeff Kirsher 	cons_rx_pg = &rxr->rx_pg_ring[cons];
2922adfc5217SJeff Kirsher 
2923adfc5217SJeff Kirsher 	/* The caller was unable to allocate a new page to replace the
2924adfc5217SJeff Kirsher 	 * last one in the frags array, so we need to recycle that page
2925adfc5217SJeff Kirsher 	 * and then free the skb.
2926adfc5217SJeff Kirsher 	 */
2927adfc5217SJeff Kirsher 	if (skb) {
2928adfc5217SJeff Kirsher 		struct page *page;
2929adfc5217SJeff Kirsher 		struct skb_shared_info *shinfo;
2930adfc5217SJeff Kirsher 
2931adfc5217SJeff Kirsher 		shinfo = skb_shinfo(skb);
2932adfc5217SJeff Kirsher 		shinfo->nr_frags--;
2933b7b6a688SIan Campbell 		page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]);
2934b7b6a688SIan Campbell 		__skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL);
2935adfc5217SJeff Kirsher 
2936adfc5217SJeff Kirsher 		cons_rx_pg->page = page;
2937adfc5217SJeff Kirsher 		dev_kfree_skb(skb);
2938adfc5217SJeff Kirsher 	}
2939adfc5217SJeff Kirsher 
2940adfc5217SJeff Kirsher 	hw_prod = rxr->rx_pg_prod;
2941adfc5217SJeff Kirsher 
2942adfc5217SJeff Kirsher 	for (i = 0; i < count; i++) {
2943adfc5217SJeff Kirsher 		prod = RX_PG_RING_IDX(hw_prod);
2944adfc5217SJeff Kirsher 
2945adfc5217SJeff Kirsher 		prod_rx_pg = &rxr->rx_pg_ring[prod];
2946adfc5217SJeff Kirsher 		cons_rx_pg = &rxr->rx_pg_ring[cons];
2947adfc5217SJeff Kirsher 		cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
2948adfc5217SJeff Kirsher 		prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
2949adfc5217SJeff Kirsher 
2950adfc5217SJeff Kirsher 		if (prod != cons) {
2951adfc5217SJeff Kirsher 			prod_rx_pg->page = cons_rx_pg->page;
2952adfc5217SJeff Kirsher 			cons_rx_pg->page = NULL;
2953adfc5217SJeff Kirsher 			dma_unmap_addr_set(prod_rx_pg, mapping,
2954adfc5217SJeff Kirsher 				dma_unmap_addr(cons_rx_pg, mapping));
2955adfc5217SJeff Kirsher 
2956adfc5217SJeff Kirsher 			prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
2957adfc5217SJeff Kirsher 			prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
2958adfc5217SJeff Kirsher 
2959adfc5217SJeff Kirsher 		}
2960adfc5217SJeff Kirsher 		cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
2961adfc5217SJeff Kirsher 		hw_prod = NEXT_RX_BD(hw_prod);
2962adfc5217SJeff Kirsher 	}
2963adfc5217SJeff Kirsher 	rxr->rx_pg_prod = hw_prod;
2964adfc5217SJeff Kirsher 	rxr->rx_pg_cons = cons;
2965adfc5217SJeff Kirsher }
2966adfc5217SJeff Kirsher 
2967adfc5217SJeff Kirsher static inline void
2968adfc5217SJeff Kirsher bnx2_reuse_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
2969adfc5217SJeff Kirsher 		  struct sk_buff *skb, u16 cons, u16 prod)
2970adfc5217SJeff Kirsher {
2971adfc5217SJeff Kirsher 	struct sw_bd *cons_rx_buf, *prod_rx_buf;
2972adfc5217SJeff Kirsher 	struct rx_bd *cons_bd, *prod_bd;
2973adfc5217SJeff Kirsher 
2974adfc5217SJeff Kirsher 	cons_rx_buf = &rxr->rx_buf_ring[cons];
2975adfc5217SJeff Kirsher 	prod_rx_buf = &rxr->rx_buf_ring[prod];
2976adfc5217SJeff Kirsher 
2977adfc5217SJeff Kirsher 	dma_sync_single_for_device(&bp->pdev->dev,
2978adfc5217SJeff Kirsher 		dma_unmap_addr(cons_rx_buf, mapping),
2979adfc5217SJeff Kirsher 		BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
2980adfc5217SJeff Kirsher 
2981adfc5217SJeff Kirsher 	rxr->rx_prod_bseq += bp->rx_buf_use_size;
2982adfc5217SJeff Kirsher 
2983adfc5217SJeff Kirsher 	prod_rx_buf->skb = skb;
2984adfc5217SJeff Kirsher 	prod_rx_buf->desc = (struct l2_fhdr *) skb->data;
2985adfc5217SJeff Kirsher 
2986adfc5217SJeff Kirsher 	if (cons == prod)
2987adfc5217SJeff Kirsher 		return;
2988adfc5217SJeff Kirsher 
2989adfc5217SJeff Kirsher 	dma_unmap_addr_set(prod_rx_buf, mapping,
2990adfc5217SJeff Kirsher 			dma_unmap_addr(cons_rx_buf, mapping));
2991adfc5217SJeff Kirsher 
2992adfc5217SJeff Kirsher 	cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
2993adfc5217SJeff Kirsher 	prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
2994adfc5217SJeff Kirsher 	prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
2995adfc5217SJeff Kirsher 	prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
2996adfc5217SJeff Kirsher }
2997adfc5217SJeff Kirsher 
2998adfc5217SJeff Kirsher static int
2999adfc5217SJeff Kirsher bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
3000adfc5217SJeff Kirsher 	    unsigned int len, unsigned int hdr_len, dma_addr_t dma_addr,
3001adfc5217SJeff Kirsher 	    u32 ring_idx)
3002adfc5217SJeff Kirsher {
3003adfc5217SJeff Kirsher 	int err;
3004adfc5217SJeff Kirsher 	u16 prod = ring_idx & 0xffff;
3005adfc5217SJeff Kirsher 
3006adfc5217SJeff Kirsher 	err = bnx2_alloc_rx_skb(bp, rxr, prod, GFP_ATOMIC);
3007adfc5217SJeff Kirsher 	if (unlikely(err)) {
3008adfc5217SJeff Kirsher 		bnx2_reuse_rx_skb(bp, rxr, skb, (u16) (ring_idx >> 16), prod);
3009adfc5217SJeff Kirsher 		if (hdr_len) {
3010adfc5217SJeff Kirsher 			unsigned int raw_len = len + 4;
3011adfc5217SJeff Kirsher 			int pages = PAGE_ALIGN(raw_len - hdr_len) >> PAGE_SHIFT;
3012adfc5217SJeff Kirsher 
3013adfc5217SJeff Kirsher 			bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages);
3014adfc5217SJeff Kirsher 		}
3015adfc5217SJeff Kirsher 		return err;
3016adfc5217SJeff Kirsher 	}
3017adfc5217SJeff Kirsher 
3018adfc5217SJeff Kirsher 	skb_reserve(skb, BNX2_RX_OFFSET);
3019adfc5217SJeff Kirsher 	dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
3020adfc5217SJeff Kirsher 			 PCI_DMA_FROMDEVICE);
3021adfc5217SJeff Kirsher 
3022adfc5217SJeff Kirsher 	if (hdr_len == 0) {
3023adfc5217SJeff Kirsher 		skb_put(skb, len);
3024adfc5217SJeff Kirsher 		return 0;
3025adfc5217SJeff Kirsher 	} else {
3026adfc5217SJeff Kirsher 		unsigned int i, frag_len, frag_size, pages;
3027adfc5217SJeff Kirsher 		struct sw_pg *rx_pg;
3028adfc5217SJeff Kirsher 		u16 pg_cons = rxr->rx_pg_cons;
3029adfc5217SJeff Kirsher 		u16 pg_prod = rxr->rx_pg_prod;
3030adfc5217SJeff Kirsher 
3031adfc5217SJeff Kirsher 		frag_size = len + 4 - hdr_len;
3032adfc5217SJeff Kirsher 		pages = PAGE_ALIGN(frag_size) >> PAGE_SHIFT;
3033adfc5217SJeff Kirsher 		skb_put(skb, hdr_len);
3034adfc5217SJeff Kirsher 
3035adfc5217SJeff Kirsher 		for (i = 0; i < pages; i++) {
3036adfc5217SJeff Kirsher 			dma_addr_t mapping_old;
3037adfc5217SJeff Kirsher 
3038adfc5217SJeff Kirsher 			frag_len = min(frag_size, (unsigned int) PAGE_SIZE);
3039adfc5217SJeff Kirsher 			if (unlikely(frag_len <= 4)) {
3040adfc5217SJeff Kirsher 				unsigned int tail = 4 - frag_len;
3041adfc5217SJeff Kirsher 
3042adfc5217SJeff Kirsher 				rxr->rx_pg_cons = pg_cons;
3043adfc5217SJeff Kirsher 				rxr->rx_pg_prod = pg_prod;
3044adfc5217SJeff Kirsher 				bnx2_reuse_rx_skb_pages(bp, rxr, NULL,
3045adfc5217SJeff Kirsher 							pages - i);
3046adfc5217SJeff Kirsher 				skb->len -= tail;
3047adfc5217SJeff Kirsher 				if (i == 0) {
3048adfc5217SJeff Kirsher 					skb->tail -= tail;
3049adfc5217SJeff Kirsher 				} else {
3050adfc5217SJeff Kirsher 					skb_frag_t *frag =
3051adfc5217SJeff Kirsher 						&skb_shinfo(skb)->frags[i - 1];
3052adfc5217SJeff Kirsher 					frag->size -= tail;
3053adfc5217SJeff Kirsher 					skb->data_len -= tail;
3054adfc5217SJeff Kirsher 					skb->truesize -= tail;
3055adfc5217SJeff Kirsher 				}
3056adfc5217SJeff Kirsher 				return 0;
3057adfc5217SJeff Kirsher 			}
3058adfc5217SJeff Kirsher 			rx_pg = &rxr->rx_pg_ring[pg_cons];
3059adfc5217SJeff Kirsher 
3060adfc5217SJeff Kirsher 			/* Don't unmap yet.  If we're unable to allocate a new
3061adfc5217SJeff Kirsher 			 * page, we need to recycle the page and the DMA addr.
3062adfc5217SJeff Kirsher 			 */
3063adfc5217SJeff Kirsher 			mapping_old = dma_unmap_addr(rx_pg, mapping);
3064adfc5217SJeff Kirsher 			if (i == pages - 1)
3065adfc5217SJeff Kirsher 				frag_len -= 4;
3066adfc5217SJeff Kirsher 
3067adfc5217SJeff Kirsher 			skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len);
3068adfc5217SJeff Kirsher 			rx_pg->page = NULL;
3069adfc5217SJeff Kirsher 
3070adfc5217SJeff Kirsher 			err = bnx2_alloc_rx_page(bp, rxr,
3071adfc5217SJeff Kirsher 						 RX_PG_RING_IDX(pg_prod),
3072adfc5217SJeff Kirsher 						 GFP_ATOMIC);
3073adfc5217SJeff Kirsher 			if (unlikely(err)) {
3074adfc5217SJeff Kirsher 				rxr->rx_pg_cons = pg_cons;
3075adfc5217SJeff Kirsher 				rxr->rx_pg_prod = pg_prod;
3076adfc5217SJeff Kirsher 				bnx2_reuse_rx_skb_pages(bp, rxr, skb,
3077adfc5217SJeff Kirsher 							pages - i);
3078adfc5217SJeff Kirsher 				return err;
3079adfc5217SJeff Kirsher 			}
3080adfc5217SJeff Kirsher 
3081adfc5217SJeff Kirsher 			dma_unmap_page(&bp->pdev->dev, mapping_old,
3082adfc5217SJeff Kirsher 				       PAGE_SIZE, PCI_DMA_FROMDEVICE);
3083adfc5217SJeff Kirsher 
3084adfc5217SJeff Kirsher 			frag_size -= frag_len;
3085adfc5217SJeff Kirsher 			skb->data_len += frag_len;
3086adfc5217SJeff Kirsher 			skb->truesize += frag_len;
3087adfc5217SJeff Kirsher 			skb->len += frag_len;
3088adfc5217SJeff Kirsher 
3089adfc5217SJeff Kirsher 			pg_prod = NEXT_RX_BD(pg_prod);
3090adfc5217SJeff Kirsher 			pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
3091adfc5217SJeff Kirsher 		}
3092adfc5217SJeff Kirsher 		rxr->rx_pg_prod = pg_prod;
3093adfc5217SJeff Kirsher 		rxr->rx_pg_cons = pg_cons;
3094adfc5217SJeff Kirsher 	}
3095adfc5217SJeff Kirsher 	return 0;
3096adfc5217SJeff Kirsher }
3097adfc5217SJeff Kirsher 
3098adfc5217SJeff Kirsher static inline u16
3099adfc5217SJeff Kirsher bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
3100adfc5217SJeff Kirsher {
3101adfc5217SJeff Kirsher 	u16 cons;
3102adfc5217SJeff Kirsher 
3103adfc5217SJeff Kirsher 	/* Tell compiler that status block fields can change. */
3104adfc5217SJeff Kirsher 	barrier();
3105adfc5217SJeff Kirsher 	cons = *bnapi->hw_rx_cons_ptr;
3106adfc5217SJeff Kirsher 	barrier();
3107adfc5217SJeff Kirsher 	if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
3108adfc5217SJeff Kirsher 		cons++;
3109adfc5217SJeff Kirsher 	return cons;
3110adfc5217SJeff Kirsher }
3111adfc5217SJeff Kirsher 
3112adfc5217SJeff Kirsher static int
3113adfc5217SJeff Kirsher bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
3114adfc5217SJeff Kirsher {
3115adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3116adfc5217SJeff Kirsher 	u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
3117adfc5217SJeff Kirsher 	struct l2_fhdr *rx_hdr;
3118adfc5217SJeff Kirsher 	int rx_pkt = 0, pg_ring_used = 0;
3119adfc5217SJeff Kirsher 
3120adfc5217SJeff Kirsher 	hw_cons = bnx2_get_hw_rx_cons(bnapi);
3121adfc5217SJeff Kirsher 	sw_cons = rxr->rx_cons;
3122adfc5217SJeff Kirsher 	sw_prod = rxr->rx_prod;
3123adfc5217SJeff Kirsher 
3124adfc5217SJeff Kirsher 	/* Memory barrier necessary as speculative reads of the rx
3125adfc5217SJeff Kirsher 	 * buffer can be ahead of the index in the status block
3126adfc5217SJeff Kirsher 	 */
3127adfc5217SJeff Kirsher 	rmb();
3128adfc5217SJeff Kirsher 	while (sw_cons != hw_cons) {
3129adfc5217SJeff Kirsher 		unsigned int len, hdr_len;
3130adfc5217SJeff Kirsher 		u32 status;
3131adfc5217SJeff Kirsher 		struct sw_bd *rx_buf, *next_rx_buf;
3132adfc5217SJeff Kirsher 		struct sk_buff *skb;
3133adfc5217SJeff Kirsher 		dma_addr_t dma_addr;
3134adfc5217SJeff Kirsher 
3135adfc5217SJeff Kirsher 		sw_ring_cons = RX_RING_IDX(sw_cons);
3136adfc5217SJeff Kirsher 		sw_ring_prod = RX_RING_IDX(sw_prod);
3137adfc5217SJeff Kirsher 
3138adfc5217SJeff Kirsher 		rx_buf = &rxr->rx_buf_ring[sw_ring_cons];
3139adfc5217SJeff Kirsher 		skb = rx_buf->skb;
3140adfc5217SJeff Kirsher 		prefetchw(skb);
3141adfc5217SJeff Kirsher 
3142adfc5217SJeff Kirsher 		next_rx_buf =
3143adfc5217SJeff Kirsher 			&rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
3144adfc5217SJeff Kirsher 		prefetch(next_rx_buf->desc);
3145adfc5217SJeff Kirsher 
3146adfc5217SJeff Kirsher 		rx_buf->skb = NULL;
3147adfc5217SJeff Kirsher 
3148adfc5217SJeff Kirsher 		dma_addr = dma_unmap_addr(rx_buf, mapping);
3149adfc5217SJeff Kirsher 
3150adfc5217SJeff Kirsher 		dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr,
3151adfc5217SJeff Kirsher 			BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
3152adfc5217SJeff Kirsher 			PCI_DMA_FROMDEVICE);
3153adfc5217SJeff Kirsher 
3154adfc5217SJeff Kirsher 		rx_hdr = rx_buf->desc;
3155adfc5217SJeff Kirsher 		len = rx_hdr->l2_fhdr_pkt_len;
3156adfc5217SJeff Kirsher 		status = rx_hdr->l2_fhdr_status;
3157adfc5217SJeff Kirsher 
3158adfc5217SJeff Kirsher 		hdr_len = 0;
3159adfc5217SJeff Kirsher 		if (status & L2_FHDR_STATUS_SPLIT) {
3160adfc5217SJeff Kirsher 			hdr_len = rx_hdr->l2_fhdr_ip_xsum;
3161adfc5217SJeff Kirsher 			pg_ring_used = 1;
3162adfc5217SJeff Kirsher 		} else if (len > bp->rx_jumbo_thresh) {
3163adfc5217SJeff Kirsher 			hdr_len = bp->rx_jumbo_thresh;
3164adfc5217SJeff Kirsher 			pg_ring_used = 1;
3165adfc5217SJeff Kirsher 		}
3166adfc5217SJeff Kirsher 
3167adfc5217SJeff Kirsher 		if (unlikely(status & (L2_FHDR_ERRORS_BAD_CRC |
3168adfc5217SJeff Kirsher 				       L2_FHDR_ERRORS_PHY_DECODE |
3169adfc5217SJeff Kirsher 				       L2_FHDR_ERRORS_ALIGNMENT |
3170adfc5217SJeff Kirsher 				       L2_FHDR_ERRORS_TOO_SHORT |
3171adfc5217SJeff Kirsher 				       L2_FHDR_ERRORS_GIANT_FRAME))) {
3172adfc5217SJeff Kirsher 
3173adfc5217SJeff Kirsher 			bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
3174adfc5217SJeff Kirsher 					  sw_ring_prod);
3175adfc5217SJeff Kirsher 			if (pg_ring_used) {
3176adfc5217SJeff Kirsher 				int pages;
3177adfc5217SJeff Kirsher 
3178adfc5217SJeff Kirsher 				pages = PAGE_ALIGN(len - hdr_len) >> PAGE_SHIFT;
3179adfc5217SJeff Kirsher 
3180adfc5217SJeff Kirsher 				bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages);
3181adfc5217SJeff Kirsher 			}
3182adfc5217SJeff Kirsher 			goto next_rx;
3183adfc5217SJeff Kirsher 		}
3184adfc5217SJeff Kirsher 
3185adfc5217SJeff Kirsher 		len -= 4;
3186adfc5217SJeff Kirsher 
3187adfc5217SJeff Kirsher 		if (len <= bp->rx_copy_thresh) {
3188adfc5217SJeff Kirsher 			struct sk_buff *new_skb;
3189adfc5217SJeff Kirsher 
3190adfc5217SJeff Kirsher 			new_skb = netdev_alloc_skb(bp->dev, len + 6);
3191adfc5217SJeff Kirsher 			if (new_skb == NULL) {
3192adfc5217SJeff Kirsher 				bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
3193adfc5217SJeff Kirsher 						  sw_ring_prod);
3194adfc5217SJeff Kirsher 				goto next_rx;
3195adfc5217SJeff Kirsher 			}
3196adfc5217SJeff Kirsher 
3197adfc5217SJeff Kirsher 			/* aligned copy */
3198adfc5217SJeff Kirsher 			skb_copy_from_linear_data_offset(skb,
3199adfc5217SJeff Kirsher 							 BNX2_RX_OFFSET - 6,
3200adfc5217SJeff Kirsher 				      new_skb->data, len + 6);
3201adfc5217SJeff Kirsher 			skb_reserve(new_skb, 6);
3202adfc5217SJeff Kirsher 			skb_put(new_skb, len);
3203adfc5217SJeff Kirsher 
3204adfc5217SJeff Kirsher 			bnx2_reuse_rx_skb(bp, rxr, skb,
3205adfc5217SJeff Kirsher 				sw_ring_cons, sw_ring_prod);
3206adfc5217SJeff Kirsher 
3207adfc5217SJeff Kirsher 			skb = new_skb;
3208adfc5217SJeff Kirsher 		} else if (unlikely(bnx2_rx_skb(bp, rxr, skb, len, hdr_len,
3209adfc5217SJeff Kirsher 			   dma_addr, (sw_ring_cons << 16) | sw_ring_prod)))
3210adfc5217SJeff Kirsher 			goto next_rx;
3211adfc5217SJeff Kirsher 
3212adfc5217SJeff Kirsher 		if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
3213adfc5217SJeff Kirsher 		    !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG))
3214adfc5217SJeff Kirsher 			__vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag);
3215adfc5217SJeff Kirsher 
3216adfc5217SJeff Kirsher 		skb->protocol = eth_type_trans(skb, bp->dev);
3217adfc5217SJeff Kirsher 
3218adfc5217SJeff Kirsher 		if ((len > (bp->dev->mtu + ETH_HLEN)) &&
3219adfc5217SJeff Kirsher 			(ntohs(skb->protocol) != 0x8100)) {
3220adfc5217SJeff Kirsher 
3221adfc5217SJeff Kirsher 			dev_kfree_skb(skb);
3222adfc5217SJeff Kirsher 			goto next_rx;
3223adfc5217SJeff Kirsher 
3224adfc5217SJeff Kirsher 		}
3225adfc5217SJeff Kirsher 
3226adfc5217SJeff Kirsher 		skb_checksum_none_assert(skb);
3227adfc5217SJeff Kirsher 		if ((bp->dev->features & NETIF_F_RXCSUM) &&
3228adfc5217SJeff Kirsher 			(status & (L2_FHDR_STATUS_TCP_SEGMENT |
3229adfc5217SJeff Kirsher 			L2_FHDR_STATUS_UDP_DATAGRAM))) {
3230adfc5217SJeff Kirsher 
3231adfc5217SJeff Kirsher 			if (likely((status & (L2_FHDR_ERRORS_TCP_XSUM |
3232adfc5217SJeff Kirsher 					      L2_FHDR_ERRORS_UDP_XSUM)) == 0))
3233adfc5217SJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
3234adfc5217SJeff Kirsher 		}
3235adfc5217SJeff Kirsher 		if ((bp->dev->features & NETIF_F_RXHASH) &&
3236adfc5217SJeff Kirsher 		    ((status & L2_FHDR_STATUS_USE_RXHASH) ==
3237adfc5217SJeff Kirsher 		     L2_FHDR_STATUS_USE_RXHASH))
3238adfc5217SJeff Kirsher 			skb->rxhash = rx_hdr->l2_fhdr_hash;
3239adfc5217SJeff Kirsher 
3240adfc5217SJeff Kirsher 		skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
3241adfc5217SJeff Kirsher 		napi_gro_receive(&bnapi->napi, skb);
3242adfc5217SJeff Kirsher 		rx_pkt++;
3243adfc5217SJeff Kirsher 
3244adfc5217SJeff Kirsher next_rx:
3245adfc5217SJeff Kirsher 		sw_cons = NEXT_RX_BD(sw_cons);
3246adfc5217SJeff Kirsher 		sw_prod = NEXT_RX_BD(sw_prod);
3247adfc5217SJeff Kirsher 
3248adfc5217SJeff Kirsher 		if ((rx_pkt == budget))
3249adfc5217SJeff Kirsher 			break;
3250adfc5217SJeff Kirsher 
3251adfc5217SJeff Kirsher 		/* Refresh hw_cons to see if there is new work */
3252adfc5217SJeff Kirsher 		if (sw_cons == hw_cons) {
3253adfc5217SJeff Kirsher 			hw_cons = bnx2_get_hw_rx_cons(bnapi);
3254adfc5217SJeff Kirsher 			rmb();
3255adfc5217SJeff Kirsher 		}
3256adfc5217SJeff Kirsher 	}
3257adfc5217SJeff Kirsher 	rxr->rx_cons = sw_cons;
3258adfc5217SJeff Kirsher 	rxr->rx_prod = sw_prod;
3259adfc5217SJeff Kirsher 
3260adfc5217SJeff Kirsher 	if (pg_ring_used)
3261adfc5217SJeff Kirsher 		REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
3262adfc5217SJeff Kirsher 
3263adfc5217SJeff Kirsher 	REG_WR16(bp, rxr->rx_bidx_addr, sw_prod);
3264adfc5217SJeff Kirsher 
3265adfc5217SJeff Kirsher 	REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
3266adfc5217SJeff Kirsher 
3267adfc5217SJeff Kirsher 	mmiowb();
3268adfc5217SJeff Kirsher 
3269adfc5217SJeff Kirsher 	return rx_pkt;
3270adfc5217SJeff Kirsher 
3271adfc5217SJeff Kirsher }
3272adfc5217SJeff Kirsher 
3273adfc5217SJeff Kirsher /* MSI ISR - The only difference between this and the INTx ISR
3274adfc5217SJeff Kirsher  * is that the MSI interrupt is always serviced.
3275adfc5217SJeff Kirsher  */
3276adfc5217SJeff Kirsher static irqreturn_t
3277adfc5217SJeff Kirsher bnx2_msi(int irq, void *dev_instance)
3278adfc5217SJeff Kirsher {
3279adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = dev_instance;
3280adfc5217SJeff Kirsher 	struct bnx2 *bp = bnapi->bp;
3281adfc5217SJeff Kirsher 
3282adfc5217SJeff Kirsher 	prefetch(bnapi->status_blk.msi);
3283adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
3284adfc5217SJeff Kirsher 		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
3285adfc5217SJeff Kirsher 		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
3286adfc5217SJeff Kirsher 
3287adfc5217SJeff Kirsher 	/* Return here if interrupt is disabled. */
3288adfc5217SJeff Kirsher 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
3289adfc5217SJeff Kirsher 		return IRQ_HANDLED;
3290adfc5217SJeff Kirsher 
3291adfc5217SJeff Kirsher 	napi_schedule(&bnapi->napi);
3292adfc5217SJeff Kirsher 
3293adfc5217SJeff Kirsher 	return IRQ_HANDLED;
3294adfc5217SJeff Kirsher }
3295adfc5217SJeff Kirsher 
3296adfc5217SJeff Kirsher static irqreturn_t
3297adfc5217SJeff Kirsher bnx2_msi_1shot(int irq, void *dev_instance)
3298adfc5217SJeff Kirsher {
3299adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = dev_instance;
3300adfc5217SJeff Kirsher 	struct bnx2 *bp = bnapi->bp;
3301adfc5217SJeff Kirsher 
3302adfc5217SJeff Kirsher 	prefetch(bnapi->status_blk.msi);
3303adfc5217SJeff Kirsher 
3304adfc5217SJeff Kirsher 	/* Return here if interrupt is disabled. */
3305adfc5217SJeff Kirsher 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
3306adfc5217SJeff Kirsher 		return IRQ_HANDLED;
3307adfc5217SJeff Kirsher 
3308adfc5217SJeff Kirsher 	napi_schedule(&bnapi->napi);
3309adfc5217SJeff Kirsher 
3310adfc5217SJeff Kirsher 	return IRQ_HANDLED;
3311adfc5217SJeff Kirsher }
3312adfc5217SJeff Kirsher 
3313adfc5217SJeff Kirsher static irqreturn_t
3314adfc5217SJeff Kirsher bnx2_interrupt(int irq, void *dev_instance)
3315adfc5217SJeff Kirsher {
3316adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = dev_instance;
3317adfc5217SJeff Kirsher 	struct bnx2 *bp = bnapi->bp;
3318adfc5217SJeff Kirsher 	struct status_block *sblk = bnapi->status_blk.msi;
3319adfc5217SJeff Kirsher 
3320adfc5217SJeff Kirsher 	/* When using INTx, it is possible for the interrupt to arrive
3321adfc5217SJeff Kirsher 	 * at the CPU before the status block posted prior to the
3322adfc5217SJeff Kirsher 	 * interrupt. Reading a register will flush the status block.
3323adfc5217SJeff Kirsher 	 * When using MSI, the MSI message will always complete after
3324adfc5217SJeff Kirsher 	 * the status block write.
3325adfc5217SJeff Kirsher 	 */
3326adfc5217SJeff Kirsher 	if ((sblk->status_idx == bnapi->last_status_idx) &&
3327adfc5217SJeff Kirsher 	    (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
3328adfc5217SJeff Kirsher 	     BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
3329adfc5217SJeff Kirsher 		return IRQ_NONE;
3330adfc5217SJeff Kirsher 
3331adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
3332adfc5217SJeff Kirsher 		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
3333adfc5217SJeff Kirsher 		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
3334adfc5217SJeff Kirsher 
3335adfc5217SJeff Kirsher 	/* Read back to deassert IRQ immediately to avoid too many
3336adfc5217SJeff Kirsher 	 * spurious interrupts.
3337adfc5217SJeff Kirsher 	 */
3338adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
3339adfc5217SJeff Kirsher 
3340adfc5217SJeff Kirsher 	/* Return here if interrupt is shared and is disabled. */
3341adfc5217SJeff Kirsher 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
3342adfc5217SJeff Kirsher 		return IRQ_HANDLED;
3343adfc5217SJeff Kirsher 
3344adfc5217SJeff Kirsher 	if (napi_schedule_prep(&bnapi->napi)) {
3345adfc5217SJeff Kirsher 		bnapi->last_status_idx = sblk->status_idx;
3346adfc5217SJeff Kirsher 		__napi_schedule(&bnapi->napi);
3347adfc5217SJeff Kirsher 	}
3348adfc5217SJeff Kirsher 
3349adfc5217SJeff Kirsher 	return IRQ_HANDLED;
3350adfc5217SJeff Kirsher }
3351adfc5217SJeff Kirsher 
3352adfc5217SJeff Kirsher static inline int
3353adfc5217SJeff Kirsher bnx2_has_fast_work(struct bnx2_napi *bnapi)
3354adfc5217SJeff Kirsher {
3355adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
3356adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3357adfc5217SJeff Kirsher 
3358adfc5217SJeff Kirsher 	if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) ||
3359adfc5217SJeff Kirsher 	    (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
3360adfc5217SJeff Kirsher 		return 1;
3361adfc5217SJeff Kirsher 	return 0;
3362adfc5217SJeff Kirsher }
3363adfc5217SJeff Kirsher 
3364adfc5217SJeff Kirsher #define STATUS_ATTN_EVENTS	(STATUS_ATTN_BITS_LINK_STATE | \
3365adfc5217SJeff Kirsher 				 STATUS_ATTN_BITS_TIMER_ABORT)
3366adfc5217SJeff Kirsher 
3367adfc5217SJeff Kirsher static inline int
3368adfc5217SJeff Kirsher bnx2_has_work(struct bnx2_napi *bnapi)
3369adfc5217SJeff Kirsher {
3370adfc5217SJeff Kirsher 	struct status_block *sblk = bnapi->status_blk.msi;
3371adfc5217SJeff Kirsher 
3372adfc5217SJeff Kirsher 	if (bnx2_has_fast_work(bnapi))
3373adfc5217SJeff Kirsher 		return 1;
3374adfc5217SJeff Kirsher 
3375adfc5217SJeff Kirsher #ifdef BCM_CNIC
3376adfc5217SJeff Kirsher 	if (bnapi->cnic_present && (bnapi->cnic_tag != sblk->status_idx))
3377adfc5217SJeff Kirsher 		return 1;
3378adfc5217SJeff Kirsher #endif
3379adfc5217SJeff Kirsher 
3380adfc5217SJeff Kirsher 	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
3381adfc5217SJeff Kirsher 	    (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
3382adfc5217SJeff Kirsher 		return 1;
3383adfc5217SJeff Kirsher 
3384adfc5217SJeff Kirsher 	return 0;
3385adfc5217SJeff Kirsher }
3386adfc5217SJeff Kirsher 
3387adfc5217SJeff Kirsher static void
3388adfc5217SJeff Kirsher bnx2_chk_missed_msi(struct bnx2 *bp)
3389adfc5217SJeff Kirsher {
3390adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
3391adfc5217SJeff Kirsher 	u32 msi_ctrl;
3392adfc5217SJeff Kirsher 
3393adfc5217SJeff Kirsher 	if (bnx2_has_work(bnapi)) {
3394adfc5217SJeff Kirsher 		msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL);
3395adfc5217SJeff Kirsher 		if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE))
3396adfc5217SJeff Kirsher 			return;
3397adfc5217SJeff Kirsher 
3398adfc5217SJeff Kirsher 		if (bnapi->last_status_idx == bp->idle_chk_status_idx) {
3399adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
3400adfc5217SJeff Kirsher 			       ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
3401adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
3402adfc5217SJeff Kirsher 			bnx2_msi(bp->irq_tbl[0].vector, bnapi);
3403adfc5217SJeff Kirsher 		}
3404adfc5217SJeff Kirsher 	}
3405adfc5217SJeff Kirsher 
3406adfc5217SJeff Kirsher 	bp->idle_chk_status_idx = bnapi->last_status_idx;
3407adfc5217SJeff Kirsher }
3408adfc5217SJeff Kirsher 
3409adfc5217SJeff Kirsher #ifdef BCM_CNIC
3410adfc5217SJeff Kirsher static void bnx2_poll_cnic(struct bnx2 *bp, struct bnx2_napi *bnapi)
3411adfc5217SJeff Kirsher {
3412adfc5217SJeff Kirsher 	struct cnic_ops *c_ops;
3413adfc5217SJeff Kirsher 
3414adfc5217SJeff Kirsher 	if (!bnapi->cnic_present)
3415adfc5217SJeff Kirsher 		return;
3416adfc5217SJeff Kirsher 
3417adfc5217SJeff Kirsher 	rcu_read_lock();
3418adfc5217SJeff Kirsher 	c_ops = rcu_dereference(bp->cnic_ops);
3419adfc5217SJeff Kirsher 	if (c_ops)
3420adfc5217SJeff Kirsher 		bnapi->cnic_tag = c_ops->cnic_handler(bp->cnic_data,
3421adfc5217SJeff Kirsher 						      bnapi->status_blk.msi);
3422adfc5217SJeff Kirsher 	rcu_read_unlock();
3423adfc5217SJeff Kirsher }
3424adfc5217SJeff Kirsher #endif
3425adfc5217SJeff Kirsher 
3426adfc5217SJeff Kirsher static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
3427adfc5217SJeff Kirsher {
3428adfc5217SJeff Kirsher 	struct status_block *sblk = bnapi->status_blk.msi;
3429adfc5217SJeff Kirsher 	u32 status_attn_bits = sblk->status_attn_bits;
3430adfc5217SJeff Kirsher 	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
3431adfc5217SJeff Kirsher 
3432adfc5217SJeff Kirsher 	if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
3433adfc5217SJeff Kirsher 	    (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
3434adfc5217SJeff Kirsher 
3435adfc5217SJeff Kirsher 		bnx2_phy_int(bp, bnapi);
3436adfc5217SJeff Kirsher 
3437adfc5217SJeff Kirsher 		/* This is needed to take care of transient status
3438adfc5217SJeff Kirsher 		 * during link changes.
3439adfc5217SJeff Kirsher 		 */
3440adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_HC_COMMAND,
3441adfc5217SJeff Kirsher 		       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
3442adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_HC_COMMAND);
3443adfc5217SJeff Kirsher 	}
3444adfc5217SJeff Kirsher }
3445adfc5217SJeff Kirsher 
3446adfc5217SJeff Kirsher static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
3447adfc5217SJeff Kirsher 			  int work_done, int budget)
3448adfc5217SJeff Kirsher {
3449adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
3450adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
3451adfc5217SJeff Kirsher 
3452adfc5217SJeff Kirsher 	if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
3453adfc5217SJeff Kirsher 		bnx2_tx_int(bp, bnapi, 0);
3454adfc5217SJeff Kirsher 
3455adfc5217SJeff Kirsher 	if (bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons)
3456adfc5217SJeff Kirsher 		work_done += bnx2_rx_int(bp, bnapi, budget - work_done);
3457adfc5217SJeff Kirsher 
3458adfc5217SJeff Kirsher 	return work_done;
3459adfc5217SJeff Kirsher }
3460adfc5217SJeff Kirsher 
3461adfc5217SJeff Kirsher static int bnx2_poll_msix(struct napi_struct *napi, int budget)
3462adfc5217SJeff Kirsher {
3463adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
3464adfc5217SJeff Kirsher 	struct bnx2 *bp = bnapi->bp;
3465adfc5217SJeff Kirsher 	int work_done = 0;
3466adfc5217SJeff Kirsher 	struct status_block_msix *sblk = bnapi->status_blk.msix;
3467adfc5217SJeff Kirsher 
3468adfc5217SJeff Kirsher 	while (1) {
3469adfc5217SJeff Kirsher 		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
3470adfc5217SJeff Kirsher 		if (unlikely(work_done >= budget))
3471adfc5217SJeff Kirsher 			break;
3472adfc5217SJeff Kirsher 
3473adfc5217SJeff Kirsher 		bnapi->last_status_idx = sblk->status_idx;
3474adfc5217SJeff Kirsher 		/* status idx must be read before checking for more work. */
3475adfc5217SJeff Kirsher 		rmb();
3476adfc5217SJeff Kirsher 		if (likely(!bnx2_has_fast_work(bnapi))) {
3477adfc5217SJeff Kirsher 
3478adfc5217SJeff Kirsher 			napi_complete(napi);
3479adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
3480adfc5217SJeff Kirsher 			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
3481adfc5217SJeff Kirsher 			       bnapi->last_status_idx);
3482adfc5217SJeff Kirsher 			break;
3483adfc5217SJeff Kirsher 		}
3484adfc5217SJeff Kirsher 	}
3485adfc5217SJeff Kirsher 	return work_done;
3486adfc5217SJeff Kirsher }
3487adfc5217SJeff Kirsher 
3488adfc5217SJeff Kirsher static int bnx2_poll(struct napi_struct *napi, int budget)
3489adfc5217SJeff Kirsher {
3490adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
3491adfc5217SJeff Kirsher 	struct bnx2 *bp = bnapi->bp;
3492adfc5217SJeff Kirsher 	int work_done = 0;
3493adfc5217SJeff Kirsher 	struct status_block *sblk = bnapi->status_blk.msi;
3494adfc5217SJeff Kirsher 
3495adfc5217SJeff Kirsher 	while (1) {
3496adfc5217SJeff Kirsher 		bnx2_poll_link(bp, bnapi);
3497adfc5217SJeff Kirsher 
3498adfc5217SJeff Kirsher 		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
3499adfc5217SJeff Kirsher 
3500adfc5217SJeff Kirsher #ifdef BCM_CNIC
3501adfc5217SJeff Kirsher 		bnx2_poll_cnic(bp, bnapi);
3502adfc5217SJeff Kirsher #endif
3503adfc5217SJeff Kirsher 
3504adfc5217SJeff Kirsher 		/* bnapi->last_status_idx is used below to tell the hw how
3505adfc5217SJeff Kirsher 		 * much work has been processed, so we must read it before
3506adfc5217SJeff Kirsher 		 * checking for more work.
3507adfc5217SJeff Kirsher 		 */
3508adfc5217SJeff Kirsher 		bnapi->last_status_idx = sblk->status_idx;
3509adfc5217SJeff Kirsher 
3510adfc5217SJeff Kirsher 		if (unlikely(work_done >= budget))
3511adfc5217SJeff Kirsher 			break;
3512adfc5217SJeff Kirsher 
3513adfc5217SJeff Kirsher 		rmb();
3514adfc5217SJeff Kirsher 		if (likely(!bnx2_has_work(bnapi))) {
3515adfc5217SJeff Kirsher 			napi_complete(napi);
3516adfc5217SJeff Kirsher 			if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
3517adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
3518adfc5217SJeff Kirsher 				       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
3519adfc5217SJeff Kirsher 				       bnapi->last_status_idx);
3520adfc5217SJeff Kirsher 				break;
3521adfc5217SJeff Kirsher 			}
3522adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
3523adfc5217SJeff Kirsher 			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
3524adfc5217SJeff Kirsher 			       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
3525adfc5217SJeff Kirsher 			       bnapi->last_status_idx);
3526adfc5217SJeff Kirsher 
3527adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
3528adfc5217SJeff Kirsher 			       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
3529adfc5217SJeff Kirsher 			       bnapi->last_status_idx);
3530adfc5217SJeff Kirsher 			break;
3531adfc5217SJeff Kirsher 		}
3532adfc5217SJeff Kirsher 	}
3533adfc5217SJeff Kirsher 
3534adfc5217SJeff Kirsher 	return work_done;
3535adfc5217SJeff Kirsher }
3536adfc5217SJeff Kirsher 
3537adfc5217SJeff Kirsher /* Called with rtnl_lock from vlan functions and also netif_tx_lock
3538adfc5217SJeff Kirsher  * from set_multicast.
3539adfc5217SJeff Kirsher  */
3540adfc5217SJeff Kirsher static void
3541adfc5217SJeff Kirsher bnx2_set_rx_mode(struct net_device *dev)
3542adfc5217SJeff Kirsher {
3543adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
3544adfc5217SJeff Kirsher 	u32 rx_mode, sort_mode;
3545adfc5217SJeff Kirsher 	struct netdev_hw_addr *ha;
3546adfc5217SJeff Kirsher 	int i;
3547adfc5217SJeff Kirsher 
3548adfc5217SJeff Kirsher 	if (!netif_running(dev))
3549adfc5217SJeff Kirsher 		return;
3550adfc5217SJeff Kirsher 
3551adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
3552adfc5217SJeff Kirsher 
3553adfc5217SJeff Kirsher 	rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
3554adfc5217SJeff Kirsher 				  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
3555adfc5217SJeff Kirsher 	sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
3556adfc5217SJeff Kirsher 	if (!(dev->features & NETIF_F_HW_VLAN_RX) &&
3557adfc5217SJeff Kirsher 	     (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
3558adfc5217SJeff Kirsher 		rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
3559adfc5217SJeff Kirsher 	if (dev->flags & IFF_PROMISC) {
3560adfc5217SJeff Kirsher 		/* Promiscuous mode. */
3561adfc5217SJeff Kirsher 		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
3562adfc5217SJeff Kirsher 		sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
3563adfc5217SJeff Kirsher 			     BNX2_RPM_SORT_USER0_PROM_VLAN;
3564adfc5217SJeff Kirsher 	}
3565adfc5217SJeff Kirsher 	else if (dev->flags & IFF_ALLMULTI) {
3566adfc5217SJeff Kirsher 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
3567adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
3568adfc5217SJeff Kirsher 			       0xffffffff);
3569adfc5217SJeff Kirsher         	}
3570adfc5217SJeff Kirsher 		sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
3571adfc5217SJeff Kirsher 	}
3572adfc5217SJeff Kirsher 	else {
3573adfc5217SJeff Kirsher 		/* Accept one or more multicast(s). */
3574adfc5217SJeff Kirsher 		u32 mc_filter[NUM_MC_HASH_REGISTERS];
3575adfc5217SJeff Kirsher 		u32 regidx;
3576adfc5217SJeff Kirsher 		u32 bit;
3577adfc5217SJeff Kirsher 		u32 crc;
3578adfc5217SJeff Kirsher 
3579adfc5217SJeff Kirsher 		memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS);
3580adfc5217SJeff Kirsher 
3581adfc5217SJeff Kirsher 		netdev_for_each_mc_addr(ha, dev) {
3582adfc5217SJeff Kirsher 			crc = ether_crc_le(ETH_ALEN, ha->addr);
3583adfc5217SJeff Kirsher 			bit = crc & 0xff;
3584adfc5217SJeff Kirsher 			regidx = (bit & 0xe0) >> 5;
3585adfc5217SJeff Kirsher 			bit &= 0x1f;
3586adfc5217SJeff Kirsher 			mc_filter[regidx] |= (1 << bit);
3587adfc5217SJeff Kirsher 		}
3588adfc5217SJeff Kirsher 
3589adfc5217SJeff Kirsher 		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
3590adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
3591adfc5217SJeff Kirsher 			       mc_filter[i]);
3592adfc5217SJeff Kirsher 		}
3593adfc5217SJeff Kirsher 
3594adfc5217SJeff Kirsher 		sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
3595adfc5217SJeff Kirsher 	}
3596adfc5217SJeff Kirsher 
3597adfc5217SJeff Kirsher 	if (netdev_uc_count(dev) > BNX2_MAX_UNICAST_ADDRESSES) {
3598adfc5217SJeff Kirsher 		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
3599adfc5217SJeff Kirsher 		sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
3600adfc5217SJeff Kirsher 			     BNX2_RPM_SORT_USER0_PROM_VLAN;
3601adfc5217SJeff Kirsher 	} else if (!(dev->flags & IFF_PROMISC)) {
3602adfc5217SJeff Kirsher 		/* Add all entries into to the match filter list */
3603adfc5217SJeff Kirsher 		i = 0;
3604adfc5217SJeff Kirsher 		netdev_for_each_uc_addr(ha, dev) {
3605adfc5217SJeff Kirsher 			bnx2_set_mac_addr(bp, ha->addr,
3606adfc5217SJeff Kirsher 					  i + BNX2_START_UNICAST_ADDRESS_INDEX);
3607adfc5217SJeff Kirsher 			sort_mode |= (1 <<
3608adfc5217SJeff Kirsher 				      (i + BNX2_START_UNICAST_ADDRESS_INDEX));
3609adfc5217SJeff Kirsher 			i++;
3610adfc5217SJeff Kirsher 		}
3611adfc5217SJeff Kirsher 
3612adfc5217SJeff Kirsher 	}
3613adfc5217SJeff Kirsher 
3614adfc5217SJeff Kirsher 	if (rx_mode != bp->rx_mode) {
3615adfc5217SJeff Kirsher 		bp->rx_mode = rx_mode;
3616adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
3617adfc5217SJeff Kirsher 	}
3618adfc5217SJeff Kirsher 
3619adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
3620adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
3621adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
3622adfc5217SJeff Kirsher 
3623adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
3624adfc5217SJeff Kirsher }
3625adfc5217SJeff Kirsher 
36267880b72eSfrançois romieu static int
3627adfc5217SJeff Kirsher check_fw_section(const struct firmware *fw,
3628adfc5217SJeff Kirsher 		 const struct bnx2_fw_file_section *section,
3629adfc5217SJeff Kirsher 		 u32 alignment, bool non_empty)
3630adfc5217SJeff Kirsher {
3631adfc5217SJeff Kirsher 	u32 offset = be32_to_cpu(section->offset);
3632adfc5217SJeff Kirsher 	u32 len = be32_to_cpu(section->len);
3633adfc5217SJeff Kirsher 
3634adfc5217SJeff Kirsher 	if ((offset == 0 && len != 0) || offset >= fw->size || offset & 3)
3635adfc5217SJeff Kirsher 		return -EINVAL;
3636adfc5217SJeff Kirsher 	if ((non_empty && len == 0) || len > fw->size - offset ||
3637adfc5217SJeff Kirsher 	    len & (alignment - 1))
3638adfc5217SJeff Kirsher 		return -EINVAL;
3639adfc5217SJeff Kirsher 	return 0;
3640adfc5217SJeff Kirsher }
3641adfc5217SJeff Kirsher 
36427880b72eSfrançois romieu static int
3643adfc5217SJeff Kirsher check_mips_fw_entry(const struct firmware *fw,
3644adfc5217SJeff Kirsher 		    const struct bnx2_mips_fw_file_entry *entry)
3645adfc5217SJeff Kirsher {
3646adfc5217SJeff Kirsher 	if (check_fw_section(fw, &entry->text, 4, true) ||
3647adfc5217SJeff Kirsher 	    check_fw_section(fw, &entry->data, 4, false) ||
3648adfc5217SJeff Kirsher 	    check_fw_section(fw, &entry->rodata, 4, false))
3649adfc5217SJeff Kirsher 		return -EINVAL;
3650adfc5217SJeff Kirsher 	return 0;
3651adfc5217SJeff Kirsher }
3652adfc5217SJeff Kirsher 
36537880b72eSfrançois romieu static void bnx2_release_firmware(struct bnx2 *bp)
36547880b72eSfrançois romieu {
36557880b72eSfrançois romieu 	if (bp->rv2p_firmware) {
36567880b72eSfrançois romieu 		release_firmware(bp->mips_firmware);
36577880b72eSfrançois romieu 		release_firmware(bp->rv2p_firmware);
36587880b72eSfrançois romieu 		bp->rv2p_firmware = NULL;
36597880b72eSfrançois romieu 	}
36607880b72eSfrançois romieu }
36617880b72eSfrançois romieu 
36627880b72eSfrançois romieu static int bnx2_request_uncached_firmware(struct bnx2 *bp)
3663adfc5217SJeff Kirsher {
3664adfc5217SJeff Kirsher 	const char *mips_fw_file, *rv2p_fw_file;
3665adfc5217SJeff Kirsher 	const struct bnx2_mips_fw_file *mips_fw;
3666adfc5217SJeff Kirsher 	const struct bnx2_rv2p_fw_file *rv2p_fw;
3667adfc5217SJeff Kirsher 	int rc;
3668adfc5217SJeff Kirsher 
3669adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
3670adfc5217SJeff Kirsher 		mips_fw_file = FW_MIPS_FILE_09;
3671adfc5217SJeff Kirsher 		if ((CHIP_ID(bp) == CHIP_ID_5709_A0) ||
3672adfc5217SJeff Kirsher 		    (CHIP_ID(bp) == CHIP_ID_5709_A1))
3673adfc5217SJeff Kirsher 			rv2p_fw_file = FW_RV2P_FILE_09_Ax;
3674adfc5217SJeff Kirsher 		else
3675adfc5217SJeff Kirsher 			rv2p_fw_file = FW_RV2P_FILE_09;
3676adfc5217SJeff Kirsher 	} else {
3677adfc5217SJeff Kirsher 		mips_fw_file = FW_MIPS_FILE_06;
3678adfc5217SJeff Kirsher 		rv2p_fw_file = FW_RV2P_FILE_06;
3679adfc5217SJeff Kirsher 	}
3680adfc5217SJeff Kirsher 
3681adfc5217SJeff Kirsher 	rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
3682adfc5217SJeff Kirsher 	if (rc) {
3683adfc5217SJeff Kirsher 		pr_err("Can't load firmware file \"%s\"\n", mips_fw_file);
36847880b72eSfrançois romieu 		goto out;
3685adfc5217SJeff Kirsher 	}
3686adfc5217SJeff Kirsher 
3687adfc5217SJeff Kirsher 	rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
3688adfc5217SJeff Kirsher 	if (rc) {
3689adfc5217SJeff Kirsher 		pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file);
36907880b72eSfrançois romieu 		goto err_release_mips_firmware;
3691adfc5217SJeff Kirsher 	}
3692adfc5217SJeff Kirsher 	mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
3693adfc5217SJeff Kirsher 	rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
3694adfc5217SJeff Kirsher 	if (bp->mips_firmware->size < sizeof(*mips_fw) ||
3695adfc5217SJeff Kirsher 	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->com) ||
3696adfc5217SJeff Kirsher 	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->cp) ||
3697adfc5217SJeff Kirsher 	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) ||
3698adfc5217SJeff Kirsher 	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
3699adfc5217SJeff Kirsher 	    check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
3700adfc5217SJeff Kirsher 		pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file);
37017880b72eSfrançois romieu 		rc = -EINVAL;
37027880b72eSfrançois romieu 		goto err_release_firmware;
3703adfc5217SJeff Kirsher 	}
3704adfc5217SJeff Kirsher 	if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
3705adfc5217SJeff Kirsher 	    check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
3706adfc5217SJeff Kirsher 	    check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
3707adfc5217SJeff Kirsher 		pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file);
37087880b72eSfrançois romieu 		rc = -EINVAL;
37097880b72eSfrançois romieu 		goto err_release_firmware;
37107880b72eSfrançois romieu 	}
37117880b72eSfrançois romieu out:
37127880b72eSfrançois romieu 	return rc;
37137880b72eSfrançois romieu 
37147880b72eSfrançois romieu err_release_firmware:
37157880b72eSfrançois romieu 	release_firmware(bp->rv2p_firmware);
37167880b72eSfrançois romieu 	bp->rv2p_firmware = NULL;
37177880b72eSfrançois romieu err_release_mips_firmware:
37187880b72eSfrançois romieu 	release_firmware(bp->mips_firmware);
37197880b72eSfrançois romieu 	goto out;
3720adfc5217SJeff Kirsher }
3721adfc5217SJeff Kirsher 
37227880b72eSfrançois romieu static int bnx2_request_firmware(struct bnx2 *bp)
37237880b72eSfrançois romieu {
37247880b72eSfrançois romieu 	return bp->rv2p_firmware ? 0 : bnx2_request_uncached_firmware(bp);
3725adfc5217SJeff Kirsher }
3726adfc5217SJeff Kirsher 
3727adfc5217SJeff Kirsher static u32
3728adfc5217SJeff Kirsher rv2p_fw_fixup(u32 rv2p_proc, int idx, u32 loc, u32 rv2p_code)
3729adfc5217SJeff Kirsher {
3730adfc5217SJeff Kirsher 	switch (idx) {
3731adfc5217SJeff Kirsher 	case RV2P_P1_FIXUP_PAGE_SIZE_IDX:
3732adfc5217SJeff Kirsher 		rv2p_code &= ~RV2P_BD_PAGE_SIZE_MSK;
3733adfc5217SJeff Kirsher 		rv2p_code |= RV2P_BD_PAGE_SIZE;
3734adfc5217SJeff Kirsher 		break;
3735adfc5217SJeff Kirsher 	}
3736adfc5217SJeff Kirsher 	return rv2p_code;
3737adfc5217SJeff Kirsher }
3738adfc5217SJeff Kirsher 
3739adfc5217SJeff Kirsher static int
3740adfc5217SJeff Kirsher load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
3741adfc5217SJeff Kirsher 	     const struct bnx2_rv2p_fw_file_entry *fw_entry)
3742adfc5217SJeff Kirsher {
3743adfc5217SJeff Kirsher 	u32 rv2p_code_len, file_offset;
3744adfc5217SJeff Kirsher 	__be32 *rv2p_code;
3745adfc5217SJeff Kirsher 	int i;
3746adfc5217SJeff Kirsher 	u32 val, cmd, addr;
3747adfc5217SJeff Kirsher 
3748adfc5217SJeff Kirsher 	rv2p_code_len = be32_to_cpu(fw_entry->rv2p.len);
3749adfc5217SJeff Kirsher 	file_offset = be32_to_cpu(fw_entry->rv2p.offset);
3750adfc5217SJeff Kirsher 
3751adfc5217SJeff Kirsher 	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
3752adfc5217SJeff Kirsher 
3753adfc5217SJeff Kirsher 	if (rv2p_proc == RV2P_PROC1) {
3754adfc5217SJeff Kirsher 		cmd = BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
3755adfc5217SJeff Kirsher 		addr = BNX2_RV2P_PROC1_ADDR_CMD;
3756adfc5217SJeff Kirsher 	} else {
3757adfc5217SJeff Kirsher 		cmd = BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
3758adfc5217SJeff Kirsher 		addr = BNX2_RV2P_PROC2_ADDR_CMD;
3759adfc5217SJeff Kirsher 	}
3760adfc5217SJeff Kirsher 
3761adfc5217SJeff Kirsher 	for (i = 0; i < rv2p_code_len; i += 8) {
3762adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
3763adfc5217SJeff Kirsher 		rv2p_code++;
3764adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
3765adfc5217SJeff Kirsher 		rv2p_code++;
3766adfc5217SJeff Kirsher 
3767adfc5217SJeff Kirsher 		val = (i / 8) | cmd;
3768adfc5217SJeff Kirsher 		REG_WR(bp, addr, val);
3769adfc5217SJeff Kirsher 	}
3770adfc5217SJeff Kirsher 
3771adfc5217SJeff Kirsher 	rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
3772adfc5217SJeff Kirsher 	for (i = 0; i < 8; i++) {
3773adfc5217SJeff Kirsher 		u32 loc, code;
3774adfc5217SJeff Kirsher 
3775adfc5217SJeff Kirsher 		loc = be32_to_cpu(fw_entry->fixup[i]);
3776adfc5217SJeff Kirsher 		if (loc && ((loc * 4) < rv2p_code_len)) {
3777adfc5217SJeff Kirsher 			code = be32_to_cpu(*(rv2p_code + loc - 1));
3778adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
3779adfc5217SJeff Kirsher 			code = be32_to_cpu(*(rv2p_code + loc));
3780adfc5217SJeff Kirsher 			code = rv2p_fw_fixup(rv2p_proc, i, loc, code);
3781adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RV2P_INSTR_LOW, code);
3782adfc5217SJeff Kirsher 
3783adfc5217SJeff Kirsher 			val = (loc / 2) | cmd;
3784adfc5217SJeff Kirsher 			REG_WR(bp, addr, val);
3785adfc5217SJeff Kirsher 		}
3786adfc5217SJeff Kirsher 	}
3787adfc5217SJeff Kirsher 
3788adfc5217SJeff Kirsher 	/* Reset the processor, un-stall is done later. */
3789adfc5217SJeff Kirsher 	if (rv2p_proc == RV2P_PROC1) {
3790adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
3791adfc5217SJeff Kirsher 	}
3792adfc5217SJeff Kirsher 	else {
3793adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
3794adfc5217SJeff Kirsher 	}
3795adfc5217SJeff Kirsher 
3796adfc5217SJeff Kirsher 	return 0;
3797adfc5217SJeff Kirsher }
3798adfc5217SJeff Kirsher 
3799adfc5217SJeff Kirsher static int
3800adfc5217SJeff Kirsher load_cpu_fw(struct bnx2 *bp, const struct cpu_reg *cpu_reg,
3801adfc5217SJeff Kirsher 	    const struct bnx2_mips_fw_file_entry *fw_entry)
3802adfc5217SJeff Kirsher {
3803adfc5217SJeff Kirsher 	u32 addr, len, file_offset;
3804adfc5217SJeff Kirsher 	__be32 *data;
3805adfc5217SJeff Kirsher 	u32 offset;
3806adfc5217SJeff Kirsher 	u32 val;
3807adfc5217SJeff Kirsher 
3808adfc5217SJeff Kirsher 	/* Halt the CPU. */
3809adfc5217SJeff Kirsher 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
3810adfc5217SJeff Kirsher 	val |= cpu_reg->mode_value_halt;
3811adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
3812adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
3813adfc5217SJeff Kirsher 
3814adfc5217SJeff Kirsher 	/* Load the Text area. */
3815adfc5217SJeff Kirsher 	addr = be32_to_cpu(fw_entry->text.addr);
3816adfc5217SJeff Kirsher 	len = be32_to_cpu(fw_entry->text.len);
3817adfc5217SJeff Kirsher 	file_offset = be32_to_cpu(fw_entry->text.offset);
3818adfc5217SJeff Kirsher 	data = (__be32 *)(bp->mips_firmware->data + file_offset);
3819adfc5217SJeff Kirsher 
3820adfc5217SJeff Kirsher 	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
3821adfc5217SJeff Kirsher 	if (len) {
3822adfc5217SJeff Kirsher 		int j;
3823adfc5217SJeff Kirsher 
3824adfc5217SJeff Kirsher 		for (j = 0; j < (len / 4); j++, offset += 4)
3825adfc5217SJeff Kirsher 			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
3826adfc5217SJeff Kirsher 	}
3827adfc5217SJeff Kirsher 
3828adfc5217SJeff Kirsher 	/* Load the Data area. */
3829adfc5217SJeff Kirsher 	addr = be32_to_cpu(fw_entry->data.addr);
3830adfc5217SJeff Kirsher 	len = be32_to_cpu(fw_entry->data.len);
3831adfc5217SJeff Kirsher 	file_offset = be32_to_cpu(fw_entry->data.offset);
3832adfc5217SJeff Kirsher 	data = (__be32 *)(bp->mips_firmware->data + file_offset);
3833adfc5217SJeff Kirsher 
3834adfc5217SJeff Kirsher 	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
3835adfc5217SJeff Kirsher 	if (len) {
3836adfc5217SJeff Kirsher 		int j;
3837adfc5217SJeff Kirsher 
3838adfc5217SJeff Kirsher 		for (j = 0; j < (len / 4); j++, offset += 4)
3839adfc5217SJeff Kirsher 			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
3840adfc5217SJeff Kirsher 	}
3841adfc5217SJeff Kirsher 
3842adfc5217SJeff Kirsher 	/* Load the Read-Only area. */
3843adfc5217SJeff Kirsher 	addr = be32_to_cpu(fw_entry->rodata.addr);
3844adfc5217SJeff Kirsher 	len = be32_to_cpu(fw_entry->rodata.len);
3845adfc5217SJeff Kirsher 	file_offset = be32_to_cpu(fw_entry->rodata.offset);
3846adfc5217SJeff Kirsher 	data = (__be32 *)(bp->mips_firmware->data + file_offset);
3847adfc5217SJeff Kirsher 
3848adfc5217SJeff Kirsher 	offset = cpu_reg->spad_base + (addr - cpu_reg->mips_view_base);
3849adfc5217SJeff Kirsher 	if (len) {
3850adfc5217SJeff Kirsher 		int j;
3851adfc5217SJeff Kirsher 
3852adfc5217SJeff Kirsher 		for (j = 0; j < (len / 4); j++, offset += 4)
3853adfc5217SJeff Kirsher 			bnx2_reg_wr_ind(bp, offset, be32_to_cpu(data[j]));
3854adfc5217SJeff Kirsher 	}
3855adfc5217SJeff Kirsher 
3856adfc5217SJeff Kirsher 	/* Clear the pre-fetch instruction. */
3857adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->inst, 0);
3858adfc5217SJeff Kirsher 
3859adfc5217SJeff Kirsher 	val = be32_to_cpu(fw_entry->start_addr);
3860adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->pc, val);
3861adfc5217SJeff Kirsher 
3862adfc5217SJeff Kirsher 	/* Start the CPU. */
3863adfc5217SJeff Kirsher 	val = bnx2_reg_rd_ind(bp, cpu_reg->mode);
3864adfc5217SJeff Kirsher 	val &= ~cpu_reg->mode_value_halt;
3865adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->state, cpu_reg->state_value_clear);
3866adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, cpu_reg->mode, val);
3867adfc5217SJeff Kirsher 
3868adfc5217SJeff Kirsher 	return 0;
3869adfc5217SJeff Kirsher }
3870adfc5217SJeff Kirsher 
3871adfc5217SJeff Kirsher static int
3872adfc5217SJeff Kirsher bnx2_init_cpus(struct bnx2 *bp)
3873adfc5217SJeff Kirsher {
3874adfc5217SJeff Kirsher 	const struct bnx2_mips_fw_file *mips_fw =
3875adfc5217SJeff Kirsher 		(const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
3876adfc5217SJeff Kirsher 	const struct bnx2_rv2p_fw_file *rv2p_fw =
3877adfc5217SJeff Kirsher 		(const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
3878adfc5217SJeff Kirsher 	int rc;
3879adfc5217SJeff Kirsher 
3880adfc5217SJeff Kirsher 	/* Initialize the RV2P processor. */
3881adfc5217SJeff Kirsher 	load_rv2p_fw(bp, RV2P_PROC1, &rv2p_fw->proc1);
3882adfc5217SJeff Kirsher 	load_rv2p_fw(bp, RV2P_PROC2, &rv2p_fw->proc2);
3883adfc5217SJeff Kirsher 
3884adfc5217SJeff Kirsher 	/* Initialize the RX Processor. */
3885adfc5217SJeff Kirsher 	rc = load_cpu_fw(bp, &cpu_reg_rxp, &mips_fw->rxp);
3886adfc5217SJeff Kirsher 	if (rc)
3887adfc5217SJeff Kirsher 		goto init_cpu_err;
3888adfc5217SJeff Kirsher 
3889adfc5217SJeff Kirsher 	/* Initialize the TX Processor. */
3890adfc5217SJeff Kirsher 	rc = load_cpu_fw(bp, &cpu_reg_txp, &mips_fw->txp);
3891adfc5217SJeff Kirsher 	if (rc)
3892adfc5217SJeff Kirsher 		goto init_cpu_err;
3893adfc5217SJeff Kirsher 
3894adfc5217SJeff Kirsher 	/* Initialize the TX Patch-up Processor. */
3895adfc5217SJeff Kirsher 	rc = load_cpu_fw(bp, &cpu_reg_tpat, &mips_fw->tpat);
3896adfc5217SJeff Kirsher 	if (rc)
3897adfc5217SJeff Kirsher 		goto init_cpu_err;
3898adfc5217SJeff Kirsher 
3899adfc5217SJeff Kirsher 	/* Initialize the Completion Processor. */
3900adfc5217SJeff Kirsher 	rc = load_cpu_fw(bp, &cpu_reg_com, &mips_fw->com);
3901adfc5217SJeff Kirsher 	if (rc)
3902adfc5217SJeff Kirsher 		goto init_cpu_err;
3903adfc5217SJeff Kirsher 
3904adfc5217SJeff Kirsher 	/* Initialize the Command Processor. */
3905adfc5217SJeff Kirsher 	rc = load_cpu_fw(bp, &cpu_reg_cp, &mips_fw->cp);
3906adfc5217SJeff Kirsher 
3907adfc5217SJeff Kirsher init_cpu_err:
3908adfc5217SJeff Kirsher 	return rc;
3909adfc5217SJeff Kirsher }
3910adfc5217SJeff Kirsher 
3911adfc5217SJeff Kirsher static int
3912adfc5217SJeff Kirsher bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
3913adfc5217SJeff Kirsher {
3914adfc5217SJeff Kirsher 	u16 pmcsr;
3915adfc5217SJeff Kirsher 
3916adfc5217SJeff Kirsher 	pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
3917adfc5217SJeff Kirsher 
3918adfc5217SJeff Kirsher 	switch (state) {
3919adfc5217SJeff Kirsher 	case PCI_D0: {
3920adfc5217SJeff Kirsher 		u32 val;
3921adfc5217SJeff Kirsher 
3922adfc5217SJeff Kirsher 		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
3923adfc5217SJeff Kirsher 			(pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
3924adfc5217SJeff Kirsher 			PCI_PM_CTRL_PME_STATUS);
3925adfc5217SJeff Kirsher 
3926adfc5217SJeff Kirsher 		if (pmcsr & PCI_PM_CTRL_STATE_MASK)
3927adfc5217SJeff Kirsher 			/* delay required during transition out of D3hot */
3928adfc5217SJeff Kirsher 			msleep(20);
3929adfc5217SJeff Kirsher 
3930adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_EMAC_MODE);
3931adfc5217SJeff Kirsher 		val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
3932adfc5217SJeff Kirsher 		val &= ~BNX2_EMAC_MODE_MPKT;
3933adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_MODE, val);
3934adfc5217SJeff Kirsher 
3935adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_RPM_CONFIG);
3936adfc5217SJeff Kirsher 		val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
3937adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RPM_CONFIG, val);
3938adfc5217SJeff Kirsher 		break;
3939adfc5217SJeff Kirsher 	}
3940adfc5217SJeff Kirsher 	case PCI_D3hot: {
3941adfc5217SJeff Kirsher 		int i;
3942adfc5217SJeff Kirsher 		u32 val, wol_msg;
3943adfc5217SJeff Kirsher 
3944adfc5217SJeff Kirsher 		if (bp->wol) {
3945adfc5217SJeff Kirsher 			u32 advertising;
3946adfc5217SJeff Kirsher 			u8 autoneg;
3947adfc5217SJeff Kirsher 
3948adfc5217SJeff Kirsher 			autoneg = bp->autoneg;
3949adfc5217SJeff Kirsher 			advertising = bp->advertising;
3950adfc5217SJeff Kirsher 
3951adfc5217SJeff Kirsher 			if (bp->phy_port == PORT_TP) {
3952adfc5217SJeff Kirsher 				bp->autoneg = AUTONEG_SPEED;
3953adfc5217SJeff Kirsher 				bp->advertising = ADVERTISED_10baseT_Half |
3954adfc5217SJeff Kirsher 					ADVERTISED_10baseT_Full |
3955adfc5217SJeff Kirsher 					ADVERTISED_100baseT_Half |
3956adfc5217SJeff Kirsher 					ADVERTISED_100baseT_Full |
3957adfc5217SJeff Kirsher 					ADVERTISED_Autoneg;
3958adfc5217SJeff Kirsher 			}
3959adfc5217SJeff Kirsher 
3960adfc5217SJeff Kirsher 			spin_lock_bh(&bp->phy_lock);
3961adfc5217SJeff Kirsher 			bnx2_setup_phy(bp, bp->phy_port);
3962adfc5217SJeff Kirsher 			spin_unlock_bh(&bp->phy_lock);
3963adfc5217SJeff Kirsher 
3964adfc5217SJeff Kirsher 			bp->autoneg = autoneg;
3965adfc5217SJeff Kirsher 			bp->advertising = advertising;
3966adfc5217SJeff Kirsher 
3967adfc5217SJeff Kirsher 			bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
3968adfc5217SJeff Kirsher 
3969adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_EMAC_MODE);
3970adfc5217SJeff Kirsher 
3971adfc5217SJeff Kirsher 			/* Enable port mode. */
3972adfc5217SJeff Kirsher 			val &= ~BNX2_EMAC_MODE_PORT;
3973adfc5217SJeff Kirsher 			val |= BNX2_EMAC_MODE_MPKT_RCVD |
3974adfc5217SJeff Kirsher 			       BNX2_EMAC_MODE_ACPI_RCVD |
3975adfc5217SJeff Kirsher 			       BNX2_EMAC_MODE_MPKT;
3976adfc5217SJeff Kirsher 			if (bp->phy_port == PORT_TP)
3977adfc5217SJeff Kirsher 				val |= BNX2_EMAC_MODE_PORT_MII;
3978adfc5217SJeff Kirsher 			else {
3979adfc5217SJeff Kirsher 				val |= BNX2_EMAC_MODE_PORT_GMII;
3980adfc5217SJeff Kirsher 				if (bp->line_speed == SPEED_2500)
3981adfc5217SJeff Kirsher 					val |= BNX2_EMAC_MODE_25G_MODE;
3982adfc5217SJeff Kirsher 			}
3983adfc5217SJeff Kirsher 
3984adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_EMAC_MODE, val);
3985adfc5217SJeff Kirsher 
3986adfc5217SJeff Kirsher 			/* receive all multicast */
3987adfc5217SJeff Kirsher 			for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
3988adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
3989adfc5217SJeff Kirsher 				       0xffffffff);
3990adfc5217SJeff Kirsher 			}
3991adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_EMAC_RX_MODE,
3992adfc5217SJeff Kirsher 			       BNX2_EMAC_RX_MODE_SORT_MODE);
3993adfc5217SJeff Kirsher 
3994adfc5217SJeff Kirsher 			val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
3995adfc5217SJeff Kirsher 			      BNX2_RPM_SORT_USER0_MC_EN;
3996adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
3997adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RPM_SORT_USER0, val);
3998adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RPM_SORT_USER0, val |
3999adfc5217SJeff Kirsher 			       BNX2_RPM_SORT_USER0_ENA);
4000adfc5217SJeff Kirsher 
4001adfc5217SJeff Kirsher 			/* Need to enable EMAC and RPM for WOL. */
4002adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
4003adfc5217SJeff Kirsher 			       BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
4004adfc5217SJeff Kirsher 			       BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
4005adfc5217SJeff Kirsher 			       BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
4006adfc5217SJeff Kirsher 
4007adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_RPM_CONFIG);
4008adfc5217SJeff Kirsher 			val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
4009adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_RPM_CONFIG, val);
4010adfc5217SJeff Kirsher 
4011adfc5217SJeff Kirsher 			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
4012adfc5217SJeff Kirsher 		}
4013adfc5217SJeff Kirsher 		else {
4014adfc5217SJeff Kirsher 			wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
4015adfc5217SJeff Kirsher 		}
4016adfc5217SJeff Kirsher 
4017adfc5217SJeff Kirsher 		if (!(bp->flags & BNX2_FLAG_NO_WOL))
4018adfc5217SJeff Kirsher 			bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg,
4019adfc5217SJeff Kirsher 				     1, 0);
4020adfc5217SJeff Kirsher 
4021adfc5217SJeff Kirsher 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
4022adfc5217SJeff Kirsher 		if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
4023adfc5217SJeff Kirsher 		    (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
4024adfc5217SJeff Kirsher 
4025adfc5217SJeff Kirsher 			if (bp->wol)
4026adfc5217SJeff Kirsher 				pmcsr |= 3;
4027adfc5217SJeff Kirsher 		}
4028adfc5217SJeff Kirsher 		else {
4029adfc5217SJeff Kirsher 			pmcsr |= 3;
4030adfc5217SJeff Kirsher 		}
4031adfc5217SJeff Kirsher 		if (bp->wol) {
4032adfc5217SJeff Kirsher 			pmcsr |= PCI_PM_CTRL_PME_ENABLE;
4033adfc5217SJeff Kirsher 		}
4034adfc5217SJeff Kirsher 		pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
4035adfc5217SJeff Kirsher 				      pmcsr);
4036adfc5217SJeff Kirsher 
4037adfc5217SJeff Kirsher 		/* No more memory access after this point until
4038adfc5217SJeff Kirsher 		 * device is brought back to D0.
4039adfc5217SJeff Kirsher 		 */
4040adfc5217SJeff Kirsher 		udelay(50);
4041adfc5217SJeff Kirsher 		break;
4042adfc5217SJeff Kirsher 	}
4043adfc5217SJeff Kirsher 	default:
4044adfc5217SJeff Kirsher 		return -EINVAL;
4045adfc5217SJeff Kirsher 	}
4046adfc5217SJeff Kirsher 	return 0;
4047adfc5217SJeff Kirsher }
4048adfc5217SJeff Kirsher 
4049adfc5217SJeff Kirsher static int
4050adfc5217SJeff Kirsher bnx2_acquire_nvram_lock(struct bnx2 *bp)
4051adfc5217SJeff Kirsher {
4052adfc5217SJeff Kirsher 	u32 val;
4053adfc5217SJeff Kirsher 	int j;
4054adfc5217SJeff Kirsher 
4055adfc5217SJeff Kirsher 	/* Request access to the flash interface. */
4056adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
4057adfc5217SJeff Kirsher 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4058adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_NVM_SW_ARB);
4059adfc5217SJeff Kirsher 		if (val & BNX2_NVM_SW_ARB_ARB_ARB2)
4060adfc5217SJeff Kirsher 			break;
4061adfc5217SJeff Kirsher 
4062adfc5217SJeff Kirsher 		udelay(5);
4063adfc5217SJeff Kirsher 	}
4064adfc5217SJeff Kirsher 
4065adfc5217SJeff Kirsher 	if (j >= NVRAM_TIMEOUT_COUNT)
4066adfc5217SJeff Kirsher 		return -EBUSY;
4067adfc5217SJeff Kirsher 
4068adfc5217SJeff Kirsher 	return 0;
4069adfc5217SJeff Kirsher }
4070adfc5217SJeff Kirsher 
4071adfc5217SJeff Kirsher static int
4072adfc5217SJeff Kirsher bnx2_release_nvram_lock(struct bnx2 *bp)
4073adfc5217SJeff Kirsher {
4074adfc5217SJeff Kirsher 	int j;
4075adfc5217SJeff Kirsher 	u32 val;
4076adfc5217SJeff Kirsher 
4077adfc5217SJeff Kirsher 	/* Relinquish nvram interface. */
4078adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
4079adfc5217SJeff Kirsher 
4080adfc5217SJeff Kirsher 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4081adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_NVM_SW_ARB);
4082adfc5217SJeff Kirsher 		if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2))
4083adfc5217SJeff Kirsher 			break;
4084adfc5217SJeff Kirsher 
4085adfc5217SJeff Kirsher 		udelay(5);
4086adfc5217SJeff Kirsher 	}
4087adfc5217SJeff Kirsher 
4088adfc5217SJeff Kirsher 	if (j >= NVRAM_TIMEOUT_COUNT)
4089adfc5217SJeff Kirsher 		return -EBUSY;
4090adfc5217SJeff Kirsher 
4091adfc5217SJeff Kirsher 	return 0;
4092adfc5217SJeff Kirsher }
4093adfc5217SJeff Kirsher 
4094adfc5217SJeff Kirsher 
4095adfc5217SJeff Kirsher static int
4096adfc5217SJeff Kirsher bnx2_enable_nvram_write(struct bnx2 *bp)
4097adfc5217SJeff Kirsher {
4098adfc5217SJeff Kirsher 	u32 val;
4099adfc5217SJeff Kirsher 
4100adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_MISC_CFG);
4101adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
4102adfc5217SJeff Kirsher 
4103adfc5217SJeff Kirsher 	if (bp->flash_info->flags & BNX2_NV_WREN) {
4104adfc5217SJeff Kirsher 		int j;
4105adfc5217SJeff Kirsher 
4106adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
4107adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_NVM_COMMAND,
4108adfc5217SJeff Kirsher 		       BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
4109adfc5217SJeff Kirsher 
4110adfc5217SJeff Kirsher 		for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4111adfc5217SJeff Kirsher 			udelay(5);
4112adfc5217SJeff Kirsher 
4113adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_NVM_COMMAND);
4114adfc5217SJeff Kirsher 			if (val & BNX2_NVM_COMMAND_DONE)
4115adfc5217SJeff Kirsher 				break;
4116adfc5217SJeff Kirsher 		}
4117adfc5217SJeff Kirsher 
4118adfc5217SJeff Kirsher 		if (j >= NVRAM_TIMEOUT_COUNT)
4119adfc5217SJeff Kirsher 			return -EBUSY;
4120adfc5217SJeff Kirsher 	}
4121adfc5217SJeff Kirsher 	return 0;
4122adfc5217SJeff Kirsher }
4123adfc5217SJeff Kirsher 
4124adfc5217SJeff Kirsher static void
4125adfc5217SJeff Kirsher bnx2_disable_nvram_write(struct bnx2 *bp)
4126adfc5217SJeff Kirsher {
4127adfc5217SJeff Kirsher 	u32 val;
4128adfc5217SJeff Kirsher 
4129adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_MISC_CFG);
4130adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
4131adfc5217SJeff Kirsher }
4132adfc5217SJeff Kirsher 
4133adfc5217SJeff Kirsher 
4134adfc5217SJeff Kirsher static void
4135adfc5217SJeff Kirsher bnx2_enable_nvram_access(struct bnx2 *bp)
4136adfc5217SJeff Kirsher {
4137adfc5217SJeff Kirsher 	u32 val;
4138adfc5217SJeff Kirsher 
4139adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
4140adfc5217SJeff Kirsher 	/* Enable both bits, even on read. */
4141adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
4142adfc5217SJeff Kirsher 	       val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
4143adfc5217SJeff Kirsher }
4144adfc5217SJeff Kirsher 
4145adfc5217SJeff Kirsher static void
4146adfc5217SJeff Kirsher bnx2_disable_nvram_access(struct bnx2 *bp)
4147adfc5217SJeff Kirsher {
4148adfc5217SJeff Kirsher 	u32 val;
4149adfc5217SJeff Kirsher 
4150adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
4151adfc5217SJeff Kirsher 	/* Disable both bits, even after read. */
4152adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
4153adfc5217SJeff Kirsher 		val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
4154adfc5217SJeff Kirsher 			BNX2_NVM_ACCESS_ENABLE_WR_EN));
4155adfc5217SJeff Kirsher }
4156adfc5217SJeff Kirsher 
4157adfc5217SJeff Kirsher static int
4158adfc5217SJeff Kirsher bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
4159adfc5217SJeff Kirsher {
4160adfc5217SJeff Kirsher 	u32 cmd;
4161adfc5217SJeff Kirsher 	int j;
4162adfc5217SJeff Kirsher 
4163adfc5217SJeff Kirsher 	if (bp->flash_info->flags & BNX2_NV_BUFFERED)
4164adfc5217SJeff Kirsher 		/* Buffered flash, no erase needed */
4165adfc5217SJeff Kirsher 		return 0;
4166adfc5217SJeff Kirsher 
4167adfc5217SJeff Kirsher 	/* Build an erase command */
4168adfc5217SJeff Kirsher 	cmd = BNX2_NVM_COMMAND_ERASE | BNX2_NVM_COMMAND_WR |
4169adfc5217SJeff Kirsher 	      BNX2_NVM_COMMAND_DOIT;
4170adfc5217SJeff Kirsher 
4171adfc5217SJeff Kirsher 	/* Need to clear DONE bit separately. */
4172adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
4173adfc5217SJeff Kirsher 
4174adfc5217SJeff Kirsher 	/* Address of the NVRAM to read from. */
4175adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
4176adfc5217SJeff Kirsher 
4177adfc5217SJeff Kirsher 	/* Issue an erase command. */
4178adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
4179adfc5217SJeff Kirsher 
4180adfc5217SJeff Kirsher 	/* Wait for completion. */
4181adfc5217SJeff Kirsher 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4182adfc5217SJeff Kirsher 		u32 val;
4183adfc5217SJeff Kirsher 
4184adfc5217SJeff Kirsher 		udelay(5);
4185adfc5217SJeff Kirsher 
4186adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_NVM_COMMAND);
4187adfc5217SJeff Kirsher 		if (val & BNX2_NVM_COMMAND_DONE)
4188adfc5217SJeff Kirsher 			break;
4189adfc5217SJeff Kirsher 	}
4190adfc5217SJeff Kirsher 
4191adfc5217SJeff Kirsher 	if (j >= NVRAM_TIMEOUT_COUNT)
4192adfc5217SJeff Kirsher 		return -EBUSY;
4193adfc5217SJeff Kirsher 
4194adfc5217SJeff Kirsher 	return 0;
4195adfc5217SJeff Kirsher }
4196adfc5217SJeff Kirsher 
4197adfc5217SJeff Kirsher static int
4198adfc5217SJeff Kirsher bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
4199adfc5217SJeff Kirsher {
4200adfc5217SJeff Kirsher 	u32 cmd;
4201adfc5217SJeff Kirsher 	int j;
4202adfc5217SJeff Kirsher 
4203adfc5217SJeff Kirsher 	/* Build the command word. */
4204adfc5217SJeff Kirsher 	cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags;
4205adfc5217SJeff Kirsher 
4206adfc5217SJeff Kirsher 	/* Calculate an offset of a buffered flash, not needed for 5709. */
4207adfc5217SJeff Kirsher 	if (bp->flash_info->flags & BNX2_NV_TRANSLATE) {
4208adfc5217SJeff Kirsher 		offset = ((offset / bp->flash_info->page_size) <<
4209adfc5217SJeff Kirsher 			   bp->flash_info->page_bits) +
4210adfc5217SJeff Kirsher 			  (offset % bp->flash_info->page_size);
4211adfc5217SJeff Kirsher 	}
4212adfc5217SJeff Kirsher 
4213adfc5217SJeff Kirsher 	/* Need to clear DONE bit separately. */
4214adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
4215adfc5217SJeff Kirsher 
4216adfc5217SJeff Kirsher 	/* Address of the NVRAM to read from. */
4217adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
4218adfc5217SJeff Kirsher 
4219adfc5217SJeff Kirsher 	/* Issue a read command. */
4220adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
4221adfc5217SJeff Kirsher 
4222adfc5217SJeff Kirsher 	/* Wait for completion. */
4223adfc5217SJeff Kirsher 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4224adfc5217SJeff Kirsher 		u32 val;
4225adfc5217SJeff Kirsher 
4226adfc5217SJeff Kirsher 		udelay(5);
4227adfc5217SJeff Kirsher 
4228adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_NVM_COMMAND);
4229adfc5217SJeff Kirsher 		if (val & BNX2_NVM_COMMAND_DONE) {
4230adfc5217SJeff Kirsher 			__be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ));
4231adfc5217SJeff Kirsher 			memcpy(ret_val, &v, 4);
4232adfc5217SJeff Kirsher 			break;
4233adfc5217SJeff Kirsher 		}
4234adfc5217SJeff Kirsher 	}
4235adfc5217SJeff Kirsher 	if (j >= NVRAM_TIMEOUT_COUNT)
4236adfc5217SJeff Kirsher 		return -EBUSY;
4237adfc5217SJeff Kirsher 
4238adfc5217SJeff Kirsher 	return 0;
4239adfc5217SJeff Kirsher }
4240adfc5217SJeff Kirsher 
4241adfc5217SJeff Kirsher 
4242adfc5217SJeff Kirsher static int
4243adfc5217SJeff Kirsher bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags)
4244adfc5217SJeff Kirsher {
4245adfc5217SJeff Kirsher 	u32 cmd;
4246adfc5217SJeff Kirsher 	__be32 val32;
4247adfc5217SJeff Kirsher 	int j;
4248adfc5217SJeff Kirsher 
4249adfc5217SJeff Kirsher 	/* Build the command word. */
4250adfc5217SJeff Kirsher 	cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags;
4251adfc5217SJeff Kirsher 
4252adfc5217SJeff Kirsher 	/* Calculate an offset of a buffered flash, not needed for 5709. */
4253adfc5217SJeff Kirsher 	if (bp->flash_info->flags & BNX2_NV_TRANSLATE) {
4254adfc5217SJeff Kirsher 		offset = ((offset / bp->flash_info->page_size) <<
4255adfc5217SJeff Kirsher 			  bp->flash_info->page_bits) +
4256adfc5217SJeff Kirsher 			 (offset % bp->flash_info->page_size);
4257adfc5217SJeff Kirsher 	}
4258adfc5217SJeff Kirsher 
4259adfc5217SJeff Kirsher 	/* Need to clear DONE bit separately. */
4260adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
4261adfc5217SJeff Kirsher 
4262adfc5217SJeff Kirsher 	memcpy(&val32, val, 4);
4263adfc5217SJeff Kirsher 
4264adfc5217SJeff Kirsher 	/* Write the data. */
4265adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
4266adfc5217SJeff Kirsher 
4267adfc5217SJeff Kirsher 	/* Address of the NVRAM to write to. */
4268adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
4269adfc5217SJeff Kirsher 
4270adfc5217SJeff Kirsher 	/* Issue the write command. */
4271adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_NVM_COMMAND, cmd);
4272adfc5217SJeff Kirsher 
4273adfc5217SJeff Kirsher 	/* Wait for completion. */
4274adfc5217SJeff Kirsher 	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
4275adfc5217SJeff Kirsher 		udelay(5);
4276adfc5217SJeff Kirsher 
4277adfc5217SJeff Kirsher 		if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
4278adfc5217SJeff Kirsher 			break;
4279adfc5217SJeff Kirsher 	}
4280adfc5217SJeff Kirsher 	if (j >= NVRAM_TIMEOUT_COUNT)
4281adfc5217SJeff Kirsher 		return -EBUSY;
4282adfc5217SJeff Kirsher 
4283adfc5217SJeff Kirsher 	return 0;
4284adfc5217SJeff Kirsher }
4285adfc5217SJeff Kirsher 
4286adfc5217SJeff Kirsher static int
4287adfc5217SJeff Kirsher bnx2_init_nvram(struct bnx2 *bp)
4288adfc5217SJeff Kirsher {
4289adfc5217SJeff Kirsher 	u32 val;
4290adfc5217SJeff Kirsher 	int j, entry_count, rc = 0;
4291adfc5217SJeff Kirsher 	const struct flash_spec *flash;
4292adfc5217SJeff Kirsher 
4293adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
4294adfc5217SJeff Kirsher 		bp->flash_info = &flash_5709;
4295adfc5217SJeff Kirsher 		goto get_flash_size;
4296adfc5217SJeff Kirsher 	}
4297adfc5217SJeff Kirsher 
4298adfc5217SJeff Kirsher 	/* Determine the selected interface. */
4299adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_NVM_CFG1);
4300adfc5217SJeff Kirsher 
4301adfc5217SJeff Kirsher 	entry_count = ARRAY_SIZE(flash_table);
4302adfc5217SJeff Kirsher 
4303adfc5217SJeff Kirsher 	if (val & 0x40000000) {
4304adfc5217SJeff Kirsher 
4305adfc5217SJeff Kirsher 		/* Flash interface has been reconfigured */
4306adfc5217SJeff Kirsher 		for (j = 0, flash = &flash_table[0]; j < entry_count;
4307adfc5217SJeff Kirsher 		     j++, flash++) {
4308adfc5217SJeff Kirsher 			if ((val & FLASH_BACKUP_STRAP_MASK) ==
4309adfc5217SJeff Kirsher 			    (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
4310adfc5217SJeff Kirsher 				bp->flash_info = flash;
4311adfc5217SJeff Kirsher 				break;
4312adfc5217SJeff Kirsher 			}
4313adfc5217SJeff Kirsher 		}
4314adfc5217SJeff Kirsher 	}
4315adfc5217SJeff Kirsher 	else {
4316adfc5217SJeff Kirsher 		u32 mask;
4317adfc5217SJeff Kirsher 		/* Not yet been reconfigured */
4318adfc5217SJeff Kirsher 
4319adfc5217SJeff Kirsher 		if (val & (1 << 23))
4320adfc5217SJeff Kirsher 			mask = FLASH_BACKUP_STRAP_MASK;
4321adfc5217SJeff Kirsher 		else
4322adfc5217SJeff Kirsher 			mask = FLASH_STRAP_MASK;
4323adfc5217SJeff Kirsher 
4324adfc5217SJeff Kirsher 		for (j = 0, flash = &flash_table[0]; j < entry_count;
4325adfc5217SJeff Kirsher 			j++, flash++) {
4326adfc5217SJeff Kirsher 
4327adfc5217SJeff Kirsher 			if ((val & mask) == (flash->strapping & mask)) {
4328adfc5217SJeff Kirsher 				bp->flash_info = flash;
4329adfc5217SJeff Kirsher 
4330adfc5217SJeff Kirsher 				/* Request access to the flash interface. */
4331adfc5217SJeff Kirsher 				if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
4332adfc5217SJeff Kirsher 					return rc;
4333adfc5217SJeff Kirsher 
4334adfc5217SJeff Kirsher 				/* Enable access to flash interface */
4335adfc5217SJeff Kirsher 				bnx2_enable_nvram_access(bp);
4336adfc5217SJeff Kirsher 
4337adfc5217SJeff Kirsher 				/* Reconfigure the flash interface */
4338adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
4339adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
4340adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
4341adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
4342adfc5217SJeff Kirsher 
4343adfc5217SJeff Kirsher 				/* Disable access to flash interface */
4344adfc5217SJeff Kirsher 				bnx2_disable_nvram_access(bp);
4345adfc5217SJeff Kirsher 				bnx2_release_nvram_lock(bp);
4346adfc5217SJeff Kirsher 
4347adfc5217SJeff Kirsher 				break;
4348adfc5217SJeff Kirsher 			}
4349adfc5217SJeff Kirsher 		}
4350adfc5217SJeff Kirsher 	} /* if (val & 0x40000000) */
4351adfc5217SJeff Kirsher 
4352adfc5217SJeff Kirsher 	if (j == entry_count) {
4353adfc5217SJeff Kirsher 		bp->flash_info = NULL;
4354adfc5217SJeff Kirsher 		pr_alert("Unknown flash/EEPROM type\n");
4355adfc5217SJeff Kirsher 		return -ENODEV;
4356adfc5217SJeff Kirsher 	}
4357adfc5217SJeff Kirsher 
4358adfc5217SJeff Kirsher get_flash_size:
4359adfc5217SJeff Kirsher 	val = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG2);
4360adfc5217SJeff Kirsher 	val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
4361adfc5217SJeff Kirsher 	if (val)
4362adfc5217SJeff Kirsher 		bp->flash_size = val;
4363adfc5217SJeff Kirsher 	else
4364adfc5217SJeff Kirsher 		bp->flash_size = bp->flash_info->total_size;
4365adfc5217SJeff Kirsher 
4366adfc5217SJeff Kirsher 	return rc;
4367adfc5217SJeff Kirsher }
4368adfc5217SJeff Kirsher 
4369adfc5217SJeff Kirsher static int
4370adfc5217SJeff Kirsher bnx2_nvram_read(struct bnx2 *bp, u32 offset, u8 *ret_buf,
4371adfc5217SJeff Kirsher 		int buf_size)
4372adfc5217SJeff Kirsher {
4373adfc5217SJeff Kirsher 	int rc = 0;
4374adfc5217SJeff Kirsher 	u32 cmd_flags, offset32, len32, extra;
4375adfc5217SJeff Kirsher 
4376adfc5217SJeff Kirsher 	if (buf_size == 0)
4377adfc5217SJeff Kirsher 		return 0;
4378adfc5217SJeff Kirsher 
4379adfc5217SJeff Kirsher 	/* Request access to the flash interface. */
4380adfc5217SJeff Kirsher 	if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
4381adfc5217SJeff Kirsher 		return rc;
4382adfc5217SJeff Kirsher 
4383adfc5217SJeff Kirsher 	/* Enable access to flash interface */
4384adfc5217SJeff Kirsher 	bnx2_enable_nvram_access(bp);
4385adfc5217SJeff Kirsher 
4386adfc5217SJeff Kirsher 	len32 = buf_size;
4387adfc5217SJeff Kirsher 	offset32 = offset;
4388adfc5217SJeff Kirsher 	extra = 0;
4389adfc5217SJeff Kirsher 
4390adfc5217SJeff Kirsher 	cmd_flags = 0;
4391adfc5217SJeff Kirsher 
4392adfc5217SJeff Kirsher 	if (offset32 & 3) {
4393adfc5217SJeff Kirsher 		u8 buf[4];
4394adfc5217SJeff Kirsher 		u32 pre_len;
4395adfc5217SJeff Kirsher 
4396adfc5217SJeff Kirsher 		offset32 &= ~3;
4397adfc5217SJeff Kirsher 		pre_len = 4 - (offset & 3);
4398adfc5217SJeff Kirsher 
4399adfc5217SJeff Kirsher 		if (pre_len >= len32) {
4400adfc5217SJeff Kirsher 			pre_len = len32;
4401adfc5217SJeff Kirsher 			cmd_flags = BNX2_NVM_COMMAND_FIRST |
4402adfc5217SJeff Kirsher 				    BNX2_NVM_COMMAND_LAST;
4403adfc5217SJeff Kirsher 		}
4404adfc5217SJeff Kirsher 		else {
4405adfc5217SJeff Kirsher 			cmd_flags = BNX2_NVM_COMMAND_FIRST;
4406adfc5217SJeff Kirsher 		}
4407adfc5217SJeff Kirsher 
4408adfc5217SJeff Kirsher 		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
4409adfc5217SJeff Kirsher 
4410adfc5217SJeff Kirsher 		if (rc)
4411adfc5217SJeff Kirsher 			return rc;
4412adfc5217SJeff Kirsher 
4413adfc5217SJeff Kirsher 		memcpy(ret_buf, buf + (offset & 3), pre_len);
4414adfc5217SJeff Kirsher 
4415adfc5217SJeff Kirsher 		offset32 += 4;
4416adfc5217SJeff Kirsher 		ret_buf += pre_len;
4417adfc5217SJeff Kirsher 		len32 -= pre_len;
4418adfc5217SJeff Kirsher 	}
4419adfc5217SJeff Kirsher 	if (len32 & 3) {
4420adfc5217SJeff Kirsher 		extra = 4 - (len32 & 3);
4421adfc5217SJeff Kirsher 		len32 = (len32 + 4) & ~3;
4422adfc5217SJeff Kirsher 	}
4423adfc5217SJeff Kirsher 
4424adfc5217SJeff Kirsher 	if (len32 == 4) {
4425adfc5217SJeff Kirsher 		u8 buf[4];
4426adfc5217SJeff Kirsher 
4427adfc5217SJeff Kirsher 		if (cmd_flags)
4428adfc5217SJeff Kirsher 			cmd_flags = BNX2_NVM_COMMAND_LAST;
4429adfc5217SJeff Kirsher 		else
4430adfc5217SJeff Kirsher 			cmd_flags = BNX2_NVM_COMMAND_FIRST |
4431adfc5217SJeff Kirsher 				    BNX2_NVM_COMMAND_LAST;
4432adfc5217SJeff Kirsher 
4433adfc5217SJeff Kirsher 		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
4434adfc5217SJeff Kirsher 
4435adfc5217SJeff Kirsher 		memcpy(ret_buf, buf, 4 - extra);
4436adfc5217SJeff Kirsher 	}
4437adfc5217SJeff Kirsher 	else if (len32 > 0) {
4438adfc5217SJeff Kirsher 		u8 buf[4];
4439adfc5217SJeff Kirsher 
4440adfc5217SJeff Kirsher 		/* Read the first word. */
4441adfc5217SJeff Kirsher 		if (cmd_flags)
4442adfc5217SJeff Kirsher 			cmd_flags = 0;
4443adfc5217SJeff Kirsher 		else
4444adfc5217SJeff Kirsher 			cmd_flags = BNX2_NVM_COMMAND_FIRST;
4445adfc5217SJeff Kirsher 
4446adfc5217SJeff Kirsher 		rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, cmd_flags);
4447adfc5217SJeff Kirsher 
4448adfc5217SJeff Kirsher 		/* Advance to the next dword. */
4449adfc5217SJeff Kirsher 		offset32 += 4;
4450adfc5217SJeff Kirsher 		ret_buf += 4;
4451adfc5217SJeff Kirsher 		len32 -= 4;
4452adfc5217SJeff Kirsher 
4453adfc5217SJeff Kirsher 		while (len32 > 4 && rc == 0) {
4454adfc5217SJeff Kirsher 			rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, 0);
4455adfc5217SJeff Kirsher 
4456adfc5217SJeff Kirsher 			/* Advance to the next dword. */
4457adfc5217SJeff Kirsher 			offset32 += 4;
4458adfc5217SJeff Kirsher 			ret_buf += 4;
4459adfc5217SJeff Kirsher 			len32 -= 4;
4460adfc5217SJeff Kirsher 		}
4461adfc5217SJeff Kirsher 
4462adfc5217SJeff Kirsher 		if (rc)
4463adfc5217SJeff Kirsher 			return rc;
4464adfc5217SJeff Kirsher 
4465adfc5217SJeff Kirsher 		cmd_flags = BNX2_NVM_COMMAND_LAST;
4466adfc5217SJeff Kirsher 		rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
4467adfc5217SJeff Kirsher 
4468adfc5217SJeff Kirsher 		memcpy(ret_buf, buf, 4 - extra);
4469adfc5217SJeff Kirsher 	}
4470adfc5217SJeff Kirsher 
4471adfc5217SJeff Kirsher 	/* Disable access to flash interface */
4472adfc5217SJeff Kirsher 	bnx2_disable_nvram_access(bp);
4473adfc5217SJeff Kirsher 
4474adfc5217SJeff Kirsher 	bnx2_release_nvram_lock(bp);
4475adfc5217SJeff Kirsher 
4476adfc5217SJeff Kirsher 	return rc;
4477adfc5217SJeff Kirsher }
4478adfc5217SJeff Kirsher 
4479adfc5217SJeff Kirsher static int
4480adfc5217SJeff Kirsher bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
4481adfc5217SJeff Kirsher 		int buf_size)
4482adfc5217SJeff Kirsher {
4483adfc5217SJeff Kirsher 	u32 written, offset32, len32;
4484adfc5217SJeff Kirsher 	u8 *buf, start[4], end[4], *align_buf = NULL, *flash_buffer = NULL;
4485adfc5217SJeff Kirsher 	int rc = 0;
4486adfc5217SJeff Kirsher 	int align_start, align_end;
4487adfc5217SJeff Kirsher 
4488adfc5217SJeff Kirsher 	buf = data_buf;
4489adfc5217SJeff Kirsher 	offset32 = offset;
4490adfc5217SJeff Kirsher 	len32 = buf_size;
4491adfc5217SJeff Kirsher 	align_start = align_end = 0;
4492adfc5217SJeff Kirsher 
4493adfc5217SJeff Kirsher 	if ((align_start = (offset32 & 3))) {
4494adfc5217SJeff Kirsher 		offset32 &= ~3;
4495adfc5217SJeff Kirsher 		len32 += align_start;
4496adfc5217SJeff Kirsher 		if (len32 < 4)
4497adfc5217SJeff Kirsher 			len32 = 4;
4498adfc5217SJeff Kirsher 		if ((rc = bnx2_nvram_read(bp, offset32, start, 4)))
4499adfc5217SJeff Kirsher 			return rc;
4500adfc5217SJeff Kirsher 	}
4501adfc5217SJeff Kirsher 
4502adfc5217SJeff Kirsher 	if (len32 & 3) {
4503adfc5217SJeff Kirsher 		align_end = 4 - (len32 & 3);
4504adfc5217SJeff Kirsher 		len32 += align_end;
4505adfc5217SJeff Kirsher 		if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4, end, 4)))
4506adfc5217SJeff Kirsher 			return rc;
4507adfc5217SJeff Kirsher 	}
4508adfc5217SJeff Kirsher 
4509adfc5217SJeff Kirsher 	if (align_start || align_end) {
4510adfc5217SJeff Kirsher 		align_buf = kmalloc(len32, GFP_KERNEL);
4511adfc5217SJeff Kirsher 		if (align_buf == NULL)
4512adfc5217SJeff Kirsher 			return -ENOMEM;
4513adfc5217SJeff Kirsher 		if (align_start) {
4514adfc5217SJeff Kirsher 			memcpy(align_buf, start, 4);
4515adfc5217SJeff Kirsher 		}
4516adfc5217SJeff Kirsher 		if (align_end) {
4517adfc5217SJeff Kirsher 			memcpy(align_buf + len32 - 4, end, 4);
4518adfc5217SJeff Kirsher 		}
4519adfc5217SJeff Kirsher 		memcpy(align_buf + align_start, data_buf, buf_size);
4520adfc5217SJeff Kirsher 		buf = align_buf;
4521adfc5217SJeff Kirsher 	}
4522adfc5217SJeff Kirsher 
4523adfc5217SJeff Kirsher 	if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
4524adfc5217SJeff Kirsher 		flash_buffer = kmalloc(264, GFP_KERNEL);
4525adfc5217SJeff Kirsher 		if (flash_buffer == NULL) {
4526adfc5217SJeff Kirsher 			rc = -ENOMEM;
4527adfc5217SJeff Kirsher 			goto nvram_write_end;
4528adfc5217SJeff Kirsher 		}
4529adfc5217SJeff Kirsher 	}
4530adfc5217SJeff Kirsher 
4531adfc5217SJeff Kirsher 	written = 0;
4532adfc5217SJeff Kirsher 	while ((written < len32) && (rc == 0)) {
4533adfc5217SJeff Kirsher 		u32 page_start, page_end, data_start, data_end;
4534adfc5217SJeff Kirsher 		u32 addr, cmd_flags;
4535adfc5217SJeff Kirsher 		int i;
4536adfc5217SJeff Kirsher 
4537adfc5217SJeff Kirsher 	        /* Find the page_start addr */
4538adfc5217SJeff Kirsher 		page_start = offset32 + written;
4539adfc5217SJeff Kirsher 		page_start -= (page_start % bp->flash_info->page_size);
4540adfc5217SJeff Kirsher 		/* Find the page_end addr */
4541adfc5217SJeff Kirsher 		page_end = page_start + bp->flash_info->page_size;
4542adfc5217SJeff Kirsher 		/* Find the data_start addr */
4543adfc5217SJeff Kirsher 		data_start = (written == 0) ? offset32 : page_start;
4544adfc5217SJeff Kirsher 		/* Find the data_end addr */
4545adfc5217SJeff Kirsher 		data_end = (page_end > offset32 + len32) ?
4546adfc5217SJeff Kirsher 			(offset32 + len32) : page_end;
4547adfc5217SJeff Kirsher 
4548adfc5217SJeff Kirsher 		/* Request access to the flash interface. */
4549adfc5217SJeff Kirsher 		if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
4550adfc5217SJeff Kirsher 			goto nvram_write_end;
4551adfc5217SJeff Kirsher 
4552adfc5217SJeff Kirsher 		/* Enable access to flash interface */
4553adfc5217SJeff Kirsher 		bnx2_enable_nvram_access(bp);
4554adfc5217SJeff Kirsher 
4555adfc5217SJeff Kirsher 		cmd_flags = BNX2_NVM_COMMAND_FIRST;
4556adfc5217SJeff Kirsher 		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
4557adfc5217SJeff Kirsher 			int j;
4558adfc5217SJeff Kirsher 
4559adfc5217SJeff Kirsher 			/* Read the whole page into the buffer
4560adfc5217SJeff Kirsher 			 * (non-buffer flash only) */
4561adfc5217SJeff Kirsher 			for (j = 0; j < bp->flash_info->page_size; j += 4) {
4562adfc5217SJeff Kirsher 				if (j == (bp->flash_info->page_size - 4)) {
4563adfc5217SJeff Kirsher 					cmd_flags |= BNX2_NVM_COMMAND_LAST;
4564adfc5217SJeff Kirsher 				}
4565adfc5217SJeff Kirsher 				rc = bnx2_nvram_read_dword(bp,
4566adfc5217SJeff Kirsher 					page_start + j,
4567adfc5217SJeff Kirsher 					&flash_buffer[j],
4568adfc5217SJeff Kirsher 					cmd_flags);
4569adfc5217SJeff Kirsher 
4570adfc5217SJeff Kirsher 				if (rc)
4571adfc5217SJeff Kirsher 					goto nvram_write_end;
4572adfc5217SJeff Kirsher 
4573adfc5217SJeff Kirsher 				cmd_flags = 0;
4574adfc5217SJeff Kirsher 			}
4575adfc5217SJeff Kirsher 		}
4576adfc5217SJeff Kirsher 
4577adfc5217SJeff Kirsher 		/* Enable writes to flash interface (unlock write-protect) */
4578adfc5217SJeff Kirsher 		if ((rc = bnx2_enable_nvram_write(bp)) != 0)
4579adfc5217SJeff Kirsher 			goto nvram_write_end;
4580adfc5217SJeff Kirsher 
4581adfc5217SJeff Kirsher 		/* Loop to write back the buffer data from page_start to
4582adfc5217SJeff Kirsher 		 * data_start */
4583adfc5217SJeff Kirsher 		i = 0;
4584adfc5217SJeff Kirsher 		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
4585adfc5217SJeff Kirsher 			/* Erase the page */
4586adfc5217SJeff Kirsher 			if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0)
4587adfc5217SJeff Kirsher 				goto nvram_write_end;
4588adfc5217SJeff Kirsher 
4589adfc5217SJeff Kirsher 			/* Re-enable the write again for the actual write */
4590adfc5217SJeff Kirsher 			bnx2_enable_nvram_write(bp);
4591adfc5217SJeff Kirsher 
4592adfc5217SJeff Kirsher 			for (addr = page_start; addr < data_start;
4593adfc5217SJeff Kirsher 				addr += 4, i += 4) {
4594adfc5217SJeff Kirsher 
4595adfc5217SJeff Kirsher 				rc = bnx2_nvram_write_dword(bp, addr,
4596adfc5217SJeff Kirsher 					&flash_buffer[i], cmd_flags);
4597adfc5217SJeff Kirsher 
4598adfc5217SJeff Kirsher 				if (rc != 0)
4599adfc5217SJeff Kirsher 					goto nvram_write_end;
4600adfc5217SJeff Kirsher 
4601adfc5217SJeff Kirsher 				cmd_flags = 0;
4602adfc5217SJeff Kirsher 			}
4603adfc5217SJeff Kirsher 		}
4604adfc5217SJeff Kirsher 
4605adfc5217SJeff Kirsher 		/* Loop to write the new data from data_start to data_end */
4606adfc5217SJeff Kirsher 		for (addr = data_start; addr < data_end; addr += 4, i += 4) {
4607adfc5217SJeff Kirsher 			if ((addr == page_end - 4) ||
4608adfc5217SJeff Kirsher 				((bp->flash_info->flags & BNX2_NV_BUFFERED) &&
4609adfc5217SJeff Kirsher 				 (addr == data_end - 4))) {
4610adfc5217SJeff Kirsher 
4611adfc5217SJeff Kirsher 				cmd_flags |= BNX2_NVM_COMMAND_LAST;
4612adfc5217SJeff Kirsher 			}
4613adfc5217SJeff Kirsher 			rc = bnx2_nvram_write_dword(bp, addr, buf,
4614adfc5217SJeff Kirsher 				cmd_flags);
4615adfc5217SJeff Kirsher 
4616adfc5217SJeff Kirsher 			if (rc != 0)
4617adfc5217SJeff Kirsher 				goto nvram_write_end;
4618adfc5217SJeff Kirsher 
4619adfc5217SJeff Kirsher 			cmd_flags = 0;
4620adfc5217SJeff Kirsher 			buf += 4;
4621adfc5217SJeff Kirsher 		}
4622adfc5217SJeff Kirsher 
4623adfc5217SJeff Kirsher 		/* Loop to write back the buffer data from data_end
4624adfc5217SJeff Kirsher 		 * to page_end */
4625adfc5217SJeff Kirsher 		if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) {
4626adfc5217SJeff Kirsher 			for (addr = data_end; addr < page_end;
4627adfc5217SJeff Kirsher 				addr += 4, i += 4) {
4628adfc5217SJeff Kirsher 
4629adfc5217SJeff Kirsher 				if (addr == page_end-4) {
4630adfc5217SJeff Kirsher 					cmd_flags = BNX2_NVM_COMMAND_LAST;
4631adfc5217SJeff Kirsher                 		}
4632adfc5217SJeff Kirsher 				rc = bnx2_nvram_write_dword(bp, addr,
4633adfc5217SJeff Kirsher 					&flash_buffer[i], cmd_flags);
4634adfc5217SJeff Kirsher 
4635adfc5217SJeff Kirsher 				if (rc != 0)
4636adfc5217SJeff Kirsher 					goto nvram_write_end;
4637adfc5217SJeff Kirsher 
4638adfc5217SJeff Kirsher 				cmd_flags = 0;
4639adfc5217SJeff Kirsher 			}
4640adfc5217SJeff Kirsher 		}
4641adfc5217SJeff Kirsher 
4642adfc5217SJeff Kirsher 		/* Disable writes to flash interface (lock write-protect) */
4643adfc5217SJeff Kirsher 		bnx2_disable_nvram_write(bp);
4644adfc5217SJeff Kirsher 
4645adfc5217SJeff Kirsher 		/* Disable access to flash interface */
4646adfc5217SJeff Kirsher 		bnx2_disable_nvram_access(bp);
4647adfc5217SJeff Kirsher 		bnx2_release_nvram_lock(bp);
4648adfc5217SJeff Kirsher 
4649adfc5217SJeff Kirsher 		/* Increment written */
4650adfc5217SJeff Kirsher 		written += data_end - data_start;
4651adfc5217SJeff Kirsher 	}
4652adfc5217SJeff Kirsher 
4653adfc5217SJeff Kirsher nvram_write_end:
4654adfc5217SJeff Kirsher 	kfree(flash_buffer);
4655adfc5217SJeff Kirsher 	kfree(align_buf);
4656adfc5217SJeff Kirsher 	return rc;
4657adfc5217SJeff Kirsher }
4658adfc5217SJeff Kirsher 
4659adfc5217SJeff Kirsher static void
4660adfc5217SJeff Kirsher bnx2_init_fw_cap(struct bnx2 *bp)
4661adfc5217SJeff Kirsher {
4662adfc5217SJeff Kirsher 	u32 val, sig = 0;
4663adfc5217SJeff Kirsher 
4664adfc5217SJeff Kirsher 	bp->phy_flags &= ~BNX2_PHY_FLAG_REMOTE_PHY_CAP;
4665adfc5217SJeff Kirsher 	bp->flags &= ~BNX2_FLAG_CAN_KEEP_VLAN;
4666adfc5217SJeff Kirsher 
4667adfc5217SJeff Kirsher 	if (!(bp->flags & BNX2_FLAG_ASF_ENABLE))
4668adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN;
4669adfc5217SJeff Kirsher 
4670adfc5217SJeff Kirsher 	val = bnx2_shmem_rd(bp, BNX2_FW_CAP_MB);
4671adfc5217SJeff Kirsher 	if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
4672adfc5217SJeff Kirsher 		return;
4673adfc5217SJeff Kirsher 
4674adfc5217SJeff Kirsher 	if ((val & BNX2_FW_CAP_CAN_KEEP_VLAN) == BNX2_FW_CAP_CAN_KEEP_VLAN) {
4675adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_CAN_KEEP_VLAN;
4676adfc5217SJeff Kirsher 		sig |= BNX2_DRV_ACK_CAP_SIGNATURE | BNX2_FW_CAP_CAN_KEEP_VLAN;
4677adfc5217SJeff Kirsher 	}
4678adfc5217SJeff Kirsher 
4679adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
4680adfc5217SJeff Kirsher 	    (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE)) {
4681adfc5217SJeff Kirsher 		u32 link;
4682adfc5217SJeff Kirsher 
4683adfc5217SJeff Kirsher 		bp->phy_flags |= BNX2_PHY_FLAG_REMOTE_PHY_CAP;
4684adfc5217SJeff Kirsher 
4685adfc5217SJeff Kirsher 		link = bnx2_shmem_rd(bp, BNX2_LINK_STATUS);
4686adfc5217SJeff Kirsher 		if (link & BNX2_LINK_STATUS_SERDES_LINK)
4687adfc5217SJeff Kirsher 			bp->phy_port = PORT_FIBRE;
4688adfc5217SJeff Kirsher 		else
4689adfc5217SJeff Kirsher 			bp->phy_port = PORT_TP;
4690adfc5217SJeff Kirsher 
4691adfc5217SJeff Kirsher 		sig |= BNX2_DRV_ACK_CAP_SIGNATURE |
4692adfc5217SJeff Kirsher 		       BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
4693adfc5217SJeff Kirsher 	}
4694adfc5217SJeff Kirsher 
4695adfc5217SJeff Kirsher 	if (netif_running(bp->dev) && sig)
4696adfc5217SJeff Kirsher 		bnx2_shmem_wr(bp, BNX2_DRV_ACK_CAP_MB, sig);
4697adfc5217SJeff Kirsher }
4698adfc5217SJeff Kirsher 
4699adfc5217SJeff Kirsher static void
4700adfc5217SJeff Kirsher bnx2_setup_msix_tbl(struct bnx2 *bp)
4701adfc5217SJeff Kirsher {
4702adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
4703adfc5217SJeff Kirsher 
4704adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
4705adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
4706adfc5217SJeff Kirsher }
4707adfc5217SJeff Kirsher 
4708adfc5217SJeff Kirsher static int
4709adfc5217SJeff Kirsher bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
4710adfc5217SJeff Kirsher {
4711adfc5217SJeff Kirsher 	u32 val;
4712adfc5217SJeff Kirsher 	int i, rc = 0;
4713adfc5217SJeff Kirsher 	u8 old_port;
4714adfc5217SJeff Kirsher 
4715adfc5217SJeff Kirsher 	/* Wait for the current PCI transaction to complete before
4716adfc5217SJeff Kirsher 	 * issuing a reset. */
4717adfc5217SJeff Kirsher 	if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
4718adfc5217SJeff Kirsher 	    (CHIP_NUM(bp) == CHIP_NUM_5708)) {
4719adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
4720adfc5217SJeff Kirsher 		       BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
4721adfc5217SJeff Kirsher 		       BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
4722adfc5217SJeff Kirsher 		       BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
4723adfc5217SJeff Kirsher 		       BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
4724adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
4725adfc5217SJeff Kirsher 		udelay(5);
4726adfc5217SJeff Kirsher 	} else {  /* 5709 */
4727adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
4728adfc5217SJeff Kirsher 		val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
4729adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
4730adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
4731adfc5217SJeff Kirsher 
4732adfc5217SJeff Kirsher 		for (i = 0; i < 100; i++) {
4733adfc5217SJeff Kirsher 			msleep(1);
4734adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
4735adfc5217SJeff Kirsher 			if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
4736adfc5217SJeff Kirsher 				break;
4737adfc5217SJeff Kirsher 		}
4738adfc5217SJeff Kirsher 	}
4739adfc5217SJeff Kirsher 
4740adfc5217SJeff Kirsher 	/* Wait for the firmware to tell us it is ok to issue a reset. */
4741adfc5217SJeff Kirsher 	bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1);
4742adfc5217SJeff Kirsher 
4743adfc5217SJeff Kirsher 	/* Deposit a driver reset signature so the firmware knows that
4744adfc5217SJeff Kirsher 	 * this is a soft reset. */
4745adfc5217SJeff Kirsher 	bnx2_shmem_wr(bp, BNX2_DRV_RESET_SIGNATURE,
4746adfc5217SJeff Kirsher 		      BNX2_DRV_RESET_SIGNATURE_MAGIC);
4747adfc5217SJeff Kirsher 
4748adfc5217SJeff Kirsher 	/* Do a dummy read to force the chip to complete all current transaction
4749adfc5217SJeff Kirsher 	 * before we issue a reset. */
4750adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_MISC_ID);
4751adfc5217SJeff Kirsher 
4752adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
4753adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
4754adfc5217SJeff Kirsher 		REG_RD(bp, BNX2_MISC_COMMAND);
4755adfc5217SJeff Kirsher 		udelay(5);
4756adfc5217SJeff Kirsher 
4757adfc5217SJeff Kirsher 		val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
4758adfc5217SJeff Kirsher 		      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
4759adfc5217SJeff Kirsher 
4760adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
4761adfc5217SJeff Kirsher 
4762adfc5217SJeff Kirsher 	} else {
4763adfc5217SJeff Kirsher 		val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
4764adfc5217SJeff Kirsher 		      BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
4765adfc5217SJeff Kirsher 		      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
4766adfc5217SJeff Kirsher 
4767adfc5217SJeff Kirsher 		/* Chip reset. */
4768adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
4769adfc5217SJeff Kirsher 
4770adfc5217SJeff Kirsher 		/* Reading back any register after chip reset will hang the
4771adfc5217SJeff Kirsher 		 * bus on 5706 A0 and A1.  The msleep below provides plenty
4772adfc5217SJeff Kirsher 		 * of margin for write posting.
4773adfc5217SJeff Kirsher 		 */
4774adfc5217SJeff Kirsher 		if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
4775adfc5217SJeff Kirsher 		    (CHIP_ID(bp) == CHIP_ID_5706_A1))
4776adfc5217SJeff Kirsher 			msleep(20);
4777adfc5217SJeff Kirsher 
4778adfc5217SJeff Kirsher 		/* Reset takes approximate 30 usec */
4779adfc5217SJeff Kirsher 		for (i = 0; i < 10; i++) {
4780adfc5217SJeff Kirsher 			val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
4781adfc5217SJeff Kirsher 			if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
4782adfc5217SJeff Kirsher 				    BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
4783adfc5217SJeff Kirsher 				break;
4784adfc5217SJeff Kirsher 			udelay(10);
4785adfc5217SJeff Kirsher 		}
4786adfc5217SJeff Kirsher 
4787adfc5217SJeff Kirsher 		if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
4788adfc5217SJeff Kirsher 			   BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
4789adfc5217SJeff Kirsher 			pr_err("Chip reset did not complete\n");
4790adfc5217SJeff Kirsher 			return -EBUSY;
4791adfc5217SJeff Kirsher 		}
4792adfc5217SJeff Kirsher 	}
4793adfc5217SJeff Kirsher 
4794adfc5217SJeff Kirsher 	/* Make sure byte swapping is properly configured. */
4795adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
4796adfc5217SJeff Kirsher 	if (val != 0x01020304) {
4797adfc5217SJeff Kirsher 		pr_err("Chip not in correct endian mode\n");
4798adfc5217SJeff Kirsher 		return -ENODEV;
4799adfc5217SJeff Kirsher 	}
4800adfc5217SJeff Kirsher 
4801adfc5217SJeff Kirsher 	/* Wait for the firmware to finish its initialization. */
4802adfc5217SJeff Kirsher 	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 1, 0);
4803adfc5217SJeff Kirsher 	if (rc)
4804adfc5217SJeff Kirsher 		return rc;
4805adfc5217SJeff Kirsher 
4806adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
4807adfc5217SJeff Kirsher 	old_port = bp->phy_port;
4808adfc5217SJeff Kirsher 	bnx2_init_fw_cap(bp);
4809adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) &&
4810adfc5217SJeff Kirsher 	    old_port != bp->phy_port)
4811adfc5217SJeff Kirsher 		bnx2_set_default_remote_link(bp);
4812adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
4813adfc5217SJeff Kirsher 
4814adfc5217SJeff Kirsher 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
4815adfc5217SJeff Kirsher 		/* Adjust the voltage regular to two steps lower.  The default
4816adfc5217SJeff Kirsher 		 * of this register is 0x0000000e. */
4817adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
4818adfc5217SJeff Kirsher 
4819adfc5217SJeff Kirsher 		/* Remove bad rbuf memory from the free pool. */
4820adfc5217SJeff Kirsher 		rc = bnx2_alloc_bad_rbuf(bp);
4821adfc5217SJeff Kirsher 	}
4822adfc5217SJeff Kirsher 
4823adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSIX) {
4824adfc5217SJeff Kirsher 		bnx2_setup_msix_tbl(bp);
4825adfc5217SJeff Kirsher 		/* Prevent MSIX table reads and write from timing out */
4826adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
4827adfc5217SJeff Kirsher 			BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
4828adfc5217SJeff Kirsher 	}
4829adfc5217SJeff Kirsher 
4830adfc5217SJeff Kirsher 	return rc;
4831adfc5217SJeff Kirsher }
4832adfc5217SJeff Kirsher 
4833adfc5217SJeff Kirsher static int
4834adfc5217SJeff Kirsher bnx2_init_chip(struct bnx2 *bp)
4835adfc5217SJeff Kirsher {
4836adfc5217SJeff Kirsher 	u32 val, mtu;
4837adfc5217SJeff Kirsher 	int rc, i;
4838adfc5217SJeff Kirsher 
4839adfc5217SJeff Kirsher 	/* Make sure the interrupt is not active. */
4840adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
4841adfc5217SJeff Kirsher 
4842adfc5217SJeff Kirsher 	val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
4843adfc5217SJeff Kirsher 	      BNX2_DMA_CONFIG_DATA_WORD_SWAP |
4844adfc5217SJeff Kirsher #ifdef __BIG_ENDIAN
4845adfc5217SJeff Kirsher 	      BNX2_DMA_CONFIG_CNTL_BYTE_SWAP |
4846adfc5217SJeff Kirsher #endif
4847adfc5217SJeff Kirsher 	      BNX2_DMA_CONFIG_CNTL_WORD_SWAP |
4848adfc5217SJeff Kirsher 	      DMA_READ_CHANS << 12 |
4849adfc5217SJeff Kirsher 	      DMA_WRITE_CHANS << 16;
4850adfc5217SJeff Kirsher 
4851adfc5217SJeff Kirsher 	val |= (0x2 << 20) | (1 << 11);
4852adfc5217SJeff Kirsher 
4853adfc5217SJeff Kirsher 	if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133))
4854adfc5217SJeff Kirsher 		val |= (1 << 23);
4855adfc5217SJeff Kirsher 
4856adfc5217SJeff Kirsher 	if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
4857adfc5217SJeff Kirsher 	    (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX))
4858adfc5217SJeff Kirsher 		val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
4859adfc5217SJeff Kirsher 
4860adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_DMA_CONFIG, val);
4861adfc5217SJeff Kirsher 
4862adfc5217SJeff Kirsher 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
4863adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_TDMA_CONFIG);
4864adfc5217SJeff Kirsher 		val |= BNX2_TDMA_CONFIG_ONE_DMA;
4865adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_TDMA_CONFIG, val);
4866adfc5217SJeff Kirsher 	}
4867adfc5217SJeff Kirsher 
4868adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_PCIX) {
4869adfc5217SJeff Kirsher 		u16 val16;
4870adfc5217SJeff Kirsher 
4871adfc5217SJeff Kirsher 		pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
4872adfc5217SJeff Kirsher 				     &val16);
4873adfc5217SJeff Kirsher 		pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
4874adfc5217SJeff Kirsher 				      val16 & ~PCI_X_CMD_ERO);
4875adfc5217SJeff Kirsher 	}
4876adfc5217SJeff Kirsher 
4877adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
4878adfc5217SJeff Kirsher 	       BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
4879adfc5217SJeff Kirsher 	       BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
4880adfc5217SJeff Kirsher 	       BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
4881adfc5217SJeff Kirsher 
4882adfc5217SJeff Kirsher 	/* Initialize context mapping and zero out the quick contexts.  The
4883adfc5217SJeff Kirsher 	 * context block must have already been enabled. */
4884adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
4885adfc5217SJeff Kirsher 		rc = bnx2_init_5709_context(bp);
4886adfc5217SJeff Kirsher 		if (rc)
4887adfc5217SJeff Kirsher 			return rc;
4888adfc5217SJeff Kirsher 	} else
4889adfc5217SJeff Kirsher 		bnx2_init_context(bp);
4890adfc5217SJeff Kirsher 
4891adfc5217SJeff Kirsher 	if ((rc = bnx2_init_cpus(bp)) != 0)
4892adfc5217SJeff Kirsher 		return rc;
4893adfc5217SJeff Kirsher 
4894adfc5217SJeff Kirsher 	bnx2_init_nvram(bp);
4895adfc5217SJeff Kirsher 
4896adfc5217SJeff Kirsher 	bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
4897adfc5217SJeff Kirsher 
4898adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_MQ_CONFIG);
4899adfc5217SJeff Kirsher 	val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
4900adfc5217SJeff Kirsher 	val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
4901adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
4902adfc5217SJeff Kirsher 		val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
4903adfc5217SJeff Kirsher 		if (CHIP_REV(bp) == CHIP_REV_Ax)
4904adfc5217SJeff Kirsher 			val |= BNX2_MQ_CONFIG_HALT_DIS;
4905adfc5217SJeff Kirsher 	}
4906adfc5217SJeff Kirsher 
4907adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MQ_CONFIG, val);
4908adfc5217SJeff Kirsher 
4909adfc5217SJeff Kirsher 	val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
4910adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
4911adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
4912adfc5217SJeff Kirsher 
4913adfc5217SJeff Kirsher 	val = (BCM_PAGE_BITS - 8) << 24;
4914adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_RV2P_CONFIG, val);
4915adfc5217SJeff Kirsher 
4916adfc5217SJeff Kirsher 	/* Configure page size. */
4917adfc5217SJeff Kirsher 	val = REG_RD(bp, BNX2_TBDR_CONFIG);
4918adfc5217SJeff Kirsher 	val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
4919adfc5217SJeff Kirsher 	val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
4920adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_TBDR_CONFIG, val);
4921adfc5217SJeff Kirsher 
4922adfc5217SJeff Kirsher 	val = bp->mac_addr[0] +
4923adfc5217SJeff Kirsher 	      (bp->mac_addr[1] << 8) +
4924adfc5217SJeff Kirsher 	      (bp->mac_addr[2] << 16) +
4925adfc5217SJeff Kirsher 	      bp->mac_addr[3] +
4926adfc5217SJeff Kirsher 	      (bp->mac_addr[4] << 8) +
4927adfc5217SJeff Kirsher 	      (bp->mac_addr[5] << 16);
4928adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
4929adfc5217SJeff Kirsher 
4930adfc5217SJeff Kirsher 	/* Program the MTU.  Also include 4 bytes for CRC32. */
4931adfc5217SJeff Kirsher 	mtu = bp->dev->mtu;
4932adfc5217SJeff Kirsher 	val = mtu + ETH_HLEN + ETH_FCS_LEN;
4933adfc5217SJeff Kirsher 	if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
4934adfc5217SJeff Kirsher 		val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
4935adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
4936adfc5217SJeff Kirsher 
4937adfc5217SJeff Kirsher 	if (mtu < 1500)
4938adfc5217SJeff Kirsher 		mtu = 1500;
4939adfc5217SJeff Kirsher 
4940adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu));
4941adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
4942adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
4943adfc5217SJeff Kirsher 
4944adfc5217SJeff Kirsher 	memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size);
4945adfc5217SJeff Kirsher 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
4946adfc5217SJeff Kirsher 		bp->bnx2_napi[i].last_status_idx = 0;
4947adfc5217SJeff Kirsher 
4948adfc5217SJeff Kirsher 	bp->idle_chk_status_idx = 0xffff;
4949adfc5217SJeff Kirsher 
4950adfc5217SJeff Kirsher 	bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
4951adfc5217SJeff Kirsher 
4952adfc5217SJeff Kirsher 	/* Set up how to generate a link change interrupt. */
4953adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
4954adfc5217SJeff Kirsher 
4955adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
4956adfc5217SJeff Kirsher 	       (u64) bp->status_blk_mapping & 0xffffffff);
4957adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
4958adfc5217SJeff Kirsher 
4959adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
4960adfc5217SJeff Kirsher 	       (u64) bp->stats_blk_mapping & 0xffffffff);
4961adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
4962adfc5217SJeff Kirsher 	       (u64) bp->stats_blk_mapping >> 32);
4963adfc5217SJeff Kirsher 
4964adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
4965adfc5217SJeff Kirsher 	       (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
4966adfc5217SJeff Kirsher 
4967adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
4968adfc5217SJeff Kirsher 	       (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
4969adfc5217SJeff Kirsher 
4970adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
4971adfc5217SJeff Kirsher 	       (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
4972adfc5217SJeff Kirsher 
4973adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
4974adfc5217SJeff Kirsher 
4975adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
4976adfc5217SJeff Kirsher 
4977adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COM_TICKS,
4978adfc5217SJeff Kirsher 	       (bp->com_ticks_int << 16) | bp->com_ticks);
4979adfc5217SJeff Kirsher 
4980adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_CMD_TICKS,
4981adfc5217SJeff Kirsher 	       (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
4982adfc5217SJeff Kirsher 
4983adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_BROKEN_STATS)
4984adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
4985adfc5217SJeff Kirsher 	else
4986adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
4987adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
4988adfc5217SJeff Kirsher 
4989adfc5217SJeff Kirsher 	if (CHIP_ID(bp) == CHIP_ID_5706_A1)
4990adfc5217SJeff Kirsher 		val = BNX2_HC_CONFIG_COLLECT_STATS;
4991adfc5217SJeff Kirsher 	else {
4992adfc5217SJeff Kirsher 		val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
4993adfc5217SJeff Kirsher 		      BNX2_HC_CONFIG_COLLECT_STATS;
4994adfc5217SJeff Kirsher 	}
4995adfc5217SJeff Kirsher 
4996adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSIX) {
4997adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
4998adfc5217SJeff Kirsher 		       BNX2_HC_MSIX_BIT_VECTOR_VAL);
4999adfc5217SJeff Kirsher 
5000adfc5217SJeff Kirsher 		val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
5001adfc5217SJeff Kirsher 	}
5002adfc5217SJeff Kirsher 
5003adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
5004adfc5217SJeff Kirsher 		val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM;
5005adfc5217SJeff Kirsher 
5006adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_CONFIG, val);
5007adfc5217SJeff Kirsher 
5008adfc5217SJeff Kirsher 	if (bp->rx_ticks < 25)
5009adfc5217SJeff Kirsher 		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
5010adfc5217SJeff Kirsher 	else
5011adfc5217SJeff Kirsher 		bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 0);
5012adfc5217SJeff Kirsher 
5013adfc5217SJeff Kirsher 	for (i = 1; i < bp->irq_nvecs; i++) {
5014adfc5217SJeff Kirsher 		u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
5015adfc5217SJeff Kirsher 			   BNX2_HC_SB_CONFIG_1;
5016adfc5217SJeff Kirsher 
5017adfc5217SJeff Kirsher 		REG_WR(bp, base,
5018adfc5217SJeff Kirsher 			BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
5019adfc5217SJeff Kirsher 			BNX2_HC_SB_CONFIG_1_RX_TMR_MODE |
5020adfc5217SJeff Kirsher 			BNX2_HC_SB_CONFIG_1_ONE_SHOT);
5021adfc5217SJeff Kirsher 
5022adfc5217SJeff Kirsher 		REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
5023adfc5217SJeff Kirsher 			(bp->tx_quick_cons_trip_int << 16) |
5024adfc5217SJeff Kirsher 			 bp->tx_quick_cons_trip);
5025adfc5217SJeff Kirsher 
5026adfc5217SJeff Kirsher 		REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
5027adfc5217SJeff Kirsher 			(bp->tx_ticks_int << 16) | bp->tx_ticks);
5028adfc5217SJeff Kirsher 
5029adfc5217SJeff Kirsher 		REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
5030adfc5217SJeff Kirsher 		       (bp->rx_quick_cons_trip_int << 16) |
5031adfc5217SJeff Kirsher 			bp->rx_quick_cons_trip);
5032adfc5217SJeff Kirsher 
5033adfc5217SJeff Kirsher 		REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
5034adfc5217SJeff Kirsher 			(bp->rx_ticks_int << 16) | bp->rx_ticks);
5035adfc5217SJeff Kirsher 	}
5036adfc5217SJeff Kirsher 
5037adfc5217SJeff Kirsher 	/* Clear internal stats counters. */
5038adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
5039adfc5217SJeff Kirsher 
5040adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
5041adfc5217SJeff Kirsher 
5042adfc5217SJeff Kirsher 	/* Initialize the receive filter. */
5043adfc5217SJeff Kirsher 	bnx2_set_rx_mode(bp->dev);
5044adfc5217SJeff Kirsher 
5045adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
5046adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
5047adfc5217SJeff Kirsher 		val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
5048adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
5049adfc5217SJeff Kirsher 	}
5050adfc5217SJeff Kirsher 	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
5051adfc5217SJeff Kirsher 			  1, 0);
5052adfc5217SJeff Kirsher 
5053adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
5054adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
5055adfc5217SJeff Kirsher 
5056adfc5217SJeff Kirsher 	udelay(20);
5057adfc5217SJeff Kirsher 
5058adfc5217SJeff Kirsher 	bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
5059adfc5217SJeff Kirsher 
5060adfc5217SJeff Kirsher 	return rc;
5061adfc5217SJeff Kirsher }
5062adfc5217SJeff Kirsher 
5063adfc5217SJeff Kirsher static void
5064adfc5217SJeff Kirsher bnx2_clear_ring_states(struct bnx2 *bp)
5065adfc5217SJeff Kirsher {
5066adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
5067adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr;
5068adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr;
5069adfc5217SJeff Kirsher 	int i;
5070adfc5217SJeff Kirsher 
5071adfc5217SJeff Kirsher 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
5072adfc5217SJeff Kirsher 		bnapi = &bp->bnx2_napi[i];
5073adfc5217SJeff Kirsher 		txr = &bnapi->tx_ring;
5074adfc5217SJeff Kirsher 		rxr = &bnapi->rx_ring;
5075adfc5217SJeff Kirsher 
5076adfc5217SJeff Kirsher 		txr->tx_cons = 0;
5077adfc5217SJeff Kirsher 		txr->hw_tx_cons = 0;
5078adfc5217SJeff Kirsher 		rxr->rx_prod_bseq = 0;
5079adfc5217SJeff Kirsher 		rxr->rx_prod = 0;
5080adfc5217SJeff Kirsher 		rxr->rx_cons = 0;
5081adfc5217SJeff Kirsher 		rxr->rx_pg_prod = 0;
5082adfc5217SJeff Kirsher 		rxr->rx_pg_cons = 0;
5083adfc5217SJeff Kirsher 	}
5084adfc5217SJeff Kirsher }
5085adfc5217SJeff Kirsher 
5086adfc5217SJeff Kirsher static void
5087adfc5217SJeff Kirsher bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
5088adfc5217SJeff Kirsher {
5089adfc5217SJeff Kirsher 	u32 val, offset0, offset1, offset2, offset3;
5090adfc5217SJeff Kirsher 	u32 cid_addr = GET_CID_ADDR(cid);
5091adfc5217SJeff Kirsher 
5092adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
5093adfc5217SJeff Kirsher 		offset0 = BNX2_L2CTX_TYPE_XI;
5094adfc5217SJeff Kirsher 		offset1 = BNX2_L2CTX_CMD_TYPE_XI;
5095adfc5217SJeff Kirsher 		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
5096adfc5217SJeff Kirsher 		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
5097adfc5217SJeff Kirsher 	} else {
5098adfc5217SJeff Kirsher 		offset0 = BNX2_L2CTX_TYPE;
5099adfc5217SJeff Kirsher 		offset1 = BNX2_L2CTX_CMD_TYPE;
5100adfc5217SJeff Kirsher 		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
5101adfc5217SJeff Kirsher 		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
5102adfc5217SJeff Kirsher 	}
5103adfc5217SJeff Kirsher 	val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
5104adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, cid_addr, offset0, val);
5105adfc5217SJeff Kirsher 
5106adfc5217SJeff Kirsher 	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
5107adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, cid_addr, offset1, val);
5108adfc5217SJeff Kirsher 
5109adfc5217SJeff Kirsher 	val = (u64) txr->tx_desc_mapping >> 32;
5110adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, cid_addr, offset2, val);
5111adfc5217SJeff Kirsher 
5112adfc5217SJeff Kirsher 	val = (u64) txr->tx_desc_mapping & 0xffffffff;
5113adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, cid_addr, offset3, val);
5114adfc5217SJeff Kirsher }
5115adfc5217SJeff Kirsher 
5116adfc5217SJeff Kirsher static void
5117adfc5217SJeff Kirsher bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
5118adfc5217SJeff Kirsher {
5119adfc5217SJeff Kirsher 	struct tx_bd *txbd;
5120adfc5217SJeff Kirsher 	u32 cid = TX_CID;
5121adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
5122adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr;
5123adfc5217SJeff Kirsher 
5124adfc5217SJeff Kirsher 	bnapi = &bp->bnx2_napi[ring_num];
5125adfc5217SJeff Kirsher 	txr = &bnapi->tx_ring;
5126adfc5217SJeff Kirsher 
5127adfc5217SJeff Kirsher 	if (ring_num == 0)
5128adfc5217SJeff Kirsher 		cid = TX_CID;
5129adfc5217SJeff Kirsher 	else
5130adfc5217SJeff Kirsher 		cid = TX_TSS_CID + ring_num - 1;
5131adfc5217SJeff Kirsher 
5132adfc5217SJeff Kirsher 	bp->tx_wake_thresh = bp->tx_ring_size / 2;
5133adfc5217SJeff Kirsher 
5134adfc5217SJeff Kirsher 	txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT];
5135adfc5217SJeff Kirsher 
5136adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32;
5137adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff;
5138adfc5217SJeff Kirsher 
5139adfc5217SJeff Kirsher 	txr->tx_prod = 0;
5140adfc5217SJeff Kirsher 	txr->tx_prod_bseq = 0;
5141adfc5217SJeff Kirsher 
5142adfc5217SJeff Kirsher 	txr->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX;
5143adfc5217SJeff Kirsher 	txr->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ;
5144adfc5217SJeff Kirsher 
5145adfc5217SJeff Kirsher 	bnx2_init_tx_context(bp, cid, txr);
5146adfc5217SJeff Kirsher }
5147adfc5217SJeff Kirsher 
5148adfc5217SJeff Kirsher static void
5149adfc5217SJeff Kirsher bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
5150adfc5217SJeff Kirsher 		     int num_rings)
5151adfc5217SJeff Kirsher {
5152adfc5217SJeff Kirsher 	int i;
5153adfc5217SJeff Kirsher 	struct rx_bd *rxbd;
5154adfc5217SJeff Kirsher 
5155adfc5217SJeff Kirsher 	for (i = 0; i < num_rings; i++) {
5156adfc5217SJeff Kirsher 		int j;
5157adfc5217SJeff Kirsher 
5158adfc5217SJeff Kirsher 		rxbd = &rx_ring[i][0];
5159adfc5217SJeff Kirsher 		for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
5160adfc5217SJeff Kirsher 			rxbd->rx_bd_len = buf_size;
5161adfc5217SJeff Kirsher 			rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
5162adfc5217SJeff Kirsher 		}
5163adfc5217SJeff Kirsher 		if (i == (num_rings - 1))
5164adfc5217SJeff Kirsher 			j = 0;
5165adfc5217SJeff Kirsher 		else
5166adfc5217SJeff Kirsher 			j = i + 1;
5167adfc5217SJeff Kirsher 		rxbd->rx_bd_haddr_hi = (u64) dma[j] >> 32;
5168adfc5217SJeff Kirsher 		rxbd->rx_bd_haddr_lo = (u64) dma[j] & 0xffffffff;
5169adfc5217SJeff Kirsher 	}
5170adfc5217SJeff Kirsher }
5171adfc5217SJeff Kirsher 
5172adfc5217SJeff Kirsher static void
5173adfc5217SJeff Kirsher bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
5174adfc5217SJeff Kirsher {
5175adfc5217SJeff Kirsher 	int i;
5176adfc5217SJeff Kirsher 	u16 prod, ring_prod;
5177adfc5217SJeff Kirsher 	u32 cid, rx_cid_addr, val;
5178adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[ring_num];
5179adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
5180adfc5217SJeff Kirsher 
5181adfc5217SJeff Kirsher 	if (ring_num == 0)
5182adfc5217SJeff Kirsher 		cid = RX_CID;
5183adfc5217SJeff Kirsher 	else
5184adfc5217SJeff Kirsher 		cid = RX_RSS_CID + ring_num - 1;
5185adfc5217SJeff Kirsher 
5186adfc5217SJeff Kirsher 	rx_cid_addr = GET_CID_ADDR(cid);
5187adfc5217SJeff Kirsher 
5188adfc5217SJeff Kirsher 	bnx2_init_rxbd_rings(rxr->rx_desc_ring, rxr->rx_desc_mapping,
5189adfc5217SJeff Kirsher 			     bp->rx_buf_use_size, bp->rx_max_ring);
5190adfc5217SJeff Kirsher 
5191adfc5217SJeff Kirsher 	bnx2_init_rx_context(bp, cid);
5192adfc5217SJeff Kirsher 
5193adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
5194adfc5217SJeff Kirsher 		val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
5195adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
5196adfc5217SJeff Kirsher 	}
5197adfc5217SJeff Kirsher 
5198adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
5199adfc5217SJeff Kirsher 	if (bp->rx_pg_ring_size) {
5200adfc5217SJeff Kirsher 		bnx2_init_rxbd_rings(rxr->rx_pg_desc_ring,
5201adfc5217SJeff Kirsher 				     rxr->rx_pg_desc_mapping,
5202adfc5217SJeff Kirsher 				     PAGE_SIZE, bp->rx_max_pg_ring);
5203adfc5217SJeff Kirsher 		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
5204adfc5217SJeff Kirsher 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
5205adfc5217SJeff Kirsher 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
5206adfc5217SJeff Kirsher 		       BNX2_L2CTX_RBDC_JUMBO_KEY - ring_num);
5207adfc5217SJeff Kirsher 
5208adfc5217SJeff Kirsher 		val = (u64) rxr->rx_pg_desc_mapping[0] >> 32;
5209adfc5217SJeff Kirsher 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
5210adfc5217SJeff Kirsher 
5211adfc5217SJeff Kirsher 		val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff;
5212adfc5217SJeff Kirsher 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
5213adfc5217SJeff Kirsher 
5214adfc5217SJeff Kirsher 		if (CHIP_NUM(bp) == CHIP_NUM_5709)
5215adfc5217SJeff Kirsher 			REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
5216adfc5217SJeff Kirsher 	}
5217adfc5217SJeff Kirsher 
5218adfc5217SJeff Kirsher 	val = (u64) rxr->rx_desc_mapping[0] >> 32;
5219adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
5220adfc5217SJeff Kirsher 
5221adfc5217SJeff Kirsher 	val = (u64) rxr->rx_desc_mapping[0] & 0xffffffff;
5222adfc5217SJeff Kirsher 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
5223adfc5217SJeff Kirsher 
5224adfc5217SJeff Kirsher 	ring_prod = prod = rxr->rx_pg_prod;
5225adfc5217SJeff Kirsher 	for (i = 0; i < bp->rx_pg_ring_size; i++) {
5226adfc5217SJeff Kirsher 		if (bnx2_alloc_rx_page(bp, rxr, ring_prod, GFP_KERNEL) < 0) {
5227adfc5217SJeff Kirsher 			netdev_warn(bp->dev, "init'ed rx page ring %d with %d/%d pages only\n",
5228adfc5217SJeff Kirsher 				    ring_num, i, bp->rx_pg_ring_size);
5229adfc5217SJeff Kirsher 			break;
5230adfc5217SJeff Kirsher 		}
5231adfc5217SJeff Kirsher 		prod = NEXT_RX_BD(prod);
5232adfc5217SJeff Kirsher 		ring_prod = RX_PG_RING_IDX(prod);
5233adfc5217SJeff Kirsher 	}
5234adfc5217SJeff Kirsher 	rxr->rx_pg_prod = prod;
5235adfc5217SJeff Kirsher 
5236adfc5217SJeff Kirsher 	ring_prod = prod = rxr->rx_prod;
5237adfc5217SJeff Kirsher 	for (i = 0; i < bp->rx_ring_size; i++) {
5238adfc5217SJeff Kirsher 		if (bnx2_alloc_rx_skb(bp, rxr, ring_prod, GFP_KERNEL) < 0) {
5239adfc5217SJeff Kirsher 			netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d skbs only\n",
5240adfc5217SJeff Kirsher 				    ring_num, i, bp->rx_ring_size);
5241adfc5217SJeff Kirsher 			break;
5242adfc5217SJeff Kirsher 		}
5243adfc5217SJeff Kirsher 		prod = NEXT_RX_BD(prod);
5244adfc5217SJeff Kirsher 		ring_prod = RX_RING_IDX(prod);
5245adfc5217SJeff Kirsher 	}
5246adfc5217SJeff Kirsher 	rxr->rx_prod = prod;
5247adfc5217SJeff Kirsher 
5248adfc5217SJeff Kirsher 	rxr->rx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BDIDX;
5249adfc5217SJeff Kirsher 	rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ;
5250adfc5217SJeff Kirsher 	rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX;
5251adfc5217SJeff Kirsher 
5252adfc5217SJeff Kirsher 	REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
5253adfc5217SJeff Kirsher 	REG_WR16(bp, rxr->rx_bidx_addr, prod);
5254adfc5217SJeff Kirsher 
5255adfc5217SJeff Kirsher 	REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
5256adfc5217SJeff Kirsher }
5257adfc5217SJeff Kirsher 
5258adfc5217SJeff Kirsher static void
5259adfc5217SJeff Kirsher bnx2_init_all_rings(struct bnx2 *bp)
5260adfc5217SJeff Kirsher {
5261adfc5217SJeff Kirsher 	int i;
5262adfc5217SJeff Kirsher 	u32 val;
5263adfc5217SJeff Kirsher 
5264adfc5217SJeff Kirsher 	bnx2_clear_ring_states(bp);
5265adfc5217SJeff Kirsher 
5266adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_TSCH_TSS_CFG, 0);
5267adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_tx_rings; i++)
5268adfc5217SJeff Kirsher 		bnx2_init_tx_ring(bp, i);
5269adfc5217SJeff Kirsher 
5270adfc5217SJeff Kirsher 	if (bp->num_tx_rings > 1)
5271adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
5272adfc5217SJeff Kirsher 		       (TX_TSS_CID << 7));
5273adfc5217SJeff Kirsher 
5274adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
5275adfc5217SJeff Kirsher 	bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0);
5276adfc5217SJeff Kirsher 
5277adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_rx_rings; i++)
5278adfc5217SJeff Kirsher 		bnx2_init_rx_ring(bp, i);
5279adfc5217SJeff Kirsher 
5280adfc5217SJeff Kirsher 	if (bp->num_rx_rings > 1) {
5281adfc5217SJeff Kirsher 		u32 tbl_32 = 0;
5282adfc5217SJeff Kirsher 
5283adfc5217SJeff Kirsher 		for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) {
5284adfc5217SJeff Kirsher 			int shift = (i % 8) << 2;
5285adfc5217SJeff Kirsher 
5286adfc5217SJeff Kirsher 			tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
5287adfc5217SJeff Kirsher 			if ((i % 8) == 7) {
5288adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
5289adfc5217SJeff Kirsher 				REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
5290adfc5217SJeff Kirsher 					BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
5291adfc5217SJeff Kirsher 					BNX2_RLUP_RSS_COMMAND_WRITE |
5292adfc5217SJeff Kirsher 					BNX2_RLUP_RSS_COMMAND_HASH_MASK);
5293adfc5217SJeff Kirsher 				tbl_32 = 0;
5294adfc5217SJeff Kirsher 			}
5295adfc5217SJeff Kirsher 		}
5296adfc5217SJeff Kirsher 
5297adfc5217SJeff Kirsher 		val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
5298adfc5217SJeff Kirsher 		      BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI;
5299adfc5217SJeff Kirsher 
5300adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
5301adfc5217SJeff Kirsher 
5302adfc5217SJeff Kirsher 	}
5303adfc5217SJeff Kirsher }
5304adfc5217SJeff Kirsher 
5305adfc5217SJeff Kirsher static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
5306adfc5217SJeff Kirsher {
5307adfc5217SJeff Kirsher 	u32 max, num_rings = 1;
5308adfc5217SJeff Kirsher 
5309adfc5217SJeff Kirsher 	while (ring_size > MAX_RX_DESC_CNT) {
5310adfc5217SJeff Kirsher 		ring_size -= MAX_RX_DESC_CNT;
5311adfc5217SJeff Kirsher 		num_rings++;
5312adfc5217SJeff Kirsher 	}
5313adfc5217SJeff Kirsher 	/* round to next power of 2 */
5314adfc5217SJeff Kirsher 	max = max_size;
5315adfc5217SJeff Kirsher 	while ((max & num_rings) == 0)
5316adfc5217SJeff Kirsher 		max >>= 1;
5317adfc5217SJeff Kirsher 
5318adfc5217SJeff Kirsher 	if (num_rings != max)
5319adfc5217SJeff Kirsher 		max <<= 1;
5320adfc5217SJeff Kirsher 
5321adfc5217SJeff Kirsher 	return max;
5322adfc5217SJeff Kirsher }
5323adfc5217SJeff Kirsher 
5324adfc5217SJeff Kirsher static void
5325adfc5217SJeff Kirsher bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
5326adfc5217SJeff Kirsher {
5327adfc5217SJeff Kirsher 	u32 rx_size, rx_space, jumbo_size;
5328adfc5217SJeff Kirsher 
5329adfc5217SJeff Kirsher 	/* 8 for CRC and VLAN */
5330adfc5217SJeff Kirsher 	rx_size = bp->dev->mtu + ETH_HLEN + BNX2_RX_OFFSET + 8;
5331adfc5217SJeff Kirsher 
5332adfc5217SJeff Kirsher 	rx_space = SKB_DATA_ALIGN(rx_size + BNX2_RX_ALIGN) + NET_SKB_PAD +
5333adfc5217SJeff Kirsher 		sizeof(struct skb_shared_info);
5334adfc5217SJeff Kirsher 
5335adfc5217SJeff Kirsher 	bp->rx_copy_thresh = BNX2_RX_COPY_THRESH;
5336adfc5217SJeff Kirsher 	bp->rx_pg_ring_size = 0;
5337adfc5217SJeff Kirsher 	bp->rx_max_pg_ring = 0;
5338adfc5217SJeff Kirsher 	bp->rx_max_pg_ring_idx = 0;
5339adfc5217SJeff Kirsher 	if ((rx_space > PAGE_SIZE) && !(bp->flags & BNX2_FLAG_JUMBO_BROKEN)) {
5340adfc5217SJeff Kirsher 		int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
5341adfc5217SJeff Kirsher 
5342adfc5217SJeff Kirsher 		jumbo_size = size * pages;
5343adfc5217SJeff Kirsher 		if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT)
5344adfc5217SJeff Kirsher 			jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT;
5345adfc5217SJeff Kirsher 
5346adfc5217SJeff Kirsher 		bp->rx_pg_ring_size = jumbo_size;
5347adfc5217SJeff Kirsher 		bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
5348adfc5217SJeff Kirsher 							MAX_RX_PG_RINGS);
5349adfc5217SJeff Kirsher 		bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
5350adfc5217SJeff Kirsher 		rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET;
5351adfc5217SJeff Kirsher 		bp->rx_copy_thresh = 0;
5352adfc5217SJeff Kirsher 	}
5353adfc5217SJeff Kirsher 
5354adfc5217SJeff Kirsher 	bp->rx_buf_use_size = rx_size;
5355adfc5217SJeff Kirsher 	/* hw alignment */
5356adfc5217SJeff Kirsher 	bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
5357adfc5217SJeff Kirsher 	bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET;
5358adfc5217SJeff Kirsher 	bp->rx_ring_size = size;
5359adfc5217SJeff Kirsher 	bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
5360adfc5217SJeff Kirsher 	bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
5361adfc5217SJeff Kirsher }
5362adfc5217SJeff Kirsher 
5363adfc5217SJeff Kirsher static void
5364adfc5217SJeff Kirsher bnx2_free_tx_skbs(struct bnx2 *bp)
5365adfc5217SJeff Kirsher {
5366adfc5217SJeff Kirsher 	int i;
5367adfc5217SJeff Kirsher 
5368adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_tx_rings; i++) {
5369adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
5370adfc5217SJeff Kirsher 		struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
5371adfc5217SJeff Kirsher 		int j;
5372adfc5217SJeff Kirsher 
5373adfc5217SJeff Kirsher 		if (txr->tx_buf_ring == NULL)
5374adfc5217SJeff Kirsher 			continue;
5375adfc5217SJeff Kirsher 
5376adfc5217SJeff Kirsher 		for (j = 0; j < TX_DESC_CNT; ) {
5377adfc5217SJeff Kirsher 			struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
5378adfc5217SJeff Kirsher 			struct sk_buff *skb = tx_buf->skb;
5379adfc5217SJeff Kirsher 			int k, last;
5380adfc5217SJeff Kirsher 
5381adfc5217SJeff Kirsher 			if (skb == NULL) {
5382adfc5217SJeff Kirsher 				j++;
5383adfc5217SJeff Kirsher 				continue;
5384adfc5217SJeff Kirsher 			}
5385adfc5217SJeff Kirsher 
5386adfc5217SJeff Kirsher 			dma_unmap_single(&bp->pdev->dev,
5387adfc5217SJeff Kirsher 					 dma_unmap_addr(tx_buf, mapping),
5388adfc5217SJeff Kirsher 					 skb_headlen(skb),
5389adfc5217SJeff Kirsher 					 PCI_DMA_TODEVICE);
5390adfc5217SJeff Kirsher 
5391adfc5217SJeff Kirsher 			tx_buf->skb = NULL;
5392adfc5217SJeff Kirsher 
5393adfc5217SJeff Kirsher 			last = tx_buf->nr_frags;
5394adfc5217SJeff Kirsher 			j++;
5395adfc5217SJeff Kirsher 			for (k = 0; k < last; k++, j++) {
5396adfc5217SJeff Kirsher 				tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
5397adfc5217SJeff Kirsher 				dma_unmap_page(&bp->pdev->dev,
5398adfc5217SJeff Kirsher 					dma_unmap_addr(tx_buf, mapping),
5399adfc5217SJeff Kirsher 					skb_shinfo(skb)->frags[k].size,
5400adfc5217SJeff Kirsher 					PCI_DMA_TODEVICE);
5401adfc5217SJeff Kirsher 			}
5402adfc5217SJeff Kirsher 			dev_kfree_skb(skb);
5403adfc5217SJeff Kirsher 		}
5404adfc5217SJeff Kirsher 	}
5405adfc5217SJeff Kirsher }
5406adfc5217SJeff Kirsher 
5407adfc5217SJeff Kirsher static void
5408adfc5217SJeff Kirsher bnx2_free_rx_skbs(struct bnx2 *bp)
5409adfc5217SJeff Kirsher {
5410adfc5217SJeff Kirsher 	int i;
5411adfc5217SJeff Kirsher 
5412adfc5217SJeff Kirsher 	for (i = 0; i < bp->num_rx_rings; i++) {
5413adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
5414adfc5217SJeff Kirsher 		struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
5415adfc5217SJeff Kirsher 		int j;
5416adfc5217SJeff Kirsher 
5417adfc5217SJeff Kirsher 		if (rxr->rx_buf_ring == NULL)
5418adfc5217SJeff Kirsher 			return;
5419adfc5217SJeff Kirsher 
5420adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_ring_idx; j++) {
5421adfc5217SJeff Kirsher 			struct sw_bd *rx_buf = &rxr->rx_buf_ring[j];
5422adfc5217SJeff Kirsher 			struct sk_buff *skb = rx_buf->skb;
5423adfc5217SJeff Kirsher 
5424adfc5217SJeff Kirsher 			if (skb == NULL)
5425adfc5217SJeff Kirsher 				continue;
5426adfc5217SJeff Kirsher 
5427adfc5217SJeff Kirsher 			dma_unmap_single(&bp->pdev->dev,
5428adfc5217SJeff Kirsher 					 dma_unmap_addr(rx_buf, mapping),
5429adfc5217SJeff Kirsher 					 bp->rx_buf_use_size,
5430adfc5217SJeff Kirsher 					 PCI_DMA_FROMDEVICE);
5431adfc5217SJeff Kirsher 
5432adfc5217SJeff Kirsher 			rx_buf->skb = NULL;
5433adfc5217SJeff Kirsher 
5434adfc5217SJeff Kirsher 			dev_kfree_skb(skb);
5435adfc5217SJeff Kirsher 		}
5436adfc5217SJeff Kirsher 		for (j = 0; j < bp->rx_max_pg_ring_idx; j++)
5437adfc5217SJeff Kirsher 			bnx2_free_rx_page(bp, rxr, j);
5438adfc5217SJeff Kirsher 	}
5439adfc5217SJeff Kirsher }
5440adfc5217SJeff Kirsher 
5441adfc5217SJeff Kirsher static void
5442adfc5217SJeff Kirsher bnx2_free_skbs(struct bnx2 *bp)
5443adfc5217SJeff Kirsher {
5444adfc5217SJeff Kirsher 	bnx2_free_tx_skbs(bp);
5445adfc5217SJeff Kirsher 	bnx2_free_rx_skbs(bp);
5446adfc5217SJeff Kirsher }
5447adfc5217SJeff Kirsher 
5448adfc5217SJeff Kirsher static int
5449adfc5217SJeff Kirsher bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
5450adfc5217SJeff Kirsher {
5451adfc5217SJeff Kirsher 	int rc;
5452adfc5217SJeff Kirsher 
5453adfc5217SJeff Kirsher 	rc = bnx2_reset_chip(bp, reset_code);
5454adfc5217SJeff Kirsher 	bnx2_free_skbs(bp);
5455adfc5217SJeff Kirsher 	if (rc)
5456adfc5217SJeff Kirsher 		return rc;
5457adfc5217SJeff Kirsher 
5458adfc5217SJeff Kirsher 	if ((rc = bnx2_init_chip(bp)) != 0)
5459adfc5217SJeff Kirsher 		return rc;
5460adfc5217SJeff Kirsher 
5461adfc5217SJeff Kirsher 	bnx2_init_all_rings(bp);
5462adfc5217SJeff Kirsher 	return 0;
5463adfc5217SJeff Kirsher }
5464adfc5217SJeff Kirsher 
5465adfc5217SJeff Kirsher static int
5466adfc5217SJeff Kirsher bnx2_init_nic(struct bnx2 *bp, int reset_phy)
5467adfc5217SJeff Kirsher {
5468adfc5217SJeff Kirsher 	int rc;
5469adfc5217SJeff Kirsher 
5470adfc5217SJeff Kirsher 	if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
5471adfc5217SJeff Kirsher 		return rc;
5472adfc5217SJeff Kirsher 
5473adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
5474adfc5217SJeff Kirsher 	bnx2_init_phy(bp, reset_phy);
5475adfc5217SJeff Kirsher 	bnx2_set_link(bp);
5476adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
5477adfc5217SJeff Kirsher 		bnx2_remote_phy_event(bp);
5478adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
5479adfc5217SJeff Kirsher 	return 0;
5480adfc5217SJeff Kirsher }
5481adfc5217SJeff Kirsher 
5482adfc5217SJeff Kirsher static int
5483adfc5217SJeff Kirsher bnx2_shutdown_chip(struct bnx2 *bp)
5484adfc5217SJeff Kirsher {
5485adfc5217SJeff Kirsher 	u32 reset_code;
5486adfc5217SJeff Kirsher 
5487adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_NO_WOL)
5488adfc5217SJeff Kirsher 		reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
5489adfc5217SJeff Kirsher 	else if (bp->wol)
5490adfc5217SJeff Kirsher 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
5491adfc5217SJeff Kirsher 	else
5492adfc5217SJeff Kirsher 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
5493adfc5217SJeff Kirsher 
5494adfc5217SJeff Kirsher 	return bnx2_reset_chip(bp, reset_code);
5495adfc5217SJeff Kirsher }
5496adfc5217SJeff Kirsher 
5497adfc5217SJeff Kirsher static int
5498adfc5217SJeff Kirsher bnx2_test_registers(struct bnx2 *bp)
5499adfc5217SJeff Kirsher {
5500adfc5217SJeff Kirsher 	int ret;
5501adfc5217SJeff Kirsher 	int i, is_5709;
5502adfc5217SJeff Kirsher 	static const struct {
5503adfc5217SJeff Kirsher 		u16   offset;
5504adfc5217SJeff Kirsher 		u16   flags;
5505adfc5217SJeff Kirsher #define BNX2_FL_NOT_5709	1
5506adfc5217SJeff Kirsher 		u32   rw_mask;
5507adfc5217SJeff Kirsher 		u32   ro_mask;
5508adfc5217SJeff Kirsher 	} reg_tbl[] = {
5509adfc5217SJeff Kirsher 		{ 0x006c, 0, 0x00000000, 0x0000003f },
5510adfc5217SJeff Kirsher 		{ 0x0090, 0, 0xffffffff, 0x00000000 },
5511adfc5217SJeff Kirsher 		{ 0x0094, 0, 0x00000000, 0x00000000 },
5512adfc5217SJeff Kirsher 
5513adfc5217SJeff Kirsher 		{ 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 },
5514adfc5217SJeff Kirsher 		{ 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5515adfc5217SJeff Kirsher 		{ 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5516adfc5217SJeff Kirsher 		{ 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff },
5517adfc5217SJeff Kirsher 		{ 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 },
5518adfc5217SJeff Kirsher 		{ 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
5519adfc5217SJeff Kirsher 		{ 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff },
5520adfc5217SJeff Kirsher 		{ 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5521adfc5217SJeff Kirsher 		{ 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5522adfc5217SJeff Kirsher 
5523adfc5217SJeff Kirsher 		{ 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5524adfc5217SJeff Kirsher 		{ 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
5525adfc5217SJeff Kirsher 		{ 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
5526adfc5217SJeff Kirsher 		{ 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
5527adfc5217SJeff Kirsher 		{ 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
5528adfc5217SJeff Kirsher 		{ 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
5529adfc5217SJeff Kirsher 
5530adfc5217SJeff Kirsher 		{ 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
5531adfc5217SJeff Kirsher 		{ 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 },
5532adfc5217SJeff Kirsher 		{ 0x0c08, BNX2_FL_NOT_5709,  0x0f0ff073, 0x00000000 },
5533adfc5217SJeff Kirsher 
5534adfc5217SJeff Kirsher 		{ 0x1000, 0, 0x00000000, 0x00000001 },
5535adfc5217SJeff Kirsher 		{ 0x1004, BNX2_FL_NOT_5709, 0x00000000, 0x000f0001 },
5536adfc5217SJeff Kirsher 
5537adfc5217SJeff Kirsher 		{ 0x1408, 0, 0x01c00800, 0x00000000 },
5538adfc5217SJeff Kirsher 		{ 0x149c, 0, 0x8000ffff, 0x00000000 },
5539adfc5217SJeff Kirsher 		{ 0x14a8, 0, 0x00000000, 0x000001ff },
5540adfc5217SJeff Kirsher 		{ 0x14ac, 0, 0x0fffffff, 0x10000000 },
5541adfc5217SJeff Kirsher 		{ 0x14b0, 0, 0x00000002, 0x00000001 },
5542adfc5217SJeff Kirsher 		{ 0x14b8, 0, 0x00000000, 0x00000000 },
5543adfc5217SJeff Kirsher 		{ 0x14c0, 0, 0x00000000, 0x00000009 },
5544adfc5217SJeff Kirsher 		{ 0x14c4, 0, 0x00003fff, 0x00000000 },
5545adfc5217SJeff Kirsher 		{ 0x14cc, 0, 0x00000000, 0x00000001 },
5546adfc5217SJeff Kirsher 		{ 0x14d0, 0, 0xffffffff, 0x00000000 },
5547adfc5217SJeff Kirsher 
5548adfc5217SJeff Kirsher 		{ 0x1800, 0, 0x00000000, 0x00000001 },
5549adfc5217SJeff Kirsher 		{ 0x1804, 0, 0x00000000, 0x00000003 },
5550adfc5217SJeff Kirsher 
5551adfc5217SJeff Kirsher 		{ 0x2800, 0, 0x00000000, 0x00000001 },
5552adfc5217SJeff Kirsher 		{ 0x2804, 0, 0x00000000, 0x00003f01 },
5553adfc5217SJeff Kirsher 		{ 0x2808, 0, 0x0f3f3f03, 0x00000000 },
5554adfc5217SJeff Kirsher 		{ 0x2810, 0, 0xffff0000, 0x00000000 },
5555adfc5217SJeff Kirsher 		{ 0x2814, 0, 0xffff0000, 0x00000000 },
5556adfc5217SJeff Kirsher 		{ 0x2818, 0, 0xffff0000, 0x00000000 },
5557adfc5217SJeff Kirsher 		{ 0x281c, 0, 0xffff0000, 0x00000000 },
5558adfc5217SJeff Kirsher 		{ 0x2834, 0, 0xffffffff, 0x00000000 },
5559adfc5217SJeff Kirsher 		{ 0x2840, 0, 0x00000000, 0xffffffff },
5560adfc5217SJeff Kirsher 		{ 0x2844, 0, 0x00000000, 0xffffffff },
5561adfc5217SJeff Kirsher 		{ 0x2848, 0, 0xffffffff, 0x00000000 },
5562adfc5217SJeff Kirsher 		{ 0x284c, 0, 0xf800f800, 0x07ff07ff },
5563adfc5217SJeff Kirsher 
5564adfc5217SJeff Kirsher 		{ 0x2c00, 0, 0x00000000, 0x00000011 },
5565adfc5217SJeff Kirsher 		{ 0x2c04, 0, 0x00000000, 0x00030007 },
5566adfc5217SJeff Kirsher 
5567adfc5217SJeff Kirsher 		{ 0x3c00, 0, 0x00000000, 0x00000001 },
5568adfc5217SJeff Kirsher 		{ 0x3c04, 0, 0x00000000, 0x00070000 },
5569adfc5217SJeff Kirsher 		{ 0x3c08, 0, 0x00007f71, 0x07f00000 },
5570adfc5217SJeff Kirsher 		{ 0x3c0c, 0, 0x1f3ffffc, 0x00000000 },
5571adfc5217SJeff Kirsher 		{ 0x3c10, 0, 0xffffffff, 0x00000000 },
5572adfc5217SJeff Kirsher 		{ 0x3c14, 0, 0x00000000, 0xffffffff },
5573adfc5217SJeff Kirsher 		{ 0x3c18, 0, 0x00000000, 0xffffffff },
5574adfc5217SJeff Kirsher 		{ 0x3c1c, 0, 0xfffff000, 0x00000000 },
5575adfc5217SJeff Kirsher 		{ 0x3c20, 0, 0xffffff00, 0x00000000 },
5576adfc5217SJeff Kirsher 
5577adfc5217SJeff Kirsher 		{ 0x5004, 0, 0x00000000, 0x0000007f },
5578adfc5217SJeff Kirsher 		{ 0x5008, 0, 0x0f0007ff, 0x00000000 },
5579adfc5217SJeff Kirsher 
5580adfc5217SJeff Kirsher 		{ 0x5c00, 0, 0x00000000, 0x00000001 },
5581adfc5217SJeff Kirsher 		{ 0x5c04, 0, 0x00000000, 0x0003000f },
5582adfc5217SJeff Kirsher 		{ 0x5c08, 0, 0x00000003, 0x00000000 },
5583adfc5217SJeff Kirsher 		{ 0x5c0c, 0, 0x0000fff8, 0x00000000 },
5584adfc5217SJeff Kirsher 		{ 0x5c10, 0, 0x00000000, 0xffffffff },
5585adfc5217SJeff Kirsher 		{ 0x5c80, 0, 0x00000000, 0x0f7113f1 },
5586adfc5217SJeff Kirsher 		{ 0x5c84, 0, 0x00000000, 0x0000f333 },
5587adfc5217SJeff Kirsher 		{ 0x5c88, 0, 0x00000000, 0x00077373 },
5588adfc5217SJeff Kirsher 		{ 0x5c8c, 0, 0x00000000, 0x0007f737 },
5589adfc5217SJeff Kirsher 
5590adfc5217SJeff Kirsher 		{ 0x6808, 0, 0x0000ff7f, 0x00000000 },
5591adfc5217SJeff Kirsher 		{ 0x680c, 0, 0xffffffff, 0x00000000 },
5592adfc5217SJeff Kirsher 		{ 0x6810, 0, 0xffffffff, 0x00000000 },
5593adfc5217SJeff Kirsher 		{ 0x6814, 0, 0xffffffff, 0x00000000 },
5594adfc5217SJeff Kirsher 		{ 0x6818, 0, 0xffffffff, 0x00000000 },
5595adfc5217SJeff Kirsher 		{ 0x681c, 0, 0xffffffff, 0x00000000 },
5596adfc5217SJeff Kirsher 		{ 0x6820, 0, 0x00ff00ff, 0x00000000 },
5597adfc5217SJeff Kirsher 		{ 0x6824, 0, 0x00ff00ff, 0x00000000 },
5598adfc5217SJeff Kirsher 		{ 0x6828, 0, 0x00ff00ff, 0x00000000 },
5599adfc5217SJeff Kirsher 		{ 0x682c, 0, 0x03ff03ff, 0x00000000 },
5600adfc5217SJeff Kirsher 		{ 0x6830, 0, 0x03ff03ff, 0x00000000 },
5601adfc5217SJeff Kirsher 		{ 0x6834, 0, 0x03ff03ff, 0x00000000 },
5602adfc5217SJeff Kirsher 		{ 0x6838, 0, 0x03ff03ff, 0x00000000 },
5603adfc5217SJeff Kirsher 		{ 0x683c, 0, 0x0000ffff, 0x00000000 },
5604adfc5217SJeff Kirsher 		{ 0x6840, 0, 0x00000ff0, 0x00000000 },
5605adfc5217SJeff Kirsher 		{ 0x6844, 0, 0x00ffff00, 0x00000000 },
5606adfc5217SJeff Kirsher 		{ 0x684c, 0, 0xffffffff, 0x00000000 },
5607adfc5217SJeff Kirsher 		{ 0x6850, 0, 0x7f7f7f7f, 0x00000000 },
5608adfc5217SJeff Kirsher 		{ 0x6854, 0, 0x7f7f7f7f, 0x00000000 },
5609adfc5217SJeff Kirsher 		{ 0x6858, 0, 0x7f7f7f7f, 0x00000000 },
5610adfc5217SJeff Kirsher 		{ 0x685c, 0, 0x7f7f7f7f, 0x00000000 },
5611adfc5217SJeff Kirsher 		{ 0x6908, 0, 0x00000000, 0x0001ff0f },
5612adfc5217SJeff Kirsher 		{ 0x690c, 0, 0x00000000, 0x0ffe00f0 },
5613adfc5217SJeff Kirsher 
5614adfc5217SJeff Kirsher 		{ 0xffff, 0, 0x00000000, 0x00000000 },
5615adfc5217SJeff Kirsher 	};
5616adfc5217SJeff Kirsher 
5617adfc5217SJeff Kirsher 	ret = 0;
5618adfc5217SJeff Kirsher 	is_5709 = 0;
5619adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
5620adfc5217SJeff Kirsher 		is_5709 = 1;
5621adfc5217SJeff Kirsher 
5622adfc5217SJeff Kirsher 	for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
5623adfc5217SJeff Kirsher 		u32 offset, rw_mask, ro_mask, save_val, val;
5624adfc5217SJeff Kirsher 		u16 flags = reg_tbl[i].flags;
5625adfc5217SJeff Kirsher 
5626adfc5217SJeff Kirsher 		if (is_5709 && (flags & BNX2_FL_NOT_5709))
5627adfc5217SJeff Kirsher 			continue;
5628adfc5217SJeff Kirsher 
5629adfc5217SJeff Kirsher 		offset = (u32) reg_tbl[i].offset;
5630adfc5217SJeff Kirsher 		rw_mask = reg_tbl[i].rw_mask;
5631adfc5217SJeff Kirsher 		ro_mask = reg_tbl[i].ro_mask;
5632adfc5217SJeff Kirsher 
5633adfc5217SJeff Kirsher 		save_val = readl(bp->regview + offset);
5634adfc5217SJeff Kirsher 
5635adfc5217SJeff Kirsher 		writel(0, bp->regview + offset);
5636adfc5217SJeff Kirsher 
5637adfc5217SJeff Kirsher 		val = readl(bp->regview + offset);
5638adfc5217SJeff Kirsher 		if ((val & rw_mask) != 0) {
5639adfc5217SJeff Kirsher 			goto reg_test_err;
5640adfc5217SJeff Kirsher 		}
5641adfc5217SJeff Kirsher 
5642adfc5217SJeff Kirsher 		if ((val & ro_mask) != (save_val & ro_mask)) {
5643adfc5217SJeff Kirsher 			goto reg_test_err;
5644adfc5217SJeff Kirsher 		}
5645adfc5217SJeff Kirsher 
5646adfc5217SJeff Kirsher 		writel(0xffffffff, bp->regview + offset);
5647adfc5217SJeff Kirsher 
5648adfc5217SJeff Kirsher 		val = readl(bp->regview + offset);
5649adfc5217SJeff Kirsher 		if ((val & rw_mask) != rw_mask) {
5650adfc5217SJeff Kirsher 			goto reg_test_err;
5651adfc5217SJeff Kirsher 		}
5652adfc5217SJeff Kirsher 
5653adfc5217SJeff Kirsher 		if ((val & ro_mask) != (save_val & ro_mask)) {
5654adfc5217SJeff Kirsher 			goto reg_test_err;
5655adfc5217SJeff Kirsher 		}
5656adfc5217SJeff Kirsher 
5657adfc5217SJeff Kirsher 		writel(save_val, bp->regview + offset);
5658adfc5217SJeff Kirsher 		continue;
5659adfc5217SJeff Kirsher 
5660adfc5217SJeff Kirsher reg_test_err:
5661adfc5217SJeff Kirsher 		writel(save_val, bp->regview + offset);
5662adfc5217SJeff Kirsher 		ret = -ENODEV;
5663adfc5217SJeff Kirsher 		break;
5664adfc5217SJeff Kirsher 	}
5665adfc5217SJeff Kirsher 	return ret;
5666adfc5217SJeff Kirsher }
5667adfc5217SJeff Kirsher 
5668adfc5217SJeff Kirsher static int
5669adfc5217SJeff Kirsher bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
5670adfc5217SJeff Kirsher {
5671adfc5217SJeff Kirsher 	static const u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
5672adfc5217SJeff Kirsher 		0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
5673adfc5217SJeff Kirsher 	int i;
5674adfc5217SJeff Kirsher 
5675adfc5217SJeff Kirsher 	for (i = 0; i < sizeof(test_pattern) / 4; i++) {
5676adfc5217SJeff Kirsher 		u32 offset;
5677adfc5217SJeff Kirsher 
5678adfc5217SJeff Kirsher 		for (offset = 0; offset < size; offset += 4) {
5679adfc5217SJeff Kirsher 
5680adfc5217SJeff Kirsher 			bnx2_reg_wr_ind(bp, start + offset, test_pattern[i]);
5681adfc5217SJeff Kirsher 
5682adfc5217SJeff Kirsher 			if (bnx2_reg_rd_ind(bp, start + offset) !=
5683adfc5217SJeff Kirsher 				test_pattern[i]) {
5684adfc5217SJeff Kirsher 				return -ENODEV;
5685adfc5217SJeff Kirsher 			}
5686adfc5217SJeff Kirsher 		}
5687adfc5217SJeff Kirsher 	}
5688adfc5217SJeff Kirsher 	return 0;
5689adfc5217SJeff Kirsher }
5690adfc5217SJeff Kirsher 
5691adfc5217SJeff Kirsher static int
5692adfc5217SJeff Kirsher bnx2_test_memory(struct bnx2 *bp)
5693adfc5217SJeff Kirsher {
5694adfc5217SJeff Kirsher 	int ret = 0;
5695adfc5217SJeff Kirsher 	int i;
5696adfc5217SJeff Kirsher 	static struct mem_entry {
5697adfc5217SJeff Kirsher 		u32   offset;
5698adfc5217SJeff Kirsher 		u32   len;
5699adfc5217SJeff Kirsher 	} mem_tbl_5706[] = {
5700adfc5217SJeff Kirsher 		{ 0x60000,  0x4000 },
5701adfc5217SJeff Kirsher 		{ 0xa0000,  0x3000 },
5702adfc5217SJeff Kirsher 		{ 0xe0000,  0x4000 },
5703adfc5217SJeff Kirsher 		{ 0x120000, 0x4000 },
5704adfc5217SJeff Kirsher 		{ 0x1a0000, 0x4000 },
5705adfc5217SJeff Kirsher 		{ 0x160000, 0x4000 },
5706adfc5217SJeff Kirsher 		{ 0xffffffff, 0    },
5707adfc5217SJeff Kirsher 	},
5708adfc5217SJeff Kirsher 	mem_tbl_5709[] = {
5709adfc5217SJeff Kirsher 		{ 0x60000,  0x4000 },
5710adfc5217SJeff Kirsher 		{ 0xa0000,  0x3000 },
5711adfc5217SJeff Kirsher 		{ 0xe0000,  0x4000 },
5712adfc5217SJeff Kirsher 		{ 0x120000, 0x4000 },
5713adfc5217SJeff Kirsher 		{ 0x1a0000, 0x4000 },
5714adfc5217SJeff Kirsher 		{ 0xffffffff, 0    },
5715adfc5217SJeff Kirsher 	};
5716adfc5217SJeff Kirsher 	struct mem_entry *mem_tbl;
5717adfc5217SJeff Kirsher 
5718adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
5719adfc5217SJeff Kirsher 		mem_tbl = mem_tbl_5709;
5720adfc5217SJeff Kirsher 	else
5721adfc5217SJeff Kirsher 		mem_tbl = mem_tbl_5706;
5722adfc5217SJeff Kirsher 
5723adfc5217SJeff Kirsher 	for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
5724adfc5217SJeff Kirsher 		if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset,
5725adfc5217SJeff Kirsher 			mem_tbl[i].len)) != 0) {
5726adfc5217SJeff Kirsher 			return ret;
5727adfc5217SJeff Kirsher 		}
5728adfc5217SJeff Kirsher 	}
5729adfc5217SJeff Kirsher 
5730adfc5217SJeff Kirsher 	return ret;
5731adfc5217SJeff Kirsher }
5732adfc5217SJeff Kirsher 
5733adfc5217SJeff Kirsher #define BNX2_MAC_LOOPBACK	0
5734adfc5217SJeff Kirsher #define BNX2_PHY_LOOPBACK	1
5735adfc5217SJeff Kirsher 
5736adfc5217SJeff Kirsher static int
5737adfc5217SJeff Kirsher bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
5738adfc5217SJeff Kirsher {
5739adfc5217SJeff Kirsher 	unsigned int pkt_size, num_pkts, i;
5740adfc5217SJeff Kirsher 	struct sk_buff *skb, *rx_skb;
5741adfc5217SJeff Kirsher 	unsigned char *packet;
5742adfc5217SJeff Kirsher 	u16 rx_start_idx, rx_idx;
5743adfc5217SJeff Kirsher 	dma_addr_t map;
5744adfc5217SJeff Kirsher 	struct tx_bd *txbd;
5745adfc5217SJeff Kirsher 	struct sw_bd *rx_buf;
5746adfc5217SJeff Kirsher 	struct l2_fhdr *rx_hdr;
5747adfc5217SJeff Kirsher 	int ret = -ENODEV;
5748adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
5749adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
5750adfc5217SJeff Kirsher 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
5751adfc5217SJeff Kirsher 
5752adfc5217SJeff Kirsher 	tx_napi = bnapi;
5753adfc5217SJeff Kirsher 
5754adfc5217SJeff Kirsher 	txr = &tx_napi->tx_ring;
5755adfc5217SJeff Kirsher 	rxr = &bnapi->rx_ring;
5756adfc5217SJeff Kirsher 	if (loopback_mode == BNX2_MAC_LOOPBACK) {
5757adfc5217SJeff Kirsher 		bp->loopback = MAC_LOOPBACK;
5758adfc5217SJeff Kirsher 		bnx2_set_mac_loopback(bp);
5759adfc5217SJeff Kirsher 	}
5760adfc5217SJeff Kirsher 	else if (loopback_mode == BNX2_PHY_LOOPBACK) {
5761adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
5762adfc5217SJeff Kirsher 			return 0;
5763adfc5217SJeff Kirsher 
5764adfc5217SJeff Kirsher 		bp->loopback = PHY_LOOPBACK;
5765adfc5217SJeff Kirsher 		bnx2_set_phy_loopback(bp);
5766adfc5217SJeff Kirsher 	}
5767adfc5217SJeff Kirsher 	else
5768adfc5217SJeff Kirsher 		return -EINVAL;
5769adfc5217SJeff Kirsher 
5770adfc5217SJeff Kirsher 	pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_jumbo_thresh - 4);
5771adfc5217SJeff Kirsher 	skb = netdev_alloc_skb(bp->dev, pkt_size);
5772adfc5217SJeff Kirsher 	if (!skb)
5773adfc5217SJeff Kirsher 		return -ENOMEM;
5774adfc5217SJeff Kirsher 	packet = skb_put(skb, pkt_size);
5775adfc5217SJeff Kirsher 	memcpy(packet, bp->dev->dev_addr, 6);
5776adfc5217SJeff Kirsher 	memset(packet + 6, 0x0, 8);
5777adfc5217SJeff Kirsher 	for (i = 14; i < pkt_size; i++)
5778adfc5217SJeff Kirsher 		packet[i] = (unsigned char) (i & 0xff);
5779adfc5217SJeff Kirsher 
5780adfc5217SJeff Kirsher 	map = dma_map_single(&bp->pdev->dev, skb->data, pkt_size,
5781adfc5217SJeff Kirsher 			     PCI_DMA_TODEVICE);
5782adfc5217SJeff Kirsher 	if (dma_mapping_error(&bp->pdev->dev, map)) {
5783adfc5217SJeff Kirsher 		dev_kfree_skb(skb);
5784adfc5217SJeff Kirsher 		return -EIO;
5785adfc5217SJeff Kirsher 	}
5786adfc5217SJeff Kirsher 
5787adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMMAND,
5788adfc5217SJeff Kirsher 	       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
5789adfc5217SJeff Kirsher 
5790adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_HC_COMMAND);
5791adfc5217SJeff Kirsher 
5792adfc5217SJeff Kirsher 	udelay(5);
5793adfc5217SJeff Kirsher 	rx_start_idx = bnx2_get_hw_rx_cons(bnapi);
5794adfc5217SJeff Kirsher 
5795adfc5217SJeff Kirsher 	num_pkts = 0;
5796adfc5217SJeff Kirsher 
5797adfc5217SJeff Kirsher 	txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)];
5798adfc5217SJeff Kirsher 
5799adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_hi = (u64) map >> 32;
5800adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
5801adfc5217SJeff Kirsher 	txbd->tx_bd_mss_nbytes = pkt_size;
5802adfc5217SJeff Kirsher 	txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
5803adfc5217SJeff Kirsher 
5804adfc5217SJeff Kirsher 	num_pkts++;
5805adfc5217SJeff Kirsher 	txr->tx_prod = NEXT_TX_BD(txr->tx_prod);
5806adfc5217SJeff Kirsher 	txr->tx_prod_bseq += pkt_size;
5807adfc5217SJeff Kirsher 
5808adfc5217SJeff Kirsher 	REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
5809adfc5217SJeff Kirsher 	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
5810adfc5217SJeff Kirsher 
5811adfc5217SJeff Kirsher 	udelay(100);
5812adfc5217SJeff Kirsher 
5813adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMMAND,
5814adfc5217SJeff Kirsher 	       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
5815adfc5217SJeff Kirsher 
5816adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_HC_COMMAND);
5817adfc5217SJeff Kirsher 
5818adfc5217SJeff Kirsher 	udelay(5);
5819adfc5217SJeff Kirsher 
5820adfc5217SJeff Kirsher 	dma_unmap_single(&bp->pdev->dev, map, pkt_size, PCI_DMA_TODEVICE);
5821adfc5217SJeff Kirsher 	dev_kfree_skb(skb);
5822adfc5217SJeff Kirsher 
5823adfc5217SJeff Kirsher 	if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod)
5824adfc5217SJeff Kirsher 		goto loopback_test_done;
5825adfc5217SJeff Kirsher 
5826adfc5217SJeff Kirsher 	rx_idx = bnx2_get_hw_rx_cons(bnapi);
5827adfc5217SJeff Kirsher 	if (rx_idx != rx_start_idx + num_pkts) {
5828adfc5217SJeff Kirsher 		goto loopback_test_done;
5829adfc5217SJeff Kirsher 	}
5830adfc5217SJeff Kirsher 
5831adfc5217SJeff Kirsher 	rx_buf = &rxr->rx_buf_ring[rx_start_idx];
5832adfc5217SJeff Kirsher 	rx_skb = rx_buf->skb;
5833adfc5217SJeff Kirsher 
5834adfc5217SJeff Kirsher 	rx_hdr = rx_buf->desc;
5835adfc5217SJeff Kirsher 	skb_reserve(rx_skb, BNX2_RX_OFFSET);
5836adfc5217SJeff Kirsher 
5837adfc5217SJeff Kirsher 	dma_sync_single_for_cpu(&bp->pdev->dev,
5838adfc5217SJeff Kirsher 		dma_unmap_addr(rx_buf, mapping),
5839adfc5217SJeff Kirsher 		bp->rx_buf_size, PCI_DMA_FROMDEVICE);
5840adfc5217SJeff Kirsher 
5841adfc5217SJeff Kirsher 	if (rx_hdr->l2_fhdr_status &
5842adfc5217SJeff Kirsher 		(L2_FHDR_ERRORS_BAD_CRC |
5843adfc5217SJeff Kirsher 		L2_FHDR_ERRORS_PHY_DECODE |
5844adfc5217SJeff Kirsher 		L2_FHDR_ERRORS_ALIGNMENT |
5845adfc5217SJeff Kirsher 		L2_FHDR_ERRORS_TOO_SHORT |
5846adfc5217SJeff Kirsher 		L2_FHDR_ERRORS_GIANT_FRAME)) {
5847adfc5217SJeff Kirsher 
5848adfc5217SJeff Kirsher 		goto loopback_test_done;
5849adfc5217SJeff Kirsher 	}
5850adfc5217SJeff Kirsher 
5851adfc5217SJeff Kirsher 	if ((rx_hdr->l2_fhdr_pkt_len - 4) != pkt_size) {
5852adfc5217SJeff Kirsher 		goto loopback_test_done;
5853adfc5217SJeff Kirsher 	}
5854adfc5217SJeff Kirsher 
5855adfc5217SJeff Kirsher 	for (i = 14; i < pkt_size; i++) {
5856adfc5217SJeff Kirsher 		if (*(rx_skb->data + i) != (unsigned char) (i & 0xff)) {
5857adfc5217SJeff Kirsher 			goto loopback_test_done;
5858adfc5217SJeff Kirsher 		}
5859adfc5217SJeff Kirsher 	}
5860adfc5217SJeff Kirsher 
5861adfc5217SJeff Kirsher 	ret = 0;
5862adfc5217SJeff Kirsher 
5863adfc5217SJeff Kirsher loopback_test_done:
5864adfc5217SJeff Kirsher 	bp->loopback = 0;
5865adfc5217SJeff Kirsher 	return ret;
5866adfc5217SJeff Kirsher }
5867adfc5217SJeff Kirsher 
5868adfc5217SJeff Kirsher #define BNX2_MAC_LOOPBACK_FAILED	1
5869adfc5217SJeff Kirsher #define BNX2_PHY_LOOPBACK_FAILED	2
5870adfc5217SJeff Kirsher #define BNX2_LOOPBACK_FAILED		(BNX2_MAC_LOOPBACK_FAILED |	\
5871adfc5217SJeff Kirsher 					 BNX2_PHY_LOOPBACK_FAILED)
5872adfc5217SJeff Kirsher 
5873adfc5217SJeff Kirsher static int
5874adfc5217SJeff Kirsher bnx2_test_loopback(struct bnx2 *bp)
5875adfc5217SJeff Kirsher {
5876adfc5217SJeff Kirsher 	int rc = 0;
5877adfc5217SJeff Kirsher 
5878adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
5879adfc5217SJeff Kirsher 		return BNX2_LOOPBACK_FAILED;
5880adfc5217SJeff Kirsher 
5881adfc5217SJeff Kirsher 	bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
5882adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
5883adfc5217SJeff Kirsher 	bnx2_init_phy(bp, 1);
5884adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
5885adfc5217SJeff Kirsher 	if (bnx2_run_loopback(bp, BNX2_MAC_LOOPBACK))
5886adfc5217SJeff Kirsher 		rc |= BNX2_MAC_LOOPBACK_FAILED;
5887adfc5217SJeff Kirsher 	if (bnx2_run_loopback(bp, BNX2_PHY_LOOPBACK))
5888adfc5217SJeff Kirsher 		rc |= BNX2_PHY_LOOPBACK_FAILED;
5889adfc5217SJeff Kirsher 	return rc;
5890adfc5217SJeff Kirsher }
5891adfc5217SJeff Kirsher 
5892adfc5217SJeff Kirsher #define NVRAM_SIZE 0x200
5893adfc5217SJeff Kirsher #define CRC32_RESIDUAL 0xdebb20e3
5894adfc5217SJeff Kirsher 
5895adfc5217SJeff Kirsher static int
5896adfc5217SJeff Kirsher bnx2_test_nvram(struct bnx2 *bp)
5897adfc5217SJeff Kirsher {
5898adfc5217SJeff Kirsher 	__be32 buf[NVRAM_SIZE / 4];
5899adfc5217SJeff Kirsher 	u8 *data = (u8 *) buf;
5900adfc5217SJeff Kirsher 	int rc = 0;
5901adfc5217SJeff Kirsher 	u32 magic, csum;
5902adfc5217SJeff Kirsher 
5903adfc5217SJeff Kirsher 	if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0)
5904adfc5217SJeff Kirsher 		goto test_nvram_done;
5905adfc5217SJeff Kirsher 
5906adfc5217SJeff Kirsher         magic = be32_to_cpu(buf[0]);
5907adfc5217SJeff Kirsher 	if (magic != 0x669955aa) {
5908adfc5217SJeff Kirsher 		rc = -ENODEV;
5909adfc5217SJeff Kirsher 		goto test_nvram_done;
5910adfc5217SJeff Kirsher 	}
5911adfc5217SJeff Kirsher 
5912adfc5217SJeff Kirsher 	if ((rc = bnx2_nvram_read(bp, 0x100, data, NVRAM_SIZE)) != 0)
5913adfc5217SJeff Kirsher 		goto test_nvram_done;
5914adfc5217SJeff Kirsher 
5915adfc5217SJeff Kirsher 	csum = ether_crc_le(0x100, data);
5916adfc5217SJeff Kirsher 	if (csum != CRC32_RESIDUAL) {
5917adfc5217SJeff Kirsher 		rc = -ENODEV;
5918adfc5217SJeff Kirsher 		goto test_nvram_done;
5919adfc5217SJeff Kirsher 	}
5920adfc5217SJeff Kirsher 
5921adfc5217SJeff Kirsher 	csum = ether_crc_le(0x100, data + 0x100);
5922adfc5217SJeff Kirsher 	if (csum != CRC32_RESIDUAL) {
5923adfc5217SJeff Kirsher 		rc = -ENODEV;
5924adfc5217SJeff Kirsher 	}
5925adfc5217SJeff Kirsher 
5926adfc5217SJeff Kirsher test_nvram_done:
5927adfc5217SJeff Kirsher 	return rc;
5928adfc5217SJeff Kirsher }
5929adfc5217SJeff Kirsher 
5930adfc5217SJeff Kirsher static int
5931adfc5217SJeff Kirsher bnx2_test_link(struct bnx2 *bp)
5932adfc5217SJeff Kirsher {
5933adfc5217SJeff Kirsher 	u32 bmsr;
5934adfc5217SJeff Kirsher 
5935adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
5936adfc5217SJeff Kirsher 		return -ENODEV;
5937adfc5217SJeff Kirsher 
5938adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
5939adfc5217SJeff Kirsher 		if (bp->link_up)
5940adfc5217SJeff Kirsher 			return 0;
5941adfc5217SJeff Kirsher 		return -ENODEV;
5942adfc5217SJeff Kirsher 	}
5943adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
5944adfc5217SJeff Kirsher 	bnx2_enable_bmsr1(bp);
5945adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
5946adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
5947adfc5217SJeff Kirsher 	bnx2_disable_bmsr1(bp);
5948adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
5949adfc5217SJeff Kirsher 
5950adfc5217SJeff Kirsher 	if (bmsr & BMSR_LSTATUS) {
5951adfc5217SJeff Kirsher 		return 0;
5952adfc5217SJeff Kirsher 	}
5953adfc5217SJeff Kirsher 	return -ENODEV;
5954adfc5217SJeff Kirsher }
5955adfc5217SJeff Kirsher 
5956adfc5217SJeff Kirsher static int
5957adfc5217SJeff Kirsher bnx2_test_intr(struct bnx2 *bp)
5958adfc5217SJeff Kirsher {
5959adfc5217SJeff Kirsher 	int i;
5960adfc5217SJeff Kirsher 	u16 status_idx;
5961adfc5217SJeff Kirsher 
5962adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
5963adfc5217SJeff Kirsher 		return -ENODEV;
5964adfc5217SJeff Kirsher 
5965adfc5217SJeff Kirsher 	status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
5966adfc5217SJeff Kirsher 
5967adfc5217SJeff Kirsher 	/* This register is not touched during run-time. */
5968adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
5969adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_HC_COMMAND);
5970adfc5217SJeff Kirsher 
5971adfc5217SJeff Kirsher 	for (i = 0; i < 10; i++) {
5972adfc5217SJeff Kirsher 		if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
5973adfc5217SJeff Kirsher 			status_idx) {
5974adfc5217SJeff Kirsher 
5975adfc5217SJeff Kirsher 			break;
5976adfc5217SJeff Kirsher 		}
5977adfc5217SJeff Kirsher 
5978adfc5217SJeff Kirsher 		msleep_interruptible(10);
5979adfc5217SJeff Kirsher 	}
5980adfc5217SJeff Kirsher 	if (i < 10)
5981adfc5217SJeff Kirsher 		return 0;
5982adfc5217SJeff Kirsher 
5983adfc5217SJeff Kirsher 	return -ENODEV;
5984adfc5217SJeff Kirsher }
5985adfc5217SJeff Kirsher 
5986adfc5217SJeff Kirsher /* Determining link for parallel detection. */
5987adfc5217SJeff Kirsher static int
5988adfc5217SJeff Kirsher bnx2_5706_serdes_has_link(struct bnx2 *bp)
5989adfc5217SJeff Kirsher {
5990adfc5217SJeff Kirsher 	u32 mode_ctl, an_dbg, exp;
5991adfc5217SJeff Kirsher 
5992adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_NO_PARALLEL)
5993adfc5217SJeff Kirsher 		return 0;
5994adfc5217SJeff Kirsher 
5995adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_MODE_CTL);
5996adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &mode_ctl);
5997adfc5217SJeff Kirsher 
5998adfc5217SJeff Kirsher 	if (!(mode_ctl & MISC_SHDW_MODE_CTL_SIG_DET))
5999adfc5217SJeff Kirsher 		return 0;
6000adfc5217SJeff Kirsher 
6001adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
6002adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
6003adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
6004adfc5217SJeff Kirsher 
6005adfc5217SJeff Kirsher 	if (an_dbg & (MISC_SHDW_AN_DBG_NOSYNC | MISC_SHDW_AN_DBG_RUDI_INVALID))
6006adfc5217SJeff Kirsher 		return 0;
6007adfc5217SJeff Kirsher 
6008adfc5217SJeff Kirsher 	bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS, MII_EXPAND_REG1);
6009adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp);
6010adfc5217SJeff Kirsher 	bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &exp);
6011adfc5217SJeff Kirsher 
6012adfc5217SJeff Kirsher 	if (exp & MII_EXPAND_REG1_RUDI_C)	/* receiving CONFIG */
6013adfc5217SJeff Kirsher 		return 0;
6014adfc5217SJeff Kirsher 
6015adfc5217SJeff Kirsher 	return 1;
6016adfc5217SJeff Kirsher }
6017adfc5217SJeff Kirsher 
6018adfc5217SJeff Kirsher static void
6019adfc5217SJeff Kirsher bnx2_5706_serdes_timer(struct bnx2 *bp)
6020adfc5217SJeff Kirsher {
6021adfc5217SJeff Kirsher 	int check_link = 1;
6022adfc5217SJeff Kirsher 
6023adfc5217SJeff Kirsher 	spin_lock(&bp->phy_lock);
6024adfc5217SJeff Kirsher 	if (bp->serdes_an_pending) {
6025adfc5217SJeff Kirsher 		bp->serdes_an_pending--;
6026adfc5217SJeff Kirsher 		check_link = 0;
6027adfc5217SJeff Kirsher 	} else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
6028adfc5217SJeff Kirsher 		u32 bmcr;
6029adfc5217SJeff Kirsher 
6030adfc5217SJeff Kirsher 		bp->current_interval = BNX2_TIMER_INTERVAL;
6031adfc5217SJeff Kirsher 
6032adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
6033adfc5217SJeff Kirsher 
6034adfc5217SJeff Kirsher 		if (bmcr & BMCR_ANENABLE) {
6035adfc5217SJeff Kirsher 			if (bnx2_5706_serdes_has_link(bp)) {
6036adfc5217SJeff Kirsher 				bmcr &= ~BMCR_ANENABLE;
6037adfc5217SJeff Kirsher 				bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
6038adfc5217SJeff Kirsher 				bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
6039adfc5217SJeff Kirsher 				bp->phy_flags |= BNX2_PHY_FLAG_PARALLEL_DETECT;
6040adfc5217SJeff Kirsher 			}
6041adfc5217SJeff Kirsher 		}
6042adfc5217SJeff Kirsher 	}
6043adfc5217SJeff Kirsher 	else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) &&
6044adfc5217SJeff Kirsher 		 (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)) {
6045adfc5217SJeff Kirsher 		u32 phy2;
6046adfc5217SJeff Kirsher 
6047adfc5217SJeff Kirsher 		bnx2_write_phy(bp, 0x17, 0x0f01);
6048adfc5217SJeff Kirsher 		bnx2_read_phy(bp, 0x15, &phy2);
6049adfc5217SJeff Kirsher 		if (phy2 & 0x20) {
6050adfc5217SJeff Kirsher 			u32 bmcr;
6051adfc5217SJeff Kirsher 
6052adfc5217SJeff Kirsher 			bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
6053adfc5217SJeff Kirsher 			bmcr |= BMCR_ANENABLE;
6054adfc5217SJeff Kirsher 			bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
6055adfc5217SJeff Kirsher 
6056adfc5217SJeff Kirsher 			bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
6057adfc5217SJeff Kirsher 		}
6058adfc5217SJeff Kirsher 	} else
6059adfc5217SJeff Kirsher 		bp->current_interval = BNX2_TIMER_INTERVAL;
6060adfc5217SJeff Kirsher 
6061adfc5217SJeff Kirsher 	if (check_link) {
6062adfc5217SJeff Kirsher 		u32 val;
6063adfc5217SJeff Kirsher 
6064adfc5217SJeff Kirsher 		bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
6065adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val);
6066adfc5217SJeff Kirsher 		bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val);
6067adfc5217SJeff Kirsher 
6068adfc5217SJeff Kirsher 		if (bp->link_up && (val & MISC_SHDW_AN_DBG_NOSYNC)) {
6069adfc5217SJeff Kirsher 			if (!(bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN)) {
6070adfc5217SJeff Kirsher 				bnx2_5706s_force_link_dn(bp, 1);
6071adfc5217SJeff Kirsher 				bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN;
6072adfc5217SJeff Kirsher 			} else
6073adfc5217SJeff Kirsher 				bnx2_set_link(bp);
6074adfc5217SJeff Kirsher 		} else if (!bp->link_up && !(val & MISC_SHDW_AN_DBG_NOSYNC))
6075adfc5217SJeff Kirsher 			bnx2_set_link(bp);
6076adfc5217SJeff Kirsher 	}
6077adfc5217SJeff Kirsher 	spin_unlock(&bp->phy_lock);
6078adfc5217SJeff Kirsher }
6079adfc5217SJeff Kirsher 
6080adfc5217SJeff Kirsher static void
6081adfc5217SJeff Kirsher bnx2_5708_serdes_timer(struct bnx2 *bp)
6082adfc5217SJeff Kirsher {
6083adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
6084adfc5217SJeff Kirsher 		return;
6085adfc5217SJeff Kirsher 
6086adfc5217SJeff Kirsher 	if ((bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) == 0) {
6087adfc5217SJeff Kirsher 		bp->serdes_an_pending = 0;
6088adfc5217SJeff Kirsher 		return;
6089adfc5217SJeff Kirsher 	}
6090adfc5217SJeff Kirsher 
6091adfc5217SJeff Kirsher 	spin_lock(&bp->phy_lock);
6092adfc5217SJeff Kirsher 	if (bp->serdes_an_pending)
6093adfc5217SJeff Kirsher 		bp->serdes_an_pending--;
6094adfc5217SJeff Kirsher 	else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
6095adfc5217SJeff Kirsher 		u32 bmcr;
6096adfc5217SJeff Kirsher 
6097adfc5217SJeff Kirsher 		bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
6098adfc5217SJeff Kirsher 		if (bmcr & BMCR_ANENABLE) {
6099adfc5217SJeff Kirsher 			bnx2_enable_forced_2g5(bp);
6100adfc5217SJeff Kirsher 			bp->current_interval = BNX2_SERDES_FORCED_TIMEOUT;
6101adfc5217SJeff Kirsher 		} else {
6102adfc5217SJeff Kirsher 			bnx2_disable_forced_2g5(bp);
6103adfc5217SJeff Kirsher 			bp->serdes_an_pending = 2;
6104adfc5217SJeff Kirsher 			bp->current_interval = BNX2_TIMER_INTERVAL;
6105adfc5217SJeff Kirsher 		}
6106adfc5217SJeff Kirsher 
6107adfc5217SJeff Kirsher 	} else
6108adfc5217SJeff Kirsher 		bp->current_interval = BNX2_TIMER_INTERVAL;
6109adfc5217SJeff Kirsher 
6110adfc5217SJeff Kirsher 	spin_unlock(&bp->phy_lock);
6111adfc5217SJeff Kirsher }
6112adfc5217SJeff Kirsher 
6113adfc5217SJeff Kirsher static void
6114adfc5217SJeff Kirsher bnx2_timer(unsigned long data)
6115adfc5217SJeff Kirsher {
6116adfc5217SJeff Kirsher 	struct bnx2 *bp = (struct bnx2 *) data;
6117adfc5217SJeff Kirsher 
6118adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
6119adfc5217SJeff Kirsher 		return;
6120adfc5217SJeff Kirsher 
6121adfc5217SJeff Kirsher 	if (atomic_read(&bp->intr_sem) != 0)
6122adfc5217SJeff Kirsher 		goto bnx2_restart_timer;
6123adfc5217SJeff Kirsher 
6124adfc5217SJeff Kirsher 	if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) ==
6125adfc5217SJeff Kirsher 	     BNX2_FLAG_USING_MSI)
6126adfc5217SJeff Kirsher 		bnx2_chk_missed_msi(bp);
6127adfc5217SJeff Kirsher 
6128adfc5217SJeff Kirsher 	bnx2_send_heart_beat(bp);
6129adfc5217SJeff Kirsher 
6130adfc5217SJeff Kirsher 	bp->stats_blk->stat_FwRxDrop =
6131adfc5217SJeff Kirsher 		bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT);
6132adfc5217SJeff Kirsher 
6133adfc5217SJeff Kirsher 	/* workaround occasional corrupted counters */
6134adfc5217SJeff Kirsher 	if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks)
6135adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
6136adfc5217SJeff Kirsher 					    BNX2_HC_COMMAND_STATS_NOW);
6137adfc5217SJeff Kirsher 
6138adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
6139adfc5217SJeff Kirsher 		if (CHIP_NUM(bp) == CHIP_NUM_5706)
6140adfc5217SJeff Kirsher 			bnx2_5706_serdes_timer(bp);
6141adfc5217SJeff Kirsher 		else
6142adfc5217SJeff Kirsher 			bnx2_5708_serdes_timer(bp);
6143adfc5217SJeff Kirsher 	}
6144adfc5217SJeff Kirsher 
6145adfc5217SJeff Kirsher bnx2_restart_timer:
6146adfc5217SJeff Kirsher 	mod_timer(&bp->timer, jiffies + bp->current_interval);
6147adfc5217SJeff Kirsher }
6148adfc5217SJeff Kirsher 
6149adfc5217SJeff Kirsher static int
6150adfc5217SJeff Kirsher bnx2_request_irq(struct bnx2 *bp)
6151adfc5217SJeff Kirsher {
6152adfc5217SJeff Kirsher 	unsigned long flags;
6153adfc5217SJeff Kirsher 	struct bnx2_irq *irq;
6154adfc5217SJeff Kirsher 	int rc = 0, i;
6155adfc5217SJeff Kirsher 
6156adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)
6157adfc5217SJeff Kirsher 		flags = 0;
6158adfc5217SJeff Kirsher 	else
6159adfc5217SJeff Kirsher 		flags = IRQF_SHARED;
6160adfc5217SJeff Kirsher 
6161adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
6162adfc5217SJeff Kirsher 		irq = &bp->irq_tbl[i];
6163adfc5217SJeff Kirsher 		rc = request_irq(irq->vector, irq->handler, flags, irq->name,
6164adfc5217SJeff Kirsher 				 &bp->bnx2_napi[i]);
6165adfc5217SJeff Kirsher 		if (rc)
6166adfc5217SJeff Kirsher 			break;
6167adfc5217SJeff Kirsher 		irq->requested = 1;
6168adfc5217SJeff Kirsher 	}
6169adfc5217SJeff Kirsher 	return rc;
6170adfc5217SJeff Kirsher }
6171adfc5217SJeff Kirsher 
6172adfc5217SJeff Kirsher static void
6173adfc5217SJeff Kirsher __bnx2_free_irq(struct bnx2 *bp)
6174adfc5217SJeff Kirsher {
6175adfc5217SJeff Kirsher 	struct bnx2_irq *irq;
6176adfc5217SJeff Kirsher 	int i;
6177adfc5217SJeff Kirsher 
6178adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
6179adfc5217SJeff Kirsher 		irq = &bp->irq_tbl[i];
6180adfc5217SJeff Kirsher 		if (irq->requested)
6181adfc5217SJeff Kirsher 			free_irq(irq->vector, &bp->bnx2_napi[i]);
6182adfc5217SJeff Kirsher 		irq->requested = 0;
6183adfc5217SJeff Kirsher 	}
6184adfc5217SJeff Kirsher }
6185adfc5217SJeff Kirsher 
6186adfc5217SJeff Kirsher static void
6187adfc5217SJeff Kirsher bnx2_free_irq(struct bnx2 *bp)
6188adfc5217SJeff Kirsher {
6189adfc5217SJeff Kirsher 
6190adfc5217SJeff Kirsher 	__bnx2_free_irq(bp);
6191adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSI)
6192adfc5217SJeff Kirsher 		pci_disable_msi(bp->pdev);
6193adfc5217SJeff Kirsher 	else if (bp->flags & BNX2_FLAG_USING_MSIX)
6194adfc5217SJeff Kirsher 		pci_disable_msix(bp->pdev);
6195adfc5217SJeff Kirsher 
6196adfc5217SJeff Kirsher 	bp->flags &= ~(BNX2_FLAG_USING_MSI_OR_MSIX | BNX2_FLAG_ONE_SHOT_MSI);
6197adfc5217SJeff Kirsher }
6198adfc5217SJeff Kirsher 
6199adfc5217SJeff Kirsher static void
6200adfc5217SJeff Kirsher bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
6201adfc5217SJeff Kirsher {
6202adfc5217SJeff Kirsher 	int i, total_vecs, rc;
6203adfc5217SJeff Kirsher 	struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC];
6204adfc5217SJeff Kirsher 	struct net_device *dev = bp->dev;
6205adfc5217SJeff Kirsher 	const int len = sizeof(bp->irq_tbl[0].name);
6206adfc5217SJeff Kirsher 
6207adfc5217SJeff Kirsher 	bnx2_setup_msix_tbl(bp);
6208adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
6209adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
6210adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
6211adfc5217SJeff Kirsher 
6212adfc5217SJeff Kirsher 	/*  Need to flush the previous three writes to ensure MSI-X
6213adfc5217SJeff Kirsher 	 *  is setup properly */
6214adfc5217SJeff Kirsher 	REG_RD(bp, BNX2_PCI_MSIX_CONTROL);
6215adfc5217SJeff Kirsher 
6216adfc5217SJeff Kirsher 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
6217adfc5217SJeff Kirsher 		msix_ent[i].entry = i;
6218adfc5217SJeff Kirsher 		msix_ent[i].vector = 0;
6219adfc5217SJeff Kirsher 	}
6220adfc5217SJeff Kirsher 
6221adfc5217SJeff Kirsher 	total_vecs = msix_vecs;
6222adfc5217SJeff Kirsher #ifdef BCM_CNIC
6223adfc5217SJeff Kirsher 	total_vecs++;
6224adfc5217SJeff Kirsher #endif
6225adfc5217SJeff Kirsher 	rc = -ENOSPC;
6226adfc5217SJeff Kirsher 	while (total_vecs >= BNX2_MIN_MSIX_VEC) {
6227adfc5217SJeff Kirsher 		rc = pci_enable_msix(bp->pdev, msix_ent, total_vecs);
6228adfc5217SJeff Kirsher 		if (rc <= 0)
6229adfc5217SJeff Kirsher 			break;
6230adfc5217SJeff Kirsher 		if (rc > 0)
6231adfc5217SJeff Kirsher 			total_vecs = rc;
6232adfc5217SJeff Kirsher 	}
6233adfc5217SJeff Kirsher 
6234adfc5217SJeff Kirsher 	if (rc != 0)
6235adfc5217SJeff Kirsher 		return;
6236adfc5217SJeff Kirsher 
6237adfc5217SJeff Kirsher 	msix_vecs = total_vecs;
6238adfc5217SJeff Kirsher #ifdef BCM_CNIC
6239adfc5217SJeff Kirsher 	msix_vecs--;
6240adfc5217SJeff Kirsher #endif
6241adfc5217SJeff Kirsher 	bp->irq_nvecs = msix_vecs;
6242adfc5217SJeff Kirsher 	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
6243adfc5217SJeff Kirsher 	for (i = 0; i < total_vecs; i++) {
6244adfc5217SJeff Kirsher 		bp->irq_tbl[i].vector = msix_ent[i].vector;
6245adfc5217SJeff Kirsher 		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
6246adfc5217SJeff Kirsher 		bp->irq_tbl[i].handler = bnx2_msi_1shot;
6247adfc5217SJeff Kirsher 	}
6248adfc5217SJeff Kirsher }
6249adfc5217SJeff Kirsher 
6250adfc5217SJeff Kirsher static int
6251adfc5217SJeff Kirsher bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
6252adfc5217SJeff Kirsher {
6253adfc5217SJeff Kirsher 	int cpus = num_online_cpus();
6254adfc5217SJeff Kirsher 	int msix_vecs = min(cpus + 1, RX_MAX_RINGS);
6255adfc5217SJeff Kirsher 
6256adfc5217SJeff Kirsher 	bp->irq_tbl[0].handler = bnx2_interrupt;
6257adfc5217SJeff Kirsher 	strcpy(bp->irq_tbl[0].name, bp->dev->name);
6258adfc5217SJeff Kirsher 	bp->irq_nvecs = 1;
6259adfc5217SJeff Kirsher 	bp->irq_tbl[0].vector = bp->pdev->irq;
6260adfc5217SJeff Kirsher 
6261adfc5217SJeff Kirsher 	if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi)
6262adfc5217SJeff Kirsher 		bnx2_enable_msix(bp, msix_vecs);
6263adfc5217SJeff Kirsher 
6264adfc5217SJeff Kirsher 	if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi &&
6265adfc5217SJeff Kirsher 	    !(bp->flags & BNX2_FLAG_USING_MSIX)) {
6266adfc5217SJeff Kirsher 		if (pci_enable_msi(bp->pdev) == 0) {
6267adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_USING_MSI;
6268adfc5217SJeff Kirsher 			if (CHIP_NUM(bp) == CHIP_NUM_5709) {
6269adfc5217SJeff Kirsher 				bp->flags |= BNX2_FLAG_ONE_SHOT_MSI;
6270adfc5217SJeff Kirsher 				bp->irq_tbl[0].handler = bnx2_msi_1shot;
6271adfc5217SJeff Kirsher 			} else
6272adfc5217SJeff Kirsher 				bp->irq_tbl[0].handler = bnx2_msi;
6273adfc5217SJeff Kirsher 
6274adfc5217SJeff Kirsher 			bp->irq_tbl[0].vector = bp->pdev->irq;
6275adfc5217SJeff Kirsher 		}
6276adfc5217SJeff Kirsher 	}
6277adfc5217SJeff Kirsher 
6278adfc5217SJeff Kirsher 	bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
6279adfc5217SJeff Kirsher 	netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
6280adfc5217SJeff Kirsher 
6281adfc5217SJeff Kirsher 	bp->num_rx_rings = bp->irq_nvecs;
6282adfc5217SJeff Kirsher 	return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
6283adfc5217SJeff Kirsher }
6284adfc5217SJeff Kirsher 
6285adfc5217SJeff Kirsher /* Called with rtnl_lock */
6286adfc5217SJeff Kirsher static int
6287adfc5217SJeff Kirsher bnx2_open(struct net_device *dev)
6288adfc5217SJeff Kirsher {
6289adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6290adfc5217SJeff Kirsher 	int rc;
6291adfc5217SJeff Kirsher 
62927880b72eSfrançois romieu 	rc = bnx2_request_firmware(bp);
62937880b72eSfrançois romieu 	if (rc < 0)
62947880b72eSfrançois romieu 		goto out;
62957880b72eSfrançois romieu 
6296adfc5217SJeff Kirsher 	netif_carrier_off(dev);
6297adfc5217SJeff Kirsher 
6298adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, PCI_D0);
6299adfc5217SJeff Kirsher 	bnx2_disable_int(bp);
6300adfc5217SJeff Kirsher 
6301adfc5217SJeff Kirsher 	rc = bnx2_setup_int_mode(bp, disable_msi);
6302adfc5217SJeff Kirsher 	if (rc)
6303adfc5217SJeff Kirsher 		goto open_err;
6304adfc5217SJeff Kirsher 	bnx2_init_napi(bp);
6305adfc5217SJeff Kirsher 	bnx2_napi_enable(bp);
6306adfc5217SJeff Kirsher 	rc = bnx2_alloc_mem(bp);
6307adfc5217SJeff Kirsher 	if (rc)
6308adfc5217SJeff Kirsher 		goto open_err;
6309adfc5217SJeff Kirsher 
6310adfc5217SJeff Kirsher 	rc = bnx2_request_irq(bp);
6311adfc5217SJeff Kirsher 	if (rc)
6312adfc5217SJeff Kirsher 		goto open_err;
6313adfc5217SJeff Kirsher 
6314adfc5217SJeff Kirsher 	rc = bnx2_init_nic(bp, 1);
6315adfc5217SJeff Kirsher 	if (rc)
6316adfc5217SJeff Kirsher 		goto open_err;
6317adfc5217SJeff Kirsher 
6318adfc5217SJeff Kirsher 	mod_timer(&bp->timer, jiffies + bp->current_interval);
6319adfc5217SJeff Kirsher 
6320adfc5217SJeff Kirsher 	atomic_set(&bp->intr_sem, 0);
6321adfc5217SJeff Kirsher 
6322adfc5217SJeff Kirsher 	memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block));
6323adfc5217SJeff Kirsher 
6324adfc5217SJeff Kirsher 	bnx2_enable_int(bp);
6325adfc5217SJeff Kirsher 
6326adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSI) {
6327adfc5217SJeff Kirsher 		/* Test MSI to make sure it is working
6328adfc5217SJeff Kirsher 		 * If MSI test fails, go back to INTx mode
6329adfc5217SJeff Kirsher 		 */
6330adfc5217SJeff Kirsher 		if (bnx2_test_intr(bp) != 0) {
6331adfc5217SJeff Kirsher 			netdev_warn(bp->dev, "No interrupt was generated using MSI, switching to INTx mode. Please report this failure to the PCI maintainer and include system chipset information.\n");
6332adfc5217SJeff Kirsher 
6333adfc5217SJeff Kirsher 			bnx2_disable_int(bp);
6334adfc5217SJeff Kirsher 			bnx2_free_irq(bp);
6335adfc5217SJeff Kirsher 
6336adfc5217SJeff Kirsher 			bnx2_setup_int_mode(bp, 1);
6337adfc5217SJeff Kirsher 
6338adfc5217SJeff Kirsher 			rc = bnx2_init_nic(bp, 0);
6339adfc5217SJeff Kirsher 
6340adfc5217SJeff Kirsher 			if (!rc)
6341adfc5217SJeff Kirsher 				rc = bnx2_request_irq(bp);
6342adfc5217SJeff Kirsher 
6343adfc5217SJeff Kirsher 			if (rc) {
6344adfc5217SJeff Kirsher 				del_timer_sync(&bp->timer);
6345adfc5217SJeff Kirsher 				goto open_err;
6346adfc5217SJeff Kirsher 			}
6347adfc5217SJeff Kirsher 			bnx2_enable_int(bp);
6348adfc5217SJeff Kirsher 		}
6349adfc5217SJeff Kirsher 	}
6350adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSI)
6351adfc5217SJeff Kirsher 		netdev_info(dev, "using MSI\n");
6352adfc5217SJeff Kirsher 	else if (bp->flags & BNX2_FLAG_USING_MSIX)
6353adfc5217SJeff Kirsher 		netdev_info(dev, "using MSIX\n");
6354adfc5217SJeff Kirsher 
6355adfc5217SJeff Kirsher 	netif_tx_start_all_queues(dev);
63567880b72eSfrançois romieu out:
63577880b72eSfrançois romieu 	return rc;
6358adfc5217SJeff Kirsher 
6359adfc5217SJeff Kirsher open_err:
6360adfc5217SJeff Kirsher 	bnx2_napi_disable(bp);
6361adfc5217SJeff Kirsher 	bnx2_free_skbs(bp);
6362adfc5217SJeff Kirsher 	bnx2_free_irq(bp);
6363adfc5217SJeff Kirsher 	bnx2_free_mem(bp);
6364adfc5217SJeff Kirsher 	bnx2_del_napi(bp);
63657880b72eSfrançois romieu 	bnx2_release_firmware(bp);
63667880b72eSfrançois romieu 	goto out;
6367adfc5217SJeff Kirsher }
6368adfc5217SJeff Kirsher 
6369adfc5217SJeff Kirsher static void
6370adfc5217SJeff Kirsher bnx2_reset_task(struct work_struct *work)
6371adfc5217SJeff Kirsher {
6372adfc5217SJeff Kirsher 	struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
6373adfc5217SJeff Kirsher 	int rc;
6374adfc5217SJeff Kirsher 
6375adfc5217SJeff Kirsher 	rtnl_lock();
6376adfc5217SJeff Kirsher 	if (!netif_running(bp->dev)) {
6377adfc5217SJeff Kirsher 		rtnl_unlock();
6378adfc5217SJeff Kirsher 		return;
6379adfc5217SJeff Kirsher 	}
6380adfc5217SJeff Kirsher 
6381adfc5217SJeff Kirsher 	bnx2_netif_stop(bp, true);
6382adfc5217SJeff Kirsher 
6383adfc5217SJeff Kirsher 	rc = bnx2_init_nic(bp, 1);
6384adfc5217SJeff Kirsher 	if (rc) {
6385adfc5217SJeff Kirsher 		netdev_err(bp->dev, "failed to reset NIC, closing\n");
6386adfc5217SJeff Kirsher 		bnx2_napi_enable(bp);
6387adfc5217SJeff Kirsher 		dev_close(bp->dev);
6388adfc5217SJeff Kirsher 		rtnl_unlock();
6389adfc5217SJeff Kirsher 		return;
6390adfc5217SJeff Kirsher 	}
6391adfc5217SJeff Kirsher 
6392adfc5217SJeff Kirsher 	atomic_set(&bp->intr_sem, 1);
6393adfc5217SJeff Kirsher 	bnx2_netif_start(bp, true);
6394adfc5217SJeff Kirsher 	rtnl_unlock();
6395adfc5217SJeff Kirsher }
6396adfc5217SJeff Kirsher 
6397adfc5217SJeff Kirsher static void
6398adfc5217SJeff Kirsher bnx2_dump_state(struct bnx2 *bp)
6399adfc5217SJeff Kirsher {
6400adfc5217SJeff Kirsher 	struct net_device *dev = bp->dev;
6401adfc5217SJeff Kirsher 	u32 val1, val2;
6402adfc5217SJeff Kirsher 
6403adfc5217SJeff Kirsher 	pci_read_config_dword(bp->pdev, PCI_COMMAND, &val1);
6404adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: intr_sem[%x] PCI_CMD[%08x]\n",
6405adfc5217SJeff Kirsher 		   atomic_read(&bp->intr_sem), val1);
6406adfc5217SJeff Kirsher 	pci_read_config_dword(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &val1);
6407adfc5217SJeff Kirsher 	pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2);
6408adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2);
6409adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n",
6410adfc5217SJeff Kirsher 		   REG_RD(bp, BNX2_EMAC_TX_STATUS),
6411adfc5217SJeff Kirsher 		   REG_RD(bp, BNX2_EMAC_RX_STATUS));
6412adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
6413adfc5217SJeff Kirsher 		   REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
6414adfc5217SJeff Kirsher 	netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
6415adfc5217SJeff Kirsher 		   REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
6416adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_USING_MSIX)
6417adfc5217SJeff Kirsher 		netdev_err(dev, "DEBUG: PBA[%08x]\n",
6418adfc5217SJeff Kirsher 			   REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
6419adfc5217SJeff Kirsher }
6420adfc5217SJeff Kirsher 
6421adfc5217SJeff Kirsher static void
6422adfc5217SJeff Kirsher bnx2_tx_timeout(struct net_device *dev)
6423adfc5217SJeff Kirsher {
6424adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6425adfc5217SJeff Kirsher 
6426adfc5217SJeff Kirsher 	bnx2_dump_state(bp);
6427adfc5217SJeff Kirsher 	bnx2_dump_mcp_state(bp);
6428adfc5217SJeff Kirsher 
6429adfc5217SJeff Kirsher 	/* This allows the netif to be shutdown gracefully before resetting */
6430adfc5217SJeff Kirsher 	schedule_work(&bp->reset_task);
6431adfc5217SJeff Kirsher }
6432adfc5217SJeff Kirsher 
6433adfc5217SJeff Kirsher /* Called with netif_tx_lock.
6434adfc5217SJeff Kirsher  * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
6435adfc5217SJeff Kirsher  * netif_wake_queue().
6436adfc5217SJeff Kirsher  */
6437adfc5217SJeff Kirsher static netdev_tx_t
6438adfc5217SJeff Kirsher bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
6439adfc5217SJeff Kirsher {
6440adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6441adfc5217SJeff Kirsher 	dma_addr_t mapping;
6442adfc5217SJeff Kirsher 	struct tx_bd *txbd;
6443adfc5217SJeff Kirsher 	struct sw_tx_bd *tx_buf;
6444adfc5217SJeff Kirsher 	u32 len, vlan_tag_flags, last_frag, mss;
6445adfc5217SJeff Kirsher 	u16 prod, ring_prod;
6446adfc5217SJeff Kirsher 	int i;
6447adfc5217SJeff Kirsher 	struct bnx2_napi *bnapi;
6448adfc5217SJeff Kirsher 	struct bnx2_tx_ring_info *txr;
6449adfc5217SJeff Kirsher 	struct netdev_queue *txq;
6450adfc5217SJeff Kirsher 
6451adfc5217SJeff Kirsher 	/*  Determine which tx ring we will be placed on */
6452adfc5217SJeff Kirsher 	i = skb_get_queue_mapping(skb);
6453adfc5217SJeff Kirsher 	bnapi = &bp->bnx2_napi[i];
6454adfc5217SJeff Kirsher 	txr = &bnapi->tx_ring;
6455adfc5217SJeff Kirsher 	txq = netdev_get_tx_queue(dev, i);
6456adfc5217SJeff Kirsher 
6457adfc5217SJeff Kirsher 	if (unlikely(bnx2_tx_avail(bp, txr) <
6458adfc5217SJeff Kirsher 	    (skb_shinfo(skb)->nr_frags + 1))) {
6459adfc5217SJeff Kirsher 		netif_tx_stop_queue(txq);
6460adfc5217SJeff Kirsher 		netdev_err(dev, "BUG! Tx ring full when queue awake!\n");
6461adfc5217SJeff Kirsher 
6462adfc5217SJeff Kirsher 		return NETDEV_TX_BUSY;
6463adfc5217SJeff Kirsher 	}
6464adfc5217SJeff Kirsher 	len = skb_headlen(skb);
6465adfc5217SJeff Kirsher 	prod = txr->tx_prod;
6466adfc5217SJeff Kirsher 	ring_prod = TX_RING_IDX(prod);
6467adfc5217SJeff Kirsher 
6468adfc5217SJeff Kirsher 	vlan_tag_flags = 0;
6469adfc5217SJeff Kirsher 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
6470adfc5217SJeff Kirsher 		vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
6471adfc5217SJeff Kirsher 	}
6472adfc5217SJeff Kirsher 
6473adfc5217SJeff Kirsher 	if (vlan_tx_tag_present(skb)) {
6474adfc5217SJeff Kirsher 		vlan_tag_flags |=
6475adfc5217SJeff Kirsher 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
6476adfc5217SJeff Kirsher 	}
6477adfc5217SJeff Kirsher 
6478adfc5217SJeff Kirsher 	if ((mss = skb_shinfo(skb)->gso_size)) {
6479adfc5217SJeff Kirsher 		u32 tcp_opt_len;
6480adfc5217SJeff Kirsher 		struct iphdr *iph;
6481adfc5217SJeff Kirsher 
6482adfc5217SJeff Kirsher 		vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
6483adfc5217SJeff Kirsher 
6484adfc5217SJeff Kirsher 		tcp_opt_len = tcp_optlen(skb);
6485adfc5217SJeff Kirsher 
6486adfc5217SJeff Kirsher 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
6487adfc5217SJeff Kirsher 			u32 tcp_off = skb_transport_offset(skb) -
6488adfc5217SJeff Kirsher 				      sizeof(struct ipv6hdr) - ETH_HLEN;
6489adfc5217SJeff Kirsher 
6490adfc5217SJeff Kirsher 			vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
6491adfc5217SJeff Kirsher 					  TX_BD_FLAGS_SW_FLAGS;
6492adfc5217SJeff Kirsher 			if (likely(tcp_off == 0))
6493adfc5217SJeff Kirsher 				vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
6494adfc5217SJeff Kirsher 			else {
6495adfc5217SJeff Kirsher 				tcp_off >>= 3;
6496adfc5217SJeff Kirsher 				vlan_tag_flags |= ((tcp_off & 0x3) <<
6497adfc5217SJeff Kirsher 						   TX_BD_FLAGS_TCP6_OFF0_SHL) |
6498adfc5217SJeff Kirsher 						  ((tcp_off & 0x10) <<
6499adfc5217SJeff Kirsher 						   TX_BD_FLAGS_TCP6_OFF4_SHL);
6500adfc5217SJeff Kirsher 				mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
6501adfc5217SJeff Kirsher 			}
6502adfc5217SJeff Kirsher 		} else {
6503adfc5217SJeff Kirsher 			iph = ip_hdr(skb);
6504adfc5217SJeff Kirsher 			if (tcp_opt_len || (iph->ihl > 5)) {
6505adfc5217SJeff Kirsher 				vlan_tag_flags |= ((iph->ihl - 5) +
6506adfc5217SJeff Kirsher 						   (tcp_opt_len >> 2)) << 8;
6507adfc5217SJeff Kirsher 			}
6508adfc5217SJeff Kirsher 		}
6509adfc5217SJeff Kirsher 	} else
6510adfc5217SJeff Kirsher 		mss = 0;
6511adfc5217SJeff Kirsher 
6512adfc5217SJeff Kirsher 	mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
6513adfc5217SJeff Kirsher 	if (dma_mapping_error(&bp->pdev->dev, mapping)) {
6514adfc5217SJeff Kirsher 		dev_kfree_skb(skb);
6515adfc5217SJeff Kirsher 		return NETDEV_TX_OK;
6516adfc5217SJeff Kirsher 	}
6517adfc5217SJeff Kirsher 
6518adfc5217SJeff Kirsher 	tx_buf = &txr->tx_buf_ring[ring_prod];
6519adfc5217SJeff Kirsher 	tx_buf->skb = skb;
6520adfc5217SJeff Kirsher 	dma_unmap_addr_set(tx_buf, mapping, mapping);
6521adfc5217SJeff Kirsher 
6522adfc5217SJeff Kirsher 	txbd = &txr->tx_desc_ring[ring_prod];
6523adfc5217SJeff Kirsher 
6524adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
6525adfc5217SJeff Kirsher 	txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
6526adfc5217SJeff Kirsher 	txbd->tx_bd_mss_nbytes = len | (mss << 16);
6527adfc5217SJeff Kirsher 	txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START;
6528adfc5217SJeff Kirsher 
6529adfc5217SJeff Kirsher 	last_frag = skb_shinfo(skb)->nr_frags;
6530adfc5217SJeff Kirsher 	tx_buf->nr_frags = last_frag;
6531adfc5217SJeff Kirsher 	tx_buf->is_gso = skb_is_gso(skb);
6532adfc5217SJeff Kirsher 
6533adfc5217SJeff Kirsher 	for (i = 0; i < last_frag; i++) {
6534adfc5217SJeff Kirsher 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
6535adfc5217SJeff Kirsher 
6536adfc5217SJeff Kirsher 		prod = NEXT_TX_BD(prod);
6537adfc5217SJeff Kirsher 		ring_prod = TX_RING_IDX(prod);
6538adfc5217SJeff Kirsher 		txbd = &txr->tx_desc_ring[ring_prod];
6539adfc5217SJeff Kirsher 
6540adfc5217SJeff Kirsher 		len = frag->size;
6541b7b6a688SIan Campbell 		mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, len,
65425d6bcdfeSIan Campbell 					   DMA_TO_DEVICE);
6543adfc5217SJeff Kirsher 		if (dma_mapping_error(&bp->pdev->dev, mapping))
6544adfc5217SJeff Kirsher 			goto dma_error;
6545adfc5217SJeff Kirsher 		dma_unmap_addr_set(&txr->tx_buf_ring[ring_prod], mapping,
6546adfc5217SJeff Kirsher 				   mapping);
6547adfc5217SJeff Kirsher 
6548adfc5217SJeff Kirsher 		txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
6549adfc5217SJeff Kirsher 		txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
6550adfc5217SJeff Kirsher 		txbd->tx_bd_mss_nbytes = len | (mss << 16);
6551adfc5217SJeff Kirsher 		txbd->tx_bd_vlan_tag_flags = vlan_tag_flags;
6552adfc5217SJeff Kirsher 
6553adfc5217SJeff Kirsher 	}
6554adfc5217SJeff Kirsher 	txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
6555adfc5217SJeff Kirsher 
6556adfc5217SJeff Kirsher 	prod = NEXT_TX_BD(prod);
6557adfc5217SJeff Kirsher 	txr->tx_prod_bseq += skb->len;
6558adfc5217SJeff Kirsher 
6559adfc5217SJeff Kirsher 	REG_WR16(bp, txr->tx_bidx_addr, prod);
6560adfc5217SJeff Kirsher 	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
6561adfc5217SJeff Kirsher 
6562adfc5217SJeff Kirsher 	mmiowb();
6563adfc5217SJeff Kirsher 
6564adfc5217SJeff Kirsher 	txr->tx_prod = prod;
6565adfc5217SJeff Kirsher 
6566adfc5217SJeff Kirsher 	if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) {
6567adfc5217SJeff Kirsher 		netif_tx_stop_queue(txq);
6568adfc5217SJeff Kirsher 
6569adfc5217SJeff Kirsher 		/* netif_tx_stop_queue() must be done before checking
6570adfc5217SJeff Kirsher 		 * tx index in bnx2_tx_avail() below, because in
6571adfc5217SJeff Kirsher 		 * bnx2_tx_int(), we update tx index before checking for
6572adfc5217SJeff Kirsher 		 * netif_tx_queue_stopped().
6573adfc5217SJeff Kirsher 		 */
6574adfc5217SJeff Kirsher 		smp_mb();
6575adfc5217SJeff Kirsher 		if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)
6576adfc5217SJeff Kirsher 			netif_tx_wake_queue(txq);
6577adfc5217SJeff Kirsher 	}
6578adfc5217SJeff Kirsher 
6579adfc5217SJeff Kirsher 	return NETDEV_TX_OK;
6580adfc5217SJeff Kirsher dma_error:
6581adfc5217SJeff Kirsher 	/* save value of frag that failed */
6582adfc5217SJeff Kirsher 	last_frag = i;
6583adfc5217SJeff Kirsher 
6584adfc5217SJeff Kirsher 	/* start back at beginning and unmap skb */
6585adfc5217SJeff Kirsher 	prod = txr->tx_prod;
6586adfc5217SJeff Kirsher 	ring_prod = TX_RING_IDX(prod);
6587adfc5217SJeff Kirsher 	tx_buf = &txr->tx_buf_ring[ring_prod];
6588adfc5217SJeff Kirsher 	tx_buf->skb = NULL;
6589adfc5217SJeff Kirsher 	dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
6590adfc5217SJeff Kirsher 			 skb_headlen(skb), PCI_DMA_TODEVICE);
6591adfc5217SJeff Kirsher 
6592adfc5217SJeff Kirsher 	/* unmap remaining mapped pages */
6593adfc5217SJeff Kirsher 	for (i = 0; i < last_frag; i++) {
6594adfc5217SJeff Kirsher 		prod = NEXT_TX_BD(prod);
6595adfc5217SJeff Kirsher 		ring_prod = TX_RING_IDX(prod);
6596adfc5217SJeff Kirsher 		tx_buf = &txr->tx_buf_ring[ring_prod];
6597adfc5217SJeff Kirsher 		dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
6598adfc5217SJeff Kirsher 			       skb_shinfo(skb)->frags[i].size,
6599adfc5217SJeff Kirsher 			       PCI_DMA_TODEVICE);
6600adfc5217SJeff Kirsher 	}
6601adfc5217SJeff Kirsher 
6602adfc5217SJeff Kirsher 	dev_kfree_skb(skb);
6603adfc5217SJeff Kirsher 	return NETDEV_TX_OK;
6604adfc5217SJeff Kirsher }
6605adfc5217SJeff Kirsher 
6606adfc5217SJeff Kirsher /* Called with rtnl_lock */
6607adfc5217SJeff Kirsher static int
6608adfc5217SJeff Kirsher bnx2_close(struct net_device *dev)
6609adfc5217SJeff Kirsher {
6610adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6611adfc5217SJeff Kirsher 
6612adfc5217SJeff Kirsher 	bnx2_disable_int_sync(bp);
6613adfc5217SJeff Kirsher 	bnx2_napi_disable(bp);
6614adfc5217SJeff Kirsher 	del_timer_sync(&bp->timer);
6615adfc5217SJeff Kirsher 	bnx2_shutdown_chip(bp);
6616adfc5217SJeff Kirsher 	bnx2_free_irq(bp);
6617adfc5217SJeff Kirsher 	bnx2_free_skbs(bp);
6618adfc5217SJeff Kirsher 	bnx2_free_mem(bp);
6619adfc5217SJeff Kirsher 	bnx2_del_napi(bp);
6620adfc5217SJeff Kirsher 	bp->link_up = 0;
6621adfc5217SJeff Kirsher 	netif_carrier_off(bp->dev);
6622adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, PCI_D3hot);
6623adfc5217SJeff Kirsher 	return 0;
6624adfc5217SJeff Kirsher }
6625adfc5217SJeff Kirsher 
6626adfc5217SJeff Kirsher static void
6627adfc5217SJeff Kirsher bnx2_save_stats(struct bnx2 *bp)
6628adfc5217SJeff Kirsher {
6629adfc5217SJeff Kirsher 	u32 *hw_stats = (u32 *) bp->stats_blk;
6630adfc5217SJeff Kirsher 	u32 *temp_stats = (u32 *) bp->temp_stats_blk;
6631adfc5217SJeff Kirsher 	int i;
6632adfc5217SJeff Kirsher 
6633adfc5217SJeff Kirsher 	/* The 1st 10 counters are 64-bit counters */
6634adfc5217SJeff Kirsher 	for (i = 0; i < 20; i += 2) {
6635adfc5217SJeff Kirsher 		u32 hi;
6636adfc5217SJeff Kirsher 		u64 lo;
6637adfc5217SJeff Kirsher 
6638adfc5217SJeff Kirsher 		hi = temp_stats[i] + hw_stats[i];
6639adfc5217SJeff Kirsher 		lo = (u64) temp_stats[i + 1] + (u64) hw_stats[i + 1];
6640adfc5217SJeff Kirsher 		if (lo > 0xffffffff)
6641adfc5217SJeff Kirsher 			hi++;
6642adfc5217SJeff Kirsher 		temp_stats[i] = hi;
6643adfc5217SJeff Kirsher 		temp_stats[i + 1] = lo & 0xffffffff;
6644adfc5217SJeff Kirsher 	}
6645adfc5217SJeff Kirsher 
6646adfc5217SJeff Kirsher 	for ( ; i < sizeof(struct statistics_block) / 4; i++)
6647adfc5217SJeff Kirsher 		temp_stats[i] += hw_stats[i];
6648adfc5217SJeff Kirsher }
6649adfc5217SJeff Kirsher 
6650adfc5217SJeff Kirsher #define GET_64BIT_NET_STATS64(ctr)		\
6651adfc5217SJeff Kirsher 	(((u64) (ctr##_hi) << 32) + (u64) (ctr##_lo))
6652adfc5217SJeff Kirsher 
6653adfc5217SJeff Kirsher #define GET_64BIT_NET_STATS(ctr)				\
6654adfc5217SJeff Kirsher 	GET_64BIT_NET_STATS64(bp->stats_blk->ctr) +		\
6655adfc5217SJeff Kirsher 	GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr)
6656adfc5217SJeff Kirsher 
6657adfc5217SJeff Kirsher #define GET_32BIT_NET_STATS(ctr)				\
6658adfc5217SJeff Kirsher 	(unsigned long) (bp->stats_blk->ctr +			\
6659adfc5217SJeff Kirsher 			 bp->temp_stats_blk->ctr)
6660adfc5217SJeff Kirsher 
6661adfc5217SJeff Kirsher static struct rtnl_link_stats64 *
6662adfc5217SJeff Kirsher bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
6663adfc5217SJeff Kirsher {
6664adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6665adfc5217SJeff Kirsher 
6666adfc5217SJeff Kirsher 	if (bp->stats_blk == NULL)
6667adfc5217SJeff Kirsher 		return net_stats;
6668adfc5217SJeff Kirsher 
6669adfc5217SJeff Kirsher 	net_stats->rx_packets =
6670adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCInUcastPkts) +
6671adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts) +
6672adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCInBroadcastPkts);
6673adfc5217SJeff Kirsher 
6674adfc5217SJeff Kirsher 	net_stats->tx_packets =
6675adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCOutUcastPkts) +
6676adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts) +
6677adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCOutBroadcastPkts);
6678adfc5217SJeff Kirsher 
6679adfc5217SJeff Kirsher 	net_stats->rx_bytes =
6680adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCInOctets);
6681adfc5217SJeff Kirsher 
6682adfc5217SJeff Kirsher 	net_stats->tx_bytes =
6683adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCOutOctets);
6684adfc5217SJeff Kirsher 
6685adfc5217SJeff Kirsher 	net_stats->multicast =
6686adfc5217SJeff Kirsher 		GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts);
6687adfc5217SJeff Kirsher 
6688adfc5217SJeff Kirsher 	net_stats->collisions =
6689adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_EtherStatsCollisions);
6690adfc5217SJeff Kirsher 
6691adfc5217SJeff Kirsher 	net_stats->rx_length_errors =
6692adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_EtherStatsUndersizePkts) +
6693adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_EtherStatsOverrsizePkts);
6694adfc5217SJeff Kirsher 
6695adfc5217SJeff Kirsher 	net_stats->rx_over_errors =
6696adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_IfInFTQDiscards) +
6697adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_IfInMBUFDiscards);
6698adfc5217SJeff Kirsher 
6699adfc5217SJeff Kirsher 	net_stats->rx_frame_errors =
6700adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_Dot3StatsAlignmentErrors);
6701adfc5217SJeff Kirsher 
6702adfc5217SJeff Kirsher 	net_stats->rx_crc_errors =
6703adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_Dot3StatsFCSErrors);
6704adfc5217SJeff Kirsher 
6705adfc5217SJeff Kirsher 	net_stats->rx_errors = net_stats->rx_length_errors +
6706adfc5217SJeff Kirsher 		net_stats->rx_over_errors + net_stats->rx_frame_errors +
6707adfc5217SJeff Kirsher 		net_stats->rx_crc_errors;
6708adfc5217SJeff Kirsher 
6709adfc5217SJeff Kirsher 	net_stats->tx_aborted_errors =
6710adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) +
6711adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions);
6712adfc5217SJeff Kirsher 
6713adfc5217SJeff Kirsher 	if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
6714adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_A0))
6715adfc5217SJeff Kirsher 		net_stats->tx_carrier_errors = 0;
6716adfc5217SJeff Kirsher 	else {
6717adfc5217SJeff Kirsher 		net_stats->tx_carrier_errors =
6718adfc5217SJeff Kirsher 			GET_32BIT_NET_STATS(stat_Dot3StatsCarrierSenseErrors);
6719adfc5217SJeff Kirsher 	}
6720adfc5217SJeff Kirsher 
6721adfc5217SJeff Kirsher 	net_stats->tx_errors =
6722adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_emac_tx_stat_dot3statsinternalmactransmiterrors) +
6723adfc5217SJeff Kirsher 		net_stats->tx_aborted_errors +
6724adfc5217SJeff Kirsher 		net_stats->tx_carrier_errors;
6725adfc5217SJeff Kirsher 
6726adfc5217SJeff Kirsher 	net_stats->rx_missed_errors =
6727adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_IfInFTQDiscards) +
6728adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_IfInMBUFDiscards) +
6729adfc5217SJeff Kirsher 		GET_32BIT_NET_STATS(stat_FwRxDrop);
6730adfc5217SJeff Kirsher 
6731adfc5217SJeff Kirsher 	return net_stats;
6732adfc5217SJeff Kirsher }
6733adfc5217SJeff Kirsher 
6734adfc5217SJeff Kirsher /* All ethtool functions called with rtnl_lock */
6735adfc5217SJeff Kirsher 
6736adfc5217SJeff Kirsher static int
6737adfc5217SJeff Kirsher bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
6738adfc5217SJeff Kirsher {
6739adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6740adfc5217SJeff Kirsher 	int support_serdes = 0, support_copper = 0;
6741adfc5217SJeff Kirsher 
6742adfc5217SJeff Kirsher 	cmd->supported = SUPPORTED_Autoneg;
6743adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
6744adfc5217SJeff Kirsher 		support_serdes = 1;
6745adfc5217SJeff Kirsher 		support_copper = 1;
6746adfc5217SJeff Kirsher 	} else if (bp->phy_port == PORT_FIBRE)
6747adfc5217SJeff Kirsher 		support_serdes = 1;
6748adfc5217SJeff Kirsher 	else
6749adfc5217SJeff Kirsher 		support_copper = 1;
6750adfc5217SJeff Kirsher 
6751adfc5217SJeff Kirsher 	if (support_serdes) {
6752adfc5217SJeff Kirsher 		cmd->supported |= SUPPORTED_1000baseT_Full |
6753adfc5217SJeff Kirsher 			SUPPORTED_FIBRE;
6754adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
6755adfc5217SJeff Kirsher 			cmd->supported |= SUPPORTED_2500baseX_Full;
6756adfc5217SJeff Kirsher 
6757adfc5217SJeff Kirsher 	}
6758adfc5217SJeff Kirsher 	if (support_copper) {
6759adfc5217SJeff Kirsher 		cmd->supported |= SUPPORTED_10baseT_Half |
6760adfc5217SJeff Kirsher 			SUPPORTED_10baseT_Full |
6761adfc5217SJeff Kirsher 			SUPPORTED_100baseT_Half |
6762adfc5217SJeff Kirsher 			SUPPORTED_100baseT_Full |
6763adfc5217SJeff Kirsher 			SUPPORTED_1000baseT_Full |
6764adfc5217SJeff Kirsher 			SUPPORTED_TP;
6765adfc5217SJeff Kirsher 
6766adfc5217SJeff Kirsher 	}
6767adfc5217SJeff Kirsher 
6768adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
6769adfc5217SJeff Kirsher 	cmd->port = bp->phy_port;
6770adfc5217SJeff Kirsher 	cmd->advertising = bp->advertising;
6771adfc5217SJeff Kirsher 
6772adfc5217SJeff Kirsher 	if (bp->autoneg & AUTONEG_SPEED) {
6773adfc5217SJeff Kirsher 		cmd->autoneg = AUTONEG_ENABLE;
6774adfc5217SJeff Kirsher 	} else {
6775adfc5217SJeff Kirsher 		cmd->autoneg = AUTONEG_DISABLE;
6776adfc5217SJeff Kirsher 	}
6777adfc5217SJeff Kirsher 
6778adfc5217SJeff Kirsher 	if (netif_carrier_ok(dev)) {
6779adfc5217SJeff Kirsher 		ethtool_cmd_speed_set(cmd, bp->line_speed);
6780adfc5217SJeff Kirsher 		cmd->duplex = bp->duplex;
6781adfc5217SJeff Kirsher 	}
6782adfc5217SJeff Kirsher 	else {
6783adfc5217SJeff Kirsher 		ethtool_cmd_speed_set(cmd, -1);
6784adfc5217SJeff Kirsher 		cmd->duplex = -1;
6785adfc5217SJeff Kirsher 	}
6786adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
6787adfc5217SJeff Kirsher 
6788adfc5217SJeff Kirsher 	cmd->transceiver = XCVR_INTERNAL;
6789adfc5217SJeff Kirsher 	cmd->phy_address = bp->phy_addr;
6790adfc5217SJeff Kirsher 
6791adfc5217SJeff Kirsher 	return 0;
6792adfc5217SJeff Kirsher }
6793adfc5217SJeff Kirsher 
6794adfc5217SJeff Kirsher static int
6795adfc5217SJeff Kirsher bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
6796adfc5217SJeff Kirsher {
6797adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6798adfc5217SJeff Kirsher 	u8 autoneg = bp->autoneg;
6799adfc5217SJeff Kirsher 	u8 req_duplex = bp->req_duplex;
6800adfc5217SJeff Kirsher 	u16 req_line_speed = bp->req_line_speed;
6801adfc5217SJeff Kirsher 	u32 advertising = bp->advertising;
6802adfc5217SJeff Kirsher 	int err = -EINVAL;
6803adfc5217SJeff Kirsher 
6804adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
6805adfc5217SJeff Kirsher 
6806adfc5217SJeff Kirsher 	if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
6807adfc5217SJeff Kirsher 		goto err_out_unlock;
6808adfc5217SJeff Kirsher 
6809adfc5217SJeff Kirsher 	if (cmd->port != bp->phy_port &&
6810adfc5217SJeff Kirsher 	    !(bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP))
6811adfc5217SJeff Kirsher 		goto err_out_unlock;
6812adfc5217SJeff Kirsher 
6813adfc5217SJeff Kirsher 	/* If device is down, we can store the settings only if the user
6814adfc5217SJeff Kirsher 	 * is setting the currently active port.
6815adfc5217SJeff Kirsher 	 */
6816adfc5217SJeff Kirsher 	if (!netif_running(dev) && cmd->port != bp->phy_port)
6817adfc5217SJeff Kirsher 		goto err_out_unlock;
6818adfc5217SJeff Kirsher 
6819adfc5217SJeff Kirsher 	if (cmd->autoneg == AUTONEG_ENABLE) {
6820adfc5217SJeff Kirsher 		autoneg |= AUTONEG_SPEED;
6821adfc5217SJeff Kirsher 
6822adfc5217SJeff Kirsher 		advertising = cmd->advertising;
6823adfc5217SJeff Kirsher 		if (cmd->port == PORT_TP) {
6824adfc5217SJeff Kirsher 			advertising &= ETHTOOL_ALL_COPPER_SPEED;
6825adfc5217SJeff Kirsher 			if (!advertising)
6826adfc5217SJeff Kirsher 				advertising = ETHTOOL_ALL_COPPER_SPEED;
6827adfc5217SJeff Kirsher 		} else {
6828adfc5217SJeff Kirsher 			advertising &= ETHTOOL_ALL_FIBRE_SPEED;
6829adfc5217SJeff Kirsher 			if (!advertising)
6830adfc5217SJeff Kirsher 				advertising = ETHTOOL_ALL_FIBRE_SPEED;
6831adfc5217SJeff Kirsher 		}
6832adfc5217SJeff Kirsher 		advertising |= ADVERTISED_Autoneg;
6833adfc5217SJeff Kirsher 	}
6834adfc5217SJeff Kirsher 	else {
6835adfc5217SJeff Kirsher 		u32 speed = ethtool_cmd_speed(cmd);
6836adfc5217SJeff Kirsher 		if (cmd->port == PORT_FIBRE) {
6837adfc5217SJeff Kirsher 			if ((speed != SPEED_1000 &&
6838adfc5217SJeff Kirsher 			     speed != SPEED_2500) ||
6839adfc5217SJeff Kirsher 			    (cmd->duplex != DUPLEX_FULL))
6840adfc5217SJeff Kirsher 				goto err_out_unlock;
6841adfc5217SJeff Kirsher 
6842adfc5217SJeff Kirsher 			if (speed == SPEED_2500 &&
6843adfc5217SJeff Kirsher 			    !(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
6844adfc5217SJeff Kirsher 				goto err_out_unlock;
6845adfc5217SJeff Kirsher 		} else if (speed == SPEED_1000 || speed == SPEED_2500)
6846adfc5217SJeff Kirsher 			goto err_out_unlock;
6847adfc5217SJeff Kirsher 
6848adfc5217SJeff Kirsher 		autoneg &= ~AUTONEG_SPEED;
6849adfc5217SJeff Kirsher 		req_line_speed = speed;
6850adfc5217SJeff Kirsher 		req_duplex = cmd->duplex;
6851adfc5217SJeff Kirsher 		advertising = 0;
6852adfc5217SJeff Kirsher 	}
6853adfc5217SJeff Kirsher 
6854adfc5217SJeff Kirsher 	bp->autoneg = autoneg;
6855adfc5217SJeff Kirsher 	bp->advertising = advertising;
6856adfc5217SJeff Kirsher 	bp->req_line_speed = req_line_speed;
6857adfc5217SJeff Kirsher 	bp->req_duplex = req_duplex;
6858adfc5217SJeff Kirsher 
6859adfc5217SJeff Kirsher 	err = 0;
6860adfc5217SJeff Kirsher 	/* If device is down, the new settings will be picked up when it is
6861adfc5217SJeff Kirsher 	 * brought up.
6862adfc5217SJeff Kirsher 	 */
6863adfc5217SJeff Kirsher 	if (netif_running(dev))
6864adfc5217SJeff Kirsher 		err = bnx2_setup_phy(bp, cmd->port);
6865adfc5217SJeff Kirsher 
6866adfc5217SJeff Kirsher err_out_unlock:
6867adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
6868adfc5217SJeff Kirsher 
6869adfc5217SJeff Kirsher 	return err;
6870adfc5217SJeff Kirsher }
6871adfc5217SJeff Kirsher 
6872adfc5217SJeff Kirsher static void
6873adfc5217SJeff Kirsher bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
6874adfc5217SJeff Kirsher {
6875adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6876adfc5217SJeff Kirsher 
6877adfc5217SJeff Kirsher 	strcpy(info->driver, DRV_MODULE_NAME);
6878adfc5217SJeff Kirsher 	strcpy(info->version, DRV_MODULE_VERSION);
6879adfc5217SJeff Kirsher 	strcpy(info->bus_info, pci_name(bp->pdev));
6880adfc5217SJeff Kirsher 	strcpy(info->fw_version, bp->fw_version);
6881adfc5217SJeff Kirsher }
6882adfc5217SJeff Kirsher 
6883adfc5217SJeff Kirsher #define BNX2_REGDUMP_LEN		(32 * 1024)
6884adfc5217SJeff Kirsher 
6885adfc5217SJeff Kirsher static int
6886adfc5217SJeff Kirsher bnx2_get_regs_len(struct net_device *dev)
6887adfc5217SJeff Kirsher {
6888adfc5217SJeff Kirsher 	return BNX2_REGDUMP_LEN;
6889adfc5217SJeff Kirsher }
6890adfc5217SJeff Kirsher 
6891adfc5217SJeff Kirsher static void
6892adfc5217SJeff Kirsher bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
6893adfc5217SJeff Kirsher {
6894adfc5217SJeff Kirsher 	u32 *p = _p, i, offset;
6895adfc5217SJeff Kirsher 	u8 *orig_p = _p;
6896adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6897adfc5217SJeff Kirsher 	static const u32 reg_boundaries[] = {
6898adfc5217SJeff Kirsher 		0x0000, 0x0098, 0x0400, 0x045c,
6899adfc5217SJeff Kirsher 		0x0800, 0x0880, 0x0c00, 0x0c10,
6900adfc5217SJeff Kirsher 		0x0c30, 0x0d08, 0x1000, 0x101c,
6901adfc5217SJeff Kirsher 		0x1040, 0x1048, 0x1080, 0x10a4,
6902adfc5217SJeff Kirsher 		0x1400, 0x1490, 0x1498, 0x14f0,
6903adfc5217SJeff Kirsher 		0x1500, 0x155c, 0x1580, 0x15dc,
6904adfc5217SJeff Kirsher 		0x1600, 0x1658, 0x1680, 0x16d8,
6905adfc5217SJeff Kirsher 		0x1800, 0x1820, 0x1840, 0x1854,
6906adfc5217SJeff Kirsher 		0x1880, 0x1894, 0x1900, 0x1984,
6907adfc5217SJeff Kirsher 		0x1c00, 0x1c0c, 0x1c40, 0x1c54,
6908adfc5217SJeff Kirsher 		0x1c80, 0x1c94, 0x1d00, 0x1d84,
6909adfc5217SJeff Kirsher 		0x2000, 0x2030, 0x23c0, 0x2400,
6910adfc5217SJeff Kirsher 		0x2800, 0x2820, 0x2830, 0x2850,
6911adfc5217SJeff Kirsher 		0x2b40, 0x2c10, 0x2fc0, 0x3058,
6912adfc5217SJeff Kirsher 		0x3c00, 0x3c94, 0x4000, 0x4010,
6913adfc5217SJeff Kirsher 		0x4080, 0x4090, 0x43c0, 0x4458,
6914adfc5217SJeff Kirsher 		0x4c00, 0x4c18, 0x4c40, 0x4c54,
6915adfc5217SJeff Kirsher 		0x4fc0, 0x5010, 0x53c0, 0x5444,
6916adfc5217SJeff Kirsher 		0x5c00, 0x5c18, 0x5c80, 0x5c90,
6917adfc5217SJeff Kirsher 		0x5fc0, 0x6000, 0x6400, 0x6428,
6918adfc5217SJeff Kirsher 		0x6800, 0x6848, 0x684c, 0x6860,
6919adfc5217SJeff Kirsher 		0x6888, 0x6910, 0x8000
6920adfc5217SJeff Kirsher 	};
6921adfc5217SJeff Kirsher 
6922adfc5217SJeff Kirsher 	regs->version = 0;
6923adfc5217SJeff Kirsher 
6924adfc5217SJeff Kirsher 	memset(p, 0, BNX2_REGDUMP_LEN);
6925adfc5217SJeff Kirsher 
6926adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
6927adfc5217SJeff Kirsher 		return;
6928adfc5217SJeff Kirsher 
6929adfc5217SJeff Kirsher 	i = 0;
6930adfc5217SJeff Kirsher 	offset = reg_boundaries[0];
6931adfc5217SJeff Kirsher 	p += offset;
6932adfc5217SJeff Kirsher 	while (offset < BNX2_REGDUMP_LEN) {
6933adfc5217SJeff Kirsher 		*p++ = REG_RD(bp, offset);
6934adfc5217SJeff Kirsher 		offset += 4;
6935adfc5217SJeff Kirsher 		if (offset == reg_boundaries[i + 1]) {
6936adfc5217SJeff Kirsher 			offset = reg_boundaries[i + 2];
6937adfc5217SJeff Kirsher 			p = (u32 *) (orig_p + offset);
6938adfc5217SJeff Kirsher 			i += 2;
6939adfc5217SJeff Kirsher 		}
6940adfc5217SJeff Kirsher 	}
6941adfc5217SJeff Kirsher }
6942adfc5217SJeff Kirsher 
6943adfc5217SJeff Kirsher static void
6944adfc5217SJeff Kirsher bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
6945adfc5217SJeff Kirsher {
6946adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6947adfc5217SJeff Kirsher 
6948adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_NO_WOL) {
6949adfc5217SJeff Kirsher 		wol->supported = 0;
6950adfc5217SJeff Kirsher 		wol->wolopts = 0;
6951adfc5217SJeff Kirsher 	}
6952adfc5217SJeff Kirsher 	else {
6953adfc5217SJeff Kirsher 		wol->supported = WAKE_MAGIC;
6954adfc5217SJeff Kirsher 		if (bp->wol)
6955adfc5217SJeff Kirsher 			wol->wolopts = WAKE_MAGIC;
6956adfc5217SJeff Kirsher 		else
6957adfc5217SJeff Kirsher 			wol->wolopts = 0;
6958adfc5217SJeff Kirsher 	}
6959adfc5217SJeff Kirsher 	memset(&wol->sopass, 0, sizeof(wol->sopass));
6960adfc5217SJeff Kirsher }
6961adfc5217SJeff Kirsher 
6962adfc5217SJeff Kirsher static int
6963adfc5217SJeff Kirsher bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
6964adfc5217SJeff Kirsher {
6965adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6966adfc5217SJeff Kirsher 
6967adfc5217SJeff Kirsher 	if (wol->wolopts & ~WAKE_MAGIC)
6968adfc5217SJeff Kirsher 		return -EINVAL;
6969adfc5217SJeff Kirsher 
6970adfc5217SJeff Kirsher 	if (wol->wolopts & WAKE_MAGIC) {
6971adfc5217SJeff Kirsher 		if (bp->flags & BNX2_FLAG_NO_WOL)
6972adfc5217SJeff Kirsher 			return -EINVAL;
6973adfc5217SJeff Kirsher 
6974adfc5217SJeff Kirsher 		bp->wol = 1;
6975adfc5217SJeff Kirsher 	}
6976adfc5217SJeff Kirsher 	else {
6977adfc5217SJeff Kirsher 		bp->wol = 0;
6978adfc5217SJeff Kirsher 	}
6979adfc5217SJeff Kirsher 	return 0;
6980adfc5217SJeff Kirsher }
6981adfc5217SJeff Kirsher 
6982adfc5217SJeff Kirsher static int
6983adfc5217SJeff Kirsher bnx2_nway_reset(struct net_device *dev)
6984adfc5217SJeff Kirsher {
6985adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
6986adfc5217SJeff Kirsher 	u32 bmcr;
6987adfc5217SJeff Kirsher 
6988adfc5217SJeff Kirsher 	if (!netif_running(dev))
6989adfc5217SJeff Kirsher 		return -EAGAIN;
6990adfc5217SJeff Kirsher 
6991adfc5217SJeff Kirsher 	if (!(bp->autoneg & AUTONEG_SPEED)) {
6992adfc5217SJeff Kirsher 		return -EINVAL;
6993adfc5217SJeff Kirsher 	}
6994adfc5217SJeff Kirsher 
6995adfc5217SJeff Kirsher 	spin_lock_bh(&bp->phy_lock);
6996adfc5217SJeff Kirsher 
6997adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
6998adfc5217SJeff Kirsher 		int rc;
6999adfc5217SJeff Kirsher 
7000adfc5217SJeff Kirsher 		rc = bnx2_setup_remote_phy(bp, bp->phy_port);
7001adfc5217SJeff Kirsher 		spin_unlock_bh(&bp->phy_lock);
7002adfc5217SJeff Kirsher 		return rc;
7003adfc5217SJeff Kirsher 	}
7004adfc5217SJeff Kirsher 
7005adfc5217SJeff Kirsher 	/* Force a link down visible on the other side */
7006adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
7007adfc5217SJeff Kirsher 		bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
7008adfc5217SJeff Kirsher 		spin_unlock_bh(&bp->phy_lock);
7009adfc5217SJeff Kirsher 
7010adfc5217SJeff Kirsher 		msleep(20);
7011adfc5217SJeff Kirsher 
7012adfc5217SJeff Kirsher 		spin_lock_bh(&bp->phy_lock);
7013adfc5217SJeff Kirsher 
7014adfc5217SJeff Kirsher 		bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
7015adfc5217SJeff Kirsher 		bp->serdes_an_pending = 1;
7016adfc5217SJeff Kirsher 		mod_timer(&bp->timer, jiffies + bp->current_interval);
7017adfc5217SJeff Kirsher 	}
7018adfc5217SJeff Kirsher 
7019adfc5217SJeff Kirsher 	bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
7020adfc5217SJeff Kirsher 	bmcr &= ~BMCR_LOOPBACK;
7021adfc5217SJeff Kirsher 	bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
7022adfc5217SJeff Kirsher 
7023adfc5217SJeff Kirsher 	spin_unlock_bh(&bp->phy_lock);
7024adfc5217SJeff Kirsher 
7025adfc5217SJeff Kirsher 	return 0;
7026adfc5217SJeff Kirsher }
7027adfc5217SJeff Kirsher 
7028adfc5217SJeff Kirsher static u32
7029adfc5217SJeff Kirsher bnx2_get_link(struct net_device *dev)
7030adfc5217SJeff Kirsher {
7031adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7032adfc5217SJeff Kirsher 
7033adfc5217SJeff Kirsher 	return bp->link_up;
7034adfc5217SJeff Kirsher }
7035adfc5217SJeff Kirsher 
7036adfc5217SJeff Kirsher static int
7037adfc5217SJeff Kirsher bnx2_get_eeprom_len(struct net_device *dev)
7038adfc5217SJeff Kirsher {
7039adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7040adfc5217SJeff Kirsher 
7041adfc5217SJeff Kirsher 	if (bp->flash_info == NULL)
7042adfc5217SJeff Kirsher 		return 0;
7043adfc5217SJeff Kirsher 
7044adfc5217SJeff Kirsher 	return (int) bp->flash_size;
7045adfc5217SJeff Kirsher }
7046adfc5217SJeff Kirsher 
7047adfc5217SJeff Kirsher static int
7048adfc5217SJeff Kirsher bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
7049adfc5217SJeff Kirsher 		u8 *eebuf)
7050adfc5217SJeff Kirsher {
7051adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7052adfc5217SJeff Kirsher 	int rc;
7053adfc5217SJeff Kirsher 
7054adfc5217SJeff Kirsher 	if (!netif_running(dev))
7055adfc5217SJeff Kirsher 		return -EAGAIN;
7056adfc5217SJeff Kirsher 
7057adfc5217SJeff Kirsher 	/* parameters already validated in ethtool_get_eeprom */
7058adfc5217SJeff Kirsher 
7059adfc5217SJeff Kirsher 	rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
7060adfc5217SJeff Kirsher 
7061adfc5217SJeff Kirsher 	return rc;
7062adfc5217SJeff Kirsher }
7063adfc5217SJeff Kirsher 
7064adfc5217SJeff Kirsher static int
7065adfc5217SJeff Kirsher bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
7066adfc5217SJeff Kirsher 		u8 *eebuf)
7067adfc5217SJeff Kirsher {
7068adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7069adfc5217SJeff Kirsher 	int rc;
7070adfc5217SJeff Kirsher 
7071adfc5217SJeff Kirsher 	if (!netif_running(dev))
7072adfc5217SJeff Kirsher 		return -EAGAIN;
7073adfc5217SJeff Kirsher 
7074adfc5217SJeff Kirsher 	/* parameters already validated in ethtool_set_eeprom */
7075adfc5217SJeff Kirsher 
7076adfc5217SJeff Kirsher 	rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
7077adfc5217SJeff Kirsher 
7078adfc5217SJeff Kirsher 	return rc;
7079adfc5217SJeff Kirsher }
7080adfc5217SJeff Kirsher 
7081adfc5217SJeff Kirsher static int
7082adfc5217SJeff Kirsher bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
7083adfc5217SJeff Kirsher {
7084adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7085adfc5217SJeff Kirsher 
7086adfc5217SJeff Kirsher 	memset(coal, 0, sizeof(struct ethtool_coalesce));
7087adfc5217SJeff Kirsher 
7088adfc5217SJeff Kirsher 	coal->rx_coalesce_usecs = bp->rx_ticks;
7089adfc5217SJeff Kirsher 	coal->rx_max_coalesced_frames = bp->rx_quick_cons_trip;
7090adfc5217SJeff Kirsher 	coal->rx_coalesce_usecs_irq = bp->rx_ticks_int;
7091adfc5217SJeff Kirsher 	coal->rx_max_coalesced_frames_irq = bp->rx_quick_cons_trip_int;
7092adfc5217SJeff Kirsher 
7093adfc5217SJeff Kirsher 	coal->tx_coalesce_usecs = bp->tx_ticks;
7094adfc5217SJeff Kirsher 	coal->tx_max_coalesced_frames = bp->tx_quick_cons_trip;
7095adfc5217SJeff Kirsher 	coal->tx_coalesce_usecs_irq = bp->tx_ticks_int;
7096adfc5217SJeff Kirsher 	coal->tx_max_coalesced_frames_irq = bp->tx_quick_cons_trip_int;
7097adfc5217SJeff Kirsher 
7098adfc5217SJeff Kirsher 	coal->stats_block_coalesce_usecs = bp->stats_ticks;
7099adfc5217SJeff Kirsher 
7100adfc5217SJeff Kirsher 	return 0;
7101adfc5217SJeff Kirsher }
7102adfc5217SJeff Kirsher 
7103adfc5217SJeff Kirsher static int
7104adfc5217SJeff Kirsher bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
7105adfc5217SJeff Kirsher {
7106adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7107adfc5217SJeff Kirsher 
7108adfc5217SJeff Kirsher 	bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
7109adfc5217SJeff Kirsher 	if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff;
7110adfc5217SJeff Kirsher 
7111adfc5217SJeff Kirsher 	bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames;
7112adfc5217SJeff Kirsher 	if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff;
7113adfc5217SJeff Kirsher 
7114adfc5217SJeff Kirsher 	bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq;
7115adfc5217SJeff Kirsher 	if (bp->rx_ticks_int > 0x3ff) bp->rx_ticks_int = 0x3ff;
7116adfc5217SJeff Kirsher 
7117adfc5217SJeff Kirsher 	bp->rx_quick_cons_trip_int = (u16) coal->rx_max_coalesced_frames_irq;
7118adfc5217SJeff Kirsher 	if (bp->rx_quick_cons_trip_int > 0xff)
7119adfc5217SJeff Kirsher 		bp->rx_quick_cons_trip_int = 0xff;
7120adfc5217SJeff Kirsher 
7121adfc5217SJeff Kirsher 	bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
7122adfc5217SJeff Kirsher 	if (bp->tx_ticks > 0x3ff) bp->tx_ticks = 0x3ff;
7123adfc5217SJeff Kirsher 
7124adfc5217SJeff Kirsher 	bp->tx_quick_cons_trip = (u16) coal->tx_max_coalesced_frames;
7125adfc5217SJeff Kirsher 	if (bp->tx_quick_cons_trip > 0xff) bp->tx_quick_cons_trip = 0xff;
7126adfc5217SJeff Kirsher 
7127adfc5217SJeff Kirsher 	bp->tx_ticks_int = (u16) coal->tx_coalesce_usecs_irq;
7128adfc5217SJeff Kirsher 	if (bp->tx_ticks_int > 0x3ff) bp->tx_ticks_int = 0x3ff;
7129adfc5217SJeff Kirsher 
7130adfc5217SJeff Kirsher 	bp->tx_quick_cons_trip_int = (u16) coal->tx_max_coalesced_frames_irq;
7131adfc5217SJeff Kirsher 	if (bp->tx_quick_cons_trip_int > 0xff) bp->tx_quick_cons_trip_int =
7132adfc5217SJeff Kirsher 		0xff;
7133adfc5217SJeff Kirsher 
7134adfc5217SJeff Kirsher 	bp->stats_ticks = coal->stats_block_coalesce_usecs;
7135adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_BROKEN_STATS) {
7136adfc5217SJeff Kirsher 		if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
7137adfc5217SJeff Kirsher 			bp->stats_ticks = USEC_PER_SEC;
7138adfc5217SJeff Kirsher 	}
7139adfc5217SJeff Kirsher 	if (bp->stats_ticks > BNX2_HC_STATS_TICKS_HC_STAT_TICKS)
7140adfc5217SJeff Kirsher 		bp->stats_ticks = BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
7141adfc5217SJeff Kirsher 	bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
7142adfc5217SJeff Kirsher 
7143adfc5217SJeff Kirsher 	if (netif_running(bp->dev)) {
7144adfc5217SJeff Kirsher 		bnx2_netif_stop(bp, true);
7145adfc5217SJeff Kirsher 		bnx2_init_nic(bp, 0);
7146adfc5217SJeff Kirsher 		bnx2_netif_start(bp, true);
7147adfc5217SJeff Kirsher 	}
7148adfc5217SJeff Kirsher 
7149adfc5217SJeff Kirsher 	return 0;
7150adfc5217SJeff Kirsher }
7151adfc5217SJeff Kirsher 
7152adfc5217SJeff Kirsher static void
7153adfc5217SJeff Kirsher bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7154adfc5217SJeff Kirsher {
7155adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7156adfc5217SJeff Kirsher 
7157adfc5217SJeff Kirsher 	ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
7158adfc5217SJeff Kirsher 	ering->rx_mini_max_pending = 0;
7159adfc5217SJeff Kirsher 	ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
7160adfc5217SJeff Kirsher 
7161adfc5217SJeff Kirsher 	ering->rx_pending = bp->rx_ring_size;
7162adfc5217SJeff Kirsher 	ering->rx_mini_pending = 0;
7163adfc5217SJeff Kirsher 	ering->rx_jumbo_pending = bp->rx_pg_ring_size;
7164adfc5217SJeff Kirsher 
7165adfc5217SJeff Kirsher 	ering->tx_max_pending = MAX_TX_DESC_CNT;
7166adfc5217SJeff Kirsher 	ering->tx_pending = bp->tx_ring_size;
7167adfc5217SJeff Kirsher }
7168adfc5217SJeff Kirsher 
7169adfc5217SJeff Kirsher static int
7170adfc5217SJeff Kirsher bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
7171adfc5217SJeff Kirsher {
7172adfc5217SJeff Kirsher 	if (netif_running(bp->dev)) {
7173adfc5217SJeff Kirsher 		/* Reset will erase chipset stats; save them */
7174adfc5217SJeff Kirsher 		bnx2_save_stats(bp);
7175adfc5217SJeff Kirsher 
7176adfc5217SJeff Kirsher 		bnx2_netif_stop(bp, true);
7177adfc5217SJeff Kirsher 		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
7178adfc5217SJeff Kirsher 		__bnx2_free_irq(bp);
7179adfc5217SJeff Kirsher 		bnx2_free_skbs(bp);
7180adfc5217SJeff Kirsher 		bnx2_free_mem(bp);
7181adfc5217SJeff Kirsher 	}
7182adfc5217SJeff Kirsher 
7183adfc5217SJeff Kirsher 	bnx2_set_rx_ring_size(bp, rx);
7184adfc5217SJeff Kirsher 	bp->tx_ring_size = tx;
7185adfc5217SJeff Kirsher 
7186adfc5217SJeff Kirsher 	if (netif_running(bp->dev)) {
7187adfc5217SJeff Kirsher 		int rc;
7188adfc5217SJeff Kirsher 
7189adfc5217SJeff Kirsher 		rc = bnx2_alloc_mem(bp);
7190adfc5217SJeff Kirsher 		if (!rc)
7191adfc5217SJeff Kirsher 			rc = bnx2_request_irq(bp);
7192adfc5217SJeff Kirsher 
7193adfc5217SJeff Kirsher 		if (!rc)
7194adfc5217SJeff Kirsher 			rc = bnx2_init_nic(bp, 0);
7195adfc5217SJeff Kirsher 
7196adfc5217SJeff Kirsher 		if (rc) {
7197adfc5217SJeff Kirsher 			bnx2_napi_enable(bp);
7198adfc5217SJeff Kirsher 			dev_close(bp->dev);
7199adfc5217SJeff Kirsher 			return rc;
7200adfc5217SJeff Kirsher 		}
7201adfc5217SJeff Kirsher #ifdef BCM_CNIC
7202adfc5217SJeff Kirsher 		mutex_lock(&bp->cnic_lock);
7203adfc5217SJeff Kirsher 		/* Let cnic know about the new status block. */
7204adfc5217SJeff Kirsher 		if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD)
7205adfc5217SJeff Kirsher 			bnx2_setup_cnic_irq_info(bp);
7206adfc5217SJeff Kirsher 		mutex_unlock(&bp->cnic_lock);
7207adfc5217SJeff Kirsher #endif
7208adfc5217SJeff Kirsher 		bnx2_netif_start(bp, true);
7209adfc5217SJeff Kirsher 	}
7210adfc5217SJeff Kirsher 	return 0;
7211adfc5217SJeff Kirsher }
7212adfc5217SJeff Kirsher 
7213adfc5217SJeff Kirsher static int
7214adfc5217SJeff Kirsher bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7215adfc5217SJeff Kirsher {
7216adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7217adfc5217SJeff Kirsher 	int rc;
7218adfc5217SJeff Kirsher 
7219adfc5217SJeff Kirsher 	if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
7220adfc5217SJeff Kirsher 		(ering->tx_pending > MAX_TX_DESC_CNT) ||
7221adfc5217SJeff Kirsher 		(ering->tx_pending <= MAX_SKB_FRAGS)) {
7222adfc5217SJeff Kirsher 
7223adfc5217SJeff Kirsher 		return -EINVAL;
7224adfc5217SJeff Kirsher 	}
7225adfc5217SJeff Kirsher 	rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending);
7226adfc5217SJeff Kirsher 	return rc;
7227adfc5217SJeff Kirsher }
7228adfc5217SJeff Kirsher 
7229adfc5217SJeff Kirsher static void
7230adfc5217SJeff Kirsher bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
7231adfc5217SJeff Kirsher {
7232adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7233adfc5217SJeff Kirsher 
7234adfc5217SJeff Kirsher 	epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0);
7235adfc5217SJeff Kirsher 	epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0);
7236adfc5217SJeff Kirsher 	epause->tx_pause = ((bp->flow_ctrl & FLOW_CTRL_TX) != 0);
7237adfc5217SJeff Kirsher }
7238adfc5217SJeff Kirsher 
7239adfc5217SJeff Kirsher static int
7240adfc5217SJeff Kirsher bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
7241adfc5217SJeff Kirsher {
7242adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7243adfc5217SJeff Kirsher 
7244adfc5217SJeff Kirsher 	bp->req_flow_ctrl = 0;
7245adfc5217SJeff Kirsher 	if (epause->rx_pause)
7246adfc5217SJeff Kirsher 		bp->req_flow_ctrl |= FLOW_CTRL_RX;
7247adfc5217SJeff Kirsher 	if (epause->tx_pause)
7248adfc5217SJeff Kirsher 		bp->req_flow_ctrl |= FLOW_CTRL_TX;
7249adfc5217SJeff Kirsher 
7250adfc5217SJeff Kirsher 	if (epause->autoneg) {
7251adfc5217SJeff Kirsher 		bp->autoneg |= AUTONEG_FLOW_CTRL;
7252adfc5217SJeff Kirsher 	}
7253adfc5217SJeff Kirsher 	else {
7254adfc5217SJeff Kirsher 		bp->autoneg &= ~AUTONEG_FLOW_CTRL;
7255adfc5217SJeff Kirsher 	}
7256adfc5217SJeff Kirsher 
7257adfc5217SJeff Kirsher 	if (netif_running(dev)) {
7258adfc5217SJeff Kirsher 		spin_lock_bh(&bp->phy_lock);
7259adfc5217SJeff Kirsher 		bnx2_setup_phy(bp, bp->phy_port);
7260adfc5217SJeff Kirsher 		spin_unlock_bh(&bp->phy_lock);
7261adfc5217SJeff Kirsher 	}
7262adfc5217SJeff Kirsher 
7263adfc5217SJeff Kirsher 	return 0;
7264adfc5217SJeff Kirsher }
7265adfc5217SJeff Kirsher 
7266adfc5217SJeff Kirsher static struct {
7267adfc5217SJeff Kirsher 	char string[ETH_GSTRING_LEN];
7268adfc5217SJeff Kirsher } bnx2_stats_str_arr[] = {
7269adfc5217SJeff Kirsher 	{ "rx_bytes" },
7270adfc5217SJeff Kirsher 	{ "rx_error_bytes" },
7271adfc5217SJeff Kirsher 	{ "tx_bytes" },
7272adfc5217SJeff Kirsher 	{ "tx_error_bytes" },
7273adfc5217SJeff Kirsher 	{ "rx_ucast_packets" },
7274adfc5217SJeff Kirsher 	{ "rx_mcast_packets" },
7275adfc5217SJeff Kirsher 	{ "rx_bcast_packets" },
7276adfc5217SJeff Kirsher 	{ "tx_ucast_packets" },
7277adfc5217SJeff Kirsher 	{ "tx_mcast_packets" },
7278adfc5217SJeff Kirsher 	{ "tx_bcast_packets" },
7279adfc5217SJeff Kirsher 	{ "tx_mac_errors" },
7280adfc5217SJeff Kirsher 	{ "tx_carrier_errors" },
7281adfc5217SJeff Kirsher 	{ "rx_crc_errors" },
7282adfc5217SJeff Kirsher 	{ "rx_align_errors" },
7283adfc5217SJeff Kirsher 	{ "tx_single_collisions" },
7284adfc5217SJeff Kirsher 	{ "tx_multi_collisions" },
7285adfc5217SJeff Kirsher 	{ "tx_deferred" },
7286adfc5217SJeff Kirsher 	{ "tx_excess_collisions" },
7287adfc5217SJeff Kirsher 	{ "tx_late_collisions" },
7288adfc5217SJeff Kirsher 	{ "tx_total_collisions" },
7289adfc5217SJeff Kirsher 	{ "rx_fragments" },
7290adfc5217SJeff Kirsher 	{ "rx_jabbers" },
7291adfc5217SJeff Kirsher 	{ "rx_undersize_packets" },
7292adfc5217SJeff Kirsher 	{ "rx_oversize_packets" },
7293adfc5217SJeff Kirsher 	{ "rx_64_byte_packets" },
7294adfc5217SJeff Kirsher 	{ "rx_65_to_127_byte_packets" },
7295adfc5217SJeff Kirsher 	{ "rx_128_to_255_byte_packets" },
7296adfc5217SJeff Kirsher 	{ "rx_256_to_511_byte_packets" },
7297adfc5217SJeff Kirsher 	{ "rx_512_to_1023_byte_packets" },
7298adfc5217SJeff Kirsher 	{ "rx_1024_to_1522_byte_packets" },
7299adfc5217SJeff Kirsher 	{ "rx_1523_to_9022_byte_packets" },
7300adfc5217SJeff Kirsher 	{ "tx_64_byte_packets" },
7301adfc5217SJeff Kirsher 	{ "tx_65_to_127_byte_packets" },
7302adfc5217SJeff Kirsher 	{ "tx_128_to_255_byte_packets" },
7303adfc5217SJeff Kirsher 	{ "tx_256_to_511_byte_packets" },
7304adfc5217SJeff Kirsher 	{ "tx_512_to_1023_byte_packets" },
7305adfc5217SJeff Kirsher 	{ "tx_1024_to_1522_byte_packets" },
7306adfc5217SJeff Kirsher 	{ "tx_1523_to_9022_byte_packets" },
7307adfc5217SJeff Kirsher 	{ "rx_xon_frames" },
7308adfc5217SJeff Kirsher 	{ "rx_xoff_frames" },
7309adfc5217SJeff Kirsher 	{ "tx_xon_frames" },
7310adfc5217SJeff Kirsher 	{ "tx_xoff_frames" },
7311adfc5217SJeff Kirsher 	{ "rx_mac_ctrl_frames" },
7312adfc5217SJeff Kirsher 	{ "rx_filtered_packets" },
7313adfc5217SJeff Kirsher 	{ "rx_ftq_discards" },
7314adfc5217SJeff Kirsher 	{ "rx_discards" },
7315adfc5217SJeff Kirsher 	{ "rx_fw_discards" },
7316adfc5217SJeff Kirsher };
7317adfc5217SJeff Kirsher 
7318adfc5217SJeff Kirsher #define BNX2_NUM_STATS (sizeof(bnx2_stats_str_arr)/\
7319adfc5217SJeff Kirsher 			sizeof(bnx2_stats_str_arr[0]))
7320adfc5217SJeff Kirsher 
7321adfc5217SJeff Kirsher #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
7322adfc5217SJeff Kirsher 
7323adfc5217SJeff Kirsher static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
7324adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCInOctets_hi),
7325adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCInBadOctets_hi),
7326adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCOutOctets_hi),
7327adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCOutBadOctets_hi),
7328adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCInUcastPkts_hi),
7329adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCInMulticastPkts_hi),
7330adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCInBroadcastPkts_hi),
7331adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCOutUcastPkts_hi),
7332adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi),
7333adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi),
7334adfc5217SJeff Kirsher     STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors),
7335adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors),
7336adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsFCSErrors),
7337adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsAlignmentErrors),
7338adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames),
7339adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames),
7340adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions),
7341adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions),
7342adfc5217SJeff Kirsher     STATS_OFFSET32(stat_Dot3StatsLateCollisions),
7343adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsCollisions),
7344adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsFragments),
7345adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsJabbers),
7346adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsUndersizePkts),
7347adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsOverrsizePkts),
7348adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx64Octets),
7349adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets),
7350adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets),
7351adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets),
7352adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets),
7353adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets),
7354adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets),
7355adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx64Octets),
7356adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets),
7357adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets),
7358adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets),
7359adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets),
7360adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets),
7361adfc5217SJeff Kirsher     STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets),
7362adfc5217SJeff Kirsher     STATS_OFFSET32(stat_XonPauseFramesReceived),
7363adfc5217SJeff Kirsher     STATS_OFFSET32(stat_XoffPauseFramesReceived),
7364adfc5217SJeff Kirsher     STATS_OFFSET32(stat_OutXonSent),
7365adfc5217SJeff Kirsher     STATS_OFFSET32(stat_OutXoffSent),
7366adfc5217SJeff Kirsher     STATS_OFFSET32(stat_MacControlFramesReceived),
7367adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),
7368adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfInFTQDiscards),
7369adfc5217SJeff Kirsher     STATS_OFFSET32(stat_IfInMBUFDiscards),
7370adfc5217SJeff Kirsher     STATS_OFFSET32(stat_FwRxDrop),
7371adfc5217SJeff Kirsher };
7372adfc5217SJeff Kirsher 
7373adfc5217SJeff Kirsher /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
7374adfc5217SJeff Kirsher  * skipped because of errata.
7375adfc5217SJeff Kirsher  */
7376adfc5217SJeff Kirsher static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
7377adfc5217SJeff Kirsher 	8,0,8,8,8,8,8,8,8,8,
7378adfc5217SJeff Kirsher 	4,0,4,4,4,4,4,4,4,4,
7379adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,4,4,4,
7380adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,4,4,4,
7381adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,
7382adfc5217SJeff Kirsher };
7383adfc5217SJeff Kirsher 
7384adfc5217SJeff Kirsher static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
7385adfc5217SJeff Kirsher 	8,0,8,8,8,8,8,8,8,8,
7386adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,4,4,4,
7387adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,4,4,4,
7388adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,4,4,4,
7389adfc5217SJeff Kirsher 	4,4,4,4,4,4,4,
7390adfc5217SJeff Kirsher };
7391adfc5217SJeff Kirsher 
7392adfc5217SJeff Kirsher #define BNX2_NUM_TESTS 6
7393adfc5217SJeff Kirsher 
7394adfc5217SJeff Kirsher static struct {
7395adfc5217SJeff Kirsher 	char string[ETH_GSTRING_LEN];
7396adfc5217SJeff Kirsher } bnx2_tests_str_arr[BNX2_NUM_TESTS] = {
7397adfc5217SJeff Kirsher 	{ "register_test (offline)" },
7398adfc5217SJeff Kirsher 	{ "memory_test (offline)" },
7399adfc5217SJeff Kirsher 	{ "loopback_test (offline)" },
7400adfc5217SJeff Kirsher 	{ "nvram_test (online)" },
7401adfc5217SJeff Kirsher 	{ "interrupt_test (online)" },
7402adfc5217SJeff Kirsher 	{ "link_test (online)" },
7403adfc5217SJeff Kirsher };
7404adfc5217SJeff Kirsher 
7405adfc5217SJeff Kirsher static int
7406adfc5217SJeff Kirsher bnx2_get_sset_count(struct net_device *dev, int sset)
7407adfc5217SJeff Kirsher {
7408adfc5217SJeff Kirsher 	switch (sset) {
7409adfc5217SJeff Kirsher 	case ETH_SS_TEST:
7410adfc5217SJeff Kirsher 		return BNX2_NUM_TESTS;
7411adfc5217SJeff Kirsher 	case ETH_SS_STATS:
7412adfc5217SJeff Kirsher 		return BNX2_NUM_STATS;
7413adfc5217SJeff Kirsher 	default:
7414adfc5217SJeff Kirsher 		return -EOPNOTSUPP;
7415adfc5217SJeff Kirsher 	}
7416adfc5217SJeff Kirsher }
7417adfc5217SJeff Kirsher 
7418adfc5217SJeff Kirsher static void
7419adfc5217SJeff Kirsher bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
7420adfc5217SJeff Kirsher {
7421adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7422adfc5217SJeff Kirsher 
7423adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, PCI_D0);
7424adfc5217SJeff Kirsher 
7425adfc5217SJeff Kirsher 	memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
7426adfc5217SJeff Kirsher 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
7427adfc5217SJeff Kirsher 		int i;
7428adfc5217SJeff Kirsher 
7429adfc5217SJeff Kirsher 		bnx2_netif_stop(bp, true);
7430adfc5217SJeff Kirsher 		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
7431adfc5217SJeff Kirsher 		bnx2_free_skbs(bp);
7432adfc5217SJeff Kirsher 
7433adfc5217SJeff Kirsher 		if (bnx2_test_registers(bp) != 0) {
7434adfc5217SJeff Kirsher 			buf[0] = 1;
7435adfc5217SJeff Kirsher 			etest->flags |= ETH_TEST_FL_FAILED;
7436adfc5217SJeff Kirsher 		}
7437adfc5217SJeff Kirsher 		if (bnx2_test_memory(bp) != 0) {
7438adfc5217SJeff Kirsher 			buf[1] = 1;
7439adfc5217SJeff Kirsher 			etest->flags |= ETH_TEST_FL_FAILED;
7440adfc5217SJeff Kirsher 		}
7441adfc5217SJeff Kirsher 		if ((buf[2] = bnx2_test_loopback(bp)) != 0)
7442adfc5217SJeff Kirsher 			etest->flags |= ETH_TEST_FL_FAILED;
7443adfc5217SJeff Kirsher 
7444adfc5217SJeff Kirsher 		if (!netif_running(bp->dev))
7445adfc5217SJeff Kirsher 			bnx2_shutdown_chip(bp);
7446adfc5217SJeff Kirsher 		else {
7447adfc5217SJeff Kirsher 			bnx2_init_nic(bp, 1);
7448adfc5217SJeff Kirsher 			bnx2_netif_start(bp, true);
7449adfc5217SJeff Kirsher 		}
7450adfc5217SJeff Kirsher 
7451adfc5217SJeff Kirsher 		/* wait for link up */
7452adfc5217SJeff Kirsher 		for (i = 0; i < 7; i++) {
7453adfc5217SJeff Kirsher 			if (bp->link_up)
7454adfc5217SJeff Kirsher 				break;
7455adfc5217SJeff Kirsher 			msleep_interruptible(1000);
7456adfc5217SJeff Kirsher 		}
7457adfc5217SJeff Kirsher 	}
7458adfc5217SJeff Kirsher 
7459adfc5217SJeff Kirsher 	if (bnx2_test_nvram(bp) != 0) {
7460adfc5217SJeff Kirsher 		buf[3] = 1;
7461adfc5217SJeff Kirsher 		etest->flags |= ETH_TEST_FL_FAILED;
7462adfc5217SJeff Kirsher 	}
7463adfc5217SJeff Kirsher 	if (bnx2_test_intr(bp) != 0) {
7464adfc5217SJeff Kirsher 		buf[4] = 1;
7465adfc5217SJeff Kirsher 		etest->flags |= ETH_TEST_FL_FAILED;
7466adfc5217SJeff Kirsher 	}
7467adfc5217SJeff Kirsher 
7468adfc5217SJeff Kirsher 	if (bnx2_test_link(bp) != 0) {
7469adfc5217SJeff Kirsher 		buf[5] = 1;
7470adfc5217SJeff Kirsher 		etest->flags |= ETH_TEST_FL_FAILED;
7471adfc5217SJeff Kirsher 
7472adfc5217SJeff Kirsher 	}
7473adfc5217SJeff Kirsher 	if (!netif_running(bp->dev))
7474adfc5217SJeff Kirsher 		bnx2_set_power_state(bp, PCI_D3hot);
7475adfc5217SJeff Kirsher }
7476adfc5217SJeff Kirsher 
7477adfc5217SJeff Kirsher static void
7478adfc5217SJeff Kirsher bnx2_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
7479adfc5217SJeff Kirsher {
7480adfc5217SJeff Kirsher 	switch (stringset) {
7481adfc5217SJeff Kirsher 	case ETH_SS_STATS:
7482adfc5217SJeff Kirsher 		memcpy(buf, bnx2_stats_str_arr,
7483adfc5217SJeff Kirsher 			sizeof(bnx2_stats_str_arr));
7484adfc5217SJeff Kirsher 		break;
7485adfc5217SJeff Kirsher 	case ETH_SS_TEST:
7486adfc5217SJeff Kirsher 		memcpy(buf, bnx2_tests_str_arr,
7487adfc5217SJeff Kirsher 			sizeof(bnx2_tests_str_arr));
7488adfc5217SJeff Kirsher 		break;
7489adfc5217SJeff Kirsher 	}
7490adfc5217SJeff Kirsher }
7491adfc5217SJeff Kirsher 
7492adfc5217SJeff Kirsher static void
7493adfc5217SJeff Kirsher bnx2_get_ethtool_stats(struct net_device *dev,
7494adfc5217SJeff Kirsher 		struct ethtool_stats *stats, u64 *buf)
7495adfc5217SJeff Kirsher {
7496adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7497adfc5217SJeff Kirsher 	int i;
7498adfc5217SJeff Kirsher 	u32 *hw_stats = (u32 *) bp->stats_blk;
7499adfc5217SJeff Kirsher 	u32 *temp_stats = (u32 *) bp->temp_stats_blk;
7500adfc5217SJeff Kirsher 	u8 *stats_len_arr = NULL;
7501adfc5217SJeff Kirsher 
7502adfc5217SJeff Kirsher 	if (hw_stats == NULL) {
7503adfc5217SJeff Kirsher 		memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS);
7504adfc5217SJeff Kirsher 		return;
7505adfc5217SJeff Kirsher 	}
7506adfc5217SJeff Kirsher 
7507adfc5217SJeff Kirsher 	if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
7508adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5706_A1) ||
7509adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5706_A2) ||
7510adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_A0))
7511adfc5217SJeff Kirsher 		stats_len_arr = bnx2_5706_stats_len_arr;
7512adfc5217SJeff Kirsher 	else
7513adfc5217SJeff Kirsher 		stats_len_arr = bnx2_5708_stats_len_arr;
7514adfc5217SJeff Kirsher 
7515adfc5217SJeff Kirsher 	for (i = 0; i < BNX2_NUM_STATS; i++) {
7516adfc5217SJeff Kirsher 		unsigned long offset;
7517adfc5217SJeff Kirsher 
7518adfc5217SJeff Kirsher 		if (stats_len_arr[i] == 0) {
7519adfc5217SJeff Kirsher 			/* skip this counter */
7520adfc5217SJeff Kirsher 			buf[i] = 0;
7521adfc5217SJeff Kirsher 			continue;
7522adfc5217SJeff Kirsher 		}
7523adfc5217SJeff Kirsher 
7524adfc5217SJeff Kirsher 		offset = bnx2_stats_offset_arr[i];
7525adfc5217SJeff Kirsher 		if (stats_len_arr[i] == 4) {
7526adfc5217SJeff Kirsher 			/* 4-byte counter */
7527adfc5217SJeff Kirsher 			buf[i] = (u64) *(hw_stats + offset) +
7528adfc5217SJeff Kirsher 				 *(temp_stats + offset);
7529adfc5217SJeff Kirsher 			continue;
7530adfc5217SJeff Kirsher 		}
7531adfc5217SJeff Kirsher 		/* 8-byte counter */
7532adfc5217SJeff Kirsher 		buf[i] = (((u64) *(hw_stats + offset)) << 32) +
7533adfc5217SJeff Kirsher 			 *(hw_stats + offset + 1) +
7534adfc5217SJeff Kirsher 			 (((u64) *(temp_stats + offset)) << 32) +
7535adfc5217SJeff Kirsher 			 *(temp_stats + offset + 1);
7536adfc5217SJeff Kirsher 	}
7537adfc5217SJeff Kirsher }
7538adfc5217SJeff Kirsher 
7539adfc5217SJeff Kirsher static int
7540adfc5217SJeff Kirsher bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
7541adfc5217SJeff Kirsher {
7542adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7543adfc5217SJeff Kirsher 
7544adfc5217SJeff Kirsher 	switch (state) {
7545adfc5217SJeff Kirsher 	case ETHTOOL_ID_ACTIVE:
7546adfc5217SJeff Kirsher 		bnx2_set_power_state(bp, PCI_D0);
7547adfc5217SJeff Kirsher 
7548adfc5217SJeff Kirsher 		bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
7549adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
7550adfc5217SJeff Kirsher 		return 1;	/* cycle on/off once per second */
7551adfc5217SJeff Kirsher 
7552adfc5217SJeff Kirsher 	case ETHTOOL_ID_ON:
7553adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
7554adfc5217SJeff Kirsher 		       BNX2_EMAC_LED_1000MB_OVERRIDE |
7555adfc5217SJeff Kirsher 		       BNX2_EMAC_LED_100MB_OVERRIDE |
7556adfc5217SJeff Kirsher 		       BNX2_EMAC_LED_10MB_OVERRIDE |
7557adfc5217SJeff Kirsher 		       BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
7558adfc5217SJeff Kirsher 		       BNX2_EMAC_LED_TRAFFIC);
7559adfc5217SJeff Kirsher 		break;
7560adfc5217SJeff Kirsher 
7561adfc5217SJeff Kirsher 	case ETHTOOL_ID_OFF:
7562adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
7563adfc5217SJeff Kirsher 		break;
7564adfc5217SJeff Kirsher 
7565adfc5217SJeff Kirsher 	case ETHTOOL_ID_INACTIVE:
7566adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_EMAC_LED, 0);
7567adfc5217SJeff Kirsher 		REG_WR(bp, BNX2_MISC_CFG, bp->leds_save);
7568adfc5217SJeff Kirsher 
7569adfc5217SJeff Kirsher 		if (!netif_running(dev))
7570adfc5217SJeff Kirsher 			bnx2_set_power_state(bp, PCI_D3hot);
7571adfc5217SJeff Kirsher 		break;
7572adfc5217SJeff Kirsher 	}
7573adfc5217SJeff Kirsher 
7574adfc5217SJeff Kirsher 	return 0;
7575adfc5217SJeff Kirsher }
7576adfc5217SJeff Kirsher 
7577adfc5217SJeff Kirsher static u32
7578adfc5217SJeff Kirsher bnx2_fix_features(struct net_device *dev, u32 features)
7579adfc5217SJeff Kirsher {
7580adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7581adfc5217SJeff Kirsher 
7582adfc5217SJeff Kirsher 	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
7583adfc5217SJeff Kirsher 		features |= NETIF_F_HW_VLAN_RX;
7584adfc5217SJeff Kirsher 
7585adfc5217SJeff Kirsher 	return features;
7586adfc5217SJeff Kirsher }
7587adfc5217SJeff Kirsher 
7588adfc5217SJeff Kirsher static int
7589adfc5217SJeff Kirsher bnx2_set_features(struct net_device *dev, u32 features)
7590adfc5217SJeff Kirsher {
7591adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7592adfc5217SJeff Kirsher 
7593adfc5217SJeff Kirsher 	/* TSO with VLAN tag won't work with current firmware */
7594adfc5217SJeff Kirsher 	if (features & NETIF_F_HW_VLAN_TX)
7595adfc5217SJeff Kirsher 		dev->vlan_features |= (dev->hw_features & NETIF_F_ALL_TSO);
7596adfc5217SJeff Kirsher 	else
7597adfc5217SJeff Kirsher 		dev->vlan_features &= ~NETIF_F_ALL_TSO;
7598adfc5217SJeff Kirsher 
7599adfc5217SJeff Kirsher 	if ((!!(features & NETIF_F_HW_VLAN_RX) !=
7600adfc5217SJeff Kirsher 	    !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
7601adfc5217SJeff Kirsher 	    netif_running(dev)) {
7602adfc5217SJeff Kirsher 		bnx2_netif_stop(bp, false);
7603adfc5217SJeff Kirsher 		dev->features = features;
7604adfc5217SJeff Kirsher 		bnx2_set_rx_mode(dev);
7605adfc5217SJeff Kirsher 		bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
7606adfc5217SJeff Kirsher 		bnx2_netif_start(bp, false);
7607adfc5217SJeff Kirsher 		return 1;
7608adfc5217SJeff Kirsher 	}
7609adfc5217SJeff Kirsher 
7610adfc5217SJeff Kirsher 	return 0;
7611adfc5217SJeff Kirsher }
7612adfc5217SJeff Kirsher 
7613adfc5217SJeff Kirsher static const struct ethtool_ops bnx2_ethtool_ops = {
7614adfc5217SJeff Kirsher 	.get_settings		= bnx2_get_settings,
7615adfc5217SJeff Kirsher 	.set_settings		= bnx2_set_settings,
7616adfc5217SJeff Kirsher 	.get_drvinfo		= bnx2_get_drvinfo,
7617adfc5217SJeff Kirsher 	.get_regs_len		= bnx2_get_regs_len,
7618adfc5217SJeff Kirsher 	.get_regs		= bnx2_get_regs,
7619adfc5217SJeff Kirsher 	.get_wol		= bnx2_get_wol,
7620adfc5217SJeff Kirsher 	.set_wol		= bnx2_set_wol,
7621adfc5217SJeff Kirsher 	.nway_reset		= bnx2_nway_reset,
7622adfc5217SJeff Kirsher 	.get_link		= bnx2_get_link,
7623adfc5217SJeff Kirsher 	.get_eeprom_len		= bnx2_get_eeprom_len,
7624adfc5217SJeff Kirsher 	.get_eeprom		= bnx2_get_eeprom,
7625adfc5217SJeff Kirsher 	.set_eeprom		= bnx2_set_eeprom,
7626adfc5217SJeff Kirsher 	.get_coalesce		= bnx2_get_coalesce,
7627adfc5217SJeff Kirsher 	.set_coalesce		= bnx2_set_coalesce,
7628adfc5217SJeff Kirsher 	.get_ringparam		= bnx2_get_ringparam,
7629adfc5217SJeff Kirsher 	.set_ringparam		= bnx2_set_ringparam,
7630adfc5217SJeff Kirsher 	.get_pauseparam		= bnx2_get_pauseparam,
7631adfc5217SJeff Kirsher 	.set_pauseparam		= bnx2_set_pauseparam,
7632adfc5217SJeff Kirsher 	.self_test		= bnx2_self_test,
7633adfc5217SJeff Kirsher 	.get_strings		= bnx2_get_strings,
7634adfc5217SJeff Kirsher 	.set_phys_id		= bnx2_set_phys_id,
7635adfc5217SJeff Kirsher 	.get_ethtool_stats	= bnx2_get_ethtool_stats,
7636adfc5217SJeff Kirsher 	.get_sset_count		= bnx2_get_sset_count,
7637adfc5217SJeff Kirsher };
7638adfc5217SJeff Kirsher 
7639adfc5217SJeff Kirsher /* Called with rtnl_lock */
7640adfc5217SJeff Kirsher static int
7641adfc5217SJeff Kirsher bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
7642adfc5217SJeff Kirsher {
7643adfc5217SJeff Kirsher 	struct mii_ioctl_data *data = if_mii(ifr);
7644adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7645adfc5217SJeff Kirsher 	int err;
7646adfc5217SJeff Kirsher 
7647adfc5217SJeff Kirsher 	switch(cmd) {
7648adfc5217SJeff Kirsher 	case SIOCGMIIPHY:
7649adfc5217SJeff Kirsher 		data->phy_id = bp->phy_addr;
7650adfc5217SJeff Kirsher 
7651adfc5217SJeff Kirsher 		/* fallthru */
7652adfc5217SJeff Kirsher 	case SIOCGMIIREG: {
7653adfc5217SJeff Kirsher 		u32 mii_regval;
7654adfc5217SJeff Kirsher 
7655adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
7656adfc5217SJeff Kirsher 			return -EOPNOTSUPP;
7657adfc5217SJeff Kirsher 
7658adfc5217SJeff Kirsher 		if (!netif_running(dev))
7659adfc5217SJeff Kirsher 			return -EAGAIN;
7660adfc5217SJeff Kirsher 
7661adfc5217SJeff Kirsher 		spin_lock_bh(&bp->phy_lock);
7662adfc5217SJeff Kirsher 		err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
7663adfc5217SJeff Kirsher 		spin_unlock_bh(&bp->phy_lock);
7664adfc5217SJeff Kirsher 
7665adfc5217SJeff Kirsher 		data->val_out = mii_regval;
7666adfc5217SJeff Kirsher 
7667adfc5217SJeff Kirsher 		return err;
7668adfc5217SJeff Kirsher 	}
7669adfc5217SJeff Kirsher 
7670adfc5217SJeff Kirsher 	case SIOCSMIIREG:
7671adfc5217SJeff Kirsher 		if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
7672adfc5217SJeff Kirsher 			return -EOPNOTSUPP;
7673adfc5217SJeff Kirsher 
7674adfc5217SJeff Kirsher 		if (!netif_running(dev))
7675adfc5217SJeff Kirsher 			return -EAGAIN;
7676adfc5217SJeff Kirsher 
7677adfc5217SJeff Kirsher 		spin_lock_bh(&bp->phy_lock);
7678adfc5217SJeff Kirsher 		err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
7679adfc5217SJeff Kirsher 		spin_unlock_bh(&bp->phy_lock);
7680adfc5217SJeff Kirsher 
7681adfc5217SJeff Kirsher 		return err;
7682adfc5217SJeff Kirsher 
7683adfc5217SJeff Kirsher 	default:
7684adfc5217SJeff Kirsher 		/* do nothing */
7685adfc5217SJeff Kirsher 		break;
7686adfc5217SJeff Kirsher 	}
7687adfc5217SJeff Kirsher 	return -EOPNOTSUPP;
7688adfc5217SJeff Kirsher }
7689adfc5217SJeff Kirsher 
7690adfc5217SJeff Kirsher /* Called with rtnl_lock */
7691adfc5217SJeff Kirsher static int
7692adfc5217SJeff Kirsher bnx2_change_mac_addr(struct net_device *dev, void *p)
7693adfc5217SJeff Kirsher {
7694adfc5217SJeff Kirsher 	struct sockaddr *addr = p;
7695adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7696adfc5217SJeff Kirsher 
7697adfc5217SJeff Kirsher 	if (!is_valid_ether_addr(addr->sa_data))
7698adfc5217SJeff Kirsher 		return -EINVAL;
7699adfc5217SJeff Kirsher 
7700adfc5217SJeff Kirsher 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
7701adfc5217SJeff Kirsher 	if (netif_running(dev))
7702adfc5217SJeff Kirsher 		bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
7703adfc5217SJeff Kirsher 
7704adfc5217SJeff Kirsher 	return 0;
7705adfc5217SJeff Kirsher }
7706adfc5217SJeff Kirsher 
7707adfc5217SJeff Kirsher /* Called with rtnl_lock */
7708adfc5217SJeff Kirsher static int
7709adfc5217SJeff Kirsher bnx2_change_mtu(struct net_device *dev, int new_mtu)
7710adfc5217SJeff Kirsher {
7711adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7712adfc5217SJeff Kirsher 
7713adfc5217SJeff Kirsher 	if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
7714adfc5217SJeff Kirsher 		((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
7715adfc5217SJeff Kirsher 		return -EINVAL;
7716adfc5217SJeff Kirsher 
7717adfc5217SJeff Kirsher 	dev->mtu = new_mtu;
7718adfc5217SJeff Kirsher 	return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
7719adfc5217SJeff Kirsher }
7720adfc5217SJeff Kirsher 
7721adfc5217SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
7722adfc5217SJeff Kirsher static void
7723adfc5217SJeff Kirsher poll_bnx2(struct net_device *dev)
7724adfc5217SJeff Kirsher {
7725adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
7726adfc5217SJeff Kirsher 	int i;
7727adfc5217SJeff Kirsher 
7728adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
7729adfc5217SJeff Kirsher 		struct bnx2_irq *irq = &bp->irq_tbl[i];
7730adfc5217SJeff Kirsher 
7731adfc5217SJeff Kirsher 		disable_irq(irq->vector);
7732adfc5217SJeff Kirsher 		irq->handler(irq->vector, &bp->bnx2_napi[i]);
7733adfc5217SJeff Kirsher 		enable_irq(irq->vector);
7734adfc5217SJeff Kirsher 	}
7735adfc5217SJeff Kirsher }
7736adfc5217SJeff Kirsher #endif
7737adfc5217SJeff Kirsher 
7738adfc5217SJeff Kirsher static void __devinit
7739adfc5217SJeff Kirsher bnx2_get_5709_media(struct bnx2 *bp)
7740adfc5217SJeff Kirsher {
7741adfc5217SJeff Kirsher 	u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
7742adfc5217SJeff Kirsher 	u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
7743adfc5217SJeff Kirsher 	u32 strap;
7744adfc5217SJeff Kirsher 
7745adfc5217SJeff Kirsher 	if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
7746adfc5217SJeff Kirsher 		return;
7747adfc5217SJeff Kirsher 	else if (bond_id == BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S) {
7748adfc5217SJeff Kirsher 		bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
7749adfc5217SJeff Kirsher 		return;
7750adfc5217SJeff Kirsher 	}
7751adfc5217SJeff Kirsher 
7752adfc5217SJeff Kirsher 	if (val & BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
7753adfc5217SJeff Kirsher 		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
7754adfc5217SJeff Kirsher 	else
7755adfc5217SJeff Kirsher 		strap = (val & BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
7756adfc5217SJeff Kirsher 
7757adfc5217SJeff Kirsher 	if (PCI_FUNC(bp->pdev->devfn) == 0) {
7758adfc5217SJeff Kirsher 		switch (strap) {
7759adfc5217SJeff Kirsher 		case 0x4:
7760adfc5217SJeff Kirsher 		case 0x5:
7761adfc5217SJeff Kirsher 		case 0x6:
7762adfc5217SJeff Kirsher 			bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
7763adfc5217SJeff Kirsher 			return;
7764adfc5217SJeff Kirsher 		}
7765adfc5217SJeff Kirsher 	} else {
7766adfc5217SJeff Kirsher 		switch (strap) {
7767adfc5217SJeff Kirsher 		case 0x1:
7768adfc5217SJeff Kirsher 		case 0x2:
7769adfc5217SJeff Kirsher 		case 0x4:
7770adfc5217SJeff Kirsher 			bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
7771adfc5217SJeff Kirsher 			return;
7772adfc5217SJeff Kirsher 		}
7773adfc5217SJeff Kirsher 	}
7774adfc5217SJeff Kirsher }
7775adfc5217SJeff Kirsher 
7776adfc5217SJeff Kirsher static void __devinit
7777adfc5217SJeff Kirsher bnx2_get_pci_speed(struct bnx2 *bp)
7778adfc5217SJeff Kirsher {
7779adfc5217SJeff Kirsher 	u32 reg;
7780adfc5217SJeff Kirsher 
7781adfc5217SJeff Kirsher 	reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
7782adfc5217SJeff Kirsher 	if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
7783adfc5217SJeff Kirsher 		u32 clkreg;
7784adfc5217SJeff Kirsher 
7785adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_PCIX;
7786adfc5217SJeff Kirsher 
7787adfc5217SJeff Kirsher 		clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
7788adfc5217SJeff Kirsher 
7789adfc5217SJeff Kirsher 		clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
7790adfc5217SJeff Kirsher 		switch (clkreg) {
7791adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
7792adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 133;
7793adfc5217SJeff Kirsher 			break;
7794adfc5217SJeff Kirsher 
7795adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
7796adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 100;
7797adfc5217SJeff Kirsher 			break;
7798adfc5217SJeff Kirsher 
7799adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
7800adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
7801adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 66;
7802adfc5217SJeff Kirsher 			break;
7803adfc5217SJeff Kirsher 
7804adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
7805adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
7806adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 50;
7807adfc5217SJeff Kirsher 			break;
7808adfc5217SJeff Kirsher 
7809adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
7810adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
7811adfc5217SJeff Kirsher 		case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
7812adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 33;
7813adfc5217SJeff Kirsher 			break;
7814adfc5217SJeff Kirsher 		}
7815adfc5217SJeff Kirsher 	}
7816adfc5217SJeff Kirsher 	else {
7817adfc5217SJeff Kirsher 		if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
7818adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 66;
7819adfc5217SJeff Kirsher 		else
7820adfc5217SJeff Kirsher 			bp->bus_speed_mhz = 33;
7821adfc5217SJeff Kirsher 	}
7822adfc5217SJeff Kirsher 
7823adfc5217SJeff Kirsher 	if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
7824adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_PCI_32BIT;
7825adfc5217SJeff Kirsher 
7826adfc5217SJeff Kirsher }
7827adfc5217SJeff Kirsher 
7828adfc5217SJeff Kirsher static void __devinit
7829adfc5217SJeff Kirsher bnx2_read_vpd_fw_ver(struct bnx2 *bp)
7830adfc5217SJeff Kirsher {
7831adfc5217SJeff Kirsher 	int rc, i, j;
7832adfc5217SJeff Kirsher 	u8 *data;
7833adfc5217SJeff Kirsher 	unsigned int block_end, rosize, len;
7834adfc5217SJeff Kirsher 
7835adfc5217SJeff Kirsher #define BNX2_VPD_NVRAM_OFFSET	0x300
7836adfc5217SJeff Kirsher #define BNX2_VPD_LEN		128
7837adfc5217SJeff Kirsher #define BNX2_MAX_VER_SLEN	30
7838adfc5217SJeff Kirsher 
7839adfc5217SJeff Kirsher 	data = kmalloc(256, GFP_KERNEL);
7840adfc5217SJeff Kirsher 	if (!data)
7841adfc5217SJeff Kirsher 		return;
7842adfc5217SJeff Kirsher 
7843adfc5217SJeff Kirsher 	rc = bnx2_nvram_read(bp, BNX2_VPD_NVRAM_OFFSET, data + BNX2_VPD_LEN,
7844adfc5217SJeff Kirsher 			     BNX2_VPD_LEN);
7845adfc5217SJeff Kirsher 	if (rc)
7846adfc5217SJeff Kirsher 		goto vpd_done;
7847adfc5217SJeff Kirsher 
7848adfc5217SJeff Kirsher 	for (i = 0; i < BNX2_VPD_LEN; i += 4) {
7849adfc5217SJeff Kirsher 		data[i] = data[i + BNX2_VPD_LEN + 3];
7850adfc5217SJeff Kirsher 		data[i + 1] = data[i + BNX2_VPD_LEN + 2];
7851adfc5217SJeff Kirsher 		data[i + 2] = data[i + BNX2_VPD_LEN + 1];
7852adfc5217SJeff Kirsher 		data[i + 3] = data[i + BNX2_VPD_LEN];
7853adfc5217SJeff Kirsher 	}
7854adfc5217SJeff Kirsher 
7855adfc5217SJeff Kirsher 	i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA);
7856adfc5217SJeff Kirsher 	if (i < 0)
7857adfc5217SJeff Kirsher 		goto vpd_done;
7858adfc5217SJeff Kirsher 
7859adfc5217SJeff Kirsher 	rosize = pci_vpd_lrdt_size(&data[i]);
7860adfc5217SJeff Kirsher 	i += PCI_VPD_LRDT_TAG_SIZE;
7861adfc5217SJeff Kirsher 	block_end = i + rosize;
7862adfc5217SJeff Kirsher 
7863adfc5217SJeff Kirsher 	if (block_end > BNX2_VPD_LEN)
7864adfc5217SJeff Kirsher 		goto vpd_done;
7865adfc5217SJeff Kirsher 
7866adfc5217SJeff Kirsher 	j = pci_vpd_find_info_keyword(data, i, rosize,
7867adfc5217SJeff Kirsher 				      PCI_VPD_RO_KEYWORD_MFR_ID);
7868adfc5217SJeff Kirsher 	if (j < 0)
7869adfc5217SJeff Kirsher 		goto vpd_done;
7870adfc5217SJeff Kirsher 
7871adfc5217SJeff Kirsher 	len = pci_vpd_info_field_size(&data[j]);
7872adfc5217SJeff Kirsher 
7873adfc5217SJeff Kirsher 	j += PCI_VPD_INFO_FLD_HDR_SIZE;
7874adfc5217SJeff Kirsher 	if (j + len > block_end || len != 4 ||
7875adfc5217SJeff Kirsher 	    memcmp(&data[j], "1028", 4))
7876adfc5217SJeff Kirsher 		goto vpd_done;
7877adfc5217SJeff Kirsher 
7878adfc5217SJeff Kirsher 	j = pci_vpd_find_info_keyword(data, i, rosize,
7879adfc5217SJeff Kirsher 				      PCI_VPD_RO_KEYWORD_VENDOR0);
7880adfc5217SJeff Kirsher 	if (j < 0)
7881adfc5217SJeff Kirsher 		goto vpd_done;
7882adfc5217SJeff Kirsher 
7883adfc5217SJeff Kirsher 	len = pci_vpd_info_field_size(&data[j]);
7884adfc5217SJeff Kirsher 
7885adfc5217SJeff Kirsher 	j += PCI_VPD_INFO_FLD_HDR_SIZE;
7886adfc5217SJeff Kirsher 	if (j + len > block_end || len > BNX2_MAX_VER_SLEN)
7887adfc5217SJeff Kirsher 		goto vpd_done;
7888adfc5217SJeff Kirsher 
7889adfc5217SJeff Kirsher 	memcpy(bp->fw_version, &data[j], len);
7890adfc5217SJeff Kirsher 	bp->fw_version[len] = ' ';
7891adfc5217SJeff Kirsher 
7892adfc5217SJeff Kirsher vpd_done:
7893adfc5217SJeff Kirsher 	kfree(data);
7894adfc5217SJeff Kirsher }
7895adfc5217SJeff Kirsher 
7896adfc5217SJeff Kirsher static int __devinit
7897adfc5217SJeff Kirsher bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
7898adfc5217SJeff Kirsher {
7899adfc5217SJeff Kirsher 	struct bnx2 *bp;
7900adfc5217SJeff Kirsher 	unsigned long mem_len;
7901adfc5217SJeff Kirsher 	int rc, i, j;
7902adfc5217SJeff Kirsher 	u32 reg;
7903adfc5217SJeff Kirsher 	u64 dma_mask, persist_dma_mask;
7904adfc5217SJeff Kirsher 	int err;
7905adfc5217SJeff Kirsher 
7906adfc5217SJeff Kirsher 	SET_NETDEV_DEV(dev, &pdev->dev);
7907adfc5217SJeff Kirsher 	bp = netdev_priv(dev);
7908adfc5217SJeff Kirsher 
7909adfc5217SJeff Kirsher 	bp->flags = 0;
7910adfc5217SJeff Kirsher 	bp->phy_flags = 0;
7911adfc5217SJeff Kirsher 
7912adfc5217SJeff Kirsher 	bp->temp_stats_blk =
7913adfc5217SJeff Kirsher 		kzalloc(sizeof(struct statistics_block), GFP_KERNEL);
7914adfc5217SJeff Kirsher 
7915adfc5217SJeff Kirsher 	if (bp->temp_stats_blk == NULL) {
7916adfc5217SJeff Kirsher 		rc = -ENOMEM;
7917adfc5217SJeff Kirsher 		goto err_out;
7918adfc5217SJeff Kirsher 	}
7919adfc5217SJeff Kirsher 
7920adfc5217SJeff Kirsher 	/* enable device (incl. PCI PM wakeup), and bus-mastering */
7921adfc5217SJeff Kirsher 	rc = pci_enable_device(pdev);
7922adfc5217SJeff Kirsher 	if (rc) {
7923adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
7924adfc5217SJeff Kirsher 		goto err_out;
7925adfc5217SJeff Kirsher 	}
7926adfc5217SJeff Kirsher 
7927adfc5217SJeff Kirsher 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
7928adfc5217SJeff Kirsher 		dev_err(&pdev->dev,
7929adfc5217SJeff Kirsher 			"Cannot find PCI device base address, aborting\n");
7930adfc5217SJeff Kirsher 		rc = -ENODEV;
7931adfc5217SJeff Kirsher 		goto err_out_disable;
7932adfc5217SJeff Kirsher 	}
7933adfc5217SJeff Kirsher 
7934adfc5217SJeff Kirsher 	rc = pci_request_regions(pdev, DRV_MODULE_NAME);
7935adfc5217SJeff Kirsher 	if (rc) {
7936adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n");
7937adfc5217SJeff Kirsher 		goto err_out_disable;
7938adfc5217SJeff Kirsher 	}
7939adfc5217SJeff Kirsher 
7940adfc5217SJeff Kirsher 	pci_set_master(pdev);
7941adfc5217SJeff Kirsher 
7942adfc5217SJeff Kirsher 	bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
7943adfc5217SJeff Kirsher 	if (bp->pm_cap == 0) {
7944adfc5217SJeff Kirsher 		dev_err(&pdev->dev,
7945adfc5217SJeff Kirsher 			"Cannot find power management capability, aborting\n");
7946adfc5217SJeff Kirsher 		rc = -EIO;
7947adfc5217SJeff Kirsher 		goto err_out_release;
7948adfc5217SJeff Kirsher 	}
7949adfc5217SJeff Kirsher 
7950adfc5217SJeff Kirsher 	bp->dev = dev;
7951adfc5217SJeff Kirsher 	bp->pdev = pdev;
7952adfc5217SJeff Kirsher 
7953adfc5217SJeff Kirsher 	spin_lock_init(&bp->phy_lock);
7954adfc5217SJeff Kirsher 	spin_lock_init(&bp->indirect_lock);
7955adfc5217SJeff Kirsher #ifdef BCM_CNIC
7956adfc5217SJeff Kirsher 	mutex_init(&bp->cnic_lock);
7957adfc5217SJeff Kirsher #endif
7958adfc5217SJeff Kirsher 	INIT_WORK(&bp->reset_task, bnx2_reset_task);
7959adfc5217SJeff Kirsher 
7960adfc5217SJeff Kirsher 	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
7961adfc5217SJeff Kirsher 	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS + 1);
7962adfc5217SJeff Kirsher 	dev->mem_end = dev->mem_start + mem_len;
7963adfc5217SJeff Kirsher 	dev->irq = pdev->irq;
7964adfc5217SJeff Kirsher 
7965adfc5217SJeff Kirsher 	bp->regview = ioremap_nocache(dev->base_addr, mem_len);
7966adfc5217SJeff Kirsher 
7967adfc5217SJeff Kirsher 	if (!bp->regview) {
7968adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "Cannot map register space, aborting\n");
7969adfc5217SJeff Kirsher 		rc = -ENOMEM;
7970adfc5217SJeff Kirsher 		goto err_out_release;
7971adfc5217SJeff Kirsher 	}
7972adfc5217SJeff Kirsher 
7973adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, PCI_D0);
7974adfc5217SJeff Kirsher 
7975adfc5217SJeff Kirsher 	/* Configure byte swap and enable write to the reg_window registers.
7976adfc5217SJeff Kirsher 	 * Rely on CPU to do target byte swapping on big endian systems
7977adfc5217SJeff Kirsher 	 * The chip's target access swapping will not swap all accesses
7978adfc5217SJeff Kirsher 	 */
7979adfc5217SJeff Kirsher 	REG_WR(bp, BNX2_PCICFG_MISC_CONFIG,
7980adfc5217SJeff Kirsher 		   BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
7981adfc5217SJeff Kirsher 		   BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
7982adfc5217SJeff Kirsher 
7983adfc5217SJeff Kirsher 	bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
7984adfc5217SJeff Kirsher 
7985adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
7986adfc5217SJeff Kirsher 		if (!pci_is_pcie(pdev)) {
7987adfc5217SJeff Kirsher 			dev_err(&pdev->dev, "Not PCIE, aborting\n");
7988adfc5217SJeff Kirsher 			rc = -EIO;
7989adfc5217SJeff Kirsher 			goto err_out_unmap;
7990adfc5217SJeff Kirsher 		}
7991adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_PCIE;
7992adfc5217SJeff Kirsher 		if (CHIP_REV(bp) == CHIP_REV_Ax)
7993adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
7994adfc5217SJeff Kirsher 
7995adfc5217SJeff Kirsher 		/* AER (Advanced Error Reporting) hooks */
7996adfc5217SJeff Kirsher 		err = pci_enable_pcie_error_reporting(pdev);
7997adfc5217SJeff Kirsher 		if (!err)
7998adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_AER_ENABLED;
7999adfc5217SJeff Kirsher 
8000adfc5217SJeff Kirsher 	} else {
8001adfc5217SJeff Kirsher 		bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
8002adfc5217SJeff Kirsher 		if (bp->pcix_cap == 0) {
8003adfc5217SJeff Kirsher 			dev_err(&pdev->dev,
8004adfc5217SJeff Kirsher 				"Cannot find PCIX capability, aborting\n");
8005adfc5217SJeff Kirsher 			rc = -EIO;
8006adfc5217SJeff Kirsher 			goto err_out_unmap;
8007adfc5217SJeff Kirsher 		}
8008adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_BROKEN_STATS;
8009adfc5217SJeff Kirsher 	}
8010adfc5217SJeff Kirsher 
8011adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) {
8012adfc5217SJeff Kirsher 		if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
8013adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_MSIX_CAP;
8014adfc5217SJeff Kirsher 	}
8015adfc5217SJeff Kirsher 
8016adfc5217SJeff Kirsher 	if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
8017adfc5217SJeff Kirsher 		if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
8018adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_MSI_CAP;
8019adfc5217SJeff Kirsher 	}
8020adfc5217SJeff Kirsher 
8021adfc5217SJeff Kirsher 	/* 5708 cannot support DMA addresses > 40-bit.  */
8022adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5708)
8023adfc5217SJeff Kirsher 		persist_dma_mask = dma_mask = DMA_BIT_MASK(40);
8024adfc5217SJeff Kirsher 	else
8025adfc5217SJeff Kirsher 		persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
8026adfc5217SJeff Kirsher 
8027adfc5217SJeff Kirsher 	/* Configure DMA attributes. */
8028adfc5217SJeff Kirsher 	if (pci_set_dma_mask(pdev, dma_mask) == 0) {
8029adfc5217SJeff Kirsher 		dev->features |= NETIF_F_HIGHDMA;
8030adfc5217SJeff Kirsher 		rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
8031adfc5217SJeff Kirsher 		if (rc) {
8032adfc5217SJeff Kirsher 			dev_err(&pdev->dev,
8033adfc5217SJeff Kirsher 				"pci_set_consistent_dma_mask failed, aborting\n");
8034adfc5217SJeff Kirsher 			goto err_out_unmap;
8035adfc5217SJeff Kirsher 		}
8036adfc5217SJeff Kirsher 	} else if ((rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
8037adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "System does not support DMA, aborting\n");
8038adfc5217SJeff Kirsher 		goto err_out_unmap;
8039adfc5217SJeff Kirsher 	}
8040adfc5217SJeff Kirsher 
8041adfc5217SJeff Kirsher 	if (!(bp->flags & BNX2_FLAG_PCIE))
8042adfc5217SJeff Kirsher 		bnx2_get_pci_speed(bp);
8043adfc5217SJeff Kirsher 
8044adfc5217SJeff Kirsher 	/* 5706A0 may falsely detect SERR and PERR. */
8045adfc5217SJeff Kirsher 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
8046adfc5217SJeff Kirsher 		reg = REG_RD(bp, PCI_COMMAND);
8047adfc5217SJeff Kirsher 		reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
8048adfc5217SJeff Kirsher 		REG_WR(bp, PCI_COMMAND, reg);
8049adfc5217SJeff Kirsher 	}
8050adfc5217SJeff Kirsher 	else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
8051adfc5217SJeff Kirsher 		!(bp->flags & BNX2_FLAG_PCIX)) {
8052adfc5217SJeff Kirsher 
8053adfc5217SJeff Kirsher 		dev_err(&pdev->dev,
8054adfc5217SJeff Kirsher 			"5706 A1 can only be used in a PCIX bus, aborting\n");
8055adfc5217SJeff Kirsher 		goto err_out_unmap;
8056adfc5217SJeff Kirsher 	}
8057adfc5217SJeff Kirsher 
8058adfc5217SJeff Kirsher 	bnx2_init_nvram(bp);
8059adfc5217SJeff Kirsher 
8060adfc5217SJeff Kirsher 	reg = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_SIGNATURE);
8061adfc5217SJeff Kirsher 
8062adfc5217SJeff Kirsher 	if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
8063adfc5217SJeff Kirsher 	    BNX2_SHM_HDR_SIGNATURE_SIG) {
8064adfc5217SJeff Kirsher 		u32 off = PCI_FUNC(pdev->devfn) << 2;
8065adfc5217SJeff Kirsher 
8066adfc5217SJeff Kirsher 		bp->shmem_base = bnx2_reg_rd_ind(bp, BNX2_SHM_HDR_ADDR_0 + off);
8067adfc5217SJeff Kirsher 	} else
8068adfc5217SJeff Kirsher 		bp->shmem_base = HOST_VIEW_SHMEM_BASE;
8069adfc5217SJeff Kirsher 
8070adfc5217SJeff Kirsher 	/* Get the permanent MAC address.  First we need to make sure the
8071adfc5217SJeff Kirsher 	 * firmware is actually running.
8072adfc5217SJeff Kirsher 	 */
8073adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_SIGNATURE);
8074adfc5217SJeff Kirsher 
8075adfc5217SJeff Kirsher 	if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
8076adfc5217SJeff Kirsher 	    BNX2_DEV_INFO_SIGNATURE_MAGIC) {
8077adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "Firmware not running, aborting\n");
8078adfc5217SJeff Kirsher 		rc = -ENODEV;
8079adfc5217SJeff Kirsher 		goto err_out_unmap;
8080adfc5217SJeff Kirsher 	}
8081adfc5217SJeff Kirsher 
8082adfc5217SJeff Kirsher 	bnx2_read_vpd_fw_ver(bp);
8083adfc5217SJeff Kirsher 
8084adfc5217SJeff Kirsher 	j = strlen(bp->fw_version);
8085adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV);
8086adfc5217SJeff Kirsher 	for (i = 0; i < 3 && j < 24; i++) {
8087adfc5217SJeff Kirsher 		u8 num, k, skip0;
8088adfc5217SJeff Kirsher 
8089adfc5217SJeff Kirsher 		if (i == 0) {
8090adfc5217SJeff Kirsher 			bp->fw_version[j++] = 'b';
8091adfc5217SJeff Kirsher 			bp->fw_version[j++] = 'c';
8092adfc5217SJeff Kirsher 			bp->fw_version[j++] = ' ';
8093adfc5217SJeff Kirsher 		}
8094adfc5217SJeff Kirsher 		num = (u8) (reg >> (24 - (i * 8)));
8095adfc5217SJeff Kirsher 		for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
8096adfc5217SJeff Kirsher 			if (num >= k || !skip0 || k == 1) {
8097adfc5217SJeff Kirsher 				bp->fw_version[j++] = (num / k) + '0';
8098adfc5217SJeff Kirsher 				skip0 = 0;
8099adfc5217SJeff Kirsher 			}
8100adfc5217SJeff Kirsher 		}
8101adfc5217SJeff Kirsher 		if (i != 2)
8102adfc5217SJeff Kirsher 			bp->fw_version[j++] = '.';
8103adfc5217SJeff Kirsher 	}
8104adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE);
8105adfc5217SJeff Kirsher 	if (reg & BNX2_PORT_FEATURE_WOL_ENABLED)
8106adfc5217SJeff Kirsher 		bp->wol = 1;
8107adfc5217SJeff Kirsher 
8108adfc5217SJeff Kirsher 	if (reg & BNX2_PORT_FEATURE_ASF_ENABLED) {
8109adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_ASF_ENABLE;
8110adfc5217SJeff Kirsher 
8111adfc5217SJeff Kirsher 		for (i = 0; i < 30; i++) {
8112adfc5217SJeff Kirsher 			reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
8113adfc5217SJeff Kirsher 			if (reg & BNX2_CONDITION_MFW_RUN_MASK)
8114adfc5217SJeff Kirsher 				break;
8115adfc5217SJeff Kirsher 			msleep(10);
8116adfc5217SJeff Kirsher 		}
8117adfc5217SJeff Kirsher 	}
8118adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
8119adfc5217SJeff Kirsher 	reg &= BNX2_CONDITION_MFW_RUN_MASK;
8120adfc5217SJeff Kirsher 	if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
8121adfc5217SJeff Kirsher 	    reg != BNX2_CONDITION_MFW_RUN_NONE) {
8122adfc5217SJeff Kirsher 		u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR);
8123adfc5217SJeff Kirsher 
8124adfc5217SJeff Kirsher 		if (j < 32)
8125adfc5217SJeff Kirsher 			bp->fw_version[j++] = ' ';
8126adfc5217SJeff Kirsher 		for (i = 0; i < 3 && j < 28; i++) {
8127adfc5217SJeff Kirsher 			reg = bnx2_reg_rd_ind(bp, addr + i * 4);
8128adfc5217SJeff Kirsher 			reg = be32_to_cpu(reg);
8129adfc5217SJeff Kirsher 			memcpy(&bp->fw_version[j], &reg, 4);
8130adfc5217SJeff Kirsher 			j += 4;
8131adfc5217SJeff Kirsher 		}
8132adfc5217SJeff Kirsher 	}
8133adfc5217SJeff Kirsher 
8134adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_UPPER);
8135adfc5217SJeff Kirsher 	bp->mac_addr[0] = (u8) (reg >> 8);
8136adfc5217SJeff Kirsher 	bp->mac_addr[1] = (u8) reg;
8137adfc5217SJeff Kirsher 
8138adfc5217SJeff Kirsher 	reg = bnx2_shmem_rd(bp, BNX2_PORT_HW_CFG_MAC_LOWER);
8139adfc5217SJeff Kirsher 	bp->mac_addr[2] = (u8) (reg >> 24);
8140adfc5217SJeff Kirsher 	bp->mac_addr[3] = (u8) (reg >> 16);
8141adfc5217SJeff Kirsher 	bp->mac_addr[4] = (u8) (reg >> 8);
8142adfc5217SJeff Kirsher 	bp->mac_addr[5] = (u8) reg;
8143adfc5217SJeff Kirsher 
8144adfc5217SJeff Kirsher 	bp->tx_ring_size = MAX_TX_DESC_CNT;
8145adfc5217SJeff Kirsher 	bnx2_set_rx_ring_size(bp, 255);
8146adfc5217SJeff Kirsher 
8147adfc5217SJeff Kirsher 	bp->tx_quick_cons_trip_int = 2;
8148adfc5217SJeff Kirsher 	bp->tx_quick_cons_trip = 20;
8149adfc5217SJeff Kirsher 	bp->tx_ticks_int = 18;
8150adfc5217SJeff Kirsher 	bp->tx_ticks = 80;
8151adfc5217SJeff Kirsher 
8152adfc5217SJeff Kirsher 	bp->rx_quick_cons_trip_int = 2;
8153adfc5217SJeff Kirsher 	bp->rx_quick_cons_trip = 12;
8154adfc5217SJeff Kirsher 	bp->rx_ticks_int = 18;
8155adfc5217SJeff Kirsher 	bp->rx_ticks = 18;
8156adfc5217SJeff Kirsher 
8157adfc5217SJeff Kirsher 	bp->stats_ticks = USEC_PER_SEC & BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
8158adfc5217SJeff Kirsher 
8159adfc5217SJeff Kirsher 	bp->current_interval = BNX2_TIMER_INTERVAL;
8160adfc5217SJeff Kirsher 
8161adfc5217SJeff Kirsher 	bp->phy_addr = 1;
8162adfc5217SJeff Kirsher 
8163adfc5217SJeff Kirsher 	/* Disable WOL support if we are running on a SERDES chip. */
8164adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
8165adfc5217SJeff Kirsher 		bnx2_get_5709_media(bp);
8166adfc5217SJeff Kirsher 	else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
8167adfc5217SJeff Kirsher 		bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
8168adfc5217SJeff Kirsher 
8169adfc5217SJeff Kirsher 	bp->phy_port = PORT_TP;
8170adfc5217SJeff Kirsher 	if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
8171adfc5217SJeff Kirsher 		bp->phy_port = PORT_FIBRE;
8172adfc5217SJeff Kirsher 		reg = bnx2_shmem_rd(bp, BNX2_SHARED_HW_CFG_CONFIG);
8173adfc5217SJeff Kirsher 		if (!(reg & BNX2_SHARED_HW_CFG_GIG_LINK_ON_VAUX)) {
8174adfc5217SJeff Kirsher 			bp->flags |= BNX2_FLAG_NO_WOL;
8175adfc5217SJeff Kirsher 			bp->wol = 0;
8176adfc5217SJeff Kirsher 		}
8177adfc5217SJeff Kirsher 		if (CHIP_NUM(bp) == CHIP_NUM_5706) {
8178adfc5217SJeff Kirsher 			/* Don't do parallel detect on this board because of
8179adfc5217SJeff Kirsher 			 * some board problems.  The link will not go down
8180adfc5217SJeff Kirsher 			 * if we do parallel detect.
8181adfc5217SJeff Kirsher 			 */
8182adfc5217SJeff Kirsher 			if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
8183adfc5217SJeff Kirsher 			    pdev->subsystem_device == 0x310c)
8184adfc5217SJeff Kirsher 				bp->phy_flags |= BNX2_PHY_FLAG_NO_PARALLEL;
8185adfc5217SJeff Kirsher 		} else {
8186adfc5217SJeff Kirsher 			bp->phy_addr = 2;
8187adfc5217SJeff Kirsher 			if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
8188adfc5217SJeff Kirsher 				bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE;
8189adfc5217SJeff Kirsher 		}
8190adfc5217SJeff Kirsher 	} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
8191adfc5217SJeff Kirsher 		   CHIP_NUM(bp) == CHIP_NUM_5708)
8192adfc5217SJeff Kirsher 		bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX;
8193adfc5217SJeff Kirsher 	else if (CHIP_NUM(bp) == CHIP_NUM_5709 &&
8194adfc5217SJeff Kirsher 		 (CHIP_REV(bp) == CHIP_REV_Ax ||
8195adfc5217SJeff Kirsher 		  CHIP_REV(bp) == CHIP_REV_Bx))
8196adfc5217SJeff Kirsher 		bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC;
8197adfc5217SJeff Kirsher 
8198adfc5217SJeff Kirsher 	bnx2_init_fw_cap(bp);
8199adfc5217SJeff Kirsher 
8200adfc5217SJeff Kirsher 	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
8201adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
8202adfc5217SJeff Kirsher 	    (CHIP_ID(bp) == CHIP_ID_5708_B1) ||
8203adfc5217SJeff Kirsher 	    !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
8204adfc5217SJeff Kirsher 		bp->flags |= BNX2_FLAG_NO_WOL;
8205adfc5217SJeff Kirsher 		bp->wol = 0;
8206adfc5217SJeff Kirsher 	}
8207adfc5217SJeff Kirsher 
8208adfc5217SJeff Kirsher 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
8209adfc5217SJeff Kirsher 		bp->tx_quick_cons_trip_int =
8210adfc5217SJeff Kirsher 			bp->tx_quick_cons_trip;
8211adfc5217SJeff Kirsher 		bp->tx_ticks_int = bp->tx_ticks;
8212adfc5217SJeff Kirsher 		bp->rx_quick_cons_trip_int =
8213adfc5217SJeff Kirsher 			bp->rx_quick_cons_trip;
8214adfc5217SJeff Kirsher 		bp->rx_ticks_int = bp->rx_ticks;
8215adfc5217SJeff Kirsher 		bp->comp_prod_trip_int = bp->comp_prod_trip;
8216adfc5217SJeff Kirsher 		bp->com_ticks_int = bp->com_ticks;
8217adfc5217SJeff Kirsher 		bp->cmd_ticks_int = bp->cmd_ticks;
8218adfc5217SJeff Kirsher 	}
8219adfc5217SJeff Kirsher 
8220adfc5217SJeff Kirsher 	/* Disable MSI on 5706 if AMD 8132 bridge is found.
8221adfc5217SJeff Kirsher 	 *
8222adfc5217SJeff Kirsher 	 * MSI is defined to be 32-bit write.  The 5706 does 64-bit MSI writes
8223adfc5217SJeff Kirsher 	 * with byte enables disabled on the unused 32-bit word.  This is legal
8224adfc5217SJeff Kirsher 	 * but causes problems on the AMD 8132 which will eventually stop
8225adfc5217SJeff Kirsher 	 * responding after a while.
8226adfc5217SJeff Kirsher 	 *
8227adfc5217SJeff Kirsher 	 * AMD believes this incompatibility is unique to the 5706, and
8228adfc5217SJeff Kirsher 	 * prefers to locally disable MSI rather than globally disabling it.
8229adfc5217SJeff Kirsher 	 */
8230adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
8231adfc5217SJeff Kirsher 		struct pci_dev *amd_8132 = NULL;
8232adfc5217SJeff Kirsher 
8233adfc5217SJeff Kirsher 		while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
8234adfc5217SJeff Kirsher 						  PCI_DEVICE_ID_AMD_8132_BRIDGE,
8235adfc5217SJeff Kirsher 						  amd_8132))) {
8236adfc5217SJeff Kirsher 
8237adfc5217SJeff Kirsher 			if (amd_8132->revision >= 0x10 &&
8238adfc5217SJeff Kirsher 			    amd_8132->revision <= 0x13) {
8239adfc5217SJeff Kirsher 				disable_msi = 1;
8240adfc5217SJeff Kirsher 				pci_dev_put(amd_8132);
8241adfc5217SJeff Kirsher 				break;
8242adfc5217SJeff Kirsher 			}
8243adfc5217SJeff Kirsher 		}
8244adfc5217SJeff Kirsher 	}
8245adfc5217SJeff Kirsher 
8246adfc5217SJeff Kirsher 	bnx2_set_default_link(bp);
8247adfc5217SJeff Kirsher 	bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
8248adfc5217SJeff Kirsher 
8249adfc5217SJeff Kirsher 	init_timer(&bp->timer);
8250adfc5217SJeff Kirsher 	bp->timer.expires = RUN_AT(BNX2_TIMER_INTERVAL);
8251adfc5217SJeff Kirsher 	bp->timer.data = (unsigned long) bp;
8252adfc5217SJeff Kirsher 	bp->timer.function = bnx2_timer;
8253adfc5217SJeff Kirsher 
8254adfc5217SJeff Kirsher #ifdef BCM_CNIC
8255adfc5217SJeff Kirsher 	if (bnx2_shmem_rd(bp, BNX2_ISCSI_INITIATOR) & BNX2_ISCSI_INITIATOR_EN)
8256adfc5217SJeff Kirsher 		bp->cnic_eth_dev.max_iscsi_conn =
8257adfc5217SJeff Kirsher 			(bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
8258adfc5217SJeff Kirsher 			 BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
8259adfc5217SJeff Kirsher #endif
8260adfc5217SJeff Kirsher 	pci_save_state(pdev);
8261adfc5217SJeff Kirsher 
8262adfc5217SJeff Kirsher 	return 0;
8263adfc5217SJeff Kirsher 
8264adfc5217SJeff Kirsher err_out_unmap:
8265adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
8266adfc5217SJeff Kirsher 		pci_disable_pcie_error_reporting(pdev);
8267adfc5217SJeff Kirsher 		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
8268adfc5217SJeff Kirsher 	}
8269adfc5217SJeff Kirsher 
8270adfc5217SJeff Kirsher 	if (bp->regview) {
8271adfc5217SJeff Kirsher 		iounmap(bp->regview);
8272adfc5217SJeff Kirsher 		bp->regview = NULL;
8273adfc5217SJeff Kirsher 	}
8274adfc5217SJeff Kirsher 
8275adfc5217SJeff Kirsher err_out_release:
8276adfc5217SJeff Kirsher 	pci_release_regions(pdev);
8277adfc5217SJeff Kirsher 
8278adfc5217SJeff Kirsher err_out_disable:
8279adfc5217SJeff Kirsher 	pci_disable_device(pdev);
8280adfc5217SJeff Kirsher 	pci_set_drvdata(pdev, NULL);
8281adfc5217SJeff Kirsher 
8282adfc5217SJeff Kirsher err_out:
8283adfc5217SJeff Kirsher 	return rc;
8284adfc5217SJeff Kirsher }
8285adfc5217SJeff Kirsher 
8286adfc5217SJeff Kirsher static char * __devinit
8287adfc5217SJeff Kirsher bnx2_bus_string(struct bnx2 *bp, char *str)
8288adfc5217SJeff Kirsher {
8289adfc5217SJeff Kirsher 	char *s = str;
8290adfc5217SJeff Kirsher 
8291adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_PCIE) {
8292adfc5217SJeff Kirsher 		s += sprintf(s, "PCI Express");
8293adfc5217SJeff Kirsher 	} else {
8294adfc5217SJeff Kirsher 		s += sprintf(s, "PCI");
8295adfc5217SJeff Kirsher 		if (bp->flags & BNX2_FLAG_PCIX)
8296adfc5217SJeff Kirsher 			s += sprintf(s, "-X");
8297adfc5217SJeff Kirsher 		if (bp->flags & BNX2_FLAG_PCI_32BIT)
8298adfc5217SJeff Kirsher 			s += sprintf(s, " 32-bit");
8299adfc5217SJeff Kirsher 		else
8300adfc5217SJeff Kirsher 			s += sprintf(s, " 64-bit");
8301adfc5217SJeff Kirsher 		s += sprintf(s, " %dMHz", bp->bus_speed_mhz);
8302adfc5217SJeff Kirsher 	}
8303adfc5217SJeff Kirsher 	return str;
8304adfc5217SJeff Kirsher }
8305adfc5217SJeff Kirsher 
8306adfc5217SJeff Kirsher static void
8307adfc5217SJeff Kirsher bnx2_del_napi(struct bnx2 *bp)
8308adfc5217SJeff Kirsher {
8309adfc5217SJeff Kirsher 	int i;
8310adfc5217SJeff Kirsher 
8311adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++)
8312adfc5217SJeff Kirsher 		netif_napi_del(&bp->bnx2_napi[i].napi);
8313adfc5217SJeff Kirsher }
8314adfc5217SJeff Kirsher 
8315adfc5217SJeff Kirsher static void
8316adfc5217SJeff Kirsher bnx2_init_napi(struct bnx2 *bp)
8317adfc5217SJeff Kirsher {
8318adfc5217SJeff Kirsher 	int i;
8319adfc5217SJeff Kirsher 
8320adfc5217SJeff Kirsher 	for (i = 0; i < bp->irq_nvecs; i++) {
8321adfc5217SJeff Kirsher 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
8322adfc5217SJeff Kirsher 		int (*poll)(struct napi_struct *, int);
8323adfc5217SJeff Kirsher 
8324adfc5217SJeff Kirsher 		if (i == 0)
8325adfc5217SJeff Kirsher 			poll = bnx2_poll;
8326adfc5217SJeff Kirsher 		else
8327adfc5217SJeff Kirsher 			poll = bnx2_poll_msix;
8328adfc5217SJeff Kirsher 
8329adfc5217SJeff Kirsher 		netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64);
8330adfc5217SJeff Kirsher 		bnapi->bp = bp;
8331adfc5217SJeff Kirsher 	}
8332adfc5217SJeff Kirsher }
8333adfc5217SJeff Kirsher 
8334adfc5217SJeff Kirsher static const struct net_device_ops bnx2_netdev_ops = {
8335adfc5217SJeff Kirsher 	.ndo_open		= bnx2_open,
8336adfc5217SJeff Kirsher 	.ndo_start_xmit		= bnx2_start_xmit,
8337adfc5217SJeff Kirsher 	.ndo_stop		= bnx2_close,
8338adfc5217SJeff Kirsher 	.ndo_get_stats64	= bnx2_get_stats64,
8339adfc5217SJeff Kirsher 	.ndo_set_rx_mode	= bnx2_set_rx_mode,
8340adfc5217SJeff Kirsher 	.ndo_do_ioctl		= bnx2_ioctl,
8341adfc5217SJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
8342adfc5217SJeff Kirsher 	.ndo_set_mac_address	= bnx2_change_mac_addr,
8343adfc5217SJeff Kirsher 	.ndo_change_mtu		= bnx2_change_mtu,
8344adfc5217SJeff Kirsher 	.ndo_fix_features	= bnx2_fix_features,
8345adfc5217SJeff Kirsher 	.ndo_set_features	= bnx2_set_features,
8346adfc5217SJeff Kirsher 	.ndo_tx_timeout		= bnx2_tx_timeout,
8347adfc5217SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
8348adfc5217SJeff Kirsher 	.ndo_poll_controller	= poll_bnx2,
8349adfc5217SJeff Kirsher #endif
8350adfc5217SJeff Kirsher };
8351adfc5217SJeff Kirsher 
8352adfc5217SJeff Kirsher static int __devinit
8353adfc5217SJeff Kirsher bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
8354adfc5217SJeff Kirsher {
8355adfc5217SJeff Kirsher 	static int version_printed = 0;
8356adfc5217SJeff Kirsher 	struct net_device *dev = NULL;
8357adfc5217SJeff Kirsher 	struct bnx2 *bp;
8358adfc5217SJeff Kirsher 	int rc;
8359adfc5217SJeff Kirsher 	char str[40];
8360adfc5217SJeff Kirsher 
8361adfc5217SJeff Kirsher 	if (version_printed++ == 0)
8362adfc5217SJeff Kirsher 		pr_info("%s", version);
8363adfc5217SJeff Kirsher 
8364adfc5217SJeff Kirsher 	/* dev zeroed in init_etherdev */
8365adfc5217SJeff Kirsher 	dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS);
8366adfc5217SJeff Kirsher 
8367adfc5217SJeff Kirsher 	if (!dev)
8368adfc5217SJeff Kirsher 		return -ENOMEM;
8369adfc5217SJeff Kirsher 
8370adfc5217SJeff Kirsher 	rc = bnx2_init_board(pdev, dev);
8371adfc5217SJeff Kirsher 	if (rc < 0) {
8372adfc5217SJeff Kirsher 		free_netdev(dev);
8373adfc5217SJeff Kirsher 		return rc;
8374adfc5217SJeff Kirsher 	}
8375adfc5217SJeff Kirsher 
8376adfc5217SJeff Kirsher 	dev->netdev_ops = &bnx2_netdev_ops;
8377adfc5217SJeff Kirsher 	dev->watchdog_timeo = TX_TIMEOUT;
8378adfc5217SJeff Kirsher 	dev->ethtool_ops = &bnx2_ethtool_ops;
8379adfc5217SJeff Kirsher 
8380adfc5217SJeff Kirsher 	bp = netdev_priv(dev);
8381adfc5217SJeff Kirsher 
8382adfc5217SJeff Kirsher 	pci_set_drvdata(pdev, dev);
8383adfc5217SJeff Kirsher 
8384adfc5217SJeff Kirsher 	memcpy(dev->dev_addr, bp->mac_addr, 6);
8385adfc5217SJeff Kirsher 	memcpy(dev->perm_addr, bp->mac_addr, 6);
8386adfc5217SJeff Kirsher 
8387adfc5217SJeff Kirsher 	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
8388adfc5217SJeff Kirsher 		NETIF_F_TSO | NETIF_F_TSO_ECN |
8389adfc5217SJeff Kirsher 		NETIF_F_RXHASH | NETIF_F_RXCSUM;
8390adfc5217SJeff Kirsher 
8391adfc5217SJeff Kirsher 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
8392adfc5217SJeff Kirsher 		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
8393adfc5217SJeff Kirsher 
8394adfc5217SJeff Kirsher 	dev->vlan_features = dev->hw_features;
8395adfc5217SJeff Kirsher 	dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
8396adfc5217SJeff Kirsher 	dev->features |= dev->hw_features;
839701789349SJiri Pirko 	dev->priv_flags |= IFF_UNICAST_FLT;
8398adfc5217SJeff Kirsher 
8399adfc5217SJeff Kirsher 	if ((rc = register_netdev(dev))) {
8400adfc5217SJeff Kirsher 		dev_err(&pdev->dev, "Cannot register net device\n");
8401adfc5217SJeff Kirsher 		goto error;
8402adfc5217SJeff Kirsher 	}
8403adfc5217SJeff Kirsher 
8404adfc5217SJeff Kirsher 	netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, node addr %pM\n",
8405adfc5217SJeff Kirsher 		    board_info[ent->driver_data].name,
8406adfc5217SJeff Kirsher 		    ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
8407adfc5217SJeff Kirsher 		    ((CHIP_ID(bp) & 0x0ff0) >> 4),
8408adfc5217SJeff Kirsher 		    bnx2_bus_string(bp, str),
8409adfc5217SJeff Kirsher 		    dev->base_addr,
8410adfc5217SJeff Kirsher 		    bp->pdev->irq, dev->dev_addr);
8411adfc5217SJeff Kirsher 
8412adfc5217SJeff Kirsher 	return 0;
8413adfc5217SJeff Kirsher 
8414adfc5217SJeff Kirsher error:
8415adfc5217SJeff Kirsher 	if (bp->regview)
8416adfc5217SJeff Kirsher 		iounmap(bp->regview);
8417adfc5217SJeff Kirsher 	pci_release_regions(pdev);
8418adfc5217SJeff Kirsher 	pci_disable_device(pdev);
8419adfc5217SJeff Kirsher 	pci_set_drvdata(pdev, NULL);
8420adfc5217SJeff Kirsher 	free_netdev(dev);
8421adfc5217SJeff Kirsher 	return rc;
8422adfc5217SJeff Kirsher }
8423adfc5217SJeff Kirsher 
8424adfc5217SJeff Kirsher static void __devexit
8425adfc5217SJeff Kirsher bnx2_remove_one(struct pci_dev *pdev)
8426adfc5217SJeff Kirsher {
8427adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8428adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8429adfc5217SJeff Kirsher 
8430adfc5217SJeff Kirsher 	unregister_netdev(dev);
8431adfc5217SJeff Kirsher 
8432adfc5217SJeff Kirsher 	del_timer_sync(&bp->timer);
8433adfc5217SJeff Kirsher 	cancel_work_sync(&bp->reset_task);
8434adfc5217SJeff Kirsher 
8435adfc5217SJeff Kirsher 	if (bp->regview)
8436adfc5217SJeff Kirsher 		iounmap(bp->regview);
8437adfc5217SJeff Kirsher 
8438adfc5217SJeff Kirsher 	kfree(bp->temp_stats_blk);
8439adfc5217SJeff Kirsher 
8440adfc5217SJeff Kirsher 	if (bp->flags & BNX2_FLAG_AER_ENABLED) {
8441adfc5217SJeff Kirsher 		pci_disable_pcie_error_reporting(pdev);
8442adfc5217SJeff Kirsher 		bp->flags &= ~BNX2_FLAG_AER_ENABLED;
8443adfc5217SJeff Kirsher 	}
8444adfc5217SJeff Kirsher 
84457880b72eSfrançois romieu 	bnx2_release_firmware(bp);
84467880b72eSfrançois romieu 
8447adfc5217SJeff Kirsher 	free_netdev(dev);
8448adfc5217SJeff Kirsher 
8449adfc5217SJeff Kirsher 	pci_release_regions(pdev);
8450adfc5217SJeff Kirsher 	pci_disable_device(pdev);
8451adfc5217SJeff Kirsher 	pci_set_drvdata(pdev, NULL);
8452adfc5217SJeff Kirsher }
8453adfc5217SJeff Kirsher 
8454adfc5217SJeff Kirsher static int
8455adfc5217SJeff Kirsher bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
8456adfc5217SJeff Kirsher {
8457adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8458adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8459adfc5217SJeff Kirsher 
8460adfc5217SJeff Kirsher 	/* PCI register 4 needs to be saved whether netif_running() or not.
8461adfc5217SJeff Kirsher 	 * MSI address and data need to be saved if using MSI and
8462adfc5217SJeff Kirsher 	 * netif_running().
8463adfc5217SJeff Kirsher 	 */
8464adfc5217SJeff Kirsher 	pci_save_state(pdev);
8465adfc5217SJeff Kirsher 	if (!netif_running(dev))
8466adfc5217SJeff Kirsher 		return 0;
8467adfc5217SJeff Kirsher 
8468adfc5217SJeff Kirsher 	cancel_work_sync(&bp->reset_task);
8469adfc5217SJeff Kirsher 	bnx2_netif_stop(bp, true);
8470adfc5217SJeff Kirsher 	netif_device_detach(dev);
8471adfc5217SJeff Kirsher 	del_timer_sync(&bp->timer);
8472adfc5217SJeff Kirsher 	bnx2_shutdown_chip(bp);
8473adfc5217SJeff Kirsher 	bnx2_free_skbs(bp);
8474adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, pci_choose_state(pdev, state));
8475adfc5217SJeff Kirsher 	return 0;
8476adfc5217SJeff Kirsher }
8477adfc5217SJeff Kirsher 
8478adfc5217SJeff Kirsher static int
8479adfc5217SJeff Kirsher bnx2_resume(struct pci_dev *pdev)
8480adfc5217SJeff Kirsher {
8481adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8482adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8483adfc5217SJeff Kirsher 
8484adfc5217SJeff Kirsher 	pci_restore_state(pdev);
8485adfc5217SJeff Kirsher 	if (!netif_running(dev))
8486adfc5217SJeff Kirsher 		return 0;
8487adfc5217SJeff Kirsher 
8488adfc5217SJeff Kirsher 	bnx2_set_power_state(bp, PCI_D0);
8489adfc5217SJeff Kirsher 	netif_device_attach(dev);
8490adfc5217SJeff Kirsher 	bnx2_init_nic(bp, 1);
8491adfc5217SJeff Kirsher 	bnx2_netif_start(bp, true);
8492adfc5217SJeff Kirsher 	return 0;
8493adfc5217SJeff Kirsher }
8494adfc5217SJeff Kirsher 
8495adfc5217SJeff Kirsher /**
8496adfc5217SJeff Kirsher  * bnx2_io_error_detected - called when PCI error is detected
8497adfc5217SJeff Kirsher  * @pdev: Pointer to PCI device
8498adfc5217SJeff Kirsher  * @state: The current pci connection state
8499adfc5217SJeff Kirsher  *
8500adfc5217SJeff Kirsher  * This function is called after a PCI bus error affecting
8501adfc5217SJeff Kirsher  * this device has been detected.
8502adfc5217SJeff Kirsher  */
8503adfc5217SJeff Kirsher static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
8504adfc5217SJeff Kirsher 					       pci_channel_state_t state)
8505adfc5217SJeff Kirsher {
8506adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8507adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8508adfc5217SJeff Kirsher 
8509adfc5217SJeff Kirsher 	rtnl_lock();
8510adfc5217SJeff Kirsher 	netif_device_detach(dev);
8511adfc5217SJeff Kirsher 
8512adfc5217SJeff Kirsher 	if (state == pci_channel_io_perm_failure) {
8513adfc5217SJeff Kirsher 		rtnl_unlock();
8514adfc5217SJeff Kirsher 		return PCI_ERS_RESULT_DISCONNECT;
8515adfc5217SJeff Kirsher 	}
8516adfc5217SJeff Kirsher 
8517adfc5217SJeff Kirsher 	if (netif_running(dev)) {
8518adfc5217SJeff Kirsher 		bnx2_netif_stop(bp, true);
8519adfc5217SJeff Kirsher 		del_timer_sync(&bp->timer);
8520adfc5217SJeff Kirsher 		bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
8521adfc5217SJeff Kirsher 	}
8522adfc5217SJeff Kirsher 
8523adfc5217SJeff Kirsher 	pci_disable_device(pdev);
8524adfc5217SJeff Kirsher 	rtnl_unlock();
8525adfc5217SJeff Kirsher 
8526adfc5217SJeff Kirsher 	/* Request a slot slot reset. */
8527adfc5217SJeff Kirsher 	return PCI_ERS_RESULT_NEED_RESET;
8528adfc5217SJeff Kirsher }
8529adfc5217SJeff Kirsher 
8530adfc5217SJeff Kirsher /**
8531adfc5217SJeff Kirsher  * bnx2_io_slot_reset - called after the pci bus has been reset.
8532adfc5217SJeff Kirsher  * @pdev: Pointer to PCI device
8533adfc5217SJeff Kirsher  *
8534adfc5217SJeff Kirsher  * Restart the card from scratch, as if from a cold-boot.
8535adfc5217SJeff Kirsher  */
8536adfc5217SJeff Kirsher static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
8537adfc5217SJeff Kirsher {
8538adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8539adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8540adfc5217SJeff Kirsher 	pci_ers_result_t result;
8541adfc5217SJeff Kirsher 	int err;
8542adfc5217SJeff Kirsher 
8543adfc5217SJeff Kirsher 	rtnl_lock();
8544adfc5217SJeff Kirsher 	if (pci_enable_device(pdev)) {
8545adfc5217SJeff Kirsher 		dev_err(&pdev->dev,
8546adfc5217SJeff Kirsher 			"Cannot re-enable PCI device after reset\n");
8547adfc5217SJeff Kirsher 		result = PCI_ERS_RESULT_DISCONNECT;
8548adfc5217SJeff Kirsher 	} else {
8549adfc5217SJeff Kirsher 		pci_set_master(pdev);
8550adfc5217SJeff Kirsher 		pci_restore_state(pdev);
8551adfc5217SJeff Kirsher 		pci_save_state(pdev);
8552adfc5217SJeff Kirsher 
8553adfc5217SJeff Kirsher 		if (netif_running(dev)) {
8554adfc5217SJeff Kirsher 			bnx2_set_power_state(bp, PCI_D0);
8555adfc5217SJeff Kirsher 			bnx2_init_nic(bp, 1);
8556adfc5217SJeff Kirsher 		}
8557adfc5217SJeff Kirsher 		result = PCI_ERS_RESULT_RECOVERED;
8558adfc5217SJeff Kirsher 	}
8559adfc5217SJeff Kirsher 	rtnl_unlock();
8560adfc5217SJeff Kirsher 
8561adfc5217SJeff Kirsher 	if (!(bp->flags & BNX2_FLAG_AER_ENABLED))
8562adfc5217SJeff Kirsher 		return result;
8563adfc5217SJeff Kirsher 
8564adfc5217SJeff Kirsher 	err = pci_cleanup_aer_uncorrect_error_status(pdev);
8565adfc5217SJeff Kirsher 	if (err) {
8566adfc5217SJeff Kirsher 		dev_err(&pdev->dev,
8567adfc5217SJeff Kirsher 			"pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n",
8568adfc5217SJeff Kirsher 			 err); /* non-fatal, continue */
8569adfc5217SJeff Kirsher 	}
8570adfc5217SJeff Kirsher 
8571adfc5217SJeff Kirsher 	return result;
8572adfc5217SJeff Kirsher }
8573adfc5217SJeff Kirsher 
8574adfc5217SJeff Kirsher /**
8575adfc5217SJeff Kirsher  * bnx2_io_resume - called when traffic can start flowing again.
8576adfc5217SJeff Kirsher  * @pdev: Pointer to PCI device
8577adfc5217SJeff Kirsher  *
8578adfc5217SJeff Kirsher  * This callback is called when the error recovery driver tells us that
8579adfc5217SJeff Kirsher  * its OK to resume normal operation.
8580adfc5217SJeff Kirsher  */
8581adfc5217SJeff Kirsher static void bnx2_io_resume(struct pci_dev *pdev)
8582adfc5217SJeff Kirsher {
8583adfc5217SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
8584adfc5217SJeff Kirsher 	struct bnx2 *bp = netdev_priv(dev);
8585adfc5217SJeff Kirsher 
8586adfc5217SJeff Kirsher 	rtnl_lock();
8587adfc5217SJeff Kirsher 	if (netif_running(dev))
8588adfc5217SJeff Kirsher 		bnx2_netif_start(bp, true);
8589adfc5217SJeff Kirsher 
8590adfc5217SJeff Kirsher 	netif_device_attach(dev);
8591adfc5217SJeff Kirsher 	rtnl_unlock();
8592adfc5217SJeff Kirsher }
8593adfc5217SJeff Kirsher 
8594adfc5217SJeff Kirsher static struct pci_error_handlers bnx2_err_handler = {
8595adfc5217SJeff Kirsher 	.error_detected	= bnx2_io_error_detected,
8596adfc5217SJeff Kirsher 	.slot_reset	= bnx2_io_slot_reset,
8597adfc5217SJeff Kirsher 	.resume		= bnx2_io_resume,
8598adfc5217SJeff Kirsher };
8599adfc5217SJeff Kirsher 
8600adfc5217SJeff Kirsher static struct pci_driver bnx2_pci_driver = {
8601adfc5217SJeff Kirsher 	.name		= DRV_MODULE_NAME,
8602adfc5217SJeff Kirsher 	.id_table	= bnx2_pci_tbl,
8603adfc5217SJeff Kirsher 	.probe		= bnx2_init_one,
8604adfc5217SJeff Kirsher 	.remove		= __devexit_p(bnx2_remove_one),
8605adfc5217SJeff Kirsher 	.suspend	= bnx2_suspend,
8606adfc5217SJeff Kirsher 	.resume		= bnx2_resume,
8607adfc5217SJeff Kirsher 	.err_handler	= &bnx2_err_handler,
8608adfc5217SJeff Kirsher };
8609adfc5217SJeff Kirsher 
8610adfc5217SJeff Kirsher static int __init bnx2_init(void)
8611adfc5217SJeff Kirsher {
8612adfc5217SJeff Kirsher 	return pci_register_driver(&bnx2_pci_driver);
8613adfc5217SJeff Kirsher }
8614adfc5217SJeff Kirsher 
8615adfc5217SJeff Kirsher static void __exit bnx2_cleanup(void)
8616adfc5217SJeff Kirsher {
8617adfc5217SJeff Kirsher 	pci_unregister_driver(&bnx2_pci_driver);
8618adfc5217SJeff Kirsher }
8619adfc5217SJeff Kirsher 
8620adfc5217SJeff Kirsher module_init(bnx2_init);
8621adfc5217SJeff Kirsher module_exit(bnx2_cleanup);
8622adfc5217SJeff Kirsher 
8623adfc5217SJeff Kirsher 
8624adfc5217SJeff Kirsher 
8625