xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/atheros/atlx/atl1.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
4*4882a593Smuzhiyun  * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
5*4882a593Smuzhiyun  * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Derived from Intel e1000 driver
8*4882a593Smuzhiyun  * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Contact Information:
11*4882a593Smuzhiyun  * Xiong Huang <xiong.huang@atheros.com>
12*4882a593Smuzhiyun  * Jie Yang <jie.yang@atheros.com>
13*4882a593Smuzhiyun  * Chris Snook <csnook@redhat.com>
14*4882a593Smuzhiyun  * Jay Cliburn <jcliburn@gmail.com>
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * This version is adapted from the Attansic reference driver.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * TODO:
19*4882a593Smuzhiyun  * Add more ethtool functions.
20*4882a593Smuzhiyun  * Fix abstruse irq enable/disable condition described here:
21*4882a593Smuzhiyun  *	http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * NEEDS TESTING:
24*4882a593Smuzhiyun  * VLAN
25*4882a593Smuzhiyun  * multicast
26*4882a593Smuzhiyun  * promiscuous mode
27*4882a593Smuzhiyun  * interrupt coalescing
28*4882a593Smuzhiyun  * SMP torture testing
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <linux/atomic.h>
32*4882a593Smuzhiyun #include <asm/byteorder.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include <linux/compiler.h>
35*4882a593Smuzhiyun #include <linux/crc32.h>
36*4882a593Smuzhiyun #include <linux/delay.h>
37*4882a593Smuzhiyun #include <linux/dma-mapping.h>
38*4882a593Smuzhiyun #include <linux/etherdevice.h>
39*4882a593Smuzhiyun #include <linux/hardirq.h>
40*4882a593Smuzhiyun #include <linux/if_ether.h>
41*4882a593Smuzhiyun #include <linux/if_vlan.h>
42*4882a593Smuzhiyun #include <linux/in.h>
43*4882a593Smuzhiyun #include <linux/interrupt.h>
44*4882a593Smuzhiyun #include <linux/ip.h>
45*4882a593Smuzhiyun #include <linux/irqflags.h>
46*4882a593Smuzhiyun #include <linux/irqreturn.h>
47*4882a593Smuzhiyun #include <linux/jiffies.h>
48*4882a593Smuzhiyun #include <linux/mii.h>
49*4882a593Smuzhiyun #include <linux/module.h>
50*4882a593Smuzhiyun #include <linux/net.h>
51*4882a593Smuzhiyun #include <linux/netdevice.h>
52*4882a593Smuzhiyun #include <linux/pci.h>
53*4882a593Smuzhiyun #include <linux/pci_ids.h>
54*4882a593Smuzhiyun #include <linux/pm.h>
55*4882a593Smuzhiyun #include <linux/skbuff.h>
56*4882a593Smuzhiyun #include <linux/slab.h>
57*4882a593Smuzhiyun #include <linux/spinlock.h>
58*4882a593Smuzhiyun #include <linux/string.h>
59*4882a593Smuzhiyun #include <linux/tcp.h>
60*4882a593Smuzhiyun #include <linux/timer.h>
61*4882a593Smuzhiyun #include <linux/types.h>
62*4882a593Smuzhiyun #include <linux/workqueue.h>
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #include <net/checksum.h>
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #include "atl1.h"
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, "
69*4882a593Smuzhiyun 	      "Chris Snook <csnook@redhat.com>, "
70*4882a593Smuzhiyun 	      "Jay Cliburn <jcliburn@gmail.com>");
71*4882a593Smuzhiyun MODULE_LICENSE("GPL");
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /* Temporary hack for merging atl1 and atl2 */
74*4882a593Smuzhiyun #include "atlx.c"
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun static const struct ethtool_ops atl1_ethtool_ops;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  * This is the only thing that needs to be changed to adjust the
80*4882a593Smuzhiyun  * maximum number of ports that the driver can manage.
81*4882a593Smuzhiyun  */
82*4882a593Smuzhiyun #define ATL1_MAX_NIC 4
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define OPTION_UNSET    -1
85*4882a593Smuzhiyun #define OPTION_DISABLED 0
86*4882a593Smuzhiyun #define OPTION_ENABLED  1
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun #define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * Interrupt Moderate Timer in units of 2 us
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * Valid Range: 10-65535
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * Default Value: 100 (200us)
96*4882a593Smuzhiyun  */
97*4882a593Smuzhiyun static int int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
98*4882a593Smuzhiyun static unsigned int num_int_mod_timer;
99*4882a593Smuzhiyun module_param_array_named(int_mod_timer, int_mod_timer, int,
100*4882a593Smuzhiyun 	&num_int_mod_timer, 0);
101*4882a593Smuzhiyun MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #define DEFAULT_INT_MOD_CNT	100	/* 200us */
104*4882a593Smuzhiyun #define MAX_INT_MOD_CNT		65000
105*4882a593Smuzhiyun #define MIN_INT_MOD_CNT		50
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun struct atl1_option {
108*4882a593Smuzhiyun 	enum { enable_option, range_option, list_option } type;
109*4882a593Smuzhiyun 	char *name;
110*4882a593Smuzhiyun 	char *err;
111*4882a593Smuzhiyun 	int def;
112*4882a593Smuzhiyun 	union {
113*4882a593Smuzhiyun 		struct {	/* range_option info */
114*4882a593Smuzhiyun 			int min;
115*4882a593Smuzhiyun 			int max;
116*4882a593Smuzhiyun 		} r;
117*4882a593Smuzhiyun 		struct {	/* list_option info */
118*4882a593Smuzhiyun 			int nr;
119*4882a593Smuzhiyun 			struct atl1_opt_list {
120*4882a593Smuzhiyun 				int i;
121*4882a593Smuzhiyun 				char *str;
122*4882a593Smuzhiyun 			} *p;
123*4882a593Smuzhiyun 		} l;
124*4882a593Smuzhiyun 	} arg;
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun 
atl1_validate_option(int * value,struct atl1_option * opt,struct pci_dev * pdev)127*4882a593Smuzhiyun static int atl1_validate_option(int *value, struct atl1_option *opt,
128*4882a593Smuzhiyun 				struct pci_dev *pdev)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	if (*value == OPTION_UNSET) {
131*4882a593Smuzhiyun 		*value = opt->def;
132*4882a593Smuzhiyun 		return 0;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	switch (opt->type) {
136*4882a593Smuzhiyun 	case enable_option:
137*4882a593Smuzhiyun 		switch (*value) {
138*4882a593Smuzhiyun 		case OPTION_ENABLED:
139*4882a593Smuzhiyun 			dev_info(&pdev->dev, "%s enabled\n", opt->name);
140*4882a593Smuzhiyun 			return 0;
141*4882a593Smuzhiyun 		case OPTION_DISABLED:
142*4882a593Smuzhiyun 			dev_info(&pdev->dev, "%s disabled\n", opt->name);
143*4882a593Smuzhiyun 			return 0;
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 		break;
146*4882a593Smuzhiyun 	case range_option:
147*4882a593Smuzhiyun 		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
148*4882a593Smuzhiyun 			dev_info(&pdev->dev, "%s set to %i\n", opt->name,
149*4882a593Smuzhiyun 				*value);
150*4882a593Smuzhiyun 			return 0;
151*4882a593Smuzhiyun 		}
152*4882a593Smuzhiyun 		break;
153*4882a593Smuzhiyun 	case list_option:{
154*4882a593Smuzhiyun 			int i;
155*4882a593Smuzhiyun 			struct atl1_opt_list *ent;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 			for (i = 0; i < opt->arg.l.nr; i++) {
158*4882a593Smuzhiyun 				ent = &opt->arg.l.p[i];
159*4882a593Smuzhiyun 				if (*value == ent->i) {
160*4882a593Smuzhiyun 					if (ent->str[0] != '\0')
161*4882a593Smuzhiyun 						dev_info(&pdev->dev, "%s\n",
162*4882a593Smuzhiyun 							ent->str);
163*4882a593Smuzhiyun 					return 0;
164*4882a593Smuzhiyun 				}
165*4882a593Smuzhiyun 			}
166*4882a593Smuzhiyun 		}
167*4882a593Smuzhiyun 		break;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	default:
170*4882a593Smuzhiyun 		break;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
174*4882a593Smuzhiyun 		opt->name, *value, opt->err);
175*4882a593Smuzhiyun 	*value = opt->def;
176*4882a593Smuzhiyun 	return -1;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun /**
180*4882a593Smuzhiyun  * atl1_check_options - Range Checking for Command Line Parameters
181*4882a593Smuzhiyun  * @adapter: board private structure
182*4882a593Smuzhiyun  *
183*4882a593Smuzhiyun  * This routine checks all command line parameters for valid user
184*4882a593Smuzhiyun  * input.  If an invalid value is given, or if no user specified
185*4882a593Smuzhiyun  * value exists, a default value is used.  The final value is stored
186*4882a593Smuzhiyun  * in a variable in the adapter structure.
187*4882a593Smuzhiyun  */
atl1_check_options(struct atl1_adapter * adapter)188*4882a593Smuzhiyun static void atl1_check_options(struct atl1_adapter *adapter)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
191*4882a593Smuzhiyun 	int bd = adapter->bd_number;
192*4882a593Smuzhiyun 	if (bd >= ATL1_MAX_NIC) {
193*4882a593Smuzhiyun 		dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
194*4882a593Smuzhiyun 		dev_notice(&pdev->dev, "using defaults for all values\n");
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 	{			/* Interrupt Moderate Timer */
197*4882a593Smuzhiyun 		struct atl1_option opt = {
198*4882a593Smuzhiyun 			.type = range_option,
199*4882a593Smuzhiyun 			.name = "Interrupt Moderator Timer",
200*4882a593Smuzhiyun 			.err = "using default of "
201*4882a593Smuzhiyun 				__MODULE_STRING(DEFAULT_INT_MOD_CNT),
202*4882a593Smuzhiyun 			.def = DEFAULT_INT_MOD_CNT,
203*4882a593Smuzhiyun 			.arg = {.r = {.min = MIN_INT_MOD_CNT,
204*4882a593Smuzhiyun 					.max = MAX_INT_MOD_CNT} }
205*4882a593Smuzhiyun 		};
206*4882a593Smuzhiyun 		int val;
207*4882a593Smuzhiyun 		if (num_int_mod_timer > bd) {
208*4882a593Smuzhiyun 			val = int_mod_timer[bd];
209*4882a593Smuzhiyun 			atl1_validate_option(&val, &opt, pdev);
210*4882a593Smuzhiyun 			adapter->imt = (u16) val;
211*4882a593Smuzhiyun 		} else
212*4882a593Smuzhiyun 			adapter->imt = (u16) (opt.def);
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun /*
217*4882a593Smuzhiyun  * atl1_pci_tbl - PCI Device ID Table
218*4882a593Smuzhiyun  */
219*4882a593Smuzhiyun static const struct pci_device_id atl1_pci_tbl[] = {
220*4882a593Smuzhiyun 	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
221*4882a593Smuzhiyun 	/* required last entry */
222*4882a593Smuzhiyun 	{0,}
223*4882a593Smuzhiyun };
224*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
227*4882a593Smuzhiyun 	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static int debug = -1;
230*4882a593Smuzhiyun module_param(debug, int, 0);
231*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /*
234*4882a593Smuzhiyun  * Reset the transmit and receive units; mask and clear all interrupts.
235*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
236*4882a593Smuzhiyun  * return : 0  or  idle status (if error)
237*4882a593Smuzhiyun  */
atl1_reset_hw(struct atl1_hw * hw)238*4882a593Smuzhiyun static s32 atl1_reset_hw(struct atl1_hw *hw)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	struct pci_dev *pdev = hw->back->pdev;
241*4882a593Smuzhiyun 	struct atl1_adapter *adapter = hw->back;
242*4882a593Smuzhiyun 	u32 icr;
243*4882a593Smuzhiyun 	int i;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	/*
246*4882a593Smuzhiyun 	 * Clear Interrupt mask to stop board from generating
247*4882a593Smuzhiyun 	 * interrupts & Clear any pending interrupt events
248*4882a593Smuzhiyun 	 */
249*4882a593Smuzhiyun 	/*
250*4882a593Smuzhiyun 	 * atlx_irq_disable(adapter);
251*4882a593Smuzhiyun 	 * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
252*4882a593Smuzhiyun 	 */
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	/*
255*4882a593Smuzhiyun 	 * Issue Soft Reset to the MAC.  This will reset the chip's
256*4882a593Smuzhiyun 	 * transmit, receive, DMA.  It will not effect
257*4882a593Smuzhiyun 	 * the current PCI configuration.  The global reset bit is self-
258*4882a593Smuzhiyun 	 * clearing, and should clear within a microsecond.
259*4882a593Smuzhiyun 	 */
260*4882a593Smuzhiyun 	iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
261*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_MASTER_CTRL);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
264*4882a593Smuzhiyun 	ioread16(hw->hw_addr + REG_PHY_ENABLE);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	/* delay about 1ms */
267*4882a593Smuzhiyun 	msleep(1);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* Wait at least 10ms for All module to be Idle */
270*4882a593Smuzhiyun 	for (i = 0; i < 10; i++) {
271*4882a593Smuzhiyun 		icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
272*4882a593Smuzhiyun 		if (!icr)
273*4882a593Smuzhiyun 			break;
274*4882a593Smuzhiyun 		/* delay 1 ms */
275*4882a593Smuzhiyun 		msleep(1);
276*4882a593Smuzhiyun 		/* FIXME: still the right way to do this? */
277*4882a593Smuzhiyun 		cpu_relax();
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	if (icr) {
281*4882a593Smuzhiyun 		if (netif_msg_hw(adapter))
282*4882a593Smuzhiyun 			dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
283*4882a593Smuzhiyun 		return icr;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	return 0;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun /* function about EEPROM
290*4882a593Smuzhiyun  *
291*4882a593Smuzhiyun  * check_eeprom_exist
292*4882a593Smuzhiyun  * return 0 if eeprom exist
293*4882a593Smuzhiyun  */
atl1_check_eeprom_exist(struct atl1_hw * hw)294*4882a593Smuzhiyun static int atl1_check_eeprom_exist(struct atl1_hw *hw)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	u32 value;
297*4882a593Smuzhiyun 	value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
298*4882a593Smuzhiyun 	if (value & SPI_FLASH_CTRL_EN_VPD) {
299*4882a593Smuzhiyun 		value &= ~SPI_FLASH_CTRL_EN_VPD;
300*4882a593Smuzhiyun 		iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
304*4882a593Smuzhiyun 	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
atl1_read_eeprom(struct atl1_hw * hw,u32 offset,u32 * p_value)307*4882a593Smuzhiyun static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	int i;
310*4882a593Smuzhiyun 	u32 control;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (offset & 3)
313*4882a593Smuzhiyun 		/* address do not align */
314*4882a593Smuzhiyun 		return false;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	iowrite32(0, hw->hw_addr + REG_VPD_DATA);
317*4882a593Smuzhiyun 	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
318*4882a593Smuzhiyun 	iowrite32(control, hw->hw_addr + REG_VPD_CAP);
319*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_VPD_CAP);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	for (i = 0; i < 10; i++) {
322*4882a593Smuzhiyun 		msleep(2);
323*4882a593Smuzhiyun 		control = ioread32(hw->hw_addr + REG_VPD_CAP);
324*4882a593Smuzhiyun 		if (control & VPD_CAP_VPD_FLAG)
325*4882a593Smuzhiyun 			break;
326*4882a593Smuzhiyun 	}
327*4882a593Smuzhiyun 	if (control & VPD_CAP_VPD_FLAG) {
328*4882a593Smuzhiyun 		*p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
329*4882a593Smuzhiyun 		return true;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 	/* timeout */
332*4882a593Smuzhiyun 	return false;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun /*
336*4882a593Smuzhiyun  * Reads the value from a PHY register
337*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
338*4882a593Smuzhiyun  * reg_addr - address of the PHY register to read
339*4882a593Smuzhiyun  */
atl1_read_phy_reg(struct atl1_hw * hw,u16 reg_addr,u16 * phy_data)340*4882a593Smuzhiyun static s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	u32 val;
343*4882a593Smuzhiyun 	int i;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
346*4882a593Smuzhiyun 		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
347*4882a593Smuzhiyun 		MDIO_CLK_SEL_SHIFT;
348*4882a593Smuzhiyun 	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
349*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_MDIO_CTRL);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
352*4882a593Smuzhiyun 		udelay(2);
353*4882a593Smuzhiyun 		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
354*4882a593Smuzhiyun 		if (!(val & (MDIO_START | MDIO_BUSY)))
355*4882a593Smuzhiyun 			break;
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 	if (!(val & (MDIO_START | MDIO_BUSY))) {
358*4882a593Smuzhiyun 		*phy_data = (u16) val;
359*4882a593Smuzhiyun 		return 0;
360*4882a593Smuzhiyun 	}
361*4882a593Smuzhiyun 	return ATLX_ERR_PHY;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun #define CUSTOM_SPI_CS_SETUP	2
365*4882a593Smuzhiyun #define CUSTOM_SPI_CLK_HI	2
366*4882a593Smuzhiyun #define CUSTOM_SPI_CLK_LO	2
367*4882a593Smuzhiyun #define CUSTOM_SPI_CS_HOLD	2
368*4882a593Smuzhiyun #define CUSTOM_SPI_CS_HI	3
369*4882a593Smuzhiyun 
atl1_spi_read(struct atl1_hw * hw,u32 addr,u32 * buf)370*4882a593Smuzhiyun static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	int i;
373*4882a593Smuzhiyun 	u32 value;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	iowrite32(0, hw->hw_addr + REG_SPI_DATA);
376*4882a593Smuzhiyun 	iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	value = SPI_FLASH_CTRL_WAIT_READY |
379*4882a593Smuzhiyun 	    (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
380*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
381*4882a593Smuzhiyun 					     SPI_FLASH_CTRL_CLK_HI_MASK) <<
382*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
383*4882a593Smuzhiyun 					   SPI_FLASH_CTRL_CLK_LO_MASK) <<
384*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
385*4882a593Smuzhiyun 					   SPI_FLASH_CTRL_CS_HOLD_MASK) <<
386*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
387*4882a593Smuzhiyun 					    SPI_FLASH_CTRL_CS_HI_MASK) <<
388*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
389*4882a593Smuzhiyun 	    SPI_FLASH_CTRL_INS_SHIFT;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	value |= SPI_FLASH_CTRL_START;
394*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
395*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	for (i = 0; i < 10; i++) {
398*4882a593Smuzhiyun 		msleep(1);
399*4882a593Smuzhiyun 		value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
400*4882a593Smuzhiyun 		if (!(value & SPI_FLASH_CTRL_START))
401*4882a593Smuzhiyun 			break;
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (value & SPI_FLASH_CTRL_START)
405*4882a593Smuzhiyun 		return false;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	*buf = ioread32(hw->hw_addr + REG_SPI_DATA);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	return true;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun /*
413*4882a593Smuzhiyun  * get_permanent_address
414*4882a593Smuzhiyun  * return 0 if get valid mac address,
415*4882a593Smuzhiyun  */
atl1_get_permanent_address(struct atl1_hw * hw)416*4882a593Smuzhiyun static int atl1_get_permanent_address(struct atl1_hw *hw)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	u32 addr[2];
419*4882a593Smuzhiyun 	u32 i, control;
420*4882a593Smuzhiyun 	u16 reg;
421*4882a593Smuzhiyun 	u8 eth_addr[ETH_ALEN];
422*4882a593Smuzhiyun 	bool key_valid;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	if (is_valid_ether_addr(hw->perm_mac_addr))
425*4882a593Smuzhiyun 		return 0;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	/* init */
428*4882a593Smuzhiyun 	addr[0] = addr[1] = 0;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	if (!atl1_check_eeprom_exist(hw)) {
431*4882a593Smuzhiyun 		reg = 0;
432*4882a593Smuzhiyun 		key_valid = false;
433*4882a593Smuzhiyun 		/* Read out all EEPROM content */
434*4882a593Smuzhiyun 		i = 0;
435*4882a593Smuzhiyun 		while (1) {
436*4882a593Smuzhiyun 			if (atl1_read_eeprom(hw, i + 0x100, &control)) {
437*4882a593Smuzhiyun 				if (key_valid) {
438*4882a593Smuzhiyun 					if (reg == REG_MAC_STA_ADDR)
439*4882a593Smuzhiyun 						addr[0] = control;
440*4882a593Smuzhiyun 					else if (reg == (REG_MAC_STA_ADDR + 4))
441*4882a593Smuzhiyun 						addr[1] = control;
442*4882a593Smuzhiyun 					key_valid = false;
443*4882a593Smuzhiyun 				} else if ((control & 0xff) == 0x5A) {
444*4882a593Smuzhiyun 					key_valid = true;
445*4882a593Smuzhiyun 					reg = (u16) (control >> 16);
446*4882a593Smuzhiyun 				} else
447*4882a593Smuzhiyun 					break;
448*4882a593Smuzhiyun 			} else
449*4882a593Smuzhiyun 				/* read error */
450*4882a593Smuzhiyun 				break;
451*4882a593Smuzhiyun 			i += 4;
452*4882a593Smuzhiyun 		}
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 		*(u32 *) &eth_addr[2] = swab32(addr[0]);
455*4882a593Smuzhiyun 		*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
456*4882a593Smuzhiyun 		if (is_valid_ether_addr(eth_addr)) {
457*4882a593Smuzhiyun 			memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
458*4882a593Smuzhiyun 			return 0;
459*4882a593Smuzhiyun 		}
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	/* see if SPI FLAGS exist ? */
463*4882a593Smuzhiyun 	addr[0] = addr[1] = 0;
464*4882a593Smuzhiyun 	reg = 0;
465*4882a593Smuzhiyun 	key_valid = false;
466*4882a593Smuzhiyun 	i = 0;
467*4882a593Smuzhiyun 	while (1) {
468*4882a593Smuzhiyun 		if (atl1_spi_read(hw, i + 0x1f000, &control)) {
469*4882a593Smuzhiyun 			if (key_valid) {
470*4882a593Smuzhiyun 				if (reg == REG_MAC_STA_ADDR)
471*4882a593Smuzhiyun 					addr[0] = control;
472*4882a593Smuzhiyun 				else if (reg == (REG_MAC_STA_ADDR + 4))
473*4882a593Smuzhiyun 					addr[1] = control;
474*4882a593Smuzhiyun 				key_valid = false;
475*4882a593Smuzhiyun 			} else if ((control & 0xff) == 0x5A) {
476*4882a593Smuzhiyun 				key_valid = true;
477*4882a593Smuzhiyun 				reg = (u16) (control >> 16);
478*4882a593Smuzhiyun 			} else
479*4882a593Smuzhiyun 				/* data end */
480*4882a593Smuzhiyun 				break;
481*4882a593Smuzhiyun 		} else
482*4882a593Smuzhiyun 			/* read error */
483*4882a593Smuzhiyun 			break;
484*4882a593Smuzhiyun 		i += 4;
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	*(u32 *) &eth_addr[2] = swab32(addr[0]);
488*4882a593Smuzhiyun 	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
489*4882a593Smuzhiyun 	if (is_valid_ether_addr(eth_addr)) {
490*4882a593Smuzhiyun 		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
491*4882a593Smuzhiyun 		return 0;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	/*
495*4882a593Smuzhiyun 	 * On some motherboards, the MAC address is written by the
496*4882a593Smuzhiyun 	 * BIOS directly to the MAC register during POST, and is
497*4882a593Smuzhiyun 	 * not stored in eeprom.  If all else thus far has failed
498*4882a593Smuzhiyun 	 * to fetch the permanent MAC address, try reading it directly.
499*4882a593Smuzhiyun 	 */
500*4882a593Smuzhiyun 	addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
501*4882a593Smuzhiyun 	addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
502*4882a593Smuzhiyun 	*(u32 *) &eth_addr[2] = swab32(addr[0]);
503*4882a593Smuzhiyun 	*(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
504*4882a593Smuzhiyun 	if (is_valid_ether_addr(eth_addr)) {
505*4882a593Smuzhiyun 		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
506*4882a593Smuzhiyun 		return 0;
507*4882a593Smuzhiyun 	}
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	return 1;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun /*
513*4882a593Smuzhiyun  * Reads the adapter's MAC address from the EEPROM
514*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
515*4882a593Smuzhiyun  */
atl1_read_mac_addr(struct atl1_hw * hw)516*4882a593Smuzhiyun static s32 atl1_read_mac_addr(struct atl1_hw *hw)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	s32 ret = 0;
519*4882a593Smuzhiyun 	u16 i;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	if (atl1_get_permanent_address(hw)) {
522*4882a593Smuzhiyun 		eth_random_addr(hw->perm_mac_addr);
523*4882a593Smuzhiyun 		ret = 1;
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	for (i = 0; i < ETH_ALEN; i++)
527*4882a593Smuzhiyun 		hw->mac_addr[i] = hw->perm_mac_addr[i];
528*4882a593Smuzhiyun 	return ret;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun /*
532*4882a593Smuzhiyun  * Hashes an address to determine its location in the multicast table
533*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
534*4882a593Smuzhiyun  * mc_addr - the multicast address to hash
535*4882a593Smuzhiyun  *
536*4882a593Smuzhiyun  * atl1_hash_mc_addr
537*4882a593Smuzhiyun  *  purpose
538*4882a593Smuzhiyun  *      set hash value for a multicast address
539*4882a593Smuzhiyun  *      hash calcu processing :
540*4882a593Smuzhiyun  *          1. calcu 32bit CRC for multicast address
541*4882a593Smuzhiyun  *          2. reverse crc with MSB to LSB
542*4882a593Smuzhiyun  */
atl1_hash_mc_addr(struct atl1_hw * hw,u8 * mc_addr)543*4882a593Smuzhiyun static u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	u32 crc32, value = 0;
546*4882a593Smuzhiyun 	int i;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	crc32 = ether_crc_le(6, mc_addr);
549*4882a593Smuzhiyun 	for (i = 0; i < 32; i++)
550*4882a593Smuzhiyun 		value |= (((crc32 >> i) & 1) << (31 - i));
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	return value;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun /*
556*4882a593Smuzhiyun  * Sets the bit in the multicast table corresponding to the hash value.
557*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
558*4882a593Smuzhiyun  * hash_value - Multicast address hash value
559*4882a593Smuzhiyun  */
atl1_hash_set(struct atl1_hw * hw,u32 hash_value)560*4882a593Smuzhiyun static void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	u32 hash_bit, hash_reg;
563*4882a593Smuzhiyun 	u32 mta;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	/*
566*4882a593Smuzhiyun 	 * The HASH Table  is a register array of 2 32-bit registers.
567*4882a593Smuzhiyun 	 * It is treated like an array of 64 bits.  We want to set
568*4882a593Smuzhiyun 	 * bit BitArray[hash_value]. So we figure out what register
569*4882a593Smuzhiyun 	 * the bit is in, read it, OR in the new bit, then write
570*4882a593Smuzhiyun 	 * back the new value.  The register is determined by the
571*4882a593Smuzhiyun 	 * upper 7 bits of the hash value and the bit within that
572*4882a593Smuzhiyun 	 * register are determined by the lower 5 bits of the value.
573*4882a593Smuzhiyun 	 */
574*4882a593Smuzhiyun 	hash_reg = (hash_value >> 31) & 0x1;
575*4882a593Smuzhiyun 	hash_bit = (hash_value >> 26) & 0x1F;
576*4882a593Smuzhiyun 	mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
577*4882a593Smuzhiyun 	mta |= (1 << hash_bit);
578*4882a593Smuzhiyun 	iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun /*
582*4882a593Smuzhiyun  * Writes a value to a PHY register
583*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
584*4882a593Smuzhiyun  * reg_addr - address of the PHY register to write
585*4882a593Smuzhiyun  * data - data to write to the PHY
586*4882a593Smuzhiyun  */
atl1_write_phy_reg(struct atl1_hw * hw,u32 reg_addr,u16 phy_data)587*4882a593Smuzhiyun static s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun 	int i;
590*4882a593Smuzhiyun 	u32 val;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
593*4882a593Smuzhiyun 	    (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
594*4882a593Smuzhiyun 	    MDIO_SUP_PREAMBLE |
595*4882a593Smuzhiyun 	    MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
596*4882a593Smuzhiyun 	iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
597*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_MDIO_CTRL);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
600*4882a593Smuzhiyun 		udelay(2);
601*4882a593Smuzhiyun 		val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
602*4882a593Smuzhiyun 		if (!(val & (MDIO_START | MDIO_BUSY)))
603*4882a593Smuzhiyun 			break;
604*4882a593Smuzhiyun 	}
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (!(val & (MDIO_START | MDIO_BUSY)))
607*4882a593Smuzhiyun 		return 0;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	return ATLX_ERR_PHY;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun /*
613*4882a593Smuzhiyun  * Make L001's PHY out of Power Saving State (bug)
614*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
615*4882a593Smuzhiyun  * when power on, L001's PHY always on Power saving State
616*4882a593Smuzhiyun  * (Gigabit Link forbidden)
617*4882a593Smuzhiyun  */
atl1_phy_leave_power_saving(struct atl1_hw * hw)618*4882a593Smuzhiyun static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	s32 ret;
621*4882a593Smuzhiyun 	ret = atl1_write_phy_reg(hw, 29, 0x0029);
622*4882a593Smuzhiyun 	if (ret)
623*4882a593Smuzhiyun 		return ret;
624*4882a593Smuzhiyun 	return atl1_write_phy_reg(hw, 30, 0);
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun /*
628*4882a593Smuzhiyun  * Resets the PHY and make all config validate
629*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
630*4882a593Smuzhiyun  *
631*4882a593Smuzhiyun  * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
632*4882a593Smuzhiyun  */
atl1_phy_reset(struct atl1_hw * hw)633*4882a593Smuzhiyun static s32 atl1_phy_reset(struct atl1_hw *hw)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	struct pci_dev *pdev = hw->back->pdev;
636*4882a593Smuzhiyun 	struct atl1_adapter *adapter = hw->back;
637*4882a593Smuzhiyun 	s32 ret_val;
638*4882a593Smuzhiyun 	u16 phy_data;
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
641*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL)
642*4882a593Smuzhiyun 		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
643*4882a593Smuzhiyun 	else {
644*4882a593Smuzhiyun 		switch (hw->media_type) {
645*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_FULL:
646*4882a593Smuzhiyun 			phy_data =
647*4882a593Smuzhiyun 			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
648*4882a593Smuzhiyun 			    MII_CR_RESET;
649*4882a593Smuzhiyun 			break;
650*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_HALF:
651*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
652*4882a593Smuzhiyun 			break;
653*4882a593Smuzhiyun 		case MEDIA_TYPE_10M_FULL:
654*4882a593Smuzhiyun 			phy_data =
655*4882a593Smuzhiyun 			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
656*4882a593Smuzhiyun 			break;
657*4882a593Smuzhiyun 		default:
658*4882a593Smuzhiyun 			/* MEDIA_TYPE_10M_HALF: */
659*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
660*4882a593Smuzhiyun 			break;
661*4882a593Smuzhiyun 		}
662*4882a593Smuzhiyun 	}
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
665*4882a593Smuzhiyun 	if (ret_val) {
666*4882a593Smuzhiyun 		u32 val;
667*4882a593Smuzhiyun 		int i;
668*4882a593Smuzhiyun 		/* pcie serdes link may be down! */
669*4882a593Smuzhiyun 		if (netif_msg_hw(adapter))
670*4882a593Smuzhiyun 			dev_dbg(&pdev->dev, "pcie phy link down\n");
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 		for (i = 0; i < 25; i++) {
673*4882a593Smuzhiyun 			msleep(1);
674*4882a593Smuzhiyun 			val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
675*4882a593Smuzhiyun 			if (!(val & (MDIO_START | MDIO_BUSY)))
676*4882a593Smuzhiyun 				break;
677*4882a593Smuzhiyun 		}
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 		if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
680*4882a593Smuzhiyun 			if (netif_msg_hw(adapter))
681*4882a593Smuzhiyun 				dev_warn(&pdev->dev,
682*4882a593Smuzhiyun 					"pcie link down at least 25ms\n");
683*4882a593Smuzhiyun 			return ret_val;
684*4882a593Smuzhiyun 		}
685*4882a593Smuzhiyun 	}
686*4882a593Smuzhiyun 	return 0;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun /*
690*4882a593Smuzhiyun  * Configures PHY autoneg and flow control advertisement settings
691*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
692*4882a593Smuzhiyun  */
atl1_phy_setup_autoneg_adv(struct atl1_hw * hw)693*4882a593Smuzhiyun static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun 	s32 ret_val;
696*4882a593Smuzhiyun 	s16 mii_autoneg_adv_reg;
697*4882a593Smuzhiyun 	s16 mii_1000t_ctrl_reg;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
700*4882a593Smuzhiyun 	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	/* Read the MII 1000Base-T Control Register (Address 9). */
703*4882a593Smuzhiyun 	mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	/*
706*4882a593Smuzhiyun 	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
707*4882a593Smuzhiyun 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
708*4882a593Smuzhiyun 	 * the  1000Base-T Control Register (Address 9).
709*4882a593Smuzhiyun 	 */
710*4882a593Smuzhiyun 	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
711*4882a593Smuzhiyun 	mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	/*
714*4882a593Smuzhiyun 	 * Need to parse media_type  and set up
715*4882a593Smuzhiyun 	 * the appropriate PHY registers.
716*4882a593Smuzhiyun 	 */
717*4882a593Smuzhiyun 	switch (hw->media_type) {
718*4882a593Smuzhiyun 	case MEDIA_TYPE_AUTO_SENSOR:
719*4882a593Smuzhiyun 		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
720*4882a593Smuzhiyun 					MII_AR_10T_FD_CAPS |
721*4882a593Smuzhiyun 					MII_AR_100TX_HD_CAPS |
722*4882a593Smuzhiyun 					MII_AR_100TX_FD_CAPS);
723*4882a593Smuzhiyun 		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
724*4882a593Smuzhiyun 		break;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	case MEDIA_TYPE_1000M_FULL:
727*4882a593Smuzhiyun 		mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
728*4882a593Smuzhiyun 		break;
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	case MEDIA_TYPE_100M_FULL:
731*4882a593Smuzhiyun 		mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
732*4882a593Smuzhiyun 		break;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	case MEDIA_TYPE_100M_HALF:
735*4882a593Smuzhiyun 		mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
736*4882a593Smuzhiyun 		break;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	case MEDIA_TYPE_10M_FULL:
739*4882a593Smuzhiyun 		mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
740*4882a593Smuzhiyun 		break;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	default:
743*4882a593Smuzhiyun 		mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
744*4882a593Smuzhiyun 		break;
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	/* flow control fixed to enable all */
748*4882a593Smuzhiyun 	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
751*4882a593Smuzhiyun 	hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
754*4882a593Smuzhiyun 	if (ret_val)
755*4882a593Smuzhiyun 		return ret_val;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
758*4882a593Smuzhiyun 	if (ret_val)
759*4882a593Smuzhiyun 		return ret_val;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun /*
765*4882a593Smuzhiyun  * Configures link settings.
766*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
767*4882a593Smuzhiyun  * Assumes the hardware has previously been reset and the
768*4882a593Smuzhiyun  * transmitter and receiver are not enabled.
769*4882a593Smuzhiyun  */
atl1_setup_link(struct atl1_hw * hw)770*4882a593Smuzhiyun static s32 atl1_setup_link(struct atl1_hw *hw)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	struct pci_dev *pdev = hw->back->pdev;
773*4882a593Smuzhiyun 	struct atl1_adapter *adapter = hw->back;
774*4882a593Smuzhiyun 	s32 ret_val;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	/*
777*4882a593Smuzhiyun 	 * Options:
778*4882a593Smuzhiyun 	 *  PHY will advertise value(s) parsed from
779*4882a593Smuzhiyun 	 *  autoneg_advertised and fc
780*4882a593Smuzhiyun 	 *  no matter what autoneg is , We will not wait link result.
781*4882a593Smuzhiyun 	 */
782*4882a593Smuzhiyun 	ret_val = atl1_phy_setup_autoneg_adv(hw);
783*4882a593Smuzhiyun 	if (ret_val) {
784*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
785*4882a593Smuzhiyun 			dev_dbg(&pdev->dev,
786*4882a593Smuzhiyun 				"error setting up autonegotiation\n");
787*4882a593Smuzhiyun 		return ret_val;
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 	/* SW.Reset , En-Auto-Neg if needed */
790*4882a593Smuzhiyun 	ret_val = atl1_phy_reset(hw);
791*4882a593Smuzhiyun 	if (ret_val) {
792*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
793*4882a593Smuzhiyun 			dev_dbg(&pdev->dev, "error resetting phy\n");
794*4882a593Smuzhiyun 		return ret_val;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 	hw->phy_configured = true;
797*4882a593Smuzhiyun 	return ret_val;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun 
atl1_init_flash_opcode(struct atl1_hw * hw)800*4882a593Smuzhiyun static void atl1_init_flash_opcode(struct atl1_hw *hw)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun 	if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
803*4882a593Smuzhiyun 		/* Atmel */
804*4882a593Smuzhiyun 		hw->flash_vendor = 0;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	/* Init OP table */
807*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_program,
808*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
809*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
810*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
811*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
812*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
813*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
814*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_RDID);
815*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_wren,
816*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_WREN);
817*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
818*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
819*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
820*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
821*4882a593Smuzhiyun 	iowrite8(flash_table[hw->flash_vendor].cmd_read,
822*4882a593Smuzhiyun 		hw->hw_addr + REG_SPI_FLASH_OP_READ);
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun /*
826*4882a593Smuzhiyun  * Performs basic configuration of the adapter.
827*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
828*4882a593Smuzhiyun  * Assumes that the controller has previously been reset and is in a
829*4882a593Smuzhiyun  * post-reset uninitialized state. Initializes multicast table,
830*4882a593Smuzhiyun  * and  Calls routines to setup link
831*4882a593Smuzhiyun  * Leaves the transmit and receive units disabled and uninitialized.
832*4882a593Smuzhiyun  */
atl1_init_hw(struct atl1_hw * hw)833*4882a593Smuzhiyun static s32 atl1_init_hw(struct atl1_hw *hw)
834*4882a593Smuzhiyun {
835*4882a593Smuzhiyun 	u32 ret_val = 0;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	/* Zero out the Multicast HASH table */
838*4882a593Smuzhiyun 	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
839*4882a593Smuzhiyun 	/* clear the old settings from the multicast hash table */
840*4882a593Smuzhiyun 	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	atl1_init_flash_opcode(hw);
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	if (!hw->phy_configured) {
845*4882a593Smuzhiyun 		/* enable GPHY LinkChange Interrupt */
846*4882a593Smuzhiyun 		ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
847*4882a593Smuzhiyun 		if (ret_val)
848*4882a593Smuzhiyun 			return ret_val;
849*4882a593Smuzhiyun 		/* make PHY out of power-saving state */
850*4882a593Smuzhiyun 		ret_val = atl1_phy_leave_power_saving(hw);
851*4882a593Smuzhiyun 		if (ret_val)
852*4882a593Smuzhiyun 			return ret_val;
853*4882a593Smuzhiyun 		/* Call a subroutine to configure the link */
854*4882a593Smuzhiyun 		ret_val = atl1_setup_link(hw);
855*4882a593Smuzhiyun 	}
856*4882a593Smuzhiyun 	return ret_val;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun /*
860*4882a593Smuzhiyun  * Detects the current speed and duplex settings of the hardware.
861*4882a593Smuzhiyun  * hw - Struct containing variables accessed by shared code
862*4882a593Smuzhiyun  * speed - Speed of the connection
863*4882a593Smuzhiyun  * duplex - Duplex setting of the connection
864*4882a593Smuzhiyun  */
atl1_get_speed_and_duplex(struct atl1_hw * hw,u16 * speed,u16 * duplex)865*4882a593Smuzhiyun static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
866*4882a593Smuzhiyun {
867*4882a593Smuzhiyun 	struct pci_dev *pdev = hw->back->pdev;
868*4882a593Smuzhiyun 	struct atl1_adapter *adapter = hw->back;
869*4882a593Smuzhiyun 	s32 ret_val;
870*4882a593Smuzhiyun 	u16 phy_data;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	/* ; --- Read   PHY Specific Status Register (17) */
873*4882a593Smuzhiyun 	ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
874*4882a593Smuzhiyun 	if (ret_val)
875*4882a593Smuzhiyun 		return ret_val;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
878*4882a593Smuzhiyun 		return ATLX_ERR_PHY_RES;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	switch (phy_data & MII_ATLX_PSSR_SPEED) {
881*4882a593Smuzhiyun 	case MII_ATLX_PSSR_1000MBS:
882*4882a593Smuzhiyun 		*speed = SPEED_1000;
883*4882a593Smuzhiyun 		break;
884*4882a593Smuzhiyun 	case MII_ATLX_PSSR_100MBS:
885*4882a593Smuzhiyun 		*speed = SPEED_100;
886*4882a593Smuzhiyun 		break;
887*4882a593Smuzhiyun 	case MII_ATLX_PSSR_10MBS:
888*4882a593Smuzhiyun 		*speed = SPEED_10;
889*4882a593Smuzhiyun 		break;
890*4882a593Smuzhiyun 	default:
891*4882a593Smuzhiyun 		if (netif_msg_hw(adapter))
892*4882a593Smuzhiyun 			dev_dbg(&pdev->dev, "error getting speed\n");
893*4882a593Smuzhiyun 		return ATLX_ERR_PHY_SPEED;
894*4882a593Smuzhiyun 	}
895*4882a593Smuzhiyun 	if (phy_data & MII_ATLX_PSSR_DPLX)
896*4882a593Smuzhiyun 		*duplex = FULL_DUPLEX;
897*4882a593Smuzhiyun 	else
898*4882a593Smuzhiyun 		*duplex = HALF_DUPLEX;
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	return 0;
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun 
atl1_set_mac_addr(struct atl1_hw * hw)903*4882a593Smuzhiyun static void atl1_set_mac_addr(struct atl1_hw *hw)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun 	u32 value;
906*4882a593Smuzhiyun 	/*
907*4882a593Smuzhiyun 	 * 00-0B-6A-F6-00-DC
908*4882a593Smuzhiyun 	 * 0:  6AF600DC   1: 000B
909*4882a593Smuzhiyun 	 * low dword
910*4882a593Smuzhiyun 	 */
911*4882a593Smuzhiyun 	value = (((u32) hw->mac_addr[2]) << 24) |
912*4882a593Smuzhiyun 	    (((u32) hw->mac_addr[3]) << 16) |
913*4882a593Smuzhiyun 	    (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
914*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
915*4882a593Smuzhiyun 	/* high dword */
916*4882a593Smuzhiyun 	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
917*4882a593Smuzhiyun 	iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun /**
921*4882a593Smuzhiyun  * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
922*4882a593Smuzhiyun  * @adapter: board private structure to initialize
923*4882a593Smuzhiyun  *
924*4882a593Smuzhiyun  * atl1_sw_init initializes the Adapter private data structure.
925*4882a593Smuzhiyun  * Fields are initialized based on PCI device information and
926*4882a593Smuzhiyun  * OS network device settings (MTU size).
927*4882a593Smuzhiyun  */
atl1_sw_init(struct atl1_adapter * adapter)928*4882a593Smuzhiyun static int atl1_sw_init(struct atl1_adapter *adapter)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
931*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
934*4882a593Smuzhiyun 	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	adapter->wol = 0;
937*4882a593Smuzhiyun 	device_set_wakeup_enable(&adapter->pdev->dev, false);
938*4882a593Smuzhiyun 	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
939*4882a593Smuzhiyun 	adapter->ict = 50000;		/* 100ms */
940*4882a593Smuzhiyun 	adapter->link_speed = SPEED_0;	/* hardware init */
941*4882a593Smuzhiyun 	adapter->link_duplex = FULL_DUPLEX;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	hw->phy_configured = false;
944*4882a593Smuzhiyun 	hw->preamble_len = 7;
945*4882a593Smuzhiyun 	hw->ipgt = 0x60;
946*4882a593Smuzhiyun 	hw->min_ifg = 0x50;
947*4882a593Smuzhiyun 	hw->ipgr1 = 0x40;
948*4882a593Smuzhiyun 	hw->ipgr2 = 0x60;
949*4882a593Smuzhiyun 	hw->max_retry = 0xf;
950*4882a593Smuzhiyun 	hw->lcol = 0x37;
951*4882a593Smuzhiyun 	hw->jam_ipg = 7;
952*4882a593Smuzhiyun 	hw->rfd_burst = 8;
953*4882a593Smuzhiyun 	hw->rrd_burst = 8;
954*4882a593Smuzhiyun 	hw->rfd_fetch_gap = 1;
955*4882a593Smuzhiyun 	hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
956*4882a593Smuzhiyun 	hw->rx_jumbo_lkah = 1;
957*4882a593Smuzhiyun 	hw->rrd_ret_timer = 16;
958*4882a593Smuzhiyun 	hw->tpd_burst = 4;
959*4882a593Smuzhiyun 	hw->tpd_fetch_th = 16;
960*4882a593Smuzhiyun 	hw->txf_burst = 0x100;
961*4882a593Smuzhiyun 	hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
962*4882a593Smuzhiyun 	hw->tpd_fetch_gap = 1;
963*4882a593Smuzhiyun 	hw->rcb_value = atl1_rcb_64;
964*4882a593Smuzhiyun 	hw->dma_ord = atl1_dma_ord_enh;
965*4882a593Smuzhiyun 	hw->dmar_block = atl1_dma_req_256;
966*4882a593Smuzhiyun 	hw->dmaw_block = atl1_dma_req_256;
967*4882a593Smuzhiyun 	hw->cmb_rrd = 4;
968*4882a593Smuzhiyun 	hw->cmb_tpd = 4;
969*4882a593Smuzhiyun 	hw->cmb_rx_timer = 1;	/* about 2us */
970*4882a593Smuzhiyun 	hw->cmb_tx_timer = 1;	/* about 2us */
971*4882a593Smuzhiyun 	hw->smb_timer = 100000;	/* about 200ms */
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 	spin_lock_init(&adapter->lock);
974*4882a593Smuzhiyun 	spin_lock_init(&adapter->mb_lock);
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	return 0;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun 
mdio_read(struct net_device * netdev,int phy_id,int reg_num)979*4882a593Smuzhiyun static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
982*4882a593Smuzhiyun 	u16 result;
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	return result;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun 
mdio_write(struct net_device * netdev,int phy_id,int reg_num,int val)989*4882a593Smuzhiyun static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
990*4882a593Smuzhiyun 	int val)
991*4882a593Smuzhiyun {
992*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 	atl1_write_phy_reg(&adapter->hw, reg_num, val);
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun 
atl1_mii_ioctl(struct net_device * netdev,struct ifreq * ifr,int cmd)997*4882a593Smuzhiyun static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
1000*4882a593Smuzhiyun 	unsigned long flags;
1001*4882a593Smuzhiyun 	int retval;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	if (!netif_running(netdev))
1004*4882a593Smuzhiyun 		return -EINVAL;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	spin_lock_irqsave(&adapter->lock, flags);
1007*4882a593Smuzhiyun 	retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
1008*4882a593Smuzhiyun 	spin_unlock_irqrestore(&adapter->lock, flags);
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	return retval;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun /**
1014*4882a593Smuzhiyun  * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
1015*4882a593Smuzhiyun  * @adapter: board private structure
1016*4882a593Smuzhiyun  *
1017*4882a593Smuzhiyun  * Return 0 on success, negative on failure
1018*4882a593Smuzhiyun  */
atl1_setup_ring_resources(struct atl1_adapter * adapter)1019*4882a593Smuzhiyun static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
1022*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1023*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
1024*4882a593Smuzhiyun 	struct atl1_ring_header *ring_header = &adapter->ring_header;
1025*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1026*4882a593Smuzhiyun 	int size;
1027*4882a593Smuzhiyun 	u8 offset = 0;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
1030*4882a593Smuzhiyun 	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
1031*4882a593Smuzhiyun 	if (unlikely(!tpd_ring->buffer_info)) {
1032*4882a593Smuzhiyun 		if (netif_msg_drv(adapter))
1033*4882a593Smuzhiyun 			dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
1034*4882a593Smuzhiyun 				size);
1035*4882a593Smuzhiyun 		goto err_nomem;
1036*4882a593Smuzhiyun 	}
1037*4882a593Smuzhiyun 	rfd_ring->buffer_info =
1038*4882a593Smuzhiyun 		(tpd_ring->buffer_info + tpd_ring->count);
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	/*
1041*4882a593Smuzhiyun 	 * real ring DMA buffer
1042*4882a593Smuzhiyun 	 * each ring/block may need up to 8 bytes for alignment, hence the
1043*4882a593Smuzhiyun 	 * additional 40 bytes tacked onto the end.
1044*4882a593Smuzhiyun 	 */
1045*4882a593Smuzhiyun 	ring_header->size =
1046*4882a593Smuzhiyun 		sizeof(struct tx_packet_desc) * tpd_ring->count
1047*4882a593Smuzhiyun 		+ sizeof(struct rx_free_desc) * rfd_ring->count
1048*4882a593Smuzhiyun 		+ sizeof(struct rx_return_desc) * rrd_ring->count
1049*4882a593Smuzhiyun 		+ sizeof(struct coals_msg_block)
1050*4882a593Smuzhiyun 		+ sizeof(struct stats_msg_block)
1051*4882a593Smuzhiyun 		+ 40;
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	ring_header->desc = dma_alloc_coherent(&pdev->dev, ring_header->size,
1054*4882a593Smuzhiyun 					       &ring_header->dma, GFP_KERNEL);
1055*4882a593Smuzhiyun 	if (unlikely(!ring_header->desc)) {
1056*4882a593Smuzhiyun 		if (netif_msg_drv(adapter))
1057*4882a593Smuzhiyun 			dev_err(&pdev->dev, "dma_alloc_coherent failed\n");
1058*4882a593Smuzhiyun 		goto err_nomem;
1059*4882a593Smuzhiyun 	}
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	/* init TPD ring */
1062*4882a593Smuzhiyun 	tpd_ring->dma = ring_header->dma;
1063*4882a593Smuzhiyun 	offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
1064*4882a593Smuzhiyun 	tpd_ring->dma += offset;
1065*4882a593Smuzhiyun 	tpd_ring->desc = (u8 *) ring_header->desc + offset;
1066*4882a593Smuzhiyun 	tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	/* init RFD ring */
1069*4882a593Smuzhiyun 	rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
1070*4882a593Smuzhiyun 	offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
1071*4882a593Smuzhiyun 	rfd_ring->dma += offset;
1072*4882a593Smuzhiyun 	rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
1073*4882a593Smuzhiyun 	rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 	/* init RRD ring */
1077*4882a593Smuzhiyun 	rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
1078*4882a593Smuzhiyun 	offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
1079*4882a593Smuzhiyun 	rrd_ring->dma += offset;
1080*4882a593Smuzhiyun 	rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
1081*4882a593Smuzhiyun 	rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun 	/* init CMB */
1085*4882a593Smuzhiyun 	adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
1086*4882a593Smuzhiyun 	offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
1087*4882a593Smuzhiyun 	adapter->cmb.dma += offset;
1088*4882a593Smuzhiyun 	adapter->cmb.cmb = (struct coals_msg_block *)
1089*4882a593Smuzhiyun 		((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	/* init SMB */
1092*4882a593Smuzhiyun 	adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
1093*4882a593Smuzhiyun 	offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
1094*4882a593Smuzhiyun 	adapter->smb.dma += offset;
1095*4882a593Smuzhiyun 	adapter->smb.smb = (struct stats_msg_block *)
1096*4882a593Smuzhiyun 		((u8 *) adapter->cmb.cmb +
1097*4882a593Smuzhiyun 		(sizeof(struct coals_msg_block) + offset));
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	return 0;
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun err_nomem:
1102*4882a593Smuzhiyun 	kfree(tpd_ring->buffer_info);
1103*4882a593Smuzhiyun 	return -ENOMEM;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
atl1_init_ring_ptrs(struct atl1_adapter * adapter)1106*4882a593Smuzhiyun static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
1109*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1110*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_use, 0);
1113*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_clean, 0);
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	rfd_ring->next_to_clean = 0;
1116*4882a593Smuzhiyun 	atomic_set(&rfd_ring->next_to_use, 0);
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 	rrd_ring->next_to_use = 0;
1119*4882a593Smuzhiyun 	atomic_set(&rrd_ring->next_to_clean, 0);
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun /**
1123*4882a593Smuzhiyun  * atl1_clean_rx_ring - Free RFD Buffers
1124*4882a593Smuzhiyun  * @adapter: board private structure
1125*4882a593Smuzhiyun  */
atl1_clean_rx_ring(struct atl1_adapter * adapter)1126*4882a593Smuzhiyun static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1129*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
1130*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
1131*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1132*4882a593Smuzhiyun 	unsigned long size;
1133*4882a593Smuzhiyun 	unsigned int i;
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	/* Free all the Rx ring sk_buffs */
1136*4882a593Smuzhiyun 	for (i = 0; i < rfd_ring->count; i++) {
1137*4882a593Smuzhiyun 		buffer_info = &rfd_ring->buffer_info[i];
1138*4882a593Smuzhiyun 		if (buffer_info->dma) {
1139*4882a593Smuzhiyun 			dma_unmap_page(&pdev->dev, buffer_info->dma,
1140*4882a593Smuzhiyun 				       buffer_info->length, DMA_FROM_DEVICE);
1141*4882a593Smuzhiyun 			buffer_info->dma = 0;
1142*4882a593Smuzhiyun 		}
1143*4882a593Smuzhiyun 		if (buffer_info->skb) {
1144*4882a593Smuzhiyun 			dev_kfree_skb(buffer_info->skb);
1145*4882a593Smuzhiyun 			buffer_info->skb = NULL;
1146*4882a593Smuzhiyun 		}
1147*4882a593Smuzhiyun 	}
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 	size = sizeof(struct atl1_buffer) * rfd_ring->count;
1150*4882a593Smuzhiyun 	memset(rfd_ring->buffer_info, 0, size);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	/* Zero out the descriptor ring */
1153*4882a593Smuzhiyun 	memset(rfd_ring->desc, 0, rfd_ring->size);
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 	rfd_ring->next_to_clean = 0;
1156*4882a593Smuzhiyun 	atomic_set(&rfd_ring->next_to_use, 0);
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 	rrd_ring->next_to_use = 0;
1159*4882a593Smuzhiyun 	atomic_set(&rrd_ring->next_to_clean, 0);
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun /**
1163*4882a593Smuzhiyun  * atl1_clean_tx_ring - Free Tx Buffers
1164*4882a593Smuzhiyun  * @adapter: board private structure
1165*4882a593Smuzhiyun  */
atl1_clean_tx_ring(struct atl1_adapter * adapter)1166*4882a593Smuzhiyun static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
1167*4882a593Smuzhiyun {
1168*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
1169*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
1170*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1171*4882a593Smuzhiyun 	unsigned long size;
1172*4882a593Smuzhiyun 	unsigned int i;
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	/* Free all the Tx ring sk_buffs */
1175*4882a593Smuzhiyun 	for (i = 0; i < tpd_ring->count; i++) {
1176*4882a593Smuzhiyun 		buffer_info = &tpd_ring->buffer_info[i];
1177*4882a593Smuzhiyun 		if (buffer_info->dma) {
1178*4882a593Smuzhiyun 			dma_unmap_page(&pdev->dev, buffer_info->dma,
1179*4882a593Smuzhiyun 				       buffer_info->length, DMA_TO_DEVICE);
1180*4882a593Smuzhiyun 			buffer_info->dma = 0;
1181*4882a593Smuzhiyun 		}
1182*4882a593Smuzhiyun 	}
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	for (i = 0; i < tpd_ring->count; i++) {
1185*4882a593Smuzhiyun 		buffer_info = &tpd_ring->buffer_info[i];
1186*4882a593Smuzhiyun 		if (buffer_info->skb) {
1187*4882a593Smuzhiyun 			dev_kfree_skb_any(buffer_info->skb);
1188*4882a593Smuzhiyun 			buffer_info->skb = NULL;
1189*4882a593Smuzhiyun 		}
1190*4882a593Smuzhiyun 	}
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	size = sizeof(struct atl1_buffer) * tpd_ring->count;
1193*4882a593Smuzhiyun 	memset(tpd_ring->buffer_info, 0, size);
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	/* Zero out the descriptor ring */
1196*4882a593Smuzhiyun 	memset(tpd_ring->desc, 0, tpd_ring->size);
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_use, 0);
1199*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_clean, 0);
1200*4882a593Smuzhiyun }
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun /**
1203*4882a593Smuzhiyun  * atl1_free_ring_resources - Free Tx / RX descriptor Resources
1204*4882a593Smuzhiyun  * @adapter: board private structure
1205*4882a593Smuzhiyun  *
1206*4882a593Smuzhiyun  * Free all transmit software resources
1207*4882a593Smuzhiyun  */
atl1_free_ring_resources(struct atl1_adapter * adapter)1208*4882a593Smuzhiyun static void atl1_free_ring_resources(struct atl1_adapter *adapter)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1211*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
1212*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1213*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
1214*4882a593Smuzhiyun 	struct atl1_ring_header *ring_header = &adapter->ring_header;
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 	atl1_clean_tx_ring(adapter);
1217*4882a593Smuzhiyun 	atl1_clean_rx_ring(adapter);
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun 	kfree(tpd_ring->buffer_info);
1220*4882a593Smuzhiyun 	dma_free_coherent(&pdev->dev, ring_header->size, ring_header->desc,
1221*4882a593Smuzhiyun 			  ring_header->dma);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	tpd_ring->buffer_info = NULL;
1224*4882a593Smuzhiyun 	tpd_ring->desc = NULL;
1225*4882a593Smuzhiyun 	tpd_ring->dma = 0;
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun 	rfd_ring->buffer_info = NULL;
1228*4882a593Smuzhiyun 	rfd_ring->desc = NULL;
1229*4882a593Smuzhiyun 	rfd_ring->dma = 0;
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	rrd_ring->desc = NULL;
1232*4882a593Smuzhiyun 	rrd_ring->dma = 0;
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	adapter->cmb.dma = 0;
1235*4882a593Smuzhiyun 	adapter->cmb.cmb = NULL;
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	adapter->smb.dma = 0;
1238*4882a593Smuzhiyun 	adapter->smb.smb = NULL;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun 
atl1_setup_mac_ctrl(struct atl1_adapter * adapter)1241*4882a593Smuzhiyun static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun 	u32 value;
1244*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
1245*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
1246*4882a593Smuzhiyun 	/* Config MAC CTRL Register */
1247*4882a593Smuzhiyun 	value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
1248*4882a593Smuzhiyun 	/* duplex */
1249*4882a593Smuzhiyun 	if (FULL_DUPLEX == adapter->link_duplex)
1250*4882a593Smuzhiyun 		value |= MAC_CTRL_DUPLX;
1251*4882a593Smuzhiyun 	/* speed */
1252*4882a593Smuzhiyun 	value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
1253*4882a593Smuzhiyun 			 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
1254*4882a593Smuzhiyun 		  MAC_CTRL_SPEED_SHIFT);
1255*4882a593Smuzhiyun 	/* flow control */
1256*4882a593Smuzhiyun 	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
1257*4882a593Smuzhiyun 	/* PAD & CRC */
1258*4882a593Smuzhiyun 	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
1259*4882a593Smuzhiyun 	/* preamble length */
1260*4882a593Smuzhiyun 	value |= (((u32) adapter->hw.preamble_len
1261*4882a593Smuzhiyun 		   & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
1262*4882a593Smuzhiyun 	/* vlan */
1263*4882a593Smuzhiyun 	__atlx_vlan_mode(netdev->features, &value);
1264*4882a593Smuzhiyun 	/* rx checksum
1265*4882a593Smuzhiyun 	   if (adapter->rx_csum)
1266*4882a593Smuzhiyun 	   value |= MAC_CTRL_RX_CHKSUM_EN;
1267*4882a593Smuzhiyun 	 */
1268*4882a593Smuzhiyun 	/* filter mode */
1269*4882a593Smuzhiyun 	value |= MAC_CTRL_BC_EN;
1270*4882a593Smuzhiyun 	if (netdev->flags & IFF_PROMISC)
1271*4882a593Smuzhiyun 		value |= MAC_CTRL_PROMIS_EN;
1272*4882a593Smuzhiyun 	else if (netdev->flags & IFF_ALLMULTI)
1273*4882a593Smuzhiyun 		value |= MAC_CTRL_MC_ALL_EN;
1274*4882a593Smuzhiyun 	/* value |= MAC_CTRL_LOOPBACK; */
1275*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun 
atl1_check_link(struct atl1_adapter * adapter)1278*4882a593Smuzhiyun static u32 atl1_check_link(struct atl1_adapter *adapter)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
1281*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
1282*4882a593Smuzhiyun 	u32 ret_val;
1283*4882a593Smuzhiyun 	u16 speed, duplex, phy_data;
1284*4882a593Smuzhiyun 	int reconfig = 0;
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	/* MII_BMSR must read twice */
1287*4882a593Smuzhiyun 	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
1288*4882a593Smuzhiyun 	atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
1289*4882a593Smuzhiyun 	if (!(phy_data & BMSR_LSTATUS)) {
1290*4882a593Smuzhiyun 		/* link down */
1291*4882a593Smuzhiyun 		if (netif_carrier_ok(netdev)) {
1292*4882a593Smuzhiyun 			/* old link state: Up */
1293*4882a593Smuzhiyun 			if (netif_msg_link(adapter))
1294*4882a593Smuzhiyun 				dev_info(&adapter->pdev->dev, "link is down\n");
1295*4882a593Smuzhiyun 			adapter->link_speed = SPEED_0;
1296*4882a593Smuzhiyun 			netif_carrier_off(netdev);
1297*4882a593Smuzhiyun 		}
1298*4882a593Smuzhiyun 		return 0;
1299*4882a593Smuzhiyun 	}
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	/* Link Up */
1302*4882a593Smuzhiyun 	ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
1303*4882a593Smuzhiyun 	if (ret_val)
1304*4882a593Smuzhiyun 		return ret_val;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	switch (hw->media_type) {
1307*4882a593Smuzhiyun 	case MEDIA_TYPE_1000M_FULL:
1308*4882a593Smuzhiyun 		if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
1309*4882a593Smuzhiyun 			reconfig = 1;
1310*4882a593Smuzhiyun 		break;
1311*4882a593Smuzhiyun 	case MEDIA_TYPE_100M_FULL:
1312*4882a593Smuzhiyun 		if (speed != SPEED_100 || duplex != FULL_DUPLEX)
1313*4882a593Smuzhiyun 			reconfig = 1;
1314*4882a593Smuzhiyun 		break;
1315*4882a593Smuzhiyun 	case MEDIA_TYPE_100M_HALF:
1316*4882a593Smuzhiyun 		if (speed != SPEED_100 || duplex != HALF_DUPLEX)
1317*4882a593Smuzhiyun 			reconfig = 1;
1318*4882a593Smuzhiyun 		break;
1319*4882a593Smuzhiyun 	case MEDIA_TYPE_10M_FULL:
1320*4882a593Smuzhiyun 		if (speed != SPEED_10 || duplex != FULL_DUPLEX)
1321*4882a593Smuzhiyun 			reconfig = 1;
1322*4882a593Smuzhiyun 		break;
1323*4882a593Smuzhiyun 	case MEDIA_TYPE_10M_HALF:
1324*4882a593Smuzhiyun 		if (speed != SPEED_10 || duplex != HALF_DUPLEX)
1325*4882a593Smuzhiyun 			reconfig = 1;
1326*4882a593Smuzhiyun 		break;
1327*4882a593Smuzhiyun 	}
1328*4882a593Smuzhiyun 
1329*4882a593Smuzhiyun 	/* link result is our setting */
1330*4882a593Smuzhiyun 	if (!reconfig) {
1331*4882a593Smuzhiyun 		if (adapter->link_speed != speed ||
1332*4882a593Smuzhiyun 		    adapter->link_duplex != duplex) {
1333*4882a593Smuzhiyun 			adapter->link_speed = speed;
1334*4882a593Smuzhiyun 			adapter->link_duplex = duplex;
1335*4882a593Smuzhiyun 			atl1_setup_mac_ctrl(adapter);
1336*4882a593Smuzhiyun 			if (netif_msg_link(adapter))
1337*4882a593Smuzhiyun 				dev_info(&adapter->pdev->dev,
1338*4882a593Smuzhiyun 					"%s link is up %d Mbps %s\n",
1339*4882a593Smuzhiyun 					netdev->name, adapter->link_speed,
1340*4882a593Smuzhiyun 					adapter->link_duplex == FULL_DUPLEX ?
1341*4882a593Smuzhiyun 					"full duplex" : "half duplex");
1342*4882a593Smuzhiyun 		}
1343*4882a593Smuzhiyun 		if (!netif_carrier_ok(netdev)) {
1344*4882a593Smuzhiyun 			/* Link down -> Up */
1345*4882a593Smuzhiyun 			netif_carrier_on(netdev);
1346*4882a593Smuzhiyun 		}
1347*4882a593Smuzhiyun 		return 0;
1348*4882a593Smuzhiyun 	}
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun 	/* change original link status */
1351*4882a593Smuzhiyun 	if (netif_carrier_ok(netdev)) {
1352*4882a593Smuzhiyun 		adapter->link_speed = SPEED_0;
1353*4882a593Smuzhiyun 		netif_carrier_off(netdev);
1354*4882a593Smuzhiyun 		netif_stop_queue(netdev);
1355*4882a593Smuzhiyun 	}
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun 	if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
1358*4882a593Smuzhiyun 	    hw->media_type != MEDIA_TYPE_1000M_FULL) {
1359*4882a593Smuzhiyun 		switch (hw->media_type) {
1360*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_FULL:
1361*4882a593Smuzhiyun 			phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
1362*4882a593Smuzhiyun 			           MII_CR_RESET;
1363*4882a593Smuzhiyun 			break;
1364*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_HALF:
1365*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
1366*4882a593Smuzhiyun 			break;
1367*4882a593Smuzhiyun 		case MEDIA_TYPE_10M_FULL:
1368*4882a593Smuzhiyun 			phy_data =
1369*4882a593Smuzhiyun 			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
1370*4882a593Smuzhiyun 			break;
1371*4882a593Smuzhiyun 		default:
1372*4882a593Smuzhiyun 			/* MEDIA_TYPE_10M_HALF: */
1373*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
1374*4882a593Smuzhiyun 			break;
1375*4882a593Smuzhiyun 		}
1376*4882a593Smuzhiyun 		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
1377*4882a593Smuzhiyun 		return 0;
1378*4882a593Smuzhiyun 	}
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 	/* auto-neg, insert timer to re-config phy */
1381*4882a593Smuzhiyun 	if (!adapter->phy_timer_pending) {
1382*4882a593Smuzhiyun 		adapter->phy_timer_pending = true;
1383*4882a593Smuzhiyun 		mod_timer(&adapter->phy_config_timer,
1384*4882a593Smuzhiyun 			  round_jiffies(jiffies + 3 * HZ));
1385*4882a593Smuzhiyun 	}
1386*4882a593Smuzhiyun 
1387*4882a593Smuzhiyun 	return 0;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun 
set_flow_ctrl_old(struct atl1_adapter * adapter)1390*4882a593Smuzhiyun static void set_flow_ctrl_old(struct atl1_adapter *adapter)
1391*4882a593Smuzhiyun {
1392*4882a593Smuzhiyun 	u32 hi, lo, value;
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun 	/* RFD Flow Control */
1395*4882a593Smuzhiyun 	value = adapter->rfd_ring.count;
1396*4882a593Smuzhiyun 	hi = value / 16;
1397*4882a593Smuzhiyun 	if (hi < 2)
1398*4882a593Smuzhiyun 		hi = 2;
1399*4882a593Smuzhiyun 	lo = value * 7 / 8;
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun 	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
1402*4882a593Smuzhiyun 		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
1403*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun 	/* RRD Flow Control */
1406*4882a593Smuzhiyun 	value = adapter->rrd_ring.count;
1407*4882a593Smuzhiyun 	lo = value / 16;
1408*4882a593Smuzhiyun 	hi = value * 7 / 8;
1409*4882a593Smuzhiyun 	if (lo < 2)
1410*4882a593Smuzhiyun 		lo = 2;
1411*4882a593Smuzhiyun 	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
1412*4882a593Smuzhiyun 		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
1413*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun 
set_flow_ctrl_new(struct atl1_hw * hw)1416*4882a593Smuzhiyun static void set_flow_ctrl_new(struct atl1_hw *hw)
1417*4882a593Smuzhiyun {
1418*4882a593Smuzhiyun 	u32 hi, lo, value;
1419*4882a593Smuzhiyun 
1420*4882a593Smuzhiyun 	/* RXF Flow Control */
1421*4882a593Smuzhiyun 	value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
1422*4882a593Smuzhiyun 	lo = value / 16;
1423*4882a593Smuzhiyun 	if (lo < 192)
1424*4882a593Smuzhiyun 		lo = 192;
1425*4882a593Smuzhiyun 	hi = value * 7 / 8;
1426*4882a593Smuzhiyun 	if (hi < lo)
1427*4882a593Smuzhiyun 		hi = lo + 16;
1428*4882a593Smuzhiyun 	value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
1429*4882a593Smuzhiyun 		((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
1430*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
1431*4882a593Smuzhiyun 
1432*4882a593Smuzhiyun 	/* RRD Flow Control */
1433*4882a593Smuzhiyun 	value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
1434*4882a593Smuzhiyun 	lo = value / 8;
1435*4882a593Smuzhiyun 	hi = value * 7 / 8;
1436*4882a593Smuzhiyun 	if (lo < 2)
1437*4882a593Smuzhiyun 		lo = 2;
1438*4882a593Smuzhiyun 	if (hi < lo)
1439*4882a593Smuzhiyun 		hi = lo + 3;
1440*4882a593Smuzhiyun 	value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
1441*4882a593Smuzhiyun 		((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
1442*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun 
1445*4882a593Smuzhiyun /**
1446*4882a593Smuzhiyun  * atl1_configure - Configure Transmit&Receive Unit after Reset
1447*4882a593Smuzhiyun  * @adapter: board private structure
1448*4882a593Smuzhiyun  *
1449*4882a593Smuzhiyun  * Configure the Tx /Rx unit of the MAC after a reset.
1450*4882a593Smuzhiyun  */
atl1_configure(struct atl1_adapter * adapter)1451*4882a593Smuzhiyun static u32 atl1_configure(struct atl1_adapter *adapter)
1452*4882a593Smuzhiyun {
1453*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
1454*4882a593Smuzhiyun 	u32 value;
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun 	/* clear interrupt status */
1457*4882a593Smuzhiyun 	iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
1458*4882a593Smuzhiyun 
1459*4882a593Smuzhiyun 	/* set MAC Address */
1460*4882a593Smuzhiyun 	value = (((u32) hw->mac_addr[2]) << 24) |
1461*4882a593Smuzhiyun 		(((u32) hw->mac_addr[3]) << 16) |
1462*4882a593Smuzhiyun 		(((u32) hw->mac_addr[4]) << 8) |
1463*4882a593Smuzhiyun 		(((u32) hw->mac_addr[5]));
1464*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
1465*4882a593Smuzhiyun 	value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
1466*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
1467*4882a593Smuzhiyun 
1468*4882a593Smuzhiyun 	/* tx / rx ring */
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 	/* HI base address */
1471*4882a593Smuzhiyun 	iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
1472*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_BASE_ADDR_HI);
1473*4882a593Smuzhiyun 	/* LO base address */
1474*4882a593Smuzhiyun 	iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
1475*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_RFD_ADDR_LO);
1476*4882a593Smuzhiyun 	iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
1477*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_RRD_ADDR_LO);
1478*4882a593Smuzhiyun 	iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
1479*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_TPD_ADDR_LO);
1480*4882a593Smuzhiyun 	iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
1481*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_CMB_ADDR_LO);
1482*4882a593Smuzhiyun 	iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
1483*4882a593Smuzhiyun 		hw->hw_addr + REG_DESC_SMB_ADDR_LO);
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun 	/* element count */
1486*4882a593Smuzhiyun 	value = adapter->rrd_ring.count;
1487*4882a593Smuzhiyun 	value <<= 16;
1488*4882a593Smuzhiyun 	value += adapter->rfd_ring.count;
1489*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
1490*4882a593Smuzhiyun 	iowrite32(adapter->tpd_ring.count, hw->hw_addr +
1491*4882a593Smuzhiyun 		REG_DESC_TPD_RING_SIZE);
1492*4882a593Smuzhiyun 
1493*4882a593Smuzhiyun 	/* Load Ptr */
1494*4882a593Smuzhiyun 	iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
1495*4882a593Smuzhiyun 
1496*4882a593Smuzhiyun 	/* config Mailbox */
1497*4882a593Smuzhiyun 	value = ((atomic_read(&adapter->tpd_ring.next_to_use)
1498*4882a593Smuzhiyun 		  & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
1499*4882a593Smuzhiyun 		((atomic_read(&adapter->rrd_ring.next_to_clean)
1500*4882a593Smuzhiyun 		& MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
1501*4882a593Smuzhiyun 		((atomic_read(&adapter->rfd_ring.next_to_use)
1502*4882a593Smuzhiyun 		& MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
1503*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAILBOX);
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	/* config IPG/IFG */
1506*4882a593Smuzhiyun 	value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
1507*4882a593Smuzhiyun 		 << MAC_IPG_IFG_IPGT_SHIFT) |
1508*4882a593Smuzhiyun 		(((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
1509*4882a593Smuzhiyun 		<< MAC_IPG_IFG_MIFG_SHIFT) |
1510*4882a593Smuzhiyun 		(((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
1511*4882a593Smuzhiyun 		<< MAC_IPG_IFG_IPGR1_SHIFT) |
1512*4882a593Smuzhiyun 		(((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
1513*4882a593Smuzhiyun 		<< MAC_IPG_IFG_IPGR2_SHIFT);
1514*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
1515*4882a593Smuzhiyun 
1516*4882a593Smuzhiyun 	/* config  Half-Duplex Control */
1517*4882a593Smuzhiyun 	value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
1518*4882a593Smuzhiyun 		(((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
1519*4882a593Smuzhiyun 		<< MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
1520*4882a593Smuzhiyun 		MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
1521*4882a593Smuzhiyun 		(0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
1522*4882a593Smuzhiyun 		(((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
1523*4882a593Smuzhiyun 		<< MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
1524*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
1525*4882a593Smuzhiyun 
1526*4882a593Smuzhiyun 	/* set Interrupt Moderator Timer */
1527*4882a593Smuzhiyun 	iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
1528*4882a593Smuzhiyun 	iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun 	/* set Interrupt Clear Timer */
1531*4882a593Smuzhiyun 	iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun 	/* set max frame size hw will accept */
1534*4882a593Smuzhiyun 	iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
1535*4882a593Smuzhiyun 
1536*4882a593Smuzhiyun 	/* jumbo size & rrd retirement timer */
1537*4882a593Smuzhiyun 	value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
1538*4882a593Smuzhiyun 		 << RXQ_JMBOSZ_TH_SHIFT) |
1539*4882a593Smuzhiyun 		(((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
1540*4882a593Smuzhiyun 		<< RXQ_JMBO_LKAH_SHIFT) |
1541*4882a593Smuzhiyun 		(((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
1542*4882a593Smuzhiyun 		<< RXQ_RRD_TIMER_SHIFT);
1543*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 	/* Flow Control */
1546*4882a593Smuzhiyun 	switch (hw->dev_rev) {
1547*4882a593Smuzhiyun 	case 0x8001:
1548*4882a593Smuzhiyun 	case 0x9001:
1549*4882a593Smuzhiyun 	case 0x9002:
1550*4882a593Smuzhiyun 	case 0x9003:
1551*4882a593Smuzhiyun 		set_flow_ctrl_old(adapter);
1552*4882a593Smuzhiyun 		break;
1553*4882a593Smuzhiyun 	default:
1554*4882a593Smuzhiyun 		set_flow_ctrl_new(hw);
1555*4882a593Smuzhiyun 		break;
1556*4882a593Smuzhiyun 	}
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 	/* config TXQ */
1559*4882a593Smuzhiyun 	value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
1560*4882a593Smuzhiyun 		 << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
1561*4882a593Smuzhiyun 		(((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
1562*4882a593Smuzhiyun 		<< TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
1563*4882a593Smuzhiyun 		(((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
1564*4882a593Smuzhiyun 		<< TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
1565*4882a593Smuzhiyun 		TXQ_CTRL_EN;
1566*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
1567*4882a593Smuzhiyun 
1568*4882a593Smuzhiyun 	/* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
1569*4882a593Smuzhiyun 	value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
1570*4882a593Smuzhiyun 		<< TX_JUMBO_TASK_TH_SHIFT) |
1571*4882a593Smuzhiyun 		(((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
1572*4882a593Smuzhiyun 		<< TX_TPD_MIN_IPG_SHIFT);
1573*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun 	/* config RXQ */
1576*4882a593Smuzhiyun 	value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
1577*4882a593Smuzhiyun 		<< RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
1578*4882a593Smuzhiyun 		(((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
1579*4882a593Smuzhiyun 		<< RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
1580*4882a593Smuzhiyun 		(((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
1581*4882a593Smuzhiyun 		<< RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
1582*4882a593Smuzhiyun 		RXQ_CTRL_EN;
1583*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
1584*4882a593Smuzhiyun 
1585*4882a593Smuzhiyun 	/* config DMA Engine */
1586*4882a593Smuzhiyun 	value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
1587*4882a593Smuzhiyun 		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
1588*4882a593Smuzhiyun 		((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
1589*4882a593Smuzhiyun 		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
1590*4882a593Smuzhiyun 		DMA_CTRL_DMAW_EN;
1591*4882a593Smuzhiyun 	value |= (u32) hw->dma_ord;
1592*4882a593Smuzhiyun 	if (atl1_rcb_128 == hw->rcb_value)
1593*4882a593Smuzhiyun 		value |= DMA_CTRL_RCB_VALUE;
1594*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 	/* config CMB / SMB */
1597*4882a593Smuzhiyun 	value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
1598*4882a593Smuzhiyun 		hw->cmb_tpd : adapter->tpd_ring.count;
1599*4882a593Smuzhiyun 	value <<= 16;
1600*4882a593Smuzhiyun 	value |= hw->cmb_rrd;
1601*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
1602*4882a593Smuzhiyun 	value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
1603*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
1604*4882a593Smuzhiyun 	iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 	/* --- enable CMB / SMB */
1607*4882a593Smuzhiyun 	value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
1608*4882a593Smuzhiyun 	iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun 	value = ioread32(adapter->hw.hw_addr + REG_ISR);
1611*4882a593Smuzhiyun 	if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
1612*4882a593Smuzhiyun 		value = 1;	/* config failed */
1613*4882a593Smuzhiyun 	else
1614*4882a593Smuzhiyun 		value = 0;
1615*4882a593Smuzhiyun 
1616*4882a593Smuzhiyun 	/* clear all interrupt status */
1617*4882a593Smuzhiyun 	iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
1618*4882a593Smuzhiyun 	iowrite32(0, adapter->hw.hw_addr + REG_ISR);
1619*4882a593Smuzhiyun 	return value;
1620*4882a593Smuzhiyun }
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun /*
1623*4882a593Smuzhiyun  * atl1_pcie_patch - Patch for PCIE module
1624*4882a593Smuzhiyun  */
atl1_pcie_patch(struct atl1_adapter * adapter)1625*4882a593Smuzhiyun static void atl1_pcie_patch(struct atl1_adapter *adapter)
1626*4882a593Smuzhiyun {
1627*4882a593Smuzhiyun 	u32 value;
1628*4882a593Smuzhiyun 
1629*4882a593Smuzhiyun 	/* much vendor magic here */
1630*4882a593Smuzhiyun 	value = 0x6500;
1631*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + 0x12FC);
1632*4882a593Smuzhiyun 	/* pcie flow control mode change */
1633*4882a593Smuzhiyun 	value = ioread32(adapter->hw.hw_addr + 0x1008);
1634*4882a593Smuzhiyun 	value |= 0x8000;
1635*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + 0x1008);
1636*4882a593Smuzhiyun }
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun /*
1639*4882a593Smuzhiyun  * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
1640*4882a593Smuzhiyun  * on PCI Command register is disable.
1641*4882a593Smuzhiyun  * The function enable this bit.
1642*4882a593Smuzhiyun  * Brackett, 2006/03/15
1643*4882a593Smuzhiyun  */
atl1_via_workaround(struct atl1_adapter * adapter)1644*4882a593Smuzhiyun static void atl1_via_workaround(struct atl1_adapter *adapter)
1645*4882a593Smuzhiyun {
1646*4882a593Smuzhiyun 	unsigned long value;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
1649*4882a593Smuzhiyun 	if (value & PCI_COMMAND_INTX_DISABLE)
1650*4882a593Smuzhiyun 		value &= ~PCI_COMMAND_INTX_DISABLE;
1651*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
1652*4882a593Smuzhiyun }
1653*4882a593Smuzhiyun 
atl1_inc_smb(struct atl1_adapter * adapter)1654*4882a593Smuzhiyun static void atl1_inc_smb(struct atl1_adapter *adapter)
1655*4882a593Smuzhiyun {
1656*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
1657*4882a593Smuzhiyun 	struct stats_msg_block *smb = adapter->smb.smb;
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun 	u64 new_rx_errors = smb->rx_frag +
1660*4882a593Smuzhiyun 			    smb->rx_fcs_err +
1661*4882a593Smuzhiyun 			    smb->rx_len_err +
1662*4882a593Smuzhiyun 			    smb->rx_sz_ov +
1663*4882a593Smuzhiyun 			    smb->rx_rxf_ov +
1664*4882a593Smuzhiyun 			    smb->rx_rrd_ov +
1665*4882a593Smuzhiyun 			    smb->rx_align_err;
1666*4882a593Smuzhiyun 	u64 new_tx_errors = smb->tx_late_col +
1667*4882a593Smuzhiyun 			    smb->tx_abort_col +
1668*4882a593Smuzhiyun 			    smb->tx_underrun +
1669*4882a593Smuzhiyun 			    smb->tx_trunc;
1670*4882a593Smuzhiyun 
1671*4882a593Smuzhiyun 	/* Fill out the OS statistics structure */
1672*4882a593Smuzhiyun 	adapter->soft_stats.rx_packets += smb->rx_ok + new_rx_errors;
1673*4882a593Smuzhiyun 	adapter->soft_stats.tx_packets += smb->tx_ok + new_tx_errors;
1674*4882a593Smuzhiyun 	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
1675*4882a593Smuzhiyun 	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
1676*4882a593Smuzhiyun 	adapter->soft_stats.multicast += smb->rx_mcast;
1677*4882a593Smuzhiyun 	adapter->soft_stats.collisions += smb->tx_1_col +
1678*4882a593Smuzhiyun 					  smb->tx_2_col +
1679*4882a593Smuzhiyun 					  smb->tx_late_col +
1680*4882a593Smuzhiyun 					  smb->tx_abort_col;
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun 	/* Rx Errors */
1683*4882a593Smuzhiyun 	adapter->soft_stats.rx_errors += new_rx_errors;
1684*4882a593Smuzhiyun 	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
1685*4882a593Smuzhiyun 	adapter->soft_stats.rx_length_errors += smb->rx_len_err;
1686*4882a593Smuzhiyun 	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
1687*4882a593Smuzhiyun 	adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 	adapter->soft_stats.rx_pause += smb->rx_pause;
1690*4882a593Smuzhiyun 	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
1691*4882a593Smuzhiyun 	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
1692*4882a593Smuzhiyun 
1693*4882a593Smuzhiyun 	/* Tx Errors */
1694*4882a593Smuzhiyun 	adapter->soft_stats.tx_errors += new_tx_errors;
1695*4882a593Smuzhiyun 	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
1696*4882a593Smuzhiyun 	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
1697*4882a593Smuzhiyun 	adapter->soft_stats.tx_window_errors += smb->tx_late_col;
1698*4882a593Smuzhiyun 
1699*4882a593Smuzhiyun 	adapter->soft_stats.excecol += smb->tx_abort_col;
1700*4882a593Smuzhiyun 	adapter->soft_stats.deffer += smb->tx_defer;
1701*4882a593Smuzhiyun 	adapter->soft_stats.scc += smb->tx_1_col;
1702*4882a593Smuzhiyun 	adapter->soft_stats.mcc += smb->tx_2_col;
1703*4882a593Smuzhiyun 	adapter->soft_stats.latecol += smb->tx_late_col;
1704*4882a593Smuzhiyun 	adapter->soft_stats.tx_underrun += smb->tx_underrun;
1705*4882a593Smuzhiyun 	adapter->soft_stats.tx_trunc += smb->tx_trunc;
1706*4882a593Smuzhiyun 	adapter->soft_stats.tx_pause += smb->tx_pause;
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun 	netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;
1709*4882a593Smuzhiyun 	netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;
1710*4882a593Smuzhiyun 	netdev->stats.multicast = adapter->soft_stats.multicast;
1711*4882a593Smuzhiyun 	netdev->stats.collisions = adapter->soft_stats.collisions;
1712*4882a593Smuzhiyun 	netdev->stats.rx_errors = adapter->soft_stats.rx_errors;
1713*4882a593Smuzhiyun 	netdev->stats.rx_length_errors =
1714*4882a593Smuzhiyun 		adapter->soft_stats.rx_length_errors;
1715*4882a593Smuzhiyun 	netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
1716*4882a593Smuzhiyun 	netdev->stats.rx_frame_errors =
1717*4882a593Smuzhiyun 		adapter->soft_stats.rx_frame_errors;
1718*4882a593Smuzhiyun 	netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
1719*4882a593Smuzhiyun 	netdev->stats.rx_dropped = adapter->soft_stats.rx_rrd_ov;
1720*4882a593Smuzhiyun 	netdev->stats.tx_errors = adapter->soft_stats.tx_errors;
1721*4882a593Smuzhiyun 	netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
1722*4882a593Smuzhiyun 	netdev->stats.tx_aborted_errors =
1723*4882a593Smuzhiyun 		adapter->soft_stats.tx_aborted_errors;
1724*4882a593Smuzhiyun 	netdev->stats.tx_window_errors =
1725*4882a593Smuzhiyun 		adapter->soft_stats.tx_window_errors;
1726*4882a593Smuzhiyun 	netdev->stats.tx_carrier_errors =
1727*4882a593Smuzhiyun 		adapter->soft_stats.tx_carrier_errors;
1728*4882a593Smuzhiyun 
1729*4882a593Smuzhiyun 	netdev->stats.rx_packets = adapter->soft_stats.rx_packets;
1730*4882a593Smuzhiyun 	netdev->stats.tx_packets = adapter->soft_stats.tx_packets;
1731*4882a593Smuzhiyun }
1732*4882a593Smuzhiyun 
atl1_update_mailbox(struct atl1_adapter * adapter)1733*4882a593Smuzhiyun static void atl1_update_mailbox(struct atl1_adapter *adapter)
1734*4882a593Smuzhiyun {
1735*4882a593Smuzhiyun 	unsigned long flags;
1736*4882a593Smuzhiyun 	u32 tpd_next_to_use;
1737*4882a593Smuzhiyun 	u32 rfd_next_to_use;
1738*4882a593Smuzhiyun 	u32 rrd_next_to_clean;
1739*4882a593Smuzhiyun 	u32 value;
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	spin_lock_irqsave(&adapter->mb_lock, flags);
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun 	tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
1744*4882a593Smuzhiyun 	rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
1745*4882a593Smuzhiyun 	rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
1746*4882a593Smuzhiyun 
1747*4882a593Smuzhiyun 	value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
1748*4882a593Smuzhiyun 		MB_RFD_PROD_INDX_SHIFT) |
1749*4882a593Smuzhiyun 		((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
1750*4882a593Smuzhiyun 		MB_RRD_CONS_INDX_SHIFT) |
1751*4882a593Smuzhiyun 		((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
1752*4882a593Smuzhiyun 		MB_TPD_PROD_INDX_SHIFT);
1753*4882a593Smuzhiyun 	iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun 	spin_unlock_irqrestore(&adapter->mb_lock, flags);
1756*4882a593Smuzhiyun }
1757*4882a593Smuzhiyun 
atl1_clean_alloc_flag(struct atl1_adapter * adapter,struct rx_return_desc * rrd,u16 offset)1758*4882a593Smuzhiyun static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
1759*4882a593Smuzhiyun 	struct rx_return_desc *rrd, u16 offset)
1760*4882a593Smuzhiyun {
1761*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun 	while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
1764*4882a593Smuzhiyun 		rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
1765*4882a593Smuzhiyun 		if (++rfd_ring->next_to_clean == rfd_ring->count) {
1766*4882a593Smuzhiyun 			rfd_ring->next_to_clean = 0;
1767*4882a593Smuzhiyun 		}
1768*4882a593Smuzhiyun 	}
1769*4882a593Smuzhiyun }
1770*4882a593Smuzhiyun 
atl1_update_rfd_index(struct atl1_adapter * adapter,struct rx_return_desc * rrd)1771*4882a593Smuzhiyun static void atl1_update_rfd_index(struct atl1_adapter *adapter,
1772*4882a593Smuzhiyun 	struct rx_return_desc *rrd)
1773*4882a593Smuzhiyun {
1774*4882a593Smuzhiyun 	u16 num_buf;
1775*4882a593Smuzhiyun 
1776*4882a593Smuzhiyun 	num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
1777*4882a593Smuzhiyun 		adapter->rx_buffer_len;
1778*4882a593Smuzhiyun 	if (rrd->num_buf == num_buf)
1779*4882a593Smuzhiyun 		/* clean alloc flag for bad rrd */
1780*4882a593Smuzhiyun 		atl1_clean_alloc_flag(adapter, rrd, num_buf);
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun 
atl1_rx_checksum(struct atl1_adapter * adapter,struct rx_return_desc * rrd,struct sk_buff * skb)1783*4882a593Smuzhiyun static void atl1_rx_checksum(struct atl1_adapter *adapter,
1784*4882a593Smuzhiyun 	struct rx_return_desc *rrd, struct sk_buff *skb)
1785*4882a593Smuzhiyun {
1786*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun 	/*
1789*4882a593Smuzhiyun 	 * The L1 hardware contains a bug that erroneously sets the
1790*4882a593Smuzhiyun 	 * PACKET_FLAG_ERR and ERR_FLAG_L4_CHKSUM bits whenever a
1791*4882a593Smuzhiyun 	 * fragmented IP packet is received, even though the packet
1792*4882a593Smuzhiyun 	 * is perfectly valid and its checksum is correct. There's
1793*4882a593Smuzhiyun 	 * no way to distinguish between one of these good packets
1794*4882a593Smuzhiyun 	 * and a packet that actually contains a TCP/UDP checksum
1795*4882a593Smuzhiyun 	 * error, so all we can do is allow it to be handed up to
1796*4882a593Smuzhiyun 	 * the higher layers and let it be sorted out there.
1797*4882a593Smuzhiyun 	 */
1798*4882a593Smuzhiyun 
1799*4882a593Smuzhiyun 	skb_checksum_none_assert(skb);
1800*4882a593Smuzhiyun 
1801*4882a593Smuzhiyun 	if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
1802*4882a593Smuzhiyun 		if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
1803*4882a593Smuzhiyun 					ERR_FLAG_CODE | ERR_FLAG_OV)) {
1804*4882a593Smuzhiyun 			adapter->hw_csum_err++;
1805*4882a593Smuzhiyun 			if (netif_msg_rx_err(adapter))
1806*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &pdev->dev,
1807*4882a593Smuzhiyun 					"rx checksum error\n");
1808*4882a593Smuzhiyun 			return;
1809*4882a593Smuzhiyun 		}
1810*4882a593Smuzhiyun 	}
1811*4882a593Smuzhiyun 
1812*4882a593Smuzhiyun 	/* not IPv4 */
1813*4882a593Smuzhiyun 	if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
1814*4882a593Smuzhiyun 		/* checksum is invalid, but it's not an IPv4 pkt, so ok */
1815*4882a593Smuzhiyun 		return;
1816*4882a593Smuzhiyun 
1817*4882a593Smuzhiyun 	/* IPv4 packet */
1818*4882a593Smuzhiyun 	if (likely(!(rrd->err_flg &
1819*4882a593Smuzhiyun 		(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
1820*4882a593Smuzhiyun 		skb->ip_summed = CHECKSUM_UNNECESSARY;
1821*4882a593Smuzhiyun 		adapter->hw_csum_good++;
1822*4882a593Smuzhiyun 		return;
1823*4882a593Smuzhiyun 	}
1824*4882a593Smuzhiyun }
1825*4882a593Smuzhiyun 
1826*4882a593Smuzhiyun /**
1827*4882a593Smuzhiyun  * atl1_alloc_rx_buffers - Replace used receive buffers
1828*4882a593Smuzhiyun  * @adapter: address of board private structure
1829*4882a593Smuzhiyun  */
atl1_alloc_rx_buffers(struct atl1_adapter * adapter)1830*4882a593Smuzhiyun static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
1831*4882a593Smuzhiyun {
1832*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1833*4882a593Smuzhiyun 	struct pci_dev *pdev = adapter->pdev;
1834*4882a593Smuzhiyun 	struct page *page;
1835*4882a593Smuzhiyun 	unsigned long offset;
1836*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info, *next_info;
1837*4882a593Smuzhiyun 	struct sk_buff *skb;
1838*4882a593Smuzhiyun 	u16 num_alloc = 0;
1839*4882a593Smuzhiyun 	u16 rfd_next_to_use, next_next;
1840*4882a593Smuzhiyun 	struct rx_free_desc *rfd_desc;
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun 	next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
1843*4882a593Smuzhiyun 	if (++next_next == rfd_ring->count)
1844*4882a593Smuzhiyun 		next_next = 0;
1845*4882a593Smuzhiyun 	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
1846*4882a593Smuzhiyun 	next_info = &rfd_ring->buffer_info[next_next];
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun 	while (!buffer_info->alloced && !next_info->alloced) {
1849*4882a593Smuzhiyun 		if (buffer_info->skb) {
1850*4882a593Smuzhiyun 			buffer_info->alloced = 1;
1851*4882a593Smuzhiyun 			goto next;
1852*4882a593Smuzhiyun 		}
1853*4882a593Smuzhiyun 
1854*4882a593Smuzhiyun 		rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
1855*4882a593Smuzhiyun 
1856*4882a593Smuzhiyun 		skb = netdev_alloc_skb_ip_align(adapter->netdev,
1857*4882a593Smuzhiyun 						adapter->rx_buffer_len);
1858*4882a593Smuzhiyun 		if (unlikely(!skb)) {
1859*4882a593Smuzhiyun 			/* Better luck next round */
1860*4882a593Smuzhiyun 			adapter->soft_stats.rx_dropped++;
1861*4882a593Smuzhiyun 			break;
1862*4882a593Smuzhiyun 		}
1863*4882a593Smuzhiyun 
1864*4882a593Smuzhiyun 		buffer_info->alloced = 1;
1865*4882a593Smuzhiyun 		buffer_info->skb = skb;
1866*4882a593Smuzhiyun 		buffer_info->length = (u16) adapter->rx_buffer_len;
1867*4882a593Smuzhiyun 		page = virt_to_page(skb->data);
1868*4882a593Smuzhiyun 		offset = offset_in_page(skb->data);
1869*4882a593Smuzhiyun 		buffer_info->dma = dma_map_page(&pdev->dev, page, offset,
1870*4882a593Smuzhiyun 						adapter->rx_buffer_len,
1871*4882a593Smuzhiyun 						DMA_FROM_DEVICE);
1872*4882a593Smuzhiyun 		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
1873*4882a593Smuzhiyun 		rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
1874*4882a593Smuzhiyun 		rfd_desc->coalese = 0;
1875*4882a593Smuzhiyun 
1876*4882a593Smuzhiyun next:
1877*4882a593Smuzhiyun 		rfd_next_to_use = next_next;
1878*4882a593Smuzhiyun 		if (unlikely(++next_next == rfd_ring->count))
1879*4882a593Smuzhiyun 			next_next = 0;
1880*4882a593Smuzhiyun 
1881*4882a593Smuzhiyun 		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
1882*4882a593Smuzhiyun 		next_info = &rfd_ring->buffer_info[next_next];
1883*4882a593Smuzhiyun 		num_alloc++;
1884*4882a593Smuzhiyun 	}
1885*4882a593Smuzhiyun 
1886*4882a593Smuzhiyun 	if (num_alloc) {
1887*4882a593Smuzhiyun 		/*
1888*4882a593Smuzhiyun 		 * Force memory writes to complete before letting h/w
1889*4882a593Smuzhiyun 		 * know there are new descriptors to fetch.  (Only
1890*4882a593Smuzhiyun 		 * applicable for weak-ordered memory model archs,
1891*4882a593Smuzhiyun 		 * such as IA-64).
1892*4882a593Smuzhiyun 		 */
1893*4882a593Smuzhiyun 		wmb();
1894*4882a593Smuzhiyun 		atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
1895*4882a593Smuzhiyun 	}
1896*4882a593Smuzhiyun 	return num_alloc;
1897*4882a593Smuzhiyun }
1898*4882a593Smuzhiyun 
atl1_intr_rx(struct atl1_adapter * adapter,int budget)1899*4882a593Smuzhiyun static int atl1_intr_rx(struct atl1_adapter *adapter, int budget)
1900*4882a593Smuzhiyun {
1901*4882a593Smuzhiyun 	int i, count;
1902*4882a593Smuzhiyun 	u16 length;
1903*4882a593Smuzhiyun 	u16 rrd_next_to_clean;
1904*4882a593Smuzhiyun 	u32 value;
1905*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
1906*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
1907*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
1908*4882a593Smuzhiyun 	struct rx_return_desc *rrd;
1909*4882a593Smuzhiyun 	struct sk_buff *skb;
1910*4882a593Smuzhiyun 
1911*4882a593Smuzhiyun 	count = 0;
1912*4882a593Smuzhiyun 
1913*4882a593Smuzhiyun 	rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
1914*4882a593Smuzhiyun 
1915*4882a593Smuzhiyun 	while (count < budget) {
1916*4882a593Smuzhiyun 		rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
1917*4882a593Smuzhiyun 		i = 1;
1918*4882a593Smuzhiyun 		if (likely(rrd->xsz.valid)) {	/* packet valid */
1919*4882a593Smuzhiyun chk_rrd:
1920*4882a593Smuzhiyun 			/* check rrd status */
1921*4882a593Smuzhiyun 			if (likely(rrd->num_buf == 1))
1922*4882a593Smuzhiyun 				goto rrd_ok;
1923*4882a593Smuzhiyun 			else if (netif_msg_rx_err(adapter)) {
1924*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1925*4882a593Smuzhiyun 					"unexpected RRD buffer count\n");
1926*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1927*4882a593Smuzhiyun 					"rx_buf_len = %d\n",
1928*4882a593Smuzhiyun 					adapter->rx_buffer_len);
1929*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1930*4882a593Smuzhiyun 					"RRD num_buf = %d\n",
1931*4882a593Smuzhiyun 					rrd->num_buf);
1932*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1933*4882a593Smuzhiyun 					"RRD pkt_len = %d\n",
1934*4882a593Smuzhiyun 					rrd->xsz.xsum_sz.pkt_size);
1935*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1936*4882a593Smuzhiyun 					"RRD pkt_flg = 0x%08X\n",
1937*4882a593Smuzhiyun 					rrd->pkt_flg);
1938*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1939*4882a593Smuzhiyun 					"RRD err_flg = 0x%08X\n",
1940*4882a593Smuzhiyun 					rrd->err_flg);
1941*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1942*4882a593Smuzhiyun 					"RRD vlan_tag = 0x%08X\n",
1943*4882a593Smuzhiyun 					rrd->vlan_tag);
1944*4882a593Smuzhiyun 			}
1945*4882a593Smuzhiyun 
1946*4882a593Smuzhiyun 			/* rrd seems to be bad */
1947*4882a593Smuzhiyun 			if (unlikely(i-- > 0)) {
1948*4882a593Smuzhiyun 				/* rrd may not be DMAed completely */
1949*4882a593Smuzhiyun 				udelay(1);
1950*4882a593Smuzhiyun 				goto chk_rrd;
1951*4882a593Smuzhiyun 			}
1952*4882a593Smuzhiyun 			/* bad rrd */
1953*4882a593Smuzhiyun 			if (netif_msg_rx_err(adapter))
1954*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
1955*4882a593Smuzhiyun 					"bad RRD\n");
1956*4882a593Smuzhiyun 			/* see if update RFD index */
1957*4882a593Smuzhiyun 			if (rrd->num_buf > 1)
1958*4882a593Smuzhiyun 				atl1_update_rfd_index(adapter, rrd);
1959*4882a593Smuzhiyun 
1960*4882a593Smuzhiyun 			/* update rrd */
1961*4882a593Smuzhiyun 			rrd->xsz.valid = 0;
1962*4882a593Smuzhiyun 			if (++rrd_next_to_clean == rrd_ring->count)
1963*4882a593Smuzhiyun 				rrd_next_to_clean = 0;
1964*4882a593Smuzhiyun 			count++;
1965*4882a593Smuzhiyun 			continue;
1966*4882a593Smuzhiyun 		} else {	/* current rrd still not be updated */
1967*4882a593Smuzhiyun 
1968*4882a593Smuzhiyun 			break;
1969*4882a593Smuzhiyun 		}
1970*4882a593Smuzhiyun rrd_ok:
1971*4882a593Smuzhiyun 		/* clean alloc flag for bad rrd */
1972*4882a593Smuzhiyun 		atl1_clean_alloc_flag(adapter, rrd, 0);
1973*4882a593Smuzhiyun 
1974*4882a593Smuzhiyun 		buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
1975*4882a593Smuzhiyun 		if (++rfd_ring->next_to_clean == rfd_ring->count)
1976*4882a593Smuzhiyun 			rfd_ring->next_to_clean = 0;
1977*4882a593Smuzhiyun 
1978*4882a593Smuzhiyun 		/* update rrd next to clean */
1979*4882a593Smuzhiyun 		if (++rrd_next_to_clean == rrd_ring->count)
1980*4882a593Smuzhiyun 			rrd_next_to_clean = 0;
1981*4882a593Smuzhiyun 		count++;
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 		if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
1984*4882a593Smuzhiyun 			if (!(rrd->err_flg &
1985*4882a593Smuzhiyun 				(ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
1986*4882a593Smuzhiyun 				| ERR_FLAG_LEN))) {
1987*4882a593Smuzhiyun 				/* packet error, don't need upstream */
1988*4882a593Smuzhiyun 				buffer_info->alloced = 0;
1989*4882a593Smuzhiyun 				rrd->xsz.valid = 0;
1990*4882a593Smuzhiyun 				continue;
1991*4882a593Smuzhiyun 			}
1992*4882a593Smuzhiyun 		}
1993*4882a593Smuzhiyun 
1994*4882a593Smuzhiyun 		/* Good Receive */
1995*4882a593Smuzhiyun 		dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
1996*4882a593Smuzhiyun 			       buffer_info->length, DMA_FROM_DEVICE);
1997*4882a593Smuzhiyun 		buffer_info->dma = 0;
1998*4882a593Smuzhiyun 		skb = buffer_info->skb;
1999*4882a593Smuzhiyun 		length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun 		skb_put(skb, length - ETH_FCS_LEN);
2002*4882a593Smuzhiyun 
2003*4882a593Smuzhiyun 		/* Receive Checksum Offload */
2004*4882a593Smuzhiyun 		atl1_rx_checksum(adapter, rrd, skb);
2005*4882a593Smuzhiyun 		skb->protocol = eth_type_trans(skb, adapter->netdev);
2006*4882a593Smuzhiyun 
2007*4882a593Smuzhiyun 		if (rrd->pkt_flg & PACKET_FLAG_VLAN_INS) {
2008*4882a593Smuzhiyun 			u16 vlan_tag = (rrd->vlan_tag >> 4) |
2009*4882a593Smuzhiyun 					((rrd->vlan_tag & 7) << 13) |
2010*4882a593Smuzhiyun 					((rrd->vlan_tag & 8) << 9);
2011*4882a593Smuzhiyun 
2012*4882a593Smuzhiyun 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
2013*4882a593Smuzhiyun 		}
2014*4882a593Smuzhiyun 		netif_receive_skb(skb);
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun 		/* let protocol layer free skb */
2017*4882a593Smuzhiyun 		buffer_info->skb = NULL;
2018*4882a593Smuzhiyun 		buffer_info->alloced = 0;
2019*4882a593Smuzhiyun 		rrd->xsz.valid = 0;
2020*4882a593Smuzhiyun 	}
2021*4882a593Smuzhiyun 
2022*4882a593Smuzhiyun 	atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
2023*4882a593Smuzhiyun 
2024*4882a593Smuzhiyun 	atl1_alloc_rx_buffers(adapter);
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun 	/* update mailbox ? */
2027*4882a593Smuzhiyun 	if (count) {
2028*4882a593Smuzhiyun 		u32 tpd_next_to_use;
2029*4882a593Smuzhiyun 		u32 rfd_next_to_use;
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun 		spin_lock(&adapter->mb_lock);
2032*4882a593Smuzhiyun 
2033*4882a593Smuzhiyun 		tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
2034*4882a593Smuzhiyun 		rfd_next_to_use =
2035*4882a593Smuzhiyun 		    atomic_read(&adapter->rfd_ring.next_to_use);
2036*4882a593Smuzhiyun 		rrd_next_to_clean =
2037*4882a593Smuzhiyun 		    atomic_read(&adapter->rrd_ring.next_to_clean);
2038*4882a593Smuzhiyun 		value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
2039*4882a593Smuzhiyun 			MB_RFD_PROD_INDX_SHIFT) |
2040*4882a593Smuzhiyun                         ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
2041*4882a593Smuzhiyun 			MB_RRD_CONS_INDX_SHIFT) |
2042*4882a593Smuzhiyun                         ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
2043*4882a593Smuzhiyun 			MB_TPD_PROD_INDX_SHIFT);
2044*4882a593Smuzhiyun 		iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
2045*4882a593Smuzhiyun 		spin_unlock(&adapter->mb_lock);
2046*4882a593Smuzhiyun 	}
2047*4882a593Smuzhiyun 
2048*4882a593Smuzhiyun 	return count;
2049*4882a593Smuzhiyun }
2050*4882a593Smuzhiyun 
atl1_intr_tx(struct atl1_adapter * adapter)2051*4882a593Smuzhiyun static int atl1_intr_tx(struct atl1_adapter *adapter)
2052*4882a593Smuzhiyun {
2053*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
2054*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
2055*4882a593Smuzhiyun 	u16 sw_tpd_next_to_clean;
2056*4882a593Smuzhiyun 	u16 cmb_tpd_next_to_clean;
2057*4882a593Smuzhiyun 	int count = 0;
2058*4882a593Smuzhiyun 
2059*4882a593Smuzhiyun 	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
2060*4882a593Smuzhiyun 	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
2061*4882a593Smuzhiyun 
2062*4882a593Smuzhiyun 	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
2063*4882a593Smuzhiyun 		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
2064*4882a593Smuzhiyun 		if (buffer_info->dma) {
2065*4882a593Smuzhiyun 			dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
2066*4882a593Smuzhiyun 				       buffer_info->length, DMA_TO_DEVICE);
2067*4882a593Smuzhiyun 			buffer_info->dma = 0;
2068*4882a593Smuzhiyun 		}
2069*4882a593Smuzhiyun 
2070*4882a593Smuzhiyun 		if (buffer_info->skb) {
2071*4882a593Smuzhiyun 			dev_consume_skb_irq(buffer_info->skb);
2072*4882a593Smuzhiyun 			buffer_info->skb = NULL;
2073*4882a593Smuzhiyun 		}
2074*4882a593Smuzhiyun 
2075*4882a593Smuzhiyun 		if (++sw_tpd_next_to_clean == tpd_ring->count)
2076*4882a593Smuzhiyun 			sw_tpd_next_to_clean = 0;
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun 		count++;
2079*4882a593Smuzhiyun 	}
2080*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
2081*4882a593Smuzhiyun 
2082*4882a593Smuzhiyun 	if (netif_queue_stopped(adapter->netdev) &&
2083*4882a593Smuzhiyun 	    netif_carrier_ok(adapter->netdev))
2084*4882a593Smuzhiyun 		netif_wake_queue(adapter->netdev);
2085*4882a593Smuzhiyun 
2086*4882a593Smuzhiyun 	return count;
2087*4882a593Smuzhiyun }
2088*4882a593Smuzhiyun 
atl1_tpd_avail(struct atl1_tpd_ring * tpd_ring)2089*4882a593Smuzhiyun static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
2090*4882a593Smuzhiyun {
2091*4882a593Smuzhiyun 	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
2092*4882a593Smuzhiyun 	u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
2093*4882a593Smuzhiyun 	return (next_to_clean > next_to_use) ?
2094*4882a593Smuzhiyun 		next_to_clean - next_to_use - 1 :
2095*4882a593Smuzhiyun 		tpd_ring->count + next_to_clean - next_to_use - 1;
2096*4882a593Smuzhiyun }
2097*4882a593Smuzhiyun 
atl1_tso(struct atl1_adapter * adapter,struct sk_buff * skb,struct tx_packet_desc * ptpd)2098*4882a593Smuzhiyun static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
2099*4882a593Smuzhiyun 		    struct tx_packet_desc *ptpd)
2100*4882a593Smuzhiyun {
2101*4882a593Smuzhiyun 	u8 hdr_len, ip_off;
2102*4882a593Smuzhiyun 	u32 real_len;
2103*4882a593Smuzhiyun 
2104*4882a593Smuzhiyun 	if (skb_shinfo(skb)->gso_size) {
2105*4882a593Smuzhiyun 		int err;
2106*4882a593Smuzhiyun 
2107*4882a593Smuzhiyun 		err = skb_cow_head(skb, 0);
2108*4882a593Smuzhiyun 		if (err < 0)
2109*4882a593Smuzhiyun 			return err;
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun 		if (skb->protocol == htons(ETH_P_IP)) {
2112*4882a593Smuzhiyun 			struct iphdr *iph = ip_hdr(skb);
2113*4882a593Smuzhiyun 
2114*4882a593Smuzhiyun 			real_len = (((unsigned char *)iph - skb->data) +
2115*4882a593Smuzhiyun 				ntohs(iph->tot_len));
2116*4882a593Smuzhiyun 			if (real_len < skb->len)
2117*4882a593Smuzhiyun 				pskb_trim(skb, real_len);
2118*4882a593Smuzhiyun 			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
2119*4882a593Smuzhiyun 			if (skb->len == hdr_len) {
2120*4882a593Smuzhiyun 				iph->check = 0;
2121*4882a593Smuzhiyun 				tcp_hdr(skb)->check =
2122*4882a593Smuzhiyun 					~csum_tcpudp_magic(iph->saddr,
2123*4882a593Smuzhiyun 					iph->daddr, tcp_hdrlen(skb),
2124*4882a593Smuzhiyun 					IPPROTO_TCP, 0);
2125*4882a593Smuzhiyun 				ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
2126*4882a593Smuzhiyun 					TPD_IPHL_SHIFT;
2127*4882a593Smuzhiyun 				ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
2128*4882a593Smuzhiyun 					TPD_TCPHDRLEN_MASK) <<
2129*4882a593Smuzhiyun 					TPD_TCPHDRLEN_SHIFT;
2130*4882a593Smuzhiyun 				ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
2131*4882a593Smuzhiyun 				ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
2132*4882a593Smuzhiyun 				return 1;
2133*4882a593Smuzhiyun 			}
2134*4882a593Smuzhiyun 
2135*4882a593Smuzhiyun 			iph->check = 0;
2136*4882a593Smuzhiyun 			tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
2137*4882a593Smuzhiyun 					iph->daddr, 0, IPPROTO_TCP, 0);
2138*4882a593Smuzhiyun 			ip_off = (unsigned char *)iph -
2139*4882a593Smuzhiyun 				(unsigned char *) skb_network_header(skb);
2140*4882a593Smuzhiyun 			if (ip_off == 8) /* 802.3-SNAP frame */
2141*4882a593Smuzhiyun 				ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
2142*4882a593Smuzhiyun 			else if (ip_off != 0)
2143*4882a593Smuzhiyun 				return -2;
2144*4882a593Smuzhiyun 
2145*4882a593Smuzhiyun 			ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
2146*4882a593Smuzhiyun 				TPD_IPHL_SHIFT;
2147*4882a593Smuzhiyun 			ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
2148*4882a593Smuzhiyun 				TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
2149*4882a593Smuzhiyun 			ptpd->word3 |= (skb_shinfo(skb)->gso_size &
2150*4882a593Smuzhiyun 				TPD_MSS_MASK) << TPD_MSS_SHIFT;
2151*4882a593Smuzhiyun 			ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
2152*4882a593Smuzhiyun 			return 3;
2153*4882a593Smuzhiyun 		}
2154*4882a593Smuzhiyun 	}
2155*4882a593Smuzhiyun 	return 0;
2156*4882a593Smuzhiyun }
2157*4882a593Smuzhiyun 
atl1_tx_csum(struct atl1_adapter * adapter,struct sk_buff * skb,struct tx_packet_desc * ptpd)2158*4882a593Smuzhiyun static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
2159*4882a593Smuzhiyun 	struct tx_packet_desc *ptpd)
2160*4882a593Smuzhiyun {
2161*4882a593Smuzhiyun 	u8 css, cso;
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun 	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
2164*4882a593Smuzhiyun 		css = skb_checksum_start_offset(skb);
2165*4882a593Smuzhiyun 		cso = css + (u8) skb->csum_offset;
2166*4882a593Smuzhiyun 		if (unlikely(css & 0x1)) {
2167*4882a593Smuzhiyun 			/* L1 hardware requires an even number here */
2168*4882a593Smuzhiyun 			if (netif_msg_tx_err(adapter))
2169*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, &adapter->pdev->dev,
2170*4882a593Smuzhiyun 					"payload offset not an even number\n");
2171*4882a593Smuzhiyun 			return -1;
2172*4882a593Smuzhiyun 		}
2173*4882a593Smuzhiyun 		ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
2174*4882a593Smuzhiyun 			TPD_PLOADOFFSET_SHIFT;
2175*4882a593Smuzhiyun 		ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
2176*4882a593Smuzhiyun 			TPD_CCSUMOFFSET_SHIFT;
2177*4882a593Smuzhiyun 		ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
2178*4882a593Smuzhiyun 		return true;
2179*4882a593Smuzhiyun 	}
2180*4882a593Smuzhiyun 	return 0;
2181*4882a593Smuzhiyun }
2182*4882a593Smuzhiyun 
atl1_tx_map(struct atl1_adapter * adapter,struct sk_buff * skb,struct tx_packet_desc * ptpd)2183*4882a593Smuzhiyun static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
2184*4882a593Smuzhiyun 	struct tx_packet_desc *ptpd)
2185*4882a593Smuzhiyun {
2186*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
2187*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
2188*4882a593Smuzhiyun 	u16 buf_len = skb->len;
2189*4882a593Smuzhiyun 	struct page *page;
2190*4882a593Smuzhiyun 	unsigned long offset;
2191*4882a593Smuzhiyun 	unsigned int nr_frags;
2192*4882a593Smuzhiyun 	unsigned int f;
2193*4882a593Smuzhiyun 	int retval;
2194*4882a593Smuzhiyun 	u16 next_to_use;
2195*4882a593Smuzhiyun 	u16 data_len;
2196*4882a593Smuzhiyun 	u8 hdr_len;
2197*4882a593Smuzhiyun 
2198*4882a593Smuzhiyun 	buf_len -= skb->data_len;
2199*4882a593Smuzhiyun 	nr_frags = skb_shinfo(skb)->nr_frags;
2200*4882a593Smuzhiyun 	next_to_use = atomic_read(&tpd_ring->next_to_use);
2201*4882a593Smuzhiyun 	buffer_info = &tpd_ring->buffer_info[next_to_use];
2202*4882a593Smuzhiyun 	BUG_ON(buffer_info->skb);
2203*4882a593Smuzhiyun 	/* put skb in last TPD */
2204*4882a593Smuzhiyun 	buffer_info->skb = NULL;
2205*4882a593Smuzhiyun 
2206*4882a593Smuzhiyun 	retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
2207*4882a593Smuzhiyun 	if (retval) {
2208*4882a593Smuzhiyun 		/* TSO */
2209*4882a593Smuzhiyun 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
2210*4882a593Smuzhiyun 		buffer_info->length = hdr_len;
2211*4882a593Smuzhiyun 		page = virt_to_page(skb->data);
2212*4882a593Smuzhiyun 		offset = offset_in_page(skb->data);
2213*4882a593Smuzhiyun 		buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
2214*4882a593Smuzhiyun 						offset, hdr_len,
2215*4882a593Smuzhiyun 						DMA_TO_DEVICE);
2216*4882a593Smuzhiyun 
2217*4882a593Smuzhiyun 		if (++next_to_use == tpd_ring->count)
2218*4882a593Smuzhiyun 			next_to_use = 0;
2219*4882a593Smuzhiyun 
2220*4882a593Smuzhiyun 		if (buf_len > hdr_len) {
2221*4882a593Smuzhiyun 			int i, nseg;
2222*4882a593Smuzhiyun 
2223*4882a593Smuzhiyun 			data_len = buf_len - hdr_len;
2224*4882a593Smuzhiyun 			nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
2225*4882a593Smuzhiyun 				ATL1_MAX_TX_BUF_LEN;
2226*4882a593Smuzhiyun 			for (i = 0; i < nseg; i++) {
2227*4882a593Smuzhiyun 				buffer_info =
2228*4882a593Smuzhiyun 				    &tpd_ring->buffer_info[next_to_use];
2229*4882a593Smuzhiyun 				buffer_info->skb = NULL;
2230*4882a593Smuzhiyun 				buffer_info->length =
2231*4882a593Smuzhiyun 				    (ATL1_MAX_TX_BUF_LEN >=
2232*4882a593Smuzhiyun 				     data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
2233*4882a593Smuzhiyun 				data_len -= buffer_info->length;
2234*4882a593Smuzhiyun 				page = virt_to_page(skb->data +
2235*4882a593Smuzhiyun 					(hdr_len + i * ATL1_MAX_TX_BUF_LEN));
2236*4882a593Smuzhiyun 				offset = offset_in_page(skb->data +
2237*4882a593Smuzhiyun 					(hdr_len + i * ATL1_MAX_TX_BUF_LEN));
2238*4882a593Smuzhiyun 				buffer_info->dma = dma_map_page(&adapter->pdev->dev,
2239*4882a593Smuzhiyun 								page, offset,
2240*4882a593Smuzhiyun 								buffer_info->length,
2241*4882a593Smuzhiyun 								DMA_TO_DEVICE);
2242*4882a593Smuzhiyun 				if (++next_to_use == tpd_ring->count)
2243*4882a593Smuzhiyun 					next_to_use = 0;
2244*4882a593Smuzhiyun 			}
2245*4882a593Smuzhiyun 		}
2246*4882a593Smuzhiyun 	} else {
2247*4882a593Smuzhiyun 		/* not TSO */
2248*4882a593Smuzhiyun 		buffer_info->length = buf_len;
2249*4882a593Smuzhiyun 		page = virt_to_page(skb->data);
2250*4882a593Smuzhiyun 		offset = offset_in_page(skb->data);
2251*4882a593Smuzhiyun 		buffer_info->dma = dma_map_page(&adapter->pdev->dev, page,
2252*4882a593Smuzhiyun 						offset, buf_len,
2253*4882a593Smuzhiyun 						DMA_TO_DEVICE);
2254*4882a593Smuzhiyun 		if (++next_to_use == tpd_ring->count)
2255*4882a593Smuzhiyun 			next_to_use = 0;
2256*4882a593Smuzhiyun 	}
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun 	for (f = 0; f < nr_frags; f++) {
2259*4882a593Smuzhiyun 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
2260*4882a593Smuzhiyun 		u16 i, nseg;
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 		buf_len = skb_frag_size(frag);
2263*4882a593Smuzhiyun 
2264*4882a593Smuzhiyun 		nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
2265*4882a593Smuzhiyun 			ATL1_MAX_TX_BUF_LEN;
2266*4882a593Smuzhiyun 		for (i = 0; i < nseg; i++) {
2267*4882a593Smuzhiyun 			buffer_info = &tpd_ring->buffer_info[next_to_use];
2268*4882a593Smuzhiyun 			BUG_ON(buffer_info->skb);
2269*4882a593Smuzhiyun 
2270*4882a593Smuzhiyun 			buffer_info->skb = NULL;
2271*4882a593Smuzhiyun 			buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
2272*4882a593Smuzhiyun 				ATL1_MAX_TX_BUF_LEN : buf_len;
2273*4882a593Smuzhiyun 			buf_len -= buffer_info->length;
2274*4882a593Smuzhiyun 			buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev,
2275*4882a593Smuzhiyun 				frag, i * ATL1_MAX_TX_BUF_LEN,
2276*4882a593Smuzhiyun 				buffer_info->length, DMA_TO_DEVICE);
2277*4882a593Smuzhiyun 
2278*4882a593Smuzhiyun 			if (++next_to_use == tpd_ring->count)
2279*4882a593Smuzhiyun 				next_to_use = 0;
2280*4882a593Smuzhiyun 		}
2281*4882a593Smuzhiyun 	}
2282*4882a593Smuzhiyun 
2283*4882a593Smuzhiyun 	/* last tpd's buffer-info */
2284*4882a593Smuzhiyun 	buffer_info->skb = skb;
2285*4882a593Smuzhiyun }
2286*4882a593Smuzhiyun 
atl1_tx_queue(struct atl1_adapter * adapter,u16 count,struct tx_packet_desc * ptpd)2287*4882a593Smuzhiyun static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
2288*4882a593Smuzhiyun        struct tx_packet_desc *ptpd)
2289*4882a593Smuzhiyun {
2290*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
2291*4882a593Smuzhiyun 	struct atl1_buffer *buffer_info;
2292*4882a593Smuzhiyun 	struct tx_packet_desc *tpd;
2293*4882a593Smuzhiyun 	u16 j;
2294*4882a593Smuzhiyun 	u32 val;
2295*4882a593Smuzhiyun 	u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
2296*4882a593Smuzhiyun 
2297*4882a593Smuzhiyun 	for (j = 0; j < count; j++) {
2298*4882a593Smuzhiyun 		buffer_info = &tpd_ring->buffer_info[next_to_use];
2299*4882a593Smuzhiyun 		tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
2300*4882a593Smuzhiyun 		if (tpd != ptpd)
2301*4882a593Smuzhiyun 			memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
2302*4882a593Smuzhiyun 		tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
2303*4882a593Smuzhiyun 		tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT);
2304*4882a593Smuzhiyun 		tpd->word2 |= (cpu_to_le16(buffer_info->length) &
2305*4882a593Smuzhiyun 			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
2306*4882a593Smuzhiyun 
2307*4882a593Smuzhiyun 		/*
2308*4882a593Smuzhiyun 		 * if this is the first packet in a TSO chain, set
2309*4882a593Smuzhiyun 		 * TPD_HDRFLAG, otherwise, clear it.
2310*4882a593Smuzhiyun 		 */
2311*4882a593Smuzhiyun 		val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
2312*4882a593Smuzhiyun 			TPD_SEGMENT_EN_MASK;
2313*4882a593Smuzhiyun 		if (val) {
2314*4882a593Smuzhiyun 			if (!j)
2315*4882a593Smuzhiyun 				tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
2316*4882a593Smuzhiyun 			else
2317*4882a593Smuzhiyun 				tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
2318*4882a593Smuzhiyun 		}
2319*4882a593Smuzhiyun 
2320*4882a593Smuzhiyun 		if (j == (count - 1))
2321*4882a593Smuzhiyun 			tpd->word3 |= 1 << TPD_EOP_SHIFT;
2322*4882a593Smuzhiyun 
2323*4882a593Smuzhiyun 		if (++next_to_use == tpd_ring->count)
2324*4882a593Smuzhiyun 			next_to_use = 0;
2325*4882a593Smuzhiyun 	}
2326*4882a593Smuzhiyun 	/*
2327*4882a593Smuzhiyun 	 * Force memory writes to complete before letting h/w
2328*4882a593Smuzhiyun 	 * know there are new descriptors to fetch.  (Only
2329*4882a593Smuzhiyun 	 * applicable for weak-ordered memory model archs,
2330*4882a593Smuzhiyun 	 * such as IA-64).
2331*4882a593Smuzhiyun 	 */
2332*4882a593Smuzhiyun 	wmb();
2333*4882a593Smuzhiyun 
2334*4882a593Smuzhiyun 	atomic_set(&tpd_ring->next_to_use, next_to_use);
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun 
atl1_xmit_frame(struct sk_buff * skb,struct net_device * netdev)2337*4882a593Smuzhiyun static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
2338*4882a593Smuzhiyun 					 struct net_device *netdev)
2339*4882a593Smuzhiyun {
2340*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2341*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
2342*4882a593Smuzhiyun 	int len;
2343*4882a593Smuzhiyun 	int tso;
2344*4882a593Smuzhiyun 	int count = 1;
2345*4882a593Smuzhiyun 	int ret_val;
2346*4882a593Smuzhiyun 	struct tx_packet_desc *ptpd;
2347*4882a593Smuzhiyun 	u16 vlan_tag;
2348*4882a593Smuzhiyun 	unsigned int nr_frags = 0;
2349*4882a593Smuzhiyun 	unsigned int mss = 0;
2350*4882a593Smuzhiyun 	unsigned int f;
2351*4882a593Smuzhiyun 	unsigned int proto_hdr_len;
2352*4882a593Smuzhiyun 
2353*4882a593Smuzhiyun 	len = skb_headlen(skb);
2354*4882a593Smuzhiyun 
2355*4882a593Smuzhiyun 	if (unlikely(skb->len <= 0)) {
2356*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
2357*4882a593Smuzhiyun 		return NETDEV_TX_OK;
2358*4882a593Smuzhiyun 	}
2359*4882a593Smuzhiyun 
2360*4882a593Smuzhiyun 	nr_frags = skb_shinfo(skb)->nr_frags;
2361*4882a593Smuzhiyun 	for (f = 0; f < nr_frags; f++) {
2362*4882a593Smuzhiyun 		unsigned int f_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
2363*4882a593Smuzhiyun 		count += (f_size + ATL1_MAX_TX_BUF_LEN - 1) /
2364*4882a593Smuzhiyun 			 ATL1_MAX_TX_BUF_LEN;
2365*4882a593Smuzhiyun 	}
2366*4882a593Smuzhiyun 
2367*4882a593Smuzhiyun 	mss = skb_shinfo(skb)->gso_size;
2368*4882a593Smuzhiyun 	if (mss) {
2369*4882a593Smuzhiyun 		if (skb->protocol == htons(ETH_P_IP)) {
2370*4882a593Smuzhiyun 			proto_hdr_len = (skb_transport_offset(skb) +
2371*4882a593Smuzhiyun 					 tcp_hdrlen(skb));
2372*4882a593Smuzhiyun 			if (unlikely(proto_hdr_len > len)) {
2373*4882a593Smuzhiyun 				dev_kfree_skb_any(skb);
2374*4882a593Smuzhiyun 				return NETDEV_TX_OK;
2375*4882a593Smuzhiyun 			}
2376*4882a593Smuzhiyun 			/* need additional TPD ? */
2377*4882a593Smuzhiyun 			if (proto_hdr_len != len)
2378*4882a593Smuzhiyun 				count += (len - proto_hdr_len +
2379*4882a593Smuzhiyun 					ATL1_MAX_TX_BUF_LEN - 1) /
2380*4882a593Smuzhiyun 					ATL1_MAX_TX_BUF_LEN;
2381*4882a593Smuzhiyun 		}
2382*4882a593Smuzhiyun 	}
2383*4882a593Smuzhiyun 
2384*4882a593Smuzhiyun 	if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
2385*4882a593Smuzhiyun 		/* not enough descriptors */
2386*4882a593Smuzhiyun 		netif_stop_queue(netdev);
2387*4882a593Smuzhiyun 		if (netif_msg_tx_queued(adapter))
2388*4882a593Smuzhiyun 			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
2389*4882a593Smuzhiyun 				"tx busy\n");
2390*4882a593Smuzhiyun 		return NETDEV_TX_BUSY;
2391*4882a593Smuzhiyun 	}
2392*4882a593Smuzhiyun 
2393*4882a593Smuzhiyun 	ptpd = ATL1_TPD_DESC(tpd_ring,
2394*4882a593Smuzhiyun 		(u16) atomic_read(&tpd_ring->next_to_use));
2395*4882a593Smuzhiyun 	memset(ptpd, 0, sizeof(struct tx_packet_desc));
2396*4882a593Smuzhiyun 
2397*4882a593Smuzhiyun 	if (skb_vlan_tag_present(skb)) {
2398*4882a593Smuzhiyun 		vlan_tag = skb_vlan_tag_get(skb);
2399*4882a593Smuzhiyun 		vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
2400*4882a593Smuzhiyun 			((vlan_tag >> 9) & 0x8);
2401*4882a593Smuzhiyun 		ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
2402*4882a593Smuzhiyun 		ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) <<
2403*4882a593Smuzhiyun 			TPD_VLANTAG_SHIFT;
2404*4882a593Smuzhiyun 	}
2405*4882a593Smuzhiyun 
2406*4882a593Smuzhiyun 	tso = atl1_tso(adapter, skb, ptpd);
2407*4882a593Smuzhiyun 	if (tso < 0) {
2408*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
2409*4882a593Smuzhiyun 		return NETDEV_TX_OK;
2410*4882a593Smuzhiyun 	}
2411*4882a593Smuzhiyun 
2412*4882a593Smuzhiyun 	if (!tso) {
2413*4882a593Smuzhiyun 		ret_val = atl1_tx_csum(adapter, skb, ptpd);
2414*4882a593Smuzhiyun 		if (ret_val < 0) {
2415*4882a593Smuzhiyun 			dev_kfree_skb_any(skb);
2416*4882a593Smuzhiyun 			return NETDEV_TX_OK;
2417*4882a593Smuzhiyun 		}
2418*4882a593Smuzhiyun 	}
2419*4882a593Smuzhiyun 
2420*4882a593Smuzhiyun 	atl1_tx_map(adapter, skb, ptpd);
2421*4882a593Smuzhiyun 	atl1_tx_queue(adapter, count, ptpd);
2422*4882a593Smuzhiyun 	atl1_update_mailbox(adapter);
2423*4882a593Smuzhiyun 	return NETDEV_TX_OK;
2424*4882a593Smuzhiyun }
2425*4882a593Smuzhiyun 
atl1_rings_clean(struct napi_struct * napi,int budget)2426*4882a593Smuzhiyun static int atl1_rings_clean(struct napi_struct *napi, int budget)
2427*4882a593Smuzhiyun {
2428*4882a593Smuzhiyun 	struct atl1_adapter *adapter = container_of(napi, struct atl1_adapter, napi);
2429*4882a593Smuzhiyun 	int work_done = atl1_intr_rx(adapter, budget);
2430*4882a593Smuzhiyun 
2431*4882a593Smuzhiyun 	if (atl1_intr_tx(adapter))
2432*4882a593Smuzhiyun 		work_done = budget;
2433*4882a593Smuzhiyun 
2434*4882a593Smuzhiyun 	/* Let's come again to process some more packets */
2435*4882a593Smuzhiyun 	if (work_done >= budget)
2436*4882a593Smuzhiyun 		return work_done;
2437*4882a593Smuzhiyun 
2438*4882a593Smuzhiyun 	napi_complete_done(napi, work_done);
2439*4882a593Smuzhiyun 	/* re-enable Interrupt */
2440*4882a593Smuzhiyun 	if (likely(adapter->int_enabled))
2441*4882a593Smuzhiyun 		atlx_imr_set(adapter, IMR_NORMAL_MASK);
2442*4882a593Smuzhiyun 	return work_done;
2443*4882a593Smuzhiyun }
2444*4882a593Smuzhiyun 
atl1_sched_rings_clean(struct atl1_adapter * adapter)2445*4882a593Smuzhiyun static inline int atl1_sched_rings_clean(struct atl1_adapter* adapter)
2446*4882a593Smuzhiyun {
2447*4882a593Smuzhiyun 	if (!napi_schedule_prep(&adapter->napi))
2448*4882a593Smuzhiyun 		/* It is possible in case even the RX/TX ints are disabled via IMR
2449*4882a593Smuzhiyun 		 * register the ISR bits are set anyway (but do not produce IRQ).
2450*4882a593Smuzhiyun 		 * To handle such situation the napi functions used to check is
2451*4882a593Smuzhiyun 		 * something scheduled or not.
2452*4882a593Smuzhiyun 		 */
2453*4882a593Smuzhiyun 		return 0;
2454*4882a593Smuzhiyun 
2455*4882a593Smuzhiyun 	__napi_schedule(&adapter->napi);
2456*4882a593Smuzhiyun 
2457*4882a593Smuzhiyun 	/*
2458*4882a593Smuzhiyun 	 * Disable RX/TX ints via IMR register if it is
2459*4882a593Smuzhiyun 	 * allowed. NAPI handler must reenable them in same
2460*4882a593Smuzhiyun 	 * way.
2461*4882a593Smuzhiyun 	 */
2462*4882a593Smuzhiyun 	if (!adapter->int_enabled)
2463*4882a593Smuzhiyun 		return 1;
2464*4882a593Smuzhiyun 
2465*4882a593Smuzhiyun 	atlx_imr_set(adapter, IMR_NORXTX_MASK);
2466*4882a593Smuzhiyun 	return 1;
2467*4882a593Smuzhiyun }
2468*4882a593Smuzhiyun 
2469*4882a593Smuzhiyun /**
2470*4882a593Smuzhiyun  * atl1_intr - Interrupt Handler
2471*4882a593Smuzhiyun  * @irq: interrupt number
2472*4882a593Smuzhiyun  * @data: pointer to a network interface device structure
2473*4882a593Smuzhiyun  */
atl1_intr(int irq,void * data)2474*4882a593Smuzhiyun static irqreturn_t atl1_intr(int irq, void *data)
2475*4882a593Smuzhiyun {
2476*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(data);
2477*4882a593Smuzhiyun 	u32 status;
2478*4882a593Smuzhiyun 
2479*4882a593Smuzhiyun 	status = adapter->cmb.cmb->int_stats;
2480*4882a593Smuzhiyun 	if (!status)
2481*4882a593Smuzhiyun 		return IRQ_NONE;
2482*4882a593Smuzhiyun 
2483*4882a593Smuzhiyun 	/* clear CMB interrupt status at once,
2484*4882a593Smuzhiyun 	 * but leave rx/tx interrupt status in case it should be dropped
2485*4882a593Smuzhiyun 	 * only if rx/tx processing queued. In other case interrupt
2486*4882a593Smuzhiyun 	 * can be lost.
2487*4882a593Smuzhiyun 	 */
2488*4882a593Smuzhiyun 	adapter->cmb.cmb->int_stats = status & (ISR_CMB_TX | ISR_CMB_RX);
2489*4882a593Smuzhiyun 
2490*4882a593Smuzhiyun 	if (status & ISR_GPHY)	/* clear phy status */
2491*4882a593Smuzhiyun 		atlx_clear_phy_int(adapter);
2492*4882a593Smuzhiyun 
2493*4882a593Smuzhiyun 	/* clear ISR status, and Enable CMB DMA/Disable Interrupt */
2494*4882a593Smuzhiyun 	iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
2495*4882a593Smuzhiyun 
2496*4882a593Smuzhiyun 	/* check if SMB intr */
2497*4882a593Smuzhiyun 	if (status & ISR_SMB)
2498*4882a593Smuzhiyun 		atl1_inc_smb(adapter);
2499*4882a593Smuzhiyun 
2500*4882a593Smuzhiyun 	/* check if PCIE PHY Link down */
2501*4882a593Smuzhiyun 	if (status & ISR_PHY_LINKDOWN) {
2502*4882a593Smuzhiyun 		if (netif_msg_intr(adapter))
2503*4882a593Smuzhiyun 			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
2504*4882a593Smuzhiyun 				"pcie phy link down %x\n", status);
2505*4882a593Smuzhiyun 		if (netif_running(adapter->netdev)) {	/* reset MAC */
2506*4882a593Smuzhiyun 			atlx_irq_disable(adapter);
2507*4882a593Smuzhiyun 			schedule_work(&adapter->reset_dev_task);
2508*4882a593Smuzhiyun 			return IRQ_HANDLED;
2509*4882a593Smuzhiyun 		}
2510*4882a593Smuzhiyun 	}
2511*4882a593Smuzhiyun 
2512*4882a593Smuzhiyun 	/* check if DMA read/write error ? */
2513*4882a593Smuzhiyun 	if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
2514*4882a593Smuzhiyun 		if (netif_msg_intr(adapter))
2515*4882a593Smuzhiyun 			dev_printk(KERN_DEBUG, &adapter->pdev->dev,
2516*4882a593Smuzhiyun 				"pcie DMA r/w error (status = 0x%x)\n",
2517*4882a593Smuzhiyun 				status);
2518*4882a593Smuzhiyun 		atlx_irq_disable(adapter);
2519*4882a593Smuzhiyun 		schedule_work(&adapter->reset_dev_task);
2520*4882a593Smuzhiyun 		return IRQ_HANDLED;
2521*4882a593Smuzhiyun 	}
2522*4882a593Smuzhiyun 
2523*4882a593Smuzhiyun 	/* link event */
2524*4882a593Smuzhiyun 	if (status & ISR_GPHY) {
2525*4882a593Smuzhiyun 		adapter->soft_stats.tx_carrier_errors++;
2526*4882a593Smuzhiyun 		atl1_check_for_link(adapter);
2527*4882a593Smuzhiyun 	}
2528*4882a593Smuzhiyun 
2529*4882a593Smuzhiyun 	/* transmit or receive event */
2530*4882a593Smuzhiyun 	if (status & (ISR_CMB_TX | ISR_CMB_RX) &&
2531*4882a593Smuzhiyun 	    atl1_sched_rings_clean(adapter))
2532*4882a593Smuzhiyun 		adapter->cmb.cmb->int_stats = adapter->cmb.cmb->int_stats &
2533*4882a593Smuzhiyun 					      ~(ISR_CMB_TX | ISR_CMB_RX);
2534*4882a593Smuzhiyun 
2535*4882a593Smuzhiyun 	/* rx exception */
2536*4882a593Smuzhiyun 	if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
2537*4882a593Smuzhiyun 		ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
2538*4882a593Smuzhiyun 		ISR_HOST_RRD_OV))) {
2539*4882a593Smuzhiyun 		if (netif_msg_intr(adapter))
2540*4882a593Smuzhiyun 			dev_printk(KERN_DEBUG,
2541*4882a593Smuzhiyun 				&adapter->pdev->dev,
2542*4882a593Smuzhiyun 				"rx exception, ISR = 0x%x\n",
2543*4882a593Smuzhiyun 				status);
2544*4882a593Smuzhiyun 		atl1_sched_rings_clean(adapter);
2545*4882a593Smuzhiyun 	}
2546*4882a593Smuzhiyun 
2547*4882a593Smuzhiyun 	/* re-enable Interrupt */
2548*4882a593Smuzhiyun 	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
2549*4882a593Smuzhiyun 	return IRQ_HANDLED;
2550*4882a593Smuzhiyun }
2551*4882a593Smuzhiyun 
2552*4882a593Smuzhiyun 
2553*4882a593Smuzhiyun /**
2554*4882a593Smuzhiyun  * atl1_phy_config - Timer Call-back
2555*4882a593Smuzhiyun  * @t: timer_list containing pointer to netdev cast into an unsigned long
2556*4882a593Smuzhiyun  */
atl1_phy_config(struct timer_list * t)2557*4882a593Smuzhiyun static void atl1_phy_config(struct timer_list *t)
2558*4882a593Smuzhiyun {
2559*4882a593Smuzhiyun 	struct atl1_adapter *adapter = from_timer(adapter, t,
2560*4882a593Smuzhiyun 						  phy_config_timer);
2561*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
2562*4882a593Smuzhiyun 	unsigned long flags;
2563*4882a593Smuzhiyun 
2564*4882a593Smuzhiyun 	spin_lock_irqsave(&adapter->lock, flags);
2565*4882a593Smuzhiyun 	adapter->phy_timer_pending = false;
2566*4882a593Smuzhiyun 	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
2567*4882a593Smuzhiyun 	atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
2568*4882a593Smuzhiyun 	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
2569*4882a593Smuzhiyun 	spin_unlock_irqrestore(&adapter->lock, flags);
2570*4882a593Smuzhiyun }
2571*4882a593Smuzhiyun 
2572*4882a593Smuzhiyun /*
2573*4882a593Smuzhiyun  * Orphaned vendor comment left intact here:
2574*4882a593Smuzhiyun  * <vendor comment>
2575*4882a593Smuzhiyun  * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
2576*4882a593Smuzhiyun  * will assert. We do soft reset <0x1400=1> according
2577*4882a593Smuzhiyun  * with the SPEC. BUT, it seemes that PCIE or DMA
2578*4882a593Smuzhiyun  * state-machine will not be reset. DMAR_TO_INT will
2579*4882a593Smuzhiyun  * assert again and again.
2580*4882a593Smuzhiyun  * </vendor comment>
2581*4882a593Smuzhiyun  */
2582*4882a593Smuzhiyun 
atl1_reset(struct atl1_adapter * adapter)2583*4882a593Smuzhiyun static int atl1_reset(struct atl1_adapter *adapter)
2584*4882a593Smuzhiyun {
2585*4882a593Smuzhiyun 	int ret;
2586*4882a593Smuzhiyun 	ret = atl1_reset_hw(&adapter->hw);
2587*4882a593Smuzhiyun 	if (ret)
2588*4882a593Smuzhiyun 		return ret;
2589*4882a593Smuzhiyun 	return atl1_init_hw(&adapter->hw);
2590*4882a593Smuzhiyun }
2591*4882a593Smuzhiyun 
atl1_up(struct atl1_adapter * adapter)2592*4882a593Smuzhiyun static s32 atl1_up(struct atl1_adapter *adapter)
2593*4882a593Smuzhiyun {
2594*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
2595*4882a593Smuzhiyun 	int err;
2596*4882a593Smuzhiyun 	int irq_flags = 0;
2597*4882a593Smuzhiyun 
2598*4882a593Smuzhiyun 	/* hardware has been reset, we need to reload some things */
2599*4882a593Smuzhiyun 	atlx_set_multi(netdev);
2600*4882a593Smuzhiyun 	atl1_init_ring_ptrs(adapter);
2601*4882a593Smuzhiyun 	atlx_restore_vlan(adapter);
2602*4882a593Smuzhiyun 	err = atl1_alloc_rx_buffers(adapter);
2603*4882a593Smuzhiyun 	if (unlikely(!err))
2604*4882a593Smuzhiyun 		/* no RX BUFFER allocated */
2605*4882a593Smuzhiyun 		return -ENOMEM;
2606*4882a593Smuzhiyun 
2607*4882a593Smuzhiyun 	if (unlikely(atl1_configure(adapter))) {
2608*4882a593Smuzhiyun 		err = -EIO;
2609*4882a593Smuzhiyun 		goto err_up;
2610*4882a593Smuzhiyun 	}
2611*4882a593Smuzhiyun 
2612*4882a593Smuzhiyun 	err = pci_enable_msi(adapter->pdev);
2613*4882a593Smuzhiyun 	if (err) {
2614*4882a593Smuzhiyun 		if (netif_msg_ifup(adapter))
2615*4882a593Smuzhiyun 			dev_info(&adapter->pdev->dev,
2616*4882a593Smuzhiyun 				"Unable to enable MSI: %d\n", err);
2617*4882a593Smuzhiyun 		irq_flags |= IRQF_SHARED;
2618*4882a593Smuzhiyun 	}
2619*4882a593Smuzhiyun 
2620*4882a593Smuzhiyun 	err = request_irq(adapter->pdev->irq, atl1_intr, irq_flags,
2621*4882a593Smuzhiyun 			netdev->name, netdev);
2622*4882a593Smuzhiyun 	if (unlikely(err))
2623*4882a593Smuzhiyun 		goto err_up;
2624*4882a593Smuzhiyun 
2625*4882a593Smuzhiyun 	napi_enable(&adapter->napi);
2626*4882a593Smuzhiyun 	atlx_irq_enable(adapter);
2627*4882a593Smuzhiyun 	atl1_check_link(adapter);
2628*4882a593Smuzhiyun 	netif_start_queue(netdev);
2629*4882a593Smuzhiyun 	return 0;
2630*4882a593Smuzhiyun 
2631*4882a593Smuzhiyun err_up:
2632*4882a593Smuzhiyun 	pci_disable_msi(adapter->pdev);
2633*4882a593Smuzhiyun 	/* free rx_buffers */
2634*4882a593Smuzhiyun 	atl1_clean_rx_ring(adapter);
2635*4882a593Smuzhiyun 	return err;
2636*4882a593Smuzhiyun }
2637*4882a593Smuzhiyun 
atl1_down(struct atl1_adapter * adapter)2638*4882a593Smuzhiyun static void atl1_down(struct atl1_adapter *adapter)
2639*4882a593Smuzhiyun {
2640*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
2641*4882a593Smuzhiyun 
2642*4882a593Smuzhiyun 	napi_disable(&adapter->napi);
2643*4882a593Smuzhiyun 	netif_stop_queue(netdev);
2644*4882a593Smuzhiyun 	del_timer_sync(&adapter->phy_config_timer);
2645*4882a593Smuzhiyun 	adapter->phy_timer_pending = false;
2646*4882a593Smuzhiyun 
2647*4882a593Smuzhiyun 	atlx_irq_disable(adapter);
2648*4882a593Smuzhiyun 	free_irq(adapter->pdev->irq, netdev);
2649*4882a593Smuzhiyun 	pci_disable_msi(adapter->pdev);
2650*4882a593Smuzhiyun 	atl1_reset_hw(&adapter->hw);
2651*4882a593Smuzhiyun 	adapter->cmb.cmb->int_stats = 0;
2652*4882a593Smuzhiyun 
2653*4882a593Smuzhiyun 	adapter->link_speed = SPEED_0;
2654*4882a593Smuzhiyun 	adapter->link_duplex = -1;
2655*4882a593Smuzhiyun 	netif_carrier_off(netdev);
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun 	atl1_clean_tx_ring(adapter);
2658*4882a593Smuzhiyun 	atl1_clean_rx_ring(adapter);
2659*4882a593Smuzhiyun }
2660*4882a593Smuzhiyun 
atl1_reset_dev_task(struct work_struct * work)2661*4882a593Smuzhiyun static void atl1_reset_dev_task(struct work_struct *work)
2662*4882a593Smuzhiyun {
2663*4882a593Smuzhiyun 	struct atl1_adapter *adapter =
2664*4882a593Smuzhiyun 		container_of(work, struct atl1_adapter, reset_dev_task);
2665*4882a593Smuzhiyun 	struct net_device *netdev = adapter->netdev;
2666*4882a593Smuzhiyun 
2667*4882a593Smuzhiyun 	netif_device_detach(netdev);
2668*4882a593Smuzhiyun 	atl1_down(adapter);
2669*4882a593Smuzhiyun 	atl1_up(adapter);
2670*4882a593Smuzhiyun 	netif_device_attach(netdev);
2671*4882a593Smuzhiyun }
2672*4882a593Smuzhiyun 
2673*4882a593Smuzhiyun /**
2674*4882a593Smuzhiyun  * atl1_change_mtu - Change the Maximum Transfer Unit
2675*4882a593Smuzhiyun  * @netdev: network interface device structure
2676*4882a593Smuzhiyun  * @new_mtu: new value for maximum frame size
2677*4882a593Smuzhiyun  *
2678*4882a593Smuzhiyun  * Returns 0 on success, negative on failure
2679*4882a593Smuzhiyun  */
atl1_change_mtu(struct net_device * netdev,int new_mtu)2680*4882a593Smuzhiyun static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
2681*4882a593Smuzhiyun {
2682*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2683*4882a593Smuzhiyun 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
2684*4882a593Smuzhiyun 
2685*4882a593Smuzhiyun 	adapter->hw.max_frame_size = max_frame;
2686*4882a593Smuzhiyun 	adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
2687*4882a593Smuzhiyun 	adapter->rx_buffer_len = (max_frame + 7) & ~7;
2688*4882a593Smuzhiyun 	adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
2689*4882a593Smuzhiyun 
2690*4882a593Smuzhiyun 	netdev->mtu = new_mtu;
2691*4882a593Smuzhiyun 	if (netif_running(netdev)) {
2692*4882a593Smuzhiyun 		atl1_down(adapter);
2693*4882a593Smuzhiyun 		atl1_up(adapter);
2694*4882a593Smuzhiyun 	}
2695*4882a593Smuzhiyun 
2696*4882a593Smuzhiyun 	return 0;
2697*4882a593Smuzhiyun }
2698*4882a593Smuzhiyun 
2699*4882a593Smuzhiyun /**
2700*4882a593Smuzhiyun  * atl1_open - Called when a network interface is made active
2701*4882a593Smuzhiyun  * @netdev: network interface device structure
2702*4882a593Smuzhiyun  *
2703*4882a593Smuzhiyun  * Returns 0 on success, negative value on failure
2704*4882a593Smuzhiyun  *
2705*4882a593Smuzhiyun  * The open entry point is called when a network interface is made
2706*4882a593Smuzhiyun  * active by the system (IFF_UP).  At this point all resources needed
2707*4882a593Smuzhiyun  * for transmit and receive operations are allocated, the interrupt
2708*4882a593Smuzhiyun  * handler is registered with the OS, the watchdog timer is started,
2709*4882a593Smuzhiyun  * and the stack is notified that the interface is ready.
2710*4882a593Smuzhiyun  */
atl1_open(struct net_device * netdev)2711*4882a593Smuzhiyun static int atl1_open(struct net_device *netdev)
2712*4882a593Smuzhiyun {
2713*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2714*4882a593Smuzhiyun 	int err;
2715*4882a593Smuzhiyun 
2716*4882a593Smuzhiyun 	netif_carrier_off(netdev);
2717*4882a593Smuzhiyun 
2718*4882a593Smuzhiyun 	/* allocate transmit descriptors */
2719*4882a593Smuzhiyun 	err = atl1_setup_ring_resources(adapter);
2720*4882a593Smuzhiyun 	if (err)
2721*4882a593Smuzhiyun 		return err;
2722*4882a593Smuzhiyun 
2723*4882a593Smuzhiyun 	err = atl1_up(adapter);
2724*4882a593Smuzhiyun 	if (err)
2725*4882a593Smuzhiyun 		goto err_up;
2726*4882a593Smuzhiyun 
2727*4882a593Smuzhiyun 	return 0;
2728*4882a593Smuzhiyun 
2729*4882a593Smuzhiyun err_up:
2730*4882a593Smuzhiyun 	atl1_reset(adapter);
2731*4882a593Smuzhiyun 	return err;
2732*4882a593Smuzhiyun }
2733*4882a593Smuzhiyun 
2734*4882a593Smuzhiyun /**
2735*4882a593Smuzhiyun  * atl1_close - Disables a network interface
2736*4882a593Smuzhiyun  * @netdev: network interface device structure
2737*4882a593Smuzhiyun  *
2738*4882a593Smuzhiyun  * Returns 0, this is not allowed to fail
2739*4882a593Smuzhiyun  *
2740*4882a593Smuzhiyun  * The close entry point is called when an interface is de-activated
2741*4882a593Smuzhiyun  * by the OS.  The hardware is still under the drivers control, but
2742*4882a593Smuzhiyun  * needs to be disabled.  A global MAC reset is issued to stop the
2743*4882a593Smuzhiyun  * hardware, and all transmit and receive resources are freed.
2744*4882a593Smuzhiyun  */
atl1_close(struct net_device * netdev)2745*4882a593Smuzhiyun static int atl1_close(struct net_device *netdev)
2746*4882a593Smuzhiyun {
2747*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2748*4882a593Smuzhiyun 	atl1_down(adapter);
2749*4882a593Smuzhiyun 	atl1_free_ring_resources(adapter);
2750*4882a593Smuzhiyun 	return 0;
2751*4882a593Smuzhiyun }
2752*4882a593Smuzhiyun 
2753*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
atl1_suspend(struct device * dev)2754*4882a593Smuzhiyun static int atl1_suspend(struct device *dev)
2755*4882a593Smuzhiyun {
2756*4882a593Smuzhiyun 	struct net_device *netdev = dev_get_drvdata(dev);
2757*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2758*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
2759*4882a593Smuzhiyun 	u32 ctrl = 0;
2760*4882a593Smuzhiyun 	u32 wufc = adapter->wol;
2761*4882a593Smuzhiyun 	u32 val;
2762*4882a593Smuzhiyun 	u16 speed;
2763*4882a593Smuzhiyun 	u16 duplex;
2764*4882a593Smuzhiyun 
2765*4882a593Smuzhiyun 	netif_device_detach(netdev);
2766*4882a593Smuzhiyun 	if (netif_running(netdev))
2767*4882a593Smuzhiyun 		atl1_down(adapter);
2768*4882a593Smuzhiyun 
2769*4882a593Smuzhiyun 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
2770*4882a593Smuzhiyun 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
2771*4882a593Smuzhiyun 	val = ctrl & BMSR_LSTATUS;
2772*4882a593Smuzhiyun 	if (val)
2773*4882a593Smuzhiyun 		wufc &= ~ATLX_WUFC_LNKC;
2774*4882a593Smuzhiyun 	if (!wufc)
2775*4882a593Smuzhiyun 		goto disable_wol;
2776*4882a593Smuzhiyun 
2777*4882a593Smuzhiyun 	if (val) {
2778*4882a593Smuzhiyun 		val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
2779*4882a593Smuzhiyun 		if (val) {
2780*4882a593Smuzhiyun 			if (netif_msg_ifdown(adapter))
2781*4882a593Smuzhiyun 				dev_printk(KERN_DEBUG, dev,
2782*4882a593Smuzhiyun 					"error getting speed/duplex\n");
2783*4882a593Smuzhiyun 			goto disable_wol;
2784*4882a593Smuzhiyun 		}
2785*4882a593Smuzhiyun 
2786*4882a593Smuzhiyun 		ctrl = 0;
2787*4882a593Smuzhiyun 
2788*4882a593Smuzhiyun 		/* enable magic packet WOL */
2789*4882a593Smuzhiyun 		if (wufc & ATLX_WUFC_MAG)
2790*4882a593Smuzhiyun 			ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
2791*4882a593Smuzhiyun 		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
2792*4882a593Smuzhiyun 		ioread32(hw->hw_addr + REG_WOL_CTRL);
2793*4882a593Smuzhiyun 
2794*4882a593Smuzhiyun 		/* configure the mac */
2795*4882a593Smuzhiyun 		ctrl = MAC_CTRL_RX_EN;
2796*4882a593Smuzhiyun 		ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 :
2797*4882a593Smuzhiyun 			MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT);
2798*4882a593Smuzhiyun 		if (duplex == FULL_DUPLEX)
2799*4882a593Smuzhiyun 			ctrl |= MAC_CTRL_DUPLX;
2800*4882a593Smuzhiyun 		ctrl |= (((u32)adapter->hw.preamble_len &
2801*4882a593Smuzhiyun 			MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
2802*4882a593Smuzhiyun 		__atlx_vlan_mode(netdev->features, &ctrl);
2803*4882a593Smuzhiyun 		if (wufc & ATLX_WUFC_MAG)
2804*4882a593Smuzhiyun 			ctrl |= MAC_CTRL_BC_EN;
2805*4882a593Smuzhiyun 		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
2806*4882a593Smuzhiyun 		ioread32(hw->hw_addr + REG_MAC_CTRL);
2807*4882a593Smuzhiyun 
2808*4882a593Smuzhiyun 		/* poke the PHY */
2809*4882a593Smuzhiyun 		ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
2810*4882a593Smuzhiyun 		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
2811*4882a593Smuzhiyun 		iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
2812*4882a593Smuzhiyun 		ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
2813*4882a593Smuzhiyun 	} else {
2814*4882a593Smuzhiyun 		ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
2815*4882a593Smuzhiyun 		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
2816*4882a593Smuzhiyun 		ioread32(hw->hw_addr + REG_WOL_CTRL);
2817*4882a593Smuzhiyun 		iowrite32(0, hw->hw_addr + REG_MAC_CTRL);
2818*4882a593Smuzhiyun 		ioread32(hw->hw_addr + REG_MAC_CTRL);
2819*4882a593Smuzhiyun 		hw->phy_configured = false;
2820*4882a593Smuzhiyun 	}
2821*4882a593Smuzhiyun 
2822*4882a593Smuzhiyun 	return 0;
2823*4882a593Smuzhiyun 
2824*4882a593Smuzhiyun  disable_wol:
2825*4882a593Smuzhiyun 	iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
2826*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_WOL_CTRL);
2827*4882a593Smuzhiyun 	ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
2828*4882a593Smuzhiyun 	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
2829*4882a593Smuzhiyun 	iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
2830*4882a593Smuzhiyun 	ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
2831*4882a593Smuzhiyun 	hw->phy_configured = false;
2832*4882a593Smuzhiyun 
2833*4882a593Smuzhiyun 	return 0;
2834*4882a593Smuzhiyun }
2835*4882a593Smuzhiyun 
atl1_resume(struct device * dev)2836*4882a593Smuzhiyun static int atl1_resume(struct device *dev)
2837*4882a593Smuzhiyun {
2838*4882a593Smuzhiyun 	struct net_device *netdev = dev_get_drvdata(dev);
2839*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2840*4882a593Smuzhiyun 
2841*4882a593Smuzhiyun 	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
2842*4882a593Smuzhiyun 
2843*4882a593Smuzhiyun 	atl1_reset_hw(&adapter->hw);
2844*4882a593Smuzhiyun 
2845*4882a593Smuzhiyun 	if (netif_running(netdev)) {
2846*4882a593Smuzhiyun 		adapter->cmb.cmb->int_stats = 0;
2847*4882a593Smuzhiyun 		atl1_up(adapter);
2848*4882a593Smuzhiyun 	}
2849*4882a593Smuzhiyun 	netif_device_attach(netdev);
2850*4882a593Smuzhiyun 
2851*4882a593Smuzhiyun 	return 0;
2852*4882a593Smuzhiyun }
2853*4882a593Smuzhiyun #endif
2854*4882a593Smuzhiyun 
2855*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume);
2856*4882a593Smuzhiyun 
atl1_shutdown(struct pci_dev * pdev)2857*4882a593Smuzhiyun static void atl1_shutdown(struct pci_dev *pdev)
2858*4882a593Smuzhiyun {
2859*4882a593Smuzhiyun 	struct net_device *netdev = pci_get_drvdata(pdev);
2860*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
2861*4882a593Smuzhiyun 
2862*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
2863*4882a593Smuzhiyun 	atl1_suspend(&pdev->dev);
2864*4882a593Smuzhiyun #endif
2865*4882a593Smuzhiyun 	pci_wake_from_d3(pdev, adapter->wol);
2866*4882a593Smuzhiyun 	pci_set_power_state(pdev, PCI_D3hot);
2867*4882a593Smuzhiyun }
2868*4882a593Smuzhiyun 
2869*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
atl1_poll_controller(struct net_device * netdev)2870*4882a593Smuzhiyun static void atl1_poll_controller(struct net_device *netdev)
2871*4882a593Smuzhiyun {
2872*4882a593Smuzhiyun 	disable_irq(netdev->irq);
2873*4882a593Smuzhiyun 	atl1_intr(netdev->irq, netdev);
2874*4882a593Smuzhiyun 	enable_irq(netdev->irq);
2875*4882a593Smuzhiyun }
2876*4882a593Smuzhiyun #endif
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun static const struct net_device_ops atl1_netdev_ops = {
2879*4882a593Smuzhiyun 	.ndo_open		= atl1_open,
2880*4882a593Smuzhiyun 	.ndo_stop		= atl1_close,
2881*4882a593Smuzhiyun 	.ndo_start_xmit		= atl1_xmit_frame,
2882*4882a593Smuzhiyun 	.ndo_set_rx_mode	= atlx_set_multi,
2883*4882a593Smuzhiyun 	.ndo_validate_addr	= eth_validate_addr,
2884*4882a593Smuzhiyun 	.ndo_set_mac_address	= atl1_set_mac,
2885*4882a593Smuzhiyun 	.ndo_change_mtu		= atl1_change_mtu,
2886*4882a593Smuzhiyun 	.ndo_fix_features	= atlx_fix_features,
2887*4882a593Smuzhiyun 	.ndo_set_features	= atlx_set_features,
2888*4882a593Smuzhiyun 	.ndo_do_ioctl		= atlx_ioctl,
2889*4882a593Smuzhiyun 	.ndo_tx_timeout		= atlx_tx_timeout,
2890*4882a593Smuzhiyun #ifdef CONFIG_NET_POLL_CONTROLLER
2891*4882a593Smuzhiyun 	.ndo_poll_controller	= atl1_poll_controller,
2892*4882a593Smuzhiyun #endif
2893*4882a593Smuzhiyun };
2894*4882a593Smuzhiyun 
2895*4882a593Smuzhiyun /**
2896*4882a593Smuzhiyun  * atl1_probe - Device Initialization Routine
2897*4882a593Smuzhiyun  * @pdev: PCI device information struct
2898*4882a593Smuzhiyun  * @ent: entry in atl1_pci_tbl
2899*4882a593Smuzhiyun  *
2900*4882a593Smuzhiyun  * Returns 0 on success, negative on failure
2901*4882a593Smuzhiyun  *
2902*4882a593Smuzhiyun  * atl1_probe initializes an adapter identified by a pci_dev structure.
2903*4882a593Smuzhiyun  * The OS initialization, configuring of the adapter private structure,
2904*4882a593Smuzhiyun  * and a hardware reset occur.
2905*4882a593Smuzhiyun  */
atl1_probe(struct pci_dev * pdev,const struct pci_device_id * ent)2906*4882a593Smuzhiyun static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2907*4882a593Smuzhiyun {
2908*4882a593Smuzhiyun 	struct net_device *netdev;
2909*4882a593Smuzhiyun 	struct atl1_adapter *adapter;
2910*4882a593Smuzhiyun 	static int cards_found = 0;
2911*4882a593Smuzhiyun 	int err;
2912*4882a593Smuzhiyun 
2913*4882a593Smuzhiyun 	err = pci_enable_device(pdev);
2914*4882a593Smuzhiyun 	if (err)
2915*4882a593Smuzhiyun 		return err;
2916*4882a593Smuzhiyun 
2917*4882a593Smuzhiyun 	/*
2918*4882a593Smuzhiyun 	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single
2919*4882a593Smuzhiyun 	 * shared register for the high 32 bits, so only a single, aligned,
2920*4882a593Smuzhiyun 	 * 4 GB physical address range can be used at a time.
2921*4882a593Smuzhiyun 	 *
2922*4882a593Smuzhiyun 	 * Supporting 64-bit DMA on this hardware is more trouble than it's
2923*4882a593Smuzhiyun 	 * worth.  It is far easier to limit to 32-bit DMA than update
2924*4882a593Smuzhiyun 	 * various kernel subsystems to support the mechanics required by a
2925*4882a593Smuzhiyun 	 * fixed-high-32-bit system.
2926*4882a593Smuzhiyun 	 */
2927*4882a593Smuzhiyun 	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
2928*4882a593Smuzhiyun 	if (err) {
2929*4882a593Smuzhiyun 		dev_err(&pdev->dev, "no usable DMA configuration\n");
2930*4882a593Smuzhiyun 		goto err_dma;
2931*4882a593Smuzhiyun 	}
2932*4882a593Smuzhiyun 	/*
2933*4882a593Smuzhiyun 	 * Mark all PCI regions associated with PCI device
2934*4882a593Smuzhiyun 	 * pdev as being reserved by owner atl1_driver_name
2935*4882a593Smuzhiyun 	 */
2936*4882a593Smuzhiyun 	err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
2937*4882a593Smuzhiyun 	if (err)
2938*4882a593Smuzhiyun 		goto err_request_regions;
2939*4882a593Smuzhiyun 
2940*4882a593Smuzhiyun 	/*
2941*4882a593Smuzhiyun 	 * Enables bus-mastering on the device and calls
2942*4882a593Smuzhiyun 	 * pcibios_set_master to do the needed arch specific settings
2943*4882a593Smuzhiyun 	 */
2944*4882a593Smuzhiyun 	pci_set_master(pdev);
2945*4882a593Smuzhiyun 
2946*4882a593Smuzhiyun 	netdev = alloc_etherdev(sizeof(struct atl1_adapter));
2947*4882a593Smuzhiyun 	if (!netdev) {
2948*4882a593Smuzhiyun 		err = -ENOMEM;
2949*4882a593Smuzhiyun 		goto err_alloc_etherdev;
2950*4882a593Smuzhiyun 	}
2951*4882a593Smuzhiyun 	SET_NETDEV_DEV(netdev, &pdev->dev);
2952*4882a593Smuzhiyun 
2953*4882a593Smuzhiyun 	pci_set_drvdata(pdev, netdev);
2954*4882a593Smuzhiyun 	adapter = netdev_priv(netdev);
2955*4882a593Smuzhiyun 	adapter->netdev = netdev;
2956*4882a593Smuzhiyun 	adapter->pdev = pdev;
2957*4882a593Smuzhiyun 	adapter->hw.back = adapter;
2958*4882a593Smuzhiyun 	adapter->msg_enable = netif_msg_init(debug, atl1_default_msg);
2959*4882a593Smuzhiyun 
2960*4882a593Smuzhiyun 	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
2961*4882a593Smuzhiyun 	if (!adapter->hw.hw_addr) {
2962*4882a593Smuzhiyun 		err = -EIO;
2963*4882a593Smuzhiyun 		goto err_pci_iomap;
2964*4882a593Smuzhiyun 	}
2965*4882a593Smuzhiyun 	/* get device revision number */
2966*4882a593Smuzhiyun 	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
2967*4882a593Smuzhiyun 		(REG_MASTER_CTRL + 2));
2968*4882a593Smuzhiyun 
2969*4882a593Smuzhiyun 	/* set default ring resource counts */
2970*4882a593Smuzhiyun 	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
2971*4882a593Smuzhiyun 	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
2972*4882a593Smuzhiyun 
2973*4882a593Smuzhiyun 	adapter->mii.dev = netdev;
2974*4882a593Smuzhiyun 	adapter->mii.mdio_read = mdio_read;
2975*4882a593Smuzhiyun 	adapter->mii.mdio_write = mdio_write;
2976*4882a593Smuzhiyun 	adapter->mii.phy_id_mask = 0x1f;
2977*4882a593Smuzhiyun 	adapter->mii.reg_num_mask = 0x1f;
2978*4882a593Smuzhiyun 
2979*4882a593Smuzhiyun 	netdev->netdev_ops = &atl1_netdev_ops;
2980*4882a593Smuzhiyun 	netdev->watchdog_timeo = 5 * HZ;
2981*4882a593Smuzhiyun 	netif_napi_add(netdev, &adapter->napi, atl1_rings_clean, 64);
2982*4882a593Smuzhiyun 
2983*4882a593Smuzhiyun 	netdev->ethtool_ops = &atl1_ethtool_ops;
2984*4882a593Smuzhiyun 	adapter->bd_number = cards_found;
2985*4882a593Smuzhiyun 
2986*4882a593Smuzhiyun 	/* setup the private structure */
2987*4882a593Smuzhiyun 	err = atl1_sw_init(adapter);
2988*4882a593Smuzhiyun 	if (err)
2989*4882a593Smuzhiyun 		goto err_common;
2990*4882a593Smuzhiyun 
2991*4882a593Smuzhiyun 	netdev->features = NETIF_F_HW_CSUM;
2992*4882a593Smuzhiyun 	netdev->features |= NETIF_F_SG;
2993*4882a593Smuzhiyun 	netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
2994*4882a593Smuzhiyun 
2995*4882a593Smuzhiyun 	netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_TSO |
2996*4882a593Smuzhiyun 			      NETIF_F_HW_VLAN_CTAG_RX;
2997*4882a593Smuzhiyun 
2998*4882a593Smuzhiyun 	/* is this valid? see atl1_setup_mac_ctrl() */
2999*4882a593Smuzhiyun 	netdev->features |= NETIF_F_RXCSUM;
3000*4882a593Smuzhiyun 
3001*4882a593Smuzhiyun 	/* MTU range: 42 - 10218 */
3002*4882a593Smuzhiyun 	netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
3003*4882a593Smuzhiyun 	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
3004*4882a593Smuzhiyun 			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
3005*4882a593Smuzhiyun 
3006*4882a593Smuzhiyun 	/*
3007*4882a593Smuzhiyun 	 * patch for some L1 of old version,
3008*4882a593Smuzhiyun 	 * the final version of L1 may not need these
3009*4882a593Smuzhiyun 	 * patches
3010*4882a593Smuzhiyun 	 */
3011*4882a593Smuzhiyun 	/* atl1_pcie_patch(adapter); */
3012*4882a593Smuzhiyun 
3013*4882a593Smuzhiyun 	/* really reset GPHY core */
3014*4882a593Smuzhiyun 	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
3015*4882a593Smuzhiyun 
3016*4882a593Smuzhiyun 	/*
3017*4882a593Smuzhiyun 	 * reset the controller to
3018*4882a593Smuzhiyun 	 * put the device in a known good starting state
3019*4882a593Smuzhiyun 	 */
3020*4882a593Smuzhiyun 	if (atl1_reset_hw(&adapter->hw)) {
3021*4882a593Smuzhiyun 		err = -EIO;
3022*4882a593Smuzhiyun 		goto err_common;
3023*4882a593Smuzhiyun 	}
3024*4882a593Smuzhiyun 
3025*4882a593Smuzhiyun 	/* copy the MAC address out of the EEPROM */
3026*4882a593Smuzhiyun 	if (atl1_read_mac_addr(&adapter->hw)) {
3027*4882a593Smuzhiyun 		/* mark random mac */
3028*4882a593Smuzhiyun 		netdev->addr_assign_type = NET_ADDR_RANDOM;
3029*4882a593Smuzhiyun 	}
3030*4882a593Smuzhiyun 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
3031*4882a593Smuzhiyun 
3032*4882a593Smuzhiyun 	if (!is_valid_ether_addr(netdev->dev_addr)) {
3033*4882a593Smuzhiyun 		err = -EIO;
3034*4882a593Smuzhiyun 		goto err_common;
3035*4882a593Smuzhiyun 	}
3036*4882a593Smuzhiyun 
3037*4882a593Smuzhiyun 	atl1_check_options(adapter);
3038*4882a593Smuzhiyun 
3039*4882a593Smuzhiyun 	/* pre-init the MAC, and setup link */
3040*4882a593Smuzhiyun 	err = atl1_init_hw(&adapter->hw);
3041*4882a593Smuzhiyun 	if (err) {
3042*4882a593Smuzhiyun 		err = -EIO;
3043*4882a593Smuzhiyun 		goto err_common;
3044*4882a593Smuzhiyun 	}
3045*4882a593Smuzhiyun 
3046*4882a593Smuzhiyun 	atl1_pcie_patch(adapter);
3047*4882a593Smuzhiyun 	/* assume we have no link for now */
3048*4882a593Smuzhiyun 	netif_carrier_off(netdev);
3049*4882a593Smuzhiyun 
3050*4882a593Smuzhiyun 	timer_setup(&adapter->phy_config_timer, atl1_phy_config, 0);
3051*4882a593Smuzhiyun 	adapter->phy_timer_pending = false;
3052*4882a593Smuzhiyun 
3053*4882a593Smuzhiyun 	INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task);
3054*4882a593Smuzhiyun 
3055*4882a593Smuzhiyun 	INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
3056*4882a593Smuzhiyun 
3057*4882a593Smuzhiyun 	err = register_netdev(netdev);
3058*4882a593Smuzhiyun 	if (err)
3059*4882a593Smuzhiyun 		goto err_common;
3060*4882a593Smuzhiyun 
3061*4882a593Smuzhiyun 	cards_found++;
3062*4882a593Smuzhiyun 	atl1_via_workaround(adapter);
3063*4882a593Smuzhiyun 	return 0;
3064*4882a593Smuzhiyun 
3065*4882a593Smuzhiyun err_common:
3066*4882a593Smuzhiyun 	pci_iounmap(pdev, adapter->hw.hw_addr);
3067*4882a593Smuzhiyun err_pci_iomap:
3068*4882a593Smuzhiyun 	free_netdev(netdev);
3069*4882a593Smuzhiyun err_alloc_etherdev:
3070*4882a593Smuzhiyun 	pci_release_regions(pdev);
3071*4882a593Smuzhiyun err_dma:
3072*4882a593Smuzhiyun err_request_regions:
3073*4882a593Smuzhiyun 	pci_disable_device(pdev);
3074*4882a593Smuzhiyun 	return err;
3075*4882a593Smuzhiyun }
3076*4882a593Smuzhiyun 
3077*4882a593Smuzhiyun /**
3078*4882a593Smuzhiyun  * atl1_remove - Device Removal Routine
3079*4882a593Smuzhiyun  * @pdev: PCI device information struct
3080*4882a593Smuzhiyun  *
3081*4882a593Smuzhiyun  * atl1_remove is called by the PCI subsystem to alert the driver
3082*4882a593Smuzhiyun  * that it should release a PCI device.  The could be caused by a
3083*4882a593Smuzhiyun  * Hot-Plug event, or because the driver is going to be removed from
3084*4882a593Smuzhiyun  * memory.
3085*4882a593Smuzhiyun  */
atl1_remove(struct pci_dev * pdev)3086*4882a593Smuzhiyun static void atl1_remove(struct pci_dev *pdev)
3087*4882a593Smuzhiyun {
3088*4882a593Smuzhiyun 	struct net_device *netdev = pci_get_drvdata(pdev);
3089*4882a593Smuzhiyun 	struct atl1_adapter *adapter;
3090*4882a593Smuzhiyun 	/* Device not available. Return. */
3091*4882a593Smuzhiyun 	if (!netdev)
3092*4882a593Smuzhiyun 		return;
3093*4882a593Smuzhiyun 
3094*4882a593Smuzhiyun 	adapter = netdev_priv(netdev);
3095*4882a593Smuzhiyun 
3096*4882a593Smuzhiyun 	/*
3097*4882a593Smuzhiyun 	 * Some atl1 boards lack persistent storage for their MAC, and get it
3098*4882a593Smuzhiyun 	 * from the BIOS during POST.  If we've been messing with the MAC
3099*4882a593Smuzhiyun 	 * address, we need to save the permanent one.
3100*4882a593Smuzhiyun 	 */
3101*4882a593Smuzhiyun 	if (!ether_addr_equal_unaligned(adapter->hw.mac_addr,
3102*4882a593Smuzhiyun 					adapter->hw.perm_mac_addr)) {
3103*4882a593Smuzhiyun 		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
3104*4882a593Smuzhiyun 			ETH_ALEN);
3105*4882a593Smuzhiyun 		atl1_set_mac_addr(&adapter->hw);
3106*4882a593Smuzhiyun 	}
3107*4882a593Smuzhiyun 
3108*4882a593Smuzhiyun 	iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
3109*4882a593Smuzhiyun 	unregister_netdev(netdev);
3110*4882a593Smuzhiyun 	pci_iounmap(pdev, adapter->hw.hw_addr);
3111*4882a593Smuzhiyun 	pci_release_regions(pdev);
3112*4882a593Smuzhiyun 	free_netdev(netdev);
3113*4882a593Smuzhiyun 	pci_disable_device(pdev);
3114*4882a593Smuzhiyun }
3115*4882a593Smuzhiyun 
3116*4882a593Smuzhiyun static struct pci_driver atl1_driver = {
3117*4882a593Smuzhiyun 	.name = ATLX_DRIVER_NAME,
3118*4882a593Smuzhiyun 	.id_table = atl1_pci_tbl,
3119*4882a593Smuzhiyun 	.probe = atl1_probe,
3120*4882a593Smuzhiyun 	.remove = atl1_remove,
3121*4882a593Smuzhiyun 	.shutdown = atl1_shutdown,
3122*4882a593Smuzhiyun 	.driver.pm = &atl1_pm_ops,
3123*4882a593Smuzhiyun };
3124*4882a593Smuzhiyun 
3125*4882a593Smuzhiyun struct atl1_stats {
3126*4882a593Smuzhiyun 	char stat_string[ETH_GSTRING_LEN];
3127*4882a593Smuzhiyun 	int sizeof_stat;
3128*4882a593Smuzhiyun 	int stat_offset;
3129*4882a593Smuzhiyun };
3130*4882a593Smuzhiyun 
3131*4882a593Smuzhiyun #define ATL1_STAT(m) \
3132*4882a593Smuzhiyun 	sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
3133*4882a593Smuzhiyun 
3134*4882a593Smuzhiyun static struct atl1_stats atl1_gstrings_stats[] = {
3135*4882a593Smuzhiyun 	{"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
3136*4882a593Smuzhiyun 	{"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
3137*4882a593Smuzhiyun 	{"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
3138*4882a593Smuzhiyun 	{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
3139*4882a593Smuzhiyun 	{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
3140*4882a593Smuzhiyun 	{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
3141*4882a593Smuzhiyun 	{"multicast", ATL1_STAT(soft_stats.multicast)},
3142*4882a593Smuzhiyun 	{"collisions", ATL1_STAT(soft_stats.collisions)},
3143*4882a593Smuzhiyun 	{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
3144*4882a593Smuzhiyun 	{"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
3145*4882a593Smuzhiyun 	{"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
3146*4882a593Smuzhiyun 	{"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
3147*4882a593Smuzhiyun 	{"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
3148*4882a593Smuzhiyun 	{"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
3149*4882a593Smuzhiyun 	{"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
3150*4882a593Smuzhiyun 	{"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
3151*4882a593Smuzhiyun 	{"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
3152*4882a593Smuzhiyun 	{"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
3153*4882a593Smuzhiyun 	{"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
3154*4882a593Smuzhiyun 	{"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
3155*4882a593Smuzhiyun 	{"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
3156*4882a593Smuzhiyun 	{"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
3157*4882a593Smuzhiyun 	{"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
3158*4882a593Smuzhiyun 	{"tx_underrun", ATL1_STAT(soft_stats.tx_underrun)},
3159*4882a593Smuzhiyun 	{"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
3160*4882a593Smuzhiyun 	{"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
3161*4882a593Smuzhiyun 	{"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
3162*4882a593Smuzhiyun 	{"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
3163*4882a593Smuzhiyun 	{"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
3164*4882a593Smuzhiyun };
3165*4882a593Smuzhiyun 
atl1_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)3166*4882a593Smuzhiyun static void atl1_get_ethtool_stats(struct net_device *netdev,
3167*4882a593Smuzhiyun 	struct ethtool_stats *stats, u64 *data)
3168*4882a593Smuzhiyun {
3169*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3170*4882a593Smuzhiyun 	int i;
3171*4882a593Smuzhiyun 	char *p;
3172*4882a593Smuzhiyun 
3173*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
3174*4882a593Smuzhiyun 		p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
3175*4882a593Smuzhiyun 		data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
3176*4882a593Smuzhiyun 			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
3177*4882a593Smuzhiyun 	}
3178*4882a593Smuzhiyun 
3179*4882a593Smuzhiyun }
3180*4882a593Smuzhiyun 
atl1_get_sset_count(struct net_device * netdev,int sset)3181*4882a593Smuzhiyun static int atl1_get_sset_count(struct net_device *netdev, int sset)
3182*4882a593Smuzhiyun {
3183*4882a593Smuzhiyun 	switch (sset) {
3184*4882a593Smuzhiyun 	case ETH_SS_STATS:
3185*4882a593Smuzhiyun 		return ARRAY_SIZE(atl1_gstrings_stats);
3186*4882a593Smuzhiyun 	default:
3187*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3188*4882a593Smuzhiyun 	}
3189*4882a593Smuzhiyun }
3190*4882a593Smuzhiyun 
atl1_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)3191*4882a593Smuzhiyun static int atl1_get_link_ksettings(struct net_device *netdev,
3192*4882a593Smuzhiyun 				   struct ethtool_link_ksettings *cmd)
3193*4882a593Smuzhiyun {
3194*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3195*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3196*4882a593Smuzhiyun 	u32 supported, advertising;
3197*4882a593Smuzhiyun 
3198*4882a593Smuzhiyun 	supported = (SUPPORTED_10baseT_Half |
3199*4882a593Smuzhiyun 			   SUPPORTED_10baseT_Full |
3200*4882a593Smuzhiyun 			   SUPPORTED_100baseT_Half |
3201*4882a593Smuzhiyun 			   SUPPORTED_100baseT_Full |
3202*4882a593Smuzhiyun 			   SUPPORTED_1000baseT_Full |
3203*4882a593Smuzhiyun 			   SUPPORTED_Autoneg | SUPPORTED_TP);
3204*4882a593Smuzhiyun 	advertising = ADVERTISED_TP;
3205*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3206*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
3207*4882a593Smuzhiyun 		advertising |= ADVERTISED_Autoneg;
3208*4882a593Smuzhiyun 		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
3209*4882a593Smuzhiyun 			advertising |= ADVERTISED_Autoneg;
3210*4882a593Smuzhiyun 			advertising |=
3211*4882a593Smuzhiyun 			    (ADVERTISED_10baseT_Half |
3212*4882a593Smuzhiyun 			     ADVERTISED_10baseT_Full |
3213*4882a593Smuzhiyun 			     ADVERTISED_100baseT_Half |
3214*4882a593Smuzhiyun 			     ADVERTISED_100baseT_Full |
3215*4882a593Smuzhiyun 			     ADVERTISED_1000baseT_Full);
3216*4882a593Smuzhiyun 		} else
3217*4882a593Smuzhiyun 			advertising |= (ADVERTISED_1000baseT_Full);
3218*4882a593Smuzhiyun 	}
3219*4882a593Smuzhiyun 	cmd->base.port = PORT_TP;
3220*4882a593Smuzhiyun 	cmd->base.phy_address = 0;
3221*4882a593Smuzhiyun 
3222*4882a593Smuzhiyun 	if (netif_carrier_ok(adapter->netdev)) {
3223*4882a593Smuzhiyun 		u16 link_speed, link_duplex;
3224*4882a593Smuzhiyun 		atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
3225*4882a593Smuzhiyun 		cmd->base.speed = link_speed;
3226*4882a593Smuzhiyun 		if (link_duplex == FULL_DUPLEX)
3227*4882a593Smuzhiyun 			cmd->base.duplex = DUPLEX_FULL;
3228*4882a593Smuzhiyun 		else
3229*4882a593Smuzhiyun 			cmd->base.duplex = DUPLEX_HALF;
3230*4882a593Smuzhiyun 	} else {
3231*4882a593Smuzhiyun 		cmd->base.speed = SPEED_UNKNOWN;
3232*4882a593Smuzhiyun 		cmd->base.duplex = DUPLEX_UNKNOWN;
3233*4882a593Smuzhiyun 	}
3234*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3235*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL)
3236*4882a593Smuzhiyun 		cmd->base.autoneg = AUTONEG_ENABLE;
3237*4882a593Smuzhiyun 	else
3238*4882a593Smuzhiyun 		cmd->base.autoneg = AUTONEG_DISABLE;
3239*4882a593Smuzhiyun 
3240*4882a593Smuzhiyun 	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
3241*4882a593Smuzhiyun 						supported);
3242*4882a593Smuzhiyun 	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
3243*4882a593Smuzhiyun 						advertising);
3244*4882a593Smuzhiyun 
3245*4882a593Smuzhiyun 	return 0;
3246*4882a593Smuzhiyun }
3247*4882a593Smuzhiyun 
atl1_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)3248*4882a593Smuzhiyun static int atl1_set_link_ksettings(struct net_device *netdev,
3249*4882a593Smuzhiyun 				   const struct ethtool_link_ksettings *cmd)
3250*4882a593Smuzhiyun {
3251*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3252*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3253*4882a593Smuzhiyun 	u16 phy_data;
3254*4882a593Smuzhiyun 	int ret_val = 0;
3255*4882a593Smuzhiyun 	u16 old_media_type = hw->media_type;
3256*4882a593Smuzhiyun 
3257*4882a593Smuzhiyun 	if (netif_running(adapter->netdev)) {
3258*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
3259*4882a593Smuzhiyun 			dev_dbg(&adapter->pdev->dev,
3260*4882a593Smuzhiyun 				"ethtool shutting down adapter\n");
3261*4882a593Smuzhiyun 		atl1_down(adapter);
3262*4882a593Smuzhiyun 	}
3263*4882a593Smuzhiyun 
3264*4882a593Smuzhiyun 	if (cmd->base.autoneg == AUTONEG_ENABLE)
3265*4882a593Smuzhiyun 		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
3266*4882a593Smuzhiyun 	else {
3267*4882a593Smuzhiyun 		u32 speed = cmd->base.speed;
3268*4882a593Smuzhiyun 		if (speed == SPEED_1000) {
3269*4882a593Smuzhiyun 			if (cmd->base.duplex != DUPLEX_FULL) {
3270*4882a593Smuzhiyun 				if (netif_msg_link(adapter))
3271*4882a593Smuzhiyun 					dev_warn(&adapter->pdev->dev,
3272*4882a593Smuzhiyun 						"1000M half is invalid\n");
3273*4882a593Smuzhiyun 				ret_val = -EINVAL;
3274*4882a593Smuzhiyun 				goto exit_sset;
3275*4882a593Smuzhiyun 			}
3276*4882a593Smuzhiyun 			hw->media_type = MEDIA_TYPE_1000M_FULL;
3277*4882a593Smuzhiyun 		} else if (speed == SPEED_100) {
3278*4882a593Smuzhiyun 			if (cmd->base.duplex == DUPLEX_FULL)
3279*4882a593Smuzhiyun 				hw->media_type = MEDIA_TYPE_100M_FULL;
3280*4882a593Smuzhiyun 			else
3281*4882a593Smuzhiyun 				hw->media_type = MEDIA_TYPE_100M_HALF;
3282*4882a593Smuzhiyun 		} else {
3283*4882a593Smuzhiyun 			if (cmd->base.duplex == DUPLEX_FULL)
3284*4882a593Smuzhiyun 				hw->media_type = MEDIA_TYPE_10M_FULL;
3285*4882a593Smuzhiyun 			else
3286*4882a593Smuzhiyun 				hw->media_type = MEDIA_TYPE_10M_HALF;
3287*4882a593Smuzhiyun 		}
3288*4882a593Smuzhiyun 	}
3289*4882a593Smuzhiyun 
3290*4882a593Smuzhiyun 	if (atl1_phy_setup_autoneg_adv(hw)) {
3291*4882a593Smuzhiyun 		ret_val = -EINVAL;
3292*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
3293*4882a593Smuzhiyun 			dev_warn(&adapter->pdev->dev,
3294*4882a593Smuzhiyun 				"invalid ethtool speed/duplex setting\n");
3295*4882a593Smuzhiyun 		goto exit_sset;
3296*4882a593Smuzhiyun 	}
3297*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3298*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL)
3299*4882a593Smuzhiyun 		phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
3300*4882a593Smuzhiyun 	else {
3301*4882a593Smuzhiyun 		switch (hw->media_type) {
3302*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_FULL:
3303*4882a593Smuzhiyun 			phy_data =
3304*4882a593Smuzhiyun 			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
3305*4882a593Smuzhiyun 			    MII_CR_RESET;
3306*4882a593Smuzhiyun 			break;
3307*4882a593Smuzhiyun 		case MEDIA_TYPE_100M_HALF:
3308*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
3309*4882a593Smuzhiyun 			break;
3310*4882a593Smuzhiyun 		case MEDIA_TYPE_10M_FULL:
3311*4882a593Smuzhiyun 			phy_data =
3312*4882a593Smuzhiyun 			    MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
3313*4882a593Smuzhiyun 			break;
3314*4882a593Smuzhiyun 		default:
3315*4882a593Smuzhiyun 			/* MEDIA_TYPE_10M_HALF: */
3316*4882a593Smuzhiyun 			phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
3317*4882a593Smuzhiyun 			break;
3318*4882a593Smuzhiyun 		}
3319*4882a593Smuzhiyun 	}
3320*4882a593Smuzhiyun 	atl1_write_phy_reg(hw, MII_BMCR, phy_data);
3321*4882a593Smuzhiyun exit_sset:
3322*4882a593Smuzhiyun 	if (ret_val)
3323*4882a593Smuzhiyun 		hw->media_type = old_media_type;
3324*4882a593Smuzhiyun 
3325*4882a593Smuzhiyun 	if (netif_running(adapter->netdev)) {
3326*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
3327*4882a593Smuzhiyun 			dev_dbg(&adapter->pdev->dev,
3328*4882a593Smuzhiyun 				"ethtool starting adapter\n");
3329*4882a593Smuzhiyun 		atl1_up(adapter);
3330*4882a593Smuzhiyun 	} else if (!ret_val) {
3331*4882a593Smuzhiyun 		if (netif_msg_link(adapter))
3332*4882a593Smuzhiyun 			dev_dbg(&adapter->pdev->dev,
3333*4882a593Smuzhiyun 				"ethtool resetting adapter\n");
3334*4882a593Smuzhiyun 		atl1_reset(adapter);
3335*4882a593Smuzhiyun 	}
3336*4882a593Smuzhiyun 	return ret_val;
3337*4882a593Smuzhiyun }
3338*4882a593Smuzhiyun 
atl1_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)3339*4882a593Smuzhiyun static void atl1_get_drvinfo(struct net_device *netdev,
3340*4882a593Smuzhiyun 	struct ethtool_drvinfo *drvinfo)
3341*4882a593Smuzhiyun {
3342*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3343*4882a593Smuzhiyun 
3344*4882a593Smuzhiyun 	strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
3345*4882a593Smuzhiyun 	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
3346*4882a593Smuzhiyun 		sizeof(drvinfo->bus_info));
3347*4882a593Smuzhiyun }
3348*4882a593Smuzhiyun 
atl1_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)3349*4882a593Smuzhiyun static void atl1_get_wol(struct net_device *netdev,
3350*4882a593Smuzhiyun 	struct ethtool_wolinfo *wol)
3351*4882a593Smuzhiyun {
3352*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3353*4882a593Smuzhiyun 
3354*4882a593Smuzhiyun 	wol->supported = WAKE_MAGIC;
3355*4882a593Smuzhiyun 	wol->wolopts = 0;
3356*4882a593Smuzhiyun 	if (adapter->wol & ATLX_WUFC_MAG)
3357*4882a593Smuzhiyun 		wol->wolopts |= WAKE_MAGIC;
3358*4882a593Smuzhiyun }
3359*4882a593Smuzhiyun 
atl1_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)3360*4882a593Smuzhiyun static int atl1_set_wol(struct net_device *netdev,
3361*4882a593Smuzhiyun 	struct ethtool_wolinfo *wol)
3362*4882a593Smuzhiyun {
3363*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3364*4882a593Smuzhiyun 
3365*4882a593Smuzhiyun 	if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
3366*4882a593Smuzhiyun 		WAKE_ARP | WAKE_MAGICSECURE))
3367*4882a593Smuzhiyun 		return -EOPNOTSUPP;
3368*4882a593Smuzhiyun 	adapter->wol = 0;
3369*4882a593Smuzhiyun 	if (wol->wolopts & WAKE_MAGIC)
3370*4882a593Smuzhiyun 		adapter->wol |= ATLX_WUFC_MAG;
3371*4882a593Smuzhiyun 
3372*4882a593Smuzhiyun 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
3373*4882a593Smuzhiyun 
3374*4882a593Smuzhiyun 	return 0;
3375*4882a593Smuzhiyun }
3376*4882a593Smuzhiyun 
atl1_get_msglevel(struct net_device * netdev)3377*4882a593Smuzhiyun static u32 atl1_get_msglevel(struct net_device *netdev)
3378*4882a593Smuzhiyun {
3379*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3380*4882a593Smuzhiyun 	return adapter->msg_enable;
3381*4882a593Smuzhiyun }
3382*4882a593Smuzhiyun 
atl1_set_msglevel(struct net_device * netdev,u32 value)3383*4882a593Smuzhiyun static void atl1_set_msglevel(struct net_device *netdev, u32 value)
3384*4882a593Smuzhiyun {
3385*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3386*4882a593Smuzhiyun 	adapter->msg_enable = value;
3387*4882a593Smuzhiyun }
3388*4882a593Smuzhiyun 
atl1_get_regs_len(struct net_device * netdev)3389*4882a593Smuzhiyun static int atl1_get_regs_len(struct net_device *netdev)
3390*4882a593Smuzhiyun {
3391*4882a593Smuzhiyun 	return ATL1_REG_COUNT * sizeof(u32);
3392*4882a593Smuzhiyun }
3393*4882a593Smuzhiyun 
atl1_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * p)3394*4882a593Smuzhiyun static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
3395*4882a593Smuzhiyun 	void *p)
3396*4882a593Smuzhiyun {
3397*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3398*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3399*4882a593Smuzhiyun 	unsigned int i;
3400*4882a593Smuzhiyun 	u32 *regbuf = p;
3401*4882a593Smuzhiyun 
3402*4882a593Smuzhiyun 	for (i = 0; i < ATL1_REG_COUNT; i++) {
3403*4882a593Smuzhiyun 		/*
3404*4882a593Smuzhiyun 		 * This switch statement avoids reserved regions
3405*4882a593Smuzhiyun 		 * of register space.
3406*4882a593Smuzhiyun 		 */
3407*4882a593Smuzhiyun 		switch (i) {
3408*4882a593Smuzhiyun 		case 6 ... 9:
3409*4882a593Smuzhiyun 		case 14:
3410*4882a593Smuzhiyun 		case 29 ... 31:
3411*4882a593Smuzhiyun 		case 34 ... 63:
3412*4882a593Smuzhiyun 		case 75 ... 127:
3413*4882a593Smuzhiyun 		case 136 ... 1023:
3414*4882a593Smuzhiyun 		case 1027 ... 1087:
3415*4882a593Smuzhiyun 		case 1091 ... 1151:
3416*4882a593Smuzhiyun 		case 1194 ... 1195:
3417*4882a593Smuzhiyun 		case 1200 ... 1201:
3418*4882a593Smuzhiyun 		case 1206 ... 1213:
3419*4882a593Smuzhiyun 		case 1216 ... 1279:
3420*4882a593Smuzhiyun 		case 1290 ... 1311:
3421*4882a593Smuzhiyun 		case 1323 ... 1343:
3422*4882a593Smuzhiyun 		case 1358 ... 1359:
3423*4882a593Smuzhiyun 		case 1368 ... 1375:
3424*4882a593Smuzhiyun 		case 1378 ... 1383:
3425*4882a593Smuzhiyun 		case 1388 ... 1391:
3426*4882a593Smuzhiyun 		case 1393 ... 1395:
3427*4882a593Smuzhiyun 		case 1402 ... 1403:
3428*4882a593Smuzhiyun 		case 1410 ... 1471:
3429*4882a593Smuzhiyun 		case 1522 ... 1535:
3430*4882a593Smuzhiyun 			/* reserved region; don't read it */
3431*4882a593Smuzhiyun 			regbuf[i] = 0;
3432*4882a593Smuzhiyun 			break;
3433*4882a593Smuzhiyun 		default:
3434*4882a593Smuzhiyun 			/* unreserved region */
3435*4882a593Smuzhiyun 			regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
3436*4882a593Smuzhiyun 		}
3437*4882a593Smuzhiyun 	}
3438*4882a593Smuzhiyun }
3439*4882a593Smuzhiyun 
atl1_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring)3440*4882a593Smuzhiyun static void atl1_get_ringparam(struct net_device *netdev,
3441*4882a593Smuzhiyun 	struct ethtool_ringparam *ring)
3442*4882a593Smuzhiyun {
3443*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3444*4882a593Smuzhiyun 	struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
3445*4882a593Smuzhiyun 	struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
3446*4882a593Smuzhiyun 
3447*4882a593Smuzhiyun 	ring->rx_max_pending = ATL1_MAX_RFD;
3448*4882a593Smuzhiyun 	ring->tx_max_pending = ATL1_MAX_TPD;
3449*4882a593Smuzhiyun 	ring->rx_pending = rxdr->count;
3450*4882a593Smuzhiyun 	ring->tx_pending = txdr->count;
3451*4882a593Smuzhiyun }
3452*4882a593Smuzhiyun 
atl1_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring)3453*4882a593Smuzhiyun static int atl1_set_ringparam(struct net_device *netdev,
3454*4882a593Smuzhiyun 	struct ethtool_ringparam *ring)
3455*4882a593Smuzhiyun {
3456*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3457*4882a593Smuzhiyun 	struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
3458*4882a593Smuzhiyun 	struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
3459*4882a593Smuzhiyun 	struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun 	struct atl1_tpd_ring tpd_old, tpd_new;
3462*4882a593Smuzhiyun 	struct atl1_rfd_ring rfd_old, rfd_new;
3463*4882a593Smuzhiyun 	struct atl1_rrd_ring rrd_old, rrd_new;
3464*4882a593Smuzhiyun 	struct atl1_ring_header rhdr_old, rhdr_new;
3465*4882a593Smuzhiyun 	struct atl1_smb smb;
3466*4882a593Smuzhiyun 	struct atl1_cmb cmb;
3467*4882a593Smuzhiyun 	int err;
3468*4882a593Smuzhiyun 
3469*4882a593Smuzhiyun 	tpd_old = adapter->tpd_ring;
3470*4882a593Smuzhiyun 	rfd_old = adapter->rfd_ring;
3471*4882a593Smuzhiyun 	rrd_old = adapter->rrd_ring;
3472*4882a593Smuzhiyun 	rhdr_old = adapter->ring_header;
3473*4882a593Smuzhiyun 
3474*4882a593Smuzhiyun 	if (netif_running(adapter->netdev))
3475*4882a593Smuzhiyun 		atl1_down(adapter);
3476*4882a593Smuzhiyun 
3477*4882a593Smuzhiyun 	rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
3478*4882a593Smuzhiyun 	rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
3479*4882a593Smuzhiyun 			rfdr->count;
3480*4882a593Smuzhiyun 	rfdr->count = (rfdr->count + 3) & ~3;
3481*4882a593Smuzhiyun 	rrdr->count = rfdr->count;
3482*4882a593Smuzhiyun 
3483*4882a593Smuzhiyun 	tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
3484*4882a593Smuzhiyun 	tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
3485*4882a593Smuzhiyun 			tpdr->count;
3486*4882a593Smuzhiyun 	tpdr->count = (tpdr->count + 3) & ~3;
3487*4882a593Smuzhiyun 
3488*4882a593Smuzhiyun 	if (netif_running(adapter->netdev)) {
3489*4882a593Smuzhiyun 		/* try to get new resources before deleting old */
3490*4882a593Smuzhiyun 		err = atl1_setup_ring_resources(adapter);
3491*4882a593Smuzhiyun 		if (err)
3492*4882a593Smuzhiyun 			goto err_setup_ring;
3493*4882a593Smuzhiyun 
3494*4882a593Smuzhiyun 		/*
3495*4882a593Smuzhiyun 		 * save the new, restore the old in order to free it,
3496*4882a593Smuzhiyun 		 * then restore the new back again
3497*4882a593Smuzhiyun 		 */
3498*4882a593Smuzhiyun 
3499*4882a593Smuzhiyun 		rfd_new = adapter->rfd_ring;
3500*4882a593Smuzhiyun 		rrd_new = adapter->rrd_ring;
3501*4882a593Smuzhiyun 		tpd_new = adapter->tpd_ring;
3502*4882a593Smuzhiyun 		rhdr_new = adapter->ring_header;
3503*4882a593Smuzhiyun 		adapter->rfd_ring = rfd_old;
3504*4882a593Smuzhiyun 		adapter->rrd_ring = rrd_old;
3505*4882a593Smuzhiyun 		adapter->tpd_ring = tpd_old;
3506*4882a593Smuzhiyun 		adapter->ring_header = rhdr_old;
3507*4882a593Smuzhiyun 		/*
3508*4882a593Smuzhiyun 		 * Save SMB and CMB, since atl1_free_ring_resources
3509*4882a593Smuzhiyun 		 * will clear them.
3510*4882a593Smuzhiyun 		 */
3511*4882a593Smuzhiyun 		smb = adapter->smb;
3512*4882a593Smuzhiyun 		cmb = adapter->cmb;
3513*4882a593Smuzhiyun 		atl1_free_ring_resources(adapter);
3514*4882a593Smuzhiyun 		adapter->rfd_ring = rfd_new;
3515*4882a593Smuzhiyun 		adapter->rrd_ring = rrd_new;
3516*4882a593Smuzhiyun 		adapter->tpd_ring = tpd_new;
3517*4882a593Smuzhiyun 		adapter->ring_header = rhdr_new;
3518*4882a593Smuzhiyun 		adapter->smb = smb;
3519*4882a593Smuzhiyun 		adapter->cmb = cmb;
3520*4882a593Smuzhiyun 
3521*4882a593Smuzhiyun 		err = atl1_up(adapter);
3522*4882a593Smuzhiyun 		if (err)
3523*4882a593Smuzhiyun 			return err;
3524*4882a593Smuzhiyun 	}
3525*4882a593Smuzhiyun 	return 0;
3526*4882a593Smuzhiyun 
3527*4882a593Smuzhiyun err_setup_ring:
3528*4882a593Smuzhiyun 	adapter->rfd_ring = rfd_old;
3529*4882a593Smuzhiyun 	adapter->rrd_ring = rrd_old;
3530*4882a593Smuzhiyun 	adapter->tpd_ring = tpd_old;
3531*4882a593Smuzhiyun 	adapter->ring_header = rhdr_old;
3532*4882a593Smuzhiyun 	atl1_up(adapter);
3533*4882a593Smuzhiyun 	return err;
3534*4882a593Smuzhiyun }
3535*4882a593Smuzhiyun 
atl1_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * epause)3536*4882a593Smuzhiyun static void atl1_get_pauseparam(struct net_device *netdev,
3537*4882a593Smuzhiyun 	struct ethtool_pauseparam *epause)
3538*4882a593Smuzhiyun {
3539*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3540*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3541*4882a593Smuzhiyun 
3542*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3543*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
3544*4882a593Smuzhiyun 		epause->autoneg = AUTONEG_ENABLE;
3545*4882a593Smuzhiyun 	} else {
3546*4882a593Smuzhiyun 		epause->autoneg = AUTONEG_DISABLE;
3547*4882a593Smuzhiyun 	}
3548*4882a593Smuzhiyun 	epause->rx_pause = 1;
3549*4882a593Smuzhiyun 	epause->tx_pause = 1;
3550*4882a593Smuzhiyun }
3551*4882a593Smuzhiyun 
atl1_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * epause)3552*4882a593Smuzhiyun static int atl1_set_pauseparam(struct net_device *netdev,
3553*4882a593Smuzhiyun 	struct ethtool_pauseparam *epause)
3554*4882a593Smuzhiyun {
3555*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3556*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3557*4882a593Smuzhiyun 
3558*4882a593Smuzhiyun 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3559*4882a593Smuzhiyun 	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
3560*4882a593Smuzhiyun 		epause->autoneg = AUTONEG_ENABLE;
3561*4882a593Smuzhiyun 	} else {
3562*4882a593Smuzhiyun 		epause->autoneg = AUTONEG_DISABLE;
3563*4882a593Smuzhiyun 	}
3564*4882a593Smuzhiyun 
3565*4882a593Smuzhiyun 	epause->rx_pause = 1;
3566*4882a593Smuzhiyun 	epause->tx_pause = 1;
3567*4882a593Smuzhiyun 
3568*4882a593Smuzhiyun 	return 0;
3569*4882a593Smuzhiyun }
3570*4882a593Smuzhiyun 
atl1_get_strings(struct net_device * netdev,u32 stringset,u8 * data)3571*4882a593Smuzhiyun static void atl1_get_strings(struct net_device *netdev, u32 stringset,
3572*4882a593Smuzhiyun 	u8 *data)
3573*4882a593Smuzhiyun {
3574*4882a593Smuzhiyun 	u8 *p = data;
3575*4882a593Smuzhiyun 	int i;
3576*4882a593Smuzhiyun 
3577*4882a593Smuzhiyun 	switch (stringset) {
3578*4882a593Smuzhiyun 	case ETH_SS_STATS:
3579*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
3580*4882a593Smuzhiyun 			memcpy(p, atl1_gstrings_stats[i].stat_string,
3581*4882a593Smuzhiyun 				ETH_GSTRING_LEN);
3582*4882a593Smuzhiyun 			p += ETH_GSTRING_LEN;
3583*4882a593Smuzhiyun 		}
3584*4882a593Smuzhiyun 		break;
3585*4882a593Smuzhiyun 	}
3586*4882a593Smuzhiyun }
3587*4882a593Smuzhiyun 
atl1_nway_reset(struct net_device * netdev)3588*4882a593Smuzhiyun static int atl1_nway_reset(struct net_device *netdev)
3589*4882a593Smuzhiyun {
3590*4882a593Smuzhiyun 	struct atl1_adapter *adapter = netdev_priv(netdev);
3591*4882a593Smuzhiyun 	struct atl1_hw *hw = &adapter->hw;
3592*4882a593Smuzhiyun 
3593*4882a593Smuzhiyun 	if (netif_running(netdev)) {
3594*4882a593Smuzhiyun 		u16 phy_data;
3595*4882a593Smuzhiyun 		atl1_down(adapter);
3596*4882a593Smuzhiyun 
3597*4882a593Smuzhiyun 		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
3598*4882a593Smuzhiyun 			hw->media_type == MEDIA_TYPE_1000M_FULL) {
3599*4882a593Smuzhiyun 			phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
3600*4882a593Smuzhiyun 		} else {
3601*4882a593Smuzhiyun 			switch (hw->media_type) {
3602*4882a593Smuzhiyun 			case MEDIA_TYPE_100M_FULL:
3603*4882a593Smuzhiyun 				phy_data = MII_CR_FULL_DUPLEX |
3604*4882a593Smuzhiyun 					MII_CR_SPEED_100 | MII_CR_RESET;
3605*4882a593Smuzhiyun 				break;
3606*4882a593Smuzhiyun 			case MEDIA_TYPE_100M_HALF:
3607*4882a593Smuzhiyun 				phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
3608*4882a593Smuzhiyun 				break;
3609*4882a593Smuzhiyun 			case MEDIA_TYPE_10M_FULL:
3610*4882a593Smuzhiyun 				phy_data = MII_CR_FULL_DUPLEX |
3611*4882a593Smuzhiyun 					MII_CR_SPEED_10 | MII_CR_RESET;
3612*4882a593Smuzhiyun 				break;
3613*4882a593Smuzhiyun 			default:
3614*4882a593Smuzhiyun 				/* MEDIA_TYPE_10M_HALF */
3615*4882a593Smuzhiyun 				phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
3616*4882a593Smuzhiyun 			}
3617*4882a593Smuzhiyun 		}
3618*4882a593Smuzhiyun 		atl1_write_phy_reg(hw, MII_BMCR, phy_data);
3619*4882a593Smuzhiyun 		atl1_up(adapter);
3620*4882a593Smuzhiyun 	}
3621*4882a593Smuzhiyun 	return 0;
3622*4882a593Smuzhiyun }
3623*4882a593Smuzhiyun 
3624*4882a593Smuzhiyun static const struct ethtool_ops atl1_ethtool_ops = {
3625*4882a593Smuzhiyun 	.get_drvinfo		= atl1_get_drvinfo,
3626*4882a593Smuzhiyun 	.get_wol		= atl1_get_wol,
3627*4882a593Smuzhiyun 	.set_wol		= atl1_set_wol,
3628*4882a593Smuzhiyun 	.get_msglevel		= atl1_get_msglevel,
3629*4882a593Smuzhiyun 	.set_msglevel		= atl1_set_msglevel,
3630*4882a593Smuzhiyun 	.get_regs_len		= atl1_get_regs_len,
3631*4882a593Smuzhiyun 	.get_regs		= atl1_get_regs,
3632*4882a593Smuzhiyun 	.get_ringparam		= atl1_get_ringparam,
3633*4882a593Smuzhiyun 	.set_ringparam		= atl1_set_ringparam,
3634*4882a593Smuzhiyun 	.get_pauseparam		= atl1_get_pauseparam,
3635*4882a593Smuzhiyun 	.set_pauseparam		= atl1_set_pauseparam,
3636*4882a593Smuzhiyun 	.get_link		= ethtool_op_get_link,
3637*4882a593Smuzhiyun 	.get_strings		= atl1_get_strings,
3638*4882a593Smuzhiyun 	.nway_reset		= atl1_nway_reset,
3639*4882a593Smuzhiyun 	.get_ethtool_stats	= atl1_get_ethtool_stats,
3640*4882a593Smuzhiyun 	.get_sset_count		= atl1_get_sset_count,
3641*4882a593Smuzhiyun 	.get_link_ksettings	= atl1_get_link_ksettings,
3642*4882a593Smuzhiyun 	.set_link_ksettings	= atl1_set_link_ksettings,
3643*4882a593Smuzhiyun };
3644*4882a593Smuzhiyun 
3645*4882a593Smuzhiyun module_pci_driver(atl1_driver);
3646