📄 acenic.c
字号:
/* * acenic.c: Linux driver for the Alteon AceNIC Gigabit Ethernet card * and other Tigon based cards. * * Copyright 1998-2002 by Jes Sorensen, <jes@trained-monkey.org>. * * Thanks to Alteon and 3Com for providing hardware and documentation * enabling me to write this driver. * * A mailing list for discussing the use of this driver has been * setup, please subscribe to the lists if you have any questions * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to * see how to subscribe. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Additional credits: * Pete Wyckoff <wyckoff@ca.sandia.gov>: Initial Linux/Alpha and trace * dump support. The trace dump support has not been * integrated yet however. * Troy Benjegerdes: Big Endian (PPC) patches. * Nate Stahl: Better out of memory handling and stats support. * Aman Singla: Nasty race between interrupt handler and tx code dealing * with 'testing the tx_ret_csm and setting tx_full' * David S. Miller <davem@redhat.com>: conversion to new PCI dma mapping * infrastructure and Sparc support * Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the * driver under Linux/Sparc64 * Matt Domsch <Matt_Domsch@dell.com>: Detect Alteon 1000baseT cards * ETHTOOL_GDRVINFO support * Chip Salzenberg <chip@valinux.com>: Fix race condition between tx * handler and close() cleanup. * Ken Aaker <kdaaker@rchland.vnet.ibm.com>: Correct check for whether * memory mapped IO is enabled to * make the driver work on RS/6000. * Takayoshi Kouchi <kouchi@hpc.bs1.fc.nec.co.jp>: Identifying problem * where the driver would disable * bus master mode if it had to disable * write and invalidate. * Stephen Hack <stephen_hack@hp.com>: Fixed ace_set_mac_addr for little * endian systems. * Val Henson <vhenson@esscom.com>: Reset Jumbo skb producer and * rx producer index when * flushing the Jumbo ring. * Hans Grobler <grobh@sun.ac.za>: Memory leak fixes in the * driver init path. * Grant Grundler <grundler@cup.hp.com>: PCI write posting fixes. */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/version.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/pci.h>#include <linux/dma-mapping.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/mm.h>#include <linux/highmem.h>#include <linux/sockios.h>#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)#include <linux/if_vlan.h>#endif#ifdef SIOCETHTOOL#include <linux/ethtool.h>#endif#include <net/sock.h>#include <net/ip.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/byteorder.h>#include <asm/uaccess.h>#define DRV_NAME "acenic"#undef INDEX_DEBUG#ifdef CONFIG_ACENIC_OMIT_TIGON_I#define ACE_IS_TIGON_I(ap) 0#define ACE_TX_RING_ENTRIES(ap) MAX_TX_RING_ENTRIES#else#define ACE_IS_TIGON_I(ap) (ap->version == 1)#define ACE_TX_RING_ENTRIES(ap) ap->tx_ring_entries#endif#ifndef PCI_VENDOR_ID_ALTEON#define PCI_VENDOR_ID_ALTEON 0x12ae#endif#ifndef PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE#define PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE 0x0001#define PCI_DEVICE_ID_ALTEON_ACENIC_COPPER 0x0002#endif#ifndef PCI_DEVICE_ID_3COM_3C985#define PCI_DEVICE_ID_3COM_3C985 0x0001#endif#ifndef PCI_VENDOR_ID_NETGEAR#define PCI_VENDOR_ID_NETGEAR 0x1385#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a#endif#ifndef PCI_DEVICE_ID_NETGEAR_GA620T#define PCI_DEVICE_ID_NETGEAR_GA620T 0x630a#endif/* * Farallon used the DEC vendor ID by mistake and they seem not * to care - stinky! */#ifndef PCI_DEVICE_ID_FARALLON_PN9000SX#define PCI_DEVICE_ID_FARALLON_PN9000SX 0x1a#endif#ifndef PCI_DEVICE_ID_FARALLON_PN9100T#define PCI_DEVICE_ID_FARALLON_PN9100T 0xfa#endif#ifndef PCI_VENDOR_ID_SGI#define PCI_VENDOR_ID_SGI 0x10a9#endif#ifndef PCI_DEVICE_ID_SGI_ACENIC#define PCI_DEVICE_ID_SGI_ACENIC 0x0009#endifstatic struct pci_device_id acenic_pci_tbl[] = { { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C985, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_NETGEAR, PCI_DEVICE_ID_NETGEAR_GA620T, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, /* * Farallon used the DEC vendor ID on their cards incorrectly, * then later Alteon's ID. */ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_FARALLON_PN9000SX, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_FARALLON_PN9100T, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_ACENIC, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { }};MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);#define ace_sync_irq(irq) synchronize_irq(irq)#ifndef offset_in_page#define offset_in_page(ptr) ((unsigned long)(ptr) & ~PAGE_MASK)#endif#define ACE_MAX_MOD_PARMS 8#define BOARD_IDX_STATIC 0#define BOARD_IDX_OVERFLOW -1#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \ defined(NETIF_F_HW_VLAN_RX)#define ACENIC_DO_VLAN 1#define ACE_RCB_VLAN_FLAG RCB_FLG_VLAN_ASSIST#else#define ACENIC_DO_VLAN 0#define ACE_RCB_VLAN_FLAG 0#endif#include "acenic.h"/* * These must be defined before the firmware is included. */#define MAX_TEXT_LEN 96*1024#define MAX_RODATA_LEN 8*1024#define MAX_DATA_LEN 2*1024#include "acenic_firmware.h"#ifndef tigon2FwReleaseLocal#define tigon2FwReleaseLocal 0#endif/* * This driver currently supports Tigon I and Tigon II based cards * including the Alteon AceNIC, the 3Com 3C985[B] and NetGear * GA620. The driver should also work on the SGI, DEC and Farallon * versions of the card, however I have not been able to test that * myself. * * This card is really neat, it supports receive hardware checksumming * and jumbo frames (up to 9000 bytes) and does a lot of work in the * firmware. Also the programming interface is quite neat, except for * the parts dealing with the i2c eeprom on the card ;-) * * Using jumbo frames: * * To enable jumbo frames, simply specify an mtu between 1500 and 9000 * bytes to ifconfig. Jumbo frames can be enabled or disabled at any time * by running `ifconfig eth<X> mtu <MTU>' with <X> being the Ethernet * interface number and <MTU> being the MTU value. * * Module parameters: * * When compiled as a loadable module, the driver allows for a number * of module parameters to be specified. The driver supports the * following module parameters: * * trace=<val> - Firmware trace level. This requires special traced * firmware to replace the firmware supplied with * the driver - for debugging purposes only. * * link=<val> - Link state. Normally you want to use the default link * parameters set by the driver. This can be used to * override these in case your switch doesn't negotiate * the link properly. Valid values are: * 0x0001 - Force half duplex link. * 0x0002 - Do not negotiate line speed with the other end. * 0x0010 - 10Mbit/sec link. * 0x0020 - 100Mbit/sec link. * 0x0040 - 1000Mbit/sec link. * 0x0100 - Do not negotiate flow control. * 0x0200 - Enable RX flow control Y * 0x0400 - Enable TX flow control Y (Tigon II NICs only). * Default value is 0x0270, ie. enable link+flow * control negotiation. Negotiating the highest * possible link speed with RX flow control enabled. * * When disabling link speed negotiation, only one link * speed is allowed to be specified! * * tx_coal_tick=<val> - number of coalescing clock ticks (us) allowed * to wait for more packets to arive before * interrupting the host, from the time the first * packet arrives. * * rx_coal_tick=<val> - number of coalescing clock ticks (us) allowed * to wait for more packets to arive in the transmit ring, * before interrupting the host, after transmitting the * first packet in the ring. * * max_tx_desc=<val> - maximum number of transmit descriptors * (packets) transmitted before interrupting the host. * * max_rx_desc=<val> - maximum number of receive descriptors * (packets) received before interrupting the host. * * tx_ratio=<val> - 7 bit value (0 - 63) specifying the split in 64th * increments of the NIC's on board memory to be used for * transmit and receive buffers. For the 1MB NIC app. 800KB * is available, on the 1/2MB NIC app. 300KB is available. * 68KB will always be available as a minimum for both * directions. The default value is a 50/50 split. * dis_pci_mem_inval=<val> - disable PCI memory write and invalidate * operations, default (1) is to always disable this as * that is what Alteon does on NT. I have not been able * to measure any real performance differences with * this on my systems. Set <val>=0 if you want to * enable these operations. * * If you use more than one NIC, specify the parameters for the * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to * run tracing on NIC #2 but not on NIC #1 and #3. * * TODO: * * - Proper multicast support. * - NIC dump support. * - More tuning parameters. * * The mini ring is not used under Linux and I am not sure it makes sense * to actually use it. * * New interrupt handler strategy: * * The old interrupt handler worked using the traditional method of * replacing an skbuff with a new one when a packet arrives. However * the rx rings do not need to contain a static number of buffer * descriptors, thus it makes sense to move the memory allocation out * of the main interrupt handler and do it in a bottom half handler * and only allocate new buffers when the number of buffers in the * ring is below a certain threshold. In order to avoid starving the * NIC under heavy load it is however necessary to force allocation * when hitting a minimum threshold. The strategy for alloction is as * follows: * * RX_LOW_BUF_THRES - allocate buffers in the bottom half * RX_PANIC_LOW_THRES - we are very low on buffers, allocate * the buffers in the interrupt handler * RX_RING_THRES - maximum number of buffers in the rx ring * RX_MINI_THRES - maximum number of buffers in the mini ring * RX_JUMBO_THRES - maximum number of buffers in the jumbo ring * * One advantagous side effect of this allocation approach is that the * entire rx processing can be done without holding any spin lock * since the rx rings and registers are totally independent of the tx * ring and its registers. This of course includes the kmalloc's of * new skb's. Thus start_xmit can run in parallel with rx processing * and the memory allocation on SMP systems. * * Note that running the skb reallocation in a bottom half opens up * another can of races which needs to be handled properly. In * particular it can happen that the interrupt handler tries to run * the reallocation while the bottom half is either running on another * CPU or was interrupted on the same CPU. To get around this the * driver uses bitops to prevent the reallocation routines from being * reentered. * * TX handling can also be done without holding any spin lock, wheee * this is fun! since tx_ret_csm is only written to by the interrupt * handler. The case to be aware of is when shutting down the device * and cleaning up where it is necessary to make sure that * start_xmit() is not running while this is happening. Well DaveM * informs me that this case is already protected against ... bye bye * Mr. Spin Lock, it was nice to know you. * * TX interrupts are now partly disabled so the NIC will only generate * TX interrupts for the number of coal ticks, not for the number of * TX packets in the queue. This should reduce the number of TX only, * ie. when no RX processing is done, interrupts seen. *//* * Threshold values for RX buffer allocation - the low water marks for * when to start refilling the rings are set to 75% of the ring * sizes. It seems to make sense to refill the rings entirely from the * intrrupt handler once it gets below the panic threshold, that way * we don't risk that the refilling is moved to another CPU when the * one running the interrupt handler just got the slab code hot in its * cache. */#define RX_RING_SIZE 72#define RX_MINI_SIZE 64#define RX_JUMBO_SIZE 48#define RX_PANIC_STD_THRES 16#define RX_PANIC_STD_REFILL (3*RX_PANIC_STD_THRES)/2#define RX_LOW_STD_THRES (3*RX_RING_SIZE)/4#define RX_PANIC_MINI_THRES 12#define RX_PANIC_MINI_REFILL (3*RX_PANIC_MINI_THRES)/2#define RX_LOW_MINI_THRES (3*RX_MINI_SIZE)/4#define RX_PANIC_JUMBO_THRES 6#define RX_PANIC_JUMBO_REFILL (3*RX_PANIC_JUMBO_THRES)/2#define RX_LOW_JUMBO_THRES (3*RX_JUMBO_SIZE)/4/* * Size of the mini ring entries, basically these just should be big * enough to take TCP ACKs */#define ACE_MINI_SIZE 100#define ACE_MINI_BUFSIZE ACE_MINI_SIZE#define ACE_STD_BUFSIZE (ACE_STD_MTU + ETH_HLEN + 4)#define ACE_JUMBO_BUFSIZE (ACE_JUMBO_MTU + ETH_HLEN + 4)/* * There seems to be a magic difference in the effect between 995 and 996 * but little difference between 900 and 995 ... no idea why. * * There is now a default set of tuning parameters which is set, depending * on whether or not the user enables Jumbo frames. It's assumed that if * Jumbo frames are enabled, the user wants optimal tuning for that case. */#define DEF_TX_COAL 400 /* 996 */#define DEF_TX_MAX_DESC 60 /* was 40 */#define DEF_RX_COAL 120 /* 1000 */#define DEF_RX_MAX_DESC 25#define DEF_TX_RATIO 21 /* 24 */#define DEF_JUMBO_TX_COAL 20#define DEF_JUMBO_TX_MAX_DESC 60#define DEF_JUMBO_RX_COAL 30#define DEF_JUMBO_RX_MAX_DESC 6#define DEF_JUMBO_TX_RATIO 21#if tigon2FwReleaseLocal < 20001118/* * Standard firmware and early modifications duplicate * IRQ load without this flag (coal timer is never reset). * Note that with this flag tx_coal should be less than * time to xmit full tx ring. * 400usec is not so bad for tx ring size of 128. */#define TX_COAL_INTS_ONLY 1 /* worth it */#else/* * With modified firmware, this is not necessary, but still useful. */#define TX_COAL_INTS_ONLY 1#endif#define DEF_TRACE 0#define DEF_STAT (2 * TICKS_PER_SEC)static int link_state[ACE_MAX_MOD_PARMS];static int trace[ACE_MAX_MOD_PARMS];static int tx_coal_tick[ACE_MAX_MOD_PARMS];static int rx_coal_tick[ACE_MAX_MOD_PARMS];static int max_tx_desc[ACE_MAX_MOD_PARMS];static int max_rx_desc[ACE_MAX_MOD_PARMS];static int tx_ratio[ACE_MAX_MOD_PARMS];static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");module_param_array_named(link, link_state, int, NULL, 0);module_param_array(trace, int, NULL, 0);module_param_array(tx_coal_tick, int, NULL, 0);module_param_array(max_tx_desc, int, NULL, 0);module_param_array(rx_coal_tick, int, NULL, 0);module_param_array(max_rx_desc, int, NULL, 0);module_param_array(tx_ratio, int, NULL, 0);MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait");MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives");MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait");MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");static char version[] __devinitdata = "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n";static int ace_get_settings(struct net_device *, struct ethtool_cmd *);static int ace_set_settings(struct net_device *, struct ethtool_cmd *);static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);static const struct ethtool_ops ace_ethtool_ops = { .get_settings = ace_get_settings, .set_settings = ace_set_settings, .get_drvinfo = ace_get_drvinfo,};static void ace_watchdog(struct net_device *dev);static int __devinit acenic_probe_one(struct pci_dev *pdev, const struct pci_device_id *id){ struct net_device *dev; struct ace_private *ap; static int boards_found; dev = alloc_etherdev(sizeof(struct ace_private));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -