This is driver version 1.4.4 of the Intel ixgbe driver.

-It has new hardware support
  -It uses a new method of TX cleanup called Head Write Back
  -It includes the provisional generic TCP LRO feature contributed
   by Myricom and made general purpose by me. This should move into
   the stack upon approval but for this driver drop its in here.
  -Also bug fixes and etc...

MFC in a week if no serious issues arise.
This commit is contained in:
Jack F Vogel 2008-05-16 18:46:30 +00:00
parent 8e230e30b7
commit 9ca4041b6c
17 changed files with 3521 additions and 1846 deletions

View File

@ -850,6 +850,8 @@ dev/ixgb/ixgb_ee.c optional ixgb
dev/ixgb/ixgb_hw.c optional ixgb
dev/ixgbe/ixgbe.c optional ixgbe \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/tcp_lro.c optional ixgbe \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_phy.c optional ixgbe \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_api.c optional ixgbe \

View File

@ -1,6 +1,6 @@
$FreeBSD$
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,3 +29,5 @@ $FreeBSD$
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/*$FreeBSD$*/

278
sys/dev/ixgbe/README Normal file
View File

@ -0,0 +1,278 @@
FreeBSD Driver for 10 Gigabit PCI Express Server Adapters
=============================================
$FreeBSD$
Contents
========
- Overview
- Supported Adapters
- Building and Installation
- Additional Configurations
- Known Limitations
Overview
========
This file describes the FreeBSD* driver for the 10 Gigabit PCIE Family of
Adapters. Drivers has been developed for use with FreeBSD 7 or later.
For questions related to hardware requirements, refer to the documentation
supplied with your Intel 10GbE adapter. All hardware requirements listed
apply to use with FreeBSD.
Supported Adapters
==================
The following Intel network adapters are compatible with the drivers in this
release:
Controller Adapter Name Physical Layer
---------- ------------ --------------
82598EB Intel(R) 10 Gigabit XF SR/AF 10G Base -LR (850 nm optical fiber)
Dual Port Server Adapter 10G Base -SR (1310 nm optical fiber)
82598EB Intel(R) 10 Gigabit XF SR/LR
Server Adapter
Intel(R) 82598EB 10 Gigabit AF
Network Connection
Intel(R) 82598EB 10 Gigabit AT
CX4 Network Connection
Building and Installation
=========================
NOTE: You must have kernel sources installed in order to compile the driver
module.
In the instructions below, x.x.x is the driver version as indicated in
the name of the driver tar.
1. Move the base driver tar file to the directory of your choice. For
example, use /home/username/ixgbe or /usr/local/src/ixgbe.
2. Untar/unzip the archive:
tar xfz ixgbe-x.x.x.tar.gz
3. To install man page:
cd ixgbe-x.x.x
gzip -c ixgbe.4 > /usr/share/man/man4/ixgbee.4.gz
4. To load the driver onto a running system:
cd ixgbe-x.x.x/src
make load
5. To assign an IP address to the interface, enter the following:
ifconfig ix<interface_num> <IP_address>
6. Verify that the interface works. Enter the following, where <IP_address>
is the IP address for another machine on the same subnet as the interface
that is being tested:
ping <IP_address>
7. If you want the driver to load automatically when the system is booted:
cd ixgbe-x.x.x/src
make
make install
Edit /boot/loader.conf, and add the following line:
ixgbe_load="YES"
OR
compile the driver into the kernel (see item 8).
Edit /etc/rc.conf, and create the appropriate ifconfig_ixgbe<interface_num>
entry:
ifconfig_ix<interface_num>="<ifconfig_settings>"
Example usage:
ifconfig_ix0="inet 192.168.10.1 netmask 255.255.255.0"
NOTE: For assistance, see the ifconfig man page.
8. If you want to compile the driver into the kernel, enter:
FreeBSD 7 or later:
cd ixgbe-x.x.x/src
cp *.[ch] /usr/src/sys/dev/ixgbe
cp Makefile.kernel /usr/src/sys/modules/ixgbe/Makefile
Edit the kernel configuration file (i.e., GENERIC or MYKERNEL) in
/usr/src/sys/i386/conf (replace "i386" with the appropriate system
architecture if necessary), and ensure the following line is present:
device ixgbe
Compile and install the kernel. The system must be reboot for the kernel
updates to take affect. For additional information on compiling the kernel,
consult the FreeBSD operating system documentation.
Configuration and Tuning
=========================
The driver supports Transmit/Receive Checksum Offload and Jumbo Frames on
all 10 Gigabit adapters.
Jumbo Frames
------------
To enable Jumbo Frames, use the ifconfig utility to increase the MTU
beyond 1500 bytes.
NOTES:
- The Jumbo Frames setting on the switch must be set to at least
22 bytes larger than that of the adapter.
- There are known performance issues with this driver when running
UDP traffic with Jumbo Frames.
The Jumbo Frames MTU range for Intel Adapters is 1500 to 16114. The default
MTU range is 1500. To modify the setting, enter the following:
ifconfig ix <interface_num> <hostname or IP address> mtu 9000
To confirm an interface's MTU value, use the ifconfig command. To confirm
the MTU used between two specific devices, use:
route get <destination_IP_address>
VLANs
-----
To create a new VLAN pseudo-interface:
ifconfig <vlan_name> create
To associate the VLAN pseudo-interface with a physical interface and
assign a VLAN ID, IP address, and netmask:
ifconfig <vlan_name> <ip_address> netmask <subnet_mask> vlan
<vlan_id> vlandev <physical_interface>
Example:
ifconfig vlan10 10.0.0.1 netmask 255.255.255.0 vlan 10 vlandev ixgbe0
In this example, all packets will be marked on egress with 802.1Q VLAN
tags, specifying a VLAN ID of 10.
To remove a VLAN pseudo-interface:
ifconfig <vlan_name> destroy
Checksum Offload
----------------
Checksum offloading supports both TCP and UDP packets and is
supported for both transmit and receive.
Checksum offloading can be enabled or disabled using ifconfig.
Both transmit and receive offloading will be either enabled or
disabled together. You cannot enable/disable one without the other.
To enable checksum offloading:
ifconfig <interface_num> rxcsum
To disable checksum offloading:
ifconfig <interface_num> -rxcsum
To confirm the current setting:
ifconfig <interface_num>
TSO
---
To disable:
ifconfig <interface_num> -tso
To re-enable:
ifconfig <interface_num> tso
LRO
___
Large Receive Offload is available in version 1.4.4, it is on
by default. It can be toggled off and on by using:
sysctl dev.ix.X.enable_lro=[0,1]
NOTE: when changing this feature you MUST be sure the interface
is reinitialized, it is easy to do this with ifconfig down/up.
The LRO code will ultimately move into the kernel stack code,
but for this first release it was included with the driver.
Important system configuration changes:
---------------------------------------
When there is a choice run on a 64bit OS rather than 32, it makes
a significant difference in improvement.
The default scheduler SCHED_4BSD is not smart about SMP locality issues.
Significant improvement can be achieved by switching to the ULE scheduler.
This is done by changing the entry in the config file from SCHED_4BSD to
SCHED_ULE. Note that this is only advisable on FreeBSD 7, on 6.X there have
been stability problems with ULE.
Change the file /etc/sysctl.conf, add the line:
hw.intr_storm_threshold: 8000 (the default is 1000)
Best throughput results are seen with a large MTU; use 9000 if possible.
The default number of descriptors is 256, increasing this to 1024 or even
2048 may improve performance.
Known Limitations
=================
Under small packets UDP stress test with 10GbE driver, the FreeBSD system
will drop UDP packets due to the fullness of socket buffers. You may want
to change the driver's Flow Control variables to the minimum value for
controlling packet reception.
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 freebsdnic@mailbox.intel.com.
License
=======
This software program is released under the terms of a license agreement
between you ('Licensee') and Intel. Do not use or load this software or any
associated materials (collectively, the 'Software') until you have carefully
read the full terms and conditions of the LICENSE located in this software
package. By loading or using the Software, you agree to the terms of this
Agreement. If you do not agree with the terms of this Agreement, do not
install or use the Software.
* Other names and brands may be claimed as the property of others.

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +1,36 @@
/**************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
All rights reserved.
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_H_
#define _IXGBE_H_
@ -80,8 +80,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/sysctl.h>
#include <sys/endian.h>
#include <sys/taskqueue.h>
#include <sys/pcpu.h>
#include "ixgbe_api.h"
#include "tcp_lro.h"
/* Tunables */
@ -157,7 +159,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define MAX_NUM_MULTICAST_ADDRESSES 128
#define IXGBE_MAX_SCATTER 100
#define IXGBE_MMBA 0x0010
#define IXGBE_MSIX_BAR 3
#define IXGBE_TSO_SIZE 65535
#define IXGBE_TX_BUFFER_SIZE ((u32) 1514)
#define IXGBE_RX_HDR_SIZE ((u32) 256)
@ -184,6 +186,9 @@ POSSIBILITY OF SUCH DAMAGE.
#define DEFAULT_ITR 1000000000/(MAX_IRQ_SEC * 256)
#define LINK_ITR 1000000000/(1950 * 256)
/* Used for auto RX queue configuration */
extern int mp_ncpus;
/*
* ******************************************************************************
* vendor_info_array
@ -203,7 +208,6 @@ typedef struct _ixgbe_vendor_info_t {
struct ixgbe_tx_buf {
int next_eop;
struct mbuf *m_head;
bus_dmamap_t map;
};
@ -233,15 +237,27 @@ struct ixgbe_dma_alloc {
*/
struct tx_ring {
struct adapter *adapter;
struct mtx tx_mtx;
u32 me;
u32 msix;
u32 eims;
u32 watchdog_timer;
union ixgbe_adv_tx_desc *tx_base;
volatile u32 tx_hwb;
struct ixgbe_dma_alloc txdma;
uint32_t next_avail_tx_desc;
uint32_t next_tx_to_clean;
struct task tx_task;
struct taskqueue *tq;
u32 next_avail_tx_desc;
u32 next_tx_to_clean;
struct ixgbe_tx_buf *tx_buffers;
volatile uint16_t tx_avail;
uint32_t txd_cmd;
volatile u16 tx_avail;
u32 txd_cmd;
bus_dma_tag_t txtag;
/* Soft Stats */
u32 no_tx_desc_avail;
u32 no_tx_desc_late;
u64 tx_irq;
u64 tx_packets;
};
@ -249,21 +265,28 @@ struct tx_ring {
* The Receive ring, one per rx queue
*/
struct rx_ring {
struct adapter *adapter;
u32 me;
u32 payload;
union ixgbe_adv_rx_desc *rx_base;
struct ixgbe_dma_alloc rxdma;
unsigned int last_cleaned;
unsigned int next_to_check;
struct ixgbe_rx_buf *rx_buffers;
bus_dma_tag_t rxtag[2];
bus_dmamap_t spare_map[2];
struct mbuf *fmp;
struct mbuf *lmp;
struct adapter *adapter;
struct mtx rx_mtx;
u32 me;
u32 msix;
u32 eims;
u32 payload;
struct task rx_task;
struct taskqueue *tq;
union ixgbe_adv_rx_desc *rx_base;
struct ixgbe_dma_alloc rxdma;
struct lro_ctrl lro;
unsigned int last_cleaned;
unsigned int next_to_check;
struct ixgbe_rx_buf *rx_buffers;
bus_dma_tag_t rxtag[2];
bus_dmamap_t spare_map[2];
struct mbuf *fmp;
struct mbuf *lmp;
/* Soft stats */
u64 packet_count;
u64 byte_count;
u64 rx_irq;
u64 packet_count;
u64 byte_count;
};
/* Our adapter structure */
@ -273,10 +296,10 @@ struct adapter {
/* FreeBSD operating-system-specific structures */
struct ixgbe_osdep osdep;
struct device *dev;
struct resource *res_memory;
struct resource *res_msix;
struct resource *pci_mem;
struct resource *msix_mem;
/*
* Interrupt resources:
@ -286,31 +309,30 @@ struct adapter {
void *tag[IXGBE_MSGS];
struct resource *res[IXGBE_MSGS];
int rid[IXGBE_MSGS];
u32 eims_mask;
struct ifmedia media;
struct callout timer;
int watchdog_timer;
int msix;
int if_flags;
struct mtx core_mtx;
struct mtx tx_mtx;
/* Legacy Fast Intr handling */
struct task link_task;
struct task rxtx_task;
struct taskqueue *tq;
/* Info about the board itself */
uint32_t part_num;
boolean_t link_active;
uint16_t max_frame_size;
uint16_t link_duplex;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
u32 part_num;
bool link_active;
u16 max_frame_size;
u32 link_speed;
u32 tx_int_delay;
u32 tx_abs_int_delay;
u32 rx_int_delay;
u32 rx_abs_int_delay;
/* Indicates the cluster size to use */
boolean_t bigbufs;
bool bigbufs;
/*
* Transmit rings:
@ -327,20 +349,35 @@ struct adapter {
struct rx_ring *rx_rings;
int num_rx_desc;
int num_rx_queues;
uint32_t rx_process_limit;
u32 rx_process_limit;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_alloc_failed;
unsigned long mbuf_cluster_failed;
unsigned long no_tx_desc_avail1;
unsigned long no_tx_desc_avail2;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long tso_tx;
unsigned long linkvec;
unsigned long link_irq;
struct ixgbe_hw_stats stats;
};
#define IXGBE_CORE_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->core_mtx, _name, "IXGBE Core Lock", MTX_DEF)
#define IXGBE_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
#define IXGBE_TX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->tx_mtx)
#define IXGBE_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
#define IXGBE_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
#define IXGBE_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
#define IXGBE_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
#define IXGBE_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
#define IXGBE_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
#define IXGBE_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_mtx)
#define IXGBE_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->core_mtx, MA_OWNED)
#define IXGBE_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
#endif /* _IXGBE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,15 +29,13 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#include "ixgbe_api.h"
#include "ixgbe_common.h"
extern s32 ixgbe_init_shared_code_82598(struct ixgbe_hw *hw);
extern s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw);
extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw);
/**
* ixgbe_init_shared_code - Initialize the shared code
@ -55,12 +53,6 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
{
s32 status;
/*
* Assign generic function pointers before entering adapter-specific
* init
*/
ixgbe_assign_func_pointers_generic(hw);
/*
* Set the mac type
*/
@ -68,8 +60,7 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
status = ixgbe_init_shared_code_82598(hw);
status = ixgbe_init_shared_code_phy(hw);
status = ixgbe_init_ops_82598(hw);
break;
default:
status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
@ -90,13 +81,19 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
{
s32 ret_val = IXGBE_SUCCESS;
DEBUGFUNC("ixgbe_set_mac_type");
DEBUGFUNC("ixgbe_set_mac_type\n");
if (hw->vendor_id == IXGBE_INTEL_VENDOR_ID) {
switch (hw->device_id) {
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AT:
case IXGBE_DEV_ID_82598AT_DUAL_PORT:
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
case IXGBE_DEV_ID_82598EB_XF_LR:
hw->mac.type = ixgbe_mac_82598EB;
break;
default:
@ -107,6 +104,8 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
}
DEBUGOUT2("ixgbe_set_mac_type found mac: %d, returns: %d\n",
hw->mac.type, ret_val);
return ret_val;
}
@ -118,8 +117,8 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
**/
s32 ixgbe_init_hw(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_init_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.init_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -131,12 +130,12 @@ s32 ixgbe_init_hw(struct ixgbe_hw *hw)
**/
s32 ixgbe_reset_hw(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_reset_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.reset_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_start_hw - Prepares hardware for TX/TX
* ixgbe_start_hw - Prepares hardware for Rx/Tx
* @hw: pointer to hardware structure
*
* Starts the hardware by filling the bus info structure and media type,
@ -147,8 +146,8 @@ s32 ixgbe_reset_hw(struct ixgbe_hw *hw)
**/
s32 ixgbe_start_hw(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_start_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.start_hw, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -160,8 +159,8 @@ s32 ixgbe_start_hw(struct ixgbe_hw *hw)
**/
s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_clear_hw_cntrs, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.clear_hw_cntrs, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -172,8 +171,8 @@ s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw)
**/
enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_get_media_type, (hw),
ixgbe_media_type_unknown);
return ixgbe_call_func(hw, hw->mac.ops.get_media_type, (hw),
ixgbe_media_type_unknown);
}
/**
@ -182,14 +181,14 @@ enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw)
* @mac_addr: Adapter MAC address
*
* Reads the adapter's MAC address from the first Receive Address Register
* (RAR0) A reset of the adapter must have been performed prior to calling this
* function in order for the MAC address to have been loaded from the EEPROM
* into RAR0
* (RAR0) A reset of the adapter must have been performed prior to calling
* this function in order for the MAC address to have been loaded from the
* EEPROM into RAR0
**/
s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr)
{
return ixgbe_call_func(hw, ixgbe_func_get_mac_addr,
(hw, mac_addr), IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.get_mac_addr,
(hw, mac_addr), IXGBE_NOT_IMPLEMENTED);
}
/**
@ -200,36 +199,34 @@ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr)
**/
s32 ixgbe_get_bus_info(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_get_bus_info, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.get_bus_info, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_get_num_of_tx_queues - Get TX queues
* ixgbe_get_num_of_tx_queues - Get Tx queues
* @hw: pointer to hardware structure
*
* Returns the number of transmit queues for the given adapter.
**/
u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_get_num_of_tx_queues,
(hw), 0);
return hw->mac.max_tx_queues;
}
/**
* ixgbe_get_num_of_rx_queues - Get RX queues
* ixgbe_get_num_of_rx_queues - Get Rx queues
* @hw: pointer to hardware structure
*
* Returns the number of receive queues for the given adapter.
**/
u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_get_num_of_rx_queues,
(hw), 0);
return hw->mac.max_rx_queues;
}
/**
* ixgbe_stop_adapter - Disable TX/TX units
* ixgbe_stop_adapter - Disable Rx/Tx units
* @hw: pointer to hardware structure
*
* Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts,
@ -239,8 +236,20 @@ u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw)
**/
s32 ixgbe_stop_adapter(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_stop_adapter, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.stop_adapter, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_read_pba_num - Reads part number from EEPROM
* @hw: pointer to hardware structure
* @pba_num: stores the part number from the EEPROM
*
* Reads the part number from the EEPROM.
**/
s32 ixgbe_read_pba_num(struct ixgbe_hw *hw, u32 *pba_num)
{
return ixgbe_read_pba_num_generic(hw, pba_num);
}
/**
@ -255,9 +264,9 @@ s32 ixgbe_identify_phy(struct ixgbe_hw *hw)
if (hw->phy.type == ixgbe_phy_unknown) {
status = ixgbe_call_func(hw,
ixgbe_func_identify_phy,
(hw),
IXGBE_NOT_IMPLEMENTED);
hw->phy.ops.identify,
(hw),
IXGBE_NOT_IMPLEMENTED);
}
return status;
@ -278,14 +287,27 @@ s32 ixgbe_reset_phy(struct ixgbe_hw *hw)
}
if (status == IXGBE_SUCCESS) {
status = ixgbe_call_func(hw,
ixgbe_func_reset_phy,
(hw),
IXGBE_NOT_IMPLEMENTED);
status = ixgbe_call_func(hw, hw->phy.ops.reset, (hw),
IXGBE_NOT_IMPLEMENTED);
}
return status;
}
/**
* ixgbe_get_phy_firmware_version -
* @hw: pointer to hardware structure
* @firmware_version: pointer to firmware version
**/
s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version)
{
s32 status = IXGBE_SUCCESS;
status = ixgbe_call_func(hw, hw->phy.ops.get_firmware_version,
(hw, firmware_version),
IXGBE_NOT_IMPLEMENTED);
return status;
}
/**
* ixgbe_read_phy_reg - Read PHY register
* @hw: pointer to hardware structure
@ -295,23 +317,10 @@ s32 ixgbe_reset_phy(struct ixgbe_hw *hw)
* Reads a value from a specified PHY register
**/
s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 *phy_data)
u16 *phy_data)
{
s32 status = IXGBE_SUCCESS;
if (hw->phy.type == ixgbe_phy_unknown) {
if (ixgbe_identify_phy(hw) != IXGBE_SUCCESS) {
status = IXGBE_ERR_PHY;
}
}
if (status == IXGBE_SUCCESS) {
status = ixgbe_call_func(hw,
ixgbe_func_read_phy_reg,
(hw, reg_addr, device_type, phy_data),
IXGBE_NOT_IMPLEMENTED);
}
return status;
return ixgbe_call_func(hw, hw->phy.ops.read_reg, (hw, reg_addr,
device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
}
/**
@ -323,23 +332,53 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
* Writes a value to specified PHY register
**/
s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 phy_data)
u16 phy_data)
{
s32 status = IXGBE_SUCCESS;
return ixgbe_call_func(hw, hw->phy.ops.write_reg, (hw, reg_addr,
device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
}
if (hw->phy.type == ixgbe_phy_unknown) {
if (ixgbe_identify_phy(hw) != IXGBE_SUCCESS) {
status = IXGBE_ERR_PHY;
}
}
/**
* ixgbe_setup_phy_link - Restart PHY autoneg
* @hw: pointer to hardware structure
*
* Restart autonegotiation and PHY and waits for completion.
**/
s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, hw->phy.ops.setup_link, (hw),
IXGBE_NOT_IMPLEMENTED);
}
if (status == IXGBE_SUCCESS) {
status = ixgbe_call_func(hw,
ixgbe_func_write_phy_reg,
(hw, reg_addr, device_type, phy_data),
IXGBE_NOT_IMPLEMENTED);
}
return status;
/**
* ixgbe_check_phy_link - Determine link and speed status
* @hw: pointer to hardware structure
*
* Reads a PHY register to determine if link is up and the current speed for
* the PHY.
**/
s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up)
{
return ixgbe_call_func(hw, hw->phy.ops.check_link, (hw, speed,
link_up), IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_setup_phy_link_speed - Set auto advertise
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
*
* Sets the auto advertised capabilities
**/
s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
{
return ixgbe_call_func(hw, hw->phy.ops.setup_link_speed, (hw, speed,
autoneg, autoneg_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -351,8 +390,8 @@ s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
**/
s32 ixgbe_setup_link(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_setup_link, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -362,10 +401,11 @@ s32 ixgbe_setup_link(struct ixgbe_hw *hw)
* Reads the links register to determine if link is up and the current speed
**/
s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up)
bool *link_up, bool link_up_wait_to_complete)
{
return ixgbe_call_func(hw, ixgbe_func_check_link, (hw, speed, link_up),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.check_link, (hw, speed,
link_up, link_up_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -377,29 +417,29 @@ s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
* Set the link speed and restarts the link.
**/
s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
bool autoneg,
bool autoneg_wait_to_complete)
{
return ixgbe_call_func(hw, ixgbe_func_setup_link_speed, (hw, speed,
autoneg, autoneg_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.setup_link_speed, (hw, speed,
autoneg, autoneg_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_get_link_settings - Set link settings to default
* ixgbe_get_link_capabilities - Returns link capabilities
* @hw: pointer to hardware structure
*
* Sets the default link settings based on attach type in the hw struct.
* Determines the link capabilities of the current configuration.
**/
s32 ixgbe_get_link_settings(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *autoneg)
s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *autoneg)
{
return ixgbe_call_func(hw, ixgbe_func_get_link_settings, (hw, speed,
autoneg), IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.get_link_capabilities, (hw,
speed, autoneg), IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_led_on - Turn on LED's
* ixgbe_led_on - Turn on LEDs
* @hw: pointer to hardware structure
* @index: led number to turn on
*
@ -407,12 +447,12 @@ s32 ixgbe_get_link_settings(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
**/
s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index)
{
return ixgbe_call_func(hw, ixgbe_func_led_on, (hw, index),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.led_on, (hw, index),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_led_off - Turn off LED's
* ixgbe_led_off - Turn off LEDs
* @hw: pointer to hardware structure
* @index: led number to turn off
*
@ -420,12 +460,12 @@ s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index)
**/
s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index)
{
return ixgbe_call_func(hw, ixgbe_func_led_off, (hw, index),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.led_off, (hw, index),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_blink_led_start - Blink LED's
* ixgbe_blink_led_start - Blink LEDs
* @hw: pointer to hardware structure
* @index: led number to blink
*
@ -433,24 +473,24 @@ s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index)
**/
s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index)
{
return ixgbe_call_func(hw, ixgbe_func_blink_led_start, (hw, index),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.blink_led_start, (hw, index),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_blink_led_stop - Stop blinking LED's
* ixgbe_blink_led_stop - Stop blinking LEDs
* @hw: pointer to hardware structure
*
* Stop blinking LED based on index.
**/
s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index)
{
return ixgbe_call_func(hw, ixgbe_func_blink_led_stop, (hw, index),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.blink_led_stop, (hw, index),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_init_eeprom_params - Initialiaze EEPROM parameters
* ixgbe_init_eeprom_params - Initialize EEPROM parameters
* @hw: pointer to hardware structure
*
* Initializes the EEPROM parameters ixgbe_eeprom_info within the
@ -458,8 +498,8 @@ s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index)
**/
s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_init_eeprom_params, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->eeprom.ops.init_params, (hw),
IXGBE_NOT_IMPLEMENTED);
}
@ -475,25 +515,8 @@ s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw)
**/
s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data)
{
s32 status;
/*
* Initialize EEPROM parameters. This will not do anything if the
* EEPROM structure has already been initialized
*/
ixgbe_init_eeprom_params(hw);
/* Check for invalid offset */
if (offset >= hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
} else {
status = ixgbe_call_func(hw,
ixgbe_func_write_eeprom,
(hw, offset, data),
IXGBE_NOT_IMPLEMENTED);
}
return status;
return ixgbe_call_func(hw, hw->eeprom.ops.write, (hw, offset, data),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -506,25 +529,8 @@ s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data)
**/
s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
s32 status;
/*
* Initialize EEPROM parameters. This will not do anything if the
* EEPROM structure has already been initialized
*/
ixgbe_init_eeprom_params(hw);
/* Check for invalid offset */
if (offset >= hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
} else {
status = ixgbe_call_func(hw,
ixgbe_func_read_eeprom,
(hw, offset, data),
IXGBE_NOT_IMPLEMENTED);
}
return status;
return ixgbe_call_func(hw, hw->eeprom.ops.read, (hw, offset, data),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -536,8 +542,8 @@ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data)
**/
s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val)
{
return ixgbe_call_func(hw, ixgbe_func_validate_eeprom_checksum,
(hw, checksum_val), IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->eeprom.ops.validate_checksum,
(hw, checksum_val), IXGBE_NOT_IMPLEMENTED);
}
/**
@ -546,25 +552,37 @@ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val)
**/
s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_update_eeprom_checksum, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->eeprom.ops.update_checksum, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_set_rar - Set RX address register
* ixgbe_set_rar - Set Rx address register
* @hw: pointer to hardware structure
* @addr: Address to put into receive address register
* @index: Receive address register to write
* @vind: Vind to set RAR to
* @addr: Address to put into receive address register
* @vmdq: VMDq "set"
* @enable_addr: set flag that address is active
*
* Puts an ethernet address into a receive address register.
**/
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind,
u32 enable_addr)
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr)
{
return ixgbe_call_func(hw, ixgbe_func_set_rar, (hw, index, addr, vind,
enable_addr), IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.set_rar, (hw, index, addr, vmdq,
enable_addr), IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_set_vmdq - Associate a VMDq index with a receive address
* @hw: pointer to hardware structure
* @rar: receive address register index to associate with VMDq index
* @vmdq: VMDq set or pool index
**/
s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
{
return ixgbe_call_func(hw, hw->mac.ops.set_vmdq, (hw, rar, vmdq),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -572,13 +590,13 @@ s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vind,
* @hw: pointer to hardware structure
*
* Places the MAC address in receive address register 0 and clears the rest
* of the receive addresss registers. Clears the multicast table. Assumes
* of the receive address registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
**/
s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_init_rx_addrs, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.init_rx_addrs, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -587,7 +605,26 @@ s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw)
**/
u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_get_num_rx_addrs, (hw), 0);
return hw->mac.num_rar_entries;
}
/**
* ixgbe_update_uc_addr_list - Updates the MAC's list of secondary addresses
* @hw: pointer to hardware structure
* @addr_list: the list of new multicast addresses
* @addr_count: number of addresses
* @func: iterator function to walk the multicast address list
*
* The given list replaces any existing list. Clears the secondary addrs from
* receive address registers. Uses unused receive address registers for the
* first secondary addresses, and falls back to promiscuous mode as needed.
**/
s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func)
{
return ixgbe_call_func(hw, hw->mac.ops.update_uc_addr_list, (hw,
addr_list, addr_count, func),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -595,19 +632,19 @@ u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw)
* @hw: pointer to hardware structure
* @mc_addr_list: the list of new multicast addresses
* @mc_addr_count: number of addresses
* @pad: number of bytes between addresses in the list
* @func: iterator function to walk the multicast address list
*
* The given list replaces any existing list. Clears the MC addrs from receive
* address registers and the multicast table. Uses unsed receive address
* address registers and the multicast table. Uses unused receive address
* registers for the first multicast addresses, and hashes the rest into the
* multicast table.
**/
s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, u32 pad)
u32 mc_addr_count, ixgbe_mc_addr_itr func)
{
return ixgbe_call_func(hw, ixgbe_func_update_mc_addr_list, (hw,
mc_addr_list, mc_addr_count, pad),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.update_mc_addr_list, (hw,
mc_addr_list, mc_addr_count, func),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -618,8 +655,8 @@ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
**/
s32 ixgbe_enable_mc(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_enable_mc, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.enable_mc, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -630,8 +667,8 @@ s32 ixgbe_enable_mc(struct ixgbe_hw *hw)
**/
s32 ixgbe_disable_mc(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_disable_mc, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.disable_mc, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -642,8 +679,8 @@ s32 ixgbe_disable_mc(struct ixgbe_hw *hw)
**/
s32 ixgbe_clear_vfta(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_clear_vfta, (hw),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.clear_vfta, (hw),
IXGBE_NOT_IMPLEMENTED);
}
/**
@ -657,8 +694,8 @@ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw)
**/
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
{
return ixgbe_call_func(hw, ixgbe_func_set_vfta, (hw, vlan, vind,
vlan_on), IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.set_vfta, (hw, vlan, vind,
vlan_on), IXGBE_NOT_IMPLEMENTED);
}
/**
@ -670,11 +707,10 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
**/
s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
{
return ixgbe_call_func(hw, ixgbe_func_setup_fc, (hw, packetbuf_num),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.setup_fc, (hw, packetbuf_num),
IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_read_analog_reg8 - Reads 8 bit analog register
* @hw: pointer to hardware structure
@ -685,8 +721,8 @@ s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
**/
s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val)
{
return ixgbe_call_func(hw, ixgbe_func_read_analog_reg8, (hw, reg, val),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.read_analog_reg8, (hw, reg,
val), IXGBE_NOT_IMPLEMENTED);
}
/**
@ -699,7 +735,7 @@ s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val)
**/
s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val)
{
return ixgbe_call_func(hw, ixgbe_func_write_analog_reg8, (hw, reg, val),
IXGBE_NOT_IMPLEMENTED);
return ixgbe_call_func(hw, hw->mac.ops.write_analog_reg8, (hw, reg,
val), IXGBE_NOT_IMPLEMENTED);
}

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,8 +29,8 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_API_H_
#define _IXGBE_API_H_
@ -50,21 +50,30 @@ s32 ixgbe_get_bus_info(struct ixgbe_hw *hw);
u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw);
u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw);
s32 ixgbe_stop_adapter(struct ixgbe_hw *hw);
s32 ixgbe_read_pba_num(struct ixgbe_hw *hw, u32 *pba_num);
s32 ixgbe_identify_phy(struct ixgbe_hw *hw);
s32 ixgbe_reset_phy(struct ixgbe_hw *hw);
s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 *phy_data);
u16 *phy_data);
s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 phy_data);
u16 phy_data);
s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw);
s32 ixgbe_check_phy_link(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_setup_link(struct ixgbe_hw *hw);
s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg, bool autoneg_wait_to_complete);
bool autoneg, bool autoneg_wait_to_complete);
s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_get_link_settings(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *autoneg);
bool *link_up, bool link_up_wait_to_complete);
s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *autoneg);
s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index);
@ -76,21 +85,26 @@ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw);
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr,
u32 vind, u32 enable_addr);
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw);
u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw);
s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, u32 pad);
u32 mc_addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_enable_mc(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc(struct ixgbe_hw *hw);
s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
u32 vind, bool vlan_on);
s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);
s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,52 +29,54 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_COMMON_H_
#define _IXGBE_COMMON_H_
#include "ixgbe_type.h"
s32 ixgbe_assign_func_pointers_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw);
s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num);
s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr);
s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw);
s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw);
s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data);
u16 *data);
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val);
u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr,
u32 vind, u32 enable_addr);
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw);
s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, u32 pad);
u32 mc_addr_count,
ixgbe_mc_addr_itr func);
s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packtetbuf_num);
u32 vind, bool vlan_on);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val);
#endif /* IXGBE_COMMON */

View File

@ -1,36 +1,36 @@
/**************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
All rights reserved.
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_OS_H_
#define _IXGBE_OS_H_
@ -91,6 +91,16 @@ typedef boolean_t bool;
#define le16_to_cpu
#if defined(__i386__) || defined(__amd64__)
#define mb() __asm volatile("mfence" ::: "memory")
#define wmb() __asm volatile("sfence" ::: "memory")
#define rmb() __asm volatile("lfence" ::: "memory")
#else
#define mb()
#define rmb()
#define wmb()
#endif
struct ixgbe_osdep
{
bus_space_tag_t mem_bus_space_tag;

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,43 +29,32 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#include "ixgbe_api.h"
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
/**
* ixgbe_init_shared_code_phy - Initialize PHY shared code
* @hw: pointer to hardware structure
**/
s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw)
{
/* Assign function pointers */
ixgbe_assign_func_pointers_phy(hw);
return IXGBE_SUCCESS;
}
/**
* ixgbe_assign_func_pointers_phy - Assigns PHY-specific function pointers
* @hw: pointer to hardware structure
* ixgbe_init_phy_ops_generic - Inits PHY function ptrs
* @hw: pointer to the hardware structure
*
* Note, generic function pointers have already been assigned, so the
* function pointers set here are only for PHY-specific functions.
* Initialize the function pointers.
**/
s32 ixgbe_assign_func_pointers_phy(struct ixgbe_hw *hw)
s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
{
hw->func.ixgbe_func_reset_phy =
&ixgbe_reset_phy_generic;
hw->func.ixgbe_func_read_phy_reg =
&ixgbe_read_phy_reg_generic;
hw->func.ixgbe_func_write_phy_reg =
&ixgbe_write_phy_reg_generic;
hw->func.ixgbe_func_identify_phy =
&ixgbe_identify_phy_generic;
struct ixgbe_phy_info *phy = &hw->phy;
/* PHY */
phy->ops.identify = &ixgbe_identify_phy_generic;
phy->ops.reset = &ixgbe_reset_phy_generic;
phy->ops.read_reg = &ixgbe_read_phy_reg_generic;
phy->ops.write_reg = &ixgbe_write_phy_reg_generic;
phy->ops.setup_link = &ixgbe_setup_phy_link_generic;
phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
phy->ops.check_link = NULL;
phy->ops.get_firmware_version = NULL;
return IXGBE_SUCCESS;
}
@ -81,15 +70,21 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 phy_addr;
for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
if (ixgbe_validate_phy_addr(hw, phy_addr)) {
hw->phy.addr = phy_addr;
ixgbe_get_phy_id(hw);
hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
status = IXGBE_SUCCESS;
break;
if (hw->phy.type == ixgbe_phy_unknown) {
for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
if (ixgbe_validate_phy_addr(hw, phy_addr)) {
hw->phy.addr = phy_addr;
ixgbe_get_phy_id(hw);
hw->phy.type =
ixgbe_get_phy_type_from_id(hw->phy.id);
status = IXGBE_SUCCESS;
break;
}
}
} else {
status = IXGBE_SUCCESS;
}
return status;
}
@ -104,10 +99,8 @@ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr)
bool valid = FALSE;
hw->phy.addr = phy_addr;
ixgbe_read_phy_reg_generic(hw,
IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id);
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id);
if (phy_id != 0xFFFF && phy_id != 0x0)
valid = TRUE;
@ -126,17 +119,15 @@ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
u16 phy_id_high = 0;
u16 phy_id_low = 0;
status = ixgbe_read_phy_reg_generic(hw,
IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id_high);
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id_high);
if (status == IXGBE_SUCCESS) {
hw->phy.id = (u32)(phy_id_high << 16);
status = ixgbe_read_phy_reg_generic(hw,
IXGBE_MDIO_PHY_ID_LOW,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id_low);
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&phy_id_low);
hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
}
@ -154,14 +145,21 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
enum ixgbe_phy_type phy_type;
switch (phy_id) {
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
case QT2022_PHY_ID:
phy_type = ixgbe_phy_qt;
break;
case ATH_PHY_ID:
phy_type = ixgbe_phy_nl;
break;
default:
phy_type = ixgbe_phy_unknown;
break;
}
DEBUGOUT1("phy type found is %d\n", phy_type);
return phy_type;
}
@ -175,9 +173,9 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
* Perform soft PHY reset to the PHY_XS.
* This will cause a soft reset to the PHY
*/
return ixgbe_write_phy_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE,
IXGBE_MDIO_PHY_XS_RESET);
return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE,
IXGBE_MDIO_PHY_XS_RESET);
}
/**
@ -187,7 +185,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
* @phy_data: Pointer to read data from PHY register
**/
s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 *phy_data)
u32 device_type, u16 *phy_data)
{
u32 command;
u32 i;
@ -206,9 +204,9 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
if (status == IXGBE_SUCCESS) {
/* Setup and write the address cycle command */
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@ -238,9 +236,9 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* command
*/
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@ -274,6 +272,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
ixgbe_release_swfw_sync(hw, gssr);
}
return status;
}
@ -285,7 +284,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* @phy_data: Data to write to the PHY register
**/
s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 phy_data)
u32 device_type, u16 phy_data)
{
u32 command;
u32 i;
@ -306,9 +305,9 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
/* Setup and write the address cycle command */
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@ -322,14 +321,14 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
DEBUGFUNC("PHY address cmd didn't complete\n");
if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
break;
}
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
DEBUGOUT("PHY address cmd didn't complete\n");
status = IXGBE_ERR_PHY;
}
if (status == IXGBE_SUCCESS) {
/*
@ -337,9 +336,9 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
* command
*/
command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) |
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
(device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
(IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@ -353,15 +352,14 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) {
DEBUGFUNC("PHY write command did not "
"complete.\n");
if ((command & IXGBE_MSCA_MDI_COMMAND) == 0)
break;
}
}
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0)
if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
DEBUGOUT("PHY address cmd didn't complete\n");
status = IXGBE_ERR_PHY;
}
}
ixgbe_release_swfw_sync(hw, gssr);
@ -371,45 +369,303 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
}
/**
* ixgbe_setup_phy_link - Restart PHY autoneg
* ixgbe_setup_phy_link_generic - Set and restart autoneg
* @hw: pointer to hardware structure
*
* Restart autonegotiation and PHY and waits for completion.
**/
s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw)
s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
{
return ixgbe_call_func(hw, ixgbe_func_setup_phy_link, (hw),
IXGBE_NOT_IMPLEMENTED);
s32 status = IXGBE_NOT_IMPLEMENTED;
u32 time_out;
u32 max_time_out = 10;
u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
/*
* Set advertisement settings in PHY based on autoneg_advertised
* settings. If autoneg_advertised = 0, then advertise default values
* tnx devices cannot be "forced" to a autoneg 10G and fail. But can
* for a 1G.
*/
hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */
else
autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */
hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
/* Restart PHY autonegotiation and wait for completion */
hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
autoneg_reg |= IXGBE_MII_RESTART;
hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
/* Wait for autonegotiation to finish */
for (time_out = 0; time_out < max_time_out; time_out++) {
usec_delay(10);
/* Restart PHY autonegotiation and wait for completion */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
&autoneg_reg);
autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
status = IXGBE_SUCCESS;
break;
}
}
if (time_out == max_time_out)
status = IXGBE_ERR_LINK_SETUP;
return status;
}
/**
* ixgbe_check_phy_link - Determine link and speed status
* @hw: pointer to hardware structure
*
* Reads a PHY register to determine if link is up and the current speed for
* the PHY.
**/
s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up)
{
return ixgbe_call_func(hw, ixgbe_func_check_phy_link, (hw, speed,
link_up), IXGBE_NOT_IMPLEMENTED);
}
/**
* ixgbe_setup_phy_link_speed - Set auto advertise
* ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: TRUE if autonegotiation enabled
*
* Sets the auto advertised capabilities
**/
s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete)
{
return ixgbe_call_func(hw, ixgbe_func_setup_phy_link_speed, (hw, speed,
autoneg, autoneg_wait_to_complete),
IXGBE_NOT_IMPLEMENTED);
UNREFERENCED_PARAMETER(autoneg);
UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
/*
* Clear autoneg_advertised and set new values based on input link
* speed.
*/
hw->phy.autoneg_advertised = 0;
if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
}
if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
}
/* Setup link based on the new speed settings */
hw->phy.ops.setup_link(hw);
return IXGBE_SUCCESS;
}
/**
* ixgbe_check_phy_link_tnx - Determine link and speed status
* @hw: pointer to hardware structure
*
* Reads the VS1 register to determine if link is up and the current speed for
* the PHY.
**/
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up)
{
s32 status = IXGBE_SUCCESS;
u32 time_out;
u32 max_time_out = 10;
u16 phy_link = 0;
u16 phy_speed = 0;
u16 phy_data = 0;
/* Initialize speed and link to default case */
*link_up = FALSE;
*speed = IXGBE_LINK_SPEED_10GB_FULL;
/*
* Check current speed and link status of the PHY register.
* This is a vendor specific register and may have to
* be changed for other copper PHYs.
*/
for (time_out = 0; time_out < max_time_out; time_out++) {
usec_delay(10);
status = hw->phy.ops.read_reg(hw,
IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
&phy_data);
phy_link = phy_data &
IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
phy_speed = phy_data &
IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
*link_up = TRUE;
if (phy_speed ==
IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
*speed = IXGBE_LINK_SPEED_1GB_FULL;
break;
}
}
return status;
}
/**
* ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
* @hw: pointer to hardware structure
* @firmware_version: pointer to the PHY Firmware Version
**/
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version)
{
s32 status = IXGBE_SUCCESS;
status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
firmware_version);
return status;
}
/**
* ixgbe_reset_phy_nl - Performs a PHY reset
* @hw: pointer to hardware structure
**/
s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
{
u16 phy_offset, control, eword, edata, list_crc, block_crc, id, sfp_id;
bool end_data = FALSE;
u16 list_offset, data_offset;
u16 phy_data = 0;
s32 ret_val = IXGBE_SUCCESS;
u32 i;
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
/* reset the PHY and poll for completion */
hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE,
(phy_data | IXGBE_MDIO_PHY_XS_RESET));
for (i = 0; i < 100; i++) {
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0 )
break;
msec_delay(10);
}
if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
DEBUGOUT("PHY reset did not complete.\n");
ret_val = IXGBE_ERR_PHY;
goto out;
}
/* read offset to PHY init contents */
hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, &list_offset);
if ((!list_offset) || (list_offset == 0xFFFF)) {
ret_val = IXGBE_ERR_PHY;
goto out;
}
/* Acquire the CRC */
hw->eeprom.ops.read(hw, list_offset, &list_crc);
/* Shift offset to first ID word */
list_offset++;
/* determine the sfp sequence based on device ID */
switch (hw->device_id) {
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
sfp_id = 0;
break;
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
sfp_id = 1;
break;
default:
ret_val = IXGBE_ERR_PHY;
goto out;
}
/*
* Find the matching sfp ID in the EEPROM
* and program the init sequence
*/
hw->eeprom.ops.read(hw, list_offset, &id);
while (!((id == IXGBE_CONTROL_EOL_NL) || (end_data == TRUE))) {
if (id == sfp_id) {
list_offset++;
hw->eeprom.ops.read(hw, list_offset, &data_offset);
if ((!data_offset) || (data_offset == 0xFFFF))
break;
ret_val = hw->eeprom.ops.read(hw, data_offset,
&block_crc);
data_offset++;
while (!end_data) {
/*
* Read control word from PHY init contents
* offset
*/
ret_val = hw->eeprom.ops.read(hw, data_offset,
&eword);
control = (eword & IXGBE_CONTROL_MASK_NL) >>
IXGBE_CONTROL_SHIFT_NL;
edata = eword & IXGBE_DATA_MASK_NL;
switch (control) {
case IXGBE_DELAY_NL:
data_offset++;
DEBUGOUT1("DELAY: %d MS\n", edata);
msec_delay(edata);
break;
case IXGBE_DATA_NL:
DEBUGOUT("DATA: \n");
data_offset++;
hw->eeprom.ops.read(hw, data_offset++,
&phy_offset);
for (i = 0; i < edata; i++) {
hw->eeprom.ops.read(hw,
data_offset,
&eword);
hw->phy.ops.write_reg(hw,
phy_offset,
IXGBE_TWINAX_DEV,
eword);
DEBUGOUT2("Wrote %4.4x to %4.4x\n",
eword, phy_offset);
data_offset++;
phy_offset++;
}
break;
case IXGBE_CONTROL_NL:
data_offset++;
DEBUGOUT("CONTROL: \n");
if (edata == IXGBE_CONTROL_EOL_NL) {
DEBUGOUT("EOL\n");
end_data = TRUE;
} else if (edata == IXGBE_CONTROL_SOL_NL) {
DEBUGOUT("SOL\n");
} else {
DEBUGOUT("Bad control value\n");
ret_val = IXGBE_ERR_PHY;
goto out;
}
break;
default:
DEBUGOUT("Bad control type\n");
ret_val = IXGBE_ERR_PHY;
goto out;
}
}
} else {
list_offset += 2;
ret_val = hw->eeprom.ops.read(hw, list_offset, &id);
if (ret_val)
goto out;
}
}
out:
return ret_val;
}

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,32 +29,36 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_PHY_H_
#define _IXGBE_PHY_H_
#include "ixgbe_type.h"
s32 ixgbe_init_shared_code_phy(struct ixgbe_hw *hw);
s32 ixgbe_assign_func_pointers_phy(struct ixgbe_hw *hw);
s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw);
s32 ixgbe_check_phy_link(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw);
s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 *phy_data);
u32 device_type, u16 *phy_data);
s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 phy_data);
u32 device_type, u16 phy_data);
s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw);
s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
/* PHY specific */
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *link_up);
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version);
s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
#endif /* _IXGBE_PHY_H_ */

View File

@ -1,6 +1,6 @@
/*******************************************************************************
/******************************************************************************
Copyright (c) 2001-2007, Intel Corporation
Copyright (c) 2001-2008, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -29,8 +29,8 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/* $FreeBSD$ */
******************************************************************************/
/*$FreeBSD$*/
#ifndef _IXGBE_TYPE_H_
#define _IXGBE_TYPE_H_
@ -43,7 +43,13 @@
/* Device IDs */
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
#define IXGBE_DEV_ID_82598AT 0x10C8
#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10D7
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
/* General Registers */
#define IXGBE_CTRL 0x00000
@ -74,11 +80,11 @@
#define IXGBE_EIMC 0x00888
#define IXGBE_EIAC 0x00810
#define IXGBE_EIAM 0x00890
#define IXGBE_EITR(_i) (0x00820 + ((_i) * 4)) /* 0x820-0x86c */
#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */
#define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : (0x012300 + ((_i) * 4)))
#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */
#define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */
#define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */
#define IXGBE_PBACL 0x11068
#define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4)))
#define IXGBE_GPIE 0x00898
/* Flow Control Registers */
@ -90,19 +96,33 @@
#define IXGBE_TFCS 0x0CE00
/* Receive DMA Registers */
#define IXGBE_RDBAL(_i) (0x01000 + ((_i) * 0x40)) /* 64 of each (0-63)*/
#define IXGBE_RDBAH(_i) (0x01004 + ((_i) * 0x40))
#define IXGBE_RDLEN(_i) (0x01008 + ((_i) * 0x40))
#define IXGBE_RDH(_i) (0x01010 + ((_i) * 0x40))
#define IXGBE_RDT(_i) (0x01018 + ((_i) * 0x40))
#define IXGBE_RXDCTL(_i) (0x01028 + ((_i) * 0x40))
#define IXGBE_SRRCTL(_i) (0x02100 + ((_i) * 4))
/* array of 16 (0x02100-0x0213C) */
#define IXGBE_DCA_RXCTRL(_i) (0x02200 + ((_i) * 4))
/* array of 16 (0x02200-0x0223C) */
#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : (0x0D000 + ((_i - 64) * 0x40)))
#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : (0x0D004 + ((_i - 64) * 0x40)))
#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : (0x0D008 + ((_i - 64) * 0x40)))
#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : (0x0D010 + ((_i - 64) * 0x40)))
#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : (0x0D018 + ((_i - 64) * 0x40)))
#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : (0x0D028 + ((_i - 64) * 0x40)))
/*
* Split and Replication Receive Control Registers
* 00-15 : 0x02100 + n*4
* 16-64 : 0x01014 + n*0x40
* 64-127: 0x0D014 + (n-64)*0x40
*/
#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
(((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
(0x0D014 + ((_i - 64) * 0x40))))
/*
* Rx DCA Control Register:
* 00-15 : 0x02200 + n*4
* 16-64 : 0x0100C + n*0x40
* 64-127: 0x0D00C + (n-64)*0x40
*/
#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
(((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
(0x0D00C + ((_i - 64) * 0x40))))
#define IXGBE_RDRXCTL 0x02F00
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
/* 8 of these 0x03C00 - 0x03C1C */
/* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_RXCTRL 0x03000
#define IXGBE_DROPEN 0x03D04
#define IXGBE_RXPBSIZE_SHIFT 10
@ -110,29 +130,30 @@
/* Receive Registers */
#define IXGBE_RXCSUM 0x05000
#define IXGBE_RFCTL 0x05008
/* Multicast Table Array - 128 entries */
#define IXGBE_MTA(_i) (0x05200 + ((_i) * 4))
/* Multicast Table Array - 128 entries */
#define IXGBE_RAL(_i) (0x05400 + ((_i) * 8)) /* 16 of these (0-15) */
#define IXGBE_RAH(_i) (0x05404 + ((_i) * 8)) /* 16 of these (0-15) */
#define IXGBE_PSRTYPE 0x05480
/* 0x5480-0x54BC Packet split receive type */
#define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : (0x0A200 + ((_i) * 8)))
#define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : (0x0A204 + ((_i) * 8)))
/* Packet split receive type */
#define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : (0x0EA00 + ((_i) * 4)))
/* array of 4096 1-bit vlan filters */
#define IXGBE_VFTA(_i) (0x0A000 + ((_i) * 4))
/* array of 4096 1-bit vlan filters */
/*array of 4096 4-bit vlan vmdq indices */
#define IXGBE_VFTAVIND(_j, _i) (0x0A200 + ((_j) * 0x200) + ((_i) * 4))
/*array of 4096 4-bit vlan vmdq indicies */
#define IXGBE_FCTRL 0x05080
#define IXGBE_VLNCTRL 0x05088
#define IXGBE_MCSTCTRL 0x05090
#define IXGBE_MRQC 0x05818
#define IXGBE_VMD_CTL 0x0581C
#define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIRVP 0x05AC0
#define IXGBE_VMD_CTL 0x0581C
#define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */
#define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */
/* Transmit DMA registers */
#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40))/* 32 of these (0-31)*/
#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/
#define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40))
#define IXGBE_TDLEN(_i) (0x06008 + ((_i) * 0x40))
#define IXGBE_TDH(_i) (0x06010 + ((_i) * 0x40))
@ -141,11 +162,10 @@
#define IXGBE_TDWBAL(_i) (0x06038 + ((_i) * 0x40))
#define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40))
#define IXGBE_DTXCTL 0x07E00
#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4))
/* there are 16 of these (0-15) */
#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
#define IXGBE_TIPG 0x0CB00
#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) *0x04))
/* there are 8 of these */
#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) *0x04)) /* 8 of these */
#define IXGBE_MNGTXMAP 0x0CD10
#define IXGBE_TIPG_FIBER_DEFAULT 3
#define IXGBE_TXPBSIZE_SHIFT 10
@ -173,6 +193,35 @@
#define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */
/* LinkSec (MacSec) Registers */
#define IXGBE_LSECTXCTRL 0x08A04
#define IXGBE_LSECTXSCL 0x08A08 /* SCI Low */
#define IXGBE_LSECTXSCH 0x08A0C /* SCI High */
#define IXGBE_LSECTXSA 0x08A10
#define IXGBE_LSECTXPN0 0x08A14
#define IXGBE_LSECTXPN1 0x08A18
#define IXGBE_LSECTXKEY0(_n) (0x08A1C + (4 * (_n))) /* 4 of these (0-3) */
#define IXGBE_LSECTXKEY1(_n) (0x08A2C + (4 * (_n))) /* 4 of these (0-3) */
#define IXGBE_LSECRXCTRL 0x08F04
#define IXGBE_LSECRXSCL 0x08F08
#define IXGBE_LSECRXSCH 0x08F0C
#define IXGBE_LSECRXSA(_i) (0x08F10 + (4 * (_i))) /* 2 of these (0-1) */
#define IXGBE_LSECRXPN(_i) (0x08F18 + (4 * (_i))) /* 2 of these (0-1) */
#define IXGBE_LSECRXKEY(_n, _m) (0x08F20 + ((0x10 * (_n)) + (4 * (_m))))
/* IpSec Registers */
#define IXGBE_IPSTXIDX 0x08900
#define IXGBE_IPSTXSALT 0x08904
#define IXGBE_IPSTXKEY(_i) (0x08908 + (4 * (_i))) /* 4 of these (0-3) */
#define IXGBE_IPSRXIDX 0x08E00
#define IXGBE_IPSRXIPADDR(_i) (0x08E04 + (4 * (_i))) /* 4 of these (0-3) */
#define IXGBE_IPSRXSPI 0x08E14
#define IXGBE_IPSRXIPIDX 0x08E18
#define IXGBE_IPSRXKEY(_i) (0x08E1C + (4 * (_i))) /* 4 of these (0-3) */
#define IXGBE_IPSRXSALT 0x08E2C
#define IXGBE_IPSRXMOD 0x08E30
/* Stats registers */
#define IXGBE_CRCERRS 0x04000
#define IXGBE_ILLERRC 0x04004
@ -227,7 +276,7 @@
#define IXGBE_XEC 0x04120
#define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4)) /* 16 of these */
#define IXGBE_TQSMR(_i) (0x07300 + ((_i) * 4)) /* 8 of these */
#define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : (0x08600 + ((_i) * 4)))
#define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
@ -385,7 +434,7 @@
#define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* TX Desc writeback RO bit */
#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
#define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */
/* MSCA Bit Masks */
@ -433,6 +482,7 @@
#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
#define IXGBE_TWINAX_DEV 1
#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
@ -449,22 +499,49 @@
#define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */
#define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/
#define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/
#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Abilty Reg */
#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */
#define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */
#define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */
/* MII clause 22/28 definitions */
#define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800
#define IXGBE_MII_SPEED_SELECTION_REG 0x10
#define IXGBE_MII_RESTART 0x200
#define IXGBE_MII_AUTONEG_COMPLETE 0x20
#define IXGBE_MII_AUTONEG_REG 0x0
#define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0
#define IXGBE_MAX_PHY_ADDR 32
/* PHY IDs*/
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
#define QT2022_PHY_ID 0x0043A400
#define ATH_PHY_ID 0x03429050
/* PHY Types */
#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
/* Special PHY Init Routine */
#define IXGBE_PHY_INIT_OFFSET_NL 0x002B
#define IXGBE_CONTROL_MASK_NL 0xF000
#define IXGBE_DATA_MASK_NL 0x0FFF
#define IXGBE_CONTROL_SHIFT_NL 12
#define IXGBE_DELAY_NL 0
#define IXGBE_DATA_NL 1
#define IXGBE_CONTROL_NL 0x000F
#define IXGBE_CONTROL_EOL_NL 0x0FFF
#define IXGBE_CONTROL_SOL_NL 0x0000
/* General purpose Interrupt Enable */
#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */
#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */
#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
#define IXGBE_GPIE_EIAME 0x40000000
#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */
#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */
#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */
#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */
#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
#define IXGBE_GPIE_EIAME 0x40000000
#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
/* Transmit Flow Control status */
#define IXGBE_TFCS_TXOFF 0x00000001
@ -525,7 +602,7 @@
#define IXGBE_PAP_TXPAUSECNT_MASK 0x0000FFFF /* Pause counter mask */
/* RMCS Bit Masks */
#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recylce Mode enable */
#define IXGBE_RMCS_RRM 0x00000002 /* Receive Recycle Mode enable */
/* Receive Arbitration Control: 0 Round Robin, 1 DFP */
#define IXGBE_RMCS_RAC 0x00000004
#define IXGBE_RMCS_DFP IXGBE_RMCS_RAC /* Deficit Fixed Priority ena */
@ -533,12 +610,15 @@
#define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority flow control ena */
#define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */
/* Interrupt register bitmasks */
/* Extended Interrupt Cause Read */
#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */
#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */
#define IXGBE_EICR_MNG 0x00400000 /* Managability Event Interrupt */
#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
#define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */
#define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */
#define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
@ -546,8 +626,9 @@
/* Extended Interrupt Cause Set */
#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
#define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */
@ -556,6 +637,8 @@
/* Extended Interrupt Mask Set */
#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
@ -565,6 +648,8 @@
/* Extended Interrupt Mask Clear */
#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
#define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */
@ -573,12 +658,12 @@
#define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */
#define IXGBE_EIMS_ENABLE_MASK ( \
IXGBE_EIMS_RTX_QUEUE | \
IXGBE_EIMS_LSC | \
IXGBE_EIMS_TCP_TIMER | \
IXGBE_EIMS_OTHER)
IXGBE_EIMS_RTX_QUEUE | \
IXGBE_EIMS_LSC | \
IXGBE_EIMS_TCP_TIMER | \
IXGBE_EIMS_OTHER)
/* Immediate Interrupt RX (A.K.A. Low Latency Interrupt) */
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
#define IXGBE_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */
#define IXGBE_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */
#define IXGBE_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
@ -615,6 +700,7 @@
#define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */
#define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */
#define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */
/* STATUS Bit Masks */
@ -697,6 +783,7 @@
#define IXGBE_LINKS_TL_FAULT 0x00001000
#define IXGBE_LINKS_SIGNAL 0x00000F00
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
#define FIBER_LINK_UP_LIMIT 50
@ -770,6 +857,8 @@
#define IXGBE_CSR0_CONFIG_PTR 0x0D
#define IXGBE_CSR1_CONFIG_PTR 0x0E
#define IXGBE_FW_PTR 0x0F
#define IXGBE_PBANUM0_PTR 0x15
#define IXGBE_PBANUM1_PTR 0x16
/* Legacy EEPROM word offsets */
#define IXGBE_ISCSI_BOOT_CAPS 0x0033
@ -783,7 +872,7 @@
#define IXGBE_EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
#define IXGBE_EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = addr bit-8 */
#define IXGBE_EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Ena latch */
/* EEPROM reset Write Enbale latch */
/* EEPROM reset Write Enable latch */
#define IXGBE_EEPROM_WRDI_OPCODE_SPI 0x04
#define IXGBE_EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status reg */
#define IXGBE_EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status reg */
@ -824,27 +913,20 @@
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
/* PHY Types */
#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
/* Check whether address is multicast. This is little-endian specific check.*/
#define IXGBE_IS_MULTICAST(Address) \
(bool)(((u8 *)(Address))[0] & ((u8)0x01))
(bool)(((u8 *)(Address))[0] & ((u8)0x01))
/* Check whether an address is broadcast. */
#define IXGBE_IS_BROADCAST(Address) \
((((u8 *)(Address))[0] == ((u8)0xff)) && \
(((u8 *)(Address))[1] == ((u8)0xff)))
((((u8 *)(Address))[0] == ((u8)0xff)) && \
(((u8 *)(Address))[1] == ((u8)0xff)))
/* RAH */
#define IXGBE_RAH_VIND_MASK 0x003C0000
#define IXGBE_RAH_VIND_SHIFT 18
#define IXGBE_RAH_AV 0x80000000
/* Filters */
#define IXGBE_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
#define IXGBE_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
/* Header split receive */
#define IXGBE_RFCTL_ISCSI_DIS 0x00000001
#define IXGBE_RFCTL_ISCSI_DWC_MASK 0x0000003E
@ -885,7 +967,7 @@
#define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */
#define IXGBE_FCTRL_PMCF 0x00001000 /* Pass MAC Control Frames */
#define IXGBE_FCTRL_DPF 0x00002000 /* Discard Pause Frame */
/* Receive Priority Flow Control Enbale */
/* Receive Priority Flow Control Enable */
#define IXGBE_FCTRL_RPFCE 0x00004000
#define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */
@ -915,9 +997,8 @@
/* Receive Descriptor bit definitions */
#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */
#define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */
#define IXGBE_RXD_STAT_IXSM 0x04 /* Ignore checksum */
#define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
#define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */
#define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
#define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */
@ -993,18 +1074,18 @@
/* Masks to determine if packets should be dropped due to frame errors */
#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \
IXGBE_RXD_ERR_CE | \
IXGBE_RXD_ERR_LE | \
IXGBE_RXD_ERR_PE | \
IXGBE_RXD_ERR_OSE | \
IXGBE_RXD_ERR_USE)
IXGBE_RXD_ERR_CE | \
IXGBE_RXD_ERR_LE | \
IXGBE_RXD_ERR_PE | \
IXGBE_RXD_ERR_OSE | \
IXGBE_RXD_ERR_USE)
#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \
IXGBE_RXDADV_ERR_CE | \
IXGBE_RXDADV_ERR_LE | \
IXGBE_RXDADV_ERR_PE | \
IXGBE_RXDADV_ERR_OSE | \
IXGBE_RXDADV_ERR_USE)
IXGBE_RXDADV_ERR_CE | \
IXGBE_RXDADV_ERR_LE | \
IXGBE_RXDADV_ERR_PE | \
IXGBE_RXDADV_ERR_OSE | \
IXGBE_RXDADV_ERR_USE)
/* Multicast bit mask */
#define IXGBE_MCSTCTRL_MFE 0x4
@ -1020,23 +1101,33 @@
#define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */
#define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT
#ifndef __le16
/* Little Endian defines */
#define __le8 u8
#define __le16 u16
#define __le32 u32
#define __le64 u64
#endif
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
u64 buffer_addr; /* Address of the descriptor's data buffer */
union {
u32 data;
__le32 data;
struct {
u16 length; /* Data buffer length */
u8 cso; /* Checksum offset */
u8 cmd; /* Descriptor control */
__le16 length; /* Data buffer length */
__le8 cso; /* Checksum offset */
__le8 cmd; /* Descriptor control */
} flags;
} lower;
union {
u32 data;
__le32 data;
struct {
u8 status; /* Descriptor status */
u8 css; /* Checksum start */
u16 vlan;
__le8 status; /* Descriptor status */
__le8 css; /* Checksum start */
__le16 vlan;
} fields;
} upper;
};
@ -1044,61 +1135,64 @@ struct ixgbe_legacy_tx_desc {
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
u64 buffer_addr; /* Address of descriptor's data buf */
u32 cmd_type_len;
u32 olinfo_status;
__le64 buffer_addr; /* Address of descriptor's data buf */
__le32 cmd_type_len;
__le32 olinfo_status;
} read;
struct {
u64 rsvd; /* Reserved */
u32 nxtseq_seed;
u32 status;
__le64 rsvd; /* Reserved */
__le32 nxtseq_seed;
__le32 status;
} wb;
};
/* Receive Descriptor - Legacy */
struct ixgbe_legacy_rx_desc {
u64 buffer_addr; /* Address of the descriptor's data buffer */
u16 length; /* Length of data DMAed into data buffer */
u16 csum; /* Packet checksum */
u8 status; /* Descriptor status */
u8 errors; /* Descriptor Errors */
u16 vlan;
__le64 buffer_addr; /* Address of the descriptor's data buffer */
__le16 length; /* Length of data DMAed into data buffer */
__le16 csum; /* Packet checksum */
__le8 status; /* Descriptor status */
__le8 errors; /* Descriptor Errors */
__le16 vlan;
};
/* Receive Descriptor - Advanced */
union ixgbe_adv_rx_desc {
struct {
u64 pkt_addr; /* Packet buffer address */
u64 hdr_addr; /* Header buffer address */
__le64 pkt_addr; /* Packet buffer address */
__le64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
struct {
u16 pkt_info; /* RSS type, Packet type */
u16 hdr_info; /* Split Header, header len */
union {
__le32 data;
struct {
__le16 pkt_info; /* RSS type, Packet type */
__le16 hdr_info; /* Split Header, header len */
} hs_rss;
} lo_dword;
union {
u32 rss; /* RSS Hash */
__le32 rss; /* RSS Hash */
struct {
u16 ip_id; /* IP id */
u16 csum; /* Packet Checksum */
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
u32 status_error; /* ext status/error */
u16 length; /* Packet length */
u16 vlan; /* VLAN tag */
__le32 status_error; /* ext status/error */
__le16 length; /* Packet length */
__le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
/* Context descriptors */
struct ixgbe_adv_tx_context_desc {
u32 vlan_macip_lens;
u32 seqnum_seed;
u32 type_tucmd_mlhl;
u32 mss_l4len_idx;
__le32 vlan_macip_lens;
__le32 seqnum_seed;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
/* Adv Transmit Descriptor Config Masks */
@ -1108,7 +1202,6 @@ struct ixgbe_adv_tx_context_desc {
#define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */
#define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */
#define IXGBE_ADVTXD_DCMD_RDMA 0x04000000 /* RDMA */
#define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */
#define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
#define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext (1=Adv) */
@ -1118,27 +1211,28 @@ struct ixgbe_adv_tx_context_desc {
#define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present in WB */
#define IXGBE_ADVTXD_STAT_RSV 0x0000000C /* STA Reserved */
#define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
#define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */
#define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */
#define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \
IXGBE_ADVTXD_POPTS_SHIFT)
IXGBE_ADVTXD_POPTS_SHIFT)
#define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \
IXGBE_ADVTXD_POPTS_SHIFT)
#define IXGBE_ADVTXD_POPTS_EOM 0x00000400 /* Enable L bit-RDMA DDP hdr */
#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/
#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */
#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */
#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
IXGBE_ADVTXD_POPTS_SHIFT)
#define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU */
#define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */
#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */
#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
/* Autonegotiation advertised speeds */
typedef u32 ixgbe_autoneg_advertised;
@ -1148,7 +1242,8 @@ typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_100_FULL 0x0008
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
#define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \
IXGBE_LINK_SPEED_10GB_FULL)
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
@ -1164,15 +1259,19 @@ enum ixgbe_mac_type {
enum ixgbe_phy_type {
ixgbe_phy_unknown = 0,
ixgbe_phy_tn,
ixgbe_phy_qt,
ixgbe_phy_xaui
ixgbe_phy_xaui,
ixgbe_phy_nl,
ixgbe_phy_generic
};
enum ixgbe_media_type {
ixgbe_media_type_unknown = 0,
ixgbe_media_type_fiber,
ixgbe_media_type_copper,
ixgbe_media_type_backplane
ixgbe_media_type_backplane,
ixgbe_media_type_virtual
};
/* Flow Control Settings */
@ -1211,24 +1310,20 @@ enum ixgbe_bus_width {
ixgbe_bus_width_unknown = 0,
ixgbe_bus_width_pcie_x1,
ixgbe_bus_width_pcie_x2,
ixgbe_bus_width_pcie_x4,
ixgbe_bus_width_pcie_x8,
ixgbe_bus_width_pcie_x4 = 4,
ixgbe_bus_width_pcie_x8 = 8,
ixgbe_bus_width_32,
ixgbe_bus_width_64,
ixgbe_bus_width_reserved
};
struct ixgbe_eeprom_info {
enum ixgbe_eeprom_type type;
u16 word_size;
u16 address_bits;
};
struct ixgbe_addr_filter_info {
u32 num_mc_addrs;
u32 rar_used_count;
u32 mc_addr_in_rar_count;
u32 mta_in_use;
u32 overflow_promisc;
bool user_set_promisc;
};
/* Bus parameters */
@ -1308,93 +1403,110 @@ struct ixgbe_hw_stats {
u64 qbtc[16];
};
/* forward declaration */
struct ixgbe_hw;
/* iterator type for walking multicast address lists */
typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr,
u32 *vmdq);
/* Function pointer table */
struct ixgbe_functions
{
s32 (*ixgbe_func_init_hw)(struct ixgbe_hw *);
s32 (*ixgbe_func_reset_hw)(struct ixgbe_hw *);
s32 (*ixgbe_func_start_hw)(struct ixgbe_hw *);
s32 (*ixgbe_func_clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*ixgbe_func_get_media_type)(struct ixgbe_hw *);
s32 (*ixgbe_func_get_mac_addr)(struct ixgbe_hw *, u8 *);
u32 (*ixgbe_func_get_num_of_tx_queues)(struct ixgbe_hw *);
u32 (*ixgbe_func_get_num_of_rx_queues)(struct ixgbe_hw *);
s32 (*ixgbe_func_stop_adapter)(struct ixgbe_hw *);
s32 (*ixgbe_func_get_bus_info)(struct ixgbe_hw *);
s32 (*ixgbe_func_read_analog_reg8)(struct ixgbe_hw*, u32, u8*);
s32 (*ixgbe_func_write_analog_reg8)(struct ixgbe_hw*, u32, u8);
/* PHY */
s32 (*ixgbe_func_identify_phy)(struct ixgbe_hw *);
s32 (*ixgbe_func_reset_phy)(struct ixgbe_hw *);
s32 (*ixgbe_func_read_phy_reg)(struct ixgbe_hw *, u32, u32, u16 *);
s32 (*ixgbe_func_write_phy_reg)(struct ixgbe_hw *, u32, u32, u16);
s32 (*ixgbe_func_setup_phy_link)(struct ixgbe_hw *);
s32 (*ixgbe_func_setup_phy_link_speed)(struct ixgbe_hw *,
ixgbe_link_speed,
bool, bool);
s32 (*ixgbe_func_check_phy_link)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
struct ixgbe_eeprom_operations {
s32 (*init_params)(struct ixgbe_hw *);
s32 (*read)(struct ixgbe_hw *, u16, u16 *);
s32 (*write)(struct ixgbe_hw *, u16, u16);
s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
s32 (*update_checksum)(struct ixgbe_hw *);
};
struct ixgbe_mac_operations {
s32 (*init_hw)(struct ixgbe_hw *);
s32 (*reset_hw)(struct ixgbe_hw *);
s32 (*start_hw)(struct ixgbe_hw *);
s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*stop_adapter)(struct ixgbe_hw *);
s32 (*get_bus_info)(struct ixgbe_hw *);
s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*);
s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8);
/* Link */
s32 (*ixgbe_func_setup_link)(struct ixgbe_hw *);
s32 (*ixgbe_func_setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed,
bool, bool);
s32 (*ixgbe_func_check_link)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
s32 (*ixgbe_func_get_link_settings)(struct ixgbe_hw *,
ixgbe_link_speed *,
bool *);
s32 (*setup_link)(struct ixgbe_hw *);
s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *,
bool *);
/* LED */
s32 (*ixgbe_func_led_on)(struct ixgbe_hw *, u32);
s32 (*ixgbe_func_led_off)(struct ixgbe_hw *, u32);
s32 (*ixgbe_func_blink_led_start)(struct ixgbe_hw *, u32);
s32 (*ixgbe_func_blink_led_stop)(struct ixgbe_hw *, u32);
/* EEPROM */
s32 (*ixgbe_func_init_eeprom_params)(struct ixgbe_hw *);
s32 (*ixgbe_func_read_eeprom)(struct ixgbe_hw *, u16, u16 *);
s32 (*ixgbe_func_write_eeprom)(struct ixgbe_hw *, u16, u16);
s32 (*ixgbe_func_validate_eeprom_checksum)(struct ixgbe_hw *, u16 *);
s32 (*ixgbe_func_update_eeprom_checksum)(struct ixgbe_hw *);
s32 (*led_on)(struct ixgbe_hw *, u32);
s32 (*led_off)(struct ixgbe_hw *, u32);
s32 (*blink_led_start)(struct ixgbe_hw *, u32);
s32 (*blink_led_stop)(struct ixgbe_hw *, u32);
/* RAR, Multicast, VLAN */
s32 (*ixgbe_func_set_rar)(struct ixgbe_hw *, u32, u8 *, u32 , u32);
s32 (*ixgbe_func_init_rx_addrs)(struct ixgbe_hw *);
u32 (*ixgbe_func_get_num_rx_addrs)(struct ixgbe_hw *);
s32 (*ixgbe_func_update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32,
u32);
s32 (*ixgbe_func_enable_mc)(struct ixgbe_hw *);
s32 (*ixgbe_func_disable_mc)(struct ixgbe_hw *);
s32 (*ixgbe_func_clear_vfta)(struct ixgbe_hw *);
s32 (*ixgbe_func_set_vfta)(struct ixgbe_hw *, u32, u32, bool);
s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32);
s32 (*init_rx_addrs)(struct ixgbe_hw *);
s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32,
ixgbe_mc_addr_itr);
s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32,
ixgbe_mc_addr_itr);
s32 (*enable_mc)(struct ixgbe_hw *);
s32 (*disable_mc)(struct ixgbe_hw *);
s32 (*clear_vfta)(struct ixgbe_hw *);
s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
/* Flow Control */
s32 (*ixgbe_func_setup_fc)(struct ixgbe_hw *, s32);
s32 (*setup_fc)(struct ixgbe_hw *, s32);
};
struct ixgbe_phy_operations {
s32 (*identify)(struct ixgbe_hw *);
s32 (*reset)(struct ixgbe_hw *);
s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *);
s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16);
s32 (*setup_link)(struct ixgbe_hw *);
s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *);
s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *);
};
struct ixgbe_eeprom_info {
struct ixgbe_eeprom_operations ops;
enum ixgbe_eeprom_type type;
u16 word_size;
u16 address_bits;
};
struct ixgbe_mac_info {
enum ixgbe_mac_type type;
u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
s32 mc_filter_type;
u32 link_attach_type;
u32 link_mode_select;
bool link_settings_loaded;
bool autoneg;
bool autoneg_failed;
struct ixgbe_mac_operations ops;
enum ixgbe_mac_type type;
u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
s32 mc_filter_type;
u32 mcft_size;
u32 vft_size;
u32 num_rar_entries;
u32 max_tx_queues;
u32 max_rx_queues;
u32 link_attach_type;
u32 link_mode_select;
bool link_settings_loaded;
bool autoneg;
bool autoneg_failed;
};
struct ixgbe_phy_info {
struct ixgbe_phy_operations ops;
enum ixgbe_phy_type type;
u32 addr;
u32 id;
u32 revision;
enum ixgbe_media_type media_type;
bool reset_disable;
ixgbe_autoneg_advertised autoneg_advertised;
bool autoneg_wait_to_complete;
};
@ -1402,7 +1514,6 @@ struct ixgbe_phy_info {
struct ixgbe_hw {
u8 *hw_addr;
void *back;
struct ixgbe_functions func;
struct ixgbe_mac_info mac;
struct ixgbe_addr_filter_info addr_ctrl;
struct ixgbe_fc_info fc;
@ -1417,12 +1528,8 @@ struct ixgbe_hw {
bool adapter_stopped;
};
#define ixgbe_func_from_hw_struct(hw, _func) hw->func._func
#define ixgbe_call_func(hw, func, params, error) \
(ixgbe_func_from_hw_struct(hw, func) != NULL) ? \
ixgbe_func_from_hw_struct(hw, func) params: error
(func != NULL) ? func params: error
/* Error Codes */
#define IXGBE_SUCCESS 0
@ -1445,8 +1552,6 @@ struct ixgbe_hw {
#define IXGBE_ERR_PHY_ADDR_INVALID -17
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(_p)
#endif
#endif /* _IXGBE_TYPE_H_ */

380
sys/dev/ixgbe/tcp_lro.c Normal file
View File

@ -0,0 +1,380 @@
/******************************************************************************
Copyright (c) 2007, Myricom Inc.
Copyright (c) 2008, Intel Corporation.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Neither the name of the Myricom Inc, nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
3. Neither the name of the Intel Corporation, nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
***************************************************************************/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/endian.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <machine/bus.h>
#include <machine/in_cksum.h>
#include "tcp_lro.h"
static uint16_t do_csum_data(uint16_t *raw, int len)
{
uint32_t csum;
csum = 0;
while (len > 0) {
csum += *raw;
raw++;
csum += *raw;
raw++;
len -= 4;
}
csum = (csum >> 16) + (csum & 0xffff);
csum = (csum >> 16) + (csum & 0xffff);
return (uint16_t)csum;
}
/*
* Allocate and init the LRO data structures
*/
int
tcp_lro_init(struct lro_ctrl *cntl)
{
struct lro_entry *lro;
int i, error = 0;
SLIST_INIT(&cntl->lro_free);
SLIST_INIT(&cntl->lro_active);
cntl->lro_bad_csum = 0;
cntl->lro_queued = 0;
cntl->lro_flushed = 0;
for (i = 0; i < LRO_ENTRIES; i++) {
lro = (struct lro_entry *) malloc(sizeof (struct lro_entry),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (lro == NULL) {
if (i == 0)
error = ENOMEM;
break;
}
cntl->lro_cnt = i;
SLIST_INSERT_HEAD(&cntl->lro_free, lro, next);
}
return (error);
}
void
tcp_lro_free(struct lro_ctrl *cntl)
{
struct lro_entry *entry;
while (!SLIST_EMPTY(&cntl->lro_free)) {
entry = SLIST_FIRST(&cntl->lro_free);
SLIST_REMOVE_HEAD(&cntl->lro_free, next);
free(entry, M_DEVBUF);
}
}
void
tcp_lro_flush(struct lro_ctrl *cntl, struct lro_entry *lro)
{
struct ifnet *ifp;
struct ip *ip;
struct tcphdr *tcp;
uint32_t *ts_ptr;
uint32_t tcplen, tcp_csum;
//printf("tcp_lro_flush: entry\n");
if (lro->append_cnt) {
/* incorporate the new len into the ip header and
* re-calculate the checksum */
ip = lro->ip;
ip->ip_len = htons(lro->len - ETHER_HDR_LEN);
ip->ip_sum = 0;
ip->ip_sum = 0xffff ^
do_csum_data((uint16_t*)ip,
sizeof (*ip));
lro->m_head->m_pkthdr.csum_flags = CSUM_IP_CHECKED |
CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
lro->m_head->m_pkthdr.csum_data = 0xffff;
lro->m_head->m_pkthdr.len = lro->len;
/* incorporate the latest ack into the tcp header */
tcp = (struct tcphdr *) (ip + 1);
tcp->th_ack = lro->ack_seq;
tcp->th_win = lro->window;
/* incorporate latest timestamp into the tcp header */
if (lro->timestamp) {
ts_ptr = (uint32_t *)(tcp + 1);
ts_ptr[1] = htonl(lro->tsval);
ts_ptr[2] = lro->tsecr;
}
/*
* update checksum in tcp header by re-calculating the
* tcp pseudoheader checksum, and adding it to the checksum
* of the tcp payload data
*/
tcp->th_sum = 0;
tcplen = lro->len - sizeof(*ip) - ETHER_HDR_LEN;
tcp_csum = lro->data_csum;
tcp_csum += in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
htons(tcplen + IPPROTO_TCP));
tcp_csum += do_csum_data((uint16_t*)tcp,
tcp->th_off << 2);
tcp_csum = (tcp_csum & 0xffff) + (tcp_csum >> 16);
tcp_csum = (tcp_csum & 0xffff) + (tcp_csum >> 16);
tcp->th_sum = 0xffff ^ tcp_csum;
}
ifp = cntl->ifp;
(*ifp->if_input)(cntl->ifp, lro->m_head);
cntl->lro_queued += lro->append_cnt + 1;
cntl->lro_flushed++;
lro->m_head = NULL;
lro->timestamp = 0;
lro->append_cnt = 0;
SLIST_INSERT_HEAD(&cntl->lro_free, lro, next);
}
int
tcp_lro_rx(struct lro_ctrl *cntl, struct mbuf *m_head, uint32_t csum)
{
struct ether_header *eh;
struct ip *ip;
struct tcphdr *tcp;
uint32_t *ts_ptr;
struct mbuf *m_nxt, *m_tail;
struct lro_entry *lro;
int hlen, ip_len, tcp_hdr_len, tcp_data_len, tot_len;
int opt_bytes, trim;
uint32_t seq, tmp_csum, device_mtu;
eh = mtod(m_head, struct ether_header *);
if (eh->ether_type != htons(ETHERTYPE_IP))
return 1;
ip = (struct ip *) (eh + 1);
if (ip->ip_p != IPPROTO_TCP)
return 1;
/* ensure there are no options */
if ((ip->ip_hl << 2) != sizeof (*ip))
return -1;
/* .. and the packet is not fragmented */
if (ip->ip_off & htons(IP_MF|IP_OFFMASK))
return -1;
/* verify that the IP header checksum is correct */
tmp_csum = do_csum_data((uint16_t *)ip, sizeof (*ip));
if (__predict_false((tmp_csum ^ 0xffff) != 0)) {
cntl->lro_bad_csum++;
return -1;
}
/* find the TCP header */
tcp = (struct tcphdr *) (ip + 1);
/* Get the TCP checksum if we dont have it */
if (!csum)
csum = tcp->th_sum;
/* ensure no bits set besides ack or psh */
if ((tcp->th_flags & ~(TH_ACK | TH_PUSH)) != 0)
return -1;
/* check for timestamps. Since the only option we handle are
timestamps, we only have to handle the simple case of
aligned timestamps */
opt_bytes = (tcp->th_off << 2) - sizeof (*tcp);
tcp_hdr_len = sizeof (*tcp) + opt_bytes;
ts_ptr = (uint32_t *)(tcp + 1);
if (opt_bytes != 0) {
if (__predict_false(opt_bytes != TCPOLEN_TSTAMP_APPA) ||
(*ts_ptr != ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16|
TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)))
return -1;
}
ip_len = ntohs(ip->ip_len);
tcp_data_len = ip_len - (tcp->th_off << 2) - sizeof (*ip);
/*
* If frame is padded beyond the end of the IP packet,
* then we must trim the extra bytes off the end.
*/
tot_len = m_head->m_pkthdr.len;
trim = tot_len - (ip_len + ETHER_HDR_LEN);
if (trim != 0) {
if (trim < 0) {
/* truncated packet */
return -1;
}
m_adj(m_head, -trim);
tot_len = m_head->m_pkthdr.len;
}
m_nxt = m_head;
m_tail = NULL; /* -Wuninitialized */
while (m_nxt != NULL) {
m_tail = m_nxt;
m_nxt = m_tail->m_next;
}
hlen = ip_len + ETHER_HDR_LEN - tcp_data_len;
seq = ntohl(tcp->th_seq);
SLIST_FOREACH(lro, &cntl->lro_active, next) {
if (lro->source_port == tcp->th_sport &&
lro->dest_port == tcp->th_dport &&
lro->source_ip == ip->ip_src.s_addr &&
lro->dest_ip == ip->ip_dst.s_addr) {
/* Try to append it */
if (__predict_false(seq != lro->next_seq)) {
/* out of order packet */
SLIST_REMOVE(&cntl->lro_active, lro,
lro_entry, next);
tcp_lro_flush(cntl, lro);
return -1;
}
if (opt_bytes) {
uint32_t tsval = ntohl(*(ts_ptr + 1));
/* make sure timestamp values are increasing */
if (__predict_false(lro->tsval > tsval ||
*(ts_ptr + 2) == 0)) {
return -1;
}
lro->tsval = tsval;
lro->tsecr = *(ts_ptr + 2);
}
lro->next_seq += tcp_data_len;
lro->ack_seq = tcp->th_ack;
lro->window = tcp->th_win;
lro->append_cnt++;
if (tcp_data_len == 0) {
m_freem(m_head);
return 0;
}
/* subtract off the checksum of the tcp header
* from the hardware checksum, and add it to the
* stored tcp data checksum. Byteswap the checksum
* if the total length so far is odd
*/
tmp_csum = do_csum_data((uint16_t*)tcp,
tcp_hdr_len);
csum = csum + (tmp_csum ^ 0xffff);
csum = (csum & 0xffff) + (csum >> 16);
csum = (csum & 0xffff) + (csum >> 16);
if (lro->len & 0x1) {
/* Odd number of bytes so far, flip bytes */
csum = ((csum << 8) | (csum >> 8)) & 0xffff;
}
csum = csum + lro->data_csum;
csum = (csum & 0xffff) + (csum >> 16);
csum = (csum & 0xffff) + (csum >> 16);
lro->data_csum = csum;
lro->len += tcp_data_len;
/* adjust mbuf so that m->m_data points to
the first byte of the payload */
m_adj(m_head, hlen);
/* append mbuf chain */
lro->m_tail->m_next = m_head;
/* advance the last pointer */
lro->m_tail = m_tail;
/* flush packet if required */
device_mtu = cntl->ifp->if_mtu;
if (lro->len > (65535 - device_mtu)) {
SLIST_REMOVE(&cntl->lro_active, lro,
lro_entry, next);
tcp_lro_flush(cntl, lro);
}
return 0;
}
}
if (SLIST_EMPTY(&cntl->lro_free))
return -1;
/* start a new chain */
lro = SLIST_FIRST(&cntl->lro_free);
SLIST_REMOVE_HEAD(&cntl->lro_free, next);
SLIST_INSERT_HEAD(&cntl->lro_active, lro, next);
lro->source_port = tcp->th_sport;
lro->dest_port = tcp->th_dport;
lro->source_ip = ip->ip_src.s_addr;
lro->dest_ip = ip->ip_dst.s_addr;
lro->next_seq = seq + tcp_data_len;
lro->mss = tcp_data_len;
lro->ack_seq = tcp->th_ack;
lro->window = tcp->th_win;
/* save the checksum of just the TCP payload by
* subtracting off the checksum of the TCP header from
* the entire hardware checksum
* Since IP header checksum is correct, checksum over
* the IP header is -0. Substracting -0 is unnecessary.
*/
tmp_csum = do_csum_data((uint16_t*)tcp, tcp_hdr_len);
csum = csum + (tmp_csum ^ 0xffff);
csum = (csum & 0xffff) + (csum >> 16);
csum = (csum & 0xffff) + (csum >> 16);
lro->data_csum = csum;
lro->ip = ip;
/* record timestamp if it is present */
if (opt_bytes) {
lro->timestamp = 1;
lro->tsval = ntohl(*(ts_ptr + 1));
lro->tsecr = *(ts_ptr + 2);
}
lro->len = tot_len;
lro->m_head = m_head;
lro->m_tail = m_tail;
return 0;
}

85
sys/dev/ixgbe/tcp_lro.h Normal file
View File

@ -0,0 +1,85 @@
/*******************************************************************************
Copyright (c) 2006, Myricom Inc.
Copyright (c) 2008, Intel Corporation.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Neither the name of the Myricom Inc, nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
2. Neither the name of the Intel Corporation, nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
***************************************************************************/
#ifndef _TCP_LRO_H_
#define _TCP_LRO_H_
struct lro_entry;
struct lro_entry
{
SLIST_ENTRY(lro_entry) next;
struct mbuf *m_head;
struct mbuf *m_tail;
int timestamp;
struct ip *ip;
uint32_t tsval;
uint32_t tsecr;
uint32_t source_ip;
uint32_t dest_ip;
uint32_t next_seq;
uint32_t ack_seq;
uint32_t len;
uint32_t data_csum;
uint16_t window;
uint16_t source_port;
uint16_t dest_port;
uint16_t append_cnt;
uint16_t mss;
};
SLIST_HEAD(lro_head, lro_entry);
struct lro_ctrl {
struct ifnet *ifp;
int lro_queued;
int lro_flushed;
int lro_bad_csum;
int lro_cnt;
struct lro_head lro_active;
struct lro_head lro_free;
};
int tcp_lro_init(struct lro_ctrl *);
void tcp_lro_free(struct lro_ctrl *);
void tcp_lro_flush(struct lro_ctrl *, struct lro_entry *);
int tcp_lro_rx(struct lro_ctrl *, struct mbuf *, uint32_t);
/* Number of LRO entries - these are per rx queue */
#define LRO_ENTRIES 8
#endif /* _TCP_LRO_H_ */

View File

@ -2,7 +2,7 @@
.PATH: ${.CURDIR}/../../dev/ixgbe
KMOD = ixgbe
SRCS = device_if.h bus_if.h pci_if.h
SRCS += ixgbe.c
SRCS += ixgbe.c tcp_lro.c
# Shared source
SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_82598.c
CFLAGS+= -I${.CURDIR}/../../dev/ixgbe