blob: c322aa77ad1c575427cc722e7daeb3ba8cf9df8c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
3 * Copyright (C) 2004 Advanced Micro Devices
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -04005 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
7 * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
8 * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
9 * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
10 * Copyright 1993 United States Government as represented by the
11 * Director, National Security Agency.[ pcnet32.c ]
12 * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
13 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
14 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -040015 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
Jeff Kirsher0ab75ae2013-12-06 06:28:43 -080027 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029Module Name:
30
31 amd8111e.c
32
33Abstract:
Jeff Garzik6aa20a22006-09-13 13:24:59 -040034
35 AMD8111 based 10/100 Ethernet Controller Driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37Environment:
38
39 Kernel Mode
40
41Revision History:
42 3.0.0
43 Initial Revision.
44 3.0.1
45 1. Dynamic interrupt coalescing.
46 2. Removed prev_stats.
47 3. MII support.
48 4. Dynamic IPG support
49 3.0.2 05/29/2003
50 1. Bug fix: Fixed failure to send jumbo packets larger than 4k.
51 2. Bug fix: Fixed VLAN support failure.
52 3. Bug fix: Fixed receive interrupt coalescing bug.
53 4. Dynamic IPG support is disabled by default.
54 3.0.3 06/05/2003
55 1. Bug fix: Fixed failure to close the interface if SMP is enabled.
56 3.0.4 12/09/2003
57 1. Added set_mac_address routine for bonding driver support.
58 2. Tested the driver for bonding support
Jeff Garzik6aa20a22006-09-13 13:24:59 -040059 3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 indicated to the h/w.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040061 4. Modified amd8111e_rx() routine to receive all the received packets
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 in the first interrupt.
63 5. Bug fix: Corrected rx_errors reported in get_stats() function.
64 3.0.5 03/22/2004
Jeff Garzik6aa20a22006-09-13 13:24:59 -040065 1. Added NAPI support
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67*/
68
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#include <linux/module.h>
71#include <linux/kernel.h>
72#include <linux/types.h>
73#include <linux/compiler.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include <linux/delay.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000075#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/ioport.h>
77#include <linux/pci.h>
78#include <linux/netdevice.h>
79#include <linux/etherdevice.h>
80#include <linux/skbuff.h>
81#include <linux/ethtool.h>
82#include <linux/mii.h>
83#include <linux/if_vlan.h>
Jeff Garzik6aa20a22006-09-13 13:24:59 -040084#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/crc32.h>
Tobias Klausercac8c812005-05-16 19:15:11 +020086#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Linus Torvalds1da177e2005-04-16 15:20:36 -070088#include <asm/io.h>
89#include <asm/byteorder.h>
90#include <asm/uaccess.h>
91
92#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
93#define AMD8111E_VLAN_TAG_USED 1
94#else
95#define AMD8111E_VLAN_TAG_USED 0
96#endif
97
98#include "amd8111e.h"
99#define MODULE_NAME "amd8111e"
Francois Romieu6ba33ac2008-07-06 20:55:12 -0700100#define MODULE_VERS "3.0.7"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101MODULE_AUTHOR("Advanced Micro Devices, Inc.");
Francois Romieu6ba33ac2008-07-06 20:55:12 -0700102MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103MODULE_LICENSE("GPL");
104MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
105module_param_array(speed_duplex, int, NULL, 0);
Joe Perches983960b2011-05-02 09:59:29 +0000106MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107module_param_array(coalesce, bool, NULL, 0);
108MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0: Disable");
109module_param_array(dynamic_ipg, bool, NULL, 0);
110MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable");
111
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000112static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400113
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462,
115 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
116 { 0, }
117
118};
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400119/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120This function will read the PHY registers.
121*/
122static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val)
123{
124 void __iomem *mmio = lp->mmio;
125 unsigned int reg_val;
126 unsigned int repeat= REPEAT_CNT;
127
128 reg_val = readl(mmio + PHY_ACCESS);
129 while (reg_val & PHY_CMD_ACTIVE)
130 reg_val = readl( mmio + PHY_ACCESS );
131
132 writel( PHY_RD_CMD | ((phy_id & 0x1f) << 21) |
133 ((reg & 0x1f) << 16), mmio +PHY_ACCESS);
134 do{
135 reg_val = readl(mmio + PHY_ACCESS);
136 udelay(30); /* It takes 30 us to read/write data */
137 } while (--repeat && (reg_val & PHY_CMD_ACTIVE));
138 if(reg_val & PHY_RD_ERR)
139 goto err_phy_read;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 *val = reg_val & 0xffff;
142 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400143err_phy_read:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 *val = 0;
145 return -EINVAL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147}
148
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400149/*
150This function will write into PHY registers.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151*/
152static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
153{
Yoann Padioleau632155e2007-06-01 00:46:35 -0700154 unsigned int repeat = REPEAT_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 void __iomem *mmio = lp->mmio;
156 unsigned int reg_val;
157
158 reg_val = readl(mmio + PHY_ACCESS);
159 while (reg_val & PHY_CMD_ACTIVE)
160 reg_val = readl( mmio + PHY_ACCESS );
161
162 writel( PHY_WR_CMD | ((phy_id & 0x1f) << 21) |
163 ((reg & 0x1f) << 16)|val, mmio + PHY_ACCESS);
164
165 do{
166 reg_val = readl(mmio + PHY_ACCESS);
167 udelay(30); /* It takes 30 us to read/write the data */
168 } while (--repeat && (reg_val & PHY_CMD_ACTIVE));
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 if(reg_val & PHY_RD_ERR)
171 goto err_phy_write;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 return 0;
174
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400175err_phy_write:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 return -EINVAL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400179/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180This is the mii register read function provided to the mii interface.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400181*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
183{
184 struct amd8111e_priv* lp = netdev_priv(dev);
185 unsigned int reg_val;
186
187 amd8111e_read_phy(lp,phy_id,reg_num,&reg_val);
188 return reg_val;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190}
191
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400192/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193This is the mii register write function provided to the mii interface.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400194*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195static void amd8111e_mdio_write(struct net_device * dev, int phy_id, int reg_num, int val)
196{
197 struct amd8111e_priv* lp = netdev_priv(dev);
198
199 amd8111e_write_phy(lp, phy_id, reg_num, val);
200}
201
202/*
203This function will set PHY speed. During initialization sets the original speed to 100 full.
204*/
205static void amd8111e_set_ext_phy(struct net_device *dev)
206{
207 struct amd8111e_priv *lp = netdev_priv(dev);
208 u32 bmcr,advert,tmp;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /* Determine mii register values to set the speed */
211 advert = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_ADVERTISE);
212 tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
213 switch (lp->ext_phy_option){
214
215 default:
216 case SPEED_AUTONEG: /* advertise all values */
217 tmp |= ( ADVERTISE_10HALF|ADVERTISE_10FULL|
218 ADVERTISE_100HALF|ADVERTISE_100FULL) ;
219 break;
220 case SPEED10_HALF:
221 tmp |= ADVERTISE_10HALF;
222 break;
223 case SPEED10_FULL:
224 tmp |= ADVERTISE_10FULL;
225 break;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400226 case SPEED100_HALF:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 tmp |= ADVERTISE_100HALF;
228 break;
229 case SPEED100_FULL:
230 tmp |= ADVERTISE_100FULL;
231 break;
232 }
233
234 if(advert != tmp)
235 amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_ADVERTISE, tmp);
236 /* Restart auto negotiation */
237 bmcr = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_BMCR);
238 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
239 amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_BMCR, bmcr);
240
241}
242
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400243/*
244This function will unmap skb->data space and will free
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245all transmit and receive skbuffs.
246*/
247static int amd8111e_free_skbs(struct net_device *dev)
248{
249 struct amd8111e_priv *lp = netdev_priv(dev);
250 struct sk_buff* rx_skbuff;
251 int i;
252
253 /* Freeing transmit skbs */
254 for(i = 0; i < NUM_TX_BUFFERS; i++){
255 if(lp->tx_skbuff[i]){
256 pci_unmap_single(lp->pci_dev,lp->tx_dma_addr[i], lp->tx_skbuff[i]->len,PCI_DMA_TODEVICE);
257 dev_kfree_skb (lp->tx_skbuff[i]);
258 lp->tx_skbuff[i] = NULL;
259 lp->tx_dma_addr[i] = 0;
260 }
261 }
262 /* Freeing previously allocated receive buffers */
263 for (i = 0; i < NUM_RX_BUFFERS; i++){
264 rx_skbuff = lp->rx_skbuff[i];
265 if(rx_skbuff != NULL){
266 pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[i],
267 lp->rx_buff_len - 2,PCI_DMA_FROMDEVICE);
268 dev_kfree_skb(lp->rx_skbuff[i]);
269 lp->rx_skbuff[i] = NULL;
270 lp->rx_dma_addr[i] = 0;
271 }
272 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 return 0;
275}
276
277/*
278This will set the receive buffer length corresponding to the mtu size of networkinterface.
279*/
280static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
281{
282 struct amd8111e_priv* lp = netdev_priv(dev);
283 unsigned int mtu = dev->mtu;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 if (mtu > ETH_DATA_LEN){
286 /* MTU + ethernet header + FCS
287 + optional VLAN tag + skb reserve space 2 */
288
289 lp->rx_buff_len = mtu + ETH_HLEN + 10;
290 lp->options |= OPTION_JUMBO_ENABLE;
291 } else{
292 lp->rx_buff_len = PKT_BUFF_SZ;
293 lp->options &= ~OPTION_JUMBO_ENABLE;
294 }
295}
296
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400297/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298This function will free all the previously allocated buffers, determine new receive buffer length and will allocate new receive buffers. This function also allocates and initializes both the transmitter and receive hardware descriptors.
299 */
300static int amd8111e_init_ring(struct net_device *dev)
301{
302 struct amd8111e_priv *lp = netdev_priv(dev);
303 int i;
304
305 lp->rx_idx = lp->tx_idx = 0;
306 lp->tx_complete_idx = 0;
307 lp->tx_ring_idx = 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310 if(lp->opened)
311 /* Free previously allocated transmit and receive skbs */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400312 amd8111e_free_skbs(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 else{
315 /* allocate the tx and rx descriptors */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400316 if((lp->tx_ring = pci_alloc_consistent(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
318 &lp->tx_ring_dma_addr)) == NULL)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 goto err_no_mem;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400321
322 if((lp->rx_ring = pci_alloc_consistent(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
324 &lp->rx_ring_dma_addr)) == NULL)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 goto err_free_tx_ring;
327
328 }
329 /* Set new receive buff size */
330 amd8111e_set_rx_buff_len(dev);
331
332 /* Allocating receive skbs */
333 for (i = 0; i < NUM_RX_BUFFERS; i++) {
334
Pradeep A Dalvi1d266432012-02-05 02:49:09 +0000335 lp->rx_skbuff[i] = netdev_alloc_skb(dev, lp->rx_buff_len);
336 if (!lp->rx_skbuff[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 /* Release previos allocated skbs */
338 for(--i; i >= 0 ;i--)
339 dev_kfree_skb(lp->rx_skbuff[i]);
340 goto err_free_rx_ring;
341 }
342 skb_reserve(lp->rx_skbuff[i],2);
343 }
344 /* Initilaizing receive descriptors */
345 for (i = 0; i < NUM_RX_BUFFERS; i++) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400346 lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
348
349 lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
350 lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
351 wmb();
352 lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
353 }
354
355 /* Initializing transmit descriptors */
356 for (i = 0; i < NUM_TX_RING_DR; i++) {
357 lp->tx_ring[i].buff_phy_addr = 0;
358 lp->tx_ring[i].tx_flags = 0;
359 lp->tx_ring[i].buff_count = 0;
360 }
361
362 return 0;
363
364err_free_rx_ring:
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400365
366 pci_free_consistent(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,lp->rx_ring,
368 lp->rx_ring_dma_addr);
369
370err_free_tx_ring:
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400371
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 pci_free_consistent(lp->pci_dev,
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400373 sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,lp->tx_ring,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 lp->tx_ring_dma_addr);
375
376err_no_mem:
377 return -ENOMEM;
378}
379/* This function will set the interrupt coalescing according to the input arguments */
380static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
381{
382 unsigned int timeout;
383 unsigned int event_count;
384
385 struct amd8111e_priv *lp = netdev_priv(dev);
386 void __iomem *mmio = lp->mmio;
387 struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
388
389
390 switch(cmod)
391 {
392 case RX_INTR_COAL :
393 timeout = coal_conf->rx_timeout;
394 event_count = coal_conf->rx_event_count;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400395 if( timeout > MAX_TIMEOUT ||
396 event_count > MAX_EVENT_COUNT )
Julia Lawall022484c2010-08-05 10:22:20 +0000397 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400399 timeout = timeout * DELAY_TIMER_CONV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 writel(VAL0|STINTEN, mmio+INTEN0);
401 writel((u32)DLY_INT_A_R0|( event_count<< 16 )|timeout,
402 mmio+DLY_INT_A);
403 break;
404
405 case TX_INTR_COAL :
406 timeout = coal_conf->tx_timeout;
407 event_count = coal_conf->tx_event_count;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400408 if( timeout > MAX_TIMEOUT ||
409 event_count > MAX_EVENT_COUNT )
Julia Lawall022484c2010-08-05 10:22:20 +0000410 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400412
413 timeout = timeout * DELAY_TIMER_CONV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 writel(VAL0|STINTEN,mmio+INTEN0);
415 writel((u32)DLY_INT_B_T0|( event_count<< 16 )|timeout,
416 mmio+DLY_INT_B);
417 break;
418
419 case DISABLE_COAL:
420 writel(0,mmio+STVAL);
421 writel(STINTEN, mmio+INTEN0);
422 writel(0, mmio +DLY_INT_B);
423 writel(0, mmio+DLY_INT_A);
424 break;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400425 case ENABLE_COAL:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* Start the timer */
427 writel((u32)SOFT_TIMER_FREQ, mmio+STVAL); /* 0.5 sec */
428 writel(VAL0|STINTEN, mmio+INTEN0);
429 break;
430 default:
431 break;
432
433 }
434 return 0;
435
436}
437
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400438/*
439This function initializes the device registers and starts the device.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440*/
441static int amd8111e_restart(struct net_device *dev)
442{
443 struct amd8111e_priv *lp = netdev_priv(dev);
444 void __iomem *mmio = lp->mmio;
445 int i,reg_val;
446
447 /* stop the chip */
448 writel(RUN, mmio + CMD0);
449
450 if(amd8111e_init_ring(dev))
451 return -ENOMEM;
452
453 /* enable the port manager and set auto negotiation always */
454 writel((u32) VAL1|EN_PMGR, mmio + CMD3 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400455 writel((u32)XPHYANE|XPHYRST , mmio + CTRL2);
456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 amd8111e_set_ext_phy(dev);
458
459 /* set control registers */
460 reg_val = readl(mmio + CTRL1);
461 reg_val &= ~XMTSP_MASK;
462 writel( reg_val| XMTSP_128 | CACHE_ALIGN, mmio + CTRL1 );
463
464 /* enable interrupt */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400465 writel( APINT5EN | APINT4EN | APINT3EN | APINT2EN | APINT1EN |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 APINT0EN | MIIPDTINTEN | MCCIINTEN | MCCINTEN | MREINTEN |
467 SPNDINTEN | MPINTEN | SINTEN | STINTEN, mmio + INTEN0);
468
469 writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
470
471 /* initialize tx and rx ring base addresses */
472 writel((u32)lp->tx_ring_dma_addr,mmio + XMT_RING_BASE_ADDR0);
473 writel((u32)lp->rx_ring_dma_addr,mmio+ RCV_RING_BASE_ADDR0);
474
475 writew((u32)NUM_TX_RING_DR, mmio + XMT_RING_LEN0);
476 writew((u16)NUM_RX_RING_DR, mmio + RCV_RING_LEN0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 /* set default IPG to 96 */
479 writew((u32)DEFAULT_IPG,mmio+IPG);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400480 writew((u32)(DEFAULT_IPG-IFS1_DELTA), mmio + IFS1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 if(lp->options & OPTION_JUMBO_ENABLE){
483 writel((u32)VAL2|JUMBO, mmio + CMD3);
484 /* Reset REX_UFLO */
485 writel( REX_UFLO, mmio + CMD2);
486 /* Should not set REX_UFLO for jumbo frames */
487 writel( VAL0 | APAD_XMT|REX_RTRY , mmio + CMD2);
488 }else{
489 writel( VAL0 | APAD_XMT | REX_RTRY|REX_UFLO, mmio + CMD2);
490 writel((u32)JUMBO, mmio + CMD3);
491 }
492
493#if AMD8111E_VLAN_TAG_USED
494 writel((u32) VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3);
495#endif
496 writel( VAL0 | APAD_XMT | REX_RTRY, mmio + CMD2 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 /* Setting the MAC address to the device */
Joe Perchesc857ff62011-11-16 09:38:05 +0000499 for (i = 0; i < ETH_ALEN; i++)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400500 writeb( dev->dev_addr[i], mmio + PADR + i );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 /* Enable interrupt coalesce */
503 if(lp->options & OPTION_INTR_COAL_ENABLE){
Varka Bhadramf7afbaa2014-07-14 14:09:06 +0530504 netdev_info(dev, "Interrupt Coalescing Enabled.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 amd8111e_set_coalesce(dev,ENABLE_COAL);
506 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 /* set RUN bit to start the chip */
509 writel(VAL2 | RDMD0, mmio + CMD0);
510 writel(VAL0 | INTREN | RUN, mmio + CMD0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 /* To avoid PCI posting bug */
513 readl(mmio+CMD0);
514 return 0;
515}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400516/*
517This function clears necessary the device registers.
518*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
520{
521 unsigned int reg_val;
522 unsigned int logic_filter[2] ={0,};
523 void __iomem *mmio = lp->mmio;
524
525
526 /* stop the chip */
527 writel(RUN, mmio + CMD0);
528
529 /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
530 writew( 0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
531
532 /* Clear RCV_RING_BASE_ADDR */
533 writel(0, mmio + RCV_RING_BASE_ADDR0);
534
535 /* Clear XMT_RING_BASE_ADDR */
536 writel(0, mmio + XMT_RING_BASE_ADDR0);
537 writel(0, mmio + XMT_RING_BASE_ADDR1);
538 writel(0, mmio + XMT_RING_BASE_ADDR2);
539 writel(0, mmio + XMT_RING_BASE_ADDR3);
540
541 /* Clear CMD0 */
542 writel(CMD0_CLEAR,mmio + CMD0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400543
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 /* Clear CMD2 */
545 writel(CMD2_CLEAR, mmio +CMD2);
546
547 /* Clear CMD7 */
548 writel(CMD7_CLEAR , mmio + CMD7);
549
550 /* Clear DLY_INT_A and DLY_INT_B */
551 writel(0x0, mmio + DLY_INT_A);
552 writel(0x0, mmio + DLY_INT_B);
553
554 /* Clear FLOW_CONTROL */
555 writel(0x0, mmio + FLOW_CONTROL);
556
557 /* Clear INT0 write 1 to clear register */
558 reg_val = readl(mmio + INT0);
559 writel(reg_val, mmio + INT0);
560
561 /* Clear STVAL */
562 writel(0x0, mmio + STVAL);
563
564 /* Clear INTEN0 */
565 writel( INTEN0_CLEAR, mmio + INTEN0);
566
567 /* Clear LADRF */
568 writel(0x0 , mmio + LADRF);
569
570 /* Set SRAM_SIZE & SRAM_BOUNDARY registers */
571 writel( 0x80010,mmio + SRAM_SIZE);
572
573 /* Clear RCV_RING0_LEN */
574 writel(0x0, mmio + RCV_RING_LEN0);
575
576 /* Clear XMT_RING0/1/2/3_LEN */
577 writel(0x0, mmio + XMT_RING_LEN0);
578 writel(0x0, mmio + XMT_RING_LEN1);
579 writel(0x0, mmio + XMT_RING_LEN2);
580 writel(0x0, mmio + XMT_RING_LEN3);
581
582 /* Clear XMT_RING_LIMIT */
583 writel(0x0, mmio + XMT_RING_LIMIT);
584
585 /* Clear MIB */
586 writew(MIB_CLEAR, mmio + MIB_ADDR);
587
588 /* Clear LARF */
589 amd8111e_writeq(*(u64*)logic_filter,mmio+LADRF);
590
591 /* SRAM_SIZE register */
592 reg_val = readl(mmio + SRAM_SIZE);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 if(lp->options & OPTION_JUMBO_ENABLE)
595 writel( VAL2|JUMBO, mmio + CMD3);
596#if AMD8111E_VLAN_TAG_USED
597 writel(VAL2|VSIZE|VL_TAG_DEL, mmio + CMD3 );
598#endif
599 /* Set default value to CTRL1 Register */
600 writel(CTRL1_DEFAULT, mmio + CTRL1);
601
602 /* To avoid PCI posting bug */
603 readl(mmio + CMD2);
604
605}
606
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400607/*
608This function disables the interrupt and clears all the pending
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609interrupts in INT0
610 */
611static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400612{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 u32 intr0;
614
615 /* Disable interrupt */
616 writel(INTREN, lp->mmio + CMD0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400617
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 /* Clear INT0 */
619 intr0 = readl(lp->mmio + INT0);
620 writel(intr0, lp->mmio + INT0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 /* To avoid PCI posting bug */
623 readl(lp->mmio + INT0);
624
625}
626
627/*
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400628This function stops the chip.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629*/
630static void amd8111e_stop_chip(struct amd8111e_priv* lp)
631{
632 writel(RUN, lp->mmio + CMD0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 /* To avoid PCI posting bug */
635 readl(lp->mmio + CMD0);
636}
637
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400638/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639This function frees the transmiter and receiver descriptor rings.
640*/
641static void amd8111e_free_ring(struct amd8111e_priv* lp)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400642{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* Free transmit and receive descriptor rings */
644 if(lp->rx_ring){
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400645 pci_free_consistent(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 sizeof(struct amd8111e_rx_dr)*NUM_RX_RING_DR,
647 lp->rx_ring, lp->rx_ring_dma_addr);
648 lp->rx_ring = NULL;
649 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 if(lp->tx_ring){
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400652 pci_free_consistent(lp->pci_dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 sizeof(struct amd8111e_tx_dr)*NUM_TX_RING_DR,
654 lp->tx_ring, lp->tx_ring_dma_addr);
655
656 lp->tx_ring = NULL;
657 }
658
659}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
661/*
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400662This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663*/
664static int amd8111e_tx(struct net_device *dev)
665{
666 struct amd8111e_priv* lp = netdev_priv(dev);
667 int tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
668 int status;
669 /* Complete all the transmit packet */
670 while (lp->tx_complete_idx != lp->tx_idx){
671 tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
672 status = le16_to_cpu(lp->tx_ring[tx_index].tx_flags);
673
674 if(status & OWN_BIT)
675 break; /* It still hasn't been Txed */
676
677 lp->tx_ring[tx_index].buff_phy_addr = 0;
678
679 /* We must free the original skb */
680 if (lp->tx_skbuff[tx_index]) {
681 pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
682 lp->tx_skbuff[tx_index]->len,
683 PCI_DMA_TODEVICE);
684 dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
685 lp->tx_skbuff[tx_index] = NULL;
686 lp->tx_dma_addr[tx_index] = 0;
687 }
688 lp->tx_complete_idx++;
689 /*COAL update tx coalescing parameters */
690 lp->coal_conf.tx_packets++;
Al Viro05d2fec2007-08-22 21:42:28 -0400691 lp->coal_conf.tx_bytes +=
692 le16_to_cpu(lp->tx_ring[tx_index].buff_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 if (netif_queue_stopped(dev) &&
695 lp->tx_complete_idx > lp->tx_idx - NUM_TX_BUFFERS +2){
696 /* The ring is no longer full, clear tbusy. */
697 /* lp->tx_full = 0; */
698 netif_wake_queue (dev);
699 }
700 }
701 return 0;
702}
703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704/* This function handles the driver receive operation in polling mode */
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700705static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700707 struct amd8111e_priv *lp = container_of(napi, struct amd8111e_priv, napi);
708 struct net_device *dev = lp->amd8111e_net_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
710 void __iomem *mmio = lp->mmio;
711 struct sk_buff *skb,*new_skb;
712 int min_pkt_len, status;
713 unsigned int intr0;
714 int num_rx_pkt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 short pkt_len;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400716#if AMD8111E_VLAN_TAG_USED
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 short vtag;
718#endif
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700719 int rx_pkt_limit = budget;
Liu Taodfa1b732005-05-12 19:40:38 -0400720 unsigned long flags;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400721
Eric W. Biederman278d5382014-03-14 18:01:11 -0700722 if (rx_pkt_limit <= 0)
723 goto rx_not_empty;
724
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400725 do{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 /* process receive packets until we use the quota*/
727 /* If we own the next entry, it's a new packet. Send it up. */
728 while(1) {
729 status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
730 if (status & OWN_BIT)
731 break;
732
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400733 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 * There is a tricky error noted by John Murphy,
735 * <murf@perftech.com> to Russ Nelson: Even with
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400736 * full-sized * buffers it's possible for a
737 * jabber packet to use two buffers, with only
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 * the last correctly noting the error.
739 */
740
741 if(status & ERR_BIT) {
742 /* reseting flags */
743 lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
744 goto err_next_pkt;
745 }
746 /* check for STP and ENP */
747 if(!((status & STP_BIT) && (status & ENP_BIT))){
748 /* reseting flags */
749 lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
750 goto err_next_pkt;
751 }
752 pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4;
753
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400754#if AMD8111E_VLAN_TAG_USED
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 vtag = status & TT_MASK;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400756 /*MAC will strip vlan tag*/
Jiri Pirkoc8d9e6d2011-07-20 04:54:11 +0000757 if (vtag != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 min_pkt_len =MIN_PKT_LEN - 4;
759 else
760#endif
761 min_pkt_len =MIN_PKT_LEN;
762
763 if (pkt_len < min_pkt_len) {
764 lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
765 lp->drv_rx_errors++;
766 goto err_next_pkt;
767 }
768 if(--rx_pkt_limit < 0)
769 goto rx_not_empty;
Pradeep A Dalvi1d266432012-02-05 02:49:09 +0000770 new_skb = netdev_alloc_skb(dev, lp->rx_buff_len);
771 if (!new_skb) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400772 /* if allocation fail,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 ignore that pkt and go to next one */
774 lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
775 lp->drv_rx_errors++;
776 goto err_next_pkt;
777 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 skb_reserve(new_skb, 2);
780 skb = lp->rx_skbuff[rx_index];
781 pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index],
782 lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
783 skb_put(skb, pkt_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 lp->rx_skbuff[rx_index] = new_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev,
786 new_skb->data,
787 lp->rx_buff_len-2,
788 PCI_DMA_FROMDEVICE);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 skb->protocol = eth_type_trans(skb, dev);
791
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400792#if AMD8111E_VLAN_TAG_USED
Jiri Pirkoc8d9e6d2011-07-20 04:54:11 +0000793 if (vtag == TT_VLAN_TAGGED){
794 u16 vlan_tag = le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info);
Patrick McHardy86a9bad2013-04-19 02:04:30 +0000795 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
Jiri Pirkoc8d9e6d2011-07-20 04:54:11 +0000796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797#endif
Jiri Pirkoc8d9e6d2011-07-20 04:54:11 +0000798 netif_receive_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 /*COAL update rx coalescing parameters*/
800 lp->coal_conf.rx_packets++;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400801 lp->coal_conf.rx_bytes += pkt_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 num_rx_pkt++;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400803
804 err_next_pkt:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 lp->rx_ring[rx_index].buff_phy_addr
806 = cpu_to_le32(lp->rx_dma_addr[rx_index]);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400807 lp->rx_ring[rx_index].buff_count =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 cpu_to_le16(lp->rx_buff_len-2);
809 wmb();
810 lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT);
811 rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
812 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400813 /* Check the interrupt status register for more packets in the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 mean time. Process them since we have not used up our quota.*/
815
816 intr0 = readl(mmio + INT0);
817 /*Ack receive packets */
818 writel(intr0 & RINT0,mmio + INT0);
819
820 } while(intr0 & RINT0);
821
Chris Friesen48e5eca2008-10-28 15:50:54 -0700822 if (rx_pkt_limit > 0) {
823 /* Receive descriptor is empty now */
824 spin_lock_irqsave(&lp->lock, flags);
Ben Hutchings288379f2009-01-19 16:43:59 -0800825 __napi_complete(napi);
Chris Friesen48e5eca2008-10-28 15:50:54 -0700826 writel(VAL0|RINTEN0, mmio + INTEN0);
827 writel(VAL2 | RDMD0, mmio + CMD0);
828 spin_unlock_irqrestore(&lp->lock, flags);
829 }
Liu Taodfa1b732005-05-12 19:40:38 -0400830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831rx_not_empty:
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700832 return num_rx_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}
834
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400835/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836This function will indicate the link status to the kernel.
837*/
838static int amd8111e_link_change(struct net_device* dev)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400839{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 struct amd8111e_priv *lp = netdev_priv(dev);
841 int status0,speed;
842
843 /* read the link change */
844 status0 = readl(lp->mmio + STAT0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if(status0 & LINK_STATS){
847 if(status0 & AUTONEG_COMPLETE)
848 lp->link_config.autoneg = AUTONEG_ENABLE;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400849 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 lp->link_config.autoneg = AUTONEG_DISABLE;
851
852 if(status0 & FULL_DPLX)
853 lp->link_config.duplex = DUPLEX_FULL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400854 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 lp->link_config.duplex = DUPLEX_HALF;
856 speed = (status0 & SPEED_MASK) >> 7;
857 if(speed == PHY_SPEED_10)
858 lp->link_config.speed = SPEED_10;
859 else if(speed == PHY_SPEED_100)
860 lp->link_config.speed = SPEED_100;
861
Varka Bhadramf7afbaa2014-07-14 14:09:06 +0530862 netdev_info(dev, "Link is Up. Speed is %s Mbps %s Duplex\n",
863 (lp->link_config.speed == SPEED_100) ?
864 "100" : "10",
865 (lp->link_config.duplex == DUPLEX_FULL) ?
866 "Full" : "Half");
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 netif_carrier_on(dev);
869 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400870 else{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 lp->link_config.speed = SPEED_INVALID;
872 lp->link_config.duplex = DUPLEX_INVALID;
873 lp->link_config.autoneg = AUTONEG_INVALID;
Varka Bhadramf7afbaa2014-07-14 14:09:06 +0530874 netdev_info(dev, "Link is Down.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 netif_carrier_off(dev);
876 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 return 0;
879}
880/*
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400881This function reads the mib counters.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882*/
883static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
884{
885 unsigned int status;
886 unsigned int data;
887 unsigned int repeat = REPEAT_CNT;
888
889 writew( MIB_RD_CMD | MIB_COUNTER, mmio + MIB_ADDR);
890 do {
891 status = readw(mmio + MIB_ADDR);
892 udelay(2); /* controller takes MAX 2 us to get mib data */
893 }
894 while (--repeat && (status & MIB_CMD_ACTIVE));
895
896 data = readl(mmio + MIB_DATA);
897 return data;
898}
899
900/*
Eric Dumazetc3227e52010-08-20 03:08:23 +0000901 * This function reads the mib registers and returns the hardware statistics.
902 * It updates previous internal driver statistics with new values.
903 */
904static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
906 struct amd8111e_priv *lp = netdev_priv(dev);
907 void __iomem *mmio = lp->mmio;
908 unsigned long flags;
Eric Dumazetc3227e52010-08-20 03:08:23 +0000909 struct net_device_stats *new_stats = &dev->stats;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400910
Eric Dumazetc3227e52010-08-20 03:08:23 +0000911 if (!lp->opened)
912 return new_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 spin_lock_irqsave (&lp->lock, flags);
914
915 /* stats.rx_packets */
916 new_stats->rx_packets = amd8111e_read_mib(mmio, rcv_broadcast_pkts)+
917 amd8111e_read_mib(mmio, rcv_multicast_pkts)+
918 amd8111e_read_mib(mmio, rcv_unicast_pkts);
919
920 /* stats.tx_packets */
921 new_stats->tx_packets = amd8111e_read_mib(mmio, xmt_packets);
922
923 /*stats.rx_bytes */
924 new_stats->rx_bytes = amd8111e_read_mib(mmio, rcv_octets);
925
926 /* stats.tx_bytes */
927 new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
928
929 /* stats.rx_errors */
930 /* hw errors + errors driver reported */
931 new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
932 amd8111e_read_mib(mmio, rcv_fragments)+
933 amd8111e_read_mib(mmio, rcv_jabbers)+
934 amd8111e_read_mib(mmio, rcv_alignment_errors)+
935 amd8111e_read_mib(mmio, rcv_fcs_errors)+
936 amd8111e_read_mib(mmio, rcv_miss_pkts)+
937 lp->drv_rx_errors;
938
939 /* stats.tx_errors */
940 new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
941
942 /* stats.rx_dropped*/
943 new_stats->rx_dropped = amd8111e_read_mib(mmio, rcv_miss_pkts);
944
945 /* stats.tx_dropped*/
946 new_stats->tx_dropped = amd8111e_read_mib(mmio, xmt_underrun_pkts);
947
948 /* stats.multicast*/
949 new_stats->multicast = amd8111e_read_mib(mmio, rcv_multicast_pkts);
950
951 /* stats.collisions*/
952 new_stats->collisions = amd8111e_read_mib(mmio, xmt_collisions);
953
954 /* stats.rx_length_errors*/
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400955 new_stats->rx_length_errors =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 amd8111e_read_mib(mmio, rcv_undersize_pkts)+
957 amd8111e_read_mib(mmio, rcv_oversize_pkts);
958
959 /* stats.rx_over_errors*/
960 new_stats->rx_over_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
961
962 /* stats.rx_crc_errors*/
963 new_stats->rx_crc_errors = amd8111e_read_mib(mmio, rcv_fcs_errors);
964
965 /* stats.rx_frame_errors*/
966 new_stats->rx_frame_errors =
967 amd8111e_read_mib(mmio, rcv_alignment_errors);
968
969 /* stats.rx_fifo_errors */
970 new_stats->rx_fifo_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
971
972 /* stats.rx_missed_errors */
973 new_stats->rx_missed_errors = amd8111e_read_mib(mmio, rcv_miss_pkts);
974
975 /* stats.tx_aborted_errors*/
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400976 new_stats->tx_aborted_errors =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 amd8111e_read_mib(mmio, xmt_excessive_collision);
978
979 /* stats.tx_carrier_errors*/
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400980 new_stats->tx_carrier_errors =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 amd8111e_read_mib(mmio, xmt_loss_carrier);
982
983 /* stats.tx_fifo_errors*/
984 new_stats->tx_fifo_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
985
986 /* stats.tx_window_errors*/
987 new_stats->tx_window_errors =
988 amd8111e_read_mib(mmio, xmt_late_collision);
989
990 /* Reset the mibs for collecting new statistics */
991 /* writew(MIB_CLEAR, mmio + MIB_ADDR);*/
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 spin_unlock_irqrestore (&lp->lock, flags);
994
995 return new_stats;
996}
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200997/* This function recalculate the interrupt coalescing mode on every interrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998according to the datarate and the packet rate.
999*/
1000static int amd8111e_calc_coalesce(struct net_device *dev)
1001{
1002 struct amd8111e_priv *lp = netdev_priv(dev);
1003 struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
1004 int tx_pkt_rate;
1005 int rx_pkt_rate;
1006 int tx_data_rate;
1007 int rx_data_rate;
1008 int rx_pkt_size;
1009 int tx_pkt_size;
1010
1011 tx_pkt_rate = coal_conf->tx_packets - coal_conf->tx_prev_packets;
1012 coal_conf->tx_prev_packets = coal_conf->tx_packets;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 tx_data_rate = coal_conf->tx_bytes - coal_conf->tx_prev_bytes;
1015 coal_conf->tx_prev_bytes = coal_conf->tx_bytes;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 rx_pkt_rate = coal_conf->rx_packets - coal_conf->rx_prev_packets;
1018 coal_conf->rx_prev_packets = coal_conf->rx_packets;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 rx_data_rate = coal_conf->rx_bytes - coal_conf->rx_prev_bytes;
1021 coal_conf->rx_prev_bytes = coal_conf->rx_bytes;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if(rx_pkt_rate < 800){
1024 if(coal_conf->rx_coal_type != NO_COALESCE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 coal_conf->rx_timeout = 0x0;
1027 coal_conf->rx_event_count = 0;
1028 amd8111e_set_coalesce(dev,RX_INTR_COAL);
1029 coal_conf->rx_coal_type = NO_COALESCE;
1030 }
1031 }
1032 else{
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 rx_pkt_size = rx_data_rate/rx_pkt_rate;
1035 if (rx_pkt_size < 128){
1036 if(coal_conf->rx_coal_type != NO_COALESCE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 coal_conf->rx_timeout = 0;
1039 coal_conf->rx_event_count = 0;
1040 amd8111e_set_coalesce(dev,RX_INTR_COAL);
1041 coal_conf->rx_coal_type = NO_COALESCE;
1042 }
1043
1044 }
1045 else if ( (rx_pkt_size >= 128) && (rx_pkt_size < 512) ){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 if(coal_conf->rx_coal_type != LOW_COALESCE){
1048 coal_conf->rx_timeout = 1;
1049 coal_conf->rx_event_count = 4;
1050 amd8111e_set_coalesce(dev,RX_INTR_COAL);
1051 coal_conf->rx_coal_type = LOW_COALESCE;
1052 }
1053 }
1054 else if ((rx_pkt_size >= 512) && (rx_pkt_size < 1024)){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 if(coal_conf->rx_coal_type != MEDIUM_COALESCE){
1057 coal_conf->rx_timeout = 1;
1058 coal_conf->rx_event_count = 4;
1059 amd8111e_set_coalesce(dev,RX_INTR_COAL);
1060 coal_conf->rx_coal_type = MEDIUM_COALESCE;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001061 }
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 }
1064 else if(rx_pkt_size >= 1024){
1065 if(coal_conf->rx_coal_type != HIGH_COALESCE){
1066 coal_conf->rx_timeout = 2;
1067 coal_conf->rx_event_count = 3;
1068 amd8111e_set_coalesce(dev,RX_INTR_COAL);
1069 coal_conf->rx_coal_type = HIGH_COALESCE;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 }
1072 }
1073 /* NOW FOR TX INTR COALESC */
1074 if(tx_pkt_rate < 800){
1075 if(coal_conf->tx_coal_type != NO_COALESCE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001076
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 coal_conf->tx_timeout = 0x0;
1078 coal_conf->tx_event_count = 0;
1079 amd8111e_set_coalesce(dev,TX_INTR_COAL);
1080 coal_conf->tx_coal_type = NO_COALESCE;
1081 }
1082 }
1083 else{
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 tx_pkt_size = tx_data_rate/tx_pkt_rate;
1086 if (tx_pkt_size < 128){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 if(coal_conf->tx_coal_type != NO_COALESCE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 coal_conf->tx_timeout = 0;
1091 coal_conf->tx_event_count = 0;
1092 amd8111e_set_coalesce(dev,TX_INTR_COAL);
1093 coal_conf->tx_coal_type = NO_COALESCE;
1094 }
1095
1096 }
1097 else if ( (tx_pkt_size >= 128) && (tx_pkt_size < 512) ){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001098
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 if(coal_conf->tx_coal_type != LOW_COALESCE){
1100 coal_conf->tx_timeout = 1;
1101 coal_conf->tx_event_count = 2;
1102 amd8111e_set_coalesce(dev,TX_INTR_COAL);
1103 coal_conf->tx_coal_type = LOW_COALESCE;
1104
1105 }
1106 }
1107 else if ((tx_pkt_size >= 512) && (tx_pkt_size < 1024)){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 if(coal_conf->tx_coal_type != MEDIUM_COALESCE){
1110 coal_conf->tx_timeout = 2;
1111 coal_conf->tx_event_count = 5;
1112 amd8111e_set_coalesce(dev,TX_INTR_COAL);
1113 coal_conf->tx_coal_type = MEDIUM_COALESCE;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001114 }
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 }
1117 else if(tx_pkt_size >= 1024){
1118 if (tx_pkt_size >= 1024){
1119 if(coal_conf->tx_coal_type != HIGH_COALESCE){
1120 coal_conf->tx_timeout = 4;
1121 coal_conf->tx_event_count = 8;
1122 amd8111e_set_coalesce(dev,TX_INTR_COAL);
1123 coal_conf->tx_coal_type = HIGH_COALESCE;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
1126 }
1127 }
1128 return 0;
1129
1130}
1131/*
1132This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
1133*/
David Howells7d12e782006-10-05 14:55:46 +01001134static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
1136
1137 struct net_device * dev = (struct net_device *) dev_id;
1138 struct amd8111e_priv *lp = netdev_priv(dev);
1139 void __iomem *mmio = lp->mmio;
Liu Taodfa1b732005-05-12 19:40:38 -04001140 unsigned int intr0, intren0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 unsigned int handled = 1;
1142
Liu Taodfa1b732005-05-12 19:40:38 -04001143 if(unlikely(dev == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 return IRQ_NONE;
1145
Liu Taodfa1b732005-05-12 19:40:38 -04001146 spin_lock(&lp->lock);
1147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 /* disabling interrupt */
1149 writel(INTREN, mmio + CMD0);
1150
1151 /* Read interrupt status */
1152 intr0 = readl(mmio + INT0);
Liu Taodfa1b732005-05-12 19:40:38 -04001153 intren0 = readl(mmio + INTEN0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 /* Process all the INT event until INTR bit is clear. */
1156
1157 if (!(intr0 & INTR)){
1158 handled = 0;
1159 goto err_no_interrupt;
1160 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 /* Current driver processes 4 interrupts : RINT,TINT,LCINT,STINT */
1163 writel(intr0, mmio + INT0);
1164
1165 /* Check if Receive Interrupt has occurred. */
Francois Romieu6ba33ac2008-07-06 20:55:12 -07001166 if (intr0 & RINT0) {
Ben Hutchings288379f2009-01-19 16:43:59 -08001167 if (napi_schedule_prep(&lp->napi)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 /* Disable receive interupts */
1169 writel(RINTEN0, mmio + INTEN0);
1170 /* Schedule a polling routine */
Ben Hutchings288379f2009-01-19 16:43:59 -08001171 __napi_schedule(&lp->napi);
Francois Romieu6ba33ac2008-07-06 20:55:12 -07001172 } else if (intren0 & RINTEN0) {
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301173 netdev_dbg(dev, "************Driver bug! interrupt while in poll\n");
Liu Taodfa1b732005-05-12 19:40:38 -04001174 /* Fix by disable receive interrupts */
1175 writel(RINTEN0, mmio + INTEN0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 }
1177 }
Francois Romieu6ba33ac2008-07-06 20:55:12 -07001178
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 /* Check if Transmit Interrupt has occurred. */
Francois Romieu6ba33ac2008-07-06 20:55:12 -07001180 if (intr0 & TINT0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 amd8111e_tx(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 /* Check if Link Change Interrupt has occurred. */
1184 if (intr0 & LCINT)
1185 amd8111e_link_change(dev);
1186
1187 /* Check if Hardware Timer Interrupt has occurred. */
1188 if (intr0 & STINT)
1189 amd8111e_calc_coalesce(dev);
1190
1191err_no_interrupt:
1192 writel( VAL0 | INTREN,mmio + CMD0);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001193
Liu Taodfa1b732005-05-12 19:40:38 -04001194 spin_unlock(&lp->lock);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 return IRQ_RETVAL(handled);
1197}
1198
1199#ifdef CONFIG_NET_POLL_CONTROLLER
1200static void amd8111e_poll(struct net_device *dev)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001201{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 unsigned long flags;
Jiri Kosinab7e36bf2007-02-05 16:29:49 -08001203 local_irq_save(flags);
David Howells7d12e782006-10-05 14:55:46 +01001204 amd8111e_interrupt(0, dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001205 local_irq_restore(flags);
1206}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207#endif
1208
1209
1210/*
1211This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
1212*/
1213static int amd8111e_close(struct net_device * dev)
1214{
1215 struct amd8111e_priv *lp = netdev_priv(dev);
1216 netif_stop_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001217
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001218 napi_disable(&lp->napi);
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 spin_lock_irq(&lp->lock);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 amd8111e_disable_interrupt(lp);
1223 amd8111e_stop_chip(lp);
Chunbo Luoe83603f2008-10-28 09:51:46 +08001224
1225 /* Free transmit and receive skbs */
1226 amd8111e_free_skbs(lp->amd8111e_net_dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 netif_carrier_off(lp->amd8111e_net_dev);
1229
1230 /* Delete ipg timer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001231 if(lp->options & OPTION_DYN_IPG_ENABLE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 del_timer_sync(&lp->ipg_data.ipg_timer);
1233
1234 spin_unlock_irq(&lp->lock);
1235 free_irq(dev->irq, dev);
Chunbo Luoe83603f2008-10-28 09:51:46 +08001236 amd8111e_free_ring(lp);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001237
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 /* Update the statistics before closing */
1239 amd8111e_get_stats(dev);
1240 lp->opened = 0;
1241 return 0;
1242}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001243/* This function opens new interface.It requests irq for the device, initializes the device,buffers and descriptors, and starts the device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244*/
1245static int amd8111e_open(struct net_device * dev )
1246{
1247 struct amd8111e_priv *lp = netdev_priv(dev);
1248
Thomas Gleixner1fb9df52006-07-01 19:29:39 -07001249 if(dev->irq ==0 || request_irq(dev->irq, amd8111e_interrupt, IRQF_SHARED,
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001250 dev->name, dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 return -EAGAIN;
1252
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001253 napi_enable(&lp->napi);
1254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 spin_lock_irq(&lp->lock);
1256
1257 amd8111e_init_hw_default(lp);
1258
1259 if(amd8111e_restart(dev)){
1260 spin_unlock_irq(&lp->lock);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001261 napi_disable(&lp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 if (dev->irq)
1263 free_irq(dev->irq, dev);
1264 return -ENOMEM;
1265 }
1266 /* Start ipg timer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001267 if(lp->options & OPTION_DYN_IPG_ENABLE){
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 add_timer(&lp->ipg_data.ipg_timer);
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301269 netdev_info(dev, "Dynamic IPG Enabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 }
1271
1272 lp->opened = 1;
1273
1274 spin_unlock_irq(&lp->lock);
1275
1276 netif_start_queue(dev);
1277
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001278 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001280/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281This function checks if there is any transmit descriptors available to queue more packet.
1282*/
1283static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001284{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 int tx_index = lp->tx_idx & TX_BUFF_MOD_MASK;
Al Viroee41a822007-08-22 21:37:46 -04001286 if (lp->tx_skbuff[tx_index])
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 return -1;
1288 else
1289 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001290
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001292/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293This function will queue the transmit packets to the descriptors and will trigger the send operation. It also initializes the transmit descriptors with buffer physical address, byte count, ownership to hardware etc.
1294*/
1295
Stephen Hemminger613573252009-08-31 19:50:58 +00001296static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
1297 struct net_device * dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298{
1299 struct amd8111e_priv *lp = netdev_priv(dev);
1300 int tx_index;
1301 unsigned long flags;
1302
1303 spin_lock_irqsave(&lp->lock, flags);
1304
1305 tx_index = lp->tx_idx & TX_RING_DR_MOD_MASK;
1306
1307 lp->tx_ring[tx_index].buff_count = cpu_to_le16(skb->len);
1308
1309 lp->tx_skbuff[tx_index] = skb;
1310 lp->tx_ring[tx_index].tx_flags = 0;
1311
1312#if AMD8111E_VLAN_TAG_USED
Jesse Grosseab6d182010-10-20 13:56:03 +00001313 if (vlan_tx_tag_present(skb)) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001314 lp->tx_ring[tx_index].tag_ctrl_cmd |=
1315 cpu_to_le16(TCC_VLAN_INSERT);
1316 lp->tx_ring[tx_index].tag_ctrl_info =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 cpu_to_le16(vlan_tx_tag_get(skb));
1318
1319 }
1320#endif
1321 lp->tx_dma_addr[tx_index] =
1322 pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
1323 lp->tx_ring[tx_index].buff_phy_addr =
Al Viroee41a822007-08-22 21:37:46 -04001324 cpu_to_le32(lp->tx_dma_addr[tx_index]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
1326 /* Set FCS and LTINT bits */
1327 wmb();
1328 lp->tx_ring[tx_index].tx_flags |=
1329 cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT|ADD_FCS_BIT|LTINT_BIT);
1330
1331 lp->tx_idx++;
1332
1333 /* Trigger an immediate send poll. */
1334 writel( VAL1 | TDMD0, lp->mmio + CMD0);
1335 writel( VAL2 | RDMD0,lp->mmio + CMD0);
1336
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 if(amd8111e_tx_queue_avail(lp) < 0){
1338 netif_stop_queue(dev);
1339 }
1340 spin_unlock_irqrestore(&lp->lock, flags);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001341 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342}
1343/*
1344This function returns all the memory mapped registers of the device.
1345*/
1346static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
1347{
1348 void __iomem *mmio = lp->mmio;
1349 /* Read only necessary registers */
1350 buf[0] = readl(mmio + XMT_RING_BASE_ADDR0);
1351 buf[1] = readl(mmio + XMT_RING_LEN0);
1352 buf[2] = readl(mmio + RCV_RING_BASE_ADDR0);
1353 buf[3] = readl(mmio + RCV_RING_LEN0);
1354 buf[4] = readl(mmio + CMD0);
1355 buf[5] = readl(mmio + CMD2);
1356 buf[6] = readl(mmio + CMD3);
1357 buf[7] = readl(mmio + CMD7);
1358 buf[8] = readl(mmio + INT0);
1359 buf[9] = readl(mmio + INTEN0);
1360 buf[10] = readl(mmio + LADRF);
1361 buf[11] = readl(mmio + LADRF+4);
1362 buf[12] = readl(mmio + STAT0);
1363}
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366/*
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001367This function sets promiscuos mode, all-multi mode or the multicast address
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368list to the device.
1369*/
1370static void amd8111e_set_multicast_list(struct net_device *dev)
1371{
Jiri Pirko22bedad32010-04-01 21:22:57 +00001372 struct netdev_hw_addr *ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 struct amd8111e_priv *lp = netdev_priv(dev);
1374 u32 mc_filter[2] ;
Jiri Pirko0ddf4772010-02-20 00:13:58 +00001375 int bit_num;
1376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 if(dev->flags & IFF_PROMISC){
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 writel( VAL2 | PROM, lp->mmio + CMD2);
1379 return;
1380 }
1381 else
1382 writel( PROM, lp->mmio + CMD2);
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001383 if (dev->flags & IFF_ALLMULTI ||
1384 netdev_mc_count(dev) > MAX_FILTER_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 /* get all multicast packet */
1386 mc_filter[1] = mc_filter[0] = 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 lp->options |= OPTION_MULTICAST_ENABLE;
1388 amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
1389 return;
1390 }
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001391 if (netdev_mc_empty(dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 /* get only own packets */
1393 mc_filter[1] = mc_filter[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 lp->options &= ~OPTION_MULTICAST_ENABLE;
1395 amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001396 /* disable promiscuous mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 writel(PROM, lp->mmio + CMD2);
1398 return;
1399 }
1400 /* load all the multicast addresses in the logic filter */
1401 lp->options |= OPTION_MULTICAST_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 mc_filter[1] = mc_filter[0] = 0;
Jiri Pirko22bedad32010-04-01 21:22:57 +00001403 netdev_for_each_mc_addr(ha, dev) {
1404 bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
1408
1409 /* To eliminate PCI posting bug */
1410 readl(lp->mmio + CMD2);
1411
1412}
1413
1414static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
1415{
1416 struct amd8111e_priv *lp = netdev_priv(dev);
1417 struct pci_dev *pci_dev = lp->pci_dev;
Rick Jones23020ab2011-11-09 09:58:07 +00001418 strlcpy(info->driver, MODULE_NAME, sizeof(info->driver));
1419 strlcpy(info->version, MODULE_VERS, sizeof(info->version));
1420 snprintf(info->fw_version, sizeof(info->fw_version),
1421 "%u", chip_version);
1422 strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423}
1424
1425static int amd8111e_get_regs_len(struct net_device *dev)
1426{
1427 return AMD8111E_REG_DUMP_LEN;
1428}
1429
1430static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
1431{
1432 struct amd8111e_priv *lp = netdev_priv(dev);
1433 regs->version = 0;
1434 amd8111e_read_regs(lp, buf);
1435}
1436
1437static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1438{
1439 struct amd8111e_priv *lp = netdev_priv(dev);
1440 spin_lock_irq(&lp->lock);
1441 mii_ethtool_gset(&lp->mii_if, ecmd);
1442 spin_unlock_irq(&lp->lock);
1443 return 0;
1444}
1445
1446static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
1447{
1448 struct amd8111e_priv *lp = netdev_priv(dev);
1449 int res;
1450 spin_lock_irq(&lp->lock);
1451 res = mii_ethtool_sset(&lp->mii_if, ecmd);
1452 spin_unlock_irq(&lp->lock);
1453 return res;
1454}
1455
1456static int amd8111e_nway_reset(struct net_device *dev)
1457{
1458 struct amd8111e_priv *lp = netdev_priv(dev);
1459 return mii_nway_restart(&lp->mii_if);
1460}
1461
1462static u32 amd8111e_get_link(struct net_device *dev)
1463{
1464 struct amd8111e_priv *lp = netdev_priv(dev);
1465 return mii_link_ok(&lp->mii_if);
1466}
1467
1468static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
1469{
1470 struct amd8111e_priv *lp = netdev_priv(dev);
1471 wol_info->supported = WAKE_MAGIC|WAKE_PHY;
1472 if (lp->options & OPTION_WOL_ENABLE)
1473 wol_info->wolopts = WAKE_MAGIC;
1474}
1475
1476static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
1477{
1478 struct amd8111e_priv *lp = netdev_priv(dev);
1479 if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY))
1480 return -EINVAL;
1481 spin_lock_irq(&lp->lock);
1482 if (wol_info->wolopts & WAKE_MAGIC)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001483 lp->options |=
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 (OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE);
1485 else if(wol_info->wolopts & WAKE_PHY)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001486 lp->options |=
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 (OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE);
1488 else
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001489 lp->options &= ~OPTION_WOL_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 spin_unlock_irq(&lp->lock);
1491 return 0;
1492}
1493
Jeff Garzik7282d492006-09-13 14:30:00 -04001494static const struct ethtool_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 .get_drvinfo = amd8111e_get_drvinfo,
1496 .get_regs_len = amd8111e_get_regs_len,
1497 .get_regs = amd8111e_get_regs,
1498 .get_settings = amd8111e_get_settings,
1499 .set_settings = amd8111e_set_settings,
1500 .nway_reset = amd8111e_nway_reset,
1501 .get_link = amd8111e_get_link,
1502 .get_wol = amd8111e_get_wol,
1503 .set_wol = amd8111e_set_wol,
1504};
1505
1506/*
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001507This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508*/
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
1511{
1512 struct mii_ioctl_data *data = if_mii(ifr);
1513 struct amd8111e_priv *lp = netdev_priv(dev);
1514 int err;
1515 u32 mii_regval;
1516
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 switch(cmd) {
1518 case SIOCGMIIPHY:
1519 data->phy_id = lp->ext_phy_addr;
1520
1521 /* fallthru */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001522 case SIOCGMIIREG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 spin_lock_irq(&lp->lock);
1525 err = amd8111e_read_phy(lp, data->phy_id,
1526 data->reg_num & PHY_REG_ADDR_MASK, &mii_regval);
1527 spin_unlock_irq(&lp->lock);
1528
1529 data->val_out = mii_regval;
1530 return err;
1531
1532 case SIOCSMIIREG:
1533
1534 spin_lock_irq(&lp->lock);
1535 err = amd8111e_write_phy(lp, data->phy_id,
1536 data->reg_num & PHY_REG_ADDR_MASK, data->val_in);
1537 spin_unlock_irq(&lp->lock);
1538
1539 return err;
1540
1541 default:
1542 /* do nothing */
1543 break;
1544 }
1545 return -EOPNOTSUPP;
1546}
1547static int amd8111e_set_mac_address(struct net_device *dev, void *p)
1548{
1549 struct amd8111e_priv *lp = netdev_priv(dev);
1550 int i;
1551 struct sockaddr *addr = p;
1552
1553 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
1554 spin_lock_irq(&lp->lock);
1555 /* Setting the MAC address to the device */
Joe Perchesc857ff62011-11-16 09:38:05 +00001556 for (i = 0; i < ETH_ALEN; i++)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001557 writeb( dev->dev_addr[i], lp->mmio + PADR + i );
1558
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 spin_unlock_irq(&lp->lock);
1560
1561 return 0;
1562}
1563
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001564/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers.
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001566*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
1568{
1569 struct amd8111e_priv *lp = netdev_priv(dev);
1570 int err;
1571
1572 if ((new_mtu < AMD8111E_MIN_MTU) || (new_mtu > AMD8111E_MAX_MTU))
1573 return -EINVAL;
1574
1575 if (!netif_running(dev)) {
1576 /* new_mtu will be used
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001577 when device starts netxt time */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 dev->mtu = new_mtu;
1579 return 0;
1580 }
1581
1582 spin_lock_irq(&lp->lock);
1583
1584 /* stop the chip */
1585 writel(RUN, lp->mmio + CMD0);
1586
1587 dev->mtu = new_mtu;
1588
1589 err = amd8111e_restart(dev);
1590 spin_unlock_irq(&lp->lock);
1591 if(!err)
1592 netif_start_queue(dev);
1593 return err;
1594}
1595
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
1597{
1598 writel( VAL1|MPPLBA, lp->mmio + CMD3);
1599 writel( VAL0|MPEN_SW, lp->mmio + CMD7);
1600
1601 /* To eliminate PCI posting bug */
1602 readl(lp->mmio + CMD7);
1603 return 0;
1604}
1605
1606static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
1607{
1608
1609 /* Adapter is already stoped/suspended/interrupt-disabled */
1610 writel(VAL0|LCMODE_SW,lp->mmio + CMD7);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 /* To eliminate PCI posting bug */
1613 readl(lp->mmio + CMD7);
1614 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001615}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001617/*
1618 * This function is called when a packet transmission fails to complete
1619 * within a reasonable period, on the assumption that an interrupt have
1620 * failed or the interface is locked up. This function will reinitialize
1621 * the hardware.
1622 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623static void amd8111e_tx_timeout(struct net_device *dev)
1624{
1625 struct amd8111e_priv* lp = netdev_priv(dev);
1626 int err;
1627
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301628 netdev_err(dev, "transmit timed out, resetting\n");
1629
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 spin_lock_irq(&lp->lock);
1631 err = amd8111e_restart(dev);
1632 spin_unlock_irq(&lp->lock);
1633 if(!err)
1634 netif_wake_queue(dev);
1635}
1636static int amd8111e_suspend(struct pci_dev *pci_dev, pm_message_t state)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001637{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 struct net_device *dev = pci_get_drvdata(pci_dev);
1639 struct amd8111e_priv *lp = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001640
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 if (!netif_running(dev))
1642 return 0;
1643
1644 /* disable the interrupt */
1645 spin_lock_irq(&lp->lock);
1646 amd8111e_disable_interrupt(lp);
1647 spin_unlock_irq(&lp->lock);
1648
1649 netif_device_detach(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001650
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 /* stop chip */
1652 spin_lock_irq(&lp->lock);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001653 if(lp->options & OPTION_DYN_IPG_ENABLE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 del_timer_sync(&lp->ipg_data.ipg_timer);
1655 amd8111e_stop_chip(lp);
1656 spin_unlock_irq(&lp->lock);
1657
1658 if(lp->options & OPTION_WOL_ENABLE){
1659 /* enable wol */
1660 if(lp->options & OPTION_WAKE_MAGIC_ENABLE)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001661 amd8111e_enable_magicpkt(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if(lp->options & OPTION_WAKE_PHY_ENABLE)
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001663 amd8111e_enable_link_change(lp);
1664
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 pci_enable_wake(pci_dev, PCI_D3hot, 1);
1666 pci_enable_wake(pci_dev, PCI_D3cold, 1);
1667
1668 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001669 else{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 pci_enable_wake(pci_dev, PCI_D3hot, 0);
1671 pci_enable_wake(pci_dev, PCI_D3cold, 0);
1672 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001673
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 pci_save_state(pci_dev);
1675 pci_set_power_state(pci_dev, PCI_D3hot);
1676
1677 return 0;
1678}
1679static int amd8111e_resume(struct pci_dev *pci_dev)
1680{
1681 struct net_device *dev = pci_get_drvdata(pci_dev);
1682 struct amd8111e_priv *lp = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001683
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 if (!netif_running(dev))
1685 return 0;
1686
1687 pci_set_power_state(pci_dev, PCI_D0);
1688 pci_restore_state(pci_dev);
1689
1690 pci_enable_wake(pci_dev, PCI_D3hot, 0);
1691 pci_enable_wake(pci_dev, PCI_D3cold, 0); /* D3 cold */
1692
1693 netif_device_attach(dev);
1694
1695 spin_lock_irq(&lp->lock);
1696 amd8111e_restart(dev);
1697 /* Restart ipg timer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001698 if(lp->options & OPTION_DYN_IPG_ENABLE)
1699 mod_timer(&lp->ipg_data.ipg_timer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 jiffies + IPG_CONVERGE_JIFFIES);
1701 spin_unlock_irq(&lp->lock);
1702
1703 return 0;
1704}
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706static void amd8111e_config_ipg(struct net_device* dev)
1707{
1708 struct amd8111e_priv *lp = netdev_priv(dev);
1709 struct ipg_info* ipg_data = &lp->ipg_data;
1710 void __iomem *mmio = lp->mmio;
1711 unsigned int prev_col_cnt = ipg_data->col_cnt;
1712 unsigned int total_col_cnt;
1713 unsigned int tmp_ipg;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001714
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if(lp->link_config.duplex == DUPLEX_FULL){
1716 ipg_data->ipg = DEFAULT_IPG;
1717 return;
1718 }
1719
1720 if(ipg_data->ipg_state == SSTATE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001721
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 if(ipg_data->timer_tick == IPG_STABLE_TIME){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001723
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 ipg_data->timer_tick = 0;
1725 ipg_data->ipg = MIN_IPG - IPG_STEP;
1726 ipg_data->current_ipg = MIN_IPG;
1727 ipg_data->diff_col_cnt = 0xFFFFFFFF;
1728 ipg_data->ipg_state = CSTATE;
1729 }
1730 else
1731 ipg_data->timer_tick++;
1732 }
1733
1734 if(ipg_data->ipg_state == CSTATE){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001735
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 /* Get the current collision count */
1737
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001738 total_col_cnt = ipg_data->col_cnt =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 amd8111e_read_mib(mmio, xmt_collisions);
1740
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001741 if ((total_col_cnt - prev_col_cnt) <
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 (ipg_data->diff_col_cnt)){
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001743
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 ipg_data->diff_col_cnt =
1745 total_col_cnt - prev_col_cnt ;
1746
1747 ipg_data->ipg = ipg_data->current_ipg;
1748 }
1749
1750 ipg_data->current_ipg += IPG_STEP;
1751
1752 if (ipg_data->current_ipg <= MAX_IPG)
1753 tmp_ipg = ipg_data->current_ipg;
1754 else{
1755 tmp_ipg = ipg_data->ipg;
1756 ipg_data->ipg_state = SSTATE;
1757 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001758 writew((u32)tmp_ipg, mmio + IPG);
1759 writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 }
1761 mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES);
1762 return;
1763
1764}
1765
Bill Pemberton0cb05682012-12-03 09:23:54 -05001766static void amd8111e_probe_ext_phy(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767{
1768 struct amd8111e_priv *lp = netdev_priv(dev);
1769 int i;
1770
1771 for (i = 0x1e; i >= 0; i--) {
1772 u32 id1, id2;
1773
1774 if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
1775 continue;
1776 if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
1777 continue;
1778 lp->ext_phy_id = (id1 << 16) | id2;
1779 lp->ext_phy_addr = i;
1780 return;
1781 }
1782 lp->ext_phy_id = 0;
1783 lp->ext_phy_addr = 1;
1784}
1785
Stephen Hemminger887e53d2009-01-07 18:09:58 -08001786static const struct net_device_ops amd8111e_netdev_ops = {
1787 .ndo_open = amd8111e_open,
1788 .ndo_stop = amd8111e_close,
1789 .ndo_start_xmit = amd8111e_start_xmit,
1790 .ndo_tx_timeout = amd8111e_tx_timeout,
1791 .ndo_get_stats = amd8111e_get_stats,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00001792 .ndo_set_rx_mode = amd8111e_set_multicast_list,
Stephen Hemminger887e53d2009-01-07 18:09:58 -08001793 .ndo_validate_addr = eth_validate_addr,
1794 .ndo_set_mac_address = amd8111e_set_mac_address,
1795 .ndo_do_ioctl = amd8111e_ioctl,
1796 .ndo_change_mtu = amd8111e_change_mtu,
Stephen Hemminger887e53d2009-01-07 18:09:58 -08001797#ifdef CONFIG_NET_POLL_CONTROLLER
1798 .ndo_poll_controller = amd8111e_poll,
1799#endif
1800};
1801
Bill Pemberton0cb05682012-12-03 09:23:54 -05001802static int amd8111e_probe_one(struct pci_dev *pdev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 const struct pci_device_id *ent)
1804{
Yijing Wangf9c7da52013-06-18 16:06:37 +08001805 int err, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 unsigned long reg_addr,reg_len;
1807 struct amd8111e_priv* lp;
1808 struct net_device* dev;
1809
1810 err = pci_enable_device(pdev);
1811 if(err){
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301812 dev_err(&pdev->dev, "Cannot enable new PCI device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 return err;
1814 }
1815
1816 if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301817 dev_err(&pdev->dev, "Cannot find PCI base address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 err = -ENODEV;
1819 goto err_disable_pdev;
1820 }
1821
1822 err = pci_request_regions(pdev, MODULE_NAME);
1823 if(err){
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301824 dev_err(&pdev->dev, "Cannot obtain PCI resources\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 goto err_disable_pdev;
1826 }
1827
1828 pci_set_master(pdev);
1829
1830 /* Find power-management capability. */
Yijing Wangf9c7da52013-06-18 16:06:37 +08001831 if (!pdev->pm_cap) {
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301832 dev_err(&pdev->dev, "No Power Management capability\n");
Peter Senna Tschudin86e506e2012-10-05 12:10:51 +00001833 err = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 goto err_free_reg;
1835 }
1836
1837 /* Initialize DMA */
Yang Hongyang284901a2009-04-06 19:01:15 -07001838 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301839 dev_err(&pdev->dev, "DMA not supported\n");
Peter Senna Tschudin86e506e2012-10-05 12:10:51 +00001840 err = -ENODEV;
Tobias Klausercac8c812005-05-16 19:15:11 +02001841 goto err_free_reg;
1842 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001843
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 reg_addr = pci_resource_start(pdev, 0);
1845 reg_len = pci_resource_len(pdev, 0);
1846
1847 dev = alloc_etherdev(sizeof(struct amd8111e_priv));
1848 if (!dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 err = -ENOMEM;
1850 goto err_free_reg;
1851 }
1852
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 SET_NETDEV_DEV(dev, &pdev->dev);
1854
1855#if AMD8111E_VLAN_TAG_USED
Patrick McHardyf6469682013-04-19 02:04:27 +00001856 dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX ;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001857#endif
1858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 lp = netdev_priv(dev);
1860 lp->pci_dev = pdev;
1861 lp->amd8111e_net_dev = dev;
Yijing Wangf9c7da52013-06-18 16:06:37 +08001862 lp->pm_cap = pdev->pm_cap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 spin_lock_init(&lp->lock);
1865
Varka Bhadram711fec52014-07-14 14:09:05 +05301866 lp->mmio = devm_ioremap(&pdev->dev, reg_addr, reg_len);
Al Viroee41a822007-08-22 21:37:46 -04001867 if (!lp->mmio) {
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301868 dev_err(&pdev->dev, "Cannot map device registers\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 err = -ENOMEM;
1870 goto err_free_dev;
1871 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001872
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 /* Initializing MAC address */
Joe Perchesc857ff62011-11-16 09:38:05 +00001874 for (i = 0; i < ETH_ALEN; i++)
Joe Perches0795af52007-10-03 17:59:30 -07001875 dev->dev_addr[i] = readb(lp->mmio + PADR + i);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001876
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 /* Setting user defined parametrs */
1878 lp->ext_phy_option = speed_duplex[card_idx];
1879 if(coalesce[card_idx])
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001880 lp->options |= OPTION_INTR_COAL_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if(dynamic_ipg[card_idx++])
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001882 lp->options |= OPTION_DYN_IPG_ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Stephen Hemminger887e53d2009-01-07 18:09:58 -08001884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 /* Initialize driver entry points */
Stephen Hemminger887e53d2009-01-07 18:09:58 -08001886 dev->netdev_ops = &amd8111e_netdev_ops;
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +00001887 dev->ethtool_ops = &ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 dev->irq =pdev->irq;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001889 dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001890 netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
1892#if AMD8111E_VLAN_TAG_USED
Patrick McHardyf6469682013-04-19 02:04:27 +00001893 dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001894#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 /* Probe the external PHY */
1896 amd8111e_probe_ext_phy(dev);
1897
1898 /* setting mii default values */
1899 lp->mii_if.dev = dev;
1900 lp->mii_if.mdio_read = amd8111e_mdio_read;
1901 lp->mii_if.mdio_write = amd8111e_mdio_write;
1902 lp->mii_if.phy_id = lp->ext_phy_addr;
1903
1904 /* Set receive buffer length and set jumbo option*/
1905 amd8111e_set_rx_buff_len(dev);
1906
1907
1908 err = register_netdev(dev);
1909 if (err) {
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301910 dev_err(&pdev->dev, "Cannot register net device\n");
Varka Bhadram711fec52014-07-14 14:09:05 +05301911 goto err_free_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 }
1913
1914 pci_set_drvdata(pdev, dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001915
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 /* Initialize software ipg timer */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001917 if(lp->options & OPTION_DYN_IPG_ENABLE){
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 init_timer(&lp->ipg_data.ipg_timer);
1919 lp->ipg_data.ipg_timer.data = (unsigned long) dev;
1920 lp->ipg_data.ipg_timer.function = (void *)&amd8111e_config_ipg;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001921 lp->ipg_data.ipg_timer.expires = jiffies +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 IPG_CONVERGE_JIFFIES;
1923 lp->ipg_data.ipg = DEFAULT_IPG;
1924 lp->ipg_data.ipg_state = CSTATE;
Joe Perches6403eab2011-06-03 11:51:20 +00001925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
1927 /* display driver and device information */
1928
1929 chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301930 dev_info(&pdev->dev, "AMD-8111e Driver Version: %s\n", MODULE_VERS);
1931 dev_info(&pdev->dev, "[ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
1932 chip_version, dev->dev_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (lp->ext_phy_id)
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301934 dev_info(&pdev->dev, "Found MII PHY ID 0x%08x at address 0x%02x\n",
1935 lp->ext_phy_id, lp->ext_phy_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 else
Varka Bhadramf7afbaa2014-07-14 14:09:06 +05301937 dev_info(&pdev->dev, "Couldn't detect MII PHY, assuming address 0x01\n");
1938
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941err_free_dev:
1942 free_netdev(dev);
1943
1944err_free_reg:
1945 pci_release_regions(pdev);
1946
1947err_disable_pdev:
1948 pci_disable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 return err;
1950
1951}
1952
Varka Bhadram43519e62014-07-14 14:09:04 +05301953static void amd8111e_remove_one(struct pci_dev *pdev)
1954{
1955 struct net_device *dev = pci_get_drvdata(pdev);
1956
1957 if (dev) {
1958 unregister_netdev(dev);
Varka Bhadram43519e62014-07-14 14:09:04 +05301959 free_netdev(dev);
1960 pci_release_regions(pdev);
1961 pci_disable_device(pdev);
1962 }
1963}
1964
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965static struct pci_driver amd8111e_driver = {
1966 .name = MODULE_NAME,
1967 .id_table = amd8111e_pci_tbl,
1968 .probe = amd8111e_probe_one,
Bill Pemberton0cb05682012-12-03 09:23:54 -05001969 .remove = amd8111e_remove_one,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 .suspend = amd8111e_suspend,
1971 .resume = amd8111e_resume
1972};
1973
Peter Hüwea46e6cc2013-05-21 12:58:10 +00001974module_pci_driver(amd8111e_driver);