blob: 490ec5b2775a225263f8a23ac9ee2f8abbe7e7bb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This code is derived from the VIA reference driver (copyright message
3 * below) provided to Red Hat by VIA Networking Technologies, Inc. for
4 * addition to the Linux kernel.
5 *
6 * The code has been merged into one source file, cleaned up to follow
7 * Linux coding style, ported to the Linux 2.6 kernel tree and cleaned
8 * for 64bit hardware platforms.
9 *
10 * TODO
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * rx_copybreak/alignment
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * More testing
13 *
Alan Cox113aa832008-10-13 19:01:08 -070014 * The changes are (c) Copyright 2004, Red Hat Inc. <alan@lxorguk.ukuu.org.uk>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * Additional fixes and clean up: Francois Romieu
16 *
17 * This source has not been verified for use in safety critical systems.
18 *
19 * Please direct queries about the revamped driver to the linux-kernel
20 * list not VIA.
21 *
22 * Original code:
23 *
24 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
25 * All rights reserved.
26 *
27 * This software may be redistributed and/or modified under
28 * the terms of the GNU General Public License as published by the Free
29 * Software Foundation; either version 2 of the License, or
30 * any later version.
31 *
32 * This program is distributed in the hope that it will be useful, but
33 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
34 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35 * for more details.
36 *
37 * Author: Chuang Liang-Shing, AJ Jiang
38 *
39 * Date: Jan 24, 2003
40 *
41 * MODULE_LICENSE("GPL");
42 *
43 */
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/module.h>
46#include <linux/types.h>
Jiri Pirko73b54682011-07-20 04:54:30 +000047#include <linux/bitops.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <linux/init.h>
49#include <linux/mm.h>
50#include <linux/errno.h>
51#include <linux/ioport.h>
52#include <linux/pci.h>
53#include <linux/kernel.h>
54#include <linux/netdevice.h>
55#include <linux/etherdevice.h>
56#include <linux/skbuff.h>
57#include <linux/delay.h>
58#include <linux/timer.h>
59#include <linux/slab.h>
60#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/string.h>
62#include <linux/wait.h>
Dave Jonesc4067402009-07-20 17:35:21 +000063#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include <linux/if.h>
Dave Jonesc4067402009-07-20 17:35:21 +000065#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <linux/proc_fs.h>
67#include <linux/inetdevice.h>
68#include <linux/reboot.h>
69#include <linux/ethtool.h>
70#include <linux/mii.h>
71#include <linux/in.h>
72#include <linux/if_arp.h>
Stephen Hemminger501e4d22007-08-24 13:56:49 -070073#include <linux/if_vlan.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070074#include <linux/ip.h>
75#include <linux/tcp.h>
76#include <linux/udp.h>
77#include <linux/crc-ccitt.h>
78#include <linux/crc32.h>
79
80#include "via-velocity.h"
81
82
Dave Jonesc4067402009-07-20 17:35:21 +000083static int velocity_nics;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084static int msglevel = MSG_LEVEL_INFO;
85
Stephen Hemminger01faccb2007-08-24 14:40:45 -070086/**
87 * mac_get_cam_mask - Read a CAM mask
88 * @regs: register block for this velocity
89 * @mask: buffer to store mask
90 *
91 * Fetch the mask bits of the selected CAM and store them into the
92 * provided mask buffer.
93 */
Dave Jonesc4067402009-07-20 17:35:21 +000094static void mac_get_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
Stephen Hemminger01faccb2007-08-24 14:40:45 -070095{
96 int i;
97
98 /* Select CAM mask */
99 BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
100
101 writeb(0, &regs->CAMADDR);
102
103 /* read mask */
104 for (i = 0; i < 8; i++)
105 *mask++ = readb(&(regs->MARCAM[i]));
106
107 /* disable CAMEN */
108 writeb(0, &regs->CAMADDR);
109
110 /* Select mar */
111 BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700112}
113
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700114/**
115 * mac_set_cam_mask - Set a CAM mask
116 * @regs: register block for this velocity
117 * @mask: CAM mask to load
118 *
119 * Store a new mask into a CAM
120 */
Dave Jonesc4067402009-07-20 17:35:21 +0000121static void mac_set_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700122{
123 int i;
124 /* Select CAM mask */
125 BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
126
127 writeb(CAMADDR_CAMEN, &regs->CAMADDR);
128
Dave Jonesc4067402009-07-20 17:35:21 +0000129 for (i = 0; i < 8; i++)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700130 writeb(*mask++, &(regs->MARCAM[i]));
Dave Jonesc4067402009-07-20 17:35:21 +0000131
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700132 /* disable CAMEN */
133 writeb(0, &regs->CAMADDR);
134
135 /* Select mar */
136 BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
137}
138
Dave Jonesc4067402009-07-20 17:35:21 +0000139static void mac_set_vlan_cam_mask(struct mac_regs __iomem *regs, u8 *mask)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700140{
141 int i;
142 /* Select CAM mask */
143 BYTE_REG_BITS_SET(CAMCR_PS_CAM_MASK, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
144
145 writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL, &regs->CAMADDR);
146
Dave Jonesc4067402009-07-20 17:35:21 +0000147 for (i = 0; i < 8; i++)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700148 writeb(*mask++, &(regs->MARCAM[i]));
Dave Jonesc4067402009-07-20 17:35:21 +0000149
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700150 /* disable CAMEN */
151 writeb(0, &regs->CAMADDR);
152
153 /* Select mar */
154 BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
155}
156
157/**
158 * mac_set_cam - set CAM data
159 * @regs: register block of this velocity
160 * @idx: Cam index
161 * @addr: 2 or 6 bytes of CAM data
162 *
163 * Load an address or vlan tag into a CAM
164 */
Dave Jonesc4067402009-07-20 17:35:21 +0000165static void mac_set_cam(struct mac_regs __iomem *regs, int idx, const u8 *addr)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700166{
167 int i;
168
169 /* Select CAM mask */
170 BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
171
172 idx &= (64 - 1);
173
174 writeb(CAMADDR_CAMEN | idx, &regs->CAMADDR);
175
Dave Jonesc4067402009-07-20 17:35:21 +0000176 for (i = 0; i < 6; i++)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700177 writeb(*addr++, &(regs->MARCAM[i]));
Dave Jonesc4067402009-07-20 17:35:21 +0000178
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700179 BYTE_REG_BITS_ON(CAMCR_CAMWR, &regs->CAMCR);
180
181 udelay(10);
182
183 writeb(0, &regs->CAMADDR);
184
185 /* Select mar */
186 BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
187}
188
Dave Jonesc4067402009-07-20 17:35:21 +0000189static void mac_set_vlan_cam(struct mac_regs __iomem *regs, int idx,
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700190 const u8 *addr)
191{
192
193 /* Select CAM mask */
194 BYTE_REG_BITS_SET(CAMCR_PS_CAM_DATA, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
195
196 idx &= (64 - 1);
197
198 writeb(CAMADDR_CAMEN | CAMADDR_VCAMSL | idx, &regs->CAMADDR);
199 writew(*((u16 *) addr), &regs->MARCAM[0]);
200
201 BYTE_REG_BITS_ON(CAMCR_CAMWR, &regs->CAMCR);
202
203 udelay(10);
204
205 writeb(0, &regs->CAMADDR);
206
207 /* Select mar */
208 BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
209}
210
211
212/**
213 * mac_wol_reset - reset WOL after exiting low power
214 * @regs: register block of this velocity
215 *
216 * Called after we drop out of wake on lan mode in order to
217 * reset the Wake on lan features. This function doesn't restore
218 * the rest of the logic from the result of sleep/wakeup
219 */
Dave Jonesc4067402009-07-20 17:35:21 +0000220static void mac_wol_reset(struct mac_regs __iomem *regs)
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700221{
222
223 /* Turn off SWPTAG right after leaving power mode */
224 BYTE_REG_BITS_OFF(STICKHW_SWPTAG, &regs->STICKHW);
225 /* clear sticky bits */
226 BYTE_REG_BITS_OFF((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
227
228 BYTE_REG_BITS_OFF(CHIPGCR_FCGMII, &regs->CHIPGCR);
229 BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
230 /* disable force PME-enable */
231 writeb(WOLCFG_PMEOVR, &regs->WOLCFGClr);
232 /* disable power-event config bit */
233 writew(0xFFFF, &regs->WOLCRClr);
234 /* clear power status */
235 writew(0xFFFF, &regs->WOLSRClr);
236}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Jeff Garzik7282d492006-09-13 14:30:00 -0400238static const struct ethtool_ops velocity_ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240/*
241 Define module options
242*/
243
244MODULE_AUTHOR("VIA Networking Technologies, Inc.");
245MODULE_LICENSE("GPL");
246MODULE_DESCRIPTION("VIA Networking Velocity Family Gigabit Ethernet Adapter Driver");
247
Dave Jonesc4067402009-07-20 17:35:21 +0000248#define VELOCITY_PARAM(N, D) \
249 static int N[MAX_UNITS] = OPTION_DEFAULT;\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 module_param_array(N, int, NULL, 0); \
Dave Jonesc4067402009-07-20 17:35:21 +0000251 MODULE_PARM_DESC(N, D);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253#define RX_DESC_MIN 64
254#define RX_DESC_MAX 255
255#define RX_DESC_DEF 64
256VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors");
257
258#define TX_DESC_MIN 16
259#define TX_DESC_MAX 256
260#define TX_DESC_DEF 64
261VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors");
262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263#define RX_THRESH_MIN 0
264#define RX_THRESH_MAX 3
265#define RX_THRESH_DEF 0
266/* rx_thresh[] is used for controlling the receive fifo threshold.
267 0: indicate the rxfifo threshold is 128 bytes.
268 1: indicate the rxfifo threshold is 512 bytes.
269 2: indicate the rxfifo threshold is 1024 bytes.
270 3: indicate the rxfifo threshold is store & forward.
271*/
272VELOCITY_PARAM(rx_thresh, "Receive fifo threshold");
273
274#define DMA_LENGTH_MIN 0
275#define DMA_LENGTH_MAX 7
Simon Kagstrom2a5774f2009-11-25 22:10:34 +0000276#define DMA_LENGTH_DEF 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278/* DMA_length[] is used for controlling the DMA length
279 0: 8 DWORDs
280 1: 16 DWORDs
281 2: 32 DWORDs
282 3: 64 DWORDs
283 4: 128 DWORDs
284 5: 256 DWORDs
285 6: SF(flush till emply)
286 7: SF(flush till emply)
287*/
288VELOCITY_PARAM(DMA_length, "DMA length");
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290#define IP_ALIG_DEF 0
291/* IP_byte_align[] is used for IP header DWORD byte aligned
292 0: indicate the IP header won't be DWORD byte aligned.(Default) .
293 1: indicate the IP header will be DWORD byte aligned.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300294 In some environment, the IP header should be DWORD byte aligned,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 or the packet will be droped when we receive it. (eg: IPVS)
296*/
297VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned");
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299#define FLOW_CNTL_DEF 1
300#define FLOW_CNTL_MIN 1
301#define FLOW_CNTL_MAX 5
302
303/* flow_control[] is used for setting the flow control ability of NIC.
304 1: hardware deafult - AUTO (default). Use Hardware default value in ANAR.
305 2: enable TX flow control.
306 3: enable RX flow control.
307 4: enable RX/TX flow control.
308 5: disable
309*/
310VELOCITY_PARAM(flow_control, "Enable flow control ability");
311
312#define MED_LNK_DEF 0
313#define MED_LNK_MIN 0
françois romieu15419222010-10-13 09:26:05 +0000314#define MED_LNK_MAX 5
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
316 0: indicate autonegotiation for both speed and duplex mode
317 1: indicate 100Mbps half duplex mode
318 2: indicate 100Mbps full duplex mode
319 3: indicate 10Mbps half duplex mode
320 4: indicate 10Mbps full duplex mode
françois romieu15419222010-10-13 09:26:05 +0000321 5: indicate 1000Mbps full duplex mode
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 Note:
Dave Jonesc4067402009-07-20 17:35:21 +0000324 if EEPROM have been set to the force mode, this option is ignored
325 by driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326*/
327VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
328
329#define VAL_PKT_LEN_DEF 0
330/* ValPktLen[] is used for setting the checksum offload ability of NIC.
331 0: Receive frame with invalid layer 2 length (Default)
332 1: Drop frame with invalid layer 2 length
333*/
334VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
335
336#define WOL_OPT_DEF 0
337#define WOL_OPT_MIN 0
338#define WOL_OPT_MAX 7
339/* wol_opts[] is used for controlling wake on lan behavior.
340 0: Wake up if recevied a magic packet. (Default)
341 1: Wake up if link status is on/off.
342 2: Wake up if recevied an arp packet.
343 4: Wake up if recevied any unicast packet.
344 Those value can be sumed up to support more than one option.
345*/
346VELOCITY_PARAM(wol_opts, "Wake On Lan options");
347
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348static int rx_copybreak = 200;
349module_param(rx_copybreak, int, 0644);
350MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352/*
353 * Internal board variants. At the moment we have only one
354 */
Andrew Morton4f14b922008-02-09 23:41:40 -0800355static struct velocity_info_tbl chip_info_table[] = {
Jeff Garzikcabb7662006-06-27 09:25:28 -0400356 {CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
357 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358};
359
360/*
361 * Describe the PCI device identifiers that we support in this
362 * device driver. Used for hotplug autoloading.
363 */
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000364static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = {
Jeff Garzike54f4892006-06-27 09:20:08 -0400365 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
366 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
369MODULE_DEVICE_TABLE(pci, velocity_id_table);
370
371/**
372 * get_chip_name - identifier to name
373 * @id: chip identifier
374 *
375 * Given a chip identifier return a suitable description. Returns
376 * a pointer a static string valid while the driver is loaded.
377 */
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700378static const char __devinit *get_chip_name(enum chip_type chip_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379{
380 int i;
381 for (i = 0; chip_info_table[i].name != NULL; i++)
382 if (chip_info_table[i].chip_id == chip_id)
383 break;
384 return chip_info_table[i].name;
385}
386
387/**
388 * velocity_remove1 - device unplug
389 * @pdev: PCI device being removed
390 *
391 * Device unload callback. Called on an unplug or on module
392 * unload for each active device that is present. Disconnects
393 * the device from the network layer and frees all the resources
394 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395static void __devexit velocity_remove1(struct pci_dev *pdev)
396{
397 struct net_device *dev = pci_get_drvdata(pdev);
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -0400398 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 unregister_netdev(dev);
401 iounmap(vptr->mac_regs);
402 pci_release_regions(pdev);
403 pci_disable_device(pdev);
404 pci_set_drvdata(pdev, NULL);
405 free_netdev(dev);
406
407 velocity_nics--;
408}
409
410/**
411 * velocity_set_int_opt - parser for integer options
412 * @opt: pointer to option value
413 * @val: value the user requested (or -1 for default)
414 * @min: lowest value allowed
415 * @max: highest value allowed
416 * @def: default value
417 * @name: property name
418 * @dev: device name
419 *
420 * Set an integer property in the module options. This function does
421 * all the verification and checking as well as reporting so that
422 * we don't duplicate code for each option.
423 */
Sven Hartge07b5f6a2008-10-23 13:03:44 +0000424static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
426 if (val == -1)
427 *opt = def;
428 else if (val < min || val > max) {
429 VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",
430 devname, name, min, max);
431 *opt = def;
432 } else {
433 VELOCITY_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",
434 devname, name, val);
435 *opt = val;
436 }
437}
438
439/**
440 * velocity_set_bool_opt - parser for boolean options
441 * @opt: pointer to option value
442 * @val: value the user requested (or -1 for default)
443 * @def: default value (yes/no)
444 * @flag: numeric value to set for true.
445 * @name: property name
446 * @dev: device name
447 *
448 * Set a boolean property in the module options. This function does
449 * all the verification and checking as well as reporting so that
450 * we don't duplicate code for each option.
451 */
Dave Jonesc4067402009-07-20 17:35:21 +0000452static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453{
454 (*opt) &= (~flag);
455 if (val == -1)
456 *opt |= (def ? flag : 0);
457 else if (val < 0 || val > 1) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400458 printk(KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 devname, name);
460 *opt |= (def ? flag : 0);
461 } else {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400462 printk(KERN_INFO "%s: set parameter %s to %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 devname, name, val ? "TRUE" : "FALSE");
464 *opt |= (val ? flag : 0);
465 }
466}
467
468/**
469 * velocity_get_options - set options on device
470 * @opts: option structure for the device
471 * @index: index of option to use in module options array
472 * @devname: device name
473 *
474 * Turn the module and command options into a single structure
475 * for the current device
476 */
Sven Hartge07b5f6a2008-10-23 13:03:44 +0000477static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
479
480 velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
481 velocity_set_int_opt(&opts->DMA_length, DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF, "DMA_length", devname);
482 velocity_set_int_opt(&opts->numrx, RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors", devname);
483 velocity_set_int_opt(&opts->numtx, TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors", devname);
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);
486 velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
487 velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
488 velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
489 velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 opts->numrx = (opts->numrx & ~3);
491}
492
493/**
494 * velocity_init_cam_filter - initialise CAM
495 * @vptr: velocity to program
496 *
497 * Initialize the content addressable memory used for filters. Load
498 * appropriately according to the presence of VLAN
499 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500static void velocity_init_cam_filter(struct velocity_info *vptr)
501{
Dave Jonesc4067402009-07-20 17:35:21 +0000502 struct mac_regs __iomem *regs = vptr->mac_regs;
Jiri Pirko73b54682011-07-20 04:54:30 +0000503 unsigned int vid, i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
505 /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
506 WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
507 WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
508
509 /* Disable all CAMs */
510 memset(vptr->vCAMmask, 0, sizeof(u8) * 8);
511 memset(vptr->mCAMmask, 0, sizeof(u8) * 8);
Stephen Hemminger01faccb2007-08-24 14:40:45 -0700512 mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
513 mac_set_cam_mask(regs, vptr->mCAMmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Francois Romieud4f73c82008-04-24 23:32:33 +0200515 /* Enable VCAMs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Jiri Pirko73b54682011-07-20 04:54:30 +0000517 if (test_bit(0, vptr->active_vlans))
518 WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
Francois Romieud4f73c82008-04-24 23:32:33 +0200519
Jiri Pirko73b54682011-07-20 04:54:30 +0000520 for_each_set_bit(vid, vptr->active_vlans, VLAN_N_VID) {
521 mac_set_vlan_cam(regs, i, (u8 *) &vid);
522 vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
523 if (++i >= VCAM_SIZE)
524 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 }
Jiri Pirko73b54682011-07-20 04:54:30 +0000526 mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
Francois Romieud4f73c82008-04-24 23:32:33 +0200527}
528
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700529static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
530{
531 struct velocity_info *vptr = netdev_priv(dev);
532
Dave Jonesc4067402009-07-20 17:35:21 +0000533 spin_lock_irq(&vptr->lock);
Jiri Pirko73b54682011-07-20 04:54:30 +0000534 set_bit(vid, vptr->active_vlans);
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700535 velocity_init_cam_filter(vptr);
Dave Jonesc4067402009-07-20 17:35:21 +0000536 spin_unlock_irq(&vptr->lock);
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700537}
538
539static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
540{
541 struct velocity_info *vptr = netdev_priv(dev);
542
Dave Jonesc4067402009-07-20 17:35:21 +0000543 spin_lock_irq(&vptr->lock);
Jiri Pirko73b54682011-07-20 04:54:30 +0000544 clear_bit(vid, vptr->active_vlans);
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700545 velocity_init_cam_filter(vptr);
Dave Jonesc4067402009-07-20 17:35:21 +0000546 spin_unlock_irq(&vptr->lock);
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700547}
548
Francois Romieu3c4dc712008-07-31 22:51:18 +0200549static void velocity_init_rx_ring_indexes(struct velocity_info *vptr)
550{
551 vptr->rx.dirty = vptr->rx.filled = vptr->rx.curr = 0;
552}
Stephen Hemminger501e4d22007-08-24 13:56:49 -0700553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554/**
555 * velocity_rx_reset - handle a receive reset
556 * @vptr: velocity we are resetting
557 *
558 * Reset the ownership and status for the receive ring side.
559 * Hand all the receive queue to the NIC.
560 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561static void velocity_rx_reset(struct velocity_info *vptr)
562{
563
Dave Jonesc4067402009-07-20 17:35:21 +0000564 struct mac_regs __iomem *regs = vptr->mac_regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 int i;
566
Francois Romieu3c4dc712008-07-31 22:51:18 +0200567 velocity_init_rx_ring_indexes(vptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 /*
570 * Init state, all RD entries belong to the NIC
571 */
572 for (i = 0; i < vptr->options.numrx; ++i)
Francois Romieu0fe9f152008-07-31 22:10:10 +0200573 vptr->rx.ring[i].rdesc0.len |= OWNED_BY_NIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
575 writew(vptr->options.numrx, &regs->RBRDU);
Francois Romieu0fe9f152008-07-31 22:10:10 +0200576 writel(vptr->rx.pool_dma, &regs->RDBaseLo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 writew(0, &regs->RDIdx);
578 writew(vptr->options.numrx - 1, &regs->RDCSize);
579}
580
581/**
Dave Jones2cf71d22009-07-23 18:11:12 -0700582 * velocity_get_opt_media_mode - get media selection
583 * @vptr: velocity adapter
584 *
585 * Get the media mode stored in EEPROM or module options and load
586 * mii_status accordingly. The requested link state information
587 * is also returned.
588 */
589static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
590{
591 u32 status = 0;
592
593 switch (vptr->options.spd_dpx) {
594 case SPD_DPX_AUTO:
595 status = VELOCITY_AUTONEG_ENABLE;
596 break;
597 case SPD_DPX_100_FULL:
598 status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
599 break;
600 case SPD_DPX_10_FULL:
601 status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
602 break;
603 case SPD_DPX_100_HALF:
604 status = VELOCITY_SPEED_100;
605 break;
606 case SPD_DPX_10_HALF:
607 status = VELOCITY_SPEED_10;
608 break;
françois romieu15419222010-10-13 09:26:05 +0000609 case SPD_DPX_1000_FULL:
610 status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
611 break;
Dave Jones2cf71d22009-07-23 18:11:12 -0700612 }
613 vptr->mii_status = status;
614 return status;
615}
616
617/**
618 * safe_disable_mii_autopoll - autopoll off
619 * @regs: velocity registers
620 *
621 * Turn off the autopoll and wait for it to disable on the chip
622 */
623static void safe_disable_mii_autopoll(struct mac_regs __iomem *regs)
624{
625 u16 ww;
626
627 /* turn off MAUTO */
628 writeb(0, &regs->MIICR);
629 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
630 udelay(1);
631 if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
632 break;
633 }
634}
635
636/**
637 * enable_mii_autopoll - turn on autopolling
638 * @regs: velocity registers
639 *
640 * Enable the MII link status autopoll feature on the Velocity
641 * hardware. Wait for it to enable.
642 */
643static void enable_mii_autopoll(struct mac_regs __iomem *regs)
644{
645 int ii;
646
647 writeb(0, &(regs->MIICR));
648 writeb(MIIADR_SWMPL, &regs->MIIADR);
649
650 for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
651 udelay(1);
652 if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
653 break;
654 }
655
656 writeb(MIICR_MAUTO, &regs->MIICR);
657
658 for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
659 udelay(1);
660 if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
661 break;
662 }
663
664}
665
666/**
667 * velocity_mii_read - read MII data
668 * @regs: velocity registers
669 * @index: MII register index
670 * @data: buffer for received data
671 *
672 * Perform a single read of an MII 16bit register. Returns zero
673 * on success or -ETIMEDOUT if the PHY did not respond.
674 */
675static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data)
676{
677 u16 ww;
678
679 /*
680 * Disable MIICR_MAUTO, so that mii addr can be set normally
681 */
682 safe_disable_mii_autopoll(regs);
683
684 writeb(index, &regs->MIIADR);
685
686 BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
687
688 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
689 if (!(readb(&regs->MIICR) & MIICR_RCMD))
690 break;
691 }
692
693 *data = readw(&regs->MIIDATA);
694
695 enable_mii_autopoll(regs);
696 if (ww == W_MAX_TIMEOUT)
697 return -ETIMEDOUT;
698 return 0;
699}
700
Dave Jones2cf71d22009-07-23 18:11:12 -0700701/**
702 * mii_check_media_mode - check media state
703 * @regs: velocity registers
704 *
705 * Check the current MII status and determine the link status
706 * accordingly
707 */
708static u32 mii_check_media_mode(struct mac_regs __iomem *regs)
709{
710 u32 status = 0;
711 u16 ANAR;
712
Francois Romieu3a7f8682010-04-06 14:24:53 -0700713 if (!MII_REG_BITS_IS_ON(BMSR_LSTATUS, MII_BMSR, regs))
Dave Jones2cf71d22009-07-23 18:11:12 -0700714 status |= VELOCITY_LINK_FAIL;
715
Francois Romieu3a7f8682010-04-06 14:24:53 -0700716 if (MII_REG_BITS_IS_ON(ADVERTISE_1000FULL, MII_CTRL1000, regs))
Dave Jones2cf71d22009-07-23 18:11:12 -0700717 status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
Francois Romieu3a7f8682010-04-06 14:24:53 -0700718 else if (MII_REG_BITS_IS_ON(ADVERTISE_1000HALF, MII_CTRL1000, regs))
Dave Jones2cf71d22009-07-23 18:11:12 -0700719 status |= (VELOCITY_SPEED_1000);
720 else {
Francois Romieu3a7f8682010-04-06 14:24:53 -0700721 velocity_mii_read(regs, MII_ADVERTISE, &ANAR);
722 if (ANAR & ADVERTISE_100FULL)
Dave Jones2cf71d22009-07-23 18:11:12 -0700723 status |= (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
Francois Romieu3a7f8682010-04-06 14:24:53 -0700724 else if (ANAR & ADVERTISE_100HALF)
Dave Jones2cf71d22009-07-23 18:11:12 -0700725 status |= VELOCITY_SPEED_100;
Francois Romieu3a7f8682010-04-06 14:24:53 -0700726 else if (ANAR & ADVERTISE_10FULL)
Dave Jones2cf71d22009-07-23 18:11:12 -0700727 status |= (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
728 else
729 status |= (VELOCITY_SPEED_10);
730 }
731
Francois Romieu3a7f8682010-04-06 14:24:53 -0700732 if (MII_REG_BITS_IS_ON(BMCR_ANENABLE, MII_BMCR, regs)) {
733 velocity_mii_read(regs, MII_ADVERTISE, &ANAR);
734 if ((ANAR & (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF))
735 == (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF)) {
736 if (MII_REG_BITS_IS_ON(ADVERTISE_1000HALF | ADVERTISE_1000FULL, MII_CTRL1000, regs))
Dave Jones2cf71d22009-07-23 18:11:12 -0700737 status |= VELOCITY_AUTONEG_ENABLE;
738 }
739 }
740
741 return status;
742}
743
744/**
745 * velocity_mii_write - write MII data
746 * @regs: velocity registers
747 * @index: MII register index
748 * @data: 16bit data for the MII register
749 *
750 * Perform a single write to an MII 16bit register. Returns zero
751 * on success or -ETIMEDOUT if the PHY did not respond.
752 */
753static int velocity_mii_write(struct mac_regs __iomem *regs, u8 mii_addr, u16 data)
754{
755 u16 ww;
756
757 /*
758 * Disable MIICR_MAUTO, so that mii addr can be set normally
759 */
760 safe_disable_mii_autopoll(regs);
761
762 /* MII reg offset */
763 writeb(mii_addr, &regs->MIIADR);
764 /* set MII data */
765 writew(data, &regs->MIIDATA);
766
767 /* turn on MIICR_WCMD */
768 BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
769
770 /* W_MAX_TIMEOUT is the timeout period */
771 for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
772 udelay(5);
773 if (!(readb(&regs->MIICR) & MIICR_WCMD))
774 break;
775 }
776 enable_mii_autopoll(regs);
777
778 if (ww == W_MAX_TIMEOUT)
779 return -ETIMEDOUT;
780 return 0;
781}
782
783/**
784 * set_mii_flow_control - flow control setup
785 * @vptr: velocity interface
786 *
787 * Set up the flow control on this interface according to
788 * the supplied user/eeprom options.
789 */
790static void set_mii_flow_control(struct velocity_info *vptr)
791{
792 /*Enable or Disable PAUSE in ANAR */
793 switch (vptr->options.flow_cntl) {
794 case FLOW_CNTL_TX:
Francois Romieu3a7f8682010-04-06 14:24:53 -0700795 MII_REG_BITS_OFF(ADVERTISE_PAUSE_CAP, MII_ADVERTISE, vptr->mac_regs);
796 MII_REG_BITS_ON(ADVERTISE_PAUSE_ASYM, MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700797 break;
798
799 case FLOW_CNTL_RX:
Francois Romieu3a7f8682010-04-06 14:24:53 -0700800 MII_REG_BITS_ON(ADVERTISE_PAUSE_CAP, MII_ADVERTISE, vptr->mac_regs);
801 MII_REG_BITS_ON(ADVERTISE_PAUSE_ASYM, MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700802 break;
803
804 case FLOW_CNTL_TX_RX:
Francois Romieu3a7f8682010-04-06 14:24:53 -0700805 MII_REG_BITS_ON(ADVERTISE_PAUSE_CAP, MII_ADVERTISE, vptr->mac_regs);
David S. Miller4a35ecf2010-04-06 23:53:30 -0700806 MII_REG_BITS_OFF(ADVERTISE_PAUSE_ASYM, MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700807 break;
808
809 case FLOW_CNTL_DISABLE:
Francois Romieu3a7f8682010-04-06 14:24:53 -0700810 MII_REG_BITS_OFF(ADVERTISE_PAUSE_CAP, MII_ADVERTISE, vptr->mac_regs);
811 MII_REG_BITS_OFF(ADVERTISE_PAUSE_ASYM, MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700812 break;
813 default:
814 break;
815 }
816}
817
818/**
819 * mii_set_auto_on - autonegotiate on
820 * @vptr: velocity
821 *
822 * Enable autonegotation on this interface
823 */
824static void mii_set_auto_on(struct velocity_info *vptr)
825{
Francois Romieu3a7f8682010-04-06 14:24:53 -0700826 if (MII_REG_BITS_IS_ON(BMCR_ANENABLE, MII_BMCR, vptr->mac_regs))
827 MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700828 else
Francois Romieu3a7f8682010-04-06 14:24:53 -0700829 MII_REG_BITS_ON(BMCR_ANENABLE, MII_BMCR, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700830}
831
832static u32 check_connection_type(struct mac_regs __iomem *regs)
833{
834 u32 status = 0;
835 u8 PHYSR0;
836 u16 ANAR;
837 PHYSR0 = readb(&regs->PHYSR0);
838
839 /*
840 if (!(PHYSR0 & PHYSR0_LINKGD))
841 status|=VELOCITY_LINK_FAIL;
842 */
843
844 if (PHYSR0 & PHYSR0_FDPX)
845 status |= VELOCITY_DUPLEX_FULL;
846
847 if (PHYSR0 & PHYSR0_SPDG)
848 status |= VELOCITY_SPEED_1000;
849 else if (PHYSR0 & PHYSR0_SPD10)
850 status |= VELOCITY_SPEED_10;
851 else
852 status |= VELOCITY_SPEED_100;
853
Francois Romieu3a7f8682010-04-06 14:24:53 -0700854 if (MII_REG_BITS_IS_ON(BMCR_ANENABLE, MII_BMCR, regs)) {
855 velocity_mii_read(regs, MII_ADVERTISE, &ANAR);
856 if ((ANAR & (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF))
857 == (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF)) {
858 if (MII_REG_BITS_IS_ON(ADVERTISE_1000HALF | ADVERTISE_1000FULL, MII_CTRL1000, regs))
Dave Jones2cf71d22009-07-23 18:11:12 -0700859 status |= VELOCITY_AUTONEG_ENABLE;
860 }
861 }
862
863 return status;
864}
865
Dave Jones2cf71d22009-07-23 18:11:12 -0700866/**
867 * velocity_set_media_mode - set media mode
868 * @mii_status: old MII link state
869 *
870 * Check the media link state and configure the flow control
871 * PHY and also velocity hardware setup accordingly. In particular
872 * we need to set up CD polling and frame bursting.
873 */
874static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
875{
876 u32 curr_status;
877 struct mac_regs __iomem *regs = vptr->mac_regs;
878
879 vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
880 curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
881
882 /* Set mii link status */
883 set_mii_flow_control(vptr);
884
885 /*
Uwe Kleine-Königa34f0b32010-12-10 14:55:42 +0100886 Check if new status is consistent with current status
Joe Perches8e95a202009-12-03 07:58:21 +0000887 if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) ||
888 (mii_status==curr_status)) {
Dave Jones2cf71d22009-07-23 18:11:12 -0700889 vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
890 vptr->mii_status=check_connection_type(vptr->mac_regs);
891 VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n");
892 return 0;
893 }
894 */
895
896 if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
Francois Romieu3a7f8682010-04-06 14:24:53 -0700897 MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700898
899 /*
900 * If connection type is AUTO
901 */
902 if (mii_status & VELOCITY_AUTONEG_ENABLE) {
903 VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity is AUTO mode\n");
904 /* clear force MAC mode bit */
905 BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
906 /* set duplex mode of MAC according to duplex mode of MII */
Francois Romieu3a7f8682010-04-06 14:24:53 -0700907 MII_REG_BITS_ON(ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF, MII_ADVERTISE, vptr->mac_regs);
908 MII_REG_BITS_ON(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
909 MII_REG_BITS_ON(BMCR_SPEED1000, MII_BMCR, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -0700910
911 /* enable AUTO-NEGO mode */
912 mii_set_auto_on(vptr);
913 } else {
françois romieu15419222010-10-13 09:26:05 +0000914 u16 CTRL1000;
Dave Jones2cf71d22009-07-23 18:11:12 -0700915 u16 ANAR;
916 u8 CHIPGCR;
917
918 /*
919 * 1. if it's 3119, disable frame bursting in halfduplex mode
920 * and enable it in fullduplex mode
921 * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
922 * 3. only enable CD heart beat counter in 10HD mode
923 */
924
925 /* set force MAC mode bit */
926 BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
927
928 CHIPGCR = readb(&regs->CHIPGCR);
françois romieu15419222010-10-13 09:26:05 +0000929
930 if (mii_status & VELOCITY_SPEED_1000)
931 CHIPGCR |= CHIPGCR_FCGMII;
932 else
933 CHIPGCR &= ~CHIPGCR_FCGMII;
Dave Jones2cf71d22009-07-23 18:11:12 -0700934
935 if (mii_status & VELOCITY_DUPLEX_FULL) {
936 CHIPGCR |= CHIPGCR_FCFDX;
937 writeb(CHIPGCR, &regs->CHIPGCR);
938 VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced full mode\n");
939 if (vptr->rev_id < REV_ID_VT3216_A0)
940 BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
941 } else {
942 CHIPGCR &= ~CHIPGCR_FCFDX;
943 VELOCITY_PRT(MSG_LEVEL_INFO, "set Velocity to forced half mode\n");
944 writeb(CHIPGCR, &regs->CHIPGCR);
945 if (vptr->rev_id < REV_ID_VT3216_A0)
946 BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
947 }
948
françois romieu15419222010-10-13 09:26:05 +0000949 velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000);
950 CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
951 if ((mii_status & VELOCITY_SPEED_1000) &&
952 (mii_status & VELOCITY_DUPLEX_FULL)) {
953 CTRL1000 |= ADVERTISE_1000FULL;
954 }
955 velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000);
Dave Jones2cf71d22009-07-23 18:11:12 -0700956
957 if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10))
958 BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
959 else
960 BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
961
Francois Romieu3a7f8682010-04-06 14:24:53 -0700962 /* MII_REG_BITS_OFF(BMCR_SPEED1000, MII_BMCR, vptr->mac_regs); */
963 velocity_mii_read(vptr->mac_regs, MII_ADVERTISE, &ANAR);
964 ANAR &= (~(ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF));
Dave Jones2cf71d22009-07-23 18:11:12 -0700965 if (mii_status & VELOCITY_SPEED_100) {
966 if (mii_status & VELOCITY_DUPLEX_FULL)
Francois Romieu3a7f8682010-04-06 14:24:53 -0700967 ANAR |= ADVERTISE_100FULL;
Dave Jones2cf71d22009-07-23 18:11:12 -0700968 else
Francois Romieu3a7f8682010-04-06 14:24:53 -0700969 ANAR |= ADVERTISE_100HALF;
françois romieu15419222010-10-13 09:26:05 +0000970 } else if (mii_status & VELOCITY_SPEED_10) {
Dave Jones2cf71d22009-07-23 18:11:12 -0700971 if (mii_status & VELOCITY_DUPLEX_FULL)
Francois Romieu3a7f8682010-04-06 14:24:53 -0700972 ANAR |= ADVERTISE_10FULL;
Dave Jones2cf71d22009-07-23 18:11:12 -0700973 else
Francois Romieu3a7f8682010-04-06 14:24:53 -0700974 ANAR |= ADVERTISE_10HALF;
Dave Jones2cf71d22009-07-23 18:11:12 -0700975 }
Francois Romieu3a7f8682010-04-06 14:24:53 -0700976 velocity_mii_write(vptr->mac_regs, MII_ADVERTISE, ANAR);
Dave Jones2cf71d22009-07-23 18:11:12 -0700977 /* enable AUTO-NEGO mode */
978 mii_set_auto_on(vptr);
Francois Romieu3a7f8682010-04-06 14:24:53 -0700979 /* MII_REG_BITS_ON(BMCR_ANENABLE, MII_BMCR, vptr->mac_regs); */
Dave Jones2cf71d22009-07-23 18:11:12 -0700980 }
981 /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
982 /* vptr->mii_status=check_connection_type(vptr->mac_regs); */
983 return VELOCITY_LINK_CHANGE;
984}
985
986/**
987 * velocity_print_link_status - link status reporting
988 * @vptr: velocity to report on
989 *
990 * Turn the link status of the velocity card into a kernel log
991 * description of the new link state, detailing speed and duplex
992 * status
993 */
994static void velocity_print_link_status(struct velocity_info *vptr)
995{
996
997 if (vptr->mii_status & VELOCITY_LINK_FAIL) {
998 VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
999 } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
1000 VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
1001
1002 if (vptr->mii_status & VELOCITY_SPEED_1000)
1003 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
1004 else if (vptr->mii_status & VELOCITY_SPEED_100)
1005 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps");
1006 else
1007 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps");
1008
1009 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
1010 VELOCITY_PRT(MSG_LEVEL_INFO, " full duplex\n");
1011 else
1012 VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n");
1013 } else {
1014 VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
1015 switch (vptr->options.spd_dpx) {
françois romieu15419222010-10-13 09:26:05 +00001016 case SPD_DPX_1000_FULL:
1017 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
1018 break;
Dave Jones2cf71d22009-07-23 18:11:12 -07001019 case SPD_DPX_100_HALF:
1020 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
1021 break;
1022 case SPD_DPX_100_FULL:
1023 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps full duplex\n");
1024 break;
1025 case SPD_DPX_10_HALF:
1026 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps half duplex\n");
1027 break;
1028 case SPD_DPX_10_FULL:
1029 VELOCITY_PRT(MSG_LEVEL_INFO, " speed 10M bps full duplex\n");
1030 break;
1031 default:
1032 break;
1033 }
1034 }
1035}
1036
1037/**
1038 * enable_flow_control_ability - flow control
1039 * @vptr: veloity to configure
1040 *
1041 * Set up flow control according to the flow control options
1042 * determined by the eeprom/configuration.
1043 */
1044static void enable_flow_control_ability(struct velocity_info *vptr)
1045{
1046
1047 struct mac_regs __iomem *regs = vptr->mac_regs;
1048
1049 switch (vptr->options.flow_cntl) {
1050
1051 case FLOW_CNTL_DEFAULT:
1052 if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
1053 writel(CR0_FDXRFCEN, &regs->CR0Set);
1054 else
1055 writel(CR0_FDXRFCEN, &regs->CR0Clr);
1056
1057 if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
1058 writel(CR0_FDXTFCEN, &regs->CR0Set);
1059 else
1060 writel(CR0_FDXTFCEN, &regs->CR0Clr);
1061 break;
1062
1063 case FLOW_CNTL_TX:
1064 writel(CR0_FDXTFCEN, &regs->CR0Set);
1065 writel(CR0_FDXRFCEN, &regs->CR0Clr);
1066 break;
1067
1068 case FLOW_CNTL_RX:
1069 writel(CR0_FDXRFCEN, &regs->CR0Set);
1070 writel(CR0_FDXTFCEN, &regs->CR0Clr);
1071 break;
1072
1073 case FLOW_CNTL_TX_RX:
1074 writel(CR0_FDXTFCEN, &regs->CR0Set);
1075 writel(CR0_FDXRFCEN, &regs->CR0Set);
1076 break;
1077
1078 case FLOW_CNTL_DISABLE:
1079 writel(CR0_FDXRFCEN, &regs->CR0Clr);
1080 writel(CR0_FDXTFCEN, &regs->CR0Clr);
1081 break;
1082
1083 default:
1084 break;
1085 }
1086
1087}
1088
1089/**
1090 * velocity_soft_reset - soft reset
1091 * @vptr: velocity to reset
1092 *
1093 * Kick off a soft reset of the velocity adapter and then poll
1094 * until the reset sequence has completed before returning.
1095 */
1096static int velocity_soft_reset(struct velocity_info *vptr)
1097{
1098 struct mac_regs __iomem *regs = vptr->mac_regs;
1099 int i = 0;
1100
1101 writel(CR0_SFRST, &regs->CR0Set);
1102
1103 for (i = 0; i < W_MAX_TIMEOUT; i++) {
1104 udelay(5);
1105 if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
1106 break;
1107 }
1108
1109 if (i == W_MAX_TIMEOUT) {
1110 writel(CR0_FORSRST, &regs->CR0Set);
1111 /* FIXME: PCI POSTING */
1112 /* delay 2ms */
1113 mdelay(2);
1114 }
1115 return 0;
1116}
1117
1118/**
1119 * velocity_set_multi - filter list change callback
1120 * @dev: network device
1121 *
1122 * Called by the network layer when the filter lists need to change
1123 * for a velocity adapter. Reload the CAMs with the new address
1124 * filter ruleset.
1125 */
1126static void velocity_set_multi(struct net_device *dev)
1127{
1128 struct velocity_info *vptr = netdev_priv(dev);
1129 struct mac_regs __iomem *regs = vptr->mac_regs;
1130 u8 rx_mode;
1131 int i;
Jiri Pirko22bedad2010-04-01 21:22:57 +00001132 struct netdev_hw_addr *ha;
Dave Jones2cf71d22009-07-23 18:11:12 -07001133
1134 if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
1135 writel(0xffffffff, &regs->MARCAM[0]);
1136 writel(0xffffffff, &regs->MARCAM[4]);
1137 rx_mode = (RCR_AM | RCR_AB | RCR_PROM);
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001138 } else if ((netdev_mc_count(dev) > vptr->multicast_limit) ||
Joe Perches8e95a202009-12-03 07:58:21 +00001139 (dev->flags & IFF_ALLMULTI)) {
Dave Jones2cf71d22009-07-23 18:11:12 -07001140 writel(0xffffffff, &regs->MARCAM[0]);
1141 writel(0xffffffff, &regs->MARCAM[4]);
1142 rx_mode = (RCR_AM | RCR_AB);
1143 } else {
1144 int offset = MCAM_SIZE - vptr->multicast_limit;
1145 mac_get_cam_mask(regs, vptr->mCAMmask);
1146
Jiri Pirko567ec872010-02-23 23:17:07 +00001147 i = 0;
Jiri Pirko22bedad2010-04-01 21:22:57 +00001148 netdev_for_each_mc_addr(ha, dev) {
1149 mac_set_cam(regs, i + offset, ha->addr);
Dave Jones2cf71d22009-07-23 18:11:12 -07001150 vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7);
Jiri Pirko567ec872010-02-23 23:17:07 +00001151 i++;
Dave Jones2cf71d22009-07-23 18:11:12 -07001152 }
1153
1154 mac_set_cam_mask(regs, vptr->mCAMmask);
1155 rx_mode = RCR_AM | RCR_AB | RCR_AP;
1156 }
1157 if (dev->mtu > 1500)
1158 rx_mode |= RCR_AL;
1159
1160 BYTE_REG_BITS_ON(rx_mode, &regs->RCR);
1161
1162}
1163
1164/*
1165 * MII access , media link mode setting functions
1166 */
1167
1168/**
1169 * mii_init - set up MII
1170 * @vptr: velocity adapter
1171 * @mii_status: links tatus
1172 *
1173 * Set up the PHY for the current link state.
1174 */
1175static void mii_init(struct velocity_info *vptr, u32 mii_status)
1176{
1177 u16 BMCR;
1178
1179 switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
1180 case PHYID_CICADA_CS8201:
1181 /*
1182 * Reset to hardware default
1183 */
Francois Romieu3a7f8682010-04-06 14:24:53 -07001184 MII_REG_BITS_OFF((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP), MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001185 /*
1186 * Turn on ECHODIS bit in NWay-forced full mode and turn it
1187 * off it in NWay-forced half mode for NWay-forced v.s.
1188 * legacy-forced issue.
1189 */
1190 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
Francois Romieu3a7f8682010-04-06 14:24:53 -07001191 MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001192 else
Francois Romieu3a7f8682010-04-06 14:24:53 -07001193 MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001194 /*
1195 * Turn on Link/Activity LED enable bit for CIS8201
1196 */
Francois Romieu3a7f8682010-04-06 14:24:53 -07001197 MII_REG_BITS_ON(PLED_LALBE, MII_TPISTATUS, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001198 break;
1199 case PHYID_VT3216_32BIT:
1200 case PHYID_VT3216_64BIT:
1201 /*
1202 * Reset to hardware default
1203 */
Francois Romieu3a7f8682010-04-06 14:24:53 -07001204 MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP), MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001205 /*
1206 * Turn on ECHODIS bit in NWay-forced full mode and turn it
1207 * off it in NWay-forced half mode for NWay-forced v.s.
1208 * legacy-forced issue
1209 */
1210 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
Francois Romieu3a7f8682010-04-06 14:24:53 -07001211 MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001212 else
Francois Romieu3a7f8682010-04-06 14:24:53 -07001213 MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001214 break;
1215
1216 case PHYID_MARVELL_1000:
1217 case PHYID_MARVELL_1000S:
1218 /*
1219 * Assert CRS on Transmit
1220 */
1221 MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
1222 /*
1223 * Reset to hardware default
1224 */
Francois Romieu3a7f8682010-04-06 14:24:53 -07001225 MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP), MII_ADVERTISE, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07001226 break;
1227 default:
1228 ;
1229 }
Francois Romieu3a7f8682010-04-06 14:24:53 -07001230 velocity_mii_read(vptr->mac_regs, MII_BMCR, &BMCR);
1231 if (BMCR & BMCR_ISOLATE) {
1232 BMCR &= ~BMCR_ISOLATE;
1233 velocity_mii_write(vptr->mac_regs, MII_BMCR, BMCR);
Dave Jones2cf71d22009-07-23 18:11:12 -07001234 }
1235}
1236
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00001237/**
1238 * setup_queue_timers - Setup interrupt timers
1239 *
1240 * Setup interrupt frequency during suppression (timeout if the frame
1241 * count isn't filled).
1242 */
1243static void setup_queue_timers(struct velocity_info *vptr)
1244{
1245 /* Only for newer revisions */
1246 if (vptr->rev_id >= REV_ID_VT3216_A0) {
1247 u8 txqueue_timer = 0;
1248 u8 rxqueue_timer = 0;
1249
1250 if (vptr->mii_status & (VELOCITY_SPEED_1000 |
1251 VELOCITY_SPEED_100)) {
1252 txqueue_timer = vptr->options.txqueue_timer;
1253 rxqueue_timer = vptr->options.rxqueue_timer;
1254 }
1255
1256 writeb(txqueue_timer, &vptr->mac_regs->TQETMR);
1257 writeb(rxqueue_timer, &vptr->mac_regs->RQETMR);
1258 }
1259}
françois romieu5ae297b2011-08-04 02:39:03 +00001260
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00001261/**
1262 * setup_adaptive_interrupts - Setup interrupt suppression
1263 *
1264 * @vptr velocity adapter
1265 *
1266 * The velocity is able to suppress interrupt during high interrupt load.
1267 * This function turns on that feature.
1268 */
1269static void setup_adaptive_interrupts(struct velocity_info *vptr)
1270{
1271 struct mac_regs __iomem *regs = vptr->mac_regs;
1272 u16 tx_intsup = vptr->options.tx_intsup;
1273 u16 rx_intsup = vptr->options.rx_intsup;
1274
1275 /* Setup default interrupt mask (will be changed below) */
1276 vptr->int_mask = INT_MASK_DEF;
1277
1278 /* Set Tx Interrupt Suppression Threshold */
1279 writeb(CAMCR_PS0, &regs->CAMCR);
1280 if (tx_intsup != 0) {
1281 vptr->int_mask &= ~(ISR_PTXI | ISR_PTX0I | ISR_PTX1I |
1282 ISR_PTX2I | ISR_PTX3I);
1283 writew(tx_intsup, &regs->ISRCTL);
1284 } else
1285 writew(ISRCTL_TSUPDIS, &regs->ISRCTL);
1286
1287 /* Set Rx Interrupt Suppression Threshold */
1288 writeb(CAMCR_PS1, &regs->CAMCR);
1289 if (rx_intsup != 0) {
1290 vptr->int_mask &= ~ISR_PRXI;
1291 writew(rx_intsup, &regs->ISRCTL);
1292 } else
1293 writew(ISRCTL_RSUPDIS, &regs->ISRCTL);
1294
1295 /* Select page to interrupt hold timer */
1296 writeb(0, &regs->CAMCR);
1297}
Dave Jones2cf71d22009-07-23 18:11:12 -07001298
1299/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 * velocity_init_registers - initialise MAC registers
1301 * @vptr: velocity to init
1302 * @type: type of initialisation (hot or cold)
1303 *
1304 * Initialise the MAC on a reset or on first set up on the
1305 * hardware.
1306 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001307static void velocity_init_registers(struct velocity_info *vptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 enum velocity_init_type type)
1309{
Dave Jonesc4067402009-07-20 17:35:21 +00001310 struct mac_regs __iomem *regs = vptr->mac_regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 int i, mii_status;
1312
1313 mac_wol_reset(regs);
1314
1315 switch (type) {
1316 case VELOCITY_INIT_RESET:
1317 case VELOCITY_INIT_WOL:
1318
1319 netif_stop_queue(vptr->dev);
1320
1321 /*
1322 * Reset RX to prevent RX pointer not on the 4X location
1323 */
1324 velocity_rx_reset(vptr);
1325 mac_rx_queue_run(regs);
1326 mac_rx_queue_wake(regs);
1327
1328 mii_status = velocity_get_opt_media_mode(vptr);
1329 if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
1330 velocity_print_link_status(vptr);
1331 if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
1332 netif_wake_queue(vptr->dev);
1333 }
1334
1335 enable_flow_control_ability(vptr);
1336
1337 mac_clear_isr(regs);
1338 writel(CR0_STOP, &regs->CR0Clr);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001339 writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 &regs->CR0Set);
1341
1342 break;
1343
1344 case VELOCITY_INIT_COLD:
1345 default:
1346 /*
1347 * Do reset
1348 */
1349 velocity_soft_reset(vptr);
1350 mdelay(5);
1351
1352 mac_eeprom_reload(regs);
Dave Jonesc4067402009-07-20 17:35:21 +00001353 for (i = 0; i < 6; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));
Dave Jonesc4067402009-07-20 17:35:21 +00001355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 /*
1357 * clear Pre_ACPI bit.
1358 */
1359 BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA));
1360 mac_set_rx_thresh(regs, vptr->options.rx_thresh);
1361 mac_set_dma_length(regs, vptr->options.DMA_length);
1362
1363 writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
1364 /*
1365 * Back off algorithm use original IEEE standard
1366 */
1367 BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);
1368
1369 /*
1370 * Init CAM filter
1371 */
1372 velocity_init_cam_filter(vptr);
1373
1374 /*
1375 * Set packet filter: Receive directed and broadcast address
1376 */
1377 velocity_set_multi(vptr->dev);
1378
1379 /*
1380 * Enable MII auto-polling
1381 */
1382 enable_mii_autopoll(regs);
1383
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00001384 setup_adaptive_interrupts(vptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Francois Romieu0fe9f152008-07-31 22:10:10 +02001386 writel(vptr->rx.pool_dma, &regs->RDBaseLo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 writew(vptr->options.numrx - 1, &regs->RDCSize);
1388 mac_rx_queue_run(regs);
1389 mac_rx_queue_wake(regs);
1390
1391 writew(vptr->options.numtx - 1, &regs->TDCSize);
1392
Francois Romieu0fe9f152008-07-31 22:10:10 +02001393 for (i = 0; i < vptr->tx.numq; i++) {
1394 writel(vptr->tx.pool_dma[i], &regs->TDBaseLo[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 mac_tx_queue_run(regs, i);
1396 }
1397
1398 init_flow_control_register(vptr);
1399
1400 writel(CR0_STOP, &regs->CR0Clr);
1401 writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);
1402
1403 mii_status = velocity_get_opt_media_mode(vptr);
1404 netif_stop_queue(vptr->dev);
1405
1406 mii_init(vptr, mii_status);
1407
1408 if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
1409 velocity_print_link_status(vptr);
1410 if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
1411 netif_wake_queue(vptr->dev);
1412 }
1413
1414 enable_flow_control_ability(vptr);
1415 mac_hw_mibs_init(regs);
1416 mac_write_int_mask(vptr->int_mask, regs);
1417 mac_clear_isr(regs);
1418
1419 }
1420}
1421
Dave Jones2cf71d22009-07-23 18:11:12 -07001422static void velocity_give_many_rx_descs(struct velocity_info *vptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423{
Dave Jonesc4067402009-07-20 17:35:21 +00001424 struct mac_regs __iomem *regs = vptr->mac_regs;
Dave Jones2cf71d22009-07-23 18:11:12 -07001425 int avail, dirty, unusable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Dave Jones2cf71d22009-07-23 18:11:12 -07001427 /*
1428 * RD number must be equal to 4X per hardware spec
1429 * (programming guide rev 1.20, p.13)
1430 */
1431 if (vptr->rx.filled < 4)
1432 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Dave Jones2cf71d22009-07-23 18:11:12 -07001434 wmb();
1435
1436 unusable = vptr->rx.filled & 0x0003;
1437 dirty = vptr->rx.dirty - unusable;
1438 for (avail = vptr->rx.filled & 0xfffc; avail; avail--) {
1439 dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
1440 vptr->rx.ring[dirty].rdesc0.len |= OWNED_BY_NIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 }
1442
Dave Jones2cf71d22009-07-23 18:11:12 -07001443 writew(vptr->rx.filled & 0xfffc, &regs->RBRDU);
1444 vptr->rx.filled = unusable;
1445}
1446
1447/**
1448 * velocity_init_dma_rings - set up DMA rings
1449 * @vptr: Velocity to set up
1450 *
1451 * Allocate PCI mapped DMA rings for the receive and transmit layer
1452 * to use.
1453 */
1454static int velocity_init_dma_rings(struct velocity_info *vptr)
1455{
1456 struct velocity_opt *opt = &vptr->options;
1457 const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc);
1458 const unsigned int tx_ring_size = opt->numtx * sizeof(struct tx_desc);
1459 struct pci_dev *pdev = vptr->pdev;
1460 dma_addr_t pool_dma;
1461 void *pool;
1462 unsigned int i;
1463
1464 /*
1465 * Allocate all RD/TD rings a single pool.
1466 *
1467 * pci_alloc_consistent() fulfills the requirement for 64 bytes
1468 * alignment
1469 */
1470 pool = pci_alloc_consistent(pdev, tx_ring_size * vptr->tx.numq +
1471 rx_ring_size, &pool_dma);
1472 if (!pool) {
1473 dev_err(&pdev->dev, "%s : DMA memory allocation failed.\n",
1474 vptr->dev->name);
1475 return -ENOMEM;
1476 }
1477
1478 vptr->rx.ring = pool;
1479 vptr->rx.pool_dma = pool_dma;
1480
1481 pool += rx_ring_size;
1482 pool_dma += rx_ring_size;
1483
1484 for (i = 0; i < vptr->tx.numq; i++) {
1485 vptr->tx.rings[i] = pool;
1486 vptr->tx.pool_dma[i] = pool_dma;
1487 pool += tx_ring_size;
1488 pool_dma += tx_ring_size;
1489 }
1490
1491 return 0;
1492}
1493
1494static void velocity_set_rxbufsize(struct velocity_info *vptr, int mtu)
1495{
1496 vptr->rx.buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32;
1497}
1498
1499/**
1500 * velocity_alloc_rx_buf - allocate aligned receive buffer
1501 * @vptr: velocity
1502 * @idx: ring index
1503 *
1504 * Allocate a new full sized buffer for the reception of a frame and
1505 * map it into PCI space for the hardware to use. The hardware
1506 * requires *64* byte alignment of the buffer which makes life
1507 * less fun than would be ideal.
1508 */
1509static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
1510{
1511 struct rx_desc *rd = &(vptr->rx.ring[idx]);
1512 struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
1513
1514 rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64);
1515 if (rd_info->skb == NULL)
1516 return -ENOMEM;
1517
1518 /*
1519 * Do the gymnastics to get the buffer head for data at
1520 * 64byte alignment.
1521 */
Simon Kagstromda95b2d2009-11-25 22:09:53 +00001522 skb_reserve(rd_info->skb,
1523 64 - ((unsigned long) rd_info->skb->data & 63));
Dave Jones2cf71d22009-07-23 18:11:12 -07001524 rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data,
1525 vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
1526
1527 /*
1528 * Fill in the descriptor to match
1529 */
1530
1531 *((u32 *) & (rd->rdesc0)) = 0;
1532 rd->size = cpu_to_le16(vptr->rx.buf_sz) | RX_INTEN;
1533 rd->pa_low = cpu_to_le32(rd_info->skb_dma);
1534 rd->pa_high = 0;
1535 return 0;
1536}
1537
1538
1539static int velocity_rx_refill(struct velocity_info *vptr)
1540{
1541 int dirty = vptr->rx.dirty, done = 0;
1542
1543 do {
1544 struct rx_desc *rd = vptr->rx.ring + dirty;
1545
1546 /* Fine for an all zero Rx desc at init time as well */
1547 if (rd->rdesc0.len & OWNED_BY_NIC)
1548 break;
1549
1550 if (!vptr->rx.info[dirty].skb) {
1551 if (velocity_alloc_rx_buf(vptr, dirty) < 0)
1552 break;
1553 }
1554 done++;
1555 dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;
1556 } while (dirty != vptr->rx.curr);
1557
1558 if (done) {
1559 vptr->rx.dirty = dirty;
1560 vptr->rx.filled += done;
1561 }
1562
1563 return done;
1564}
1565
1566/**
1567 * velocity_free_rd_ring - free receive ring
1568 * @vptr: velocity to clean up
1569 *
1570 * Free the receive buffers for each ring slot and any
1571 * attached socket buffers that need to go away.
1572 */
1573static void velocity_free_rd_ring(struct velocity_info *vptr)
1574{
1575 int i;
1576
1577 if (vptr->rx.info == NULL)
1578 return;
1579
1580 for (i = 0; i < vptr->options.numrx; i++) {
1581 struct velocity_rd_info *rd_info = &(vptr->rx.info[i]);
1582 struct rx_desc *rd = vptr->rx.ring + i;
1583
1584 memset(rd, 0, sizeof(*rd));
1585
1586 if (!rd_info->skb)
1587 continue;
1588 pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
1589 PCI_DMA_FROMDEVICE);
1590 rd_info->skb_dma = 0;
1591
1592 dev_kfree_skb(rd_info->skb);
1593 rd_info->skb = NULL;
1594 }
1595
1596 kfree(vptr->rx.info);
1597 vptr->rx.info = NULL;
1598}
1599
Dave Jones2cf71d22009-07-23 18:11:12 -07001600/**
1601 * velocity_init_rd_ring - set up receive ring
1602 * @vptr: velocity to configure
1603 *
1604 * Allocate and set up the receive buffers for each ring slot and
1605 * assign them to the network adapter.
1606 */
1607static int velocity_init_rd_ring(struct velocity_info *vptr)
1608{
1609 int ret = -ENOMEM;
1610
1611 vptr->rx.info = kcalloc(vptr->options.numrx,
1612 sizeof(struct velocity_rd_info), GFP_KERNEL);
1613 if (!vptr->rx.info)
1614 goto out;
1615
1616 velocity_init_rx_ring_indexes(vptr);
1617
1618 if (velocity_rx_refill(vptr) != vptr->options.numrx) {
1619 VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
1620 "%s: failed to allocate RX buffer.\n", vptr->dev->name);
1621 velocity_free_rd_ring(vptr);
1622 goto out;
1623 }
1624
1625 ret = 0;
1626out:
1627 return ret;
1628}
1629
1630/**
1631 * velocity_init_td_ring - set up transmit ring
1632 * @vptr: velocity
1633 *
1634 * Set up the transmit ring and chain the ring pointers together.
1635 * Returns zero on success or a negative posix errno code for
1636 * failure.
1637 */
1638static int velocity_init_td_ring(struct velocity_info *vptr)
1639{
Dave Jones2cf71d22009-07-23 18:11:12 -07001640 int j;
1641
1642 /* Init the TD ring entries */
1643 for (j = 0; j < vptr->tx.numq; j++) {
Dave Jones2cf71d22009-07-23 18:11:12 -07001644
1645 vptr->tx.infos[j] = kcalloc(vptr->options.numtx,
1646 sizeof(struct velocity_td_info),
1647 GFP_KERNEL);
1648 if (!vptr->tx.infos[j]) {
1649 while (--j >= 0)
1650 kfree(vptr->tx.infos[j]);
1651 return -ENOMEM;
1652 }
1653
1654 vptr->tx.tail[j] = vptr->tx.curr[j] = vptr->tx.used[j] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 }
1656 return 0;
1657}
1658
Dave Jones2cf71d22009-07-23 18:11:12 -07001659/**
1660 * velocity_free_dma_rings - free PCI ring pointers
1661 * @vptr: Velocity to free from
1662 *
1663 * Clean up the PCI ring buffers allocated to this velocity.
1664 */
1665static void velocity_free_dma_rings(struct velocity_info *vptr)
1666{
1667 const int size = vptr->options.numrx * sizeof(struct rx_desc) +
1668 vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq;
1669
1670 pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma);
1671}
1672
Dave Jones2cf71d22009-07-23 18:11:12 -07001673static int velocity_init_rings(struct velocity_info *vptr, int mtu)
1674{
1675 int ret;
1676
1677 velocity_set_rxbufsize(vptr, mtu);
1678
1679 ret = velocity_init_dma_rings(vptr);
1680 if (ret < 0)
1681 goto out;
1682
1683 ret = velocity_init_rd_ring(vptr);
1684 if (ret < 0)
1685 goto err_free_dma_rings_0;
1686
1687 ret = velocity_init_td_ring(vptr);
1688 if (ret < 0)
1689 goto err_free_rd_ring_1;
1690out:
1691 return ret;
1692
1693err_free_rd_ring_1:
1694 velocity_free_rd_ring(vptr);
1695err_free_dma_rings_0:
1696 velocity_free_dma_rings(vptr);
1697 goto out;
1698}
1699
1700/**
1701 * velocity_free_tx_buf - free transmit buffer
1702 * @vptr: velocity
1703 * @tdinfo: buffer
1704 *
1705 * Release an transmit buffer. If the buffer was preallocated then
1706 * recycle it, if not then unmap the buffer.
1707 */
Simon Kagstromc79992f2009-11-25 22:10:43 +00001708static void velocity_free_tx_buf(struct velocity_info *vptr,
1709 struct velocity_td_info *tdinfo, struct tx_desc *td)
Dave Jones2cf71d22009-07-23 18:11:12 -07001710{
1711 struct sk_buff *skb = tdinfo->skb;
Dave Jones2cf71d22009-07-23 18:11:12 -07001712
1713 /*
1714 * Don't unmap the pre-allocated tx_bufs
1715 */
1716 if (tdinfo->skb_dma) {
Simon Kagstromc79992f2009-11-25 22:10:43 +00001717 int i;
Dave Jones2cf71d22009-07-23 18:11:12 -07001718
Dave Jones2cf71d22009-07-23 18:11:12 -07001719 for (i = 0; i < tdinfo->nskb_dma; i++) {
Simon Kagstromc79992f2009-11-25 22:10:43 +00001720 size_t pktlen = max_t(size_t, skb->len, ETH_ZLEN);
1721
1722 /* For scatter-gather */
1723 if (skb_shinfo(skb)->nr_frags > 0)
1724 pktlen = max_t(size_t, pktlen,
1725 td->td_buf[i].size & ~TD_QUEUE);
1726
1727 pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i],
1728 le16_to_cpu(pktlen), PCI_DMA_TODEVICE);
Dave Jones2cf71d22009-07-23 18:11:12 -07001729 }
1730 }
1731 dev_kfree_skb_irq(skb);
1732 tdinfo->skb = NULL;
1733}
1734
Dave Jones2cf71d22009-07-23 18:11:12 -07001735/*
1736 * FIXME: could we merge this with velocity_free_tx_buf ?
1737 */
1738static void velocity_free_td_ring_entry(struct velocity_info *vptr,
1739 int q, int n)
1740{
1741 struct velocity_td_info *td_info = &(vptr->tx.infos[q][n]);
1742 int i;
1743
1744 if (td_info == NULL)
1745 return;
1746
1747 if (td_info->skb) {
1748 for (i = 0; i < td_info->nskb_dma; i++) {
1749 if (td_info->skb_dma[i]) {
1750 pci_unmap_single(vptr->pdev, td_info->skb_dma[i],
1751 td_info->skb->len, PCI_DMA_TODEVICE);
1752 td_info->skb_dma[i] = 0;
1753 }
1754 }
1755 dev_kfree_skb(td_info->skb);
1756 td_info->skb = NULL;
1757 }
1758}
1759
1760/**
1761 * velocity_free_td_ring - free td ring
1762 * @vptr: velocity
1763 *
1764 * Free up the transmit ring for this particular velocity adapter.
1765 * We free the ring contents but not the ring itself.
1766 */
1767static void velocity_free_td_ring(struct velocity_info *vptr)
1768{
1769 int i, j;
1770
1771 for (j = 0; j < vptr->tx.numq; j++) {
1772 if (vptr->tx.infos[j] == NULL)
1773 continue;
1774 for (i = 0; i < vptr->options.numtx; i++)
1775 velocity_free_td_ring_entry(vptr, j, i);
1776
1777 kfree(vptr->tx.infos[j]);
1778 vptr->tx.infos[j] = NULL;
1779 }
1780}
1781
Dave Jones2cf71d22009-07-23 18:11:12 -07001782static void velocity_free_rings(struct velocity_info *vptr)
1783{
1784 velocity_free_td_ring(vptr);
1785 velocity_free_rd_ring(vptr);
1786 velocity_free_dma_rings(vptr);
1787}
1788
1789/**
1790 * velocity_error - handle error from controller
1791 * @vptr: velocity
1792 * @status: card status
1793 *
1794 * Process an error report from the hardware and attempt to recover
1795 * the card itself. At the moment we cannot recover from some
1796 * theoretically impossible errors but this could be fixed using
1797 * the pci_device_failed logic to bounce the hardware
1798 *
1799 */
1800static void velocity_error(struct velocity_info *vptr, int status)
1801{
1802
1803 if (status & ISR_TXSTLI) {
1804 struct mac_regs __iomem *regs = vptr->mac_regs;
1805
1806 printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(&regs->TDIdx[0]));
1807 BYTE_REG_BITS_ON(TXESR_TDSTR, &regs->TXESR);
1808 writew(TRDCSR_RUN, &regs->TDCSRClr);
1809 netif_stop_queue(vptr->dev);
1810
1811 /* FIXME: port over the pci_device_failed code and use it
1812 here */
1813 }
1814
1815 if (status & ISR_SRCI) {
1816 struct mac_regs __iomem *regs = vptr->mac_regs;
1817 int linked;
1818
1819 if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
1820 vptr->mii_status = check_connection_type(regs);
1821
1822 /*
1823 * If it is a 3119, disable frame bursting in
1824 * halfduplex mode and enable it in fullduplex
1825 * mode
1826 */
1827 if (vptr->rev_id < REV_ID_VT3216_A0) {
David S. Miller6cdee2f2009-09-02 00:32:56 -07001828 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
Dave Jones2cf71d22009-07-23 18:11:12 -07001829 BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
1830 else
1831 BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
1832 }
1833 /*
1834 * Only enable CD heart beat counter in 10HD mode
1835 */
1836 if (!(vptr->mii_status & VELOCITY_DUPLEX_FULL) && (vptr->mii_status & VELOCITY_SPEED_10))
1837 BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
1838 else
1839 BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00001840
1841 setup_queue_timers(vptr);
Dave Jones2cf71d22009-07-23 18:11:12 -07001842 }
1843 /*
1844 * Get link status from PHYSR0
1845 */
1846 linked = readb(&regs->PHYSR0) & PHYSR0_LINKGD;
1847
1848 if (linked) {
1849 vptr->mii_status &= ~VELOCITY_LINK_FAIL;
1850 netif_carrier_on(vptr->dev);
1851 } else {
1852 vptr->mii_status |= VELOCITY_LINK_FAIL;
1853 netif_carrier_off(vptr->dev);
1854 }
1855
1856 velocity_print_link_status(vptr);
1857 enable_flow_control_ability(vptr);
1858
1859 /*
1860 * Re-enable auto-polling because SRCI will disable
1861 * auto-polling
1862 */
1863
1864 enable_mii_autopoll(regs);
1865
1866 if (vptr->mii_status & VELOCITY_LINK_FAIL)
1867 netif_stop_queue(vptr->dev);
1868 else
1869 netif_wake_queue(vptr->dev);
1870
Joe Perches6403eab2011-06-03 11:51:20 +00001871 }
Dave Jones2cf71d22009-07-23 18:11:12 -07001872 if (status & ISR_MIBFI)
1873 velocity_update_hw_mibs(vptr);
1874 if (status & ISR_LSTEI)
1875 mac_rx_queue_wake(vptr->mac_regs);
1876}
1877
1878/**
1879 * tx_srv - transmit interrupt service
1880 * @vptr; Velocity
Dave Jones2cf71d22009-07-23 18:11:12 -07001881 *
1882 * Scan the queues looking for transmitted packets that
1883 * we can complete and clean up. Update any statistics as
1884 * necessary/
1885 */
Simon Kagstromd6cade02010-02-09 23:37:54 +00001886static int velocity_tx_srv(struct velocity_info *vptr)
Dave Jones2cf71d22009-07-23 18:11:12 -07001887{
1888 struct tx_desc *td;
1889 int qnum;
1890 int full = 0;
1891 int idx;
1892 int works = 0;
1893 struct velocity_td_info *tdinfo;
1894 struct net_device_stats *stats = &vptr->dev->stats;
1895
1896 for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
1897 for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
1898 idx = (idx + 1) % vptr->options.numtx) {
1899
1900 /*
1901 * Get Tx Descriptor
1902 */
1903 td = &(vptr->tx.rings[qnum][idx]);
1904 tdinfo = &(vptr->tx.infos[qnum][idx]);
1905
1906 if (td->tdesc0.len & OWNED_BY_NIC)
1907 break;
1908
1909 if ((works++ > 15))
1910 break;
1911
1912 if (td->tdesc0.TSR & TSR0_TERR) {
1913 stats->tx_errors++;
1914 stats->tx_dropped++;
1915 if (td->tdesc0.TSR & TSR0_CDH)
1916 stats->tx_heartbeat_errors++;
1917 if (td->tdesc0.TSR & TSR0_CRS)
1918 stats->tx_carrier_errors++;
1919 if (td->tdesc0.TSR & TSR0_ABT)
1920 stats->tx_aborted_errors++;
1921 if (td->tdesc0.TSR & TSR0_OWC)
1922 stats->tx_window_errors++;
1923 } else {
1924 stats->tx_packets++;
1925 stats->tx_bytes += tdinfo->skb->len;
1926 }
Simon Kagstromc79992f2009-11-25 22:10:43 +00001927 velocity_free_tx_buf(vptr, tdinfo, td);
Dave Jones2cf71d22009-07-23 18:11:12 -07001928 vptr->tx.used[qnum]--;
1929 }
1930 vptr->tx.tail[qnum] = idx;
1931
1932 if (AVAIL_TD(vptr, qnum) < 1)
1933 full = 1;
1934 }
1935 /*
1936 * Look to see if we should kick the transmit network
1937 * layer for more work.
1938 */
Joe Perches8e95a202009-12-03 07:58:21 +00001939 if (netif_queue_stopped(vptr->dev) && (full == 0) &&
1940 (!(vptr->mii_status & VELOCITY_LINK_FAIL))) {
Dave Jones2cf71d22009-07-23 18:11:12 -07001941 netif_wake_queue(vptr->dev);
1942 }
1943 return works;
1944}
1945
1946/**
1947 * velocity_rx_csum - checksum process
1948 * @rd: receive packet descriptor
1949 * @skb: network layer packet buffer
1950 *
1951 * Process the status bits for the received packet and determine
1952 * if the checksum was computed and verified by the hardware
1953 */
1954static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
1955{
Eric Dumazetbc8acf22010-09-02 13:07:41 -07001956 skb_checksum_none_assert(skb);
Dave Jones2cf71d22009-07-23 18:11:12 -07001957
1958 if (rd->rdesc1.CSM & CSM_IPKT) {
1959 if (rd->rdesc1.CSM & CSM_IPOK) {
1960 if ((rd->rdesc1.CSM & CSM_TCPKT) ||
1961 (rd->rdesc1.CSM & CSM_UDPKT)) {
1962 if (!(rd->rdesc1.CSM & CSM_TUPOK))
1963 return;
1964 }
1965 skb->ip_summed = CHECKSUM_UNNECESSARY;
1966 }
1967 }
1968}
1969
1970/**
1971 * velocity_rx_copy - in place Rx copy for small packets
1972 * @rx_skb: network layer packet buffer candidate
1973 * @pkt_size: received data size
1974 * @rd: receive packet descriptor
1975 * @dev: network device
1976 *
1977 * Replace the current skb that is scheduled for Rx processing by a
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001978 * shorter, immediately allocated skb, if the received packet is small
Dave Jones2cf71d22009-07-23 18:11:12 -07001979 * enough. This function returns a negative value if the received
1980 * packet is too big or if memory is exhausted.
1981 */
1982static int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
1983 struct velocity_info *vptr)
1984{
1985 int ret = -1;
1986 if (pkt_size < rx_copybreak) {
1987 struct sk_buff *new_skb;
1988
Eric Dumazet89d71a62009-10-13 05:34:20 +00001989 new_skb = netdev_alloc_skb_ip_align(vptr->dev, pkt_size);
Dave Jones2cf71d22009-07-23 18:11:12 -07001990 if (new_skb) {
1991 new_skb->ip_summed = rx_skb[0]->ip_summed;
Dave Jones2cf71d22009-07-23 18:11:12 -07001992 skb_copy_from_linear_data(*rx_skb, new_skb->data, pkt_size);
1993 *rx_skb = new_skb;
1994 ret = 0;
1995 }
1996
1997 }
1998 return ret;
1999}
2000
2001/**
2002 * velocity_iph_realign - IP header alignment
2003 * @vptr: velocity we are handling
2004 * @skb: network layer packet buffer
2005 * @pkt_size: received data size
2006 *
2007 * Align IP header on a 2 bytes boundary. This behavior can be
2008 * configured by the user.
2009 */
2010static inline void velocity_iph_realign(struct velocity_info *vptr,
2011 struct sk_buff *skb, int pkt_size)
2012{
2013 if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
2014 memmove(skb->data + 2, skb->data, pkt_size);
2015 skb_reserve(skb, 2);
2016 }
2017}
2018
Dave Jones2cf71d22009-07-23 18:11:12 -07002019/**
2020 * velocity_receive_frame - received packet processor
2021 * @vptr: velocity we are handling
2022 * @idx: ring index
2023 *
2024 * A packet has arrived. We process the packet and if appropriate
2025 * pass the frame up the network stack
2026 */
2027static int velocity_receive_frame(struct velocity_info *vptr, int idx)
2028{
2029 void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
2030 struct net_device_stats *stats = &vptr->dev->stats;
2031 struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
2032 struct rx_desc *rd = &(vptr->rx.ring[idx]);
2033 int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
2034 struct sk_buff *skb;
2035
2036 if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
2037 VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name);
2038 stats->rx_length_errors++;
2039 return -EINVAL;
2040 }
2041
2042 if (rd->rdesc0.RSR & RSR_MAR)
2043 stats->multicast++;
2044
2045 skb = rd_info->skb;
2046
2047 pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
2048 vptr->rx.buf_sz, PCI_DMA_FROMDEVICE);
2049
2050 /*
2051 * Drop frame not meeting IEEE 802.3
2052 */
2053
2054 if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) {
2055 if (rd->rdesc0.RSR & RSR_RL) {
2056 stats->rx_length_errors++;
2057 return -EINVAL;
2058 }
2059 }
2060
2061 pci_action = pci_dma_sync_single_for_device;
2062
2063 velocity_rx_csum(rd, skb);
2064
2065 if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
2066 velocity_iph_realign(vptr, skb, pkt_len);
2067 pci_action = pci_unmap_single;
2068 rd_info->skb = NULL;
2069 }
2070
2071 pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz,
2072 PCI_DMA_FROMDEVICE);
2073
2074 skb_put(skb, pkt_len - 4);
2075 skb->protocol = eth_type_trans(skb, vptr->dev);
2076
Jiri Pirko73b54682011-07-20 04:54:30 +00002077 if (rd->rdesc0.RSR & RSR_DETAG) {
2078 u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG));
2079
2080 __vlan_hwaccel_put_tag(skb, vid);
2081 }
2082 netif_rx(skb);
Dave Jones2cf71d22009-07-23 18:11:12 -07002083
2084 stats->rx_bytes += pkt_len;
françois romieu3cb7a792011-08-04 02:37:55 +00002085 stats->rx_packets++;
Dave Jones2cf71d22009-07-23 18:11:12 -07002086
2087 return 0;
2088}
2089
Dave Jones2cf71d22009-07-23 18:11:12 -07002090/**
2091 * velocity_rx_srv - service RX interrupt
2092 * @vptr: velocity
Dave Jones2cf71d22009-07-23 18:11:12 -07002093 *
2094 * Walk the receive ring of the velocity adapter and remove
2095 * any received packets from the receive queue. Hand the ring
2096 * slots back to the adapter for reuse.
2097 */
Simon Kagstromd6cade02010-02-09 23:37:54 +00002098static int velocity_rx_srv(struct velocity_info *vptr, int budget_left)
Dave Jones2cf71d22009-07-23 18:11:12 -07002099{
2100 struct net_device_stats *stats = &vptr->dev->stats;
2101 int rd_curr = vptr->rx.curr;
2102 int works = 0;
2103
Simon Kagstromdfff7142009-11-25 22:10:26 +00002104 while (works < budget_left) {
Dave Jones2cf71d22009-07-23 18:11:12 -07002105 struct rx_desc *rd = vptr->rx.ring + rd_curr;
2106
2107 if (!vptr->rx.info[rd_curr].skb)
2108 break;
2109
2110 if (rd->rdesc0.len & OWNED_BY_NIC)
2111 break;
2112
2113 rmb();
2114
2115 /*
2116 * Don't drop CE or RL error frame although RXOK is off
2117 */
2118 if (rd->rdesc0.RSR & (RSR_RXOK | RSR_CE | RSR_RL)) {
2119 if (velocity_receive_frame(vptr, rd_curr) < 0)
2120 stats->rx_dropped++;
2121 } else {
2122 if (rd->rdesc0.RSR & RSR_CRC)
2123 stats->rx_crc_errors++;
2124 if (rd->rdesc0.RSR & RSR_FAE)
2125 stats->rx_frame_errors++;
2126
2127 stats->rx_dropped++;
2128 }
2129
2130 rd->size |= RX_INTEN;
2131
2132 rd_curr++;
2133 if (rd_curr >= vptr->options.numrx)
2134 rd_curr = 0;
Simon Kagstromdfff7142009-11-25 22:10:26 +00002135 works++;
2136 }
Dave Jones2cf71d22009-07-23 18:11:12 -07002137
2138 vptr->rx.curr = rd_curr;
2139
2140 if ((works > 0) && (velocity_rx_refill(vptr) > 0))
2141 velocity_give_many_rx_descs(vptr);
2142
2143 VAR_USED(stats);
2144 return works;
2145}
2146
Simon Kagstromdfff7142009-11-25 22:10:26 +00002147static int velocity_poll(struct napi_struct *napi, int budget)
2148{
2149 struct velocity_info *vptr = container_of(napi,
2150 struct velocity_info, napi);
2151 unsigned int rx_done;
Simon Kagstrom3f2e8d92010-02-09 23:38:25 +00002152 unsigned long flags;
Simon Kagstromdfff7142009-11-25 22:10:26 +00002153
Simon Kagstrom3f2e8d92010-02-09 23:38:25 +00002154 spin_lock_irqsave(&vptr->lock, flags);
Simon Kagstromdfff7142009-11-25 22:10:26 +00002155 /*
2156 * Do rx and tx twice for performance (taken from the VIA
2157 * out-of-tree driver).
2158 */
Simon Kagstromd6cade02010-02-09 23:37:54 +00002159 rx_done = velocity_rx_srv(vptr, budget / 2);
2160 velocity_tx_srv(vptr);
2161 rx_done += velocity_rx_srv(vptr, budget - rx_done);
2162 velocity_tx_srv(vptr);
Simon Kagstromdfff7142009-11-25 22:10:26 +00002163
2164 /* If budget not fully consumed, exit the polling mode */
2165 if (rx_done < budget) {
2166 napi_complete(napi);
2167 mac_enable_int(vptr->mac_regs);
2168 }
Simon Kagstrom3f2e8d92010-02-09 23:38:25 +00002169 spin_unlock_irqrestore(&vptr->lock, flags);
Simon Kagstromdfff7142009-11-25 22:10:26 +00002170
2171 return rx_done;
2172}
Dave Jones2cf71d22009-07-23 18:11:12 -07002173
2174/**
2175 * velocity_intr - interrupt callback
2176 * @irq: interrupt number
2177 * @dev_instance: interrupting device
2178 *
2179 * Called whenever an interrupt is generated by the velocity
2180 * adapter IRQ line. We may not be the source of the interrupt
2181 * and need to identify initially if we are, and if not exit as
2182 * efficiently as possible.
2183 */
2184static irqreturn_t velocity_intr(int irq, void *dev_instance)
2185{
2186 struct net_device *dev = dev_instance;
2187 struct velocity_info *vptr = netdev_priv(dev);
2188 u32 isr_status;
Dave Jones2cf71d22009-07-23 18:11:12 -07002189
2190 spin_lock(&vptr->lock);
2191 isr_status = mac_read_isr(vptr->mac_regs);
2192
2193 /* Not us ? */
2194 if (isr_status == 0) {
2195 spin_unlock(&vptr->lock);
2196 return IRQ_NONE;
2197 }
2198
Simon Kagstrom3f2e8d92010-02-09 23:38:25 +00002199 /* Ack the interrupt */
2200 mac_write_isr(vptr->mac_regs, isr_status);
2201
Simon Kagstromdfff7142009-11-25 22:10:26 +00002202 if (likely(napi_schedule_prep(&vptr->napi))) {
2203 mac_disable_int(vptr->mac_regs);
2204 __napi_schedule(&vptr->napi);
Dave Jones2cf71d22009-07-23 18:11:12 -07002205 }
Simon Kagstrom3f2e8d92010-02-09 23:38:25 +00002206
2207 if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI)))
2208 velocity_error(vptr, isr_status);
2209
Dave Jones2cf71d22009-07-23 18:11:12 -07002210 spin_unlock(&vptr->lock);
Dave Jones2cf71d22009-07-23 18:11:12 -07002211
Simon Kagstromdfff7142009-11-25 22:10:26 +00002212 return IRQ_HANDLED;
Dave Jones2cf71d22009-07-23 18:11:12 -07002213}
2214
2215/**
2216 * velocity_open - interface activation callback
2217 * @dev: network layer device to open
2218 *
2219 * Called when the network layer brings the interface up. Returns
2220 * a negative posix error code on failure, or zero on success.
2221 *
2222 * All the ring allocation and set up is done on open for this
2223 * adapter to minimise memory usage when inactive
2224 */
2225static int velocity_open(struct net_device *dev)
2226{
2227 struct velocity_info *vptr = netdev_priv(dev);
2228 int ret;
2229
2230 ret = velocity_init_rings(vptr, dev->mtu);
2231 if (ret < 0)
2232 goto out;
2233
2234 /* Ensure chip is running */
2235 pci_set_power_state(vptr->pdev, PCI_D0);
2236
Dave Jones2cf71d22009-07-23 18:11:12 -07002237 velocity_init_registers(vptr, VELOCITY_INIT_COLD);
2238
Julia Lawall1ede9b52009-11-18 08:24:13 +00002239 ret = request_irq(vptr->pdev->irq, velocity_intr, IRQF_SHARED,
Dave Jones2cf71d22009-07-23 18:11:12 -07002240 dev->name, dev);
2241 if (ret < 0) {
2242 /* Power down the chip */
2243 pci_set_power_state(vptr->pdev, PCI_D3hot);
2244 velocity_free_rings(vptr);
2245 goto out;
2246 }
2247
Ben Hutchings35bb5ca2009-12-14 16:05:09 +00002248 velocity_give_many_rx_descs(vptr);
2249
Dave Jones2cf71d22009-07-23 18:11:12 -07002250 mac_enable_int(vptr->mac_regs);
2251 netif_start_queue(dev);
Simon Kagstromdfff7142009-11-25 22:10:26 +00002252 napi_enable(&vptr->napi);
Dave Jones2cf71d22009-07-23 18:11:12 -07002253 vptr->flags |= VELOCITY_FLAGS_OPENED;
2254out:
2255 return ret;
2256}
2257
2258/**
2259 * velocity_shutdown - shut down the chip
2260 * @vptr: velocity to deactivate
2261 *
2262 * Shuts down the internal operations of the velocity and
2263 * disables interrupts, autopolling, transmit and receive
2264 */
2265static void velocity_shutdown(struct velocity_info *vptr)
2266{
2267 struct mac_regs __iomem *regs = vptr->mac_regs;
2268 mac_disable_int(regs);
2269 writel(CR0_STOP, &regs->CR0Set);
2270 writew(0xFFFF, &regs->TDCSRClr);
2271 writeb(0xFF, &regs->RDCSRClr);
2272 safe_disable_mii_autopoll(regs);
2273 mac_clear_isr(regs);
2274}
2275
2276/**
2277 * velocity_change_mtu - MTU change callback
2278 * @dev: network device
2279 * @new_mtu: desired MTU
2280 *
2281 * Handle requests from the networking layer for MTU change on
2282 * this interface. It gets called on a change by the network layer.
2283 * Return zero for success or negative posix error code.
2284 */
2285static int velocity_change_mtu(struct net_device *dev, int new_mtu)
2286{
2287 struct velocity_info *vptr = netdev_priv(dev);
2288 int ret = 0;
2289
2290 if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) {
2291 VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n",
2292 vptr->dev->name);
2293 ret = -EINVAL;
2294 goto out_0;
2295 }
2296
2297 if (!netif_running(dev)) {
2298 dev->mtu = new_mtu;
2299 goto out_0;
2300 }
2301
2302 if (dev->mtu != new_mtu) {
2303 struct velocity_info *tmp_vptr;
2304 unsigned long flags;
2305 struct rx_info rx;
2306 struct tx_info tx;
2307
2308 tmp_vptr = kzalloc(sizeof(*tmp_vptr), GFP_KERNEL);
2309 if (!tmp_vptr) {
2310 ret = -ENOMEM;
2311 goto out_0;
2312 }
2313
2314 tmp_vptr->dev = dev;
2315 tmp_vptr->pdev = vptr->pdev;
2316 tmp_vptr->options = vptr->options;
2317 tmp_vptr->tx.numq = vptr->tx.numq;
2318
2319 ret = velocity_init_rings(tmp_vptr, new_mtu);
2320 if (ret < 0)
2321 goto out_free_tmp_vptr_1;
2322
2323 spin_lock_irqsave(&vptr->lock, flags);
2324
2325 netif_stop_queue(dev);
2326 velocity_shutdown(vptr);
2327
2328 rx = vptr->rx;
2329 tx = vptr->tx;
2330
2331 vptr->rx = tmp_vptr->rx;
2332 vptr->tx = tmp_vptr->tx;
2333
2334 tmp_vptr->rx = rx;
2335 tmp_vptr->tx = tx;
2336
2337 dev->mtu = new_mtu;
2338
Dave Jones2cf71d22009-07-23 18:11:12 -07002339 velocity_init_registers(vptr, VELOCITY_INIT_COLD);
2340
Ben Hutchings35bb5ca2009-12-14 16:05:09 +00002341 velocity_give_many_rx_descs(vptr);
2342
Dave Jones2cf71d22009-07-23 18:11:12 -07002343 mac_enable_int(vptr->mac_regs);
2344 netif_start_queue(dev);
2345
2346 spin_unlock_irqrestore(&vptr->lock, flags);
2347
2348 velocity_free_rings(tmp_vptr);
2349
2350out_free_tmp_vptr_1:
2351 kfree(tmp_vptr);
2352 }
2353out_0:
2354 return ret;
2355}
2356
2357/**
2358 * velocity_mii_ioctl - MII ioctl handler
2359 * @dev: network device
2360 * @ifr: the ifreq block for the ioctl
2361 * @cmd: the command
2362 *
2363 * Process MII requests made via ioctl from the network layer. These
2364 * are used by tools like kudzu to interrogate the link state of the
2365 * hardware
2366 */
2367static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2368{
2369 struct velocity_info *vptr = netdev_priv(dev);
2370 struct mac_regs __iomem *regs = vptr->mac_regs;
2371 unsigned long flags;
2372 struct mii_ioctl_data *miidata = if_mii(ifr);
2373 int err;
2374
2375 switch (cmd) {
2376 case SIOCGMIIPHY:
2377 miidata->phy_id = readb(&regs->MIIADR) & 0x1f;
2378 break;
2379 case SIOCGMIIREG:
Dave Jones2cf71d22009-07-23 18:11:12 -07002380 if (velocity_mii_read(vptr->mac_regs, miidata->reg_num & 0x1f, &(miidata->val_out)) < 0)
2381 return -ETIMEDOUT;
2382 break;
2383 case SIOCSMIIREG:
Dave Jones2cf71d22009-07-23 18:11:12 -07002384 spin_lock_irqsave(&vptr->lock, flags);
2385 err = velocity_mii_write(vptr->mac_regs, miidata->reg_num & 0x1f, miidata->val_in);
2386 spin_unlock_irqrestore(&vptr->lock, flags);
2387 check_connection_type(vptr->mac_regs);
2388 if (err)
2389 return err;
2390 break;
2391 default:
2392 return -EOPNOTSUPP;
2393 }
2394 return 0;
2395}
2396
Dave Jones2cf71d22009-07-23 18:11:12 -07002397/**
2398 * velocity_ioctl - ioctl entry point
2399 * @dev: network device
2400 * @rq: interface request ioctl
2401 * @cmd: command code
2402 *
2403 * Called when the user issues an ioctl request to the network
2404 * device in question. The velocity interface supports MII.
2405 */
2406static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2407{
2408 struct velocity_info *vptr = netdev_priv(dev);
2409 int ret;
2410
2411 /* If we are asked for information and the device is power
2412 saving then we need to bring the device back up to talk to it */
2413
2414 if (!netif_running(dev))
2415 pci_set_power_state(vptr->pdev, PCI_D0);
2416
2417 switch (cmd) {
2418 case SIOCGMIIPHY: /* Get address of MII PHY in use. */
2419 case SIOCGMIIREG: /* Read MII PHY register. */
2420 case SIOCSMIIREG: /* Write to MII PHY register. */
2421 ret = velocity_mii_ioctl(dev, rq, cmd);
2422 break;
2423
2424 default:
2425 ret = -EOPNOTSUPP;
2426 }
2427 if (!netif_running(dev))
2428 pci_set_power_state(vptr->pdev, PCI_D3hot);
2429
2430
2431 return ret;
2432}
2433
2434/**
2435 * velocity_get_status - statistics callback
2436 * @dev: network device
2437 *
2438 * Callback from the network layer to allow driver statistics
2439 * to be resynchronized with hardware collected state. In the
2440 * case of the velocity we need to pull the MIB counters from
2441 * the hardware into the counters before letting the network
2442 * layer display them.
2443 */
2444static struct net_device_stats *velocity_get_stats(struct net_device *dev)
2445{
2446 struct velocity_info *vptr = netdev_priv(dev);
2447
2448 /* If the hardware is down, don't touch MII */
2449 if (!netif_running(dev))
2450 return &dev->stats;
2451
2452 spin_lock_irq(&vptr->lock);
2453 velocity_update_hw_mibs(vptr);
2454 spin_unlock_irq(&vptr->lock);
2455
2456 dev->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
2457 dev->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
2458 dev->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
2459
2460// unsigned long rx_dropped; /* no space in linux buffers */
2461 dev->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
2462 /* detailed rx_errors: */
2463// unsigned long rx_length_errors;
2464// unsigned long rx_over_errors; /* receiver ring buff overflow */
2465 dev->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
2466// unsigned long rx_frame_errors; /* recv'd frame alignment error */
2467// unsigned long rx_fifo_errors; /* recv'r fifo overrun */
2468// unsigned long rx_missed_errors; /* receiver missed packet */
2469
2470 /* detailed tx_errors */
2471// unsigned long tx_fifo_errors;
2472
2473 return &dev->stats;
2474}
2475
2476/**
2477 * velocity_close - close adapter callback
2478 * @dev: network device
2479 *
2480 * Callback from the network layer when the velocity is being
2481 * deactivated by the network layer
2482 */
2483static int velocity_close(struct net_device *dev)
2484{
2485 struct velocity_info *vptr = netdev_priv(dev);
2486
Simon Kagstromdfff7142009-11-25 22:10:26 +00002487 napi_disable(&vptr->napi);
Dave Jones2cf71d22009-07-23 18:11:12 -07002488 netif_stop_queue(dev);
2489 velocity_shutdown(vptr);
2490
2491 if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
2492 velocity_get_ip(vptr);
2493 if (dev->irq != 0)
2494 free_irq(dev->irq, dev);
2495
2496 /* Power down the chip */
2497 pci_set_power_state(vptr->pdev, PCI_D3hot);
2498
2499 velocity_free_rings(vptr);
2500
2501 vptr->flags &= (~VELOCITY_FLAGS_OPENED);
2502 return 0;
2503}
2504
2505/**
2506 * velocity_xmit - transmit packet callback
2507 * @skb: buffer to transmit
2508 * @dev: network device
2509 *
2510 * Called by the networ layer to request a packet is queued to
2511 * the velocity. Returns zero on success.
2512 */
Stephen Hemminger613573252009-08-31 19:50:58 +00002513static netdev_tx_t velocity_xmit(struct sk_buff *skb,
2514 struct net_device *dev)
Dave Jones2cf71d22009-07-23 18:11:12 -07002515{
2516 struct velocity_info *vptr = netdev_priv(dev);
2517 int qnum = 0;
2518 struct tx_desc *td_ptr;
2519 struct velocity_td_info *tdinfo;
2520 unsigned long flags;
2521 int pktlen;
Simon Kagstromc79992f2009-11-25 22:10:43 +00002522 int index, prev;
2523 int i = 0;
Dave Jones2cf71d22009-07-23 18:11:12 -07002524
2525 if (skb_padto(skb, ETH_ZLEN))
2526 goto out;
Dave Jones2cf71d22009-07-23 18:11:12 -07002527
Simon Kagstromc79992f2009-11-25 22:10:43 +00002528 /* The hardware can handle at most 7 memory segments, so merge
2529 * the skb if there are more */
2530 if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
2531 kfree_skb(skb);
2532 return NETDEV_TX_OK;
2533 }
2534
2535 pktlen = skb_shinfo(skb)->nr_frags == 0 ?
2536 max_t(unsigned int, skb->len, ETH_ZLEN) :
2537 skb_headlen(skb);
Dave Jones2cf71d22009-07-23 18:11:12 -07002538
2539 spin_lock_irqsave(&vptr->lock, flags);
2540
2541 index = vptr->tx.curr[qnum];
2542 td_ptr = &(vptr->tx.rings[qnum][index]);
2543 tdinfo = &(vptr->tx.infos[qnum][index]);
2544
2545 td_ptr->tdesc1.TCR = TCR0_TIC;
2546 td_ptr->td_buf[0].size &= ~TD_QUEUE;
2547
2548 /*
2549 * Map the linear network buffer into PCI space and
2550 * add it to the transmit ring.
2551 */
2552 tdinfo->skb = skb;
2553 tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
Simon Kagstromc79992f2009-11-25 22:10:43 +00002554 td_ptr->tdesc0.len = cpu_to_le16(pktlen);
Dave Jones2cf71d22009-07-23 18:11:12 -07002555 td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
2556 td_ptr->td_buf[0].pa_high = 0;
Simon Kagstromc79992f2009-11-25 22:10:43 +00002557 td_ptr->td_buf[0].size = cpu_to_le16(pktlen);
2558
2559 /* Handle fragments */
2560 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
2561 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
2562
2563 tdinfo->skb_dma[i + 1] = pci_map_page(vptr->pdev, frag->page,
2564 frag->page_offset, frag->size,
2565 PCI_DMA_TODEVICE);
2566
2567 td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
2568 td_ptr->td_buf[i + 1].pa_high = 0;
2569 td_ptr->td_buf[i + 1].size = cpu_to_le16(frag->size);
2570 }
2571 tdinfo->nskb_dma = i + 1;
Dave Jones2cf71d22009-07-23 18:11:12 -07002572
2573 td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
2574
Jesse Grosseab6d182010-10-20 13:56:03 +00002575 if (vlan_tx_tag_present(skb)) {
Dave Jones2cf71d22009-07-23 18:11:12 -07002576 td_ptr->tdesc1.vlan = cpu_to_le16(vlan_tx_tag_get(skb));
2577 td_ptr->tdesc1.TCR |= TCR0_VETAG;
2578 }
2579
2580 /*
2581 * Handle hardware checksum
2582 */
Michał Mirosławf593fe32011-04-10 03:13:21 +00002583 if (skb->ip_summed == CHECKSUM_PARTIAL) {
Dave Jones2cf71d22009-07-23 18:11:12 -07002584 const struct iphdr *ip = ip_hdr(skb);
2585 if (ip->protocol == IPPROTO_TCP)
2586 td_ptr->tdesc1.TCR |= TCR0_TCPCK;
2587 else if (ip->protocol == IPPROTO_UDP)
2588 td_ptr->tdesc1.TCR |= (TCR0_UDPCK);
2589 td_ptr->tdesc1.TCR |= TCR0_IPCK;
2590 }
Dave Jones2cf71d22009-07-23 18:11:12 -07002591
Simon Kagstromc79992f2009-11-25 22:10:43 +00002592 prev = index - 1;
2593 if (prev < 0)
2594 prev = vptr->options.numtx - 1;
2595 td_ptr->tdesc0.len |= OWNED_BY_NIC;
2596 vptr->tx.used[qnum]++;
2597 vptr->tx.curr[qnum] = (index + 1) % vptr->options.numtx;
Dave Jones2cf71d22009-07-23 18:11:12 -07002598
Simon Kagstromc79992f2009-11-25 22:10:43 +00002599 if (AVAIL_TD(vptr, qnum) < 1)
2600 netif_stop_queue(dev);
Dave Jones2cf71d22009-07-23 18:11:12 -07002601
Simon Kagstromc79992f2009-11-25 22:10:43 +00002602 td_ptr = &(vptr->tx.rings[qnum][prev]);
2603 td_ptr->td_buf[0].size |= TD_QUEUE;
2604 mac_tx_queue_wake(vptr->mac_regs, qnum);
Dave Jones2cf71d22009-07-23 18:11:12 -07002605
Dave Jones2cf71d22009-07-23 18:11:12 -07002606 spin_unlock_irqrestore(&vptr->lock, flags);
2607out:
2608 return NETDEV_TX_OK;
2609}
2610
Stephen Hemminger39a11bd2008-11-19 22:19:33 -08002611static const struct net_device_ops velocity_netdev_ops = {
2612 .ndo_open = velocity_open,
2613 .ndo_stop = velocity_close,
Stephen Hemminger00829822008-11-20 20:14:53 -08002614 .ndo_start_xmit = velocity_xmit,
Stephen Hemminger39a11bd2008-11-19 22:19:33 -08002615 .ndo_get_stats = velocity_get_stats,
2616 .ndo_validate_addr = eth_validate_addr,
françois romieu5ae297b2011-08-04 02:39:03 +00002617 .ndo_set_mac_address = eth_mac_addr,
Stephen Hemminger39a11bd2008-11-19 22:19:33 -08002618 .ndo_set_multicast_list = velocity_set_multi,
2619 .ndo_change_mtu = velocity_change_mtu,
2620 .ndo_do_ioctl = velocity_ioctl,
2621 .ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
2622 .ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
Stephen Hemminger39a11bd2008-11-19 22:19:33 -08002623};
2624
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625/**
Dave Jones2cf71d22009-07-23 18:11:12 -07002626 * velocity_init_info - init private data
2627 * @pdev: PCI device
2628 * @vptr: Velocity info
2629 * @info: Board type
2630 *
2631 * Set up the initial velocity_info struct for the device that has been
2632 * discovered.
2633 */
2634static void __devinit velocity_init_info(struct pci_dev *pdev,
2635 struct velocity_info *vptr,
2636 const struct velocity_info_tbl *info)
2637{
2638 memset(vptr, 0, sizeof(struct velocity_info));
2639
2640 vptr->pdev = pdev;
2641 vptr->chip_id = info->chip_id;
2642 vptr->tx.numq = info->txqueue;
2643 vptr->multicast_limit = MCAM_SIZE;
2644 spin_lock_init(&vptr->lock);
Dave Jones2cf71d22009-07-23 18:11:12 -07002645}
2646
2647/**
2648 * velocity_get_pci_info - retrieve PCI info for device
2649 * @vptr: velocity device
2650 * @pdev: PCI device it matches
2651 *
2652 * Retrieve the PCI configuration space data that interests us from
2653 * the kernel PCI layer
2654 */
2655static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
2656{
2657 vptr->rev_id = pdev->revision;
2658
2659 pci_set_master(pdev);
2660
2661 vptr->ioaddr = pci_resource_start(pdev, 0);
2662 vptr->memaddr = pci_resource_start(pdev, 1);
2663
2664 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
2665 dev_err(&pdev->dev,
2666 "region #0 is not an I/O resource, aborting.\n");
2667 return -EINVAL;
2668 }
2669
2670 if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
2671 dev_err(&pdev->dev,
2672 "region #1 is an I/O resource, aborting.\n");
2673 return -EINVAL;
2674 }
2675
2676 if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
2677 dev_err(&pdev->dev, "region #1 is too small.\n");
2678 return -EINVAL;
2679 }
2680 vptr->pdev = pdev;
2681
2682 return 0;
2683}
2684
2685/**
2686 * velocity_print_info - per driver data
2687 * @vptr: velocity
2688 *
2689 * Print per driver data as the kernel driver finds Velocity
2690 * hardware
2691 */
2692static void __devinit velocity_print_info(struct velocity_info *vptr)
2693{
2694 struct net_device *dev = vptr->dev;
2695
2696 printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id));
H Hartley Sweetenaa7c68a2009-12-29 20:04:14 -08002697 printk(KERN_INFO "%s: Ethernet Address: %pM\n",
2698 dev->name, dev->dev_addr);
Dave Jones2cf71d22009-07-23 18:11:12 -07002699}
2700
2701static u32 velocity_get_link(struct net_device *dev)
2702{
2703 struct velocity_info *vptr = netdev_priv(dev);
2704 struct mac_regs __iomem *regs = vptr->mac_regs;
2705 return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
2706}
2707
Dave Jones2cf71d22009-07-23 18:11:12 -07002708/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 * velocity_found1 - set up discovered velocity card
2710 * @pdev: PCI device
2711 * @ent: PCI device table entry that matched
2712 *
2713 * Configure a discovered adapter from scratch. Return a negative
2714 * errno error code on failure paths.
2715 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
2717{
2718 static int first = 1;
2719 struct net_device *dev;
2720 int i;
Sven Hartge07b5f6a2008-10-23 13:03:44 +00002721 const char *drv_string;
Jeff Garzikcabb7662006-06-27 09:25:28 -04002722 const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 struct velocity_info *vptr;
Dave Jonesc4067402009-07-20 17:35:21 +00002724 struct mac_regs __iomem *regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 int ret = -ENOMEM;
2726
Jeff Garzike54f4892006-06-27 09:20:08 -04002727 /* FIXME: this driver, like almost all other ethernet drivers,
2728 * can support more than MAX_UNITS.
2729 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 if (velocity_nics >= MAX_UNITS) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002731 dev_notice(&pdev->dev, "already found %d NICs.\n",
Jeff Garzike54f4892006-06-27 09:20:08 -04002732 velocity_nics);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return -ENODEV;
2734 }
2735
2736 dev = alloc_etherdev(sizeof(struct velocity_info));
Jeff Garzike54f4892006-06-27 09:20:08 -04002737 if (!dev) {
Jeff Garzik9b91cf92006-06-27 11:39:50 -04002738 dev_err(&pdev->dev, "allocate net device failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 goto out;
2740 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002741
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 /* Chain it all together */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002743
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 SET_NETDEV_DEV(dev, &pdev->dev);
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04002745 vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
2747
2748 if (first) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002749 printk(KERN_INFO "%s Ver. %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION);
2751 printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n");
2752 printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n");
2753 first = 0;
2754 }
2755
2756 velocity_init_info(pdev, vptr, info);
2757
2758 vptr->dev = dev;
2759
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 ret = pci_enable_device(pdev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002761 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 goto err_free_dev;
2763
Kulikov Vasiliy889635f2010-08-03 05:43:18 +00002764 dev->irq = pdev->irq;
2765
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 ret = velocity_get_pci_info(vptr, pdev);
2767 if (ret < 0) {
Jeff Garzike54f4892006-06-27 09:20:08 -04002768 /* error message already printed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 goto err_disable;
2770 }
2771
2772 ret = pci_request_regions(pdev, VELOCITY_NAME);
2773 if (ret < 0) {
Jeff Garzik9b91cf92006-06-27 11:39:50 -04002774 dev_err(&pdev->dev, "No PCI resources.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 goto err_disable;
2776 }
2777
Jeff Garzikcabb7662006-06-27 09:25:28 -04002778 regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 if (regs == NULL) {
2780 ret = -EIO;
2781 goto err_release_res;
2782 }
2783
2784 vptr->mac_regs = regs;
2785
2786 mac_wol_reset(regs);
2787
2788 dev->base_addr = vptr->ioaddr;
2789
2790 for (i = 0; i < 6; i++)
2791 dev->dev_addr[i] = readb(&regs->PAR[i]);
2792
2793
Sven Hartge07b5f6a2008-10-23 13:03:44 +00002794 drv_string = dev_driver_string(&pdev->dev);
2795
2796 velocity_get_options(&vptr->options, velocity_nics, drv_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002798 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 * Mask out the options cannot be set to the chip
2800 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002801
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 vptr->options.flags &= info->flags;
2803
2804 /*
2805 * Enable the chip specified capbilities
2806 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002807
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL);
2809
2810 vptr->wol_opts = vptr->options.wol_opts;
2811 vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
2812
2813 vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
2814
2815 dev->irq = pdev->irq;
Stephen Hemminger39a11bd2008-11-19 22:19:33 -08002816 dev->netdev_ops = &velocity_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 dev->ethtool_ops = &velocity_ethtool_ops;
Simon Kagstromdfff7142009-11-25 22:10:26 +00002818 netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
Stephen Hemminger501e4d22007-08-24 13:56:49 -07002819
Michał Mirosławf593fe32011-04-10 03:13:21 +00002820 dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HW_VLAN_TX;
Francois Romieud4f73c82008-04-24 23:32:33 +02002821 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
David S. Millerde2b96f2010-09-07 13:49:44 -07002822 NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
2824 ret = register_netdev(dev);
2825 if (ret < 0)
2826 goto err_iounmap;
2827
Séguier Régisd3b238a2009-06-16 11:25:49 +00002828 if (!velocity_get_link(dev)) {
Francois Romieu8a22ddd2006-06-23 00:47:06 +02002829 netif_carrier_off(dev);
Séguier Régisd3b238a2009-06-16 11:25:49 +00002830 vptr->mii_status |= VELOCITY_LINK_FAIL;
2831 }
Francois Romieu8a22ddd2006-06-23 00:47:06 +02002832
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 velocity_print_info(vptr);
2834 pci_set_drvdata(pdev, dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002835
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 /* and leave the chip powered down */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002837
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 pci_set_power_state(pdev, PCI_D3hot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 velocity_nics++;
2840out:
2841 return ret;
2842
2843err_iounmap:
2844 iounmap(regs);
2845err_release_res:
2846 pci_release_regions(pdev);
2847err_disable:
2848 pci_disable_device(pdev);
2849err_free_dev:
2850 free_netdev(dev);
2851 goto out;
2852}
2853
Dave Jones2cf71d22009-07-23 18:11:12 -07002854#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855/**
Dave Jones2cf71d22009-07-23 18:11:12 -07002856 * wol_calc_crc - WOL CRC
2857 * @pattern: data pattern
2858 * @mask_pattern: mask
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 *
Dave Jones2cf71d22009-07-23 18:11:12 -07002860 * Compute the wake on lan crc hashes for the packet header
2861 * we are interested in.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 */
Dave Jones2cf71d22009-07-23 18:11:12 -07002863static u16 wol_calc_crc(int size, u8 *pattern, u8 *mask_pattern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
Dave Jones2cf71d22009-07-23 18:11:12 -07002865 u16 crc = 0xFFFF;
2866 u8 mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 int i, j;
2868
Dave Jones2cf71d22009-07-23 18:11:12 -07002869 for (i = 0; i < size; i++) {
2870 mask = mask_pattern[i];
2871
2872 /* Skip this loop if the mask equals to zero */
2873 if (mask == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Dave Jones2cf71d22009-07-23 18:11:12 -07002876 for (j = 0; j < 8; j++) {
2877 if ((mask & 0x01) == 0) {
2878 mask >>= 1;
2879 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 }
Dave Jones2cf71d22009-07-23 18:11:12 -07002881 mask >>= 1;
2882 crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 }
2884 }
Dave Jones2cf71d22009-07-23 18:11:12 -07002885 /* Finally, invert the result once to get the correct data */
2886 crc = ~crc;
2887 return bitrev32(crc) >> 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888}
2889
2890/**
Dave Jones2cf71d22009-07-23 18:11:12 -07002891 * velocity_set_wol - set up for wake on lan
2892 * @vptr: velocity to set WOL status on
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 *
Dave Jones2cf71d22009-07-23 18:11:12 -07002894 * Set a card up for wake on lan either by unicast or by
2895 * ARP packet.
2896 *
2897 * FIXME: check static buffer is safe here
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 */
Dave Jones2cf71d22009-07-23 18:11:12 -07002899static int velocity_set_wol(struct velocity_info *vptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
Dave Jonesc4067402009-07-20 17:35:21 +00002901 struct mac_regs __iomem *regs = vptr->mac_regs;
françois romieu2ffa0072011-01-20 04:59:33 +00002902 enum speed_opt spd_dpx = vptr->options.spd_dpx;
Dave Jones2cf71d22009-07-23 18:11:12 -07002903 static u8 buf[256];
2904 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
Dave Jones2cf71d22009-07-23 18:11:12 -07002906 static u32 mask_pattern[2][4] = {
2907 {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
2908 {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */
2909 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Dave Jones2cf71d22009-07-23 18:11:12 -07002911 writew(0xFFFF, &regs->WOLCRClr);
2912 writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
2913 writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
Dave Jones2cf71d22009-07-23 18:11:12 -07002915 /*
2916 if (vptr->wol_opts & VELOCITY_WOL_PHY)
2917 writew((WOLCR_LINKON_EN|WOLCR_LINKOFF_EN), &regs->WOLCRSet);
2918 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
Dave Jones2cf71d22009-07-23 18:11:12 -07002920 if (vptr->wol_opts & VELOCITY_WOL_UCAST)
2921 writew(WOLCR_UNICAST_EN, &regs->WOLCRSet);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002922
Dave Jones2cf71d22009-07-23 18:11:12 -07002923 if (vptr->wol_opts & VELOCITY_WOL_ARP) {
2924 struct arp_packet *arp = (struct arp_packet *) buf;
2925 u16 crc;
2926 memset(buf, 0, sizeof(struct arp_packet) + 7);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002927
Dave Jones2cf71d22009-07-23 18:11:12 -07002928 for (i = 0; i < 4; i++)
2929 writel(mask_pattern[0][i], &regs->ByteMask[0][i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
Dave Jones2cf71d22009-07-23 18:11:12 -07002931 arp->type = htons(ETH_P_ARP);
2932 arp->ar_op = htons(1);
2933
2934 memcpy(arp->ar_tip, vptr->ip_addr, 4);
2935
2936 crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
2937 (u8 *) & mask_pattern[0][0]);
2938
2939 writew(crc, &regs->PatternCRC[0]);
2940 writew(WOLCR_ARP_EN, &regs->WOLCRSet);
2941 }
2942
2943 BYTE_REG_BITS_ON(PWCFG_WOLTYPE, &regs->PWCFGSet);
2944 BYTE_REG_BITS_ON(PWCFG_LEGACY_WOLEN, &regs->PWCFGSet);
2945
2946 writew(0x0FFF, &regs->WOLSRClr);
2947
françois romieu2ffa0072011-01-20 04:59:33 +00002948 if (spd_dpx == SPD_DPX_1000_FULL)
2949 goto mac_done;
2950
2951 if (spd_dpx != SPD_DPX_AUTO)
2952 goto advertise_done;
2953
Dave Jones2cf71d22009-07-23 18:11:12 -07002954 if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
2955 if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
Francois Romieu3a7f8682010-04-06 14:24:53 -07002956 MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07002957
Francois Romieu3a7f8682010-04-06 14:24:53 -07002958 MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07002959 }
2960
2961 if (vptr->mii_status & VELOCITY_SPEED_1000)
Francois Romieu3a7f8682010-04-06 14:24:53 -07002962 MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07002963
françois romieu2ffa0072011-01-20 04:59:33 +00002964advertise_done:
Dave Jones2cf71d22009-07-23 18:11:12 -07002965 BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
2966
2967 {
2968 u8 GCR;
2969 GCR = readb(&regs->CHIPGCR);
2970 GCR = (GCR & ~CHIPGCR_FCGMII) | CHIPGCR_FCFDX;
2971 writeb(GCR, &regs->CHIPGCR);
2972 }
2973
françois romieu2ffa0072011-01-20 04:59:33 +00002974mac_done:
Dave Jones2cf71d22009-07-23 18:11:12 -07002975 BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
2976 /* Turn on SWPTAG just before entering power mode */
2977 BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
2978 /* Go to bed ..... */
2979 BYTE_REG_BITS_ON((STICKHW_DS1 | STICKHW_DS0), &regs->STICKHW);
2980
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 return 0;
2982}
2983
2984/**
Dave Jones2cf71d22009-07-23 18:11:12 -07002985 * velocity_save_context - save registers
2986 * @vptr: velocity
2987 * @context: buffer for stored context
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 *
Dave Jones2cf71d22009-07-23 18:11:12 -07002989 * Retrieve the current configuration from the velocity hardware
2990 * and stash it in the context structure, for use by the context
2991 * restore functions. This allows us to save things we need across
2992 * power down states
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 */
Dave Jones2cf71d22009-07-23 18:11:12 -07002994static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995{
Dave Jones2cf71d22009-07-23 18:11:12 -07002996 struct mac_regs __iomem *regs = vptr->mac_regs;
2997 u16 i;
2998 u8 __iomem *ptr = (u8 __iomem *)regs;
2999
3000 for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4)
3001 *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
3002
3003 for (i = MAC_REG_MAR; i < MAC_REG_TDCSR_CLR; i += 4)
3004 *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
3005
3006 for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
3007 *((u32 *) (context->mac_reg + i)) = readl(ptr + i);
3008
3009}
3010
3011static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
3012{
3013 struct net_device *dev = pci_get_drvdata(pdev);
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003014 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 unsigned long flags;
Francois Romieu580a6902008-07-11 00:03:44 +02003016
Dave Jones2cf71d22009-07-23 18:11:12 -07003017 if (!netif_running(vptr->dev))
3018 return 0;
Francois Romieu580a6902008-07-11 00:03:44 +02003019
Dave Jones2cf71d22009-07-23 18:11:12 -07003020 netif_device_detach(vptr->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
3022 spin_lock_irqsave(&vptr->lock, flags);
Dave Jones2cf71d22009-07-23 18:11:12 -07003023 pci_save_state(pdev);
françois romieu5ae297b2011-08-04 02:39:03 +00003024
Dave Jones2cf71d22009-07-23 18:11:12 -07003025 if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
3026 velocity_get_ip(vptr);
3027 velocity_save_context(vptr, &vptr->context);
3028 velocity_shutdown(vptr);
3029 velocity_set_wol(vptr);
3030 pci_enable_wake(pdev, PCI_D3hot, 1);
3031 pci_set_power_state(pdev, PCI_D3hot);
3032 } else {
3033 velocity_save_context(vptr, &vptr->context);
3034 velocity_shutdown(vptr);
3035 pci_disable_device(pdev);
3036 pci_set_power_state(pdev, pci_choose_state(pdev, state));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
françois romieu5ae297b2011-08-04 02:39:03 +00003038
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 spin_unlock_irqrestore(&vptr->lock, flags);
Dave Jones2cf71d22009-07-23 18:11:12 -07003040 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041}
3042
3043/**
Dave Jones2cf71d22009-07-23 18:11:12 -07003044 * velocity_restore_context - restore registers
3045 * @vptr: velocity
3046 * @context: buffer for stored context
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 *
Dave Jones2cf71d22009-07-23 18:11:12 -07003048 * Reload the register configuration from the velocity context
3049 * created by velocity_save_context.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050 */
Dave Jones2cf71d22009-07-23 18:11:12 -07003051static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052{
Dave Jones2cf71d22009-07-23 18:11:12 -07003053 struct mac_regs __iomem *regs = vptr->mac_regs;
3054 int i;
3055 u8 __iomem *ptr = (u8 __iomem *)regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Dave Jones2cf71d22009-07-23 18:11:12 -07003057 for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4)
3058 writel(*((u32 *) (context->mac_reg + i)), ptr + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
Dave Jones2cf71d22009-07-23 18:11:12 -07003060 /* Just skip cr0 */
3061 for (i = MAC_REG_CR1_SET; i < MAC_REG_CR0_CLR; i++) {
3062 /* Clear */
3063 writeb(~(*((u8 *) (context->mac_reg + i))), ptr + i + 4);
3064 /* Set */
3065 writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 }
3067
Dave Jones2cf71d22009-07-23 18:11:12 -07003068 for (i = MAC_REG_MAR; i < MAC_REG_IMR; i += 4)
3069 writel(*((u32 *) (context->mac_reg + i)), ptr + i);
3070
3071 for (i = MAC_REG_RDBASE_LO; i < MAC_REG_FIFO_TEST0; i += 4)
3072 writel(*((u32 *) (context->mac_reg + i)), ptr + i);
3073
3074 for (i = MAC_REG_TDCSR_SET; i <= MAC_REG_RDCSR_SET; i++)
3075 writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
3076}
3077
3078static int velocity_resume(struct pci_dev *pdev)
3079{
3080 struct net_device *dev = pci_get_drvdata(pdev);
3081 struct velocity_info *vptr = netdev_priv(dev);
3082 unsigned long flags;
3083 int i;
3084
3085 if (!netif_running(vptr->dev))
3086 return 0;
3087
3088 pci_set_power_state(pdev, PCI_D0);
3089 pci_enable_wake(pdev, 0, 0);
3090 pci_restore_state(pdev);
3091
3092 mac_wol_reset(vptr->mac_regs);
3093
3094 spin_lock_irqsave(&vptr->lock, flags);
3095 velocity_restore_context(vptr, &vptr->context);
3096 velocity_init_registers(vptr, VELOCITY_INIT_WOL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 mac_disable_int(vptr->mac_regs);
3098
Simon Kagstromd6cade02010-02-09 23:37:54 +00003099 velocity_tx_srv(vptr);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003100
Dave Jones2cf71d22009-07-23 18:11:12 -07003101 for (i = 0; i < vptr->tx.numq; i++) {
3102 if (vptr->tx.used[i])
3103 mac_tx_queue_wake(vptr->mac_regs, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 }
Dave Jones2cf71d22009-07-23 18:11:12 -07003105
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 mac_enable_int(vptr->mac_regs);
Dave Jones2cf71d22009-07-23 18:11:12 -07003107 spin_unlock_irqrestore(&vptr->lock, flags);
3108 netif_device_attach(vptr->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
Dave Jones2cf71d22009-07-23 18:11:12 -07003110 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111}
Dave Jones2cf71d22009-07-23 18:11:12 -07003112#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113
3114/*
3115 * Definition for our device driver. The PCI layer interface
3116 * uses this to handle all our card discover and plugging
3117 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118static struct pci_driver velocity_driver = {
françois romieu5ae297b2011-08-04 02:39:03 +00003119 .name = VELOCITY_NAME,
3120 .id_table = velocity_id_table,
3121 .probe = velocity_found1,
3122 .remove = __devexit_p(velocity_remove1),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123#ifdef CONFIG_PM
françois romieu5ae297b2011-08-04 02:39:03 +00003124 .suspend = velocity_suspend,
3125 .resume = velocity_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126#endif
3127};
3128
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
3130/**
3131 * velocity_ethtool_up - pre hook for ethtool
3132 * @dev: network device
3133 *
3134 * Called before an ethtool operation. We need to make sure the
3135 * chip is out of D3 state before we poke at it.
3136 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137static int velocity_ethtool_up(struct net_device *dev)
3138{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003139 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 if (!netif_running(dev))
3141 pci_set_power_state(vptr->pdev, PCI_D0);
3142 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003143}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
3145/**
3146 * velocity_ethtool_down - post hook for ethtool
3147 * @dev: network device
3148 *
3149 * Called after an ethtool operation. Restore the chip back to D3
3150 * state if it isn't running.
3151 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152static void velocity_ethtool_down(struct net_device *dev)
3153{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003154 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 if (!netif_running(dev))
3156 pci_set_power_state(vptr->pdev, PCI_D3hot);
3157}
3158
David Decotigny70739492011-04-27 18:32:40 +00003159static int velocity_get_settings(struct net_device *dev,
3160 struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003162 struct velocity_info *vptr = netdev_priv(dev);
Dave Jonesc4067402009-07-20 17:35:21 +00003163 struct mac_regs __iomem *regs = vptr->mac_regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 u32 status;
3165 status = check_connection_type(vptr->mac_regs);
3166
Jay Cliburn59b693f2006-07-20 23:23:57 +02003167 cmd->supported = SUPPORTED_TP |
3168 SUPPORTED_Autoneg |
3169 SUPPORTED_10baseT_Half |
3170 SUPPORTED_10baseT_Full |
3171 SUPPORTED_100baseT_Half |
3172 SUPPORTED_100baseT_Full |
3173 SUPPORTED_1000baseT_Half |
3174 SUPPORTED_1000baseT_Full;
françois romieu15419222010-10-13 09:26:05 +00003175
3176 cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
3177 if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
3178 cmd->advertising |=
3179 ADVERTISED_10baseT_Half |
3180 ADVERTISED_10baseT_Full |
3181 ADVERTISED_100baseT_Half |
3182 ADVERTISED_100baseT_Full |
3183 ADVERTISED_1000baseT_Half |
3184 ADVERTISED_1000baseT_Full;
3185 } else {
3186 switch (vptr->options.spd_dpx) {
3187 case SPD_DPX_1000_FULL:
3188 cmd->advertising |= ADVERTISED_1000baseT_Full;
3189 break;
3190 case SPD_DPX_100_HALF:
3191 cmd->advertising |= ADVERTISED_100baseT_Half;
3192 break;
3193 case SPD_DPX_100_FULL:
3194 cmd->advertising |= ADVERTISED_100baseT_Full;
3195 break;
3196 case SPD_DPX_10_HALF:
3197 cmd->advertising |= ADVERTISED_10baseT_Half;
3198 break;
3199 case SPD_DPX_10_FULL:
3200 cmd->advertising |= ADVERTISED_10baseT_Full;
3201 break;
3202 default:
3203 break;
3204 }
3205 }
David Decotigny70739492011-04-27 18:32:40 +00003206
Jay Cliburn59b693f2006-07-20 23:23:57 +02003207 if (status & VELOCITY_SPEED_1000)
David Decotigny70739492011-04-27 18:32:40 +00003208 ethtool_cmd_speed_set(cmd, SPEED_1000);
Jay Cliburn59b693f2006-07-20 23:23:57 +02003209 else if (status & VELOCITY_SPEED_100)
David Decotigny70739492011-04-27 18:32:40 +00003210 ethtool_cmd_speed_set(cmd, SPEED_100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 else
David Decotigny70739492011-04-27 18:32:40 +00003212 ethtool_cmd_speed_set(cmd, SPEED_10);
3213
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 cmd->autoneg = (status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
3215 cmd->port = PORT_TP;
3216 cmd->transceiver = XCVR_INTERNAL;
3217 cmd->phy_address = readb(&regs->MIIADR) & 0x1F;
3218
3219 if (status & VELOCITY_DUPLEX_FULL)
3220 cmd->duplex = DUPLEX_FULL;
3221 else
3222 cmd->duplex = DUPLEX_HALF;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003223
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 return 0;
3225}
3226
David Decotigny25db0332011-04-27 18:32:39 +00003227static int velocity_set_settings(struct net_device *dev,
3228 struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003230 struct velocity_info *vptr = netdev_priv(dev);
David Decotigny25db0332011-04-27 18:32:39 +00003231 u32 speed = ethtool_cmd_speed(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 u32 curr_status;
3233 u32 new_status = 0;
3234 int ret = 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003235
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 curr_status = check_connection_type(vptr->mac_regs);
3237 curr_status &= (~VELOCITY_LINK_FAIL);
3238
3239 new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0);
David Decotigny25db0332011-04-27 18:32:39 +00003240 new_status |= ((speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0);
3241 new_status |= ((speed == SPEED_100) ? VELOCITY_SPEED_100 : 0);
3242 new_status |= ((speed == SPEED_10) ? VELOCITY_SPEED_10 : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0);
3244
françois romieu15419222010-10-13 09:26:05 +00003245 if ((new_status & VELOCITY_AUTONEG_ENABLE) &&
3246 (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 ret = -EINVAL;
françois romieu15419222010-10-13 09:26:05 +00003248 } else {
3249 enum speed_opt spd_dpx;
3250
3251 if (new_status & VELOCITY_AUTONEG_ENABLE)
3252 spd_dpx = SPD_DPX_AUTO;
3253 else if ((new_status & VELOCITY_SPEED_1000) &&
3254 (new_status & VELOCITY_DUPLEX_FULL)) {
3255 spd_dpx = SPD_DPX_1000_FULL;
3256 } else if (new_status & VELOCITY_SPEED_100)
3257 spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
3258 SPD_DPX_100_FULL : SPD_DPX_100_HALF;
3259 else if (new_status & VELOCITY_SPEED_10)
3260 spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
3261 SPD_DPX_10_FULL : SPD_DPX_10_HALF;
3262 else
3263 return -EOPNOTSUPP;
3264
3265 vptr->options.spd_dpx = spd_dpx;
3266
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 velocity_set_media_mode(vptr, new_status);
françois romieu15419222010-10-13 09:26:05 +00003268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
3270 return ret;
3271}
3272
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
3274{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003275 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 strcpy(info->driver, VELOCITY_NAME);
3277 strcpy(info->version, VELOCITY_VERSION);
3278 strcpy(info->bus_info, pci_name(vptr->pdev));
3279}
3280
3281static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
3282{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003283 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284 wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP;
3285 wol->wolopts |= WAKE_MAGIC;
3286 /*
3287 if (vptr->wol_opts & VELOCITY_WOL_PHY)
3288 wol.wolopts|=WAKE_PHY;
3289 */
3290 if (vptr->wol_opts & VELOCITY_WOL_UCAST)
3291 wol->wolopts |= WAKE_UCAST;
3292 if (vptr->wol_opts & VELOCITY_WOL_ARP)
3293 wol->wolopts |= WAKE_ARP;
3294 memcpy(&wol->sopass, vptr->wol_passwd, 6);
3295}
3296
3297static int velocity_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
3298{
Jeff Garzik8ab6f3f2006-06-27 08:56:23 -04003299 struct velocity_info *vptr = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
3301 if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP)))
3302 return -EFAULT;
3303 vptr->wol_opts = VELOCITY_WOL_MAGIC;
3304
3305 /*
3306 if (wol.wolopts & WAKE_PHY) {
3307 vptr->wol_opts|=VELOCITY_WOL_PHY;
3308 vptr->flags |=VELOCITY_FLAGS_WOL_ENABLED;
3309 }
3310 */
3311
3312 if (wol->wolopts & WAKE_MAGIC) {
3313 vptr->wol_opts |= VELOCITY_WOL_MAGIC;
3314 vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
3315 }
3316 if (wol->wolopts & WAKE_UCAST) {
3317 vptr->wol_opts |= VELOCITY_WOL_UCAST;
3318 vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
3319 }
3320 if (wol->wolopts & WAKE_ARP) {
3321 vptr->wol_opts |= VELOCITY_WOL_ARP;
3322 vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
3323 }
3324 memcpy(vptr->wol_passwd, wol->sopass, 6);
3325 return 0;
3326}
3327
3328static u32 velocity_get_msglevel(struct net_device *dev)
3329{
3330 return msglevel;
3331}
3332
3333static void velocity_set_msglevel(struct net_device *dev, u32 value)
3334{
3335 msglevel = value;
3336}
3337
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00003338static int get_pending_timer_val(int val)
3339{
3340 int mult_bits = val >> 6;
3341 int mult = 1;
3342
3343 switch (mult_bits)
3344 {
3345 case 1:
3346 mult = 4; break;
3347 case 2:
3348 mult = 16; break;
3349 case 3:
3350 mult = 64; break;
3351 case 0:
3352 default:
3353 break;
3354 }
3355
3356 return (val & 0x3f) * mult;
3357}
3358
3359static void set_pending_timer_val(int *val, u32 us)
3360{
3361 u8 mult = 0;
3362 u8 shift = 0;
3363
3364 if (us >= 0x3f) {
3365 mult = 1; /* mult with 4 */
3366 shift = 2;
3367 }
3368 if (us >= 0x3f * 4) {
3369 mult = 2; /* mult with 16 */
3370 shift = 4;
3371 }
3372 if (us >= 0x3f * 16) {
3373 mult = 3; /* mult with 64 */
3374 shift = 6;
3375 }
3376
3377 *val = (mult << 6) | ((us >> shift) & 0x3f);
3378}
3379
3380
3381static int velocity_get_coalesce(struct net_device *dev,
3382 struct ethtool_coalesce *ecmd)
3383{
3384 struct velocity_info *vptr = netdev_priv(dev);
3385
3386 ecmd->tx_max_coalesced_frames = vptr->options.tx_intsup;
3387 ecmd->rx_max_coalesced_frames = vptr->options.rx_intsup;
3388
3389 ecmd->rx_coalesce_usecs = get_pending_timer_val(vptr->options.rxqueue_timer);
3390 ecmd->tx_coalesce_usecs = get_pending_timer_val(vptr->options.txqueue_timer);
3391
3392 return 0;
3393}
3394
3395static int velocity_set_coalesce(struct net_device *dev,
3396 struct ethtool_coalesce *ecmd)
3397{
3398 struct velocity_info *vptr = netdev_priv(dev);
3399 int max_us = 0x3f * 64;
Simon Kagstrom39c2ff42010-02-09 23:38:07 +00003400 unsigned long flags;
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00003401
3402 /* 6 bits of */
3403 if (ecmd->tx_coalesce_usecs > max_us)
3404 return -EINVAL;
3405 if (ecmd->rx_coalesce_usecs > max_us)
3406 return -EINVAL;
3407
3408 if (ecmd->tx_max_coalesced_frames > 0xff)
3409 return -EINVAL;
3410 if (ecmd->rx_max_coalesced_frames > 0xff)
3411 return -EINVAL;
3412
3413 vptr->options.rx_intsup = ecmd->rx_max_coalesced_frames;
3414 vptr->options.tx_intsup = ecmd->tx_max_coalesced_frames;
3415
3416 set_pending_timer_val(&vptr->options.rxqueue_timer,
3417 ecmd->rx_coalesce_usecs);
3418 set_pending_timer_val(&vptr->options.txqueue_timer,
3419 ecmd->tx_coalesce_usecs);
3420
3421 /* Setup the interrupt suppression and queue timers */
Simon Kagstrom39c2ff42010-02-09 23:38:07 +00003422 spin_lock_irqsave(&vptr->lock, flags);
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00003423 mac_disable_int(vptr->mac_regs);
3424 setup_adaptive_interrupts(vptr);
3425 setup_queue_timers(vptr);
3426
3427 mac_write_int_mask(vptr->int_mask, vptr->mac_regs);
3428 mac_clear_isr(vptr->mac_regs);
3429 mac_enable_int(vptr->mac_regs);
Simon Kagstrom39c2ff42010-02-09 23:38:07 +00003430 spin_unlock_irqrestore(&vptr->lock, flags);
Simon Kagstrom6dfc4b92009-11-25 22:10:12 +00003431
3432 return 0;
3433}
3434
françois romieuad66fa72011-08-04 02:38:28 +00003435static const char velocity_gstrings[][ETH_GSTRING_LEN] = {
3436 "rx_all",
3437 "rx_ok",
3438 "tx_ok",
3439 "rx_error",
3440 "rx_runt_ok",
3441 "rx_runt_err",
3442 "rx_64",
3443 "tx_64",
3444 "rx_65_to_127",
3445 "tx_65_to_127",
3446 "rx_128_to_255",
3447 "tx_128_to_255",
3448 "rx_256_to_511",
3449 "tx_256_to_511",
3450 "rx_512_to_1023",
3451 "tx_512_to_1023",
3452 "rx_1024_to_1518",
3453 "tx_1024_to_1518",
3454 "tx_ether_collisions",
3455 "rx_crc_errors",
3456 "rx_jumbo",
3457 "tx_jumbo",
3458 "rx_mac_control_frames",
3459 "tx_mac_control_frames",
3460 "rx_frame_alignement_errors",
3461 "rx_long_ok",
3462 "rx_long_err",
3463 "tx_sqe_errors",
3464 "rx_no_buf",
3465 "rx_symbol_errors",
3466 "in_range_length_errors",
3467 "late_collisions"
3468};
3469
3470static void velocity_get_strings(struct net_device *dev, u32 sset, u8 *data)
3471{
3472 switch (sset) {
3473 case ETH_SS_STATS:
3474 memcpy(data, *velocity_gstrings, sizeof(velocity_gstrings));
3475 break;
3476 }
3477}
3478
3479static int velocity_get_sset_count(struct net_device *dev, int sset)
3480{
3481 switch (sset) {
3482 case ETH_SS_STATS:
3483 return ARRAY_SIZE(velocity_gstrings);
3484 default:
3485 return -EOPNOTSUPP;
3486 }
3487}
3488
3489static void velocity_get_ethtool_stats(struct net_device *dev,
3490 struct ethtool_stats *stats, u64 *data)
3491{
3492 if (netif_running(dev)) {
3493 struct velocity_info *vptr = netdev_priv(dev);
3494 u32 *p = vptr->mib_counter;
3495 int i;
3496
3497 spin_lock_irq(&vptr->lock);
3498 velocity_update_hw_mibs(vptr);
3499 spin_unlock_irq(&vptr->lock);
3500
3501 for (i = 0; i < ARRAY_SIZE(velocity_gstrings); i++)
3502 *data++ = *p++;
3503 }
3504}
3505
Jeff Garzik7282d492006-09-13 14:30:00 -04003506static const struct ethtool_ops velocity_ethtool_ops = {
françois romieu5ae297b2011-08-04 02:39:03 +00003507 .get_settings = velocity_get_settings,
3508 .set_settings = velocity_set_settings,
3509 .get_drvinfo = velocity_get_drvinfo,
3510 .get_wol = velocity_ethtool_get_wol,
3511 .set_wol = velocity_ethtool_set_wol,
3512 .get_msglevel = velocity_get_msglevel,
3513 .set_msglevel = velocity_set_msglevel,
3514 .get_link = velocity_get_link,
françois romieuad66fa72011-08-04 02:38:28 +00003515 .get_strings = velocity_get_strings,
3516 .get_sset_count = velocity_get_sset_count,
3517 .get_ethtool_stats = velocity_get_ethtool_stats,
françois romieu5ae297b2011-08-04 02:39:03 +00003518 .get_coalesce = velocity_get_coalesce,
3519 .set_coalesce = velocity_set_coalesce,
3520 .begin = velocity_ethtool_up,
3521 .complete = velocity_ethtool_down
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522};
3523
françois romieu5ae297b2011-08-04 02:39:03 +00003524#if defined(CONFIG_PM) && defined(CONFIG_INET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
3526{
françois romieu5ae297b2011-08-04 02:39:03 +00003527 struct in_ifaddr *ifa = ptr;
Denis V. Luneva3374992008-02-28 20:44:27 -08003528 struct net_device *dev = ifa->ifa_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529
Ben Hutchings516b4df2009-10-28 04:01:46 -07003530 if (dev_net(dev) == &init_net &&
3531 dev->netdev_ops == &velocity_netdev_ops)
3532 velocity_get_ip(netdev_priv(dev));
Denis V. Luneva3374992008-02-28 20:44:27 -08003533
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534 return NOTIFY_DONE;
3535}
Randy Dunlapce9f7fe2006-12-18 21:21:10 -08003536
Dave Jones2cf71d22009-07-23 18:11:12 -07003537static struct notifier_block velocity_inetaddr_notifier = {
françois romieu5ae297b2011-08-04 02:39:03 +00003538 .notifier_call = velocity_netdev_event,
Dave Jones2cf71d22009-07-23 18:11:12 -07003539};
3540
3541static void velocity_register_notifier(void)
3542{
3543 register_inetaddr_notifier(&velocity_inetaddr_notifier);
3544}
3545
3546static void velocity_unregister_notifier(void)
3547{
3548 unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
3549}
3550
3551#else
3552
3553#define velocity_register_notifier() do {} while (0)
3554#define velocity_unregister_notifier() do {} while (0)
3555
3556#endif /* defined(CONFIG_PM) && defined(CONFIG_INET) */
3557
3558/**
3559 * velocity_init_module - load time function
3560 *
3561 * Called when the velocity module is loaded. The PCI driver
3562 * is registered with the PCI layer, and in turn will call
3563 * the probe functions for each velocity adapter installed
3564 * in the system.
3565 */
3566static int __init velocity_init_module(void)
3567{
3568 int ret;
3569
3570 velocity_register_notifier();
3571 ret = pci_register_driver(&velocity_driver);
3572 if (ret < 0)
3573 velocity_unregister_notifier();
3574 return ret;
3575}
3576
3577/**
3578 * velocity_cleanup - module unload
3579 *
3580 * When the velocity hardware is unloaded this function is called.
3581 * It will clean up the notifiers and the unregister the PCI
3582 * driver interface for this hardware. This in turn cleans up
3583 * all discovered interfaces before returning from the function
3584 */
3585static void __exit velocity_cleanup_module(void)
3586{
3587 velocity_unregister_notifier();
3588 pci_unregister_driver(&velocity_driver);
3589}
3590
3591module_init(velocity_init_module);
3592module_exit(velocity_cleanup_module);