david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[igbvf] Add igbvf driver

Driver for Intel 82576 based virtual functions, based on Intel source
code available at:

    http://sourceforge.net/projects/e1000  (igbvf-1.0.7)

Based on initial port from Eric Keller <ekeller@princeton.edu>.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Alex Williamson 2010-12-15 20:49:32 -07:00 committed by Michael Brown
parent 708c5060b9
commit c080de1a60
11 changed files with 4477 additions and 0 deletions

View File

@ -64,6 +64,7 @@ SRCDIRS += drivers/net
SRCDIRS += drivers/net/e1000
SRCDIRS += drivers/net/e1000e
SRCDIRS += drivers/net/igb
SRCDIRS += drivers/net/igbvf
SRCDIRS += drivers/net/phantom
SRCDIRS += drivers/net/rtl818x
SRCDIRS += drivers/net/ath5k

View File

@ -0,0 +1,375 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
/* Linux PRO/1000 Ethernet Driver main header file */
#ifndef _IGBVF_H_
#define _IGBVF_H_
#include "igbvf_vf.h"
/* Forward declarations */
struct igbvf_info;
struct igbvf_adapter;
/* Interrupt defines */
#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
/* Tx/Rx descriptor defines */
#define IGBVF_DEFAULT_TXD 256
#define IGBVF_MAX_TXD 4096
#define IGBVF_MIN_TXD 80
#define IGBVF_DEFAULT_RXD 256
#define IGBVF_MAX_RXD 4096
#define IGBVF_MIN_RXD 80
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
/* RX descriptor control thresholds.
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
* descriptors available in its onboard memory.
* Setting this to 0 disables RX descriptor prefetch.
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
* available in host memory.
* If PTHRESH is 0, this should also be 0.
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
* descriptors until either it has this many to write back, or the
* ITR timer expires.
*/
#define IGBVF_RX_PTHRESH 16
#define IGBVF_RX_HTHRESH 8
#define IGBVF_RX_WTHRESH 1
#define IGBVF_TX_PTHRESH 8
#define IGBVF_TX_HTHRESH 1
#define IGBVF_TX_WTHRESH 1
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define IGBVF_TX_QUEUE_WAKE 32
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define AUTO_ALL_MODES 0
#define IGBVF_EEPROM_APME 0x0400
#define IGBVF_MNG_VLAN_NONE (-1)
enum igbvf_boards {
board_vf,
};
struct igbvf_queue_stats {
u64 packets;
u64 bytes;
};
/*
* wrappers around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
*/
struct igbvf_buffer {
dma_addr_t dma;
dma_addr_t page_dma;
struct sk_buff *skb;
union {
/* Tx */
struct {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
};
/* Rx */
struct {
struct page *page;
unsigned int page_offset;
};
};
struct page *page;
};
struct igbvf_ring {
struct igbvf_adapter *adapter; /* backlink */
void *desc; /* pointer to ring memory */
dma_addr_t dma; /* phys address of ring */
unsigned int size; /* length of ring in bytes */
unsigned int count; /* number of desc. in ring */
u16 next_to_use;
u16 next_to_clean;
u16 head;
u16 tail;
/* array of buffer information structs */
struct igbvf_buffer *buffer_info;
#if 0
struct napi_struct napi;
char name[IFNAMSIZ + 5];
#endif
u32 eims_value;
u32 itr_val;
u16 itr_register;
int set_itr;
struct sk_buff *rx_skb_top;
struct igbvf_queue_stats stats;
};
/* board specific private data structure */
struct igbvf_adapter {
#if 0
struct timer_list watchdog_timer;
struct timer_list blink_timer;
struct work_struct reset_task;
struct work_struct watchdog_task;
const struct igbvf_info *ei;
struct vlan_group *vlgrp;
u32 bd_number;
u32 rx_buffer_len;
u32 polling_interval;
u16 mng_vlan_id;
u16 link_speed;
u16 link_duplex;
spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
/* track device up/down/testing state */
unsigned long state;
/* Interrupt Throttle Rate */
u32 itr;
u32 itr_setting;
u16 tx_itr;
u16 rx_itr;
/*
* Tx
*/
struct igbvf_ring *tx_ring /* One per active queue */
____cacheline_aligned_in_smp;
unsigned long tx_queue_len;
unsigned int restart_queue;
u32 txd_cmd;
bool detect_tx_hung;
u8 tx_timeout_factor;
unsigned int total_tx_bytes;
unsigned int total_tx_packets;
unsigned int total_rx_bytes;
unsigned int total_rx_packets;
/* Tx stats */
u32 tx_timeout_count;
u32 tx_fifo_head;
u32 tx_head_addr;
u32 tx_fifo_size;
u32 tx_dma_failed;
/*
* Rx
*/
struct igbvf_ring *rx_ring;
/* Rx stats */
u64 hw_csum_err;
u64 hw_csum_good;
u64 rx_hdr_split;
u32 alloc_rx_buff_failed;
u32 rx_dma_failed;
unsigned int rx_ps_hdr_size;
u32 max_frame_size;
u32 min_frame_size;
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
struct net_device_stats net_stats;
spinlock_t stats_lock; /* prevent concurrent stats updates */
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
/* The VF counters don't clear on read so we have to get a base
* count on driver start up and always subtract that base on
* on the first update, thus the flag..
*/
struct e1000_vf_stats stats;
u64 zero_base;
struct igbvf_ring test_tx_ring;
struct igbvf_ring test_rx_ring;
u32 test_icr;
u32 msg_enable;
struct msix_entry *msix_entries;
int int_mode;
u32 eims_enable_mask;
u32 eims_other;
u32 int_counter0;
u32 int_counter1;
u32 eeprom_wol;
u32 wol;
u32 pba;
bool fc_autoneg;
unsigned long led_status;
unsigned int flags;
unsigned long last_reset;
u32 *config_space;
#endif
/* OS defined structs */
struct net_device *netdev;
struct pci_device *pdev;
struct net_device_stats net_stats;
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
u32 min_frame_size;
u32 max_frame_size;
u32 max_hw_frame_size;
#define NUM_TX_DESC 8
#define NUM_RX_DESC 8
struct io_buffer *tx_iobuf[NUM_TX_DESC];
struct io_buffer *rx_iobuf[NUM_RX_DESC];
union e1000_adv_tx_desc *tx_base;
union e1000_adv_rx_desc *rx_base;
uint32_t tx_ring_size;
uint32_t rx_ring_size;
uint32_t tx_head;
uint32_t tx_tail;
uint32_t tx_fill_ctr;
uint32_t rx_curr;
uint32_t ioaddr;
uint32_t irqno;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
uint32_t txd_cmd;
};
struct igbvf_info {
enum e1000_mac_type mac;
unsigned int flags;
u32 pba;
void (*init_ops)(struct e1000_hw *);
s32 (*get_variants)(struct igbvf_adapter *);
};
/* hardware capability, feature, and workaround flags */
#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
#define IGBVF_DESC_UNUSED(R) \
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
(R)->next_to_clean - (R)->next_to_use - 1)
#define IGBVF_RX_DESC_ADV(R, i) \
(&(((union e1000_adv_rx_desc *)((R).desc))[i]))
#define IGBVF_TX_DESC_ADV(R, i) \
(&(((union e1000_adv_tx_desc *)((R).desc))[i]))
#define IGBVF_TX_CTXTDESC_ADV(R, i) \
(&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
enum igbvf_state_t {
__IGBVF_TESTING,
__IGBVF_RESETTING,
__IGBVF_DOWN
};
enum latency_range {
lowest_latency = 0,
low_latency = 1,
bulk_latency = 2,
latency_invalid = 255
};
extern char igbvf_driver_name[];
extern const char igbvf_driver_version[];
extern void igbvf_check_options(struct igbvf_adapter *adapter);
extern void igbvf_set_ethtool_ops(struct net_device *netdev);
#ifdef ETHTOOL_OPS_COMPAT
extern int ethtool_ioctl(struct ifreq *ifr);
#endif
extern int igbvf_up(struct igbvf_adapter *adapter);
extern void igbvf_down(struct igbvf_adapter *adapter);
extern void igbvf_reinit_locked(struct igbvf_adapter *adapter);
extern void igbvf_reset(struct igbvf_adapter *adapter);
extern int igbvf_setup_rx_resources(struct igbvf_adapter *adapter);
extern int igbvf_setup_tx_resources(struct igbvf_adapter *adapter);
extern void igbvf_free_rx_resources(struct igbvf_adapter *adapter);
extern void igbvf_free_tx_resources(struct igbvf_adapter *adapter);
extern void igbvf_update_stats(struct igbvf_adapter *adapter);
extern void igbvf_set_interrupt_capability(struct igbvf_adapter *adapter);
extern void igbvf_reset_interrupt_capability(struct igbvf_adapter *adapter);
extern unsigned int copybreak;
static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
{
return readl(hw->hw_addr + reg);
}
static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
{
writel(val, hw->hw_addr + reg);
}
#define er32(reg) E1000_READ_REG(hw, E1000_##reg)
#define ew32(reg,val) E1000_WRITE_REG(hw, E1000_##reg, (val))
#define e1e_flush() er32(STATUS)
#endif /* _IGBVF_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,955 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 2009 Intel Corporation.
Copyright(c) 2010 Eric Keller <ekeller@princeton.edu>
Copyright(c) 2010 Red Hat Inc.
Alex Williamson <alex.williamson@redhat.com>
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#include "igbvf.h"
/**
* igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
*
* @v adapter e1000 private structure
*
* @ret rc Returns 0 on success, negative on failure
**/
int igbvf_setup_tx_resources ( struct igbvf_adapter *adapter )
{
DBG ( "igbvf_setup_tx_resources\n" );
/* Allocate transmit descriptor ring memory.
It must not cross a 64K boundary because of hardware errata #23
so we use malloc_dma() requesting a 128 byte block that is
128 byte aligned. This should guarantee that the memory
allocated will not cross a 64K boundary, because 128 is an
even multiple of 65536 ( 65536 / 128 == 512 ), so all possible
allocations of 128 bytes on a 128 byte boundary will not
cross 64K bytes.
*/
adapter->tx_base =
malloc_dma ( adapter->tx_ring_size, adapter->tx_ring_size );
if ( ! adapter->tx_base ) {
return -ENOMEM;
}
memset ( adapter->tx_base, 0, adapter->tx_ring_size );
DBG ( "adapter->tx_base = %#08lx\n", virt_to_bus ( adapter->tx_base ) );
return 0;
}
/**
* igbvf_free_tx_resources - Free Tx Resources per Queue
* @adapter: board private structure
*
* Free all transmit software resources
**/
void igbvf_free_tx_resources ( struct igbvf_adapter *adapter )
{
DBG ( "igbvf_free_tx_resources\n" );
free_dma ( adapter->tx_base, adapter->tx_ring_size );
}
/**
* igbvf_free_rx_resources - Free Rx Resources
* @adapter: board private structure
*
* Free all receive software resources
**/
void igbvf_free_rx_resources ( struct igbvf_adapter *adapter )
{
int i;
DBG ( "igbvf_free_rx_resources\n" );
free_dma ( adapter->rx_base, adapter->rx_ring_size );
for ( i = 0; i < NUM_RX_DESC; i++ ) {
free_iob ( adapter->rx_iobuf[i] );
}
}
/**
* igbvf_refill_rx_ring - allocate Rx io_buffers
*
* @v adapter e1000 private structure
*
* @ret rc Returns 0 on success, negative on failure
**/
static int igbvf_refill_rx_ring ( struct igbvf_adapter *adapter )
{
int i, rx_curr;
int rc = 0;
union e1000_adv_rx_desc *rx_curr_desc;
struct e1000_hw *hw = &adapter->hw;
struct io_buffer *iob;
DBGP ("igbvf_refill_rx_ring\n");
for ( i = 0; i < NUM_RX_DESC; i++ ) {
rx_curr = ( ( adapter->rx_curr + i ) % NUM_RX_DESC );
rx_curr_desc = adapter->rx_base + rx_curr;
if ( rx_curr_desc->wb.upper.status_error & E1000_RXD_STAT_DD )
continue;
if ( adapter->rx_iobuf[rx_curr] != NULL )
continue;
DBG2 ( "Refilling rx desc %d\n", rx_curr );
iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
adapter->rx_iobuf[rx_curr] = iob;
rx_curr_desc->wb.upper.status_error = 0;
if ( ! iob ) {
DBG ( "alloc_iob failed\n" );
rc = -ENOMEM;
break;
} else {
rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
rx_curr_desc->read.hdr_addr = 0;
ew32 ( RDT(0), rx_curr );
}
}
return rc;
}
/**
* igbvf_irq_disable - Mask off interrupt generation on the NIC
* @adapter: board private structure
**/
static void igbvf_irq_disable ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
ew32 ( EIMC, ~0 );
}
/**
* igbvf_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
**/
static void igbvf_irq_enable ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
ew32 ( EIAC, IMS_ENABLE_MASK );
ew32 ( EIAM, IMS_ENABLE_MASK );
ew32 ( EIMS, IMS_ENABLE_MASK );
}
/**
* igbvf_irq - enable or Disable interrupts
*
* @v adapter e1000 adapter
* @v action requested interrupt action
**/
static void igbvf_irq ( struct net_device *netdev, int enable )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
DBG ( "igbvf_irq\n" );
if ( enable ) {
igbvf_irq_enable ( adapter );
} else {
igbvf_irq_disable ( adapter );
}
}
/**
* igbvf_process_tx_packets - process transmitted packets
*
* @v netdev network interface device structure
**/
static void igbvf_process_tx_packets ( struct net_device *netdev )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
uint32_t i;
uint32_t tx_status;
union e1000_adv_tx_desc *tx_curr_desc;
/* Check status of transmitted packets
*/
DBGP ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head,
adapter->tx_tail );
while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
( i * sizeof ( *adapter->tx_base ) );
tx_status = tx_curr_desc->wb.status;
DBG ( " tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
DBG ( " tx_status = %#08x\n", tx_status );
/* if the packet at tx_head is not owned by hardware it is for us */
if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
break;
DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
adapter->tx_head, adapter->tx_tail, tx_status );
netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
DBG ( "Success transmitting packet, tx_status: %#08x\n",
tx_status );
/* Decrement count of used descriptors, clear this descriptor
*/
adapter->tx_fill_ctr--;
memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
}
}
/**
* igbvf_process_rx_packets - process received packets
*
* @v netdev network interface device structure
**/
static void igbvf_process_rx_packets ( struct net_device *netdev )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
struct e1000_hw *hw = &adapter->hw;
uint32_t i;
uint32_t rx_status;
uint32_t rx_len;
uint32_t rx_err;
union e1000_adv_rx_desc *rx_curr_desc;
DBGP ( "igbvf_process_rx_packets\n" );
/* Process received packets
*/
while ( 1 ) {
i = adapter->rx_curr;
rx_curr_desc = ( void * ) ( adapter->rx_base ) +
( i * sizeof ( *adapter->rx_base ) );
rx_status = rx_curr_desc->wb.upper.status_error;
DBG2 ( "Before DD Check RX_status: %#08x, rx_curr: %d\n",
rx_status, i );
if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
break;
if ( adapter->rx_iobuf[i] == NULL )
break;
DBG ( "E1000_RCTL = %#08x\n", er32 (RCTL) );
rx_len = rx_curr_desc->wb.upper.length;
DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n",
i, rx_status, rx_len );
rx_err = rx_status;
iob_put ( adapter->rx_iobuf[i], rx_len );
if ( rx_err & E1000_RXDEXT_ERR_FRAME_ERR_MASK ) {
netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
DBG ( "igbvf_process_rx_packets: Corrupted packet received!"
" rx_err: %#08x\n", rx_err );
} else {
/* Add this packet to the receive queue. */
netdev_rx ( netdev, adapter->rx_iobuf[i] );
}
adapter->rx_iobuf[i] = NULL;
memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );
adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
}
}
/**
* igbvf_poll - Poll for received packets
*
* @v netdev Network device
*/
static void igbvf_poll ( struct net_device *netdev )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
uint32_t rx_status;
union e1000_adv_rx_desc *rx_curr_desc;
DBGP ( "igbvf_poll\n" );
rx_curr_desc = ( void * ) ( adapter->rx_base ) +
( adapter->rx_curr * sizeof ( *adapter->rx_base ) );
rx_status = rx_curr_desc->wb.upper.status_error;
if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
return;
igbvf_process_tx_packets ( netdev );
igbvf_process_rx_packets ( netdev );
igbvf_refill_rx_ring ( adapter );
}
/**
* igbvf_config_collision_dist_generic - Configure collision distance
* @hw: pointer to the HW structure
*
* Configures the collision distance to the default value and is used
* during link setup. Currently no func pointer exists and all
* implementations are handled in the generic version of this function.
**/
void igbvf_config_collision_dist ( struct e1000_hw *hw )
{
u32 tctl;
DBG ("igbvf_config_collision_dist");
tctl = er32 (TCTL);
tctl &= ~E1000_TCTL_COLD;
tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
ew32 (TCTL, tctl);
e1e_flush();
}
/**
* igbvf_configure_tx - Configure Transmit Unit after Reset
* @adapter: board private structure
*
* Configure the Tx unit of the MAC after a reset.
**/
static void igbvf_configure_tx ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
u32 tctl, txdctl;
DBG ( "igbvf_configure_tx\n" );
/* disable transmits while setting up the descriptors */
tctl = er32 ( TCTL );
ew32 ( TCTL, tctl & ~E1000_TCTL_EN );
e1e_flush();
mdelay (10);
ew32 ( TDBAH(0), 0 );
ew32 ( TDBAL(0), virt_to_bus ( adapter->tx_base ) );
ew32 ( TDLEN(0), adapter->tx_ring_size );
DBG ( "E1000_TDBAL(0): %#08x\n", er32 ( TDBAL(0) ) );
DBG ( "E1000_TDLEN(0): %d\n", er32 ( TDLEN(0) ) );
/* Setup the HW Tx Head and Tail descriptor pointers */
ew32 ( TDH(0), 0 );
ew32 ( TDT(0), 0 );
adapter->tx_head = 0;
adapter->tx_tail = 0;
adapter->tx_fill_ctr = 0;
txdctl = er32(TXDCTL(0));
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
ew32 ( TXDCTL(0), txdctl );
txdctl = er32 ( TXDCTL(0) );
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
ew32 ( TXDCTL(0), txdctl );
/* Setup Transmit Descriptor Settings for eop descriptor */
adapter->txd_cmd = E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_IFCS;
/* Advanced descriptor */
adapter->txd_cmd |= E1000_ADVTXD_DCMD_DEXT;
/* (not part of cmd, but in same 32 bit word...) */
adapter->txd_cmd |= E1000_ADVTXD_DTYP_DATA;
/* enable Report Status bit */
adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
/* Program the Transmit Control Register */
tctl &= ~E1000_TCTL_CT;
tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
igbvf_config_collision_dist ( hw );
/* Enable transmits */
tctl |= E1000_TCTL_EN;
ew32(TCTL, tctl);
e1e_flush();
}
/* igbvf_reset - bring the hardware into a known good state
*
* This function boots the hardware and enables some settings that
* require a configuration cycle of the hardware - those cannot be
* set/changed during runtime. After reset the device needs to be
* properly configured for Rx, Tx etc.
*/
void igbvf_reset ( struct igbvf_adapter *adapter )
{
struct e1000_mac_info *mac = &adapter->hw.mac;
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
/* Allow time for pending master requests to run */
if ( mac->ops.reset_hw(hw) )
DBG ("PF still resetting\n");
mac->ops.init_hw ( hw );
if ( is_valid_ether_addr(adapter->hw.mac.addr) ) {
memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
}
}
extern void igbvf_init_function_pointers_vf(struct e1000_hw *hw);
/**
* igbvf_sw_init - Initialize general software structures (struct igbvf_adapter)
* @adapter: board private structure to initialize
*
* igbvf_sw_init initializes the Adapter private data structure.
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
static int __devinit igbvf_sw_init ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
struct pci_device *pdev = adapter->pdev;
int rc;
/* PCI config space info */
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
pci_read_config_byte ( pdev, PCI_REVISION_ID, &hw->revision_id );
pci_read_config_word ( pdev, PCI_COMMAND, &hw->bus.pci_cmd_word );
adapter->max_frame_size = MAXIMUM_ETHERNET_VLAN_SIZE + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
/* Set various function pointers */
igbvf_init_function_pointers_vf ( &adapter->hw );
rc = adapter->hw.mac.ops.init_params ( &adapter->hw );
if (rc) {
DBG ("hw.mac.ops.init_params(&adapter->hw) Failure\n");
return rc;
}
rc = adapter->hw.mbx.ops.init_params ( &adapter->hw );
if (rc) {
DBG ("hw.mbx.ops.init_params(&adapter->hw) Failure\n");
return rc;
}
/* Explicitly disable IRQ since the NIC can be in any state. */
igbvf_irq_disable ( adapter );
return 0;
}
/**
* igbvf_setup_srrctl - configure the receive control registers
* @adapter: Board private structure
**/
static void igbvf_setup_srrctl ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
u32 srrctl = 0;
DBG ( "igbvf_setup_srrctl\n" );
srrctl &= ~(E1000_SRRCTL_DESCTYPE_MASK |
E1000_SRRCTL_BSIZEHDR_MASK |
E1000_SRRCTL_BSIZEPKT_MASK);
/* Enable queue drop to avoid head of line blocking */
srrctl |= E1000_SRRCTL_DROP_EN;
/* Setup buffer sizes */
srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
ew32 ( SRRCTL(0), srrctl );
}
/**
* igbvf_configure_rx - Configure 8254x Receive Unit after Reset
* @adapter: board private structure
*
* Configure the Rx unit of the MAC after a reset.
**/
static void igbvf_configure_rx ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
u32 rxdctl;
DBG ( "igbvf_configure_rx\n" );
/* disable receives */
rxdctl = er32 ( RXDCTL(0) );
ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
msleep ( 10 );
/*
* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring
*/
ew32 ( RDBAL(0), virt_to_bus (adapter->rx_base) );
ew32 ( RDBAH(0), 0 );
ew32 ( RDLEN(0), adapter->rx_ring_size );
adapter->rx_curr = 0;
ew32 ( RDH(0), 0 );
ew32 ( RDT(0), 0 );
rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
rxdctl &= 0xFFF00000;
rxdctl |= IGBVF_RX_PTHRESH;
rxdctl |= IGBVF_RX_HTHRESH << 8;
rxdctl |= IGBVF_RX_WTHRESH << 16;
igbvf_rlpml_set_vf ( hw, adapter->max_frame_size );
/* enable receives */
ew32 ( RXDCTL(0), rxdctl );
ew32 ( RDT(0), NUM_RX_DESC );
}
/**
* igbvf_setup_rx_resources - allocate Rx resources (Descriptors)
*
* @v adapter e1000 private structure
**/
int igbvf_setup_rx_resources ( struct igbvf_adapter *adapter )
{
int i;
union e1000_adv_rx_desc *rx_curr_desc;
struct io_buffer *iob;
DBG ( "igbvf_setup_rx_resources\n" );
/* Allocate receive descriptor ring memory.
It must not cross a 64K boundary because of hardware errata
*/
adapter->rx_base =
malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
if ( ! adapter->rx_base ) {
return -ENOMEM;
}
memset ( adapter->rx_base, 0, adapter->rx_ring_size );
for ( i = 0; i < NUM_RX_DESC; i++ ) {
rx_curr_desc = adapter->rx_base + i;
iob = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
adapter->rx_iobuf[i] = iob;
rx_curr_desc->wb.upper.status_error = 0;
if ( ! iob ) {
DBG ( "alloc_iob failed\n" );
return -ENOMEM;
} else {
rx_curr_desc->read.pkt_addr = virt_to_bus ( iob->data );
rx_curr_desc->read.hdr_addr = 0;
}
}
return 0;
}
/**
* igbvf_open - Called when a network interface is made active
* @netdev: network interface device structure
*
* Returns 0 on success, negative value on failure
*
* The open entry point is called when a network interface is made
* active by the system (IFF_UP). At this point all resources needed
* for transmit and receive operations are allocated, the interrupt
* handler is registered with the OS, the watchdog timer is started,
* and the stack is notified that the interface is ready.
**/
static int igbvf_open ( struct net_device *netdev )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
int err;
DBG ("igbvf_open\n");
/* allocate transmit descriptors */
err = igbvf_setup_tx_resources ( adapter );
if (err) {
DBG ( "Error setting up TX resources!\n" );
goto err_setup_tx;
}
igbvf_configure_tx ( adapter );
igbvf_setup_srrctl( adapter );
err = igbvf_setup_rx_resources( adapter );
if (err) {
DBG ( "Error setting up RX resources!\n" );
goto err_setup_rx;
}
igbvf_configure_rx ( adapter );
return 0;
err_setup_rx:
DBG ( "err_setup_rx\n" );
igbvf_free_tx_resources ( adapter );
return err;
err_setup_tx:
DBG ( "err_setup_tx\n" );
igbvf_reset ( adapter );
return err;
}
/**
* igbvf_close - Disables a network interface
* @netdev: network interface device structure
*
* Returns 0, this is not allowed to fail
*
* The close entry point is called when an interface is de-activated
* by the OS. The hardware is still under the drivers control, but
* needs to be disabled. A global MAC reset is issued to stop the
* hardware, and all transmit and receive resources are freed.
**/
static void igbvf_close ( struct net_device *netdev )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
struct e1000_hw *hw = &adapter->hw;
uint32_t rxdctl;
uint32_t icr;
DBG ( "igbvf_close\n" );
icr = er32(EICR);
igbvf_irq_disable ( adapter );
/* disable receives */
rxdctl = er32 ( RXDCTL(0) );
ew32 ( RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE );
mdelay ( 10 );
igbvf_reset ( adapter );
igbvf_free_tx_resources( adapter );
igbvf_free_rx_resources( adapter );
}
/**
* igbvf_transmit - Transmit a packet
*
* @v netdev Network device
* @v iobuf I/O buffer
*
* @ret rc Returns 0 on success, negative on failure
*/
static int igbvf_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
{
struct igbvf_adapter *adapter = netdev_priv ( netdev );
struct e1000_hw *hw = &adapter->hw;
uint32_t tx_curr = adapter->tx_tail;
union e1000_adv_tx_desc *tx_curr_desc;
DBGP ("igbvf_transmit\n");
if ( adapter->tx_fill_ctr == NUM_TX_DESC ) {
DBG ("TX overflow\n");
return -ENOBUFS;
}
/* Save pointer to iobuf we have been given to transmit,
netdev_tx_complete() will need it later
*/
adapter->tx_iobuf[tx_curr] = iobuf;
tx_curr_desc = ( void * ) ( adapter->tx_base ) +
( tx_curr * sizeof ( *adapter->tx_base ) );
DBG ( "tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
DBG ( "tx_curr_desc + 16 = %#08lx\n", virt_to_bus ( tx_curr_desc ) + 16 );
DBG ( "iobuf->data = %#08lx\n", virt_to_bus ( iobuf->data ) );
/* Add the packet to TX ring
*/
tx_curr_desc->read.buffer_addr = virt_to_bus ( iobuf->data );
tx_curr_desc->read.cmd_type_len = adapter->txd_cmd |(iob_len ( iobuf )) ;
// minus hdr_len ????
tx_curr_desc->read.olinfo_status = ((iob_len ( iobuf )) << E1000_ADVTXD_PAYLEN_SHIFT);
DBG ( "TX fill: %d tx_curr: %d addr: %#08lx len: %zd\n", adapter->tx_fill_ctr,
tx_curr, virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
/* Point to next free descriptor */
adapter->tx_tail = ( adapter->tx_tail + 1 ) % NUM_TX_DESC;
adapter->tx_fill_ctr++;
/* Write new tail to NIC, making packet available for transmit
*/
ew32 ( TDT(0), adapter->tx_tail );
e1e_flush ();
return 0;
}
/** igbvf net device operations */
static struct net_device_operations igbvf_operations = {
.open = igbvf_open,
.close = igbvf_close,
.transmit = igbvf_transmit,
.poll = igbvf_poll,
.irq = igbvf_irq,
};
/**
* igbvf_get_hw_control - get control of the h/w from f/w
* @adapter: address of board private structure
*
* igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit.
* For ASF and Pass Through versions of f/w this means that
* the driver is loaded.
*
**/
void igbvf_get_hw_control ( struct igbvf_adapter *adapter )
{
struct e1000_hw *hw = &adapter->hw;
u32 ctrl_ext;
/* Let firmware know the driver has taken over */
ctrl_ext = er32 ( CTRL_EXT );
ew32 ( CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD );
}
/**
* igbvf_probe - Device Initialization Routine
* @pdev: PCI device information struct
* @ent: entry in igbvf_pci_tbl
*
* Returns 0 on success, negative on failure
*
* igbvf_probe initializes an adapter identified by a pci_dev structure.
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
int igbvf_probe ( struct pci_device *pdev,
const struct pci_device_id *ent __unused )
{
int err;
struct net_device *netdev;
struct igbvf_adapter *adapter;
unsigned long mmio_start, mmio_len;
struct e1000_hw *hw;
DBG ( "igbvf_probe\n" );
err = -ENOMEM;
/* Allocate net device ( also allocates memory for netdev->priv
and makes netdev-priv point to it ) */
netdev = alloc_etherdev ( sizeof ( struct igbvf_adapter ) );
if ( ! netdev )
goto err_alloc_etherdev;
/* Associate igbvf-specific network operations operations with
* generic network device layer */
netdev_init ( netdev, &igbvf_operations );
/* Associate this network device with given PCI device */
pci_set_drvdata ( pdev, netdev );
netdev->dev = &pdev->dev;
/* Initialize driver private storage */
adapter = netdev_priv ( netdev );
memset ( adapter, 0, ( sizeof ( *adapter ) ) );
adapter->pdev = pdev;
adapter->ioaddr = pdev->ioaddr;
adapter->hw.io_base = pdev->ioaddr;
hw = &adapter->hw;
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
adapter->irqno = pdev->irq;
adapter->netdev = netdev;
adapter->hw.back = adapter;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
adapter->tx_ring_size = sizeof ( *adapter->tx_base ) * NUM_TX_DESC;
adapter->rx_ring_size = sizeof ( *adapter->rx_base ) * NUM_RX_DESC;
/* Fix up PCI device */
adjust_pci_device ( pdev );
err = -EIO;
mmio_start = pci_bar_start ( pdev, PCI_BASE_ADDRESS_0 );
mmio_len = pci_bar_size ( pdev, PCI_BASE_ADDRESS_0 );
DBG ( "mmio_start: %#08lx\n", mmio_start );
DBG ( "mmio_len: %#08lx\n", mmio_len );
adapter->hw.hw_addr = ioremap ( mmio_start, mmio_len );
DBG ( "adapter->hw.hw_addr: %p\n", adapter->hw.hw_addr );
if ( ! adapter->hw.hw_addr ) {
DBG ( "err_ioremap\n" );
goto err_ioremap;
}
/* setup adapter struct */
err = igbvf_sw_init ( adapter );
if (err) {
DBG ( "err_sw_init\n" );
goto err_sw_init;
}
/* reset the controller to put the device in a known good state */
err = hw->mac.ops.reset_hw ( hw );
if ( err ) {
DBG ("PF still in reset state, assigning new address\n");
netdev->hw_addr[0] = 0x21;
netdev->hw_addr[1] = 0x21;
netdev->hw_addr[2] = 0x21;
netdev->hw_addr[3] = 0x21;
netdev->hw_addr[4] = 0x21;
netdev->hw_addr[5] = 0x21;
netdev->hw_addr[6] = 0x21;
} else {
err = hw->mac.ops.read_mac_addr(hw);
if (err) {
DBG ("Error reading MAC address\n");
goto err_hw_init;
}
}
memcpy ( netdev->hw_addr, adapter->hw.mac.addr, ETH_ALEN );
if ( ! is_valid_ether_addr( netdev->hw_addr ) ) {
DBG ("Invalid MAC Address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
netdev->hw_addr[0], netdev->hw_addr[1],
netdev->hw_addr[2], netdev->hw_addr[3],
netdev->hw_addr[4], netdev->hw_addr[5]);
err = -EIO;
goto err_hw_init;
}
/* reset the hardware with the new settings */
igbvf_reset ( adapter );
/* let the f/w know that the h/w is now under the control of the
* driver. */
igbvf_get_hw_control ( adapter );
/* Mark as link up; we don't yet handle link state */
netdev_link_up ( netdev );
if ( ( err = register_netdev ( netdev ) ) != 0) {
DBG ( "err_register\n" );
goto err_register;
}
DBG ("igbvf_probe_succeeded\n");
return 0;
err_register:
err_hw_init:
err_sw_init:
iounmap ( adapter->hw.hw_addr );
err_ioremap:
netdev_put ( netdev );
err_alloc_etherdev:
return err;
}
/**
* igbvf_remove - Device Removal Routine
* @pdev: PCI device information struct
*
* igbvf_remove is called by the PCI subsystem to alert the driver
* that it should release a PCI device. The could be caused by a
* Hot-Plug event, or because the driver is going to be removed from
* memory.
**/
void igbvf_remove ( struct pci_device *pdev )
{
struct net_device *netdev = pci_get_drvdata ( pdev );
struct igbvf_adapter *adapter = netdev_priv ( netdev );
DBG ( "igbvf_remove\n" );
if ( adapter->hw.flash_address )
iounmap ( adapter->hw.flash_address );
if ( adapter->hw.hw_addr )
iounmap ( adapter->hw.hw_addr );
unregister_netdev ( netdev );
igbvf_reset ( adapter );
netdev_nullify ( netdev );
netdev_put ( netdev );
}
static struct pci_device_id igbvf_pci_tbl[] = {
PCI_ROM(0x8086, 0x10CA, "igbvf", "E1000_DEV_ID_82576_VF", 0)
};
struct pci_driver igbvf_driver __pci_driver = {
.ids = igbvf_pci_tbl,
.id_count = (sizeof(igbvf_pci_tbl) / sizeof(igbvf_pci_tbl[0])),
.probe = igbvf_probe,
.remove = igbvf_remove,
};

View File

@ -0,0 +1,404 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#include "igbvf_mbx.h"
/**
* igbvf_poll_for_msg - Wait for message notification
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message notification
**/
static s32 igbvf_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
DEBUGFUNC("igbvf_poll_for_msg");
if (!countdown || !mbx->ops.check_for_msg)
goto out;
while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
countdown--;
if (!countdown)
break;
usec_delay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* igbvf_poll_for_ack - Wait for message acknowledgement
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message acknowledgement
**/
static s32 igbvf_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
DEBUGFUNC("igbvf_poll_for_ack");
if (!countdown || !mbx->ops.check_for_ack)
goto out;
while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
countdown--;
if (!countdown)
break;
usec_delay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* igbvf_read_posted_mbx - Wait for message notification and receive message
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully received a message notification and
* copied it into the receive buffer.
**/
static s32 igbvf_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_read_posted_mbx");
if (!mbx->ops.read)
goto out;
ret_val = igbvf_poll_for_msg(hw, mbx_id);
/* if ack received read message, otherwise we timed out */
if (!ret_val)
ret_val = mbx->ops.read(hw, msg, size, mbx_id);
out:
return ret_val;
}
/**
* igbvf_write_posted_mbx - Write a message to the mailbox, wait for ack
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully copied message into the buffer and
* received an ack to that message within delay * timeout period
**/
static s32 igbvf_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_write_posted_mbx");
/* exit if either we can't write or there isn't a defined timeout */
if (!mbx->ops.write || !mbx->timeout)
goto out;
/* send msg */
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
/* if msg sent wait until we receive an ack */
if (!ret_val)
ret_val = igbvf_poll_for_ack(hw, mbx_id);
out:
return ret_val;
}
/**
* igbvf_init_mbx_ops_generic - Initialize NVM function pointers
* @hw: pointer to the HW structure
*
* Setups up the function pointers to no-op functions
**/
void igbvf_init_mbx_ops_generic(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
mbx->ops.read_posted = igbvf_read_posted_mbx;
mbx->ops.write_posted = igbvf_write_posted_mbx;
}
/**
* igbvf_read_v2p_mailbox - read v2p mailbox
* @hw: pointer to the HW structure
*
* This function is used to read the v2p mailbox without losing the read to
* clear status bits.
**/
static u32 igbvf_read_v2p_mailbox(struct e1000_hw *hw)
{
u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0));
v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
return v2p_mailbox;
}
/**
* igbvf_check_for_bit_vf - Determine if a status bit was set
* @hw: pointer to the HW structure
* @mask: bitmask for bits to be tested and cleared
*
* This function is used to check for the read to clear bits within
* the V2P mailbox.
**/
static s32 igbvf_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
{
u32 v2p_mailbox = igbvf_read_v2p_mailbox(hw);
s32 ret_val = -E1000_ERR_MBX;
if (v2p_mailbox & mask)
ret_val = E1000_SUCCESS;
hw->dev_spec.vf.v2p_mailbox &= ~mask;
return ret_val;
}
/**
* igbvf_check_for_msg_vf - checks to see if the PF has sent mail
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
**/
static s32 igbvf_check_for_msg_vf(struct e1000_hw *hw, u16 mbx_id __unused)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_check_for_msg_vf");
if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.reqs++;
}
return ret_val;
}
/**
* igbvf_check_for_ack_vf - checks to see if the PF has ACK'd
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
**/
static s32 igbvf_check_for_ack_vf(struct e1000_hw *hw, u16 mbx_id __unused)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_check_for_ack_vf");
if (!igbvf_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.acks++;
}
return ret_val;
}
/**
* igbvf_check_for_rst_vf - checks to see if the PF has reset
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns true if the PF has set the reset done bit or else false
**/
static s32 igbvf_check_for_rst_vf(struct e1000_hw *hw, u16 mbx_id __unused)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_check_for_rst_vf");
if (!igbvf_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
E1000_V2PMAILBOX_RSTI))) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.rsts++;
}
return ret_val;
}
/**
* igbvf_obtain_mbx_lock_vf - obtain mailbox lock
* @hw: pointer to the HW structure
*
* return SUCCESS if we obtained the mailbox lock
**/
static s32 igbvf_obtain_mbx_lock_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
DEBUGFUNC("igbvf_obtain_mbx_lock_vf");
/* Take ownership of the buffer */
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
/* reserve mailbox for vf use */
if (igbvf_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
ret_val = E1000_SUCCESS;
return ret_val;
}
/**
* igbvf_write_mbx_vf - Write a message to the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to write
*
* returns SUCCESS if it successfully copied message into the buffer
**/
static s32 igbvf_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
u16 mbx_id __unused)
{
s32 ret_val;
u16 i;
DEBUGFUNC("igbvf_write_mbx_vf");
/* lock the mailbox to prevent pf/vf race condition */
ret_val = igbvf_obtain_mbx_lock_vf(hw);
if (ret_val)
goto out_no_write;
/* flush msg and acks as we are overwriting the message buffer */
igbvf_check_for_msg_vf(hw, 0);
igbvf_check_for_ack_vf(hw, 0);
/* copy the caller specified message to the mailbox memory buffer */
for (i = 0; i < size; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]);
/* update stats */
hw->mbx.stats.msgs_tx++;
/* Drop VFU and interrupt the PF to tell it a message has been sent */
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
out_no_write:
return ret_val;
}
/**
* igbvf_read_mbx_vf - Reads a message from the inbox intended for vf
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
* @mbx_id: id of mailbox to read
*
* returns SUCCESS if it successfuly read message from buffer
**/
static s32 igbvf_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
u16 mbx_id __unused)
{
s32 ret_val = E1000_SUCCESS;
u16 i;
DEBUGFUNC("igbvf_read_mbx_vf");
/* lock the mailbox to prevent pf/vf race condition */
ret_val = igbvf_obtain_mbx_lock_vf(hw);
if (ret_val)
goto out_no_read;
/* copy the message from the mailbox memory buffer */
for (i = 0; i < size; i++)
msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i);
/* Acknowledge receipt and release mailbox, then we're done */
E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
/* update stats */
hw->mbx.stats.msgs_rx++;
out_no_read:
return ret_val;
}
/**
* igbvf_init_mbx_params_vf - set initial values for vf mailbox
* @hw: pointer to the HW structure
*
* Initializes the hw->mbx struct to correct values for vf mailbox
*/
s32 igbvf_init_mbx_params_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
/* start mailbox as timed out and let the reset_hw call set the timeout
* value to begin communications */
mbx->timeout = 0;
mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
mbx->size = E1000_VFMAILBOX_SIZE;
mbx->ops.read = igbvf_read_mbx_vf;
mbx->ops.write = igbvf_write_mbx_vf;
mbx->ops.read_posted = igbvf_read_posted_mbx;
mbx->ops.write_posted = igbvf_write_posted_mbx;
mbx->ops.check_for_msg = igbvf_check_for_msg_vf;
mbx->ops.check_for_ack = igbvf_check_for_ack_vf;
mbx->ops.check_for_rst = igbvf_check_for_rst_vf;
mbx->stats.msgs_tx = 0;
mbx->stats.msgs_rx = 0;
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
return E1000_SUCCESS;
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#ifndef _IGBVF_MBX_H_
#define _IGBVF_MBX_H_
#include "igbvf_vf.h"
/* Define mailbox specific registers */
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
/* Define mailbox register bits */
#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
* PF. The reverse is true if it is E1000_PF_*.
* Message ACK's are the value or'd with 0xF0000000
*/
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
* this are the ACK */
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
* this are the NACK */
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
clear to send requests */
#define E1000_VT_MSGINFO_SHIFT 16
/* bits 23:16 are used for exra info for certain messages */
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_RESET 0x01 /* VF requests reset */
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */
#define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */
#define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_LPE 0x05 /* VF requests to set VMOLR.LPE */
#define E1000_VF_SET_PROMISC 0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
#define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT)
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */
#define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */
void igbvf_init_mbx_ops_generic(struct e1000_hw *hw);
s32 igbvf_init_mbx_params_vf(struct e1000_hw *);
#endif /* _IGBVF_MBX_H_ */

View File

@ -0,0 +1,121 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
/* glue for the OS-dependent part of igbvf
* includes register access macros
*/
#ifndef _IGBVF_OSDEP_H_
#define _IGBVF_OSDEP_H_
#define u8 unsigned char
#define bool boolean_t
#define dma_addr_t unsigned long
#define __le16 uint16_t
#define __le32 uint32_t
#define __le64 uint64_t
#define __iomem
#define __devinit
#define ____cacheline_aligned_in_smp
#define msleep(x) mdelay(x)
#define ETH_FCS_LEN 4
typedef int spinlock_t;
typedef enum {
false = 0,
true = 1
} boolean_t;
#define TRUE 1
#define FALSE 0
#define usec_delay(x) udelay(x)
#define msec_delay(x) mdelay(x)
#define msec_delay_irq(x) mdelay(x)
#define PCI_COMMAND_REGISTER PCI_COMMAND
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
#define ETH_ADDR_LEN ETH_ALEN
#define DEBUGOUT(S) if (0) { printf(S); }
#define DEBUGOUT1(S, A...) if (0) { printf(S, A); }
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
#define DEBUGOUT2 DEBUGOUT1
#define DEBUGOUT3 DEBUGOUT2
#define DEBUGOUT7 DEBUGOUT3
#define E1000_WRITE_REG(a, reg, value) do { \
writel((value), ((a)->hw_addr + reg)); } while (0)
#define E1000_READ_REG(a, reg) (readl((a)->hw_addr + reg))
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) do { \
writel((value), ((a)->hw_addr + reg + ((offset) << 2))); } while (0)
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
readl((a)->hw_addr + reg + ((offset) << 2)))
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
writew((value), ((a)->hw_addr + reg + ((offset) << 1))))
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
readw((a)->hw_addr + reg + ((offset) << 1)))
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
writeb((value), ((a)->hw_addr + reg + (offset))))
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
readb((a)->hw_addr + reg + (offset)))
#define E1000_WRITE_REG_IO(a, reg, offset) do { \
outl(reg, ((a)->io_base)); \
outl(offset, ((a)->io_base + 4)); } while(0)
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS)
#define E1000_WRITE_FLASH_REG(a, reg, value) ( \
writel((value), ((a)->flash_address + reg)))
#define E1000_WRITE_FLASH_REG16(a, reg, value) ( \
writew((value), ((a)->flash_address + reg)))
#define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg))
#define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg))
#endif /* _IGBVF_OSDEP_H_ */

View File

@ -0,0 +1,338 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#ifndef _IGBVF_REGS_H_
#define _IGBVF_REGS_H_
#define E1000_CTRL 0x00000 /* Device Control - RW */
#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
#define E1000_STATUS 0x00008 /* Device Status - RO */
#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define E1000_EERD 0x00014 /* EEPROM Read - RW */
#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define E1000_FLA 0x0001C /* Flash Access - RW */
#define E1000_MDIC 0x00020 /* MDI Control - RW */
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
#define E1000_FEXT 0x0002C /* Future Extended - RW */
#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* Rx Control - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
#define E1000_TCTL 0x00400 /* Tx Control - RW */
#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */
#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
#define E1000_FLSWCTL 0x01030 /* FLASH control register */
#define E1000_FLSWDATA 0x01034 /* FLASH data register */
#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
#define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
#define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */
#define E1000_SWDSTS 0x01044 /* SW Device Status - RW */
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
#define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
/* Split and Replication Rx Control - RW */
#define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */
#define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */
#define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */
#define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */
#define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */
#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n)))
#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n)))
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
/*
* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
* Example usage:
* E1000_RDBAL_REG(current_rx_queue)
*/
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
(0x0C000 + ((_n) * 0x40)))
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
(0x0C004 + ((_n) * 0x40)))
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
(0x0C008 + ((_n) * 0x40)))
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
(0x0C00C + ((_n) * 0x40)))
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
(0x0C010 + ((_n) * 0x40)))
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
(0x0C018 + ((_n) * 0x40)))
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
(0x0C028 + ((_n) * 0x40)))
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
(0x0E000 + ((_n) * 0x40)))
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
(0x0E004 + ((_n) * 0x40)))
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
(0x0E008 + ((_n) * 0x40)))
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
(0x0E010 + ((_n) * 0x40)))
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
(0x0E018 + ((_n) * 0x40)))
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
(0x0E028 + ((_n) * 0x40)))
#define E1000_TARC(_n) (0x03840 + (_n << 8))
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
#define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \
(0x0E038 + ((_n) * 0x40)))
#define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \
(0x0E03C + ((_n) * 0x40)))
#define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
#define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */
#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
(0x054E0 + ((_i - 16) * 8)))
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
(0x054E4 + ((_i - 16) * 8)))
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */
#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */
#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */
#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */
#define E1000_TDPUMB 0x0357C /* DMA Tx Descriptor uC Mail Box - RW */
#define E1000_TDPUAD 0x03580 /* DMA Tx Descriptor uC Addr Command - RW */
#define E1000_TDPUWD 0x03584 /* DMA Tx Descriptor uC Data Write - RW */
#define E1000_TDPURD 0x03588 /* DMA Tx Descriptor uC Data Read - RW */
#define E1000_TDPUCTL 0x0358C /* DMA Tx Descriptor uC Control - RW */
#define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */
#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
#define E1000_COLC 0x04028 /* Collision Count - R/clr */
#define E1000_DC 0x04030 /* Defer Count - R/clr */
#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */
#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */
#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */
#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */
#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */
#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */
#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */
#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */
#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */
#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */
#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */
#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */
#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */
#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */
#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */
#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */
#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_VFGPRC 0x00F10
#define E1000_VFGORC 0x00F18
#define E1000_VFMPRC 0x00F3C
#define E1000_VFGPTC 0x00F14
#define E1000_VFGOTC 0x00F34
#define E1000_VFGOTLBC 0x00F50
#define E1000_VFGPTLBC 0x00F44
#define E1000_VFGORLBC 0x00F48
#define E1000_VFGPRLBC 0x00F40
#define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */
#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */
#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */
#define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */
#define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */
#define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */
#define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */
#define E1000_RPTHC 0x04104 /* Rx Packets To Host */
#define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */
#define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */
#define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */
#define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */
#define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
#define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
#define E1000_LENERRS 0x04138 /* Length Errors Count */
#define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */
#define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */
#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */
#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
#define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */
#define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Page - RW */
#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Packet Count - RW */
#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */
#define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */
#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
#define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */
#define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
#define E1000_WUS 0x05810 /* Wakeup Status - RO */
#define E1000_MANC 0x05820 /* Management Control - RW */
#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
#define E1000_HOST_IF 0x08800 /* Host Interface */
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
#define E1000_MDPHYA 0x0003C /* PHY address - RW */
#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
#define E1000_SWSM 0x05B50 /* SW Semaphore */
#define E1000_FWSM 0x05B54 /* FW Semaphore */
#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Interface Control */
/* RSS registers */
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
* (_i) - RW */
#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
* low reg - RW */
#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
* upper reg - RW */
#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
* message reg - RW */
#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
* vector ctrl reg - RW */
#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
#endif /* _IGBVF_REGS_H_ */

View File

@ -0,0 +1,455 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#include "igbvf_vf.h"
static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw);
static s32 igbvf_check_for_link_vf(struct e1000_hw *hw);
static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
static s32 igbvf_init_hw_vf(struct e1000_hw *hw);
static s32 igbvf_reset_hw_vf(struct e1000_hw *hw);
static void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32);
static void igbvf_rar_set_vf(struct e1000_hw *, u8 *, u32);
static s32 igbvf_read_mac_addr_vf(struct e1000_hw *);
/**
* igbvf_init_mac_params_vf - Inits MAC params
* @hw: pointer to the HW structure
**/
static s32 igbvf_init_mac_params_vf(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
DEBUGFUNC("igbvf_init_mac_params_vf");
/* VF's have no MTA Registers - PF feature only */
mac->mta_reg_count = 128;
/* VF's have no access to RAR entries */
mac->rar_entry_count = 1;
/* Function pointers */
/* reset */
mac->ops.reset_hw = igbvf_reset_hw_vf;
/* hw initialization */
mac->ops.init_hw = igbvf_init_hw_vf;
/* check for link */
mac->ops.check_for_link = igbvf_check_for_link_vf;
/* link info */
mac->ops.get_link_up_info = igbvf_get_link_up_info_vf;
/* multicast address update */
mac->ops.update_mc_addr_list = igbvf_update_mc_addr_list_vf;
/* set mac address */
mac->ops.rar_set = igbvf_rar_set_vf;
/* read mac address */
mac->ops.read_mac_addr = igbvf_read_mac_addr_vf;
return E1000_SUCCESS;
}
/**
* igbvf_init_function_pointers_vf - Inits function pointers
* @hw: pointer to the HW structure
**/
void igbvf_init_function_pointers_vf(struct e1000_hw *hw)
{
DEBUGFUNC("igbvf_init_function_pointers_vf");
hw->mac.ops.init_params = igbvf_init_mac_params_vf;
hw->mbx.ops.init_params = igbvf_init_mbx_params_vf;
}
/**
* igbvf_get_link_up_info_vf - Gets link info.
* @hw: pointer to the HW structure
* @speed: pointer to 16 bit value to store link speed.
* @duplex: pointer to 16 bit value to store duplex.
*
* Since we cannot read the PHY and get accurate link info, we must rely upon
* the status register's data which is often stale and inaccurate.
**/
static s32 igbvf_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
u16 *duplex)
{
s32 status;
DEBUGFUNC("igbvf_get_link_up_info_vf");
status = E1000_READ_REG(hw, E1000_STATUS);
if (status & E1000_STATUS_SPEED_1000) {
*speed = SPEED_1000;
DEBUGOUT("1000 Mbs, ");
} else if (status & E1000_STATUS_SPEED_100) {
*speed = SPEED_100;
DEBUGOUT("100 Mbs, ");
} else {
*speed = SPEED_10;
DEBUGOUT("10 Mbs, ");
}
if (status & E1000_STATUS_FD) {
*duplex = FULL_DUPLEX;
DEBUGOUT("Full Duplex\n");
} else {
*duplex = HALF_DUPLEX;
DEBUGOUT("Half Duplex\n");
}
return E1000_SUCCESS;
}
/**
* igbvf_reset_hw_vf - Resets the HW
* @hw: pointer to the HW structure
*
* VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
* This is all the reset we can perform on a VF.
**/
static s32 igbvf_reset_hw_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 timeout = E1000_VF_INIT_TIMEOUT;
s32 ret_val = -E1000_ERR_MAC_INIT;
u32 ctrl, msgbuf[3];
u8 *addr = (u8 *)(&msgbuf[1]);
DEBUGFUNC("igbvf_reset_hw_vf");
DEBUGOUT("Issuing a function level reset to MAC\n");
ctrl = E1000_READ_REG(hw, E1000_CTRL);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
/* we cannot reset while the RSTI / RSTD bits are asserted */
while (!mbx->ops.check_for_rst(hw, 0) && timeout) {
timeout--;
usec_delay(5);
}
if (timeout) {
/* mailbox timeout can now become active */
mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
msgbuf[0] = E1000_VF_RESET;
mbx->ops.write_posted(hw, msgbuf, 1, 0);
msec_delay(10);
/* set our "perm_addr" based on info provided by PF */
ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
if (!ret_val) {
if (msgbuf[0] == (E1000_VF_RESET |
E1000_VT_MSGTYPE_ACK))
memcpy(hw->mac.perm_addr, addr, 6);
else
ret_val = -E1000_ERR_MAC_INIT;
}
}
return ret_val;
}
/**
* igbvf_init_hw_vf - Inits the HW
* @hw: pointer to the HW structure
*
* Not much to do here except clear the PF Reset indication if there is one.
**/
static s32 igbvf_init_hw_vf(struct e1000_hw *hw)
{
DEBUGFUNC("igbvf_init_hw_vf");
/* attempt to set and restore our mac address */
igbvf_rar_set_vf(hw, hw->mac.addr, 0);
return E1000_SUCCESS;
}
/**
* igbvf_rar_set_vf - set device MAC address
* @hw: pointer to the HW structure
* @addr: pointer to the receive address
* @index receive address array register
**/
static void igbvf_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index __unused)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[3];
u8 *msg_addr = (u8 *)(&msgbuf[1]);
s32 ret_val;
memset(msgbuf, 0, 12);
msgbuf[0] = E1000_VF_SET_MAC_ADDR;
memcpy(msg_addr, addr, 6);
ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
if (!ret_val)
ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
/* if nacked the address was rejected, use "perm_addr" */
if (!ret_val &&
(msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
igbvf_read_mac_addr_vf(hw);
}
/**
* igbvf_hash_mc_addr_vf - Generate a multicast hash value
* @hw: pointer to the HW structure
* @mc_addr: pointer to a multicast address
*
* Generates a multicast address hash value which is used to determine
* the multicast filter table array address and new table value. See
* igbvf_mta_set_generic()
**/
static u32 igbvf_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
{
u32 hash_value, hash_mask;
u8 bit_shift = 0;
DEBUGFUNC("igbvf_hash_mc_addr_generic");
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
/*
* The bit_shift is the number of left-shifts
* where 0xFF would still fall within the hash mask.
*/
while (hash_mask >> bit_shift != 0xFF)
bit_shift++;
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
(((u16) mc_addr[5]) << bit_shift)));
return hash_value;
}
/**
* igbvf_update_mc_addr_list_vf - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
*
* Updates the Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void igbvf_update_mc_addr_list_vf(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[E1000_VFMAILBOX_SIZE];
u16 *hash_list = (u16 *)&msgbuf[1];
u32 hash_value;
u32 i;
DEBUGFUNC("igbvf_update_mc_addr_list_vf");
/* Each entry in the list uses 1 16 bit word. We have 30
* 16 bit words available in our HW msg buffer (minus 1 for the
* msg type). That's 30 hash values if we pack 'em right. If
* there are more than 30 MC addresses to add then punt the
* extras for now and then add code to handle more than 30 later.
* It would be unusual for a server to request that many multi-cast
* addresses except for in large enterprise network environments.
*/
DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count);
msgbuf[0] = E1000_VF_SET_MULTICAST;
if (mc_addr_count > 30) {
msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW;
mc_addr_count = 30;
}
msgbuf[0] |= mc_addr_count << E1000_VT_MSGINFO_SHIFT;
for (i = 0; i < mc_addr_count; i++) {
hash_value = igbvf_hash_mc_addr_vf(hw, mc_addr_list);
DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
hash_list[i] = hash_value & 0x0FFF;
mc_addr_list += ETH_ADDR_LEN;
}
mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE, 0);
}
/**
* igbvf_vfta_set_vf - Set/Unset vlan filter table address
* @hw: pointer to the HW structure
* @vid: determines the vfta register and bit to set/unset
* @set: if true then set bit, else clear bit
**/
void igbvf_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
msgbuf[0] = E1000_VF_SET_VLAN;
msgbuf[1] = vid;
/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
if (set)
msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
mbx->ops.write_posted(hw, msgbuf, 2, 0);
}
/** igbvf_rlpml_set_vf - Set the maximum receive packet length
* @hw: pointer to the HW structure
* @max_size: value to assign to max frame size
**/
void igbvf_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
msgbuf[0] = E1000_VF_SET_LPE;
msgbuf[1] = max_size;
mbx->ops.write_posted(hw, msgbuf, 2, 0);
}
/**
* igbvf_promisc_set_vf - Set flags for Unicast or Multicast promisc
* @hw: pointer to the HW structure
* @uni: boolean indicating unicast promisc status
* @multi: boolean indicating multicast promisc status
**/
s32 igbvf_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf = E1000_VF_SET_PROMISC;
s32 ret_val;
switch (type) {
case e1000_promisc_multicast:
msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
break;
case e1000_promisc_enabled:
msgbuf |= E1000_VF_SET_PROMISC_MULTICAST;
case e1000_promisc_unicast:
msgbuf |= E1000_VF_SET_PROMISC_UNICAST;
case e1000_promisc_disabled:
break;
default:
return -E1000_ERR_MAC_INIT;
}
ret_val = mbx->ops.write_posted(hw, &msgbuf, 1, 0);
if (!ret_val)
ret_val = mbx->ops.read_posted(hw, &msgbuf, 1, 0);
if (!ret_val && !(msgbuf & E1000_VT_MSGTYPE_ACK))
ret_val = -E1000_ERR_MAC_INIT;
return ret_val;
}
/**
* igbvf_read_mac_addr_vf - Read device MAC address
* @hw: pointer to the HW structure
**/
static s32 igbvf_read_mac_addr_vf(struct e1000_hw *hw)
{
int i;
for (i = 0; i < ETH_ADDR_LEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
return E1000_SUCCESS;
}
/**
* igbvf_check_for_link_vf - Check for link for a virtual interface
* @hw: pointer to the HW structure
*
* Checks to see if the underlying PF is still talking to the VF and
* if it is then it reports the link state to the hardware, otherwise
* it reports link down and returns an error.
**/
static s32 igbvf_check_for_link_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val = E1000_SUCCESS;
u32 in_msg = 0;
DEBUGFUNC("igbvf_check_for_link_vf");
/*
* We only want to run this if there has been a rst asserted.
* in this case that could mean a link change, device reset,
* or a virtual function reset
*/
/* If we were hit with a reset drop the link */
if (!mbx->ops.check_for_rst(hw, 0))
mac->get_link_status = true;
if (!mac->get_link_status)
goto out;
/* if link status is down no point in checking to see if pf is up */
if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU))
goto out;
/* if the read failed it could just be a mailbox collision, best wait
* until we are called again and don't report an error */
if (mbx->ops.read(hw, &in_msg, 1, 0))
goto out;
/* if incoming message isn't clear to send we are waiting on response */
if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
/* message is not CTS and is NACK we have lost CTS status */
if (in_msg & E1000_VT_MSGTYPE_NACK)
ret_val = -E1000_ERR_MAC_INIT;
goto out;
}
/* at this point we know the PF is talking to us, check and see if
* we are still accepting timeout or if we had a timeout failure.
* if we failed then we will need to reinit */
if (!mbx->timeout) {
ret_val = -E1000_ERR_MAC_INIT;
goto out;
}
/* if we passed all the tests above then the link is up and we no
* longer need to check for link */
mac->get_link_status = false;
out:
return ret_val;
}

View File

@ -0,0 +1,345 @@
/*******************************************************************************
Intel(R) 82576 Virtual Function Linux driver
Copyright(c) 1999 - 2008 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
FILE_LICENCE ( GPL2_ONLY );
#ifndef _IGBVF_VF_H_
#define _IGBVF_VF_H_
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <byteswap.h>
#include <errno.h>
#include <ipxe/pci.h>
#include <ipxe/malloc.h>
#include <ipxe/if_ether.h>
#include <ipxe/io.h>
#include <ipxe/ethernet.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include "igbvf_osdep.h"
#include "igbvf_regs.h"
#include "igbvf_defines.h"
struct e1000_hw;
#define E1000_DEV_ID_82576_VF 0x10CA
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
/* Additional Descriptor Control definitions */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
/* SRRCTL bit definitions */
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
/* Interrupt Defines */
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
#define E1000_IVAR_VALID 0x80
/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
struct {
u64 pkt_addr; /* Packet buffer address */
u64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
union {
u32 data;
struct {
u16 pkt_info; /* RSS type, Packet type */
u16 hdr_info; /* Split Header,
* header buffer length */
} hs_rss;
} lo_dword;
union {
u32 rss; /* RSS Hash */
struct {
u16 ip_id; /* IP id */
u16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
u32 status_error; /* ext status/error */
u16 length; /* Packet length */
u16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
struct {
u64 buffer_addr; /* Address of descriptor's data buf */
u32 cmd_type_len;
u32 olinfo_status;
} read;
struct {
u64 rsvd; /* Reserved */
u32 nxtseq_seed;
u32 status;
} wb;
};
/* Adv Transmit Descriptor Config Masks */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
/* Context descriptors */
struct e1000_adv_tx_context_desc {
u32 vlan_macip_lens;
u32 seqnum_seed;
u32 type_tucmd_mlhl;
u32 mss_l4len_idx;
};
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
enum e1000_mac_type {
e1000_undefined = 0,
e1000_vfadapt,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
struct e1000_vf_stats {
u64 base_gprc;
u64 base_gptc;
u64 base_gorc;
u64 base_gotc;
u64 base_mprc;
u64 base_gotlbc;
u64 base_gptlbc;
u64 base_gorlbc;
u64 base_gprlbc;
u32 last_gprc;
u32 last_gptc;
u32 last_gorc;
u32 last_gotc;
u32 last_mprc;
u32 last_gotlbc;
u32 last_gptlbc;
u32 last_gorlbc;
u32 last_gprlbc;
u64 gprc;
u64 gptc;
u64 gorc;
u64 gotc;
u64 mprc;
u64 gotlbc;
u64 gptlbc;
u64 gorlbc;
u64 gprlbc;
};
#include "igbvf_mbx.h"
struct e1000_mac_operations {
/* Function pointers for the MAC. */
s32 (*init_params)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
void (*clear_vfta)(struct e1000_hw *);
s32 (*get_bus_info)(struct e1000_hw *);
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
s32 (*reset_hw)(struct e1000_hw *);
s32 (*init_hw)(struct e1000_hw *);
s32 (*setup_link)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
void (*mta_set)(struct e1000_hw *, u32);
void (*rar_set)(struct e1000_hw *, u8*, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
};
struct e1000_mac_info {
struct e1000_mac_operations ops;
u8 addr[6];
u8 perm_addr[6];
enum e1000_mac_type type;
u16 mta_reg_count;
u16 rar_entry_count;
bool get_link_status;
};
enum e1000_bus_type {
e1000_bus_type_unknown = 0,
e1000_bus_type_pci,
e1000_bus_type_pcix,
e1000_bus_type_pci_express,
e1000_bus_type_reserved
};
enum e1000_bus_speed {
e1000_bus_speed_unknown = 0,
e1000_bus_speed_33,
e1000_bus_speed_66,
e1000_bus_speed_100,
e1000_bus_speed_120,
e1000_bus_speed_133,
e1000_bus_speed_2500,
e1000_bus_speed_5000,
e1000_bus_speed_reserved
};
enum e1000_bus_width {
e1000_bus_width_unknown = 0,
e1000_bus_width_pcie_x1,
e1000_bus_width_pcie_x2,
e1000_bus_width_pcie_x4 = 4,
e1000_bus_width_pcie_x8 = 8,
e1000_bus_width_32,
e1000_bus_width_64,
e1000_bus_width_reserved
};
struct e1000_bus_info {
enum e1000_bus_type type;
enum e1000_bus_speed speed;
enum e1000_bus_width width;
u16 func;
u16 pci_cmd_word;
};
struct e1000_mbx_operations {
s32 (*init_params)(struct e1000_hw *hw);
s32 (*read)(struct e1000_hw *, u32 *, u16, u16);
s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16);
s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
s32 (*check_for_msg)(struct e1000_hw *, u16);
s32 (*check_for_ack)(struct e1000_hw *, u16);
s32 (*check_for_rst)(struct e1000_hw *, u16);
};
struct e1000_mbx_stats {
u32 msgs_tx;
u32 msgs_rx;
u32 acks;
u32 reqs;
u32 rsts;
};
struct e1000_mbx_info {
struct e1000_mbx_operations ops;
struct e1000_mbx_stats stats;
u32 timeout;
u32 usec_delay;
u16 size;
};
struct e1000_dev_spec_vf {
u32 vf_number;
u32 v2p_mailbox;
};
struct e1000_hw {
void *back;
u8 __iomem *hw_addr;
u8 __iomem *flash_address;
unsigned long io_base;
struct e1000_mac_info mac;
struct e1000_bus_info bus;
struct e1000_mbx_info mbx;
union {
struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
u16 subsystem_vendor_id;
u16 subsystem_device_id;
u16 vendor_id;
u8 revision_id;
};
enum e1000_promisc_type {
e1000_promisc_disabled = 0, /* all promisc modes disabled */
e1000_promisc_unicast = 1, /* unicast promiscuous enabled */
e1000_promisc_multicast = 2, /* multicast promiscuous enabled */
e1000_promisc_enabled = 3, /* both uni and multicast promisc */
e1000_num_promisc_types
};
/* These functions must be implemented by drivers */
s32 igbvf_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
void igbvf_vfta_set_vf(struct e1000_hw *, u16, bool);
void igbvf_rlpml_set_vf(struct e1000_hw *, u16);
s32 igbvf_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type);
#endif /* _IGBVF_VF_H_ */

View File

@ -135,6 +135,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_jme ( ERRFILE_DRIVER | 0x005b0000 )
#define ERRFILE_virtio_net ( ERRFILE_DRIVER | 0x005c0000 )
#define ERRFILE_tap ( ERRFILE_DRIVER | 0x005d0000 )
#define ERRFILE_igbvf_main ( ERRFILE_DRIVER | 0x005e0000 )
#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )