Commit d2f797b0 authored by Ganesh Venkatesan's avatar Ganesh Venkatesan Committed by Jeff Garzik

[netdrvr ixgb] add new driver for Intel's 10 gig ethernet

parent 70e09b6b
Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters
================================================================
January 06, 2003
Contents
========
- In This Release
- Supported Adapters
- Command Line Parameters
- Improving Performance
- Support
In This Release
===============
This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family
of Adapters, version 1.0.x. This driver is intended for 2.4.x kernels; it is
known to build properly on 2.4.x kernels through 2.4.18. Intel focused
testing on Intel architectures running kernels 2.4.18. This driver includes
support for Itanium(TM)-based systems.
For questions related to hardware requirements, refer to the documentation
supplied with your Intel PRO/10GbE adapter. All hardware requirements listed
apply to use with Linux.
Supported Adapters
==================
The following Intel network adapters are compatible with the drivers in this
release:
Controller Adapter Name Board IDs
---------- ------------ ---------
82597EX Intel(R) PRO/10GbE LR Server Adapter A82505-xxx
To verify your Intel adapter is supported, find the board ID number on the
adapter. Look for a label that has a barcode and a number in the format
A12345-001. Match this to the list of numbers above.
For more information on how to identify your adapter, go to the Adapter &
Driver ID Guide at:
http://support.intel.com/support/network/adapter/pro100/21397.htm
For the latest Intel network drivers for Linux, go to:
http://downloadfinder.intel.com/scripts-df/support_intel.asp
Command Line Parameters
=======================
If the driver is built as a module, the following optional parameters are
used by entering them on the command line with the modprobe or insmod command
using this syntax:
modprobe ixgb [<option>=<VAL1>,<VAL2>,...]
insmod ixgb [<option>=<VAL1>,<VAL2>,...]
For example, with two PRO/10GbE PCI adapters, entering:
insmod ixgb TxDescriptors=80,128
loads the ixgb driver with 80 TX resources for the first adapter and 128 TX
resources for the second adapter.
The default value for each parameter is generally the recommended setting,
unless otherwise noted.
FlowControl
Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
Default: Read from the EEPROM
If EEPROM is not detected, default is 3
This parameter controls the automatic generation(Tx) and response(Rx) to
Ethernet PAUSE frames.
RxDescriptors
Valid Range: 64-4096
Default Value: 1024
This value is the number of receive descriptors allocated by the driver.
Increasing this value allows the driver to buffer more incoming packets.
Each descriptor is 16 bytes. A receive buffer is also allocated for
each descriptor and can be either 2048, 4056, 8192, or 16384 bytes,
depending on the MTU setting. When the MTU size is 1500 or less, the
receive buffer size is 2048 bytes. When the MTU is greater than 1500 the
receive buffer size will be either 4056, 8192, or 16384 bytes. The
maximum MTU size is 16114.
RxIntDelay
Valid Range: 0-65535 (0=off)
Default Value: 6
This value delays the generation of receive interrupts in units of
0.8192 microseconds. Receive interrupt reduction can improve CPU
efficiency if properly tuned for specific network traffic. Increasing
this value adds extra latency to frame reception and can end up
decreasing the throughput of TCP traffic. If the system is reporting
dropped receives, this value may be set too high, causing the driver to
run out of available receive descriptors.
TxDescriptors
Valid Range: 64-4096
Default Value: 256
This value is the number of transmit descriptors allocated by the driver.
Increasing this value allows the driver to queue more transmits. Each
descriptor is 16 bytes.
XsumRX
Valid Range: 0-1
Default Value: 1
A value of '1' indicates that the driver should enable IP checksum
offload for received packets (both UDP and TCP) to the adapter hardware.
XsumTX
Valid Range: 0-1
Default Value: 1
A value of '1' indicates that the driver should enable IP checksum
offload for transmitted packets (both UDP and TCP) to the adapter
hardware.
Improving Performance
=====================
With the Intel PRO/10 GbE adapter, the default Linux configuration will very
likely limit the total available throughput artificially. There is a set of
things that when applied together increase the ability of Linux to transmit
and receive data. The following enhancements were originally acquired from
settings published at http://www.spec.org/web99 for various submitted results
using Linux.
NOTE: These changes are only suggestions, and serve as a starting point for
tuning your network performance.
The changes are made in three major ways, listed in order of greatest effect:
- Use ifconfig to modify the mtu (maximum transmission unit) and the txqueuelen
parameter.
- Use sysctl to modify /proc parameters (essentially kernel tuning)
- Use setpci to modify the MMRBC field in PCI-X configuration space to increase
transmit burst lengths on the bus.
NOTE: setpci modifies the adapter's configuration registers to allow it to read
up to 4k bytes at a time (for transmits). However, for some systems the
behavior after modifying this register may be undefined (possibly errors of some
kind). A power-cycle, hard reset or explicitly setting the e6 register back to
22 (setpci -d 8086:1048 e6.b=22) may be required to get back to a stable
configuration.
- COPY these lines and paste them into ixgb_perf.sh:
#!/bin/bash
echo "configuring network performance , edit this file to change the interface"
# set mmrbc to 4k reads, modify only Intel 10GbE device IDs
setpci -d 8086:1048 e6.b=2e
# set the MTU (max transmission unit) - it requires your switch and clients to change too!
# set the txqueuelen
# your ixgb adapter should be loaded as eth1 for this to work, change if needed
ifconfig eth1 mtu 9000 txqueuelen 1000 up
# call the sysctl utility to modify /proc/sys entries
sysctl -p ./sysctl_ixgb.conf
- END ixgb_perf.sh
- COPY these lines and paste them into sysctl_ixgb.conf:
# some of the defaults may be different for your kernel
# call this file with sysctl -p <this file>
# these are just suggested values that worked well to increase throughput in
# several network benchmark tests, your mileage may vary
### IPV4 specific settings
net.ipv4.tcp_timestamps = 0 # turns TCP timestamp support off, default 1, reduces CPU use
net.ipv4.tcp_sack = 0 # turn SACK support off, default on
# on systems with a VERY fast bus -> memory interface this is the big gainer
net.ipv4.tcp_rmem = 10000000 10000000 10000000 # sets min/default/max TCP read buffer, default 4096 87380 174760
net.ipv4.tcp_wmem = 10000000 10000000 10000000 # sets min/pressure/max TCP write buffer, default 4096 16384 131072
net.ipv4.tcp_mem = 10000000 10000000 10000000 # sets min/pressure/max TCP buffer space, default 31744 32256 32768
### CORE settings (mostly for socket and UDP effect)
net.core.rmem_max = 524287 # maximum receive socket buffer size, default 131071
net.core.wmem_max = 524287 # maximum send socket buffer size, default 131071
net.core.rmem_default = 524287 # default receive socket buffer size, default 65535
net.core.wmem_default = 524287 # default send socket buffer size, default 65535
net.core.optmem_max = 524287 # maximum amount of option memory buffers, default 10240
net.core.netdev_max_backlog = 300000 # number of unprocessed input packets before kernel starts dropping them, default 300
- END sysctl_ixgb.conf
Edit the ixgb_perf.sh script if necessary to change eth1 to whatever interface
your ixgb driver is using.
NOTE: Unless these scripts are added to the boot process, these changes will
only last only until the next system reboot.
Resolving Slow UDP Traffic
--------------------------
If your server does not seem to be able to receive UDP traffic as fast as it
can receive TCP traffic, it could be because Linux, by default, does not set
the network stack buffers as large as they need to be to support high UDP
transfer rates. One way to alleviate this problem is to allow more memory to
be used by the IP stack to store incoming data.
For instance, use the commands:
sysctl -w net.core.rmem_max=262143
and
sysctl -w net.core.rmem_default=262143
to increase the read buffer memory max and default to 262143 (256k - 1) from
defaults of max=131071 (128k - 1) and default=65535 (64k - 1). These variables
will increase the amount of memory used by the network stack for receives, and
can be increased significantly more if necessary for your application.
Support
=======
For general information and support, go to the Intel support website at:
http://support.intel.com
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related to
the issue to linux.nics@intel.com.
......@@ -943,6 +943,13 @@ M: scott.feldman@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported
INTEL PRO/10GbE SUPPORT
P: Ganesh Venkatesan
M: Ganesh.Venkatesan@intel.com
P: Scott Feldman
M: scott.feldman@intel.com
S: Supported
INTERMEZZO FILE SYSTEM
P: Chen Yang
M: intermezzo-devel@lists.sf.net
......
......@@ -2085,6 +2085,50 @@ config TIGON3
endmenu
#
# 10 Gigabit Ethernet
#
menu "Ethernet (10000 Mbit)"
depends on NETDEVICES
config IXGB
tristate "Intel(R) PRO/10GbE support"
depends on PCI
---help---
This driver supports Intel(R) PRO/10GbE family of
adapters, which includes:
Controller Adapter Name Board IDs
---------- ------------ ---------
82597EX Intel(R) PRO/10GbE LR Server Adapter A82505-xxx
For more information on how to identify your adapter, go to the
Adapter & Driver ID Guide at:
<http://support.intel.com/support/network/adapter/pro100/21397.htm>
For general information and support, go to the Intel support
website at:
<http://support.intel.com>
More specific information on configuring the driver is in
<file:Documentation/networking/ixgb.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ixgb. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/networking/net-modules.txt>.
config IXGB_NAPI
bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
depends on IXGB && EXPERIMENTAL
endmenu
config VETH
tristate "iSeries Virtual Ethernet driver support"
depends on NETDEVICES && PPC_ISERIES
......
......@@ -10,6 +10,7 @@ endif
obj-$(CONFIG_E100) += e100/
obj-$(CONFIG_E1000) += e1000/
obj-$(CONFIG_IXGB) += ixgb/
#
# link order important here
......
################################################################################
#
#
# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
#
# 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.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# The full GNU General Public License is included in this distribution in the
# file called LICENSE.
#
# Contact Information:
# Linux NICS <linux.nics@intel.com>
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
#
################################################################################
#
# Makefile for the Intel(R) PRO/10GbE driver
#
obj-$(CONFIG_IXGB) += ixgb.o
ixgb-objs := ixgb_main.o ixgb_hw.o ixgb_ee.o ixgb_ethtool.o ixgb_param.o
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGB_H_
#define _IXGB_H_
#include <linux/stddef.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/pagemap.h>
#include <linux/bitops.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <net/pkt_sched.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <linux/reboot.h>
#ifdef NETIF_F_TSO
#include <net/checksum.h>
#endif
/* ethtool support */
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
struct ixgb_adapter;
#define BAR_0 0
#define BAR_1 1
#define BAR_5 5
#define PCI_DMA_64BIT 0xffffffffffffffffULL
#define PCI_DMA_32BIT 0x00000000ffffffffULL
#include "ixgb_hw.h"
#include "ixgb_ee.h"
#include "ixgb_ids.h"
#if _DEBUG_DRIVER_
#define IXGB_DBG(args...) printk(KERN_DEBUG "ixgb: " args)
#else
#define IXGB_DBG(args...)
#endif
#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
/* Supported Rx Buffer Sizes */
#define IXGB_RXBUFFER_2048 2048
#define IXGB_RXBUFFER_4096 4096
#define IXGB_RXBUFFER_8192 8192
#define IXGB_RXBUFFER_16384 16384
/* How many Tx Descriptors do we need to call netif_wake_queue? */
#define IXGB_TX_QUEUE_WAKE 16
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IXGB_RX_BUFFER_WRITE 16
/* only works for sizes that are powers of 2 */
#define IXGB_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct ixgb_buffer {
struct sk_buff *skb;
uint64_t dma;
unsigned long length;
unsigned long time_stamp;
};
struct ixgb_desc_ring {
/* pointer to the descriptor ring memory */
void *desc;
/* physical address of the descriptor ring */
dma_addr_t dma;
/* length of descriptor ring in bytes */
unsigned int size;
/* number of descriptors in the ring */
unsigned int count;
/* next descriptor to associate a buffer with */
unsigned int next_to_use;
/* next descriptor to check for DD status bit */
unsigned int next_to_clean;
/* array of buffer information structs */
struct ixgb_buffer *buffer_info;
};
#define IXGB_DESC_UNUSED(R) \
((((R)->next_to_clean + (R)->count) - ((R)->next_to_use + 1)) % ((R)->count))
#define IXGB_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
#define IXGB_RX_DESC(R, i) IXGB_GET_DESC(R, i, ixgb_rx_desc)
#define IXGB_TX_DESC(R, i) IXGB_GET_DESC(R, i, ixgb_tx_desc)
#define IXGB_CONTEXT_DESC(R, i) IXGB_GET_DESC(R, i, ixgb_context_desc)
/* board specific private data structure */
struct ixgb_adapter {
struct timer_list watchdog_timer;
struct vlan_group *vlgrp;
char *id_string;
uint32_t bd_number;
uint32_t rx_buffer_len;
uint32_t part_num;
uint16_t link_speed;
uint16_t link_duplex;
atomic_t irq_sem;
struct work_struct tx_timeout_task;
#ifdef ETHTOOL_PHYS_ID
struct timer_list blink_timer;
unsigned long led_status;
#endif
#ifdef _INTERNAL_LOOPBACK_DRIVER_
struct ixgb_desc_ring diag_tx_ring;
struct ixgb_desc_ring diag_rx_ring;
#endif
/* TX */
struct ixgb_desc_ring tx_ring;
unsigned long timeo_start;
uint32_t tx_cmd_type;
int max_data_per_txd;
uint64_t hw_csum_tx_good;
uint64_t hw_csum_tx_error;
boolean_t tx_csum;
uint32_t tx_int_delay;
boolean_t tx_int_delay_enable;
/* RX */
struct ixgb_desc_ring rx_ring;
uint64_t hw_csum_rx_error;
uint64_t hw_csum_rx_good;
uint32_t rx_int_delay;
boolean_t raidc;
boolean_t rx_csum;
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
struct net_device_stats net_stats;
/* structs defined in ixgb_hw.h */
struct ixgb_hw hw;
struct ixgb_hw_stats stats;
uint32_t pci_state[16];
char ifname[IFNAMSIZ];
};
#endif /* _IXGB_H_ */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "ixgb_hw.h"
#include "ixgb_ee.h"
/* Local prototypes */
static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
static void ixgb_shift_out_bits(struct ixgb_hw *hw,
uint16_t data,
uint16_t count);
static void ixgb_standby_eeprom(struct ixgb_hw *hw);
static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
/******************************************************************************
* Raises the EEPROM's clock input.
*
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
static void
ixgb_raise_clock(struct ixgb_hw *hw,
uint32_t *eecd_reg)
{
/* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait 50 microseconds.
*/
*eecd_reg = *eecd_reg | IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, *eecd_reg);
usec_delay(50);
return;
}
/******************************************************************************
* Lowers the EEPROM's clock input.
*
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
static void
ixgb_lower_clock(struct ixgb_hw *hw,
uint32_t *eecd_reg)
{
/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
* wait 50 microseconds.
*/
*eecd_reg = *eecd_reg & ~IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, *eecd_reg);
usec_delay(50);
return;
}
/******************************************************************************
* Shift data bits out to the EEPROM.
*
* hw - Struct containing variables accessed by shared code
* data - data to send to the EEPROM
* count - number of bits to shift out
*****************************************************************************/
static void
ixgb_shift_out_bits(struct ixgb_hw *hw,
uint16_t data,
uint16_t count)
{
uint32_t eecd_reg;
uint32_t mask;
/* We need to shift "count" bits out to the EEPROM. So, value in the
* "data" parameter will be shifted out to the EEPROM one bit at a time.
* In order to do this, "data" must be broken down into bits.
*/
mask = 0x01 << (count - 1);
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
do {
/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
* and then raising and then lowering the clock (the SK bit controls
* the clock input to the EEPROM). A "0" is shifted out to the EEPROM
* by setting "DI" to "0" and then raising and then lowering the clock.
*/
eecd_reg &= ~IXGB_EECD_DI;
if(data & mask)
eecd_reg |= IXGB_EECD_DI;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
ixgb_raise_clock(hw, &eecd_reg);
ixgb_lower_clock(hw, &eecd_reg);
mask = mask >> 1;
} while(mask);
/* We leave the "DI" bit set to "0" when we leave this routine. */
eecd_reg &= ~IXGB_EECD_DI;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
return;
}
/******************************************************************************
* Shift data bits in from the EEPROM
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static uint16_t
ixgb_shift_in_bits(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
uint16_t data;
/* In order to read a register from the EEPROM, we need to shift 16 bits
* in from the EEPROM. Bits are "shifted in" by raising the clock input to
* the EEPROM (setting the SK bit), and then reading the value of the "DO"
* bit. During this "shifting in" process the "DI" bit should always be
* clear..
*/
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
data = 0;
for(i = 0; i < 16; i++) {
data = data << 1;
ixgb_raise_clock(hw, &eecd_reg);
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_DI);
if(eecd_reg & IXGB_EECD_DO)
data |= 1;
ixgb_lower_clock(hw, &eecd_reg);
}
return data;
}
/******************************************************************************
* Prepares EEPROM for access
*
* hw - Struct containing variables accessed by shared code
*
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM.
*****************************************************************************/
static void
ixgb_setup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
eecd_reg = IXGB_READ_REG(hw, EECD);
/* Clear SK and DI */
eecd_reg &= ~(IXGB_EECD_SK | IXGB_EECD_DI);
IXGB_WRITE_REG(hw, EECD, eecd_reg);
/* Set CS */
eecd_reg |= IXGB_EECD_CS;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
return;
}
/******************************************************************************
* Returns EEPROM to a "standby" state
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static void
ixgb_standby_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
eecd_reg = IXGB_READ_REG(hw, EECD);
/* Deselct EEPROM */
eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_SK);
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
/* Clock high */
eecd_reg |= IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
/* Select EEPROM */
eecd_reg |= IXGB_EECD_CS;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
/* Clock low */
eecd_reg &= ~IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
return;
}
/******************************************************************************
* Raises then lowers the EEPROM's clock pin
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static void
ixgb_clock_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
eecd_reg = IXGB_READ_REG(hw, EECD);
/* Rising edge of clock */
eecd_reg |= IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
/* Falling edge of clock */
eecd_reg &= ~IXGB_EECD_SK;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
usec_delay(50);
return;
}
/******************************************************************************
* Terminates a command by lowering the EEPROM's chip select pin
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static void
ixgb_cleanup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_DI);
IXGB_WRITE_REG(hw, EECD, eecd_reg);
ixgb_clock_eeprom(hw);
return;
}
/******************************************************************************
* Waits for the EEPROM to finish the current command.
*
* hw - Struct containing variables accessed by shared code
*
* The command is done when the EEPROM's data out pin goes high.
*
* Returns:
* TRUE: EEPROM data pin is high before timeout.
* FALSE: Time expired.
*****************************************************************************/
static boolean_t
ixgb_wait_eeprom_command(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
/* Toggle the CS line. This in effect tells to EEPROM to actually execute
* the command in question.
*/
ixgb_standby_eeprom(hw);
/* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will
* signal that the command has been completed by raising the DO signal.
* If DO does not go high in 10 milliseconds, then error out.
*/
for(i = 0; i < 200; i++) {
eecd_reg = IXGB_READ_REG(hw, EECD);
if(eecd_reg & IXGB_EECD_DO)
return (TRUE);
usec_delay(50);
}
ASSERT(0);
return (FALSE);
}
/******************************************************************************
* Verifies that the EEPROM has a valid checksum
*
* hw - Struct containing variables accessed by shared code
*
* Reads the first 64 16 bit words of the EEPROM and sums the values read.
* If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
* valid.
*
* Returns:
* TRUE: Checksum is valid
* FALSE: Checksum is not valid.
*****************************************************************************/
boolean_t
ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
checksum += ixgb_read_eeprom(hw, i);
if(checksum == (uint16_t) EEPROM_SUM)
return (TRUE);
else
return (FALSE);
}
/******************************************************************************
* Calculates the EEPROM checksum and writes it to the EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
* Writes the difference to word offset 63 of the EEPROM.
*****************************************************************************/
void
ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
checksum += ixgb_read_eeprom(hw, i);
checksum = (uint16_t) EEPROM_SUM - checksum;
ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum);
return;
}
/******************************************************************************
* Writes a 16 bit word to a given offset in the EEPROM.
*
* hw - Struct containing variables accessed by shared code
* reg - offset within the EEPROM to be written to
* data - 16 bit word to be writen to the EEPROM
*
* If ixgb_update_eeprom_checksum is not called after this function, the
* EEPROM will most likely contain an invalid checksum.
*
*****************************************************************************/
void
ixgb_write_eeprom(struct ixgb_hw *hw,
uint16_t offset,
uint16_t data)
{
/* Prepare the EEPROM for writing */
ixgb_setup_eeprom(hw);
/* Send the 9-bit EWEN (write enable) command to the EEPROM (5-bit opcode
* plus 4-bit dummy). This puts the EEPROM into write/erase mode.
*/
ixgb_shift_out_bits(hw, EEPROM_EWEN_OPCODE, 5);
ixgb_shift_out_bits(hw, 0, 4);
/* Prepare the EEPROM */
ixgb_standby_eeprom(hw);
/* Send the Write command (3-bit opcode + 6-bit addr) */
ixgb_shift_out_bits(hw, EEPROM_WRITE_OPCODE, 3);
ixgb_shift_out_bits(hw, offset, 6);
/* Send the data */
ixgb_shift_out_bits(hw, data, 16);
ixgb_wait_eeprom_command(hw);
/* Recover from write */
ixgb_standby_eeprom(hw);
/* Send the 9-bit EWDS (write disable) command to the EEPROM (5-bit
* opcode plus 4-bit dummy). This takes the EEPROM out of write/erase
* mode.
*/
ixgb_shift_out_bits(hw, EEPROM_EWDS_OPCODE, 5);
ixgb_shift_out_bits(hw, 0, 4);
/* Done with writing */
ixgb_cleanup_eeprom(hw);
return;
}
/******************************************************************************
* Reads a 16 bit word from the EEPROM.
*
* hw - Struct containing variables accessed by shared code
* offset - offset of 16 bit word in the EEPROM to read
*
* Returns:
* The 16-bit value read from the eeprom
*****************************************************************************/
uint16_t
ixgb_read_eeprom(struct ixgb_hw *hw,
uint16_t offset)
{
uint16_t data;
/* Prepare the EEPROM for reading */
ixgb_setup_eeprom(hw);
/* Send the READ command (opcode + addr) */
ixgb_shift_out_bits(hw, EEPROM_READ_OPCODE, 3);
/*
* We have a 64 word EEPROM, there are 6 address bits
*/
ixgb_shift_out_bits(hw, offset, 6);
/* Read the data */
data = ixgb_shift_in_bits(hw);
/* End this read operation */
ixgb_standby_eeprom(hw);
return (data);
}
/******************************************************************************
* Reads eeprom and stores data in shared structure.
* Validates eeprom checksum and eeprom signature.
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* TRUE: if eeprom read is successful
* FALSE: otherwise.
*****************************************************************************/
boolean_t
ixgb_get_eeprom_data(struct ixgb_hw *hw)
{
uint16_t i;
uint16_t checksum = 0;
struct ixgb_ee_map_type *ee_map;
DEBUGFUNC("ixgb_get_eeprom_data");
ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
DEBUGOUT("ixgb_ee: Reading eeprom data\n");
for (i=0; i < IXGB_EEPROM_SIZE ; i++) {
uint16_t ee_data;
ee_data = ixgb_read_eeprom(hw, i);
checksum += ee_data;
hw->eeprom[i] = le16_to_cpu (ee_data);
}
if (checksum != (uint16_t) EEPROM_SUM) {
DEBUGOUT("ixgb_ee: Checksum invalid.\n");
return (FALSE);
}
if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
!= le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
DEBUGOUT("ixgb_ee: Signature invalid.\n");
return(FALSE);
}
return(TRUE);
}
/******************************************************************************
* Local function to check if the eeprom signature is good
* If the eeprom signature is good, calls ixgb)get_eeprom_data.
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* TRUE: eeprom signature was good and the eeprom read was successful
* FALSE: otherwise.
******************************************************************************/
static boolean_t
ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
== le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
return (TRUE);
} else {
return ixgb_get_eeprom_data(hw);
}
}
/******************************************************************************
* return the mac address from EEPROM
*
* hw - Struct containing variables accessed by shared code
* mac_addr - Ethernet Address if EEPROM contents are valid, 0 otherwise
*
* Returns: None.
******************************************************************************/
void
ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
uint8_t *mac_addr)
{
int i;
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
DEBUGFUNC("ixgb_get_ee_mac_addr");
if (ixgb_check_and_get_eeprom_data (hw) == TRUE) {
for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
mac_addr[i] = ee_map->mac_addr[i];
DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
}
}
}
/******************************************************************************
* return the compatibility flags from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* compatibility flags if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_compatibility(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->compatibility);
return(0);
}
/******************************************************************************
* return the Printed Board Assembly number from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* PBA number if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint32_t
ixgb_get_ee_pba_number(struct ixgb_hw *hw)
{
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return ( le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
return(0);
}
/******************************************************************************
* return the Initialization Control Word 1 from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->init_ctrl_reg_1);
return(0);
}
/******************************************************************************
* return the Initialization Control Word 2 from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->init_ctrl_reg_2);
return(0);
}
/******************************************************************************
* return the Subsystem Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Subsystem Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->subsystem_id);
return(0);
}
/******************************************************************************
* return the Sub Vendor Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Sub Vendor Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->subvendor_id);
return(0);
}
/******************************************************************************
* return the Device Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_device_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->device_id);
return(0);
}
/******************************************************************************
* return the Vendor Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->vendor_id);
return(0);
}
/******************************************************************************
* return the Software Defined Pins Register from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* SDP Register if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->swdpins_reg);
return(0);
}
/******************************************************************************
* return the D3 Power Management Bits from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint8_t
ixgb_get_ee_d3_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->d3_power);
return(0);
}
/******************************************************************************
* return the D0 Power Management Bits from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint8_t
ixgb_get_ee_d0_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *) hw->eeprom;
if (ixgb_check_and_get_eeprom_data (hw) == TRUE)
return(ee_map->d0_power);
return(0);
}
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGB_EE_H_
#define _IXGB_EE_H_
#define IXGB_EEPROM_SIZE 64 /* Size in words */
#define IXGB_ETH_LENGTH_OF_ADDRESS 6
/* EEPROM Commands */
#define EEPROM_READ_OPCODE 0x6 /* EERPOM read opcode */
#define EEPROM_WRITE_OPCODE 0x5 /* EERPOM write opcode */
#define EEPROM_ERASE_OPCODE 0x7 /* EERPOM erase opcode */
#define EEPROM_EWEN_OPCODE 0x13 /* EERPOM erase/write enable */
#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */
/* EEPROM MAP (Word Offsets) */
#define EEPROM_IA_1_2_REG 0x0000
#define EEPROM_IA_3_4_REG 0x0001
#define EEPROM_IA_5_6_REG 0x0002
#define EEPROM_COMPATIBILITY_REG 0x0003
#define EEPROM_PBA_1_2_REG 0x0008
#define EEPROM_PBA_3_4_REG 0x0009
#define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_SUBSYS_ID_REG 0x000B
#define EEPROM_SUBVEND_ID_REG 0x000C
#define EEPROM_DEVICE_ID_REG 0x000D
#define EEPROM_VENDOR_ID_REG 0x000E
#define EEPROM_INIT_CONTROL2_REG 0x000F
#define EEPROM_SWDPINS_REG 0x0020
#define EEPROM_CIRCUIT_CTRL_REG 0x0021
#define EEPROM_D0_D3_POWER_REG 0x0022
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
/* Mask bits for fields in Word 0x0a of the EEPROM */
#define EEPROM_ICW1_SIGNATURE_MASK 0xC000
#define EEPROM_ICW1_SIGNATURE_VALID 0x4000
/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
#define EEPROM_SUM 0xBABA
/* EEPROM Map Sizes (Byte Counts) */
#define PBA_SIZE 4
/* EEPROM Map defines (WORD OFFSETS)*/
/* EEPROM structure */
struct ixgb_ee_map_type{
uint8_t mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
uint16_t compatibility;
uint16_t reserved1[4];
uint32_t pba_number;
uint16_t init_ctrl_reg_1;
uint16_t subsystem_id;
uint16_t subvendor_id;
uint16_t device_id;
uint16_t vendor_id;
uint16_t init_ctrl_reg_2;
uint16_t oem_reserved[16];
uint16_t swdpins_reg;
uint16_t circuit_ctrl_reg;
uint8_t d3_power;
uint8_t d0_power;
uint16_t reserved2[28];
uint16_t checksum;
};
/* EEPROM Functions */
uint16_t ixgb_read_eeprom(struct ixgb_hw *hw,
uint16_t reg);
boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
void ixgb_write_eeprom(struct ixgb_hw *hw,
uint16_t reg,
uint16_t data);
#endif /* IXGB_EE_H */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* ethtool support for ixgb */
#include "ixgb.h"
#include <asm/uaccess.h>
extern char ixgb_driver_name[];
extern char ixgb_driver_version[];
extern int ixgb_up(struct ixgb_adapter *adapter);
extern int ixgb_down(struct ixgb_adapter *adapter);
/**
* ixgb_ethtool_ioctl - Ethtool Ioctl Support
* @netdev: net device structure
* @ifr: interface request structure
**/
static inline int
ixgb_eeprom_size(struct ixgb_hw *hw)
{
/* return size in bytes */
return (IXGB_EEPROM_SIZE << 1);
}
#define SUPPORTED_10000baseT_Full (1 << 11)
#define SPEED_10000 10000
static void
ixgb_ethtool_gset(struct ixgb_adapter *adapter,
struct ethtool_cmd *ecmd)
{
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
if(netif_carrier_ok(adapter->netdev)) {
ecmd->speed = 10000;
ecmd->duplex = DUPLEX_FULL;
} else {
ecmd->speed = -1;
ecmd->duplex = -1;
}
ecmd->autoneg = AUTONEG_DISABLE;
}
static int
ixgb_ethtool_sset(struct ixgb_adapter *adapter,
struct ethtool_cmd *ecmd)
{
if(ecmd->autoneg == AUTONEG_ENABLE ||
ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
return -EINVAL;
else {
ixgb_down(adapter);
ixgb_up(adapter);
}
return 0;
}
#if 0
static int
ixgb_ethtool_promiscuous(struct ixgb_adapter *adapter,
struct ethtool_pmode *pmode)
{
uint32_t rctl = IXGB_READ_REG(&adapter->hw, RCTL);
pmode->rctl_old = rctl;
if(pmode->upe)
rctl |= IXGB_RCTL_UPE;
else
rctl &= ~IXGB_RCTL_UPE;
if(pmode->mpe)
rctl |= IXGB_RCTL_MPE;
else
rctl &= ~IXGB_RCTL_MPE;
IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
pmode->rctl_new = IXGB_READ_REG(&adapter->hw, RCTL);
return 0;
}
#endif
#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t)
static void
ixgb_ethtool_gdrvinfo(struct ixgb_adapter *adapter,
struct ethtool_drvinfo *drvinfo)
{
strncpy(drvinfo->driver, ixgb_driver_name, 32);
strncpy(drvinfo->version, ixgb_driver_version, 32);
strncpy(drvinfo->fw_version, "", 32);
strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
#ifdef ETHTOOL_GREGS
drvinfo->regdump_len = IXGB_REG_DUMP_LEN;
#endif /* ETHTOOL_GREGS */
drvinfo->eedump_len = ixgb_eeprom_size(&adapter->hw);
}
#ifdef ETHTOOL_GREGS
#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
static void
ixgb_ethtool_gregs(struct ixgb_adapter *adapter,
struct ethtool_regs *regs,
uint8_t *regs_buff)
{
struct ixgb_hw *hw = &adapter->hw;
uint32_t *reg = (uint32_t *) regs_buff;
uint32_t *reg_start = reg;
uint8_t i;
regs->version =
(adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
/* General Registers */
*reg++ = IXGB_READ_REG(hw, CTRL0); /* 0 */
*reg++ = IXGB_READ_REG(hw, CTRL1); /* 1 */
*reg++ = IXGB_READ_REG(hw, STATUS); /* 2 */
*reg++ = IXGB_READ_REG(hw, EECD); /* 3 */
*reg++ = IXGB_READ_REG(hw, MFS); /* 4 */
/* Interrupt */
*reg++ = IXGB_READ_REG(hw, ICR); /* 5 */
*reg++ = IXGB_READ_REG(hw, ICS); /* 6 */
*reg++ = IXGB_READ_REG(hw, IMS); /* 7 */
*reg++ = IXGB_READ_REG(hw, IMC); /* 8 */
/* Receive */
*reg++ = IXGB_READ_REG(hw, RCTL); /* 9 */
*reg++ = IXGB_READ_REG(hw, FCRTL); /* 10 */
*reg++ = IXGB_READ_REG(hw, FCRTH); /* 11 */
*reg++ = IXGB_READ_REG(hw, RDBAL); /* 12 */
*reg++ = IXGB_READ_REG(hw, RDBAH); /* 13 */
*reg++ = IXGB_READ_REG(hw, RDLEN); /* 14 */
*reg++ = IXGB_READ_REG(hw, RDH); /* 15 */
*reg++ = IXGB_READ_REG(hw, RDT); /* 16 */
*reg++ = IXGB_READ_REG(hw, RDTR); /* 17 */
*reg++ = IXGB_READ_REG(hw, RXDCTL); /* 18 */
*reg++ = IXGB_READ_REG(hw, RAIDC); /* 19 */
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
for(i = 0; i < IXGB_RAR_ENTRIES; i++) {
*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
}
/* Transmit */
*reg++ = IXGB_READ_REG(hw, TCTL); /* 53 */
*reg++ = IXGB_READ_REG(hw, TDBAL); /* 54 */
*reg++ = IXGB_READ_REG(hw, TDBAH); /* 55 */
*reg++ = IXGB_READ_REG(hw, TDLEN); /* 56 */
*reg++ = IXGB_READ_REG(hw, TDH); /* 57 */
*reg++ = IXGB_READ_REG(hw, TDT); /* 58 */
*reg++ = IXGB_READ_REG(hw, TIDV); /* 59 */
*reg++ = IXGB_READ_REG(hw, TXDCTL); /* 60 */
*reg++ = IXGB_READ_REG(hw, TSPMT); /* 61 */
*reg++ = IXGB_READ_REG(hw, PAP); /* 62 */
/* Physical */
*reg++ = IXGB_READ_REG(hw, PCSC1); /* 63 */
*reg++ = IXGB_READ_REG(hw, PCSC2); /* 64 */
*reg++ = IXGB_READ_REG(hw, PCSS1); /* 65 */
*reg++ = IXGB_READ_REG(hw, PCSS2); /* 66 */
*reg++ = IXGB_READ_REG(hw, XPCSS); /* 67 */
*reg++ = IXGB_READ_REG(hw, UCCR); /* 68 */
*reg++ = IXGB_READ_REG(hw, XPCSTC); /* 69 */
*reg++ = IXGB_READ_REG(hw, MACA); /* 70 */
*reg++ = IXGB_READ_REG(hw, APAE); /* 71 */
*reg++ = IXGB_READ_REG(hw, ARD); /* 72 */
*reg++ = IXGB_READ_REG(hw, AIS); /* 73 */
*reg++ = IXGB_READ_REG(hw, MSCA); /* 74 */
*reg++ = IXGB_READ_REG(hw, MSRWD); /* 75 */
#if 0
/* Wake-up */
reg[IXGB_WUFC] = IXGB_READ_REG(hw, WUFC);
reg[IXGB_WUS] = IXGB_READ_REG(hw, WUS);
reg[IXGB_FFLT] = IXGB_READ_REG(hw, FFLT);
reg[IXGB_FFMT] = IXGB_READ_REG(hw, FFMT);
reg[IXGB_FTVT] = IXGB_READ_REG(hw, FTVT);
#endif
/* Statistics */
*reg++ = IXGB_GET_STAT(adapter, tprl); /* 76 */
*reg++ = IXGB_GET_STAT(adapter, tprh); /* 77 */
*reg++ = IXGB_GET_STAT(adapter, gprcl); /* 78 */
*reg++ = IXGB_GET_STAT(adapter, gprch); /* 79 */
*reg++ = IXGB_GET_STAT(adapter, bprcl); /* 80 */
*reg++ = IXGB_GET_STAT(adapter, bprch); /* 81 */
*reg++ = IXGB_GET_STAT(adapter, mprcl); /* 82 */
*reg++ = IXGB_GET_STAT(adapter, mprch); /* 83 */
*reg++ = IXGB_GET_STAT(adapter, uprcl); /* 84 */
*reg++ = IXGB_GET_STAT(adapter, uprch); /* 85 */
*reg++ = IXGB_GET_STAT(adapter, vprcl); /* 86 */
*reg++ = IXGB_GET_STAT(adapter, vprch); /* 87 */
*reg++ = IXGB_GET_STAT(adapter, jprcl); /* 88 */
*reg++ = IXGB_GET_STAT(adapter, jprch); /* 89 */
*reg++ = IXGB_GET_STAT(adapter, gorcl); /* 90 */
*reg++ = IXGB_GET_STAT(adapter, gorch); /* 91 */
*reg++ = IXGB_GET_STAT(adapter, torl); /* 92 */
*reg++ = IXGB_GET_STAT(adapter, torh); /* 93 */
*reg++ = IXGB_GET_STAT(adapter, rnbc); /* 94 */
*reg++ = IXGB_GET_STAT(adapter, ruc); /* 95 */
*reg++ = IXGB_GET_STAT(adapter, roc); /* 96 */
*reg++ = IXGB_GET_STAT(adapter, rlec); /* 97 */
*reg++ = IXGB_GET_STAT(adapter, crcerrs); /* 98 */
*reg++ = IXGB_GET_STAT(adapter, icbc); /* 99 */
*reg++ = IXGB_GET_STAT(adapter, ecbc); /* 100 */
*reg++ = IXGB_GET_STAT(adapter, mpc); /* 101 */
*reg++ = IXGB_GET_STAT(adapter, tptl); /* 102 */
*reg++ = IXGB_GET_STAT(adapter, tpth); /* 103 */
*reg++ = IXGB_GET_STAT(adapter, gptcl); /* 104 */
*reg++ = IXGB_GET_STAT(adapter, gptch); /* 105 */
*reg++ = IXGB_GET_STAT(adapter, bptcl); /* 106 */
*reg++ = IXGB_GET_STAT(adapter, bptch); /* 107 */
*reg++ = IXGB_GET_STAT(adapter, mptcl); /* 108 */
*reg++ = IXGB_GET_STAT(adapter, mptch); /* 109 */
*reg++ = IXGB_GET_STAT(adapter, uptcl); /* 110 */
*reg++ = IXGB_GET_STAT(adapter, uptch); /* 111 */
*reg++ = IXGB_GET_STAT(adapter, vptcl); /* 112 */
*reg++ = IXGB_GET_STAT(adapter, vptch); /* 113 */
*reg++ = IXGB_GET_STAT(adapter, jptcl); /* 114 */
*reg++ = IXGB_GET_STAT(adapter, jptch); /* 115 */
*reg++ = IXGB_GET_STAT(adapter, gotcl); /* 116 */
*reg++ = IXGB_GET_STAT(adapter, gotch); /* 117 */
*reg++ = IXGB_GET_STAT(adapter, totl); /* 118 */
*reg++ = IXGB_GET_STAT(adapter, toth); /* 119 */
*reg++ = IXGB_GET_STAT(adapter, dc); /* 120 */
*reg++ = IXGB_GET_STAT(adapter, plt64c); /* 121 */
*reg++ = IXGB_GET_STAT(adapter, tsctc); /* 122 */
*reg++ = IXGB_GET_STAT(adapter, tsctfc); /* 123 */
*reg++ = IXGB_GET_STAT(adapter, ibic); /* 124 */
*reg++ = IXGB_GET_STAT(adapter, rfc); /* 125 */
*reg++ = IXGB_GET_STAT(adapter, lfc); /* 126 */
*reg++ = IXGB_GET_STAT(adapter, pfrc); /* 127 */
*reg++ = IXGB_GET_STAT(adapter, pftc); /* 128 */
*reg++ = IXGB_GET_STAT(adapter, mcfrc); /* 129 */
*reg++ = IXGB_GET_STAT(adapter, mcftc); /* 130 */
*reg++ = IXGB_GET_STAT(adapter, xonrxc); /* 131 */
*reg++ = IXGB_GET_STAT(adapter, xontxc); /* 132 */
*reg++ = IXGB_GET_STAT(adapter, xoffrxc); /* 133 */
*reg++ = IXGB_GET_STAT(adapter, xofftxc); /* 134 */
*reg++ = IXGB_GET_STAT(adapter, rjc); /* 135 */
#if 0
#endif
regs->len = (reg - reg_start) * sizeof(uint32_t);
}
#endif /* ETHTOOL_GREGS */
static int
ixgb_ethtool_geeprom(struct ixgb_adapter *adapter,
struct ethtool_eeprom *eeprom,
uint16_t *eeprom_buff)
{
struct ixgb_hw *hw = &adapter->hw;
int i, max_len, first_word, last_word;
IXGB_DBG("ixgb_ethtool_geeprom\n");
if (eeprom->len == 0)
return -EINVAL;
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
max_len = ixgb_eeprom_size(hw);
/* use our function to read the eeprom and update our cache */
ixgb_get_eeprom_data(hw);
if(eeprom->offset > eeprom->offset + eeprom->len)
return -EINVAL;
if((eeprom->offset + eeprom->len) > max_len)
eeprom->len = (max_len - eeprom->offset);
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
for(i = 0; i <= (last_word - first_word); i++) {
eeprom_buff[i] = hw->eeprom[first_word + i];
}
return 0;
}
static int
ixgb_ethtool_seeprom(struct ixgb_adapter *adapter,
struct ethtool_eeprom *eeprom, void *user_data)
{
struct ixgb_hw *hw = &adapter->hw;
uint16_t eeprom_buff[256];
int i, max_len, first_word, last_word;
void *ptr;
if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
if(eeprom->len == 0)
return -EINVAL;
max_len = ixgb_eeprom_size(hw);
if(eeprom->offset > eeprom->offset + eeprom->len)
return -EINVAL;
if((eeprom->offset + eeprom->len) > max_len)
eeprom->len = (max_len - eeprom->offset);
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
ptr = (void *)eeprom_buff;
if(eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
ptr++;
}
if((eeprom->offset + eeprom->len) & 1) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
eeprom_buff[last_word - first_word]
= ixgb_read_eeprom(hw, last_word);
}
if(copy_from_user(ptr, user_data, eeprom->len))
return -EFAULT;
for(i = 0; i <= (last_word - first_word); i++)
ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
/* Update the checksum over the first part of the EEPROM if needed */
if(first_word <= EEPROM_CHECKSUM_REG)
ixgb_update_eeprom_checksum(hw);
return 0;
}
#ifdef ETHTOOL_PHYS_ID
/* toggle LED 4 times per second = 2 "blinks" per second */
#define IXGB_ID_INTERVAL (HZ/4)
/* bit defines for adapter->led_status */
#define IXGB_LED_ON 0
static void
ixgb_led_blink_callback(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *) data;
if(test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
ixgb_led_off(&adapter->hw);
else
ixgb_led_on(&adapter->hw);
mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);
}
static int
ixgb_ethtool_led_blink(struct ixgb_adapter *adapter,
struct ethtool_value *id)
{
if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = ixgb_led_blink_callback;
adapter->blink_timer.data = (unsigned long) adapter;
}
mod_timer(&adapter->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
if(id->data)
schedule_timeout(id->data * HZ);
else
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
del_timer_sync(&adapter->blink_timer);
ixgb_led_off(&adapter->hw);
clear_bit(IXGB_LED_ON, &adapter->led_status);
return 0;
}
#endif /* ETHTOOL_PHYS_ID */
int
ixgb_ethtool_ioctl(struct net_device *netdev,
struct ifreq *ifr)
{
struct ixgb_adapter *adapter = netdev->priv;
void *addr = ifr->ifr_data;
uint32_t cmd;
if(get_user(cmd, (uint32_t *) addr))
return -EFAULT;
switch (cmd) {
#if 0
case ETHTOOL_PROMISCUOUS: {
struct ethtool_pmode pmode;
if(copy_from_user(&pmode, addr, sizeof(pmode)))
return -EFAULT;
ixgb_ethtool_promiscuous(adapter, &pmode);
if(copy_to_user(addr, &pmode, sizeof(pmode)))
return -EFAULT;
return 0;
}
case ETHTOOL_DOWN_UP:
ixgb_down(netdev->priv);
ixgb_up(netdev->priv);
return 0;
#endif
case ETHTOOL_GSET: {
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
ixgb_ethtool_gset(adapter, &ecmd);
if(copy_to_user(addr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0;
}
case ETHTOOL_SSET: {
struct ethtool_cmd ecmd;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
return -EFAULT;
return ixgb_ethtool_sset(adapter, &ecmd);
}
case ETHTOOL_GDRVINFO:
{
struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO };
ixgb_ethtool_gdrvinfo(adapter, &drvinfo);
if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
return -EFAULT;
return 0;
}
#if defined(ETHTOOL_GREGS) && defined(ETHTOOL_GEEPROM)
case ETHTOOL_GREGS: {
struct ethtool_regs regs = { ETHTOOL_GREGS };
uint8_t regs_buff[IXGB_REG_DUMP_LEN];
ixgb_ethtool_gregs(adapter, &regs, regs_buff);
if(copy_to_user(addr, &regs, sizeof(regs)))
return -EFAULT;
addr += offsetof(struct ethtool_regs, data);
if(copy_to_user(addr, regs_buff, regs.len))
return -EFAULT;
return 0;
}
#endif /* ETHTOOL_GREGS */
case ETHTOOL_NWAY_RST: {
IXGB_DBG("ETHTOOL_NWAY_RST\n");
if(!capable(CAP_NET_ADMIN))
return -EPERM;
ixgb_down(adapter);
ixgb_up(adapter);
return 0;
}
#ifdef ETHTOOL_PHYS_ID
case ETHTOOL_PHYS_ID: {
struct ethtool_value id;
IXGB_DBG("ETHTOOL_PHYS_ID\n");
if(copy_from_user(&id, addr, sizeof(id)))
return -EFAULT;
return ixgb_ethtool_led_blink(adapter, &id);
}
#endif /* ETHTOOL_PHYS_ID */
case ETHTOOL_GLINK: {
struct ethtool_value link = { ETHTOOL_GLINK };
IXGB_DBG("ETHTOOL_GLINK\n");
link.data = netif_carrier_ok(netdev);
if(copy_to_user(addr, &link, sizeof(link)))
return -EFAULT;
return 0;
}
case ETHTOOL_GEEPROM: {
struct ethtool_eeprom eeprom = { ETHTOOL_GEEPROM };
uint16_t eeprom_buff[IXGB_EEPROM_SIZE];
void *ptr;
int err;
IXGB_DBG("ETHTOOL_GEEPROM\n");
if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
return -EFAULT;
if ((err = ixgb_ethtool_geeprom(adapter, &eeprom, eeprom_buff))<0)
return err;
if(copy_to_user(addr, &eeprom, sizeof(eeprom)))
return -EFAULT;
addr += offsetof(struct ethtool_eeprom, data);
ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
if(copy_to_user(addr, ptr, eeprom.len))
return -EFAULT;
return 0;
}
case ETHTOOL_SEEPROM: {
struct ethtool_eeprom eeprom;
IXGB_DBG("ETHTOOL_SEEPROM\n");
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
return -EFAULT;
addr += offsetof(struct ethtool_eeprom, data);
return ixgb_ethtool_seeprom(adapter, &eeprom, addr);
}
default:
return -EOPNOTSUPP;
}
}
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* ixgb_hw.c
* Shared functions for accessing and configuring the adapter
*/
#include "ixgb_hw.h"
#include "ixgb_ids.h"
/* Local function prototypes */
static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw,
uint8_t *mc_addr);
static void ixgb_mta_set(struct ixgb_hw *hw,
uint32_t hash_value);
static void ixgb_get_bus_info(struct ixgb_hw *hw);
boolean_t mac_addr_valid(uint8_t *mac_addr);
static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
static void ixgb_optics_reset(struct ixgb_hw *hw);
uint32_t ixgb_mac_reset (struct ixgb_hw* hw);
uint32_t ixgb_mac_reset (struct ixgb_hw* hw)
{
uint32_t ctrl_reg;
/* Setup up hardware to known state with RESET. */
ctrl_reg = IXGB_CTRL0_RST |
IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
IXGB_CTRL0_SDP2_DIR |
IXGB_CTRL0_SDP1_DIR |
IXGB_CTRL0_SDP0_DIR |
IXGB_CTRL0_SDP3 | /* Initial value 1101 */
IXGB_CTRL0_SDP2 |
IXGB_CTRL0_SDP0;
#ifdef HP_ZX1
outl(IXGB_CTRL0, hw->io_base);
outl(ctrl_reg, hw->io_base + 4);
#else
IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
#endif
/* Delay a few ms just to allow the reset to complete */
msec_delay(IXGB_DELAY_AFTER_RESET);
ctrl_reg = IXGB_READ_REG(hw, CTRL0);
#if DBG
/* Make sure the self-clearing global reset bit did self clear */
ASSERT(!(ctrl_reg & IXGB_CTRL0_RST));
#endif
ixgb_optics_reset(hw);
return ctrl_reg;
}
/******************************************************************************
* Reset the transmit and receive units; mask and clear all interrupts.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
boolean_t
ixgb_adapter_stop(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
uint32_t icr_reg;
DEBUGFUNC("ixgb_adapter_stop");
/* If we are stopped or resetting exit gracefully and wait to be
* started again before accessing the hardware.
*/
if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
return FALSE;
}
/* Set the Adapter Stopped flag so other driver functions stop
* touching the Hardware.
*/
hw->adapter_stopped = TRUE;
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
IXGB_WRITE_REG(hw, IMC, 0xFFFFFFFF);
/* Disable the Transmit and Receive units. Then delay to allow
* any pending transactions to complete before we hit the MAC with
* the global reset.
*/
IXGB_WRITE_REG(hw, RCTL, IXGB_READ_REG(hw, RCTL) & ~IXGB_RCTL_RXEN);
IXGB_WRITE_REG(hw, TCTL, IXGB_READ_REG(hw, TCTL) & ~IXGB_TCTL_TXEN);
msec_delay(IXGB_DELAY_BEFORE_RESET);
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
* clearing, and should clear within a microsecond.
*/
DEBUGOUT("Issuing a global reset to MAC\n");
ctrl_reg = ixgb_mac_reset(hw);
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
IXGB_WRITE_REG(hw, IMC, 0xffffffff);
/* Clear any pending interrupt events. */
icr_reg = IXGB_READ_REG(hw, ICR);
return (ctrl_reg & IXGB_CTRL0_RST);
}
/******************************************************************************
* Performs basic configuration of the adapter.
*
* hw - Struct containing variables accessed by shared code
*
* Resets the controller.
* Reads and validates the EEPROM.
* Initializes the receive address registers.
* Initializes the multicast table.
* Clears all on-chip counters.
* Calls routine to setup flow control settings.
* Leaves the transmit and receive units disabled and uninitialized.
*
* Returns:
* TRUE if successful,
* FALSE if unrecoverable problems were encountered.
*****************************************************************************/
boolean_t
ixgb_init_hw(struct ixgb_hw *hw)
{
uint32_t i;
uint32_t ctrl_reg;
boolean_t status;
DEBUGFUNC("ixgb_init_hw");
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
* clearing, and should clear within a microsecond.
*/
DEBUGOUT("Issuing a global reset to MAC\n");
ctrl_reg = ixgb_mac_reset(hw);
DEBUGOUT("Issuing an EE reset to MAC\n");
#ifdef HP_ZX1
outl(IXGB_CTRL1, hw->io_base);
outl(IXGB_CTRL1_EE_RST, hw->io_base + 4);
#else
IXGB_WRITE_REG(hw, CTRL1, IXGB_CTRL1_EE_RST);
#endif
/* Delay a few ms just to allow the reset to complete */
msec_delay(IXGB_DELAY_AFTER_EE_RESET);
if (ixgb_get_eeprom_data(hw) == FALSE) {
return(FALSE);
}
/* Setup the receive addresses.
* Receive Address Registers (RARs 0 - 15).
*/
ixgb_init_rx_addrs(hw);
/*
* Check that a valid MAC address has been set.
* If it is not valid, we fail hardware init.
*/
if (!mac_addr_valid(hw->curr_mac_addr)) {
DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
return(FALSE);
}
/* tell the routines in this file they can access hardware again */
hw->adapter_stopped = FALSE;
/* Fill in the bus_info structure */
ixgb_get_bus_info(hw);
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
for(i = 0; i < IXGB_MC_TBL_SIZE; i++)
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* Zero out the VLAN Filter Table Array */
ixgb_clear_vfta(hw);
/* Zero all of the hardware counters */
ixgb_clear_hw_cntrs(hw);
/* Call a subroutine to setup flow control. */
status = ixgb_setup_fc(hw);
/* check-for-link in case lane deskew is locked */
ixgb_check_for_link(hw);
return (status);
}
/******************************************************************************
* Initializes receive address filters.
*
* hw - Struct containing variables accessed by shared code
*
* Places the MAC address in receive address register 0 and clears the rest
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
void
ixgb_init_rx_addrs(struct ixgb_hw *hw)
{
uint32_t i;
DEBUGFUNC("ixgb_init_rx_addrs");
/*
* If the current mac address is valid, assume it is a software override
* to the permanent address.
* Otherwise, use the permanent address from the eeprom.
*/
if (!mac_addr_valid(hw->curr_mac_addr)) {
/* Get the MAC address from the eeprom for later reference */
ixgb_get_ee_mac_addr(hw, hw->curr_mac_addr);
DEBUGOUT3(" Keeping Permanent MAC Addr =%.2X %.2X %.2X ",
hw->curr_mac_addr[0],
hw->curr_mac_addr[1],
hw->curr_mac_addr[2]);
DEBUGOUT3("%.2X %.2X %.2X\n",
hw->curr_mac_addr[3],
hw->curr_mac_addr[4],
hw->curr_mac_addr[5]);
} else {
/* Setup the receive address. */
DEBUGOUT("Overriding MAC Address in RAR[0]\n");
DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
hw->curr_mac_addr[0],
hw->curr_mac_addr[1],
hw->curr_mac_addr[2]);
DEBUGOUT3("%.2X %.2X %.2X\n",
hw->curr_mac_addr[3],
hw->curr_mac_addr[4],
hw->curr_mac_addr[5]);
ixgb_rar_set(hw, hw->curr_mac_addr, 0);
}
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
return;
}
/******************************************************************************
* Updates the MAC's list of multicast addresses.
*
* hw - Struct containing variables accessed by shared code
* mc_addr_list - the list of new multicast addresses
* mc_addr_count - number of addresses
* pad - number of bytes between addresses in the list
*
* The given list replaces any existing list. Clears the last 15 receive
* address registers and the multicast table. Uses receive address registers
* for the first 15 multicast addresses, and hashes the rest into the
* multicast table.
*****************************************************************************/
void
ixgb_mc_addr_list_update(struct ixgb_hw *hw,
uint8_t *mc_addr_list,
uint32_t mc_addr_count,
uint32_t pad)
{
uint32_t hash_value;
uint32_t i;
uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
DEBUGFUNC("ixgb_mc_addr_list_update");
/* Set the new number of MC addresses that we are being requested to use. */
hw->num_mc_addrs = mc_addr_count;
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
for(i = 0; i < IXGB_MC_TBL_SIZE; i++) {
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
}
/* Add the new addresses */
for(i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 1],
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 2],
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 3],
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 4],
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 5]);
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
if(rar_used_count < IXGB_RAR_ENTRIES) {
ixgb_rar_set(hw,
mc_addr_list + (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
rar_used_count);
DEBUGOUT1("Added a multicast address to RAR[%d]\n", i);
rar_used_count++;
} else {
hash_value = ixgb_hash_mc_addr(hw,
mc_addr_list +
(i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)));
DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
ixgb_mta_set(hw, hash_value);
}
}
DEBUGOUT("MC Update Complete\n");
return;
}
/******************************************************************************
* Hashes an address to determine its location in the multicast table
*
* hw - Struct containing variables accessed by shared code
* mc_addr - the multicast address to hash
*
* Returns:
* The hash value
*****************************************************************************/
static uint32_t
ixgb_hash_mc_addr(struct ixgb_hw *hw,
uint8_t *mc_addr)
{
uint32_t hash_value = 0;
DEBUGFUNC("ixgb_hash_mc_addr");
/* The portion of the address that is used for the hash table is
* determined by the mc_filter_type setting.
*/
switch (hw->mc_filter_type) {
/* [0] [1] [2] [3] [4] [5]
* 01 AA 00 12 34 56
* LSB MSB - According to H/W docs */
case 0:
/* [47:36] i.e. 0x563 for above example address */
hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
break;
case 1: /* [46:35] i.e. 0xAC6 for above example address */
hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
break;
case 2: /* [45:34] i.e. 0x5D8 for above example address */
hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
break;
case 3: /* [43:32] i.e. 0x634 for above example address */
hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
break;
default:
/* Invalid mc_filter_type, what should we do? */
DEBUGOUT("MC filter type param set incorrectly\n");
ASSERT(0);
break;
}
hash_value &= 0xFFF;
return (hash_value);
}
/******************************************************************************
* Sets the bit in the multicast table corresponding to the hash value.
*
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
static void
ixgb_mta_set(struct ixgb_hw *hw,
uint32_t hash_value)
{
uint32_t hash_bit, hash_reg;
uint32_t mta_reg;
/* The MTA is a register array of 128 32-bit registers.
* It is treated like an array of 4096 bits. We want to set
* bit BitArray[hash_value]. So we figure out what register
* the bit is in, read it, OR in the new bit, then write
* back the new value. The register is determined by the
* upper 7 bits of the hash value and the bit within that
* register are determined by the lower 5 bits of the value.
*/
hash_reg = (hash_value >> 5) & 0x7F;
hash_bit = hash_value & 0x1F;
mta_reg = IXGB_READ_REG_ARRAY(hw, MTA, hash_reg);
mta_reg |= (1 << hash_bit);
IXGB_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta_reg);
return;
}
/******************************************************************************
* Puts an ethernet address into a receive address register.
*
* hw - Struct containing variables accessed by shared code
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
void
ixgb_rar_set(struct ixgb_hw *hw,
uint8_t *addr,
uint32_t index)
{
uint32_t rar_low, rar_high;
DEBUGFUNC("ixgb_rar_set");
/* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
rar_low = ((uint32_t) addr[0] |
((uint32_t) addr[1] << 8) |
((uint32_t) addr[2] << 16) |
((uint32_t) addr[3] << 24));
rar_high = ((uint32_t) addr[4] |
((uint32_t) addr[5] << 8) |
IXGB_RAH_AV);
IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
return;
}
/******************************************************************************
* Writes a value to the specified offset in the VLAN filter table.
*
* hw - Struct containing variables accessed by shared code
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
void
ixgb_write_vfta(struct ixgb_hw *hw,
uint32_t offset,
uint32_t value)
{
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
return;
}
/******************************************************************************
* Clears the VLAN filer table
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
void
ixgb_clear_vfta(struct ixgb_hw *hw)
{
uint32_t offset;
for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
return;
}
/******************************************************************************
* Configures the flow control settings based on SW configuration.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
boolean_t
ixgb_setup_fc(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
uint32_t pap_reg = 0; /* by default, assume no pause time */
boolean_t status = TRUE;
DEBUGFUNC("ixgb_setup_fc");
/* Get the current control reg 0 settings */
ctrl_reg = IXGB_READ_REG(hw, CTRL0);
/* Clear the Receive Pause Enable and Transmit Pause Enable bits */
ctrl_reg &= ~(IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
/* The possible values of the "flow_control" parameter are:
* 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames
* but not send pause frames).
* 2: Tx flow control is enabled (we can send pause frames
* but we do not support receiving pause frames).
* 3: Both Rx and TX flow control (symmetric) are enabled.
* other: Invalid.
*/
switch (hw->fc.type) {
case ixgb_fc_none: /* 0 */
break;
case ixgb_fc_rx_pause: /* 1 */
/* RX Flow control is enabled, and TX Flow control is
* disabled.
*/
ctrl_reg |= (IXGB_CTRL0_RPE);
break;
case ixgb_fc_tx_pause: /* 2 */
/* TX Flow control is enabled, and RX Flow control is
* disabled, by a software over-ride.
*/
ctrl_reg |= (IXGB_CTRL0_TPE);
pap_reg = hw->fc.pause_time;
break;
case ixgb_fc_full: /* 3 */
/* Flow control (both RX and TX) is enabled by a software
* over-ride.
*/
ctrl_reg |= (IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
pap_reg = hw->fc.pause_time;
break;
default:
/* We should never get here. The value should be 0-3. */
DEBUGOUT("Flow control param set incorrectly\n");
ASSERT(0);
break;
}
/* Write the new settings */
IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
if (pap_reg != 0) {
IXGB_WRITE_REG(hw, PAP, pap_reg);
}
/* Set the flow control receive threshold registers. Normally,
* these registers will be set to a default threshold that may be
* adjusted later by the driver's runtime code. However, if the
* ability to transmit pause frames in not enabled, then these
* registers will be set to 0.
*/
if(!(hw->fc.type & ixgb_fc_tx_pause)) {
IXGB_WRITE_REG(hw, FCRTL, 0);
IXGB_WRITE_REG(hw, FCRTH, 0);
} else {
/* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of XON frames.
*/
if(hw->fc.send_xon) {
IXGB_WRITE_REG(hw, FCRTL,
(hw->fc.low_water | IXGB_FCRTL_XONE));
} else {
IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);
}
IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);
}
return (status);
}
/******************************************************************************
* Reads a word from a device over the Management Data Interface (MDI) bus.
* This interface is used to manage Physical layer devices.
*
* hw - Struct containing variables accessed by hw code
* reg_address - Offset of device register being read.
* phy_address - Address of device on MDI.
*
* Returns: Data word (16 bits) from MDI device.
*
* This routine uses the new protocol MDI Single Command and Address Operation.
* This requires that first an address cycle command is sent, followed by a
* read command.
*****************************************************************************/
uint16_t
ixgb_read_phy_reg(struct ixgb_hw *hw,
uint32_t reg_address,
uint32_t phy_address,
uint32_t device_type)
{
uint32_t i;
uint32_t data;
uint32_t command = 0;
ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
/* Setup and write the address cycle command */
command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
(phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
(IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
/**************************************************************
** Check every 10 usec to see if the address cycle completed
** The COMMAND bit will clear when the operation is complete.
** This may take as long as 64 usecs (we'll wait 100 usecs max)
** from the CPU Write to the Ready bit assertion.
**************************************************************/
for (i = 0; i < 10; i++)
{
usec_delay(10);
command = IXGB_READ_REG(hw, MSCA);
if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
break;
}
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Address cycle complete, setup and write the read command */
command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
(phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
(IXGB_MSCA_READ | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
/**************************************************************
** Check every 10 usec to see if the read command completed
** The COMMAND bit will clear when the operation is complete.
** The read may take as long as 64 usecs (we'll wait 100 usecs max)
** from the CPU Write to the Ready bit assertion.
**************************************************************/
for (i = 0; i < 10; i++)
{
usec_delay(10);
command = IXGB_READ_REG(hw, MSCA);
if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
break;
}
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Operation is complete, get the data from the MDIO Read/Write Data
* register and return.
*/
data = IXGB_READ_REG(hw, MSRWD);
data >>= IXGB_MSRWD_READ_DATA_SHIFT;
return((uint16_t) data);
}
/******************************************************************************
* Writes a word to a device over the Management Data Interface (MDI) bus.
* This interface is used to manage Physical layer devices.
*
* hw - Struct containing variables accessed by hw code
* reg_address - Offset of device register being read.
* phy_address - Address of device on MDI.
* device_type - Also known as the Device ID or DID.
* data - 16-bit value to be written
*
* Returns: void.
*
* This routine uses the new protocol MDI Single Command and Address Operation.
* This requires that first an address cycle command is sent, followed by a
* write command.
*****************************************************************************/
void
ixgb_write_phy_reg(struct ixgb_hw *hw,
uint32_t reg_address,
uint32_t phy_address,
uint32_t device_type,
uint16_t data)
{
uint32_t i;
uint32_t command = 0;
ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
/* Put the data in the MDIO Read/Write Data register */
IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
/* Setup and write the address cycle command */
command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
(phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
(IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
/**************************************************************
** Check every 10 usec to see if the address cycle completed
** The COMMAND bit will clear when the operation is complete.
** This may take as long as 64 usecs (we'll wait 100 usecs max)
** from the CPU Write to the Ready bit assertion.
**************************************************************/
for (i = 0; i < 10; i++)
{
usec_delay(10);
command = IXGB_READ_REG(hw, MSCA);
if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
break;
}
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Address cycle complete, setup and write the write command */
command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
(phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
(IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
/**************************************************************
** Check every 10 usec to see if the read command completed
** The COMMAND bit will clear when the operation is complete.
** The write may take as long as 64 usecs (we'll wait 100 usecs max)
** from the CPU Write to the Ready bit assertion.
**************************************************************/
for (i = 0; i < 10; i++)
{
usec_delay(10);
command = IXGB_READ_REG(hw, MSCA);
if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
break;
}
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Operation is complete, return. */
}
/******************************************************************************
* Checks to see if the link status of the hardware has changed.
*
* hw - Struct containing variables accessed by hw code
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
void
ixgb_check_for_link(struct ixgb_hw *hw)
{
uint32_t status_reg;
uint32_t xpcss_reg;
DEBUGFUNC("ixgb_check_for_link");
xpcss_reg = IXGB_READ_REG(hw, XPCSS);
status_reg = IXGB_READ_REG(hw, STATUS);
if ((xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
(status_reg & IXGB_STATUS_LU)) {
hw->link_up = TRUE;
} else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
(status_reg & IXGB_STATUS_LU)) {
DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
hw->link_up = ixgb_link_reset(hw);
} else {
hw->link_up = ixgb_link_reset(hw);
}
/* Anything else for 10 Gig?? */
}
boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
{
uint32_t newLFC, newRFC;
boolean_t bad_link_returncode = FALSE;
/* check for a bad reset that may have occured
* the indication is that the RFC / LFC registers may be incrementing
* continually. Do a full adapter reset to recover
*/
newLFC = IXGB_READ_REG(hw, LFC);
newRFC = IXGB_READ_REG(hw, RFC);
if ((hw->lastLFC + 250 < newLFC) || (hw->lastRFC + 250 < newRFC)) {
DEBUGOUT("BAD LINK! too many LFC/RFC since last check\n");
bad_link_returncode = TRUE;
}
hw->lastLFC = newLFC;
hw->lastRFC = newRFC;
return bad_link_returncode;
}
/******************************************************************************
* Clears all hardware statistics counters.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
void
ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
{
volatile uint32_t temp_reg;
DEBUGFUNC("ixgb_clear_hw_cntrs");
/* if we are stopped or resetting exit gracefully */
if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is stopped!!!\n");
return;
}
temp_reg = IXGB_READ_REG(hw, TPRL);
temp_reg = IXGB_READ_REG(hw, TPRH);
temp_reg = IXGB_READ_REG(hw, GPRCL);
temp_reg = IXGB_READ_REG(hw, GPRCH);
temp_reg = IXGB_READ_REG(hw, BPRCL);
temp_reg = IXGB_READ_REG(hw, BPRCH);
temp_reg = IXGB_READ_REG(hw, MPRCL);
temp_reg = IXGB_READ_REG(hw, MPRCH);
temp_reg = IXGB_READ_REG(hw, UPRCL);
temp_reg = IXGB_READ_REG(hw, UPRCH);
temp_reg = IXGB_READ_REG(hw, VPRCL);
temp_reg = IXGB_READ_REG(hw, VPRCH);
temp_reg = IXGB_READ_REG(hw, JPRCL);
temp_reg = IXGB_READ_REG(hw, JPRCH);
temp_reg = IXGB_READ_REG(hw, GORCL);
temp_reg = IXGB_READ_REG(hw, GORCH);
temp_reg = IXGB_READ_REG(hw, TORL);
temp_reg = IXGB_READ_REG(hw, TORH);
temp_reg = IXGB_READ_REG(hw, RNBC);
temp_reg = IXGB_READ_REG(hw, RUC);
temp_reg = IXGB_READ_REG(hw, ROC);
temp_reg = IXGB_READ_REG(hw, RLEC);
temp_reg = IXGB_READ_REG(hw, CRCERRS);
temp_reg = IXGB_READ_REG(hw, ICBC);
temp_reg = IXGB_READ_REG(hw, ECBC);
temp_reg = IXGB_READ_REG(hw, MPC);
temp_reg = IXGB_READ_REG(hw, TPTL);
temp_reg = IXGB_READ_REG(hw, TPTH);
temp_reg = IXGB_READ_REG(hw, GPTCL);
temp_reg = IXGB_READ_REG(hw, GPTCH);
temp_reg = IXGB_READ_REG(hw, BPTCL);
temp_reg = IXGB_READ_REG(hw, BPTCH);
temp_reg = IXGB_READ_REG(hw, MPTCL);
temp_reg = IXGB_READ_REG(hw, MPTCH);
temp_reg = IXGB_READ_REG(hw, UPTCL);
temp_reg = IXGB_READ_REG(hw, UPTCH);
temp_reg = IXGB_READ_REG(hw, VPTCL);
temp_reg = IXGB_READ_REG(hw, VPTCH);
temp_reg = IXGB_READ_REG(hw, JPTCL);
temp_reg = IXGB_READ_REG(hw, JPTCH);
temp_reg = IXGB_READ_REG(hw, GOTCL);
temp_reg = IXGB_READ_REG(hw, GOTCH);
temp_reg = IXGB_READ_REG(hw, TOTL);
temp_reg = IXGB_READ_REG(hw, TOTH);
temp_reg = IXGB_READ_REG(hw, DC);
temp_reg = IXGB_READ_REG(hw, PLT64C);
temp_reg = IXGB_READ_REG(hw, TSCTC);
temp_reg = IXGB_READ_REG(hw, TSCTFC);
temp_reg = IXGB_READ_REG(hw, IBIC);
temp_reg = IXGB_READ_REG(hw, RFC);
temp_reg = IXGB_READ_REG(hw, LFC);
temp_reg = IXGB_READ_REG(hw, PFRC);
temp_reg = IXGB_READ_REG(hw, PFTC);
temp_reg = IXGB_READ_REG(hw, MCFRC);
temp_reg = IXGB_READ_REG(hw, MCFTC);
temp_reg = IXGB_READ_REG(hw, XONRXC);
temp_reg = IXGB_READ_REG(hw, XONTXC);
temp_reg = IXGB_READ_REG(hw, XOFFRXC);
temp_reg = IXGB_READ_REG(hw, XOFFTXC);
temp_reg = IXGB_READ_REG(hw, RJC);
return;
}
/******************************************************************************
* Turns on the software controllable LED
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
void
ixgb_led_on(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
/* To turn on the LED, clear software-definable pin 0 (SDP0). */
ctrl0_reg &= ~IXGB_CTRL0_SDP0;
IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
return;
}
/******************************************************************************
* Turns off the software controllable LED
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
void
ixgb_led_off(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
/* To turn off the LED, set software-definable pin 0 (SDP0). */
ctrl0_reg |= IXGB_CTRL0_SDP0;
IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
return;
}
/******************************************************************************
* Gets the current PCI bus type, speed, and width of the hardware
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
static void
ixgb_get_bus_info(struct ixgb_hw *hw)
{
uint32_t status_reg;
status_reg = IXGB_READ_REG(hw, STATUS);
hw->bus.type = (status_reg & IXGB_STATUS_PCIX_MODE) ?
ixgb_bus_type_pcix : ixgb_bus_type_pci;
if (hw->bus.type == ixgb_bus_type_pci) {
hw->bus.speed = (status_reg & IXGB_STATUS_PCI_SPD) ?
ixgb_bus_speed_66 : ixgb_bus_speed_33;
} else {
switch (status_reg & IXGB_STATUS_PCIX_SPD_MASK) {
case IXGB_STATUS_PCIX_SPD_66:
hw->bus.speed = ixgb_bus_speed_66;
break;
case IXGB_STATUS_PCIX_SPD_100:
hw->bus.speed = ixgb_bus_speed_100;
break;
case IXGB_STATUS_PCIX_SPD_133:
hw->bus.speed = ixgb_bus_speed_133;
break;
default:
hw->bus.speed = ixgb_bus_speed_reserved;
break;
}
}
hw->bus.width = (status_reg & IXGB_STATUS_BUS64) ?
ixgb_bus_width_64 : ixgb_bus_width_32;
return;
}
/******************************************************************************
* Tests a MAC address to ensure it is a valid Individual Address
*
* mac_addr - pointer to MAC address.
*
*****************************************************************************/
boolean_t
mac_addr_valid(uint8_t *mac_addr)
{
boolean_t is_valid = TRUE;
DEBUGFUNC("mac_addr_valid");
/* Make sure it is not a multicast address */
if (IS_MULTICAST(mac_addr)) {
DEBUGOUT("MAC address is multicast\n");
is_valid = FALSE;
}
/* Not a broadcast address */
else if (IS_BROADCAST(mac_addr)) {
DEBUGOUT("MAC address is broadcast\n");
is_valid = FALSE;
}
/* Reject the zero address */
else if (mac_addr[0] == 0 &&
mac_addr[1] == 0 &&
mac_addr[2] == 0 &&
mac_addr[3] == 0 &&
mac_addr[4] == 0 &&
mac_addr[5] == 0
)
{
DEBUGOUT("MAC address is all zeros\n");
is_valid = FALSE;
}
return (is_valid);
}
/******************************************************************************
* Resets the 10GbE link. Waits the settle time and returns the state of
* the link.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
boolean_t
ixgb_link_reset(struct ixgb_hw *hw)
{
boolean_t link_status = FALSE;
uint8_t wait_retries = MAX_RESET_ITERATIONS;
uint8_t lrst_retries = MAX_RESET_ITERATIONS;
do {
IXGB_WRITE_REG(hw, CTRL0, IXGB_READ_REG(hw, CTRL0) | IXGB_CTRL0_LRST);
do {
usec_delay(IXGB_DELAY_USECS_AFTER_LINK_RESET);
link_status = ((IXGB_READ_REG(hw, STATUS) & IXGB_STATUS_LU) &&
(IXGB_READ_REG(hw, XPCSS) & IXGB_XPCSS_ALIGN_STATUS)) ?
TRUE : FALSE;
} while (!link_status && -- wait_retries);
} while (!link_status && --lrst_retries);
return link_status;
}
/******************************************************************************
* Resets the 10GbE optics module.
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
void
ixgb_optics_reset(struct ixgb_hw *hw)
{
uint16_t mdio_reg;
ixgb_write_phy_reg( hw,
TXN17401_PMA_PMD_CR1,
IXGB_PHY_ADDRESS,
TXN17401_PMA_PMD_DID,
TXN17401_PMA_PMD_CR1_RESET);
mdio_reg = ixgb_read_phy_reg( hw,
TXN17401_PMA_PMD_CR1,
IXGB_PHY_ADDRESS,
TXN17401_PMA_PMD_DID);
}
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGB_HW_H_
#define _IXGB_HW_H_
#include "ixgb_osdep.h"
/* Enums */
typedef enum {
ixgb_mac_unknown = 0,
ixgb_82597,
ixgb_num_macs
} ixgb_mac_type;
/* Media Types */
typedef enum {
ixgb_media_type_unknown = 0,
ixgb_media_type_fiber = 1,
ixgb_num_media_types
} ixgb_media_type;
/* Flow Control Settings */
typedef enum {
ixgb_fc_none = 0,
ixgb_fc_rx_pause = 1,
ixgb_fc_tx_pause = 2,
ixgb_fc_full = 3,
ixgb_fc_default = 0xFF
} ixgb_fc_type;
/* PCI bus types */
typedef enum {
ixgb_bus_type_unknown = 0,
ixgb_bus_type_pci,
ixgb_bus_type_pcix
} ixgb_bus_type;
/* PCI bus speeds */
typedef enum {
ixgb_bus_speed_unknown = 0,
ixgb_bus_speed_33,
ixgb_bus_speed_66,
ixgb_bus_speed_100,
ixgb_bus_speed_133,
ixgb_bus_speed_reserved
} ixgb_bus_speed;
/* PCI bus widths */
typedef enum {
ixgb_bus_width_unknown = 0,
ixgb_bus_width_32,
ixgb_bus_width_64
} ixgb_bus_width;
#define IXGB_ETH_LENGTH_OF_ADDRESS 6
#define IXGB_EEPROM_SIZE 64 /* Size in words */
#define SPEED_10000 10000
#define FULL_DUPLEX 2
#define IXGB_DELAY_BEFORE_RESET 10 /* allow 10ms after idling rx/tx units */
#define IXGB_DELAY_AFTER_RESET 1 /* allow 1ms after the reset */
#define IXGB_DELAY_AFTER_EE_RESET 10 /* allow 10ms after the EEPROM reset */
#define IXGB_DELAY_USECS_AFTER_LINK_RESET 13 /* allow 13 microseconds after the reset */
/* NOTE: this is MICROSECONDS */
#define MAX_RESET_ITERATIONS 8 /* number of iterations to get things right */
/* General Registers */
#define IXGB_CTRL0 0x00000 /* Device Control Register 0 - RW */
#define IXGB_CTRL1 0x00008 /* Device Control Register 1 - RW */
#define IXGB_STATUS 0x00010 /* Device Status Register - RO */
#define IXGB_EECD 0x00018 /* EEPROM/Flash Control/Data Register - RW */
#define IXGB_MFS 0x00020 /* Maximum Frame Size - RW */
/* Interrupt */
#define IXGB_ICR 0x00080 /* Interrupt Cause Read - R/clr */
#define IXGB_ICS 0x00088 /* Interrupt Cause Set - RW */
#define IXGB_IMS 0x00090 /* Interrupt Mask Set/Read - RW */
#define IXGB_IMC 0x00098 /* Interrupt Mask Clear - WO */
/* Receive */
#define IXGB_RCTL 0x00100 /* RX Control - RW */
#define IXGB_FCRTL 0x00108 /* Flow Control Receive Threshold Low - RW */
#define IXGB_FCRTH 0x00110 /* Flow Control Receive Threshold High - RW */
#define IXGB_RDBAL 0x00118 /* RX Descriptor Base Low - RW */
#define IXGB_RDBAH 0x0011C /* RX Descriptor Base High - RW */
#define IXGB_RDLEN 0x00120 /* RX Descriptor Length - RW */
#define IXGB_RDH 0x00128 /* RX Descriptor Head - RW */
#define IXGB_RDT 0x00130 /* RX Descriptor Tail - RW */
#define IXGB_RDTR 0x00138 /* RX Delay Timer Ring - RW */
#define IXGB_RXDCTL 0x00140 /* Receive Descriptor Control - RW */
#define IXGB_RAIDC 0x00148 /* Receive Adaptive Interrupt Delay Control - RW */
#define IXGB_RXCSUM 0x00158 /* Receive Checksum Control - RW */
#define IXGB_RA 0x00180 /* Receive Address Array Base - RW */
#define IXGB_RAL 0x00180 /* Receive Address Low [0:15] - RW */
#define IXGB_RAH 0x00184 /* Receive Address High [0:15] - RW */
#define IXGB_MTA 0x00200 /* Multicast Table Array [0:127] - RW */
#define IXGB_VFTA 0x00400 /* VLAN Filter Table Array [0:127] - RW */
#define IXGB_REQ_RX_DESCRIPTOR_MULTIPLE 8
/* Transmit */
#define IXGB_TCTL 0x00600 /* TX Control - RW */
#define IXGB_TDBAL 0x00608 /* TX Descriptor Base Low - RW */
#define IXGB_TDBAH 0x0060C /* TX Descriptor Base High - RW */
#define IXGB_TDLEN 0x00610 /* TX Descriptor Length - RW */
#define IXGB_TDH 0x00618 /* TX Descriptor Head - RW */
#define IXGB_TDT 0x00620 /* TX Descriptor Tail - RW */
#define IXGB_TIDV 0x00628 /* TX Interrupt Delay Value - RW */
#define IXGB_TXDCTL 0x00630 /* Transmit Descriptor Control - RW */
#define IXGB_TSPMT 0x00638 /* TCP Segmentation PAD & Min Threshold - RW */
#define IXGB_PAP 0x00640 /* Pause and Pace - RW */
#define IXGB_REQ_TX_DESCRIPTOR_MULTIPLE 8
/* Physical */
#define IXGB_PCSC1 0x00700 /* PCS Control 1 - RW */
#define IXGB_PCSC2 0x00708 /* PCS Control 2 - RW */
#define IXGB_PCSS1 0x00710 /* PCS Status 1 - RO */
#define IXGB_PCSS2 0x00718 /* PCS Status 2 - RO */
#define IXGB_XPCSS 0x00720 /* 10GBASE-X PCS Status (or XGXS Lane Status) - RO */
#define IXGB_UCCR 0x00728 /* Unilink Circuit Control Register */
#define IXGB_XPCSTC 0x00730 /* 10GBASE-X PCS Test Control */
#define IXGB_MACA 0x00738 /* MDI Autoscan Command and Address - RW */
#define IXGB_APAE 0x00740 /* Autoscan PHY Address Enable - RW */
#define IXGB_ARD 0x00748 /* Autoscan Read Data - RO */
#define IXGB_AIS 0x00750 /* Autoscan Interrupt Status - RO */
#define IXGB_MSCA 0x00758 /* MDI Single Command and Address - RW */
#define IXGB_MSRWD 0x00760 /* MDI Single Read and Write Data - RW, RO */
/* Wake-up */
#define IXGB_WUFC 0x00808 /* Wake Up Filter Control - RW */
#define IXGB_WUS 0x00810 /* Wake Up Status - RO */
#define IXGB_FFLT 0x01000 /* Flexible Filter Length Table - RW */
#define IXGB_FFMT 0x01020 /* Flexible Filter Mask Table - RW */
#define IXGB_FTVT 0x01420 /* Flexible Filter Value Table - RW */
/* Statistics */
#define IXGB_TPRL 0x02000 /* Total Packets Received (Low) */
#define IXGB_TPRH 0x02004 /* Total Packets Received (High) */
#define IXGB_GPRCL 0x02008 /* Good Packets Received Count (Low) */
#define IXGB_GPRCH 0x0200C /* Good Packets Received Count (High) */
#define IXGB_BPRCL 0x02010 /* Broadcast Packets Received Count (Low) */
#define IXGB_BPRCH 0x02014 /* Broadcast Packets Received Count (High) */
#define IXGB_MPRCL 0x02018 /* Multicast Packets Received Count (Low) */
#define IXGB_MPRCH 0x0201C /* Multicast Packets Received Count (High) */
#define IXGB_UPRCL 0x02020 /* Unicast Packets Received Count (Low) */
#define IXGB_UPRCH 0x02024 /* Unicast Packets Received Count (High) */
#define IXGB_VPRCL 0x02028 /* VLAN Packets Received Count (Low) */
#define IXGB_VPRCH 0x0202C /* VLAN Packets Received Count (High) */
#define IXGB_JPRCL 0x02030 /* Jumbo Packets Received Count (Low) */
#define IXGB_JPRCH 0x02034 /* Jumbo Packets Received Count (High) */
#define IXGB_GORCL 0x02038 /* Good Octets Received Count (Low) */
#define IXGB_GORCH 0x0203C /* Good Octets Received Count (High) */
#define IXGB_TORL 0x02040 /* Total Octets Received (Low) */
#define IXGB_TORH 0x02044 /* Total Octets Received (High) */
#define IXGB_RNBC 0x02048 /* Receive No Buffers Count */
#define IXGB_RUC 0x02050 /* Receive Undersize Count */
#define IXGB_ROC 0x02058 /* Receive Oversize Count */
#define IXGB_RLEC 0x02060 /* Receive Length Error Count */
#define IXGB_CRCERRS 0x02068 /* CRC Error Count */
#define IXGB_ICBC 0x02070 /* Illegal control byte in mid-packet Count */
#define IXGB_ECBC 0x02078 /* Error Control byte in mid-packet Count */
#define IXGB_MPC 0x02080 /* Missed Packets Count */
#define IXGB_TPTL 0x02100 /* Total Packets Transmitted (Low) */
#define IXGB_TPTH 0x02104 /* Total Packets Transmitted (High) */
#define IXGB_GPTCL 0x02108 /* Good Packets Transmitted Count (Low) */
#define IXGB_GPTCH 0x0210C /* Good Packets Transmitted Count (High) */
#define IXGB_BPTCL 0x02110 /* Broadcast Packets Transmitted Count (Low) */
#define IXGB_BPTCH 0x02114 /* Broadcast Packets Transmitted Count (High) */
#define IXGB_MPTCL 0x02118 /* Multicast Packets Transmitted Count (Low) */
#define IXGB_MPTCH 0x0211C /* Multicast Packets Transmitted Count (High) */
#define IXGB_UPTCL 0x02120 /* Unicast Packets Transmitted Count (Low) */
#define IXGB_UPTCH 0x02124 /* Unicast Packets Transmitted Count (High) */
#define IXGB_VPTCL 0x02128 /* VLAN Packets Transmitted Count (Low) */
#define IXGB_VPTCH 0x0212C /* VLAN Packets Transmitted Count (High) */
#define IXGB_JPTCL 0x02130 /* Jumbo Packets Transmitted Count (Low) */
#define IXGB_JPTCH 0x02134 /* Jumbo Packets Transmitted Count (High) */
#define IXGB_GOTCL 0x02138 /* Good Octets Transmitted Count (Low) */
#define IXGB_GOTCH 0x0213C /* Good Octets Transmitted Count (High) */
#define IXGB_TOTL 0x02140 /* Total Octets Transmitted Count (Low) */
#define IXGB_TOTH 0x02144 /* Total Octets Transmitted Count (High) */
#define IXGB_DC 0x02148 /* Defer Count */
#define IXGB_PLT64C 0x02150 /* Packet Transmitted was less than 64 bytes Count */
#define IXGB_TSCTC 0x02170 /* TCP Segmentation Context Transmitted Count */
#define IXGB_TSCTFC 0x02178 /* TCP Segmentation Context Tx Fail Count */
#define IXGB_IBIC 0x02180 /* Illegal byte during Idle stream count */
#define IXGB_RFC 0x02188 /* Remote Fault Count */
#define IXGB_LFC 0x02190 /* Local Fault Count */
#define IXGB_PFRC 0x02198 /* Pause Frame Receive Count */
#define IXGB_PFTC 0x021A0 /* Pause Frame Transmit Count */
#define IXGB_MCFRC 0x021A8 /* MAC Control Frames (non-Pause) Received Count */
#define IXGB_MCFTC 0x021B0 /* MAC Control Frames (non-Pause) Transmitted Count */
#define IXGB_XONRXC 0x021B8 /* XON Received Count */
#define IXGB_XONTXC 0x021C0 /* XON Transmitted Count */
#define IXGB_XOFFRXC 0x021C8 /* XOFF Received Count */
#define IXGB_XOFFTXC 0x021D0 /* XOFF Transmitted Count */
#define IXGB_RJC 0x021D8 /* Receive Jabber Count */
/* CTRL0 Bit Masks */
#define IXGB_CTRL0_LRST 0x00000008
#define IXGB_CTRL0_JFE 0x00000010
#define IXGB_CTRL0_SDP0 0x00040000
#define IXGB_CTRL0_SDP1 0x00080000
#define IXGB_CTRL0_SDP2 0x00100000
#define IXGB_CTRL0_SDP3 0x00200000
#define IXGB_CTRL0_SDP0_DIR 0x00400000
#define IXGB_CTRL0_SDP1_DIR 0x00800000
#define IXGB_CTRL0_SDP2_DIR 0x01000000
#define IXGB_CTRL0_SDP3_DIR 0x02000000
#define IXGB_CTRL0_RST 0x04000000
#define IXGB_CTRL0_RPE 0x08000000
#define IXGB_CTRL0_TPE 0x10000000
#define IXGB_CTRL0_VME 0x40000000
/* CTRL1 Bit Masks */
#define IXGB_CTRL1_EE_RST 0x00002000
/* STATUS Bit Masks */
#define IXGB_STATUS_LU 0x00000002
#define IXGB_STATUS_TXOFF 0x00000010
#define IXGB_STATUS_PCI_SPD 0x00000800
#define IXGB_STATUS_BUS64 0x00001000
#define IXGB_STATUS_PCIX_MODE 0x00002000
#define IXGB_STATUS_PCIX_SPD_MASK 0x0000C000
#define IXGB_STATUS_PCIX_SPD_66 0x00000000
#define IXGB_STATUS_PCIX_SPD_100 0x00004000
#define IXGB_STATUS_PCIX_SPD_133 0x00008000
/* EECD Bit Masks */
#define IXGB_EECD_SK 0x00000001
#define IXGB_EECD_CS 0x00000002
#define IXGB_EECD_DI 0x00000004
#define IXGB_EECD_DO 0x00000008
/* MFS */
#define IXGB_MFS_SHIFT 16
/* Interrupt Register Bit Masks (used for ICR, ICS, IMS, and IMC) */
#define IXGB_INT_TXDW 0x00000001
#define IXGB_INT_LSC 0x00000004
#define IXGB_INT_RXSEQ 0x00000008
#define IXGB_INT_RXDMT0 0x00000010
#define IXGB_INT_RXO 0x00000040
#define IXGB_INT_RXT0 0x00000080
/* RCTL Bit Masks */
#define IXGB_RCTL_RXEN 0x00000002
#define IXGB_RCTL_UPE 0x00000008
#define IXGB_RCTL_MPE 0x00000010
#define IXGB_RCTL_RDMTS_1_2 0x00000000
#define IXGB_RCTL_MO_SHIFT 12
#define IXGB_RCTL_BAM 0x00008000
#define IXGB_RCTL_BSIZE_2048 0x00000000
#define IXGB_RCTL_BSIZE_4096 0x00010000
#define IXGB_RCTL_BSIZE_8192 0x00020000
#define IXGB_RCTL_BSIZE_16384 0x00030000
#define IXGB_RCTL_VFE 0x00040000
#define IXGB_RCTL_CFIEN 0x00080000
#define IXGB_RCTL_CFI 0x00100000
#define IXGB_RCTL_CFF 0x00800000
#define IXGB_RCTL_SECRC 0x04000000
/* FCRTL Bit Masks */
#define IXGB_FCRTL_XONE 0x80000000
/* RXDCTL Bit Masks */
#define IXGB_RXDCTL_PTHRESH_SHIFT 0
#define IXGB_RXDCTL_HTHRESH_SHIFT 9
#define IXGB_RXDCTL_WTHRESH_SHIFT 18
/* RAIDC Bit Masks */
#define IXGB_RAIDC_DELAY_SHIFT 11
#define IXGB_RAIDC_POLL_SHIFT 20
#define IXGB_RAIDC_RXT_GATE 0x40000000
#define IXGB_RAIDC_EN 0x80000000
/* RXCSUM Bit Masks */
#define IXGB_RXCSUM_TUOFL 0x00000200
/* RAH Bit Masks */
#define IXGB_RAH_AV 0x80000000
/* TCTL Bit Masks */
#define IXGB_TCTL_TCE 0x00000001
#define IXGB_TCTL_TXEN 0x00000002
#define IXGB_TCTL_TPDE 0x00000004
/* TXDCTL Bit Masks */
#define IXGB_TXDCTL_HTHRESH_SHIFT 8
/* TSPMT Bit Masks */
/* PAP Bit Masks */
/* PCSC1 Bit Masks */
/* PCSC2 Bit Masks */
/* PCSS1 Bit Masks */
/* PCSS2 Bit Masks */
/* XPCSS Bit Masks */
#define IXGB_XPCSS_ALIGN_STATUS 0x00001000
/* XPCSTC Bit Masks */
/* MSCA bit Masks */
/* New Protocol Address */
#define IXGB_MSCA_NP_ADDR_SHIFT 0
/* Either Device Type or Register Address,depending on ST_CODE */
#define IXGB_MSCA_DEV_TYPE_SHIFT 16
#define IXGB_MSCA_PHY_ADDR_SHIFT 21
#define IXGB_MSCA_ADDR_CYCLE 0x00000000
#define IXGB_MSCA_WRITE 0x04000000
#define IXGB_MSCA_READ 0x08000000
/* Initiate command, self-clearing when command completes */
#define IXGB_MSCA_MDI_COMMAND 0x40000000
/*MDI In Progress Enable. */
/* MSRWD bit masks */
#define IXGB_MSRWD_READ_DATA_SHIFT 16
/* Definitions for the TXN17401 devices on the MDIO bus. */
#define IXGB_PHY_ADDRESS 0x0 /* Single PHY, multiple "Devices" */
/* Five bit Device IDs */
#define TXN17401_PMA_PMD_DID 0x01
#define TXN17401_PCS_DID 0x03
#define TXN17401_XGXS_DID 0x04
/* PMA/PMD registers and bit definitions. */
/* Note: This is a very limited set of definitions, */
/* only implemented features are defined. */
#define TXN17401_PMA_PMD_CR1 0x0000
#define TXN17401_PMA_PMD_CR1_RESET 0x8000
struct ixgb_rx_desc {
uint64_t buff_addr;
uint16_t length;
uint16_t reserved;
uint8_t status;
uint8_t errors;
uint16_t special;
};
#define IXGB_RX_DESC_STATUS_DD 0x01
#define IXGB_RX_DESC_STATUS_EOP 0x02
#define IXGB_RX_DESC_STATUS_IXSM 0x04
#define IXGB_RX_DESC_STATUS_VP 0x08
#define IXGB_RX_DESC_STATUS_TCPCS 0x20
#define IXGB_RX_DESC_ERRORS_CE 0x01
#define IXGB_RX_DESC_ERRORS_SE 0x02
#define IXGB_RX_DESC_ERRORS_P 0x08
#define IXGB_RX_DESC_ERRORS_TCPE 0x20
#define IXGB_RX_DESC_ERRORS_RXE 0x80
#define IXGB_RX_DESC_SPECIAL_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
struct ixgb_tx_desc {
uint64_t buff_addr;
uint32_t cmd_type_len;
uint8_t status;
uint8_t popts;
uint16_t vlan;
};
#define IXGB_TX_DESC_CMD_EOP 0x01000000
#define IXGB_TX_DESC_CMD_TSE 0x04000000
#define IXGB_TX_DESC_CMD_RS 0x08000000
#define IXGB_TX_DESC_CMD_VLE 0x40000000
#define IXGB_TX_DESC_CMD_IDE 0x80000000
#define IXGB_TX_DESC_TYPE 0x00100000
#define IXGB_TX_DESC_STATUS_DD 0x01
#define IXGB_TX_DESC_POPTS_IXSM 0x01
#define IXGB_TX_DESC_POPTS_TXSM 0x02
struct ixgb_context_desc {
uint8_t ipcss;
uint8_t ipcso;
uint16_t ipcse;
uint8_t tucss;
uint8_t tucso;
uint16_t tucse;
uint32_t cmd_type_len;
uint8_t status;
uint8_t hdr_len;
uint16_t mss;
};
#define IXGB_CONTEXT_DESC_CMD_TCP 0x01000000
#define IXGB_CONTEXT_DESC_CMD_IP 0x02000000
#define IXGB_CONTEXT_DESC_CMD_TSE 0x04000000
#define IXGB_CONTEXT_DESC_CMD_RS 0x08000000
#define IXGB_CONTEXT_DESC_CMD_IDE 0x80000000
#define IXGB_CONTEXT_DESC_TYPE 0x00000000
/* Filters */
#define IXGB_RAR_ENTRIES 16 /* Number of entries in Rx Address array */
#define IXGB_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
#define IXGB_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
#define ENET_HEADER_SIZE 14
#define ENET_FCS_LENGTH 4
#define IXGB_MAX_NUM_MULTICAST_ADDRESSES 128
#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS 60
#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS 1514
#define IXGB_MAX_JUMBO_FRAME_SIZE 0x3F00
/* Phy Addresses */
/*
* This is a little-endian specific check.
*/
#define IS_MULTICAST(Address) \
(boolean_t)(((uint8_t *)(Address))[0] & ((uint8_t)0x01))
/*
* Check whether an address is broadcast.
*/
#define IS_BROADCAST(Address) \
((((uint8_t *)(Address))[0] == ((uint8_t)0xff)) && (((uint8_t *)(Address))[1] == ((uint8_t)0xff)))
/* Flow control parameters */
struct ixgb_fc {
uint32_t high_water; /* Flow Control High-water */
uint32_t low_water; /* Flow Control Low-water */
uint16_t pause_time; /* Flow Control Pause timer */
boolean_t send_xon; /* Flow control send XON */
ixgb_fc_type type; /* Type of flow control */
};
/* The historical defaults for the flow control values are given below. */
/* Phy definitions */
#define IXGB_MAX_PHY_REG_ADDRESS 0xFFFF
#define IXGB_MAX_PHY_ADDRESS 31
#define IXGB_MAX_PHY_DEV_TYPE 31
/* Bus parameters */
struct ixgb_bus {
ixgb_bus_speed speed;
ixgb_bus_width width;
ixgb_bus_type type;
};
struct ixgb_hw {
uint8_t *hw_addr; /* Base Address of the hardware */
void *back; /* Pointer to OS-dependent struct */
struct ixgb_fc fc; /* Flow control parameters */
struct ixgb_bus bus; /* Bus parameters */
uint32_t phy_id; /* Phy Identifier */
uint32_t phy_addr; /* XGMII address of Phy */
ixgb_mac_type mac_type; /* Identifier for MAC controller */
uint32_t max_frame_size; /* Maximum frame size supported */
uint32_t mc_filter_type; /* Multicast filter hash type */
uint32_t num_mc_addrs; /* Number of current Multicast addrs*/
uint8_t curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS]; /* Individual address currently programmed in MAC */
uint32_t num_tx_desc; /* Number of Transmit descriptors */
uint32_t num_rx_desc; /* Number of Receive descriptors */
uint32_t rx_buffer_size; /* Size of Receive buffer */
boolean_t link_up; /* TRUE if link is valid */
boolean_t adapter_stopped; /* State of adapter */
uint16_t device_id; /* device id from PCI configuration space */
uint16_t vendor_id; /* vendor id from PCI configuration space */
uint8_t revision_id; /* revision id from PCI configuration space */
uint16_t subsystem_vendor_id;/* subsystem vendor id from PCI configuration space */
uint16_t subsystem_id; /* subsystem id from PCI configuration space */
uint16_t pci_cmd_word; /* PCI command register id from PCI configuration space */
uint16_t eeprom[IXGB_EEPROM_SIZE]; /* EEPROM contents read at init time */
uint64_t io_base; /* Our I/O mapped location */
uint32_t lastLFC;
uint32_t lastRFC;
};
struct ixgb_hw_stats {
uint64_t tprl;
uint64_t tprh;
uint64_t gprcl;
uint64_t gprch;
uint64_t bprcl;
uint64_t bprch;
uint64_t mprcl;
uint64_t mprch;
uint64_t uprcl;
uint64_t uprch;
uint64_t vprcl;
uint64_t vprch;
uint64_t jprcl;
uint64_t jprch;
uint64_t gorcl;
uint64_t gorch;
uint64_t torl;
uint64_t torh;
uint64_t rnbc;
uint64_t ruc;
uint64_t roc;
uint64_t rlec;
uint64_t crcerrs;
uint64_t icbc;
uint64_t ecbc;
uint64_t mpc;
uint64_t tptl;
uint64_t tpth;
uint64_t gptcl;
uint64_t gptch;
uint64_t bptcl;
uint64_t bptch;
uint64_t mptcl;
uint64_t mptch;
uint64_t uptcl;
uint64_t uptch;
uint64_t vptcl;
uint64_t vptch;
uint64_t jptcl;
uint64_t jptch;
uint64_t gotcl;
uint64_t gotch;
uint64_t totl;
uint64_t toth;
uint64_t dc;
uint64_t plt64c;
uint64_t tsctc;
uint64_t tsctfc;
uint64_t ibic;
uint64_t rfc;
uint64_t lfc;
uint64_t pfrc;
uint64_t pftc;
uint64_t mcfrc;
uint64_t mcftc;
uint64_t xonrxc;
uint64_t xontxc;
uint64_t xoffrxc;
uint64_t xofftxc;
uint64_t rjc;
};
/* Function Prototypes */
extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw);
extern boolean_t ixgb_init_hw(struct ixgb_hw *hw);
extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw);
extern void ixgb_init_rx_addrs(struct ixgb_hw *hw);
extern void ixgb_check_for_link(struct ixgb_hw *hw);
extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw);
extern boolean_t mac_addr_valid(uint8_t *mac_addr);
extern uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
uint32_t reg_addr,
uint32_t phy_addr,
uint32_t device_type);
extern void ixgb_write_phy_reg(struct ixgb_hw *hw,
uint32_t reg_addr,
uint32_t phy_addr,
uint32_t device_type,
uint16_t data);
extern void ixgb_rar_set(struct ixgb_hw *hw,
uint8_t *addr,
uint32_t index);
/* Filters (multicast, vlan, receive) */
extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
uint8_t * mc_addr_list,
uint32_t mc_addr_count,
uint32_t pad);
/* Vfta functions */
extern void ixgb_write_vfta(struct ixgb_hw *hw,
uint32_t offset,
uint32_t value);
extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */
void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
/* Everything else */
void ixgb_led_on(struct ixgb_hw *hw);
void ixgb_led_off(struct ixgb_hw *hw);
void ixgb_write_pci_cfg(struct ixgb_hw *hw,
uint32_t reg,
uint16_t * value);
#endif /* _IXGB_HW_H_ */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#ifndef _IXGB_IDS_H_
#define _IXGB_IDS_H_
/**********************************************************************
** The Device and Vendor IDs for 10 Gigabit MACs
**********************************************************************/
#define INTEL_VENDOR_ID 0x8086
#define INTEL_SUBVENDOR_ID 0x8086
#define IXGB_DEVICE_ID_82597EX 0x1048
#define IXGB_SUBDEVICE_ID_A11F 0xA11F /* Adapter-OEM-1310nm-Fiber */
#define IXGB_SUBDEVICE_ID_A01F 0xA01F /* Adapter-Retail-1310nm-Fiber */
#endif /* #ifndef _IXGB_IDS_H_ */
/* End of File */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#define __IXGB_MAIN__
#include "ixgb.h"
char ixgb_driver_name[] = "ixgb";
char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
char ixgb_driver_version[] = "1.0.47-k1";
char ixgb_copyright[] = "Copyright (c) 2001-2003 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
* For selecting devices to load on private driver_data field (last one)
* stores an index into ixgb_strings.
* Wildcard entries (PCI_ANY_ID) should come last
* Last entry must be all 0s
*
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, String Index }
*/
static struct pci_device_id ixgb_pci_tbl[] __devinitdata = {
/* Intel(R) PRO/10GbE Network Connection */
{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
INTEL_SUBVENDOR_ID, IXGB_SUBDEVICE_ID_A11F, 0, 0, 0},
{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
INTEL_SUBVENDOR_ID, IXGB_SUBDEVICE_ID_A01F, 0, 0, 0},
/* Generic */
{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */
{0,}
};
MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
static char *ixgb_strings[] = {
"Intel(R) PRO/10GbE Network Connection"
};
/* Local Function Prototypes */
int ixgb_up(struct ixgb_adapter *adapter);
void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
void ixgb_reset(struct ixgb_adapter *adapter);
static int ixgb_init_module(void);
static void ixgb_exit_module(void);
static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void ixgb_remove(struct pci_dev *pdev);
static void ixgb_sw_init(struct ixgb_adapter *adapter);
static int ixgb_open(struct net_device *netdev);
static int ixgb_close(struct net_device *netdev);
static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_configure_tx(struct ixgb_adapter *adapter);
static void ixgb_configure_rx(struct ixgb_adapter *adapter);
static void ixgb_setup_rctl(struct ixgb_adapter *adapter);
static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);
static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);
static void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
static void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_set_multi(struct net_device *netdev);
static void ixgb_watchdog(unsigned long data);
static inline boolean_t ixgb_tso(struct ixgb_adapter *adapter,
struct sk_buff *skb);
static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static void ixgb_tx_timeout(struct net_device *netdev);
static void ixgb_tx_timeout_task(struct net_device *netdev);
static void ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
static int ixgb_set_mac(struct net_device *netdev, void *p);
static void ixgb_update_stats(struct ixgb_adapter *adapter);
static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
static void ixgb_intr(int irq, void *data, struct pt_regs *regs);
static void ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
#ifdef CONFIG_IXGB_NAPI
static int ixgb_poll(struct net_device *netdev, int *budget);
#else
static void ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
#endif
static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
struct ixgb_rx_desc *rx_desc,
struct sk_buff *skb);
static int ixgb_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
static int ixgb_suspend(struct pci_dev *pdev, uint32_t state);
struct notifier_block ixgb_notifier_reboot = {
.notifier_call = ixgb_notify_reboot,
.next = NULL,
.priority = 0
};
/* Exported from other modules */
extern void ixgb_check_options(struct ixgb_adapter *adapter);
extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
static struct pci_driver ixgb_driver = {
.name = ixgb_driver_name,
.id_table = ixgb_pci_tbl,
.probe = ixgb_probe,
.remove = __devexit_p(ixgb_remove),
/* Power Managment Hooks */
.suspend = NULL,
.resume = NULL
};
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
MODULE_LICENSE("GPL");
/* some defines for controlling descriptor fetches in h/w */
#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */
#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is
pushed this many descriptors from head */
#define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */
/**
* ixgb_init_module - Driver Registration Routine.
*
* ixgb_init_module is the first routine called when the driver is
* loaded. All it does is register with the PCI subsystem.
**/
static int __init
ixgb_init_module(void)
{
int ret;
IXGB_DBG("ixgb_init_module\n");
printk(KERN_INFO "%s - version %s\n", ixgb_driver_string,
ixgb_driver_version);
printk(KERN_INFO "%s\n", ixgb_copyright);
#ifdef CONFIG_IXGB_NAPI
printk(KERN_INFO "NAPI Enabled\n");
#endif
ret = pci_module_init(&ixgb_driver);
if(ret >= 0) {
register_reboot_notifier(&ixgb_notifier_reboot);
}
return ret;
}
module_init(ixgb_init_module);
/**
* ixgb_exit_module - Driver Exit Cleanup Routine.
*
* ixgb_exit_module is called just before the driver is removed
* from memory.
**/
static void __exit
ixgb_exit_module(void)
{
IXGB_DBG("ixgb_exit_module\n");
unregister_reboot_notifier(&ixgb_notifier_reboot);
pci_unregister_driver(&ixgb_driver);
}
module_exit(ixgb_exit_module);
/**
* ixgb_up - Driver ifconfig UP routine.
*
* ixgb_up is called to initialize and bring online an interface.
* @param adapter board private structure
**/
int
ixgb_up(struct ixgb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
IXGB_DBG("ixgb_up\n");
if(request_irq(netdev->irq, &ixgb_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev)) {
IXGB_DBG("%s: request_irq failed\n", netdev->name);
return -1;
}
/* disable interrupts and get the hardware into a known state */
IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
/* hardware was reset in probe/down, we need to reload some things */
ixgb_set_multi(netdev);
ixgb_restore_vlan(adapter);
ixgb_configure_tx(adapter);
ixgb_setup_rctl(adapter);
ixgb_configure_rx(adapter);
ixgb_alloc_rx_buffers(adapter);
mod_timer(&adapter->watchdog_timer, jiffies);
ixgb_irq_enable(adapter);
IXGB_DBG("ixgb_up: RAH_0 is <%x>\n", IXGB_READ_REG(&adapter->hw, RAH));
IXGB_DBG("ixgb_up: RDBAL is <%x>\n",
IXGB_READ_REG(&adapter->hw, RDBAL));
return 0;
}
/**
* ixgb_down - Driver ifconfig DOWN routine.
*
* ixgb_down is called to uninitialize and take offline an interface.
* @param adapter board private structure
* @param kill_watchdog
**/
void
ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
{
struct net_device *netdev = adapter->netdev;
IXGB_DBG("ixgb_down\n");
ixgb_irq_disable(adapter);
free_irq(netdev->irq, netdev);
if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
ixgb_reset(adapter);
ixgb_clean_tx_ring(adapter);
ixgb_clean_rx_ring(adapter);
}
/**
* ixgb_reset - hardware reset.
*
* ixgb_reset is called to initialize hardware to a known state.
* @param adapter board private structure
**/
void
ixgb_reset(struct ixgb_adapter *adapter)
{
IXGB_DBG("ixgb_reset\n");
ixgb_adapter_stop(&adapter->hw);
if(!ixgb_init_hw(&adapter->hw))
IXGB_DBG("ixgb_init_hw failed.\n");
}
/**
* ixgb_probe - Device Initialization Routine.
* @param pdev PCI device information struct
* @param ent entry in ixgb_pci_table
*
* Returns 0 on success, negative on failure
**/
static int __devinit
ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct ixgb_adapter *adapter;
static int cards_found = 0;
unsigned long mmio_start;
int mmio_len;
int pci_using_dac;
int i;
IXGB_DBG("ixgb_probe\n");
if((i = pci_enable_device(pdev))) {
IXGB_ERR("pci_enable_device failed\n");
return i;
}
if(!(i = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) {
pci_using_dac = 1;
} else {
if((i = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) {
IXGB_ERR("No usable DMA configuration, aborting\n");
return i;
}
pci_using_dac = 0;
}
if((i = pci_request_regions(pdev, ixgb_driver_name))) {
IXGB_ERR("Failed to reserve PCI I/O and Memory resources.\n");
return i;
}
pci_set_master(pdev);
/* alloc_etherdev clears the memory for us */
netdev = alloc_etherdev(sizeof(struct ixgb_adapter));
if(!netdev) {
IXGB_ERR("Unable to allocate net_device struct\n");
goto err_alloc_etherdev;
}
SET_MODULE_OWNER(netdev);
pci_set_drvdata(pdev, netdev);
adapter = netdev->priv;
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
mmio_start = pci_resource_start(pdev, BAR_0);
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
if(!adapter->hw.hw_addr)
goto err_ioremap;
for(i = BAR_1; i <= BAR_5; i++) {
if(pci_resource_len(pdev, i) == 0)
continue;
if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
}
IXGB_DBG("mmio_start<%lx> hw_addr<%p>\n", mmio_start,
adapter->hw.hw_addr);
netdev->open = &ixgb_open;
netdev->stop = &ixgb_close;
netdev->hard_start_xmit = &ixgb_xmit_frame;
netdev->get_stats = &ixgb_get_stats;
netdev->set_multicast_list = &ixgb_set_multi;
netdev->set_mac_address = &ixgb_set_mac;
netdev->change_mtu = &ixgb_change_mtu;
netdev->do_ioctl = &ixgb_ioctl;
netdev->tx_timeout = &ixgb_tx_timeout;
netdev->watchdog_timeo = HZ;
#ifdef CONFIG_IXGB_NAPI
netdev->poll = &ixgb_poll;
netdev->weight = 64;
#endif
netdev->vlan_rx_register = ixgb_vlan_rx_register;
netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;
netdev->irq = pdev->irq;
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len;
netdev->base_addr = adapter->hw.io_base;
adapter->bd_number = cards_found;
adapter->id_string = ixgb_strings[ent->driver_data];
adapter->link_speed = 0;
adapter->link_duplex = 0;
/* setup the private structure */
ixgb_sw_init(adapter);
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
#ifdef NETIF_F_TSO
netdev->features |= NETIF_F_TSO;
#endif
if(pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* make sure the EEPROM is good */
if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
IXGB_DBG("Invalid EEPROM checksum.\n");
goto err_eeprom;
}
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
if(!is_valid_ether_addr(netdev->dev_addr)) {
IXGB_DBG("Invalid MAC address in EEPROM.\n");
goto err_eeprom;
}
adapter->max_data_per_txd = IXGB_MAX_JUMBO_FRAME_SIZE;
adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &ixgb_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
INIT_WORK(&adapter->tx_timeout_task,
(void (*)(void *))ixgb_tx_timeout_task, netdev);
register_netdev(netdev);
memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
adapter->ifname[IFNAMSIZ-1] = 0;
/* we're going to reset, so assume we have no link for now */
netif_carrier_off(netdev);
netif_stop_queue(netdev);
printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
ixgb_check_options(adapter);
/* reset the hardware with the new settings */
ixgb_reset(adapter);
cards_found++;
return 0;
err_eeprom:
iounmap(adapter->hw.hw_addr);
err_ioremap:
pci_release_regions(pdev);
kfree(netdev);
err_alloc_etherdev:
return -ENOMEM;
}
/**
* ixgb_remove - Device Removal Routine.
* @param pdev PCI device information struct
*
* ixgb_remove is called by the PCI subsystem to alert the driver
* that it should release a PCI device. The could be caused by a
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
static void __devexit
ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
IXGB_DBG("ixgb_remove\n");
unregister_netdev(netdev);
#ifdef ETHTOOL_IDENTIFY
ixgb_identify_stop(adapter);
#endif
iounmap((void *) adapter->hw.hw_addr);
pci_release_regions(pdev);
kfree(netdev);
}
/**
* ixgb_sw_init - Initialize general software structures (struct ixgb_adapter).
* @param adapter board private structure to initialize
*
* ixgb_sw_init initializes the adapter private data structure.
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
static void __devinit
ixgb_sw_init(struct ixgb_adapter *adapter)
{
struct ixgb_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
IXGB_DBG("ixgb_sw_init\n");
/* PCI config space info */
pci_read_config_word(pdev, PCI_VENDOR_ID, &hw->vendor_id);
pci_read_config_word(pdev, PCI_DEVICE_ID, &hw->device_id);
pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID,
&hw->subsystem_vendor_id);
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id);
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
if(hw->device_id == IXGB_DEVICE_ID_82597EX)
hw->mac_type = ixgb_82597;
else {
/* should never have loaded on this device */
printk(KERN_ERR "ixgb: unsupported device id\n");
}
/* enable flow control to be programmed */
hw->fc.send_xon = 1;
atomic_set(&adapter->irq_sem, 1);
}
/**
* ixgb_open - Called when a network interface is made active.
* @param netdev network interface device structure
*
* Returns 0 on success, negative value on failure
*
* The open entry point is called when a network interface is made
* active by the system (IFF_UP). At this point all resources needed
* for transmit and receive operations are allocated, the interrupt
* handler is registered with the OS, the watchdog timer is started,
* and the stack is notified that the interface is ready.
**/
static int
ixgb_open(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
IXGB_DBG("ixgb_open\n");
/* allocate transmit descriptors */
if(ixgb_setup_tx_resources(adapter)) {
IXGB_DBG("ixgb_open: failed ixgb_setup_tx_resources.\n");
goto err_setup_tx;
}
/* allocate receive descriptors and buffers */
if(ixgb_setup_rx_resources(adapter)) {
IXGB_DBG("ixgb_open: failed ixgb_setup_rx_resources.\n");
goto err_setup_rx;
}
if(ixgb_up(adapter))
goto err_up;
return 0;
err_up:
ixgb_free_rx_resources(adapter);
err_setup_rx:
ixgb_free_tx_resources(adapter);
err_setup_tx:
ixgb_reset(adapter);
return -EBUSY;
}
/**
* ixgb_close - Disables a network interface.
* @param netdev network interface device structure
*
* Returns 0, this is not allowed to fail
*
* The close entry point is called when an interface is de-activated
* by the OS. The hardware is still under the drivers control, but
* needs to be disabled. A global MAC reset is issued to stop the
* hardware, and all transmit and receive resources are freed.
**/
static int
ixgb_close(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
IXGB_DBG("ixgb_close\n");
ixgb_down(adapter, TRUE);
ixgb_free_tx_resources(adapter);
ixgb_free_rx_resources(adapter);
return 0;
}
/**
* ixgb_setup_tx_resources - allocate Tx resources (Descriptors).
* @param adapter board private structure
*
* Return 0 on success, negative on failure
**/
static int
ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
int size;
IXGB_DBG("ixgb_setup_tx_resources\n");
size = sizeof(struct ixgb_buffer) * txdr->count;
txdr->buffer_info = kmalloc(size, GFP_KERNEL);
if(!txdr->buffer_info) {
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
/* round up to nearest 4K */
txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
IXGB_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
if(!txdr->desc) {
kfree(txdr->buffer_info);
return -ENOMEM;
}
memset(txdr->desc, 0, txdr->size);
IXGB_DBG("txdr->desc <%p>\n", txdr->desc);
IXGB_DBG("txdr->next_to_use = <%p>\n", &txdr->next_to_use);
IXGB_DBG("txdr->next_to_clean = <%p>\n", &txdr->next_to_clean);
txdr->next_to_use = 0;
txdr->next_to_clean = 0;
return 0;
}
/**
* ixgb_configure_tx - Configure 82597 Transmit Unit after Reset.
* @adapter board private structure
*
* Configure the Tx unit of the MAC after a reset.
**/
static void
ixgb_configure_tx(struct ixgb_adapter *adapter)
{
uint32_t tctl;
uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
uint64_t tdba = adapter->tx_ring.dma;
struct ixgb_hw *hw = &adapter->hw;
IXGB_DBG("ixgb_configure_tx\n");
/* Setup the Base and Length of the Tx Descriptor Ring
* tx_ring.dma can be either a 32 or 64 bit value
*/
IXGB_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
IXGB_WRITE_REG(hw, TDBAH, (tdba >> 32));
IXGB_WRITE_REG(hw, TDLEN, tdlen);
/* Setup the HW Tx Head and Tail descriptor pointers */
IXGB_WRITE_REG(hw, TDH, 0);
IXGB_WRITE_REG(hw, TDT, 0);
/* don't set up txdctl, it induces performance problems if
* configured incorrectly
txdctl = TXDCTL_PTHRESH_DEFAULT; // prefetch txds below this threshold
txdctl |= (TXDCTL_HTHRESH_DEFAULT // only prefetch if there are this many ready
<< IXGB_TXDCTL_HTHRESH_SHIFT);
IXGB_WRITE_REG (hw, TXDCTL, txdctl);
*/
/* Set the Tx Interrupt Delay register */
IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
/* Program the Transmit Control Register */
tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
IXGB_WRITE_REG(hw, TCTL, tctl);
/* Setup Transmit Descriptor Settings for this adapter */
adapter->tx_cmd_type =
IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS
| (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
}
/**
* ixgb_setup_rx_resources - allocate Rx resources (Descriptors).
* @param adapter board private structure
*
* Returns 0 on success, negative on failure
**/
static int
ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
int size;
IXGB_DBG("ixgb_setup_rx_resources.\n");
size = sizeof(struct ixgb_buffer) * rxdr->count;
rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
if(!rxdr->buffer_info) {
return -ENOMEM;
}
memset(rxdr->buffer_info, 0, size);
/* Round up to nearest 4K */
rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
IXGB_ROUNDUP(rxdr->size, 4096);
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
if(!rxdr->desc) {
IXGB_DBG("pci_alloc_consistent failed.\n");
kfree(rxdr->buffer_info);
return -ENOMEM;
}
memset(rxdr->desc, 0, rxdr->size);
IXGB_DBG("rxdr->desc <%p>\n", rxdr->desc);
IXGB_DBG("rxdr->next_to_use = <%p>\n", &rxdr->next_to_use);
IXGB_DBG("rxdr->next_to_clean = <%p>\n", &rxdr->next_to_clean);
rxdr->next_to_use = 0;
rxdr->next_to_clean = 0;
return 0;
}
/**
* ixgb_setup_rctl - configure the receive control register.
* @param adapter Board private structure
**/
static void
ixgb_setup_rctl(struct ixgb_adapter *adapter)
{
uint32_t rctl;
rctl = IXGB_READ_REG(&adapter->hw, RCTL);
IXGB_DBG("ixgb_setup_rctl\n");
rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
rctl |=
IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
rctl |= IXGB_RCTL_SECRC;
switch (adapter->rx_buffer_len) {
case IXGB_RXBUFFER_2048:
default:
rctl |= IXGB_RCTL_BSIZE_2048;
break;
case IXGB_RXBUFFER_4096:
rctl |= IXGB_RCTL_BSIZE_4096;
break;
case IXGB_RXBUFFER_8192:
rctl |= IXGB_RCTL_BSIZE_8192;
break;
case IXGB_RXBUFFER_16384:
rctl |= IXGB_RCTL_BSIZE_16384;
break;
}
IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
}
/**
* ixgb_configure_rx - Configure 82597 Receive Unit after Reset.
* @param adapter board private structure
*
* Configure the Rx unit of the MAC after a reset.
**/
static void
ixgb_configure_rx(struct ixgb_adapter *adapter)
{
uint64_t rdba = adapter->rx_ring.dma;
uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
struct ixgb_hw *hw = &adapter->hw;
uint32_t rctl;
uint32_t rxcsum;
IXGB_DBG("ixgb_configure_rx\n");
/* make sure receives are disabled while setting up the descriptors */
rctl = IXGB_READ_REG(hw, RCTL);
IXGB_WRITE_REG(hw, RCTL, rctl & ~IXGB_RCTL_RXEN);
/* set the Receive Delay Timer Register */
IXGB_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
/* Setup the Base and Length of the Rx Descriptor Ring */
IXGB_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
IXGB_WRITE_REG(hw, RDBAH, (rdba >> 32));
IXGB_WRITE_REG(hw, RDLEN, rdlen);
/* Setup the HW Rx Head and Tail Descriptor Pointers */
IXGB_WRITE_REG(hw, RDH, 0);
IXGB_WRITE_REG(hw, RDT, 0);
{
uint32_t rxdctl;
/* burst 16 or burst when RXT0*/
rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
}
if (adapter->raidc) {
uint32_t raidc;
uint8_t poll_threshold;
/* Poll every rx_int_delay period, if RBD exists
* Receive Backlog Detection is set to <threshold>
* Rx Descriptors
* max is 0x3F == set to poll when 504 RxDesc left
* min is 0 */
/* polling times are 1 == 0.8192us
2 == 1.6384us
3 == 3.2768us etc
...
511 == 418 us
*/
#define IXGB_RAIDC_POLL_DEFAULT 122 /* set to poll every ~100 us under load
also known as 10000 interrupts / sec */
/* divide this by 2^3 (8) to get a register size count */
poll_threshold = ((adapter->rx_ring.count-1) >> 3);
/* poll at half of that size */
poll_threshold >>= 1;
/* make sure its not bigger than our max */
poll_threshold &= 0x3F;
raidc =
IXGB_RAIDC_EN | /* turn on raidc style moderation */
IXGB_RAIDC_RXT_GATE | /* don't interrupt with rxt0 while
in RBD mode (polling) */
(IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
/* this sets the regular "min interrupt delay" */
(adapter-> rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
poll_threshold;
IXGB_WRITE_REG(hw, RAIDC, raidc);
}
/* Enable Receive Checksum Offload for TCP and UDP */
if(adapter->rx_csum == TRUE) {
rxcsum = IXGB_READ_REG(hw, RXCSUM);
rxcsum |= IXGB_RXCSUM_TUOFL;
IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
}
/* Enable Receives */
IXGB_WRITE_REG(hw, RCTL, rctl);
}
/**
* ixgb_free_tx_resources - Free Tx Resources.
* @param adapter board private structure
*
* Free all transmit software resources
**/
static void
ixgb_free_tx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
IXGB_DBG("ixgb_free_tx_resources\n");
ixgb_clean_tx_ring(adapter);
kfree(adapter->tx_ring.buffer_info);
adapter->tx_ring.buffer_info = NULL;
pci_free_consistent(pdev, adapter->tx_ring.size, adapter->tx_ring.desc,
adapter->tx_ring.dma);
adapter->tx_ring.desc = NULL;
}
/**
* ixgb_clean_tx_ring - Free Tx Buffers.
* @param adapter board private structure
**/
static void
ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
int i;
IXGB_DBG("ixgb_clean_tx_ring\n");
/* Free all the Tx ring sk_buffs */
for(i = 0; i < adapter->tx_ring.count; i++) {
if(adapter->tx_ring.buffer_info[i].skb) {
pci_unmap_page(pdev,
adapter->tx_ring.buffer_info[i].dma,
adapter->tx_ring.buffer_info[i].length,
PCI_DMA_TODEVICE);
dev_kfree_skb(adapter->tx_ring.buffer_info[i].skb);
adapter->tx_ring.buffer_info[i].skb = NULL;
}
}
size = sizeof(struct ixgb_buffer) * adapter->tx_ring.count;
memset(adapter->tx_ring.buffer_info, 0, size);
/* Zero out the descriptor ring */
memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size);
adapter->tx_ring.next_to_use = 0;
adapter->tx_ring.next_to_clean = 0;
IXGB_WRITE_REG(&adapter->hw, TDH, 0);
IXGB_WRITE_REG(&adapter->hw, TDT, 0);
}
/**
* ixgb_free_rx_resources - Free Rx Resources.
* @param adapter board private structure
*
* Free all receive software resources
**/
static void
ixgb_free_rx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
IXGB_DBG("ixgb_free_rx_resources\n");
ixgb_clean_rx_ring(adapter);
kfree(adapter->rx_ring.buffer_info);
adapter->rx_ring.buffer_info = NULL;
pci_free_consistent(pdev, adapter->rx_ring.size,
adapter->rx_ring.desc, adapter->rx_ring.dma);
adapter->rx_ring.desc = NULL;
}
/**
* ixgb_clean_rx_ring - Free Rx Buffers.
* @param adapter board private structure
**/
static void
ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
int i;
IXGB_DBG("ixgb_free_rx_ring\n");
/* Free all the Rx ring sk_buffs */
for(i = 0; i < adapter->rx_ring.count; i++) {
if(adapter->rx_ring.buffer_info[i].skb) {
pci_unmap_single(pdev,
adapter->rx_ring.buffer_info[i].dma,
adapter->rx_ring.buffer_info[i].length,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(adapter->rx_ring.buffer_info[i].skb);
adapter->rx_ring.buffer_info[i].skb = NULL;
}
}
size = sizeof(struct ixgb_buffer) * adapter->rx_ring.count;
memset(adapter->rx_ring.buffer_info, 0, size);
/* Zero out the descriptor ring */
memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size);
adapter->rx_ring.next_to_clean = 0;
adapter->rx_ring.next_to_use = 0;
IXGB_WRITE_REG(&adapter->hw, RDH, 0);
IXGB_WRITE_REG(&adapter->hw, RDT, 0);
}
/**
* ixgb_set_multi - Multicast and Promiscuous mode set.
* @param netdev network interface device structure
*
* The set_multi entry point is called whenever the multicast address
* list or the network interface flags are updated. This routine is
* resposible for configuring the hardware for proper multicast,
* promiscuous mode, and all-multi behavior.
**/
void
ixgb_set_multi(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
uint32_t rctl;
int i;
struct dev_mc_list *mc_ptr;
IXGB_DBG("ixgb_set_multi <%x>\n", netdev->flags);
/* Check for Promiscuous and All Multicast modes */
rctl = IXGB_READ_REG(&adapter->hw, RCTL);
if(netdev->flags & IFF_PROMISC) {
rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
} else if(netdev->flags & IFF_ALLMULTI) {
rctl |= IXGB_RCTL_MPE;
rctl &= ~IXGB_RCTL_UPE;
} else {
rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
}
if(netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];
IXGB_WRITE_REG(hw, RCTL, rctl);
for(i = 0, mc_ptr = netdev->mc_list; mc_ptr;
i++, mc_ptr = mc_ptr->next)
memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);
}
}
/**
* ixgb_watchdog - Timer Call-back.
* @param data pointer to adapter cast into an unsigned long
**/
void
ixgb_watchdog(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *) data;
struct net_device *netdev = adapter->netdev;
ixgb_check_for_link(&adapter->hw);
if (ixgb_check_for_bad_link(&adapter->hw)) {
/* force the reset path */
netif_stop_queue(netdev);
}
if(adapter->hw.link_up) {
if(!netif_carrier_ok(netdev)) {
printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
netdev->name, 10000, "Full Duplex");
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
} else {
if(netif_carrier_ok(netdev)) {
printk(KERN_INFO "ixgb: %s NIC Link is Down\n", netdev->name);
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
ixgb_down(adapter, FALSE);
ixgb_up(adapter);
}
}
ixgb_update_stats(adapter);
/* Early detection of hung controller */
{
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
int i = txdr->next_to_clean;
if(txdr->buffer_info[i].dma &&
time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
!(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF)) {
IXGB_DBG("ixgb: %s Hung controller? Watchdog stopping queue\n",
netdev->name);
netif_stop_queue(netdev);
}
}
/* generate an interrupt to force clean up of any stragglers */
IXGB_WRITE_REG (&adapter->hw, ICS, IXGB_INT_TXDW);
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
#define IXGB_TX_FLAGS_CSUM 0x00000001
#define IXGB_TX_FLAGS_VLAN 0x00000002
#define IXGB_TX_FLAGS_TSO 0x00000004
/** Transmit Segmentation offload setup.
* ixgb_tso - (Large Send) setup where the initial descriptor is prepared
* @param adapter adapter specific information
* @param skb the skb we are trying to set up for segmentation
**/
static inline boolean_t
ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
struct ixgb_context_desc *context_desc;
int i;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
uint16_t ipcse, tucse, mss;
if(likely(skb_shinfo(skb)->tso_size)) {
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
skb->nh.iph->tot_len = 0;
skb->nh.iph->check = 0;
skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
skb->nh.iph->daddr,
0,
IPPROTO_TCP,
0);
ipcss = skb->nh.raw - skb->data;
ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
ipcse = skb->h.raw - skb->data - 1;
tucss = skb->h.raw - skb->data;
tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
tucse = 0;
i = adapter->tx_ring.next_to_use;
context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
context_desc->ipcss = ipcss;
context_desc->ipcso = ipcso;
context_desc->ipcse = cpu_to_le16(ipcse);
context_desc->tucss = tucss;
context_desc->tucso = tucso;
context_desc->tucse = cpu_to_le16(tucse);
context_desc->mss = cpu_to_le16(mss);
context_desc->hdr_len= hdr_len;
context_desc->status = 0;
context_desc->cmd_type_len = cpu_to_le32(
IXGB_CONTEXT_DESC_TYPE
| IXGB_CONTEXT_DESC_CMD_TSE
| IXGB_CONTEXT_DESC_CMD_IP
| IXGB_CONTEXT_DESC_CMD_TCP
| IXGB_CONTEXT_DESC_CMD_RS
| IXGB_CONTEXT_DESC_CMD_IDE
| (skb->len - (hdr_len)));
i = (i + 1) % adapter->tx_ring.count;
adapter->tx_ring.next_to_use = i;
return TRUE;
}
#endif
return FALSE;
}
/**
* ixgb_tx_csum - prepare context descriptor for checksum offload.
*
* ixgb_tx_csum is called to prepare for checksumming a packet in hw.
* @param adapter board private structure
* @param skb structure containing data to send
**/
static inline boolean_t
ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
{
struct ixgb_context_desc *context_desc;
int i;
uint8_t css, cso;
if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
cso = (skb->h.raw + skb->csum) - skb->data;
i = adapter->tx_ring.next_to_use;
context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
context_desc->tucss = css;
context_desc->tucso = cso;
context_desc->tucse = 0;
/* zero out any previously existing data in one instruction */
*(uint32_t *)&(context_desc->ipcss) = 0;
context_desc->status = 0;
context_desc->hdr_len = 0;
context_desc->mss = 0;
context_desc->cmd_type_len =
cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
| IXGB_TX_DESC_CMD_RS
| IXGB_TX_DESC_CMD_IDE);
i = (i + 1) % adapter->tx_ring.count;
adapter->tx_ring.next_to_use = i;
return TRUE;
}
return FALSE;
}
/**
* ixgb_tx_map - private function for mapping send data to hardware addresses.
*
* @param adapter board private structure
* @param skb structure containing data to send
**/
static inline int
ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
int len, offset, count, size, i;
int f;
len = skb->len - skb->data_len;
i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count;
count = 0;
offset = 0;
while(len) {
i = (i + 1) % tx_ring->count;
size = min(len, adapter->max_data_per_txd);
tx_ring->buffer_info[i].length = size;
tx_ring->buffer_info[i].dma =
pci_map_single(adapter->pdev, skb->data + offset, size,
PCI_DMA_TODEVICE);
tx_ring->buffer_info[i].time_stamp = jiffies;
len -= size;
offset += size;
count++;
}
for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = 0;
while(len) {
i = (i + 1) % tx_ring->count;
size = min(len, adapter->max_data_per_txd);
tx_ring->buffer_info[i].length = size;
tx_ring->buffer_info[i].dma =
pci_map_page(adapter->pdev, frag->page,
frag->page_offset + offset, size,
PCI_DMA_TODEVICE);
tx_ring->buffer_info[i].time_stamp = jiffies;
len -= size;
offset += size;
count++;
}
}
tx_ring->buffer_info[i].skb = skb;
return count;
}
/**
* ixgb_tx_queue - private function to start transmit on hardware.
*
* @param adapter board private structure
* @param count number of tx_descriptors to initialize (consume)
* @param vlan_id the vlan tag to insert (if necessary)
* @param tx_flags special handling for this transmit, if any
**/
static inline void
ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct ixgb_tx_desc *tx_desc = NULL;
uint32_t cmd_type_len = adapter->tx_cmd_type;
uint8_t status = 0;
uint8_t popts = 0;
int i;
if(tx_flags & IXGB_TX_FLAGS_TSO) {
cmd_type_len |= IXGB_TX_DESC_CMD_TSE;
popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);
}
if(tx_flags & IXGB_TX_FLAGS_CSUM)
popts |= IXGB_TX_DESC_POPTS_TXSM;
if(tx_flags & IXGB_TX_FLAGS_VLAN) {
cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
}
i = tx_ring->next_to_use;
while(count--) {
tx_desc = IXGB_TX_DESC(*tx_ring, i);
tx_desc->buff_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
tx_desc->cmd_type_len =
cpu_to_le32(cmd_type_len | tx_ring->buffer_info[i].length);
tx_desc->status = status;
tx_desc->popts = popts;
tx_desc->vlan = cpu_to_le16(vlan_id);
i = (i + 1) % tx_ring->count;
}
tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP);
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
tx_ring->next_to_use = i;
IXGB_WRITE_REG(&adapter->hw, TDT, i);
}
#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0))
/**
* ixgb_xmit_frame - hard_start_xmit linked function, transmit entry point.
*
* ixgb_xmit_frame is called to send an skb on the wire.
* @param skb contains data to send
* @param netdev network interface device structure
**/
static int
ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
int vlan_id = 0;
int tx_flags = 0, count;
int f;
count =
TXD_USE_COUNT(skb->len - skb->data_len, adapter->max_data_per_txd);
if(count == 0) {
dev_kfree_skb_any(skb);
return 0;
}
for(f = 0; f < skb_shinfo(skb)->nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
adapter->max_data_per_txd);
#ifdef NETIF_F_TSO
if((skb_shinfo(skb)->tso_size) || (skb->ip_summed == CHECKSUM_HW))
count++;
#else
if(skb->ip_summed == CHECKSUM_HW)
count++;
#endif
if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < count)) {
netif_stop_queue(netdev);
return 1;
}
if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= IXGB_TX_FLAGS_VLAN;
vlan_id = vlan_tx_tag_get(skb);
}
if(ixgb_tso(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_TSO;
else if(ixgb_tx_csum(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_CSUM;
count = ixgb_tx_map(adapter, skb);
ixgb_tx_queue(adapter, count, vlan_id, tx_flags);
netdev->trans_start = jiffies;
return 0;
}
/**
* ixgb_tx_timeout - Respond to a Tx Hang by resetting the adapter.
* @param netdev network interface device structure
**/
static void
ixgb_tx_timeout(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
IXGB_DBG("ixgb_tx_timeout\n");
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
}
/**
* ixgb_tx_timeout_task - worker function to reset hardware and dump queues.
* This function is pointed to by adapter->tx_timeout_task
*
* @param netdev network interface device structure
**/
static void
ixgb_tx_timeout_task(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
IXGB_DBG("ixgb_tx_timeout_task\n");
netif_device_detach(netdev);
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
netif_device_attach(netdev);
}
/**
* ixgb_get_stats - Get System Network Statistics.
* @param netdev network interface device structure
*
* Returns the address of the device statistics structure.
* The statistics are actually updated from the timer callback.
**/
static struct net_device_stats *
ixgb_get_stats(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
return &adapter->net_stats;
}
/**
* ixgb_change_mtu - Change the Maximum Transfer Unit.
* @param netdev network interface device structure
* @param new_mtu new value for maximum frame size
*
* Returns 0 on success, negative on failure
**/
static int
ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t old_mtu = adapter->rx_buffer_len;
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
IXGB_DBG("ixgb_change_mtu\n");
if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
|| (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
IXGB_ERR("Invalid MTU setting\n");
return -EINVAL;
}
if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
|| (max_frame <= IXGB_RXBUFFER_2048)) {
adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
} else if(max_frame <= IXGB_RXBUFFER_4096) {
adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
} else if(max_frame <= IXGB_RXBUFFER_8192) {
adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
} else {
adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
}
if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
}
if(adapter->hw.max_frame_size != max_frame) {
struct ixgb_hw *hw = &adapter->hw;
adapter->hw.max_frame_size = max_frame;
IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
if(hw->max_frame_size >
IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
if(!(ctrl0 & IXGB_CTRL0_JFE)) {
ctrl0 |= IXGB_CTRL0_JFE;
IXGB_WRITE_REG(hw, CTRL0, ctrl0);
}
}
printk(KERN_ERR "%s: ixgb_change_mtu MFS is set to <%x>\n",
adapter->netdev->name,
(IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT));
}
netdev->mtu = new_mtu;
return 0;
}
/**
* ixgb_set_mac - Change the Ethernet Address of the NIC.
* @param netdev network interface device structure
* @param p pointer to an address structure
*
* Returns 0 on success, negative on failure
**/
static int
ixgb_set_mac(struct net_device *netdev, void *p)
{
struct ixgb_adapter *adapter = netdev->priv;
struct sockaddr *addr = (struct sockaddr *) p;
IXGB_DBG("ixgb_set_mac\n");
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
ixgb_rar_set(&adapter->hw, addr->sa_data, 0);
return 0;
}
/**
* ixgb_update_stats - Update the board statistics counters.
* @param adapter board private structure
**/
static void
ixgb_update_stats(struct ixgb_adapter *adapter)
{
adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
adapter->stats.mcftc += IXGB_READ_REG(&adapter->hw, MCFTC);
adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
/* Fill out the OS statistics structure */
adapter->net_stats.rx_packets = adapter->stats.gprcl;
adapter->net_stats.tx_packets = adapter->stats.gptcl;
adapter->net_stats.rx_bytes = adapter->stats.gorcl;
adapter->net_stats.tx_bytes = adapter->stats.gotcl;
adapter->net_stats.multicast = adapter->stats.mprcl;
adapter->net_stats.collisions = 0;
/* ignore RLEC as it reports errors for padded (<64bytes) frames
* with a length in the type/len field */
adapter->net_stats.rx_errors =
/* adapter->stats.rnbc + */ adapter->stats.crcerrs + adapter->stats.ruc +
adapter->stats.roc /*+ adapter->stats.rlec*/ + adapter->stats.icbc +
adapter->stats.ecbc + adapter->stats.mpc;
adapter->net_stats.rx_dropped = adapter->stats.mpc;
/* see above
* adapter->net_stats.rx_length_errors = adapter->stats.rlec;
*/
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
adapter->net_stats.rx_over_errors = adapter->stats.mpc;
adapter->net_stats.tx_errors = 0;
adapter->net_stats.rx_frame_errors = 0;
adapter->net_stats.tx_aborted_errors = 0;
adapter->net_stats.tx_carrier_errors = 0;
adapter->net_stats.tx_fifo_errors = 0;
adapter->net_stats.tx_heartbeat_errors = 0;
adapter->net_stats.tx_window_errors = 0;
}
/**
* ixgb_irq_disable - Mask off interrupt generation on the NIC
* @param adapter board private structure
**/
static inline void
ixgb_irq_disable(struct ixgb_adapter *adapter)
{
IXGB_DBG("ixgb_irq_disable\n");
atomic_inc(&adapter->irq_sem);
IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
synchronize_irq(adapter->netdev->irq);
}
/**
* ixgb_irq_enable - Enable default interrupt generation settings.
* @param adapter board private structure
**/
static inline void
ixgb_irq_enable(struct ixgb_adapter *adapter)
{
IXGB_DBG("ixgb_irq_enable\n");
if(atomic_dec_and_test(&adapter->irq_sem)) {
IXGB_WRITE_REG(&adapter->hw, IMS,
IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
IXGB_INT_RXO | IXGB_INT_LSC);
}
}
#define IXGB_MAX_INTR 10
/**
* ixgb_intr - Interrupt Handler.
* @param irq interrupt number
* @param data pointer to a network interface device structure
* @param regs CPU registers structure
**/
static void
ixgb_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = (struct net_device *) data;
struct ixgb_adapter *adapter = netdev->priv;
#ifdef CONFIG_IXGB_NAPI
if (netif_rx_schedule_prep(netdev)) {
ixgb_irq_disable(adapter);
__netif_rx_schedule(netdev);
}
#else
struct ixgb_hw *hw = &adapter->hw;
uint32_t icr;
uint i = IXGB_MAX_INTR;
boolean_t rxdmt0 = FALSE;
while(i && (icr = IXGB_READ_REG(hw, ICR))) {
if(icr & IXGB_INT_RXDMT0)
rxdmt0 = TRUE;
if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
mod_timer(&adapter->watchdog_timer, jiffies);
}
/* adapter->generate_int = 0; */
ixgb_clean_rx_irq(adapter);
ixgb_clean_tx_irq(adapter);
i--;
}
/* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
* set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
*/
if(rxdmt0 && adapter->raidc) {
/* ready the timer by writing the clear reg */
IXGB_WRITE_REG(hw, IMC, IXGB_INT_RXDMT0);
/* now restart it, h/w will decide if its necessary */
IXGB_WRITE_REG(hw, IMS, IXGB_INT_RXDMT0);
}
#endif // NAPI else
}
#ifdef CONFIG_IXGB_NAPI
static int
ixgb_process_intr(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t icr;
int i = IXGB_MAX_INTR;
int hasReceived = 0;
while(i && (icr = IXGB_READ_REG(&adapter->hw, ICR))) {
if (icr & IXGB_INT_RXT0)
hasReceived = 1;
if (!(icr & ~(IXGB_INT_RXT0)))
break;
if (icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
mod_timer(&adapter->watchdog_timer, jiffies);
}
ixgb_clean_tx_irq(adapter);
i--;
}
return hasReceived;
}
#endif
/**
* ixgb_clean_tx_irq - Reclaim resources after transmit completes.
* @param adapter board private structure
**/
static void
ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int i = adapter->tx_ring.next_to_clean;
struct ixgb_tx_desc *tx_desc = IXGB_TX_DESC(*tx_ring, i);
while((tx_desc->status & IXGB_TX_DESC_STATUS_DD)) {
if (tx_desc->popts
& (IXGB_TX_DESC_POPTS_TXSM | IXGB_TX_DESC_POPTS_IXSM))
adapter->hw_csum_tx_good++;
if(tx_ring->buffer_info[i].dma) {
pci_unmap_page(pdev, tx_ring->buffer_info[i].dma,
tx_ring->buffer_info[i].length,
PCI_DMA_TODEVICE);
tx_ring->buffer_info[i].dma = 0;
}
if(tx_ring->buffer_info[i].skb) {
dev_kfree_skb_any(tx_ring->buffer_info[i].skb);
tx_ring->buffer_info[i].skb = NULL;
}
*(uint32_t *)&(tx_desc->status) = 0;
i = (i + 1) % tx_ring->count;
tx_desc = IXGB_TX_DESC(*tx_ring, i);
}
tx_ring->next_to_clean = i;
if(netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
(IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
netif_wake_queue(netdev);
}
}
#ifdef CONFIG_IXGB_NAPI
static int
ixgb_poll(struct net_device *netdev, int *budget)
{
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
struct ixgb_rx_desc *rx_desc;
struct sk_buff *skb;
uint32_t length;
int i;
int received = 0;
int rx_work_limit = *budget;
if(rx_work_limit > netdev->quota)
rx_work_limit = netdev->quota;
ixgb_process_intr(netdev);
i = rx_ring->next_to_clean;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
while((rx_desc->status & IXGB_RX_DESC_STATUS_DD)) {
if(--rx_work_limit < 0)
goto not_done;
pci_unmap_single(pdev,
rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
skb = rx_ring->buffer_info[i].skb;
length = le16_to_cpu(rx_desc->length);
if(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP)) {
/* All receives must fit into a single buffer */
IXGB_DBG("Receive packet consumed multiple buffers\n");
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
continue;
}
if(rx_desc->
errors & (IXGB_RX_DESC_ERRORS_CE | IXGB_RX_DESC_ERRORS_SE |
IXGB_RX_DESC_ERRORS_P | IXGB_RX_DESC_ERRORS_RXE)) {
IXGB_DBG("Receive Errors Reported by Hardware-%x.\n",
rx_desc->errors);
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
continue;
}
/* Good Receive */
skb_put(skb, length);
/* Receive Checksum Offload */
ixgb_rx_checksum(adapter, rx_desc, skb);
skb->protocol = eth_type_trans(skb, netdev);
if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & IXGB_RX_DESC_SPECIAL_VLAN_MASK));
} else {
netif_receive_skb(skb);
}
netdev->last_rx = jiffies;
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
received++;
}
if(!received)
received = 1;
ixgb_alloc_rx_buffers(adapter);
rx_ring->next_to_clean = i;
netdev->quota -= received;
*budget -= received;
netif_rx_complete(netdev);
/* NOTE: RAIDC will be automatically restarted by this enable */
ixgb_irq_enable(adapter);
return 0;
not_done:
ixgb_alloc_rx_buffers(adapter);
rx_ring->next_to_clean = i;
netdev->quota -= received;
*budget -= received;
return 1;
}
#else
/**
* ixgb_clean_rx_irq - Send received data up the network stack.
* @param adapter board private structure
**/
static void
ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct ixgb_rx_desc *rx_desc;
struct sk_buff *skb;
uint32_t length;
int i;
i = rx_ring->next_to_clean;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
while((rx_desc->status & IXGB_RX_DESC_STATUS_DD)) {
pci_unmap_single(pdev, rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
skb = rx_ring->buffer_info[i].skb;
length = le16_to_cpu(rx_desc->length);
if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
/* All receives must fit into a single buffer */
IXGB_DBG("Receive packet consumed multiple buffers "
"length<%x>\n", length);
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
continue;
}
if(unlikely(rx_desc->errors
& (IXGB_RX_DESC_ERRORS_CE | IXGB_RX_DESC_ERRORS_SE |
IXGB_RX_DESC_ERRORS_P | IXGB_RX_DESC_ERRORS_RXE))) {
IXGB_DBG("Receive Errors Reported by Hardware-%x.\n",
rx_desc->errors);
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
continue;
}
/* Good Receive */
skb_put(skb, length);
/* Receive Checksum Offload */
ixgb_rx_checksum(adapter, rx_desc, skb);
skb->protocol = eth_type_trans(skb, netdev);
if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & IXGB_RX_DESC_SPECIAL_VLAN_MASK));
} else {
netif_rx(skb);
}
netdev->last_rx = jiffies;
rx_desc->status = 0;
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = IXGB_RX_DESC(*rx_ring, i);
} /* while */
rx_ring->next_to_clean = i;
ixgb_alloc_rx_buffers(adapter);
}
#endif
/**
* ixgb_alloc_rx_buffers - Replace used receive buffers.
* @param adapter address of board private structure
**/
static void
ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct ixgb_rx_desc *rx_desc;
struct sk_buff *skb;
int reserve_len;
int i;
int num_group_tail_writes;
long cleancount;
reserve_len = 2;
i = rx_ring->next_to_use;
cleancount = IXGB_DESC_UNUSED (rx_ring);
/* lessen this to 4 if we're
* in the midst of raidc and rbd is occuring
* because we don't want to delay returning buffers when low
*/
num_group_tail_writes
= adapter->raidc ? 4 : IXGB_RX_BUFFER_WRITE;
/* leave one descriptor unused */
while(--cleancount > 0) {
rx_desc = IXGB_RX_DESC(*rx_ring, i);
/* allocate a new one */
skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
if(unlikely(!skb)) {
/* better luck next time around */
IXGB_DBG("Could not allocate SKB\n");
break;
}
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
* the 14 byte MAC header is removed
*/
skb_reserve(skb, reserve_len);
skb->dev = netdev;
rx_ring->buffer_info[i].skb = skb;
rx_ring->buffer_info[i].length = adapter->rx_buffer_len;
rx_ring->buffer_info[i].dma =
pci_map_single(pdev, skb->data, adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
rx_desc->buff_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
if(!(i % num_group_tail_writes)) {
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
/* move tail */
IXGB_WRITE_REG(&adapter->hw, RDT, i);
}
i = (i + 1) % rx_ring->count;
}
rx_ring->next_to_use = i;
}
/**
* ixgb_ioctl - perform a command - e.g: ethtool:get_driver_info.
* @param netdev network interface device structure
* @param ifr data to be used/filled in by the ioctl command
* @param cmd ioctl command to execute
**/
int
ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
return ixgb_ethtool_ioctl(netdev, ifr);
default:
return -EOPNOTSUPP;
}
return 0;
}
/**
* ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
*
* @param netdev network interface device structure
* @param grp indicates to enable or disable tagging/stripping
**/
static void
ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t ctrl, rctl;
ixgb_irq_disable(adapter);
adapter->vlgrp = grp;
if(grp) {
/* enable VLAN tag insert/strip */
ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
ctrl |= IXGB_CTRL0_VME;
IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
/* enable VLAN receive filtering */
rctl = IXGB_READ_REG(&adapter->hw, RCTL);
rctl |= IXGB_RCTL_VFE;
rctl &= ~IXGB_RCTL_CFIEN;
IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
} else {
/* disable VLAN tag insert/strip */
ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
ctrl &= ~IXGB_CTRL0_VME;
IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
/* disable VLAN filtering */
rctl = IXGB_READ_REG(&adapter->hw, RCTL);
rctl &= ~IXGB_RCTL_VFE;
IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
}
ixgb_irq_enable(adapter);
}
/**
* ixgb_vlan_rx_add_vid - adds a vlan id to be tagged/stripped in packet data.
* @param netdev network interface device structure
* @param vid the vlan to be added
**/
static void
ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
vfta |= (1 << (vid & 0x1F));
ixgb_write_vfta(&adapter->hw, index, vfta);
}
/**
* ixgb_vlan_rx_kill_vid - removes a vlan id from tag/strip tables.
* @param netdev network interface device structure
* @param vid the vlan to be deleted
**/
static void
ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
ixgb_irq_disable(adapter);
if(adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
ixgb_irq_enable(adapter);
/* remove VID from filter table*/
index = (vid >> 5) & 0x7F;
vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
vfta &= ~(1 << (vid & 0x1F));
ixgb_write_vfta(&adapter->hw, index, vfta);
}
/**
* ixgb_restore_vlan - restores vlan settings after adapter reset.
* @param adapter the address of the board private structure
**/
static void
ixgb_restore_vlan(struct ixgb_adapter *adapter)
{
ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
if(adapter->vlgrp) {
uint16_t vid;
for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
if(!adapter->vlgrp->vlan_devices[vid])
continue;
ixgb_vlan_rx_add_vid(adapter->netdev, vid);
}
}
}
/**
* ixgb_rx_checksum - Receive Checksum Offload for 82597.
* @param adapter board private structure
* @param rx_desc receive descriptor
* @param skb socket buffer with received data
**/
static inline void
ixgb_rx_checksum(struct ixgb_adapter *adapter,
struct ixgb_rx_desc *rx_desc,
struct sk_buff *skb)
{
/* Ignore Checksum bit is set OR
* TCP Checksum has not been calculated
*/
if((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
(!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
skb->ip_summed = CHECKSUM_NONE;
return;
}
/* At this point we know the hardware did the TCP checksum
* now look at the TCP checksum error bit
*/
if(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
/* let the stack verify checksum errors */
skb->ip_summed = CHECKSUM_NONE;
adapter->hw_csum_rx_error++;
} else {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
adapter->hw_csum_rx_good++;
}
}
/**
* ixgb_write_pci_cfg - write PCI configuration space.
* @param hw board specific data structure
* @param reg PCI configuration space register to write to
* @param value Value to be written to reg
**/
void
ixgb_write_pci_cfg(struct ixgb_hw *hw, uint32_t reg, uint16_t *value)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *) hw->back;
pci_write_config_word(adapter->pdev, reg, *value);
}
/**
* ixgb_notify_reboot - handles OS notification of reboot event.
* @param nb notifier block, unused
* @param event Event being passed to driver to act upon
* @param p A pointer to our net device
**/
static int
ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
pci_for_each_dev(pdev) {
if(pci_dev_driver(pdev) == &ixgb_driver)
ixgb_suspend(pdev, 3);
}
}
return NOTIFY_DONE;
}
/**
* ixgb_suspend - driver suspend function called from notify.
* @param pdev pci driver structure used for passing to
* @param state power state to enter
**/
static int
ixgb_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
netif_device_detach(netdev);
if(netif_running(netdev))
ixgb_down(adapter, TRUE);
pci_save_state(pdev, adapter->pci_state);
state = (state > 0) ? 3 : 0;
pci_set_power_state(pdev, state);
msec_delay(200);
return 0;
}
/* ixgb_main.c */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
/* glue for the OS independant part of ixgb
* includes register access macros
*/
#ifndef IXGB_OSDEP_H
#define IXGB_OSDEP_H
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#define usec_delay(x) udelay(x)
#define msec_delay(x) do { if(in_interrupt()) { \
mdelay(x); \
} else { \
set_current_state(TASK_UNINTERRUPTIBLE); \
schedule_timeout((x * HZ)/1000); \
} } while(0)
#define PCI_COMMAND_REGISTER PCI_COMMAND
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
typedef enum {
FALSE = 0,
TRUE = 1
} boolean_t;
#define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B)
#if DBG
#define ASSERT(x) if(!(x)) BUG()
#define DEBUGOUT(S) printk(KERN_ERR S "\n")
#define DEBUGOUT1(S, A...) printk(KERN_ERR S "\n", A)
#else
#define ASSERT(x)
#define DEBUGOUT(S)
#define DEBUGOUT1(S, A...)
#endif
#define DEBUGOUT2 DEBUGOUT1
#define DEBUGOUT3 DEBUGOUT1
#define DEBUGOUT7 DEBUGOUT1
#define DEBUGFUNC(F) DEBUGOUT(F)
#define IXGB_WRITE_REG(a, reg, value) ( \
writel((value), ((a)->hw_addr + IXGB_##reg)))
#define IXGB_READ_REG(a, reg) ( \
readl((a)->hw_addr + IXGB_##reg))
#define IXGB_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
#define IXGB_READ_REG_ARRAY(a, reg, offset) ( \
readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
#define IXGB_MEMCPY memcpy
#endif /* IXGB_OSDEP_H */
/*******************************************************************************
Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
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.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
The full GNU General Public License is included in this distribution in the
file called LICENSE.
Contact Information:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "ixgb.h"
/* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage.
*/
#define IXGB_MAX_NIC 8
#define OPTION_UNSET -1
#define OPTION_DISABLED 0
#define OPTION_ENABLED 1
/* Module Parameters are always initialized to -1, so that the driver
* can tell the difference between no user specified value or the
* user asking for the default value.
* The true default values are loaded in when ixgb_check_options is called.
*
* This is a GCC extension to ANSI C.
* See the item "Labeled Elements in Initializers" in the section
* "Extensions to the C Language Family" of the GCC documentation.
*/
#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over (plus this helps to avoid typo bugs).
*/
#define IXGB_PARAM(X, S) \
static const int __devinitdata X[IXGB_MAX_NIC + 1] = IXGB_PARAM_INIT; \
MODULE_PARM(X, "1-" __MODULE_STRING(IXGB_MAX_NIC) "i"); \
MODULE_PARM_DESC(X, S);
/* Transmit Descriptor Count
*
* Valid Range: 64-4096
*
* Default Value: 256
*/
IXGB_PARAM(TxDescriptors, "Number of transmit descriptors");
/* Receive Descriptor Count
*
* Valid Range: 64-4096
*
* Default Value: 1024
*/
IXGB_PARAM(RxDescriptors, "Number of receive descriptors");
/* User Specified Flow Control Override
*
* Valid Range: 0-3
* - 0 - No Flow Control
* - 1 - Rx only, respond to PAUSE frames but do not generate them
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
* - 3 - Full Flow Control Support
*
* Default Value: Read flow control settings from the EEPROM
*/
IXGB_PARAM(FlowControl, "Flow Control setting");
/* XsumRX - Receive Checksum Offload Enable/Disable
*
* Valid Range: 0, 1
* - 0 - disables all checksum offload
* - 1 - enables receive IP/TCP/UDP checksum offload
* on 82597 based NICs
*
* Default Value: 1
*/
IXGB_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
/* XsumTX - Transmit Checksum Offload Enable/Disable
*
* Valid Range: 0, 1
* - 0 - disables all checksum offload
* - 1 - enables transmmit IP/TCP/UDP checksum offload
* on 82597 based NICs
*
* Default Value: 1
*/
IXGB_PARAM(XsumTX, "Disable or enable Transmit Checksum offload");
/* Receive Interrupt Delay in units of 0.8192 microseconds
*
* Valid Range: 0-65535
*
* Default Value: 72
*/
IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");
/* Receive Interrupt Moderation enable (uses RxIntDelay too)
*
* Valid Range: 0,1
*
* Default Value: 1
*/
IXGB_PARAM(RAIDC, "Disable or enable Receive Interrupt Moderation");
/* Receive Flow control high threshold (when we send a pause frame)
* (FCRTH)
*
* Valid Range: 1,536 - 262,136 (0x600 - 0x3FFF8, 8 byte granularity)
*
* Default Value: 196,608 (0x30000)
*/
IXGB_PARAM(RxFCHighThresh, "Receive Flow Control High Threshold");
/* Receive Flow control low threshold (when we send a resume frame)
* (FCRTL)
*
* Valid Range: 64 - 262,136 (0x40 - 0x3FFF8, 8 byte granularity)
* must be less than high threshold by at least 8 bytes
*
* Default Value: 163,840 (0x28000)
*/
IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");
/* Flow control request timeout (how long to pause the link partner's tx)
* (PAP 15:0)
*
* Valid Range: 1 - 65535
*
* Default Value: 256 (0x100)
*/
IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
/* Transmit Interrupt Delay in units of 0.8192 microseconds
*
* Valid Range: 0-65535
*
* Default Value: 32
*/
IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");
/* Interrupt Delay Enable
*
* Valid Range: 0, 1
*
* - 0 - disables transmit interrupt delay
* - 1 - enables transmmit interrupt delay
*
* Default Value: 1
*/
IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
#define DEFAULT_TXD 256
#define MAX_TXD 4096
#define MIN_TXD 64
#define DEFAULT_RXD 1024
#define MAX_RXD 4096
#define MIN_RXD 64
#define DEFAULT_TIDV 32
#define MAX_TIDV 0xFFFF
#define MIN_TIDV 0
#define DEFAULT_RDTR 72
#define MAX_RDTR 0xFFFF
#define MIN_RDTR 0
#define XSUMRX_DEFAULT OPTION_ENABLED
#define FLOW_CONTROL_FULL ixgb_fc_full
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
#define DEFAULT_FCRTL 0x28000
#define DEFAULT_FCRTH 0x30000
#define MIN_FCRTL 0
#define MAX_FCRTL 0x3FFE8
#define MIN_FCRTH 8
#define MAX_FCRTH 0x3FFF0
#define DEFAULT_FCPAUSE 0x100
#define MIN_FCPAUSE 1
#define MAX_FCPAUSE 0xffff
struct ixgb_option {
enum { enable_option, range_option, list_option } type;
char *name;
char *err;
int def;
union {
struct { /* range option information */
int min;
int max;
} r;
struct { /* list option information */
int nr;
struct ixgb_opt_list {
int i;
char *str;
} *p;
} l;
} arg;
};
static int __devinit
ixgb_validate_option(int *value,
struct ixgb_option *opt)
{
if(*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
switch (opt->type) {
case enable_option:
switch (*value) {
case OPTION_ENABLED:
printk(KERN_INFO "%s Enabled\n", opt->name);
return 0;
case OPTION_DISABLED:
printk(KERN_INFO "%s Disabled\n", opt->name);
return 0;
}
break;
case range_option:
if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
printk(KERN_INFO "%s set to %i\n", opt->name, *value);
return 0;
}
break;
case list_option:
{
int i;
struct ixgb_opt_list *ent;
for(i = 0; i < opt->arg.l.nr; i++) {
ent = &opt->arg.l.p[i];
if(*value == ent->i) {
if(ent->str[0] != '\0')
printk(KERN_INFO "%s",
ent->str);
return 0;
}
}
}
break;
default:
BUG();
}
printk(KERN_INFO "Invalid %s specified (%i) %s\n", opt->name, *value,
opt->err);
*value = opt->def;
return -1;
}
#define LIST_LEN(l) (sizeof(l) / sizeof(l[0]))
/**
* ixgb_check_options - Range Checking for Command Line Parameters
* @adapter: board private structure
*
* This routine checks all command line paramters for valid user
* input. If an invalid value is given, or if no user specified
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
**/
void __devinit
ixgb_check_options(struct ixgb_adapter *adapter)
{
int board = adapter->bd_number;
IXGB_DBG("ixgb_check_options\n");
if(board >= IXGB_MAX_NIC) {
printk(KERN_NOTICE "Warning: no configuration for board #%i\n", board);
printk(KERN_NOTICE "Using defaults for all values\n");
board = IXGB_MAX_NIC;
}
{ /* Transmit Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_TXD),
.def = DEFAULT_TXD,
.arg = {.r = {.min = MIN_TXD, .max = MAX_TXD}}
};
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
tx_ring->count = TxDescriptors[board];
ixgb_validate_option(&tx_ring->count, &opt);
IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Descriptors",
.err = "using default of " __MODULE_STRING(DEFAULT_RXD),
.def = DEFAULT_RXD,
.arg = {.r = {.min = MIN_RXD, .max = MAX_RXD}}
};
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
rx_ring->count = RxDescriptors[board];
ixgb_validate_option(&rx_ring->count, &opt);
IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
}
{ /* Receive Checksum Offload Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Receive Checksum Offload",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED,
};
int rx_csum = XsumRX[board];
ixgb_validate_option(&rx_csum, &opt);
adapter->rx_csum = rx_csum;
}
{ /* Transmit Checksum Offload Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Transmit Checksum Offload",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED,
};
int tx_csum = XsumTX[board];
ixgb_validate_option(&tx_csum, &opt);
adapter->tx_csum = tx_csum;
}
{ /* Flow Control */
struct ixgb_opt_list fc_list[] = {
{ixgb_fc_none, "Flow Control Disabled\n"},
{ixgb_fc_rx_pause, "Flow Control Receive Only\n"},
{ixgb_fc_tx_pause, "Flow Control Transmit Only\n"},
{ixgb_fc_full, "Flow Control Enabled\n"},
{ixgb_fc_default, "Flow Control Hardware Default\n"}
};
struct ixgb_option opt = {
.type = list_option,
.name = "Flow Control",
.err = "reading default settings from EEPROM",
.def = ixgb_fc_full,
.arg = {.l = {.nr = LIST_LEN(fc_list), .p = fc_list}}
};
int fc = FlowControl[board];
ixgb_validate_option(&fc, &opt);
adapter->hw.fc.type = fc;
}
{ /* Receive Flow Control High Threshold */
struct ixgb_option fcrth = {
.type = range_option,
.name = "Rx Flow Control High Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
.def = DEFAULT_FCRTH,
.arg = {.r = {.min = MIN_FCRTH, .max = MAX_FCRTH}}
};
adapter->hw.fc.high_water = RxFCHighThresh[board];
ixgb_validate_option(&adapter->hw.fc.high_water, &fcrth);
if ( !(adapter->hw.fc.type & ixgb_fc_rx_pause) )
printk (KERN_INFO
"Ignoring RxFCHighThresh when no RxFC\n");
}
{ /* Receive Flow Control Low Threshold */
struct ixgb_option fcrtl = {
.type = range_option,
.name = "Rx Flow Control Low Threshold",
.err = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
.def = DEFAULT_FCRTL,
.arg = {.r = {.min = MIN_FCRTL, .max = MAX_FCRTL}}
};
adapter->hw.fc.low_water = RxFCLowThresh[board];
ixgb_validate_option(&adapter->hw.fc.low_water, &fcrtl);
if ( !(adapter->hw.fc.type & ixgb_fc_rx_pause) )
printk (KERN_INFO
"Ignoring RxFCLowThresh when no RxFC\n");
}
{ /* Flow Control Pause Time Request*/
struct ixgb_option fcpap = {
.type = range_option,
.name = "Flow Control Pause Time Request",
.err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
.def = DEFAULT_FCPAUSE,
.arg = {.r = {.min = MIN_FCPAUSE, .max = MAX_FCPAUSE}}
};
int pause_time = FCReqTimeout[board];
ixgb_validate_option(&pause_time, &fcpap);
if ( !(adapter->hw.fc.type & ixgb_fc_rx_pause) )
printk (KERN_INFO
"Ignoring FCReqTimeout when no RxFC\n");
adapter->hw.fc.pause_time = pause_time;
}
/* high low and spacing check for rx flow control thresholds */
if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
/* high must be greater than low */
if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
/* set defaults */
printk (KERN_INFO
"RxFCHighThresh must be >= (RxFCLowThresh + 8), "
"Using Defaults\n");
adapter->hw.fc.high_water = DEFAULT_FCRTH;
adapter->hw.fc.low_water = DEFAULT_FCRTL;
}
}
{ /* Receive Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
.def = DEFAULT_RDTR,
.arg = {.r = {.min = MIN_RDTR, .max = MAX_RDTR}}
};
adapter->rx_int_delay = RxIntDelay[board];
ixgb_validate_option(&adapter->rx_int_delay, &opt);
}
{ /* Receive Interrupt Moderation */
struct ixgb_option opt = {
.type = enable_option,
.name = "Advanced Receive Interrupt Moderation",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED,
};
int raidc = RAIDC[board];
ixgb_validate_option(&raidc, &opt);
adapter->raidc = raidc;
}
{ /* Transmit Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
.def = DEFAULT_TIDV,
.arg = {.r = {.min = MIN_TIDV, .max = MAX_TIDV}}
};
adapter->tx_int_delay = TxIntDelay[board];
ixgb_validate_option(&adapter->tx_int_delay, &opt);
}
{ /* Transmit Interrupt Delay Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Tx Interrupt Delay Enable",
.err = "defaulting to Enabled",
.def = OPTION_ENABLED,
};
int ide = IntDelayEnable[board];
ixgb_validate_option(&ide, &opt);
adapter->tx_int_delay_enable = ide;
}
}
......@@ -6207,6 +6207,9 @@
103e 82801BD PRO/100 VM (MOB) Ethernet Controller
1040 536EP Data Fax Modem
16be 1040 V.9X DSP Data Fax Modem
1048 82597EX 10GbE Ethernet Controller
8086 a01f PRO/10GbE LR Server Adapter
8086 a11f PRO/10GbE LR Server Adapter
1059 82551QM Ethernet Controller
1130 82815 815 Chipset Host Bridge and Memory Controller Hub
1025 1016 Travelmate 612 TX
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment