virtual function ixgbe driver
Subsystems (3)
cover virtual function ixgbe driver
The following series implements the ixgbevf driver. This series of patches has the following known issues:
- ixgbevf multiple load/unload can cause a panic
- loading ixgbevf before ixgbe does not work
- Tx hangs on VF interfaces - this happens when various resets, mostly due to ethtool operations are executed while passing traffic
We are looking for inclusion into net-next-2.6 so that we can get assistance from the community in testing and further development of this driver.
---
Greg Rose (13):
ixgbe: Fix ethtool diag test for VT mode operation
ixgbe: Add SR-IOV features to main module
ixgbe: Add SR-IOV feature enablement code
ixgbe: Add SR-IOV specific modules to driver Makefile
ixgbe: Add SR-IOV specific features
ixgbe: Add SR-IOV register, structure and bit defines
ixgbe: Mailbox header and code module
ixgbevf: Kconfig, Makefile and Documentation
ixgbevf: Driver Makefile
ixgbevf: Driver main and ethool interface module and main header
ixgbevf: Mailbox communication
ixgbevf: 82599 Virtual Function core functions and header
ixgbevf: Macros, data structures, useful defines and registers
Documentation/networking/ixgbevf.txt | 90 + drivers/net/Kconfig | 22 drivers/net/Makefile | 1 drivers/net/ixgbe/Makefile | 3 drivers/net/ixgbe/ixgbe.h | 31 drivers/net/ixgbe/ixgbe_82599.c | 126 + drivers/net/ixgbe/ixgbe_ethtool.c | 11 drivers/net/ixgbe/ixgbe_main.c | 280 +++ drivers/net/ixgbe/ixgbe_mbx.c | 479 +++++ drivers/net/ixgbe/ixgbe_mbx.h | 96 + drivers/net/ixgbe/ixgbe_sriov.c | 336 +++ drivers/net/ixgbe/ixgbe_sriov.h | 45 drivers/net/ixgbe/ixgbe_type.h | 53 + drivers/net/ixgbevf/Makefile | 38 drivers/net/ixgbevf/defines.h | 292 +++ drivers/net/ixgbevf/ethtool.c | 716 +++++++ drivers/net/ixgbevf/ixgbevf.h | 318 +++ drivers/net/ixgbevf/ixgbevf_main.c | 3571 ++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/mbx.c | 341 +++ drivers/net/ixgbevf/mbx.h | 100 + drivers/net/ixgbevf/regs.h | 85 + drivers/net/ixgbevf/vf.c | 387 ++++ drivers/net/ixgbevf/vf.h | 168 ++ 23 files changed, 7517 insertions(+), 72 deletions(-) create mode 100755 Documentation/networking/ixgbevf.txt create mode 100644 drivers/net/ixgbe/ixgbe_mbx.c create mode 100644 drivers/net/ixgbe/ixgbe_mbx.h create mode 100644 drivers/net/ixgbe/ixgbe_sriov.c create mode 100644 drivers/net/ixgbe/ixgbe_sriov.h create mode 100644 drivers/net/ixgbevf/Makefile create mode 100644 drivers/net/ixgbevf/defines.h create mode 100644 drivers/net/ixgbevf/ethtool.c create mode 100644 drivers/net/ixgbevf/ixgbevf.h create mode 100644 drivers/net/ixgbevf/ixgbevf_main.c create mode 100644 drivers/net/ixgbevf/mbx.c create mode 100644 drivers/net/ixgbevf/mbx.h create mode 100644 drivers/net/ixgbevf/regs.h create mode 100644 drivers/net/ixgbevf/vf.c create mode 100644 drivers/net/ixgbevf/vf.h
Signature · 2 lines
Cheers, Jeff Kirsher
PATCH 1/13 ixgbevf: Macros, data structures, useful defines and registers
From: Greg Rose <[email protected]>
These two headers define the commonly used macros, data structures, register bits and register offsets used by the ixgbevf driver on the 82599 virtual function device
---
drivers/net/ixgbevf/defines.h | 292 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/regs.h | 85 ++++++++++++ 2 files changed, 377 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbevf/defines.h create mode 100644 drivers/net/ixgbevf/regs.h
drivers/net/ixgbevf/defines.h new file +292 -0
@@ -0,0 +1,292 @@ +/******************************************************************************* + +Intel 82599 Virtual Function driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBEVF_DEFINES_H_ +#define _IXGBEVF_DEFINES_H_ + +/* Device IDs */ +#define IXGBE_DEV_ID_82599_VF 0x10ED + +#define IXGBE_VF_IRQ_CLEAR_MASK 7 +#define IXGBE_VF_MAX_TX_QUEUES 1 +#define IXGBE_VF_MAX_RX_QUEUES 1 +#define IXGBE_ETH_LENGTH_OF_ADDRESS 6 + +/* Link speed */ +typedef u32 ixgbe_link_speed ; +#define IXGBE_LINK_SPEED_1GB_FULL 0x0020 +#define IXGBE_LINK_SPEED_10GB_FULL 0x0080 + +#define IXGBE_CTRL_RST 0x04000000/* Reset (SW) */ +#define IXGBE_RXDCTL_ENABLE 0x02000000/* Enable specific Rx Queue */ +#define IXGBE_TXDCTL_ENABLE 0x02000000/* Enable specific Tx Queue */ +#define IXGBE_LINKS_UP 0x40000000 +#define IXGBE_LINKS_SPEED 0x20000000 + +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE 8 +#define IXGBE_REQ_TX_BUFFER_GRANULARITY 1024 + +/* Interrupt Vector Allocation Registers */ +#define IXGBE_IVAR_ALLOC_VAL 0x80/* Interrupt Allocation valid */ + +#define IXGBE_VF_INIT_TIMEOUT 200/* Number of retries to clear RSTI */ + +/* Receive Config masks */ +#define IXGBE_RXCTRL_RXEN 0x00000001/* Enable Receiver */ +#define IXGBE_RXCTRL_DMBYPS 0x00000002/* Descriptor Monitor Bypass */ +#define IXGBE_RXDCTL_ENABLE 0x02000000/* Enable specific Rx Queue */ +#define IXGBE_RXDCTL_VME 0x40000000/* VLAN mode enable */ + +/* DCA Control */ +#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11)/* Tx Desc writeback RO bit */ + +/* PSRTYPE bit definitions */ +#define IXGBE_PSRTYPE_TCPHDR 0x00000010 +#define IXGBE_PSRTYPE_UDPHDR 0x00000020 +#define IXGBE_PSRTYPE_IPV4HDR 0x00000100 +#define IXGBE_PSRTYPE_IPV6HDR 0x00000200 +#define IXGBE_PSRTYPE_L2HDR 0x00001000 + +/* SRRCTL bit definitions */ +#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10/* so many KBs */ +#define IXGBE_SRRCTL_RDMTS_SHIFT 22 +#define IXGBE_SRRCTL_RDMTS_MASK 0x01C00000 +#define IXGBE_SRRCTL_DROP_EN 0x10000000 +#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F +#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 +#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 +#define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 +#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 + +/* Receive Descriptor bit definitions */ +#define IXGBE_RXD_STAT_DD 0x01/* Descriptor Done */ +#define IXGBE_RXD_STAT_EOP 0x02/* End of Packet */ +#define IXGBE_RXD_STAT_FLM 0x04/* FDir Match */ +#define IXGBE_RXD_STAT_VP 0x08/* IEEE VLAN Packet */ +#define IXGBE_RXDADV_NEXTP_MASK 0x000FFFF0/* Next Descriptor Index */ +#define IXGBE_RXDADV_NEXTP_SHIFT 0x00000004 +#define IXGBE_RXD_STAT_UDPCS 0x10/* UDP xsum calculated */ +#define IXGBE_RXD_STAT_L4CS 0x20/* L4 xsum calculated */ +#define IXGBE_RXD_STAT_IPCS 0x40/* IP xsum calculated */ +#define IXGBE_RXD_STAT_PIF 0x80/* passed in-exact filter */ +#define IXGBE_RXD_STAT_CRCV 0x100/* Speculative CRC Valid */ +#define IXGBE_RXD_STAT_VEXT 0x200/* 1st VLAN found */ +#define IXGBE_RXD_STAT_UDPV 0x400/* Valid UDP checksum */ +#define IXGBE_RXD_STAT_DYNINT 0x800/* Pkt caused INT via DYNINT */ +#define IXGBE_RXD_STAT_TS 0x10000/* Time Stamp */ +#define IXGBE_RXD_STAT_SECP 0x20000/* Security Processing */ +#define IXGBE_RXD_STAT_LB 0x40000/* Loopback Status */ +#define IXGBE_RXD_STAT_ACK 0x8000/* ACK Packet indication */ +#define IXGBE_RXD_ERR_CE 0x01/* CRC Error */ +#define IXGBE_RXD_ERR_LE 0x02/* Length Error */ +#define IXGBE_RXD_ERR_PE 0x08/* Packet Error */ +#define IXGBE_RXD_ERR_OSE 0x10/* Oversize Error */ +#define IXGBE_RXD_ERR_USE 0x20/* Undersize Error */ +#define IXGBE_RXD_ERR_TCPE 0x40/* TCP/UDP Checksum Error */ +#define IXGBE_RXD_ERR_IPE 0x80/* IP Checksum Error */ +#define IXGBE_RXDADV_ERR_MASK 0xFFF00000/* RDESC.ERRORS mask */ +#define IXGBE_RXDADV_ERR_SHIFT 20/* RDESC.ERRORS shift */ +#define IXGBE_RXDADV_ERR_HBO 0x00800000/*Header Buffer Overflow */ +#define IXGBE_RXDADV_ERR_CE 0x01000000/* CRC Error */ +#define IXGBE_RXDADV_ERR_LE 0x02000000/* Length Error */ +#define IXGBE_RXDADV_ERR_PE 0x08000000/* Packet Error */ +#define IXGBE_RXDADV_ERR_OSE 0x10000000/* Oversize Error */ +#define IXGBE_RXDADV_ERR_USE 0x20000000/* Undersize Error */ +#define IXGBE_RXDADV_ERR_TCPE 0x40000000/* TCP/UDP Checksum Error */ +#define IXGBE_RXDADV_ERR_IPE 0x80000000/* IP Checksum Error */ +#define IXGBE_RXD_VLAN_ID_MASK 0x0FFF/* VLAN ID is in lower 12 bits */ +#define IXGBE_RXD_PRI_MASK 0xE000/* Priority is in upper 3 bits */ +#define IXGBE_RXD_PRI_SHIFT 13 +#define IXGBE_RXD_CFI_MASK 0x1000/* CFI is bit 12 */ +#define IXGBE_RXD_CFI_SHIFT 12 + +#define IXGBE_RXDADV_STAT_DD IXGBE_RXD_STAT_DD/* Done */ +#define IXGBE_RXDADV_STAT_EOP IXGBE_RXD_STAT_EOP/* End of Packet */ +#define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM/* FDir Match */ +#define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP/* IEEE VLAN Pkt */ +#define IXGBE_RXDADV_STAT_MASK 0x000FFFFF/* Stat/NEXTP: bit 0-19 */ +#define IXGBE_RXDADV_STAT_FCEOFS 0x00000040/* FCoE EOF/SOF Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT 0x00000030/* FCoE Pkt Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000/* 00: No Ctxt Match */ +#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010/* 01: Ctxt w/o DDP */ +#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020/* 10: Recv. FCP_RSP */ +#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030/* 11: Ctxt w/ DDP */ + +#define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F +#define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0 +#define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0 +#define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0 +#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 +#define IXGBE_RXDADV_RSCCNT_SHIFT 17 +#define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5 +#define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000 +#define IXGBE_RXDADV_SPH 0x8000 + +#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXD_ERR_CE | \ + IXGBE_RXD_ERR_LE | \ + IXGBE_RXD_ERR_PE | \ + IXGBE_RXD_ERR_OSE | \ + IXGBE_RXD_ERR_USE) + +#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXDADV_ERR_CE | \ + IXGBE_RXDADV_ERR_LE | \ + IXGBE_RXDADV_ERR_PE | \ + IXGBE_RXDADV_ERR_OSE | \ + IXGBE_RXDADV_ERR_USE) + +#define IXGBE_TXD_POPTS_IXSM 0x01/* Insert IP checksum */ +#define IXGBE_TXD_POPTS_TXSM 0x02/* Insert TCP/UDP checksum */ +#define IXGBE_TXD_CMD_EOP 0x01000000/* End of Packet */ +#define IXGBE_TXD_CMD_IFCS 0x02000000/* Insert FCS (Ethernet CRC) */ +#define IXGBE_TXD_CMD_IC 0x04000000/* Insert Checksum */ +#define IXGBE_TXD_CMD_RS 0x08000000/* Report Status */ +#define IXGBE_TXD_CMD_DEXT 0x20000000/* Descriptor extension (0 = legacy) */ +#define IXGBE_TXD_CMD_VLE 0x40000000/* Add VLAN tag */ +#define IXGBE_TXD_STAT_DD 0x00000001/* Descriptor Done */ + +/* Transmit Descriptor - Advanced */ +union ixgbe_adv_tx_desc { +struct { +__le64 buffer_addr;/* Address of descriptor's data buf */ +__le32 cmd_type_len; +__le32 olinfo_status; + } read; +struct { +__le64 rsvd;/* Reserved */ +__le32 nxtseq_seed; +__le32 status; + } wb; +}; + +/* Receive Descriptor - Advanced */ +union ixgbe_adv_rx_desc { +struct { +__le64 pkt_addr;/* Packet buffer address */ +__le64 hdr_addr;/* Header buffer address */ + } read; +struct { +struct { +union { +__le32 data; +struct { +__le16 pkt_info;/* RSS, Pkt type */ +__le16 hdr_info;/* Splithdr, hdrlen */ + } hs_rss; + } lo_dword; +union { +__le32 rss;/* RSS Hash */ +struct { +__le16 ip_id;/* IP id */ +__le16 csum;/* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; +struct { +__le32 status_error;/* ext status/error */ +__le16 length;/* Packet length */ +__le16 vlan;/* VLAN tag */ + } upper; + } wb;/* writeback */ +}; + +/* Context descriptors */ +struct ixgbe_adv_tx_context_desc { +__le32 vlan_macip_lens; +__le32 seqnum_seed; +__le32 type_tucmd_mlhl; +__le32 mss_l4len_idx; +}; + +/* Adv Transmit Descriptor Config Masks */ +#define IXGBE_ADVTXD_DTYP_MASK 0x00F00000/* DTYP mask */ +#define IXGBE_ADVTXD_DTYP_CTXT 0x00200000/* Advanced Context Desc */ +#define IXGBE_ADVTXD_DTYP_DATA 0x00300000/* Advanced Data Descriptor */ +#define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP/* End of Packet */ +#define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS/* Insert FCS */ +#define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS/* Report Status */ +#define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT/* Desc ext (1=Adv) */ +#define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE/* VLAN pkt enable */ +#define IXGBE_ADVTXD_DCMD_TSE 0x80000000/* TCP Seg enable */ +#define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD/* Descriptor Done */ +#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400/* IP Packet Type: 1=IPv4 */ +#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000/* IP Packet Type: 0=IPv6 */ +#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000/* L4 Packet TYPE of UDP */ +#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800/* L4 Packet TYPE of TCP */ +#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000/* L4 Packet TYPE of SCTP */ +#define IXGBE_ADVTXD_IDX_SHIFT 4/* Adv desc Index shift */ +#define IXGBE_ADVTXD_POPTS_SHIFT 8/* Adv desc POPTS shift */ +#define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \ + IXGBE_ADVTXD_POPTS_SHIFT) +#define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \ + IXGBE_ADVTXD_POPTS_SHIFT) +#define IXGBE_ADVTXD_PAYLEN_SHIFT 14/* Adv desc PAYLEN shift */ +#define IXGBE_ADVTXD_MACLEN_SHIFT 9/* Adv ctxt desc mac len shift */ +#define IXGBE_ADVTXD_VLAN_SHIFT 16/* Adv ctxt vlan tag shift */ +#define IXGBE_ADVTXD_L4LEN_SHIFT 8/* Adv ctxt L4LEN shift */ +#define IXGBE_ADVTXD_MSS_SHIFT 16/* Adv ctxt MSS shift */ + +/* Interrupt register bitmasks */ + +/* Extended Interrupt Cause Read */ +#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF/* RTx Queue Interrupt */ +#define IXGBE_EICR_MAILBOX 0x00080000/* VF to PF Mailbox Interrupt */ +#define IXGBE_EICR_OTHER 0x80000000/* Interrupt Cause Active */ + +/* Extended Interrupt Cause Set */ +#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE/* RTx Queue Interrupt */ +#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX/* VF to PF Mailbox Int */ +#define IXGBE_EICS_OTHER IXGBE_EICR_OTHER/* INT Cause Active */ + +/* Extended Interrupt Mask Set */ +#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE/* RTx Queue Interrupt */ +#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX/* VF to PF Mailbox Int */ +#define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER/* INT Cause Active */ + +/* Extended Interrupt Mask Clear */ +#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE/* RTx Queue Interrupt */ +#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX/* VF to PF Mailbox Int */ +#define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER/* INT Cause Active */ + +#define IXGBE_EIMS_ENABLE_MASK ( \ + IXGBE_EIMS_RTX_QUEUE | \ + IXGBE_EIMS_MAILBOX | \ + IXGBE_EIMS_OTHER) + +#define IXGBE_EITR_CNT_WDIS 0x80000000 + +/* Error Codes */ +#define IXGBE_ERR_INVALID_MAC_ADDR -1 +#define IXGBE_ERR_RESET_FAILED -2 + +#endif /* _IXGBEVF_DEFINES_H_ */
drivers/net/ixgbevf/regs.h new file +85 -0
85 lines not on this page · raw message
PATCH 2/13 ixgbevf: 82599 Virtual Function core functions and header
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
This module and header file contain the core functions for the 82599 virtual function device.
---
drivers/net/ixgbevf/vf.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/vf.h | 168 ++++++++++++++++++++ 2 files changed, 555 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbevf/vf.c create mode 100644 drivers/net/ixgbevf/vf.h
drivers/net/ixgbevf/vf.c new file +387 -0
@@ -0,0 +1,387 @@ +/******************************************************************************* + +Intel 82599 Virtual Function driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "vf.h" + +/** +* ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx +* @hw: pointer to hardware structure +* +* Starts the hardware by filling the bus info structure and media type, clears +* all on chip counters, initializes receive address registers, multicast +* table, VLAN filter table, calls routine to set up link and flow control +* settings, and leaves transmit and receive units disabled and uninitialized +**/ +static s32 ixgbevf_start_hw_vf (struct ixgbe_hw *hw) +{ +/* Clear adapter stopped flag */ + hw->adapter_stopped = false; + +return 0 ; +} + +/** +* ixgbevf_init_hw_vf - virtual function hardware initialization +* @hw: pointer to hardware structure +* +* Initialize the hardware by resetting the hardware and then starting +* the hardware +**/ +static s32 ixgbevf_init_hw_vf (struct ixgbe_hw *hw) +{ +s32 status = hw->mac.ops.start_hw (hw); + + hw->mac.ops.get_mac_addr (hw, hw->mac.addr); + +return status; +} + +/** +* ixgbevf_reset_hw_vf - Performs hardware reset +* @hw: pointer to hardware structure +* +* Resets the hardware by reseting the transmit and receive units, masks and +* clears all interrupts. +**/ +static s32 ixgbevf_reset_hw_vf (struct ixgbe_hw *hw) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +u32 timeout =IXGBE_VF_INIT_TIMEOUT ; +s32 ret_val =IXGBE_ERR_INVALID_MAC_ADDR ; +u32 msgbuf[IXGBE_VF_PERMADDR_MSG_LEN ]; +u8 *addr = (u8 *)(&msgbuf[1 ]); + +/* Call adapter stop to disable tx/rx and clear interrupts */ + hw->mac.ops.stop_adapter (hw); + +IXGBE_WRITE_REG (hw,IXGBE_VFCTRL ,IXGBE_CTRL_RST ); +IXGBE_WRITE_FLUSH (hw); + +/* we cannot reset while the RSTI / RSTD bits are asserted */ +while (!mbx->ops.check_for_rst (hw) && timeout) { + timeout--; +udelay (5 ); + } + +if (!timeout) +return IXGBE_ERR_RESET_FAILED ; + +/* mailbox timeout can now become active */ + mbx->timeout =IXGBE_VF_MBX_INIT_TIMEOUT ; + + msgbuf[0 ] =IXGBE_VF_RESET ; + mbx->ops.write_posted (hw, msgbuf,1 ); + +msleep (10 ); + +/* set our "perm_addr" based on info provided by PF */ +/* also set up the mc_filter_type which is piggy backed +* on the mac address in word 3 */ + ret_val = mbx->ops.read_posted (hw, msgbuf,IXGBE_VF_PERMADDR_MSG_LEN ); +if (ret_val) +return ret_val; + +if (msgbuf[0 ] != (IXGBE_VF_RESET |IXGBE_VT_MSGTYPE_ACK )) +return IXGBE_ERR_INVALID_MAC_ADDR ; + +memcpy (hw->mac.perm_addr, addr,IXGBE_ETH_LENGTH_OF_ADDRESS ); + hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD ]; + +return 0 ; +} + +/** +* ixgbevf_stop_hw_vf - Generic stop Tx/Rx units +* @hw: pointer to hardware structure +* +* Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, +* disables transmit and receive units. The adapter_stopped flag is used by +* the shared code and drivers to determine if the adapter is in a stopped +* state and should not touch the hardware. +**/ +static s32 ixgbevf_stop_hw_vf (struct ixgbe_hw *hw) +{ +u32 number_of_queues; +u32 reg_val; +u16 i; + +/* +* Set the adapter_stopped flag so other driver functions stop touching +* the hardware +*/ + hw->adapter_stopped = true; + +/* Disable the receive unit by stopped each queue */ + number_of_queues = hw->mac.max_rx_queues; +for (i =0 ; i < number_of_queues; i++) { + reg_val =IXGBE_READ_REG (hw,IXGBE_VFRXDCTL (i)); +if (reg_val &IXGBE_RXDCTL_ENABLE ) { + reg_val &= ~IXGBE_RXDCTL_ENABLE ; +IXGBE_WRITE_REG (hw,IXGBE_VFRXDCTL (i), reg_val); + } + } + +IXGBE_WRITE_FLUSH (hw); + +/* Clear interrupt mask to stop from interrupts being generated */ +IXGBE_WRITE_REG (hw,IXGBE_VTEIMC ,IXGBE_VF_IRQ_CLEAR_MASK ); + +/* Clear any pending interrupts */ +IXGBE_READ_REG (hw,IXGBE_VTEICR ); + +/* Disable the transmit unit. Each queue must be disabled. */ + number_of_queues = hw->mac.max_tx_queues; +for (i =0 ; i < number_of_queues; i++) { + reg_val =IXGBE_READ_REG (hw,IXGBE_VFTXDCTL (i)); +if (reg_val &IXGBE_TXDCTL_ENABLE ) { + reg_val &= ~IXGBE_TXDCTL_ENABLE ; +IXGBE_WRITE_REG (hw,IXGBE_VFTXDCTL (i), reg_val); + } + } + +return 0 ; +} + +/** +* ixgbevf_mta_vector - Determines bit-vector in multicast table to set +* @hw: pointer to hardware structure +* @mc_addr: the multicast address +* +* Extracts the 12 bits, from a multicast address, to determine which +* bit-vector to set in the multicast table. The hardware uses 12 bits, from +* incoming rx multicast addresses, to determine the bit-vector to check in +* the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set +* by the MO field of the MCSTCTRL. The MO field is set during initialization +* to mc_filter_type. +**/ +static s32 ixgbevf_mta_vector (struct ixgbe_hw *hw,u8 *mc_addr) +{ +u32 vector =0 ; + +switch (hw->mac.mc_filter_type) { +case 0 :/* use bits [47:36] of the address */ + vector = ((mc_addr[4 ] >>4 ) | (((u16 )mc_addr[5 ]) <<4 )); +break ; +case 1 :/* use bits [46:35] of the address */ + vector = ((mc_addr[4 ] >>3 ) | (((u16 )mc_addr[5 ]) <<5 )); +break ; +case 2 :/* use bits [45:34] of the address */ + vector = ((mc_addr[4 ] >>2 ) | (((u16 )mc_addr[5 ]) <<6 )); +break ; +case 3 :/* use bits [43:32] of the address */ + vector = ((mc_addr[4 ]) | (((u16 )mc_addr[5 ]) <<8 )); +break ; +default :/* Invalid mc_filter_type */ +break ; + } + +/* vector can only be 12-bits or boundary will be exceeded */ + vector &=0xFFF ; +return vector; +} + +/** +* ixgbevf_get_mac_addr_vf - Read device MAC address +* @hw: pointer to the HW structure +* @mac_addr: pointer to storage for retrieved MAC address +**/ +static s32 ixgbevf_get_mac_addr_vf (struct ixgbe_hw *hw,u8 *mac_addr) +{ +memcpy (mac_addr, hw->mac.perm_addr,IXGBE_ETH_LENGTH_OF_ADDRESS ); + +return 0 ; +} + +/** +* ixgbevf_set_rar_vf - set device MAC address +* @hw: pointer to hardware structure +* @index: Receive address register to write +* @addr: Address to put into receive address register +* @vmdq: Unused in this implementation +**/ +static s32 ixgbevf_set_rar_vf (struct ixgbe_hw *hw,u32 index,u8 *addr, +u32 vmdq) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +u32 msgbuf[3 ]; +u8 *msg_addr = (u8 *)(&msgbuf[1 ]); +s32 ret_val; + +memset (msgbuf,0 ,sizeof (msgbuf)); + msgbuf[0 ] =IXGBE_VF_SET_MAC_ADDR ; +memcpy (msg_addr, addr,6 ); + ret_val = mbx->ops.write_posted (hw, msgbuf,3 ); + +if (!ret_val) + ret_val = mbx->ops.read_posted (hw, msgbuf,3 ); + + msgbuf[0 ] &= ~IXGBE_VT_MSGTYPE_CTS ; + +/* if nacked the address was rejected, use "perm_addr" */ +if (!ret_val && + (msgbuf[0 ] == (IXGBE_VF_SET_MAC_ADDR |IXGBE_VT_MSGTYPE_NACK ))) +ixgbevf_get_mac_addr_vf (hw, hw->mac.addr); + +return ret_val; +} + +/** +* ixgbevf_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 +* @next: caller supplied function to return next address in list +* +* Updates the Multicast Table Array. +**/ +static s32 ixgbevf_update_mc_addr_list_vf (struct ixgbe_hw *hw,u8 *mc_addr_list, +u32 mc_addr_count, +ixgbe_mc_addr_itr next) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +u32 msgbuf[IXGBE_VFMAILBOX_SIZE ]; +u16 *vector_list = (u16 *)&msgbuf[1 ]; +u32 vector; +u32 cnt, i; +u32 vmdq; + +/* 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. +*/ + + cnt = (mc_addr_count >30 ) ?30 : mc_addr_count; + msgbuf[0 ] =IXGBE_VF_SET_MULTICAST ; + msgbuf[0 ] |= cnt <<IXGBE_VT_MSGINFO_SHIFT ; + +for (i =0 ; i < cnt; i++) { + vector =ixgbevf_mta_vector (hw,next (hw, &mc_addr_list, &vmdq)); + vector_list[i] = vector; + } + + mbx->ops.write_posted (hw, msgbuf,IXGBE_VFMAILBOX_SIZE ); + +return 0 ; +} + +/** +* ixgbevf_set_vfta_vf - Set/Unset vlan filter table address +* @hw: pointer to the HW structure +* @vlan: 12 bit VLAN ID +* @vind: unused by VF drivers +* @vlan_on: if true then set bit, else clear bit +**/ +static s32 ixgbevf_set_vfta_vf (struct ixgbe_hw *hw,u32 vlan,u32 vind, +bool vlan_on) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +u32 msgbuf[2 ]; + + msgbuf[0 ] =IXGBE_VF_SET_VLAN ; + msgbuf[1 ] = vlan; +/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ + msgbuf[0 ] |= vlan_on <<IXGBE_VT_MSGINFO_SHIFT ; + +return mbx->ops.write_posted (hw, msgbuf,2 ); +} + +/** +* ixgbevf_setup_mac_link_vf - Setup MAC link settings +* @hw: pointer to hardware structure +* @speed: Unused in this implementation +* @autoneg: Unused in this implementation +* @autoneg_wait_to_complete: Unused in this implementation +* +* Do nothing and return success. VF drivers are not allowed to change +* global settings. Maintained for driver compatibility. +**/ +static s32 ixgbevf_setup_mac_link_vf (struct ixgbe_hw *hw, +ixgbe_link_speed speed,bool autoneg, +bool autoneg_wait_to_complete) +{ +return 0 ; +} + +/** +* ixgbevf_check_mac_link_vf - Get link/speed status +* @hw: pointer to hardware structure +* @speed: pointer to link speed +* @link_up: true is link is up, false otherwise +* @autoneg_wait_to_complete: true when waiting for completion is needed +* +* Reads the links register to determine if link is up and the current speed +**/ +static s32 ixgbevf_check_mac_link_vf (struct ixgbe_hw *hw, +ixgbe_link_speed *speed, +bool *link_up, +bool autoneg_wait_to_complete) +{ +u32 links_reg; + +if (!(hw->mbx.ops.check_for_rst (hw))) { + *link_up = false; + *speed =0 ; +return -1 ; + } + + links_reg =IXGBE_READ_REG (hw,IXGBE_VFLINKS ); + +if (links_reg &IXGBE_LINKS_UP ) + *link_up = true; +else + *link_up = false; + +if (links_reg &IXGBE_LINKS_SPEED ) + *speed =IXGBE_LINK_SPEED_10GB_FULL ; +else + *speed =IXGBE_LINK_SPEED_1GB_FULL ; + +return 0 ; +} + +struct ixgbe_mac_operations ixgbevf_mac_ops = { + .init_hw = ixgbevf_init_hw_vf, + .reset_hw = ixgbevf_reset_hw_vf, + .start_hw = ixgbevf_start_hw_vf, + .get_mac_addr = ixgbevf_get_mac_addr_vf, + .stop_adapter = ixgbevf_stop_hw_vf, + .setup_link = ixgbevf_setup_mac_link_vf, + .check_link = ixgbevf_check_mac_link_vf, + .set_rar = ixgbevf_set_rar_vf, + .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf, + .set_vfta = ixgbevf_set_vfta_vf, +}; + +struct ixgbevf_info ixgbevf_vf_info = { + .mac = ixgbe_mac_82599_vf, + .mac_ops = &ixgbevf_mac_ops, +}; +
drivers/net/ixgbevf/vf.h new file +168 -0
168 lines not on this page · raw message
PATCH 3/13 ixgbevf: Mailbox communication
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
The 82599 virtual function device and the master 82599 physical function device implement a mailbox utility for communication between the devices using some SRAM scratch memory and a doorbell/answering mechanism enabled via interrupt and/or polling. This C module and accompanying header file implement the base functions for use of this feature.
---
drivers/net/ixgbevf/mbx.c | 341 +++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/mbx.h | 100 +++++++++++++ 2 files changed, 441 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbevf/mbx.c create mode 100644 drivers/net/ixgbevf/mbx.h
drivers/net/ixgbevf/mbx.c new file +341 -0
@@ -0,0 +1,341 @@ +/******************************************************************************* + +Intel 82599 Virtual Function driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "mbx.h" + +/** +* ixgbevf_poll_for_msg - Wait for message notification +* @hw: pointer to the HW structure +* +* returns 0 if it successfully received a message notification +**/ +static s32 ixgbevf_poll_for_msg (struct ixgbe_hw *hw) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +int countdown = mbx->timeout; + +while (countdown && mbx->ops.check_for_msg (hw)) { + countdown--; +udelay (mbx->udelay); + } + +/* if we failed, all future posted messages fail until reset */ +if (!countdown) + mbx->timeout =0 ; + +return countdown ?0 :IXGBE_ERR_MBX ; +} + +/** +* ixgbevf_poll_for_ack - Wait for message acknowledgement +* @hw: pointer to the HW structure +* +* returns 0 if it successfully received a message acknowledgement +**/ +static s32 ixgbevf_poll_for_ack (struct ixgbe_hw *hw) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +int countdown = mbx->timeout; + +while (countdown && mbx->ops.check_for_ack (hw)) { + countdown--; +udelay (mbx->udelay); + } + +/* if we failed, all future posted messages fail until reset */ +if (!countdown) + mbx->timeout =0 ; + +return countdown ?0 :IXGBE_ERR_MBX ; +} + +/** +* ixgbevf_read_posted_mbx - Wait for message notification and receive message +* @hw: pointer to the HW structure +* @msg: The message buffer +* @size: Length of buffer +* +* returns 0 if it successfully received a message notification and +* copied it into the receive buffer. +**/ +static s32 ixgbevf_read_posted_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + + ret_val =ixgbevf_poll_for_msg (hw); + +/* if ack received read message, otherwise we timed out */ +if (!ret_val) + ret_val = mbx->ops.read (hw, msg, size); + +return ret_val; +} + +/** +* ixgbevf_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 +* +* returns 0 if it successfully copied message into the buffer and +* received an ack to that message within delay * timeout period +**/ +static s32 ixgbevf_write_posted_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val; + +/* send msg */ + ret_val = mbx->ops.write (hw, msg, size); + +/* if msg sent wait until we receive an ack */ +if (!ret_val) + ret_val =ixgbevf_poll_for_ack (hw); + +return ret_val; +} + +/** +* ixgbevf_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 ixgbevf_read_v2p_mailbox (struct ixgbe_hw *hw) +{ +u32 v2p_mailbox =IXGBE_READ_REG (hw,IXGBE_VFMAILBOX ); + + v2p_mailbox |= hw->mbx.v2p_mailbox; + hw->mbx.v2p_mailbox |= v2p_mailbox &IXGBE_VFMAILBOX_R2C_BITS ; + +return v2p_mailbox; +} + +/** +* ixgbevf_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 ixgbevf_check_for_bit_vf (struct ixgbe_hw *hw,u32 mask) +{ +u32 v2p_mailbox =ixgbevf_read_v2p_mailbox (hw); +s32 ret_val =IXGBE_ERR_MBX ; + +if (v2p_mailbox & mask) + ret_val =0 ; + + hw->mbx.v2p_mailbox &= ~mask; + +return ret_val; +} + +/** +* ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail +* @hw: pointer to the HW structure +* +* returns 0 if the PF has set the Status bit or else ERR_MBX +**/ +static s32 ixgbevf_check_for_msg_vf (struct ixgbe_hw *hw) +{ +s32 ret_val =IXGBE_ERR_MBX ; + +if (!ixgbevf_check_for_bit_vf (hw,IXGBE_VFMAILBOX_PFSTS )) { + ret_val =0 ; + hw->mbx.stats.reqs++; + } + +return ret_val; +} + +/** +* ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd +* @hw: pointer to the HW structure +* +* returns 0 if the PF has set the ACK bit or else ERR_MBX +**/ +static s32 ixgbevf_check_for_ack_vf (struct ixgbe_hw *hw) +{ +s32 ret_val =IXGBE_ERR_MBX ; + +if (!ixgbevf_check_for_bit_vf (hw,IXGBE_VFMAILBOX_PFACK )) { + ret_val =0 ; + hw->mbx.stats.acks++; + } + +return ret_val; +} + +/** +* ixgbevf_check_for_rst_vf - checks to see if the PF has reset +* @hw: pointer to the HW structure +* +* returns true if the PF has set the reset done bit or else false +**/ +static s32 ixgbevf_check_for_rst_vf (struct ixgbe_hw *hw) +{ +s32 ret_val =IXGBE_ERR_MBX ; + +if (!ixgbevf_check_for_bit_vf (hw, (IXGBE_VFMAILBOX_RSTD | +IXGBE_VFMAILBOX_RSTI ))) { + ret_val =0 ; + hw->mbx.stats.rsts++; + } + +return ret_val; +} + +/** +* ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock +* @hw: pointer to the HW structure +* +* return 0 if we obtained the mailbox lock +**/ +static s32 ixgbevf_obtain_mbx_lock_vf (struct ixgbe_hw *hw) +{ +s32 ret_val =IXGBE_ERR_MBX ; + +/* Take ownership of the buffer */ +IXGBE_WRITE_REG (hw,IXGBE_VFMAILBOX ,IXGBE_VFMAILBOX_VFU ); + +/* reserve mailbox for vf use */ +if (ixgbevf_read_v2p_mailbox (hw) &IXGBE_VFMAILBOX_VFU ) + ret_val =0 ; + +return ret_val; +} + +/** +* ixgbevf_write_mbx_vf - Write a message to the mailbox +* @hw: pointer to the HW structure +* @msg: The message buffer +* @size: Length of buffer +* +* returns 0 if it successfully copied message into the buffer +**/ +static s32 ixgbevf_write_mbx_vf (struct ixgbe_hw *hw,u32 *msg,u16 size) +{ +s32 ret_val; +u16 i; + + +/* lock the mailbox to prevent pf/vf race condition */ + ret_val =ixgbevf_obtain_mbx_lock_vf (hw); +if (ret_val) + goto out_no_write; + +/* flush msg and acks as we are overwriting the message buffer */ +ixgbevf_check_for_msg_vf (hw); +ixgbevf_check_for_ack_vf (hw); + +/* copy the caller specified message to the mailbox memory buffer */ +for (i =0 ; i < size; i++) +IXGBE_WRITE_REG_ARRAY (hw,IXGBE_VFMBMEM , i, msg[i]); + +/* update stats */ + hw->mbx.stats.msgs_tx++; + +/* Drop VFU and interrupt the PF to tell it a message has been sent */ +IXGBE_WRITE_REG (hw,IXGBE_VFMAILBOX ,IXGBE_VFMAILBOX_REQ ); + +out_no_write: +return ret_val; +} + +/** +* ixgbevf_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 +* +* returns 0 if it successfuly read message from buffer +**/ +static s32 ixgbevf_read_mbx_vf (struct ixgbe_hw *hw,u32 *msg,u16 size) +{ +s32 ret_val =0 ; +u16 i; + +/* lock the mailbox to prevent pf/vf race condition */ + ret_val =ixgbevf_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] =IXGBE_READ_REG_ARRAY (hw,IXGBE_VFMBMEM , i); + +/* Acknowledge receipt and release mailbox, then we're done */ +IXGBE_WRITE_REG (hw,IXGBE_VFMAILBOX ,IXGBE_VFMAILBOX_ACK ); + +/* update stats */ + hw->mbx.stats.msgs_rx++; + +out_no_read: +return ret_val; +} + +/** +* ixgbevf_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 ixgbevf_init_mbx_params_vf (struct ixgbe_hw *hw) +{ +struct ixgbe_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->udelay =IXGBE_VF_MBX_INIT_DELAY ; + + mbx->size =IXGBE_VFMAILBOX_SIZE ; + + mbx->stats.msgs_tx =0 ; + mbx->stats.msgs_rx =0 ; + mbx->stats.reqs =0 ; + mbx->stats.acks =0 ; + mbx->stats.rsts =0 ; + +return 0 ; +} + +struct ixgbe_mbx_operations ixgbevf_mbx_ops = { + .init_params = ixgbevf_init_mbx_params_vf, + .read = ixgbevf_read_mbx_vf, + .write = ixgbevf_write_mbx_vf, + .read_posted = ixgbevf_read_posted_mbx, + .write_posted = ixgbevf_write_posted_mbx, + .check_for_msg = ixgbevf_check_for_msg_vf, + .check_for_ack = ixgbevf_check_for_ack_vf, + .check_for_rst = ixgbevf_check_for_rst_vf, +}; +
drivers/net/ixgbevf/mbx.h new file +100 -0
100 lines not on this page · raw message
PATCH 4/13 ixgbevf: Driver main and ethool interface module and main header
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
These modules and header contain the Linux OS network interface code and core interrupt and network send/receive handlers.
---
drivers/net/ixgbevf/ethtool.c | 716 +++++++ drivers/net/ixgbevf/ixgbevf.h | 318 +++ drivers/net/ixgbevf/ixgbevf_main.c | 3571 ++++++++++++++++++++++++++++++++++++ 3 files changed, 4605 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbevf/ethtool.c create mode 100644 drivers/net/ixgbevf/ixgbevf.h create mode 100644 drivers/net/ixgbevf/ixgbevf_main.c
drivers/net/ixgbevf/ethtool.c new file +716 -0
@@ -0,0 +1,716 @@ +/******************************************************************************* + +Intel 82599 Virtual Function driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* ethtool support for ixgbevf */ + +#include <linux/types.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/ethtool.h> +#include <linux/vmalloc.h> +#include <linux/if_vlan.h> +#include <linux/uaccess.h> + +#include "ixgbevf.h" + +#define IXGBE_ALL_RAR_ENTRIES 16 + +#ifdef ETHTOOL_GSTATS +struct ixgbe_stats { +char stat_string[ETH_GSTRING_LEN ]; +int sizeof_stat; +int stat_offset; +int base_stat_offset; +}; + +#define IXGBEVF_STAT (m, b) sizeof(((struct ixgbevf_adapter *)0)->m), \ + offsetof(struct ixgbevf_adapter, m), \ + offsetof(struct ixgbevf_adapter, b) +static struct ixgbe_stats ixgbe_gstrings_stats[] = { + {"rx_packets" ,IXGBEVF_STAT (stats.vfgprc, stats.base_vfgprc)}, + {"tx_packets" ,IXGBEVF_STAT (stats.vfgptc, stats.base_vfgptc)}, + {"rx_bytes" ,IXGBEVF_STAT (stats.vfgorc, stats.base_vfgorc)}, + {"tx_bytes" ,IXGBEVF_STAT (stats.vfgotc, stats.base_vfgotc)}, + {"tx_busy" ,IXGBEVF_STAT (tx_busy, zero_base)}, + {"multicast" ,IXGBEVF_STAT (stats.vfmprc, stats.base_vfmprc)}, + {"rx_csum_offload_good" ,IXGBEVF_STAT (hw_csum_rx_good, zero_base)}, + {"rx_csum_offload_errors" ,IXGBEVF_STAT (hw_csum_rx_error, zero_base)}, + {"tx_csum_offload_ctxt" ,IXGBEVF_STAT (hw_csum_tx_good, zero_base)}, + {"rx_header_split" ,IXGBEVF_STAT (rx_hdr_split, zero_base)}, +}; + +#define IXGBE_QUEUE_STATS_LEN 0 +#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) + +#define IXGBEVF_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) +#endif /* ETHTOOL_GSTATS */ +#ifdef ETHTOOL_TEST +static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN ] = { +"Register test (offline)" , +"Link test (on/offline)" +}; +#define IXGBE_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) +#endif /* ETHTOOL_TEST */ + +static int ixgbevf_get_settings (struct net_device *netdev, +struct ethtool_cmd *ecmd) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +struct ixgbe_hw *hw = &adapter->hw; +u32 link_speed =0 ; +bool link_up; + + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->autoneg =AUTONEG_DISABLE ; + ecmd->transceiver =XCVR_DUMMY1 ; + ecmd->port =-1 ; + + hw->mac.ops.check_link (hw, &link_speed, &link_up, false); + +if (link_up) { + ecmd->speed = (link_speed ==IXGBE_LINK_SPEED_10GB_FULL ) ? +SPEED_10000 :SPEED_1000 ; + ecmd->duplex =DUPLEX_FULL ; + }else { + ecmd->speed =-1 ; + ecmd->duplex =-1 ; + } + +return 0 ; +} + +static u32 ixgbevf_get_rx_csum (struct net_device *netdev) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +return adapter->flags &IXGBE_FLAG_RX_CSUM_ENABLED ; +} + +static int ixgbevf_set_rx_csum (struct net_device *netdev,u32 data) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +if (data) + adapter->flags |=IXGBE_FLAG_RX_CSUM_ENABLED ; +else + adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED ; + +if (netif_running (netdev)) { +if (!adapter->dev_closed) +ixgbevf_reinit_locked (adapter); + }else { +ixgbevf_reset (adapter); + } + +return 0 ; +} + +static int ixgbevf_set_tso (struct net_device *netdev,u32 data) +{ +if (data) { + netdev->features |=NETIF_F_TSO ; + netdev->features |=NETIF_F_TSO6 ; + }else { +netif_tx_stop_all_queues (netdev); + netdev->features &= ~NETIF_F_TSO ; + netdev->features &= ~NETIF_F_TSO6 ; +netif_tx_start_all_queues (netdev); + } +return 0 ; +} + +static u32 ixgbevf_get_msglevel (struct net_device *netdev) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +return adapter->msg_enable; +} + +static void ixgbevf_set_msglevel (struct net_device *netdev,u32 data) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); + adapter->msg_enable = data; +} + +#define IXGBE_GET_STAT (_A_, _R_) (_A_->stats._R_) + +static char *ixgbevf_reg_names[] = { +"IXGBE_VFCTRL" , +"IXGBE_VFSTATUS" , +"IXGBE_VFLINKS" , +"IXGBE_VFRXMEMWRAP" , +"IXGBE_VFRTIMER" , +"IXGBE_VTEICR" , +"IXGBE_VTEICS" , +"IXGBE_VTEIMS" , +"IXGBE_VTEIMC" , +"IXGBE_VTEIAC" , +"IXGBE_VTEIAM" , +"IXGBE_VTEITR" , +"IXGBE_VTIVAR" , +"IXGBE_VTIVAR_MISC" , +"IXGBE_VFRDBAL0" , +"IXGBE_VFRDBAL1" , +"IXGBE_VFRDBAH0" , +"IXGBE_VFRDBAH1" , +"IXGBE_VFRDLEN0" , +"IXGBE_VFRDLEN1" , +"IXGBE_VFRDH0" , +"IXGBE_VFRDH1" , +"IXGBE_VFRDT0" , +"IXGBE_VFRDT1" , +"IXGBE_VFRXDCTL0" , +"IXGBE_VFRXDCTL1" , +"IXGBE_VFSRRCTL0" , +"IXGBE_VFSRRCTL1" , +"IXGBE_VFPSRTYPE" , +"IXGBE_VFTDBAL0" , +"IXGBE_VFTDBAL1" , +"IXGBE_VFTDBAH0" , +"IXGBE_VFTDBAH1" , +"IXGBE_VFTDLEN0" , +"IXGBE_VFTDLEN1" , +"IXGBE_VFTDH0" , +"IXGBE_VFTDH1" , +"IXGBE_VFTDT0" , +"IXGBE_VFTDT1" , +"IXGBE_VFTXDCTL0" , +"IXGBE_VFTXDCTL1" , +"IXGBE_VFTDWBAL0" , +"IXGBE_VFTDWBAL1" , +"IXGBE_VFTDWBAH0" , +"IXGBE_VFTDWBAH1" +}; + + +static int ixgbevf_get_regs_len (struct net_device *netdev) +{ +return (ARRAY_SIZE (ixgbevf_reg_names)) *sizeof (u32); +} + +static void ixgbevf_get_regs (struct net_device *netdev, +struct ethtool_regs *regs, +void *p) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +struct ixgbe_hw *hw = &adapter->hw; +u32 *regs_buff = p; +u32 regs_len =ixgbevf_get_regs_len (netdev); +u8 i; + +memset (p,0 , regs_len); + + regs->version = (1 <<24 ) | hw->revision_id <<16 | hw->device_id; + +/* General Registers */ + regs_buff[0 ] =IXGBE_READ_REG (hw,IXGBE_VFCTRL ); + regs_buff[1 ] =IXGBE_READ_REG (hw,IXGBE_VFSTATUS ); + regs_buff[2 ] =IXGBE_READ_REG (hw,IXGBE_VFLINKS ); + regs_buff[3 ] =IXGBE_READ_REG (hw,IXGBE_VFRXMEMWRAP ); + regs_buff[4 ] =IXGBE_READ_REG (hw,IXGBE_VFRTIMER ); + +/* Interrupt */ +/* don't read EICR because it can clear interrupt causes, instead +* read EICS which is a shadow but doesn't clear EICR */ + regs_buff[5 ] =IXGBE_READ_REG (hw,IXGBE_VTEICS ); + regs_buff[6 ] =IXGBE_READ_REG (hw,IXGBE_VTEICS ); + regs_buff[7 ] =IXGBE_READ_REG (hw,IXGBE_VTEIMS ); + regs_buff[8 ] =IXGBE_READ_REG (hw,IXGBE_VTEIMC ); + regs_buff[9 ] =IXGBE_READ_REG (hw,IXGBE_VTEIAC ); + regs_buff[10 ] =IXGBE_READ_REG (hw,IXGBE_VTEIAM ); + regs_buff[11 ] =IXGBE_READ_REG (hw,IXGBE_VTEITR (0 )); + regs_buff[12 ] =IXGBE_READ_REG (hw,IXGBE_VTIVAR (0 )); + regs_buff[13 ] =IXGBE_READ_REG (hw,IXGBE_VTIVAR_MISC ); + +/* Receive DMA */ +for (i =0 ; i <2 ; i++) + regs_buff[14 + i] =IXGBE_READ_REG (hw,IXGBE_VFRDBAL (i)); +for (i =0 ; i <2 ; i++) + regs_buff[16 + i] =IXGBE_READ_REG (hw,IXGBE_VFRDBAH (i)); +for (i =0 ; i <2 ; i++) + regs_buff[18 + i] =IXGBE_READ_REG (hw,IXGBE_VFRDLEN (i)); +for (i =0 ; i <2 ; i++) + regs_buff[20 + i] =IXGBE_READ_REG (hw,IXGBE_VFRDH (i)); +for (i =0 ; i <2 ; i++) + regs_buff[22 + i] =IXGBE_READ_REG (hw,IXGBE_VFRDT (i)); +for (i =0 ; i <2 ; i++) + regs_buff[24 + i] =IXGBE_READ_REG (hw,IXGBE_VFRXDCTL (i)); +for (i =0 ; i <2 ; i++) + regs_buff[26 + i] =IXGBE_READ_REG (hw,IXGBE_VFSRRCTL (i)); + +/* Receive */ + regs_buff[28 ] =IXGBE_READ_REG (hw,IXGBE_VFPSRTYPE ); + +/* Transmit */ +for (i =0 ; i <2 ; i++) + regs_buff[29 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDBAL (i)); +for (i =0 ; i <2 ; i++) + regs_buff[31 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDBAH (i)); +for (i =0 ; i <2 ; i++) + regs_buff[33 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDLEN (i)); +for (i =0 ; i <2 ; i++) + regs_buff[35 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDH (i)); +for (i =0 ; i <2 ; i++) + regs_buff[37 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDT (i)); +for (i =0 ; i <2 ; i++) + regs_buff[39 + i] =IXGBE_READ_REG (hw,IXGBE_VFTXDCTL (i)); +for (i =0 ; i <2 ; i++) + regs_buff[41 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDWBAL (i)); +for (i =0 ; i <2 ; i++) + regs_buff[43 + i] =IXGBE_READ_REG (hw,IXGBE_VFTDWBAH (i)); + +for (i =0 ; i <ARRAY_SIZE (ixgbevf_reg_names); i++) +hw_dbg (hw,"%s\t%8.8x\n" , ixgbevf_reg_names[i], regs_buff[i]); +} + +static void ixgbevf_get_drvinfo (struct net_device *netdev, +struct ethtool_drvinfo *drvinfo) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); + +strlcpy (drvinfo->driver, ixgbevf_driver_name,32 ); +strlcpy (drvinfo->version, ixgbevf_driver_version,32 ); + +strlcpy (drvinfo->fw_version,"N/A" ,4 ); +strlcpy (drvinfo->bus_info,pci_name (adapter->pdev),32 ); +} + +static void ixgbevf_get_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +struct ixgbevf_ring *tx_ring = adapter->tx_ring; +struct ixgbevf_ring *rx_ring = adapter->rx_ring; + + ring->rx_max_pending =IXGBEVF_MAX_RXD ; + ring->tx_max_pending =IXGBEVF_MAX_TXD ; + ring->rx_mini_max_pending =0 ; + ring->rx_jumbo_max_pending =0 ; + ring->rx_pending = rx_ring->count; + ring->tx_pending = tx_ring->count; + ring->rx_mini_pending =0 ; + ring->rx_jumbo_pending =0 ; +} + +static int ixgbevf_set_ringparam (struct net_device *netdev, +struct ethtool_ringparam *ring) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +struct ixgbevf_ring *tx_ring =NULL , *rx_ring =NULL ; +int i, err; +u32 new_rx_count, new_tx_count; +bool need_tx_update = false; +bool need_rx_update = false; + +if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) +return -EINVAL ; + + new_rx_count =max (ring->rx_pending, (u32 )IXGBEVF_MIN_RXD ); + new_rx_count =min (new_rx_count, (u32 )IXGBEVF_MAX_RXD ); + new_rx_count =ALIGN (new_rx_count,IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE ); + + new_tx_count =max (ring->tx_pending, (u32 )IXGBEVF_MIN_TXD ); + new_tx_count =min (new_tx_count, (u32 )IXGBEVF_MAX_TXD ); + new_tx_count =ALIGN (new_tx_count,IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE ); + +if ((new_tx_count == adapter->tx_ring->count) && + (new_rx_count == adapter->rx_ring->count)) { +/* nothing to do */ +return 0 ; + } + +while (test_and_set_bit (__IXGBEVF_RESETTING, &adapter->state)) +msleep (1 ); + +if (new_tx_count != adapter->tx_ring_count) { + tx_ring =kcalloc (adapter->num_tx_queues, +sizeof (struct ixgbevf_ring ),GFP_KERNEL ); +if (!tx_ring) { + err = -ENOMEM ; + goto err_setup; + } +memcpy (tx_ring, adapter->tx_ring, + adapter->num_tx_queues *sizeof (struct ixgbevf_ring )); +for (i =0 ; i < adapter->num_tx_queues; i++) { + tx_ring[i].count = new_tx_count; + err =ixgbevf_setup_tx_resources (adapter, + &tx_ring[i]); +if (err) { +while (i) { + i--; +ixgbevf_free_tx_resources (adapter, + &tx_ring[i]); + } +kfree (tx_ring); + goto err_setup; + } + tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; + } + need_tx_update = true; + } + +if (new_rx_count != adapter->rx_ring_count) { + rx_ring =kcalloc (adapter->num_rx_queues, +sizeof (struct ixgbevf_ring ),GFP_KERNEL ); +if ((!rx_ring) && (need_tx_update)) { + err = -ENOMEM ; + goto err_rx_setup; + } +memcpy (rx_ring, adapter->rx_ring, + adapter->num_rx_queues *sizeof (struct ixgbevf_ring )); +for (i =0 ; i < adapter->num_rx_queues; i++) { + rx_ring[i].count = new_rx_count; + err =ixgbevf_setup_rx_resources (adapter, + &rx_ring[i]); +if (err) { +while (i) { + i--; +ixgbevf_free_rx_resources (adapter, + &rx_ring[i]); + } +kfree (rx_ring); + goto err_rx_setup; + } + rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; + } + need_rx_update = true; + } + +err_rx_setup: +/* if rings need to be updated, here's the place to do it in one shot */ +if (need_tx_update || need_rx_update) { +if (netif_running (netdev)) +ixgbevf_down (adapter); + } + +/* tx */ +if (need_tx_update) { +kfree (adapter->tx_ring); + adapter->tx_ring = tx_ring; + tx_ring =NULL ; + adapter->tx_ring_count = new_tx_count; + } + +/* rx */ +if (need_rx_update) { +kfree (adapter->rx_ring); + adapter->rx_ring = rx_ring; + rx_ring =NULL ; + adapter->rx_ring_count = new_rx_count; + } + +/* success! */ + err =0 ; +if (netif_running (netdev)) +ixgbevf_up (adapter); + +err_setup: +clear_bit (__IXGBEVF_RESETTING, &adapter->state); +return err; +} + +static int ixgbevf_get_sset_count (struct net_device *dev,int stringset) +{ +switch (stringset) { +case ETH_SS_TEST : +return IXGBE_TEST_LEN ; +case ETH_SS_STATS : +return IXGBE_GLOBAL_STATS_LEN ; +default : +return -EINVAL ; + } +} + +static void ixgbevf_get_ethtool_stats (struct net_device *netdev, +struct ethtool_stats *stats,u64 *data) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +int i; + +ixgbevf_update_stats (adapter); +for (i =0 ; i <IXGBE_GLOBAL_STATS_LEN ; i++) { +char *p = (char *)adapter + + ixgbe_gstrings_stats[i].stat_offset; +char *b = (char *)adapter + + ixgbe_gstrings_stats[i].base_stat_offset; + data[i] = ((ixgbe_gstrings_stats[i].sizeof_stat == +sizeof (u64)) ? *(u64 *)p : *(u32 *)p) - + ((ixgbe_gstrings_stats[i].sizeof_stat == +sizeof (u64)) ? *(u64 *)b : *(u32 *)b); + } +} + +static void ixgbevf_get_strings (struct net_device *netdev,u32 stringset, +u8 *data) +{ +char *p = (char *)data; +int i; + +switch (stringset) { +case ETH_SS_TEST : +memcpy (data, *ixgbe_gstrings_test, +IXGBE_TEST_LEN *ETH_GSTRING_LEN ); +break ; +case ETH_SS_STATS : +for (i =0 ; i <IXGBE_GLOBAL_STATS_LEN ; i++) { +memcpy (p, ixgbe_gstrings_stats[i].stat_string, +ETH_GSTRING_LEN ); + p +=ETH_GSTRING_LEN ; + } +break ; + } +} + +static int ixgbevf_link_test (struct ixgbevf_adapter *adapter,u64 *data) +{ +struct ixgbe_hw *hw = &adapter->hw; +bool link_up; +u32 link_speed =0 ; + *data =0 ; + + hw->mac.ops.check_link (hw, &link_speed, &link_up, true); +if (!link_up) + *data =1 ; + +return *data; +} + +/* ethtool register test data */ +struct ixgbevf_reg_test { +u16 reg; +u8 array_len; +u8 test_type; +u32 mask; +u32 write; +}; + +/* In the hardware, registers are laid out either singly, in arrays +* spaced 0x40 bytes apart, or in contiguous tables. We assume +* most tests take place on arrays or single registers (handled +* as a single-element array) and special-case the tables. +* Table tests are always pattern tests. +* +* We also make provision for some required setup steps by specifying +* registers to be written without any read-back testing. +*/ + +#define PATTERN_TEST 1 +#define SET_READ_TEST 2 +#define WRITE_NO_TEST 3 +#define TABLE32_TEST 4 +#define TABLE64_TEST_LO 5 +#define TABLE64_TEST_HI 6 + +/* default VF register test */ +static struct ixgbevf_reg_test reg_test_vf[] = { + {IXGBE_VFRDBAL (0 ),2 ,PATTERN_TEST ,0xFFFFFF80 ,0xFFFFFF80 }, + {IXGBE_VFRDBAH (0 ),2 ,PATTERN_TEST ,0xFFFFFFFF ,0xFFFFFFFF }, + {IXGBE_VFRDLEN (0 ),2 ,PATTERN_TEST ,0x000FFF80 ,0x000FFFFF }, + {IXGBE_VFRXDCTL (0 ),2 ,WRITE_NO_TEST ,0 ,IXGBE_RXDCTL_ENABLE }, + {IXGBE_VFRDT (0 ),2 ,PATTERN_TEST ,0x0000FFFF ,0x0000FFFF }, + {IXGBE_VFRXDCTL (0 ),2 ,WRITE_NO_TEST ,0 ,0 }, + {IXGBE_VFTDBAL (0 ),2 ,PATTERN_TEST ,0xFFFFFF80 ,0xFFFFFFFF }, + {IXGBE_VFTDBAH (0 ),2 ,PATTERN_TEST ,0xFFFFFFFF ,0xFFFFFFFF }, + {IXGBE_VFTDLEN (0 ),2 ,PATTERN_TEST ,0x000FFF80 ,0x000FFF80 }, + {0 ,0 ,0 ,0 } +}; + +#define REG_PATTERN_TEST (R ,M ,W ) \ +{ \ + u32 pat, val, before; \ + const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ + for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { \ + before = readl(adapter->hw.hw_addr + R); \ + writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if (val != (_test[pat] & W & M)) { \ + hw_dbg(&adapter->hw, \ + "pattern test reg %04X failed: got " \ + "0x%08X expected 0x%08X\n", \ + R, val, (_test[pat] & W & M)); \ + *data = R; \ + writel(before, adapter->hw.hw_addr + R); \ + return 1; \ + } \ + writel(before, adapter->hw.hw_addr + R); \ + } \ +} + +#define REG_SET_AND_CHECK (R ,M ,W ) \ +{ \ + u32 val, before; \ + before = readl(adapter->hw.hw_addr + R); \ + writel((W & M), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if ((W & M) != (val & M)) { \ + printk(KERN_ERR "set/check reg %04X test failed: got 0x%08X " \ + "expected 0x%08X\n", R, (val & M), (W & M)); \ + *data = R; \ + writel(before, (adapter->hw.hw_addr + R)); \ + return 1; \ + } \ + writel(before, (adapter->hw.hw_addr + R)); \ +} + +static int ixgbevf_reg_test (struct ixgbevf_adapter *adapter,u64 *data) +{ +struct ixgbevf_reg_test *test; +u32 i; + + test = reg_test_vf; + +/* +* Perform the register test, looping through the test table +* until we either fail or reach the null entry. +*/ +while (test->reg) { +for (i =0 ; i < test->array_len; i++) { +switch (test->test_type) { +case PATTERN_TEST : +REG_PATTERN_TEST (test->reg + (i *0x40 ), + test->mask, + test->write); +break ; +case SET_READ_TEST : +REG_SET_AND_CHECK (test->reg + (i *0x40 ), + test->mask, + test->write); +break ; +case WRITE_NO_TEST : +writel (test->write, + (adapter->hw.hw_addr + test->reg) + + (i *0x40 )); +break ; +case TABLE32_TEST : +REG_PATTERN_TEST (test->reg + (i *4 ), + test->mask, + test->write); +break ; +case TABLE64_TEST_LO : +REG_PATTERN_TEST (test->reg + (i *8 ), + test->mask, + test->write); +break ; +case TABLE64_TEST_HI : +REG_PATTERN_TEST ((test->reg +4 ) + (i *8 ), + test->mask, + test->write); +break ; + } + } + test++; + } + + *data =0 ; +return *data; +} + +static void ixgbevf_diag_test (struct net_device *netdev, +struct ethtool_test *eth_test,u64 *data) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); +bool if_running =netif_running (netdev); + +set_bit (__IXGBEVF_TESTING, &adapter->state); +if (eth_test->flags ==ETH_TEST_FL_OFFLINE ) { +/* Offline tests */ + +hw_dbg (&adapter->hw,"offline testing starting\n" ); + +/* Link test performed before hardware reset so autoneg doesn't +* interfere with test result */ +if (ixgbevf_link_test (adapter, &data[1 ])) + eth_test->flags |=ETH_TEST_FL_FAILED ; + +if (if_running) +/* indicate we're in test mode */ +dev_close (netdev); +else +ixgbevf_reset (adapter); + +hw_dbg (&adapter->hw,"register testing starting\n" ); +if (ixgbevf_reg_test (adapter, &data[0 ])) + eth_test->flags |=ETH_TEST_FL_FAILED ; + +ixgbevf_reset (adapter); + +clear_bit (__IXGBEVF_TESTING, &adapter->state); +if (if_running) +dev_open (netdev); + }else { +hw_dbg (&adapter->hw,"online testing starting\n" ); +/* Online tests */ +if (ixgbevf_link_test (adapter, &data[1 ])) + eth_test->flags |=ETH_TEST_FL_FAILED ; + +/* Online tests aren't run; pass by default */ + data[0 ] =0 ; + +clear_bit (__IXGBEVF_TESTING, &adapter->state); + } +msleep_interruptible (4 *1000 ); +} + +static int ixgbevf_nway_reset (struct net_device *netdev) +{ +struct ixgbevf_adapter *adapter =netdev_priv (netdev); + +if (netif_running (netdev)) { +if (!adapter->dev_closed) +ixgbevf_reinit_locked (adapter); + } + +return 0 ; +} + +static struct ethtool_ops ixgbevf_ethtool_ops = { + .get_settings = ixgbevf_get_settings, + .get_drvinfo = ixgbevf_get_drvinfo, + .get_regs_len = ixgbevf_get_regs_len, + .get_regs = ixgbevf_get_regs, + .nway_reset = ixgbevf_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = ixgbevf_get_ringparam, + .set_ringparam = ixgbevf_set_ringparam, + .get_rx_csum = ixgbevf_get_rx_csum, + .set_rx_csum = ixgbevf_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_ipv6_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_msglevel = ixgbevf_get_msglevel, + .set_msglevel = ixgbevf_set_msglevel, + .get_tso = ethtool_op_get_tso, + .set_tso = ixgbevf_set_tso, + .self_test = ixgbevf_diag_test, + .get_sset_count = ixgbevf_get_sset_count, + .get_strings = ixgbevf_get_strings, + .get_ethtool_stats = ixgbevf_get_ethtool_stats, +}; + +void ixgbevf_set_ethtool_ops (struct net_device *netdev) +{ +SET_ETHTOOL_OPS (netdev, &ixgbevf_ethtool_ops); +}
drivers/net/ixgbevf/ixgbevf.h new file +318 -0
318 lines not on this page · raw message
drivers/net/ixgbevf/ixgbevf_main.c new file +3571 -0
1,966 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH 5/13 ixgbevf: Driver Makefile
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
82599 Virtual Function Device Driver Makefile
---
drivers/net/ixgbevf/Makefile | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbevf/Makefile
drivers/net/ixgbevf/Makefile new file +38 -0
@@ -0,0 +1,38 @@ +################################################################################ +# +# Intel 82599 Virtual Function driver +# Copyright(c) 1999 - 2009 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: +# e1000-devel Mailing List <[email protected]> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# +################################################################################ + +# +# Makefile for the Intel(R) 82599 VF ethernet driver +# + +obj-$(CONFIG_IXGBEVF) += ixgbevf.o + +ixgbevf-objs := vf.o \ + mbx.o \ + ethtool.o \ + ixgbevf_main.o +
PATCH 6/13 ixgbevf: Kconfig, Makefile and Documentation
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
Modifications for the Kconfig and network device Makefile to add the ixgbevf driver module to the kernel plus basic driver documentation.
---
Documentation/networking/ixgbevf.txt | 90 ++++++++++++++++++++++++++++++++++ drivers/net/Kconfig | 22 ++++++++ drivers/net/Makefile | 1 3 files changed, 113 insertions(+), 0 deletions(-) create mode 100755 Documentation/networking/ixgbevf.txt
Documentation/networking/ixgbevf.txt new file +90 -0
@@ -0,0 +1,90 @@ +Linux* Base Driver for Intel(R) Network Connection +================================================== + +November 24, 2009 + +Contents +======== + +- In This Release +- Identifying Your Adapter +- Known Issues/Troubleshooting +- Support + +In This Release +=============== + +This file describes the ixgbevf Linux* Base Driver for Intel Network +Connection. + +The ixgbevf driver supports 82599-based virtual function devices that can only +be activated on kernels with CONFIG_PCI_IOV enabled. + +The ixgbevf driver supports virtual functions generated by the ixgbe driver +with a max_vfs value of 1 or greater. + +The guest OS loading the ixgbevf driver must support MSI-X interrupts. + +VLANs: There is a limit of a total of 32 shared VLANs to 1 or more VFs. + +Identifying Your Adapter +======================== + +For more information on how to identify your adapter, go to the Adapter & +Driver ID Guide at: + + http://support.intel.com/support/network/sb/CS-008441.htm + +Known Issues/Troubleshooting +============================ + + Unloading Physical Function (PF) Driver Causes System Reboots When VM is + Running and VF is Loaded on the VM + ------------------------------------------------------------------------ + Do not unload the PF driver (ixgbe) while VFs are assigned to guests. + +Support +======= + +For general information, go to the Intel support website at: + + http://support.intel.com + +or the Intel Wired Networking project hosted by Sourceforge at: + + http://sourceforge.net/projects/e1000 + +If an issue is identified with the released source code on the supported +kernel with a supported adapter, email the specific information related +to the issue to [email protected] + +License +======= + +Intel 10 Gigabit Linux driver. +Copyright(c) 1999 - 2009 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". + +Trademarks +========== + +Intel, Itanium, and Pentium are trademarks or registered trademarks of +Intel Corporation or its subsidiaries in the United States and other +countries. + +* Other names and brands may be claimed as the property of others.
drivers/net/Kconfig +22 -0
@@ -2618,6 +2618,28 @@ config IXGBE_DCB If unsure, say N. +config IXGBEVF + tristate "Intel(R) 82599 Virtual Function Ethernet support" + depends on PCI_MSI + ---help--- + This driver supports Intel(R) 82599 virtual functions. For more + information on how to identify your adapter, go to the Adapter & + Driver ID Guide at: + + <http://support.intel.com/support/network/sb/CS-008441.htm> + + For general information and support, go to the Intel support + website at: + + <http://support.intel.com> + + More specific information on configuring the driver is in + <file:Documentation/networking/ixgbevf.txt>. + + To compile this driver as a module, choose M here. The module + will be called ixgbevf. MSI-X interrupt support is required + for this driver to work correctly. + config IXGB tristate "Intel(R) PRO/10GbE support" depends on PCI
drivers/net/Makefile +1 -0
@@ -14,6 +14,7 @@ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/ obj-$(CONFIG_IGB) += igb/ obj-$(CONFIG_IGBVF) += igbvf/ obj-$(CONFIG_IXGBE) += ixgbe/ +obj-$(CONFIG_IXGBEVF) += ixgbevf/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_IP1000) += ipg.o obj-$(CONFIG_CHELSIO_T1) += chelsio/
PATCH 7/13 ixgbe: Mailbox header and code module
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
The 82599 virtual function device and the master 82599 physical function device implement a mailbox utility for communication between the devices using some SRAM scratch memory and a doorbell/answering mechanism enabled via interrupt and/or polling. This C module and accompanying header file implement the base functions for use of this feature.
---
drivers/net/ixgbe/ixgbe_mbx.c | 479 +++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_mbx.h | 96 ++++++++ 2 files changed, 575 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbe/ixgbe_mbx.c create mode 100644 drivers/net/ixgbe/ixgbe_mbx.h
drivers/net/ixgbe/ixgbe_mbx.c new file +479 -0
@@ -0,0 +1,479 @@ +/******************************************************************************* + +Intel 10 Gigabit PCI Express Linux driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include <linux/pci.h> +#include <linux/delay.h> +#include "ixgbe_type.h" +#include "ixgbe_common.h" +#include "ixgbe_mbx.h" + +/** +* ixgbe_read_mbx - Reads a message from the mailbox +* @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 +**/ +s32 ixgbe_read_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + +/* limit read to size of mailbox */ +if (size > mbx->size) + size = mbx->size; + +if (mbx->ops.read) + ret_val = mbx->ops.read (hw, msg, size, mbx_id); + +return ret_val; +} + +/** +* ixgbe_write_mbx - 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 +**/ +s32 ixgbe_write_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =0 ; + +if (size > mbx->size) + ret_val =IXGBE_ERR_MBX ; + +else if (mbx->ops.write) + ret_val = mbx->ops.write (hw, msg, size, mbx_id); + +return ret_val; +} + +/** +* ixgbe_check_for_msg - checks to see if someone sent us mail +* @hw: pointer to the HW structure +* @mbx_id: id of mailbox to check +* +* returns SUCCESS if the Status bit was found or else ERR_MBX +**/ +s32 ixgbe_check_for_msg (struct ixgbe_hw *hw,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + +if (mbx->ops.check_for_msg) + ret_val = mbx->ops.check_for_msg (hw, mbx_id); + +return ret_val; +} + +/** +* ixgbe_check_for_ack - checks to see if someone sent us ACK +* @hw: pointer to the HW structure +* @mbx_id: id of mailbox to check +* +* returns SUCCESS if the Status bit was found or else ERR_MBX +**/ +s32 ixgbe_check_for_ack (struct ixgbe_hw *hw,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + +if (mbx->ops.check_for_ack) + ret_val = mbx->ops.check_for_ack (hw, mbx_id); + +return ret_val; +} + +/** +* ixgbe_check_for_rst - checks to see if other side has reset +* @hw: pointer to the HW structure +* @mbx_id: id of mailbox to check +* +* returns SUCCESS if the Status bit was found or else ERR_MBX +**/ +s32 ixgbe_check_for_rst (struct ixgbe_hw *hw,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + +if (mbx->ops.check_for_rst) + ret_val = mbx->ops.check_for_rst (hw, mbx_id); + +return ret_val; +} + +/** +* ixgbe_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 ixgbe_poll_for_msg (struct ixgbe_hw *hw,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +int countdown = mbx->timeout; + +if (!countdown || !mbx->ops.check_for_msg) + goto out; + +while (countdown && mbx->ops.check_for_msg (hw, mbx_id)) { + countdown--; +if (!countdown) +break ; +udelay (mbx->usec_delay); + } + +/* if we failed, all future posted messages fail until reset */ +if (!countdown) + mbx->timeout =0 ; +out: +return countdown ?0 :IXGBE_ERR_MBX ; +} + +/** +* ixgbe_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 ixgbe_poll_for_ack (struct ixgbe_hw *hw,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +int countdown = mbx->timeout; + +if (!countdown || !mbx->ops.check_for_ack) + goto out; + +while (countdown && mbx->ops.check_for_ack (hw, mbx_id)) { + countdown--; +if (!countdown) +break ; +udelay (mbx->usec_delay); + } + +/* if we failed, all future posted messages fail until reset */ +if (!countdown) + mbx->timeout =0 ; +out: +return countdown ?0 :IXGBE_ERR_MBX ; +} + +/** +* ixgbe_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. +**/ +s32 ixgbe_read_posted_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size,u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_MBX ; + +if (!mbx->ops.read) + goto out; + + ret_val =ixgbe_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; +} + +/** +* ixgbe_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 +**/ +s32 ixgbe_write_posted_mbx (struct ixgbe_hw *hw,u32 *msg,u16 size, +u16 mbx_id) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; +s32 ret_val =IXGBE_ERR_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 =ixgbe_poll_for_ack (hw, mbx_id); +out: +return ret_val; +} + +/** +* ixgbe_init_mbx_ops_generic - Initialize MB function pointers +* @hw: pointer to the HW structure +* +* Setup the mailbox read and write message function pointers +**/ +void ixgbe_init_mbx_ops_generic (struct ixgbe_hw *hw) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; + + mbx->ops.read_posted = ixgbe_read_posted_mbx; + mbx->ops.write_posted = ixgbe_write_posted_mbx; +} + +static s32 ixgbe_check_for_bit_pf (struct ixgbe_hw *hw,u32 mask,s32 index) +{ +u32 mbvficr =IXGBE_READ_REG (hw,IXGBE_MBVFICR (index)); +s32 ret_val =IXGBE_ERR_MBX ; + +if (mbvficr & mask) { + ret_val =0 ; +IXGBE_WRITE_REG (hw,IXGBE_MBVFICR (index), mask); + } + +return ret_val; +} + +/** +* ixgbe_check_for_msg_pf - checks to see if the VF has sent mail +* @hw: pointer to the HW structure +* @vf_number: the VF index +* +* returns SUCCESS if the VF has set the Status bit or else ERR_MBX +**/ +static s32 ixgbe_check_for_msg_pf (struct ixgbe_hw *hw,u16 vf_number) +{ +s32 ret_val =IXGBE_ERR_MBX ; +s32 index =IXGBE_MBVFICR_INDEX (vf_number); +u32 vf_bit = vf_number %16 ; + +if (!ixgbe_check_for_bit_pf (hw,IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, + index)) { + ret_val =0 ; + hw->mbx.stats.reqs++; + } + +return ret_val; +} + +/** +* ixgbe_check_for_ack_pf - checks to see if the VF has ACKed +* @hw: pointer to the HW structure +* @vf_number: the VF index +* +* returns SUCCESS if the VF has set the Status bit or else ERR_MBX +**/ +static s32 ixgbe_check_for_ack_pf (struct ixgbe_hw *hw,u16 vf_number) +{ +s32 ret_val =IXGBE_ERR_MBX ; +s32 index =IXGBE_MBVFICR_INDEX (vf_number); +u32 vf_bit = vf_number %16 ; + +if (!ixgbe_check_for_bit_pf (hw,IXGBE_MBVFICR_VFACK_VF1 << vf_bit, + index)) { + ret_val =0 ; + hw->mbx.stats.acks++; + } + +return ret_val; +} + +/** +* ixgbe_check_for_rst_pf - checks to see if the VF has reset +* @hw: pointer to the HW structure +* @vf_number: the VF index +* +* returns SUCCESS if the VF has set the Status bit or else ERR_MBX +**/ +static s32 ixgbe_check_for_rst_pf (struct ixgbe_hw *hw,u16 vf_number) +{ +u32 reg_offset = (vf_number <32 ) ?0 :1 ; +u32 vf_shift = vf_number %32 ; +u32 vflre =0 ; +s32 ret_val =IXGBE_ERR_MBX ; + +if (hw->mac.type == ixgbe_mac_82599EB) + vflre =IXGBE_READ_REG (hw,IXGBE_VFLRE (reg_offset)); + +if (vflre & (1 << vf_shift)) { + ret_val =0 ; +IXGBE_WRITE_REG (hw,IXGBE_VFLREC (reg_offset), (1 << vf_shift)); + hw->mbx.stats.rsts++; + } + +return ret_val; +} + +/** +* ixgbe_obtain_mbx_lock_pf - obtain mailbox lock +* @hw: pointer to the HW structure +* @vf_number: the VF index +* +* return SUCCESS if we obtained the mailbox lock +**/ +static s32 ixgbe_obtain_mbx_lock_pf (struct ixgbe_hw *hw,u16 vf_number) +{ +s32 ret_val =IXGBE_ERR_MBX ; +u32 p2v_mailbox; + +/* Take ownership of the buffer */ +IXGBE_WRITE_REG (hw,IXGBE_PFMAILBOX (vf_number),IXGBE_PFMAILBOX_PFU ); + +/* reserve mailbox for vf use */ + p2v_mailbox =IXGBE_READ_REG (hw,IXGBE_PFMAILBOX (vf_number)); +if (p2v_mailbox &IXGBE_PFMAILBOX_PFU ) + ret_val =0 ; + +return ret_val; +} + +/** +* ixgbe_write_mbx_pf - Places a message in the mailbox +* @hw: pointer to the HW structure +* @msg: The message buffer +* @size: Length of buffer +* @vf_number: the VF index +* +* returns SUCCESS if it successfully copied message into the buffer +**/ +static s32 ixgbe_write_mbx_pf (struct ixgbe_hw *hw,u32 *msg,u16 size, +u16 vf_number) +{ +s32 ret_val; +u16 i; + +/* lock the mailbox to prevent pf/vf race condition */ + ret_val =ixgbe_obtain_mbx_lock_pf (hw, vf_number); +if (ret_val) + goto out_no_write; + +/* flush msg and acks as we are overwriting the message buffer */ +ixgbe_check_for_msg_pf (hw, vf_number); +ixgbe_check_for_ack_pf (hw, vf_number); + +/* copy the caller specified message to the mailbox memory buffer */ +for (i =0 ; i < size; i++) +IXGBE_WRITE_REG_ARRAY (hw,IXGBE_PFMBMEM (vf_number), i, msg[i]); + +/* Interrupt VF to tell it a message has been sent and release buffer*/ +IXGBE_WRITE_REG (hw,IXGBE_PFMAILBOX (vf_number),IXGBE_PFMAILBOX_STS ); + +/* update stats */ + hw->mbx.stats.msgs_tx++; + +out_no_write: +return ret_val; + +} + +/** +* ixgbe_read_mbx_pf - Read a message from the mailbox +* @hw: pointer to the HW structure +* @msg: The message buffer +* @size: Length of buffer +* @vf_number: the VF index +* +* This function copies a message from the mailbox buffer to the caller's +* memory buffer. The presumption is that the caller knows that there was +* a message due to a VF request so no polling for message is needed. +**/ +static s32 ixgbe_read_mbx_pf (struct ixgbe_hw *hw,u32 *msg,u16 size, +u16 vf_number) +{ +s32 ret_val; +u16 i; + +/* lock the mailbox to prevent pf/vf race condition */ + ret_val =ixgbe_obtain_mbx_lock_pf (hw, vf_number); +if (ret_val) + goto out_no_read; + +/* copy the message to the mailbox memory buffer */ +for (i =0 ; i < size; i++) + msg[i] =IXGBE_READ_REG_ARRAY (hw,IXGBE_PFMBMEM (vf_number), i); + +/* Acknowledge the message and release buffer */ +IXGBE_WRITE_REG (hw,IXGBE_PFMAILBOX (vf_number),IXGBE_PFMAILBOX_ACK ); + +/* update stats */ + hw->mbx.stats.msgs_rx++; + +out_no_read: +return ret_val; +} + +/** +* ixgbe_init_mbx_params_pf - set initial values for pf mailbox +* @hw: pointer to the HW structure +* +* Initializes the hw->mbx struct to correct values for pf mailbox +*/ +void ixgbe_init_mbx_params_pf (struct ixgbe_hw *hw) +{ +struct ixgbe_mbx_info *mbx = &hw->mbx; + +if (hw->mac.type != ixgbe_mac_82599EB) +return ; + + mbx->timeout =0 ; + mbx->usec_delay =0 ; + + mbx->size =IXGBE_VFMAILBOX_SIZE ; + + mbx->stats.msgs_tx =0 ; + mbx->stats.msgs_rx =0 ; + mbx->stats.reqs =0 ; + mbx->stats.acks =0 ; + mbx->stats.rsts =0 ; +} + +struct ixgbe_mbx_operations mbx_ops_82599 = { + .read = ixgbe_read_mbx_pf, + .write = ixgbe_write_mbx_pf, + .read_posted = ixgbe_read_posted_mbx, + .write_posted = ixgbe_write_posted_mbx, + .check_for_msg = ixgbe_check_for_msg_pf, + .check_for_ack = ixgbe_check_for_ack_pf, + .check_for_rst = ixgbe_check_for_rst_pf, +}; +
drivers/net/ixgbe/ixgbe_mbx.h new file +96 -0
96 lines not on this page · raw message
PATCH 8/13 ixgbe: Add SR-IOV register, structure and bit defines
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
This patch adds register definitions, bit definitions and structures used by the driver to support SR-IOV features of the 82599 controller.
---
drivers/net/ixgbe/ixgbe.h | 31 ++++++++++++++++++++++- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbe/ixgbe_type.h | 53 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-)
drivers/net/ixgbe/ixgbe.h +29 -2
@@ -98,6 +98,23 @@#define IXGBE_MAX_RSC_INT_RATE 162760 +#define IXGBE_MAX_VF_MC_ENTRIES 30 +#define IXGBE_MAX_VF_FUNCTIONS 64 +#define IXGBE_MAX_VFTA_ENTRIES 128 +#define MAX_EMULATION_MAC_ADDRS 16 +#define VMDQ_P (p) ((p) + adapter->num_vfs) + +struct vf_data_storage { +unsigned char vf_mac_addresses[ETH_ALEN ]; +u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES ]; +u16 num_vf_mc_hashes; +u16 default_vf_vlan_id; +u16 vlans_enabled; +unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS *ETH_ALEN ]; +bool clear_to_send; +int rar; +}; +/* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer {
@@ -171,7 +188,7 @@ struct ixgbe_ring {enum ixgbe_ring_f_enum {RING_F_NONE =0 ,RING_F_DCB , -RING_F_VMDQ , +RING_F_VMDQ ,/* SR-IOV uses the same ring feature */ RING_F_RSS ,RING_F_FDIR ,#ifdef IXGBE_FCOE
@@ -183,7 +200,7 @@ enum ixgbe_ring_f_enum {#define IXGBE_MAX_DCB_INDICES 8#define IXGBE_MAX_RSS_INDICES 16 -#define IXGBE_MAX_VMDQ_INDICES 16 +#define IXGBE_MAX_VMDQ_INDICES 64#define IXGBE_MAX_FDIR_INDICES 64#ifdef IXGBE_FCOE #define IXGBE_MAX_FCOE_INDICES 8
@@ -288,6 +305,8 @@ struct ixgbe_adapter {/* RX */ struct ixgbe_ring *rx_ring____cacheline_aligned_in_smp ;/* One per active queue */ int num_rx_queues; +int num_rx_pools;/* == num_rx_queues in 82598 */ +int num_rx_queues_per_pool;/* 1 if 82598, can be many if 82599 */ u64 hw_csum_rx_error;u64 hw_rx_no_dma_resources;u64 non_eop_descs;
@@ -330,6 +349,8 @@ struct ixgbe_adapter {#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27)#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 28)#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29) +#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 30) +#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 31)u32 flags2;#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
@@ -379,6 +400,11 @@ struct ixgbe_adapter {u64 rsc_total_flush;u32 wol;u16 eeprom_version; + +/* SR-IOV */ +DECLARE_BITMAP (active_vfs,IXGBE_MAX_VF_FUNCTIONS ); +unsigned int num_vfs; +struct vf_data_storage *vfinfo; };enum ixbge_state_t {
@@ -440,6 +466,7 @@ extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte);extern s32 ixgbe_atr_set_l4type_82599 (struct ixgbe_atr_input *input,u8 l4type); +extern void ixgbe_set_rx_mode (struct net_device *netdev);#ifdef IXGBE_FCOE extern void ixgbe_configure_fcoe (struct ixgbe_adapter *adapter); extern int ixgbe_fso(struct ixgbe_adapter *adapter,
drivers/net/ixgbe/ixgbe_main.c +1 -1
@@ -2414,7 +2414,7 @@ static u8 *ixgbe_addr_list_itr(struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq)* responsible for configuring the hardware for proper unicast, multicast and * promiscuous mode. **/ -static void ixgbe_set_rx_mode (struct net_device *netdev) +void ixgbe_set_rx_mode (struct net_device *netdev) {struct ixgbe_adapter *adapter =netdev_priv (netdev);struct ixgbe_hw *hw = &adapter->hw;
drivers/net/ixgbe/ixgbe_type.h +53 -0
113 lines not on this page · raw message
PATCH 9/13 ixgbe: Add SR-IOV specific features
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
This module and header file add functions to support SR-IOV features of the 82599 10Gbe controller.
---
drivers/net/ixgbe/ixgbe_sriov.c | 336 +++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_sriov.h | 45 +++++ 2 files changed, 381 insertions(+), 0 deletions(-) create mode 100644 drivers/net/ixgbe/ixgbe_sriov.c create mode 100644 drivers/net/ixgbe/ixgbe_sriov.h
drivers/net/ixgbe/ixgbe_sriov.c new file +336 -0
@@ -0,0 +1,336 @@ +/******************************************************************************* + +Intel 10 Gigabit PCI Express Linux driver +Copyright(c) 1999 - 2009 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: +e1000-devel Mailing List <[email protected]> +Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +#include <linux/types.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/vmalloc.h> +#include <linux/string.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/ipv6.h> +#ifdef NETIF_F_HW_VLAN_TX +#include <linux/if_vlan.h> +#endif + +#include "ixgbe.h" + +#include "ixgbe_sriov.h" + +int ixgbe_set_vf_multicasts (struct ixgbe_adapter *adapter, +int entries,u16 *hash_list,u32 vf) +{ +struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; +int i; + +/* only so many hash values supported */ + entries =min (entries,IXGBE_MAX_VF_MC_ENTRIES ); + +/* +* salt away the number of multi cast addresses assigned +* to this VF for later use to restore when the PF multi cast +* list changes +*/ + vfinfo->num_vf_mc_hashes = entries; + +/* +* VFs are limited to using the MTA hash table for their multicast +* addresses +*/ +for (i =0 ; i < entries; i++) { + vfinfo->vf_mc_hashes[i] = hash_list[i];; + } + +/* Flush and reset the mta with the new values */ +ixgbe_set_rx_mode (adapter->netdev); + +return 0 ; +} + +void ixgbe_restore_vf_multicasts (struct ixgbe_adapter *adapter) +{ +struct ixgbe_hw *hw = &adapter->hw; +struct vf_data_storage *vfinfo; +int i, j; +u32 vector_bit; +u32 vector_reg; +u32 mta_reg; + +for (i =0 ; i < adapter->num_vfs; i++) { + vfinfo = &adapter->vfinfo[i]; +for (j =0 ; j < vfinfo->num_vf_mc_hashes; j++) { + hw->addr_ctrl.mta_in_use++; + vector_reg = (vfinfo->vf_mc_hashes[j] >>5 ) &0x7F ; + vector_bit = vfinfo->vf_mc_hashes[j] &0x1F ; + mta_reg =IXGBE_READ_REG (hw,IXGBE_MTA (vector_reg)); + mta_reg |= (1 << vector_bit); +IXGBE_WRITE_REG (hw,IXGBE_MTA (vector_reg), mta_reg); + } + } +} + +int ixgbe_set_vf_vlan (struct ixgbe_adapter *adapter,int add,int vid,u32 vf) +{ +u32 ctrl; + +/* Check if global VLAN already set, if not set it */ + ctrl =IXGBE_READ_REG (&adapter->hw,IXGBE_VLNCTRL ); +if (!(ctrl &IXGBE_VLNCTRL_VFE )) { +/* enable VLAN tag insert/strip */ + ctrl |=IXGBE_VLNCTRL_VFE ; + ctrl &= ~IXGBE_VLNCTRL_CFIEN ; +IXGBE_WRITE_REG (&adapter->hw,IXGBE_VLNCTRL , ctrl); + } + +return adapter->hw.mac.ops.set_vfta (&adapter->hw, vid, vf, (bool )add); +} + + +void ixgbe_set_vmolr (struct ixgbe_hw *hw,u32 vf) +{ +u32 vmolr =IXGBE_READ_REG (hw,IXGBE_VMOLR (vf)); + vmolr |= (IXGBE_VMOLR_AUPE | +IXGBE_VMOLR_ROMPE | +IXGBE_VMOLR_ROPE | +IXGBE_VMOLR_BAM ); +IXGBE_WRITE_REG (hw,IXGBE_VMOLR (vf), vmolr); +} + +inline void ixgbe_vf_reset_event (struct ixgbe_adapter *adapter,u32 vf) +{ +struct ixgbe_hw *hw = &adapter->hw; + +/* reset offloads to defaults */ +ixgbe_set_vmolr (hw, vf); + + +/* reset multicast table array for vf */ + adapter->vfinfo[vf].num_vf_mc_hashes =0 ; + +/* Flush and reset the mta with the new values */ +ixgbe_set_rx_mode (adapter->netdev); + +if (adapter->vfinfo[vf].rar >0 ) { + adapter->hw.mac.ops.clear_rar (&adapter->hw, + adapter->vfinfo[vf].rar); + adapter->vfinfo[vf].rar =-1 ; + } +} + +int ixgbe_set_vf_mac (struct ixgbe_adapter *adapter, +int vf,unsigned char *mac_addr) +{ +struct ixgbe_hw *hw = &adapter->hw; + + adapter->vfinfo[vf].rar = hw->mac.ops.set_rar (hw, vf +1 , mac_addr, + vf,IXGBE_RAH_AV ); +if (adapter->vfinfo[vf].rar <0 ) { +DPRINTK (DRV ,ERR ,"Could not set MAC Filter for VF %d\n" , vf); +return -1 ; + } + +memcpy (adapter->vfinfo[vf].vf_mac_addresses, mac_addr,6 ); + +return 0 ; +} + +int ixgbe_vf_configuration (struct pci_dev *pdev,unsigned int event_mask) +{ +unsigned char vf_mac_addr[6 ]; +struct net_device *netdev =pci_get_drvdata (pdev); +struct ixgbe_adapter *adapter =netdev_priv (netdev); +unsigned int vfn = (event_mask &0x3f ); + +bool enable = ((event_mask &0x10000000U ) !=0 ); + +if (enable) { +random_ether_addr (vf_mac_addr); +DPRINTK (PROBE ,INFO ,"IOV: VF %d is enabled " +"mac %02X:%02X:%02X:%02X:%02X:%02X\n" , + vfn, + vf_mac_addr[0 ], vf_mac_addr[1 ], vf_mac_addr[2 ], + vf_mac_addr[3 ], vf_mac_addr[4 ], vf_mac_addr[5 ]); +/* +* Store away the VF "permananet" MAC address, it will ask +* for it later. +*/ +memcpy (adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr,6 ); + } + +return 0 ; +} + +inline void ixgbe_vf_reset_msg (struct ixgbe_adapter *adapter,u32 vf) +{ +struct ixgbe_hw *hw = &adapter->hw; +u32 reg; +u32 reg_offset, vf_shift; + + vf_shift = vf %32 ; + reg_offset = vf /32 ; + +/* enable transmit and receive for vf */ + reg =IXGBE_READ_REG (hw,IXGBE_VFTE (reg_offset)); + reg |= (reg | (1 << vf_shift)); +IXGBE_WRITE_REG (hw,IXGBE_VFTE (reg_offset), reg); + + reg =IXGBE_READ_REG (hw,IXGBE_VFRE (reg_offset)); + reg |= (reg | (1 << vf_shift)); +IXGBE_WRITE_REG (hw,IXGBE_VFRE (reg_offset), reg); + +ixgbe_vf_reset_event (adapter, vf); +} + +static int ixgbe_rcv_msg_from_vf (struct ixgbe_adapter *adapter,u32 vf) +{ +u32 mbx_size =IXGBE_VFMAILBOX_SIZE ; +u32 msgbuf[mbx_size]; +struct ixgbe_hw *hw = &adapter->hw; +s32 retval; +int entries; +u16 *hash_list; +int add, vid; + + retval =ixgbe_read_mbx (hw, msgbuf, mbx_size, vf); + +if (retval) +printk (KERN_ERR "Error receiving message from VF\n" ); + +/* this is a message we already processed, do nothing */ +if (msgbuf[0 ] & (IXGBE_VT_MSGTYPE_ACK |IXGBE_VT_MSGTYPE_NACK )) +return retval; + +/* +* until the vf completes a virtual function reset it should not be +* allowed to start any configuration. +*/ + +if (msgbuf[0 ] ==IXGBE_VF_RESET ) { +unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; +u8 *addr = (u8 *)(&msgbuf[1 ]); +DPRINTK (PROBE ,INFO ,"VF Reset msg received from vf %d\n" , vf); + adapter->vfinfo[vf].clear_to_send = false; +ixgbe_vf_reset_msg (adapter, vf); + adapter->vfinfo[vf].clear_to_send = true; + +/* reply to reset with ack and vf mac address */ + msgbuf[0 ] =IXGBE_VF_RESET |IXGBE_VT_MSGTYPE_ACK ; +memcpy (addr, vf_mac,IXGBE_ETH_LENGTH_OF_ADDRESS ); +/* +* Piggyback the multicast filter type so VF can compute the +* correct vectors +*/ + msgbuf[3 ] = hw->mac.mc_filter_type; +ixgbe_write_mbx (hw, msgbuf,IXGBE_VF_PERMADDR_MSG_LEN , vf); + +return retval; + } + +if (!adapter->vfinfo[vf].clear_to_send) { + msgbuf[0 ] |=IXGBE_VT_MSGTYPE_NACK ; +ixgbe_write_mbx (hw, msgbuf,1 , vf); +return retval; + } + +switch ((msgbuf[0 ] &0xFFFF )) { +case IXGBE_VF_SET_MAC_ADDR : + { +u8 *new_mac = ((u8 *)(&msgbuf[1 ])); +if (is_valid_ether_addr (new_mac)) +ixgbe_set_vf_mac (adapter, vf, new_mac); +else + retval =-1 ; + } +break ; +case IXGBE_VF_SET_MULTICAST : + entries = (msgbuf[0 ] &IXGBE_VT_MSGINFO_MASK ) + >>IXGBE_VT_MSGINFO_SHIFT ; + hash_list = (u16 *)&msgbuf[1 ]; + retval =ixgbe_set_vf_multicasts (adapter, entries, + hash_list, vf); +break ; +case IXGBE_VF_SET_LPE : +WARN_ON ((msgbuf[0 ] &0xFFFF ) ==IXGBE_VF_SET_LPE ); +break ; +case IXGBE_VF_SET_VLAN : + add = (msgbuf[0 ] &IXGBE_VT_MSGINFO_MASK ) + >>IXGBE_VT_MSGINFO_SHIFT ; + vid = (msgbuf[1 ] &IXGBE_VLVF_VLANID_MASK ); + retval =ixgbe_set_vf_vlan (adapter, add, vid, vf); +break ; +default : +DPRINTK (DRV ,ERR ,"Unhandled Msg %8.8x\n" , msgbuf[0 ]); + retval =IXGBE_ERR_MBX ; +break ; + } + +/* notify the VF of the results of what it sent us */ +if (retval) + msgbuf[0 ] |=IXGBE_VT_MSGTYPE_NACK ; +else + msgbuf[0 ] |=IXGBE_VT_MSGTYPE_ACK ; + + msgbuf[0 ] |=IXGBE_VT_MSGTYPE_CTS ; + +ixgbe_write_mbx (hw, msgbuf,1 , vf); + +return retval; +} + +static void ixgbe_rcv_ack_from_vf (struct ixgbe_adapter *adapter,u32 vf) +{ +struct ixgbe_hw *hw = &adapter->hw; +u32 msg =IXGBE_VT_MSGTYPE_NACK ; + +/* if device isn't clear to send it shouldn't be reading either */ +if (!adapter->vfinfo[vf].clear_to_send) +ixgbe_write_mbx (hw, &msg,1 , vf); +} + +void ixgbe_msg_task (struct ixgbe_adapter *adapter) +{ +struct ixgbe_hw *hw = &adapter->hw; +u32 vf; + +for (vf =0 ; vf < adapter->num_vfs; vf++) { +/* process any reset requests */ +if (!ixgbe_check_for_rst (hw, vf)) +ixgbe_vf_reset_event (adapter, vf); + +/* process any messages pending */ +if (!ixgbe_check_for_msg (hw, vf)) +ixgbe_rcv_msg_from_vf (adapter, vf); + +/* process any acks */ +if (!ixgbe_check_for_ack (hw, vf)) +ixgbe_rcv_ack_from_vf (adapter, vf); + } +} +
drivers/net/ixgbe/ixgbe_sriov.h new file +45 -0
45 lines not on this page · raw message
PATCH 10/13 ixgbe: Add SR-IOV specific modules to driver Makefile
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
Add the mailbox and SR-IOV feature modules to the ixgbe driver Makefile.
---
drivers/net/ixgbe/Makefile | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/net/ixgbe/Makefile +2 -1
@@ -33,7 +33,8 @@ obj-$(CONFIG_IXGBE) += ixgbe.o ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ - ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o + ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ + ixgbe_mbx.o ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o
PATCH 11/13 ixgbe: Add SR-IOV feature enablement code
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
Adds code to the core 82599 module to support SR-IOV features of the 82599 network controller
---
drivers/net/ixgbe/ixgbe_82599.c | 126 +++++++++++++++++++++------------------ 1 files changed, 68 insertions(+), 58 deletions(-)
drivers/net/ixgbe/ixgbe_82599.c +68 -58
@@ -31,6 +31,7 @@#include "ixgbe.h" #include "ixgbe_phy.h" +#include "ixgbe_mbx.h" #define IXGBE_82599_MAX_TX_QUEUES 128#define IXGBE_82599_MAX_RX_QUEUES 128
@@ -951,8 +952,6 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)msleep (50 ); - -/* * Store the original AUTOC/AUTOC2 values if they have not been * stored off yet. Otherwise restore the stored original
@@ -1095,9 +1094,11 @@ static s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) {u32 regindex; +u32 vlvf_index;u32 bitindex;u32 bits;u32 first_empty_slot; +u32 vt_ctl;if (vlan >4095 )return IXGBE_ERR_PARAM ;
@@ -1124,76 +1125,84 @@ static s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind,/* Part 2 -* If the vind is set +* If VT mode is set * Either vlan_on * make sure the vlan is in VLVF * set the vind bit in the matching VLVFB * Or !vlan_on * clear the pool bit and possibly the vind */ -if (vind) { -/* find the vlanid or the first empty slot */ - first_empty_slot =0 ; - -for (regindex =1 ; regindex <IXGBE_VLVF_ENTRIES ; regindex++) { - bits =IXGBE_READ_REG (hw,IXGBE_VLVF (regindex)); -if (!bits && !first_empty_slot) - first_empty_slot = regindex; -else if ((bits &0x0FFF ) == vlan) -break ; - } + vt_ctl =IXGBE_READ_REG (hw,IXGBE_VT_CTL ); +if (!(vt_ctl &IXGBE_VT_CTL_VT_ENABLE )) + goto out; -if (regindex >=IXGBE_VLVF_ENTRIES ) { -if (first_empty_slot) - regindex = first_empty_slot; -else { -hw_dbg (hw,"No space in VLVF.\n" ); - goto out; - } +/* find the vlanid or the first empty slot */ + first_empty_slot =0 ; + +for (vlvf_index =1 ; vlvf_index <IXGBE_VLVF_ENTRIES ; vlvf_index++) { + bits =IXGBE_READ_REG (hw,IXGBE_VLVF (vlvf_index)); +if (!bits && !first_empty_slot) + first_empty_slot = vlvf_index; +else if ((bits &0x0FFF ) == vlan) +break ; + } + +if (vlvf_index >=IXGBE_VLVF_ENTRIES ) { +if (first_empty_slot) + vlvf_index = first_empty_slot; +else { +hw_dbg (hw,"No space in VLVF.\n" ); + goto out; } + } -if (vlan_on) { -/* set the pool bit */ -if (vind <32 ) { - bits =IXGBE_READ_REG (hw, -IXGBE_VLVFB (regindex *2 )); - bits |= (1 << vind); -IXGBE_WRITE_REG (hw, -IXGBE_VLVFB (regindex *2 ), bits); - }else { - bits =IXGBE_READ_REG (hw, -IXGBE_VLVFB ((regindex *2 ) +1 )); - bits |= (1 << vind); -IXGBE_WRITE_REG (hw, -IXGBE_VLVFB ((regindex *2 ) +1 ), bits); - } +if (vlan_on) { +/* set the pool bit */ +if (vind <32 ) { + bits =IXGBE_READ_REG (hw, +IXGBE_VLVFB (vlvf_index *2 )); + bits |= (1 << vind); +IXGBE_WRITE_REG (hw, +IXGBE_VLVFB (vlvf_index *2 ), bits); }else { -/* clear the pool bit */ -if (vind <32 ) { - bits =IXGBE_READ_REG (hw, -IXGBE_VLVFB (regindex *2 )); + bits =IXGBE_READ_REG (hw, +IXGBE_VLVFB ((vlvf_index *2 ) +1 )); + bits |= (1 << (vind -32 )); +IXGBE_WRITE_REG (hw, +IXGBE_VLVFB ((vlvf_index *2 ) +1 ), bits); + } + }else { +/* clear the pool bit */ +if (vind <32 ) { + bits =IXGBE_READ_REG (hw, +IXGBE_VLVFB (vlvf_index *2 )); bits &= ~(1 << vind); -IXGBE_WRITE_REG (hw, -IXGBE_VLVFB (regindex *2 ), bits); - bits |=IXGBE_READ_REG (hw, -IXGBE_VLVFB ((regindex *2 ) +1 )); - }else { - bits =IXGBE_READ_REG (hw, -IXGBE_VLVFB ((regindex *2 ) +1 )); - bits &= ~(1 << vind); -IXGBE_WRITE_REG (hw, -IXGBE_VLVFB ((regindex *2 ) +1 ), bits); - bits |=IXGBE_READ_REG (hw, -IXGBE_VLVFB (regindex *2 )); - } +IXGBE_WRITE_REG (hw, +IXGBE_VLVFB (vlvf_index *2 ), bits); + bits |=IXGBE_READ_REG (hw, +IXGBE_VLVFB ((vlvf_index *2 ) +1 )); + }else { + bits =IXGBE_READ_REG (hw, +IXGBE_VLVFB ((vlvf_index *2 ) +1 )); + bits &= ~(1 << (vind -32 )); +IXGBE_WRITE_REG (hw, +IXGBE_VLVFB ((vlvf_index *2 ) +1 ), bits); + bits |=IXGBE_READ_REG (hw, +IXGBE_VLVFB (vlvf_index *2 )); } + } -if (bits) -IXGBE_WRITE_REG (hw,IXGBE_VLVF (regindex), - (IXGBE_VLVF_VIEN | vlan)); -else -IXGBE_WRITE_REG (hw,IXGBE_VLVF (regindex),0 ); +if (bits) { +IXGBE_WRITE_REG (hw,IXGBE_VLVF (vlvf_index), + (IXGBE_VLVF_VIEN | vlan)); +/* if bits is non-zero then some pools/VFs are still +* using this VLAN ID. Force the VFTA entry to on */ + bits =IXGBE_READ_REG (hw,IXGBE_VFTA (regindex)); + bits |= (1 << bitindex); +IXGBE_WRITE_REG (hw,IXGBE_VFTA (regindex), bits); } +else +IXGBE_WRITE_REG (hw,IXGBE_VLVF (vlvf_index),0 ); out:return 0 ;
@@ -2655,4 +2664,5 @@ struct ixgbe_info ixgbe_82599_info = { .mac_ops = &mac_ops_82599, .eeprom_ops = &eeprom_ops_82599, .phy_ops = &phy_ops_82599, + .mbx_ops = &mbx_ops_82599, };
PATCH 12/13 ixgbe: Add SR-IOV features to main module
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
Adds SR-IOV features supported by the 82599 controller to the main driver module. If the CONFIG_PCI_IOV kernel option is selected then the SR-IOV features are enabled. Use the max_vfs module option to allocate up to 63 virtual functions per physical port.
---
drivers/net/ixgbe/ixgbe_main.c | 278 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 268 insertions(+), 10 deletions(-)
drivers/net/ixgbe/ixgbe_main.c +268 -10
@@ -45,6 +45,7 @@#include "ixgbe.h" #include "ixgbe_common.h" #include "ixgbe_dcb_82599.h" +#include "ixgbe_sriov.h" char ixgbe_driver_name[] ="ixgbe" ; static const char ixgbe_driver_string[] =
@@ -124,6 +125,13 @@ static struct notifier_block dca_notifier = { };#endif +#ifdef CONFIG_PCI_IOV +static unsigned int max_vfs; +module_param (max_vfs, uint,0 ); +MODULE_PARM_DESC (max_vfs,"Maximum number of virtual functions to allocate " +"per physical function" ); +#endif /* CONFIG_PCI_IOV */ +MODULE_AUTHOR ("Intel Corporation, <[email protected]>" );MODULE_DESCRIPTION ("Intel(R) 10 Gigabit PCI Express Network Driver" );MODULE_LICENSE ("GPL" );
@@ -131,6 +139,41 @@ MODULE_VERSION(DRV_VERSION);#define DEFAULT_DEBUG_LEVEL_SHIFT 3 +static inline void ixgbe_disable_sriov (struct ixgbe_adapter *adapter) +{ +struct ixgbe_hw *hw = &adapter->hw; +u32 gcr; +u32 gpie; +u32 vmdctl; + +#ifdef CONFIG_PCI_IOV +/* disable iov and allow time for transactions to clear */ +pci_disable_sriov (adapter->pdev); +#endif + +/* turn off device IOV mode */ + gcr =IXGBE_READ_REG (hw,IXGBE_GCR_EXT ); + gcr &= ~(IXGBE_GCR_EXT_SRIOV ); +IXGBE_WRITE_REG (hw,IXGBE_GCR_EXT , gcr); + gpie =IXGBE_READ_REG (hw,IXGBE_GPIE ); + gpie &= ~IXGBE_GPIE_VTMODE_MASK ; +IXGBE_WRITE_REG (hw,IXGBE_GPIE , gpie); + +/* set default pool back to 0 */ + vmdctl =IXGBE_READ_REG (hw,IXGBE_VT_CTL ); + vmdctl &= ~IXGBE_VT_CTL_POOL_MASK ; +IXGBE_WRITE_REG (hw,IXGBE_VT_CTL , vmdctl); + +/* take a breather then clean up driver data */ +msleep (100 ); +if (adapter->vfinfo) +kfree (adapter->vfinfo); + adapter->vfinfo =NULL ; + + adapter->num_vfs =0 ; + adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED ; +} +static void ixgbe_release_hw_control (struct ixgbe_adapter *adapter) {u32 ctrl_ext;
@@ -1025,7 +1068,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)/* set up to autoclear timer, and the vectors */ mask =IXGBE_EIMS_ENABLE_MASK ; - mask &= ~(IXGBE_EIMS_OTHER |IXGBE_EIMS_LSC ); +if (adapter->num_vfs) + mask &= ~(IXGBE_EIMS_OTHER | +IXGBE_EIMS_MAILBOX | +IXGBE_EIMS_LSC ); +else + mask &= ~(IXGBE_EIMS_OTHER |IXGBE_EIMS_LSC );IXGBE_WRITE_REG (&adapter->hw,IXGBE_EIAC , mask); }
@@ -1254,6 +1302,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)if (eicr &IXGBE_EICR_LSC )ixgbe_check_lsc (adapter); +if (eicr &IXGBE_EICR_MAILBOX ) +ixgbe_msg_task (adapter); +if (hw->mac.type == ixgbe_mac_82598EB)ixgbe_check_fan_failure (adapter, eicr);
@@ -1768,6 +1819,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) mask |=IXGBE_EIMS_ECC ; mask |=IXGBE_EIMS_GPI_SDP1 ; mask |=IXGBE_EIMS_GPI_SDP2 ; +if (adapter->num_vfs) + mask |=IXGBE_EIMS_MAILBOX ; }if (adapter->flags &IXGBE_FLAG_FDIR_HASH_CAPABLE || adapter->flags &IXGBE_FLAG_FDIR_PERFECT_CAPABLE )
@@ -1776,6 +1829,11 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)IXGBE_WRITE_REG (&adapter->hw,IXGBE_EIMS , mask);ixgbe_irq_enable_queues (adapter, ~0 );IXGBE_WRITE_FLUSH (&adapter->hw); + +if (adapter->num_vfs >32 ) { +u32 eitrsel = (1 << (adapter->num_vfs -32 )) -1 ; +IXGBE_WRITE_REG (&adapter->hw,IXGBE_EITRSEL , eitrsel); + } }/**
@@ -1905,6 +1963,8 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)IXGBE_WRITE_REG (&adapter->hw,IXGBE_EIMC ,0xFFFF0000 );IXGBE_WRITE_REG (&adapter->hw,IXGBE_EIMC_EX (0 ), ~0 );IXGBE_WRITE_REG (&adapter->hw,IXGBE_EIMC_EX (1 ), ~0 ); +if (adapter->num_vfs >32 ) +IXGBE_WRITE_REG (&adapter->hw,IXGBE_EITRSEL ,0 ); }IXGBE_WRITE_FLUSH (&adapter->hw);if (adapter->flags &IXGBE_FLAG_MSIX_ENABLED ) {
@@ -1989,18 +2049,32 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)if (hw->mac.type == ixgbe_mac_82599EB) {u32 rttdcs; +u32 mask;/* disable the arbiter while setting MTQC */ rttdcs =IXGBE_READ_REG (hw,IXGBE_RTTDCS ); rttdcs |=IXGBE_RTTDCS_ARBDIS ;IXGBE_WRITE_REG (hw,IXGBE_RTTDCS , rttdcs); -/* We enable 8 traffic classes, DCB only */ -if (adapter->flags &IXGBE_FLAG_DCB_ENABLED ) -IXGBE_WRITE_REG (hw,IXGBE_MTQC , (IXGBE_MTQC_RT_ENA | -IXGBE_MTQC_8TC_8TQ )); -else +/* set transmit pool layout */ + mask = (IXGBE_FLAG_SRIOV_ENABLED |IXGBE_FLAG_DCB_ENABLED ); +switch (adapter->flags & mask) { + +case (IXGBE_FLAG_SRIOV_ENABLED ): +IXGBE_WRITE_REG (hw,IXGBE_MTQC , + (IXGBE_MTQC_VT_ENA |IXGBE_MTQC_64VF )); +break ; + +case (IXGBE_FLAG_DCB_ENABLED ): +/* We enable 8 traffic classes, DCB only */ +IXGBE_WRITE_REG (hw,IXGBE_MTQC , + (IXGBE_MTQC_RT_ENA |IXGBE_MTQC_8TC_8TQ )); +break ; + +default :IXGBE_WRITE_REG (hw,IXGBE_MTQC ,IXGBE_MTQC_64Q_1PB ); +break ; + }/* re-eable the arbiter */ rttdcs &= ~IXGBE_RTTDCS_ARBDIS ;
@@ -2059,12 +2133,16 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)#ifdef CONFIG_IXGBE_DCB | IXGBE_FLAG_DCB_ENABLED #endif + |IXGBE_FLAG_SRIOV_ENABLED );switch (mask) {case (IXGBE_FLAG_RSS_ENABLED ): mrqc =IXGBE_MRQC_RSSEN ;break ; +case (IXGBE_FLAG_SRIOV_ENABLED ): + mrqc =IXGBE_MRQC_VMDQEN ; +break ;#ifdef CONFIG_IXGBE_DCB case (IXGBE_FLAG_DCB_ENABLED ): mrqc =IXGBE_MRQC_RT8TCEN ;
@@ -2145,7 +2223,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)int rx_buf_len;/* Decide whether to use packet split mode or not */ - adapter->flags |=IXGBE_FLAG_RX_PS_ENABLED ; +/* Do not use packet split if we're in SR-IOV Mode */ +if (!adapter->num_vfs) + adapter->flags |=IXGBE_FLAG_RX_PS_ENABLED ;/* Set the RX buffer length according to the mode */ if (adapter->flags &IXGBE_FLAG_RX_PS_ENABLED ) {
@@ -2157,7 +2237,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)IXGBE_PSRTYPE_IPV4HDR |IXGBE_PSRTYPE_IPV6HDR |IXGBE_PSRTYPE_L2HDR ; -IXGBE_WRITE_REG (hw,IXGBE_PSRTYPE (0 ), psrtype); +IXGBE_WRITE_REG (hw, +IXGBE_PSRTYPE (adapter->num_vfs), + psrtype); } }else { if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
@@ -2243,6 +2325,30 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)IXGBE_WRITE_REG (hw,IXGBE_RDRXCTL , rdrxctl); } +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) { +u32 vt_reg_bits; +u32 reg_offset, vf_shift; +u32 vmdctl =IXGBE_READ_REG (hw,IXGBE_VT_CTL ); + vt_reg_bits =IXGBE_VMD_CTL_VMDQ_EN + |IXGBE_VT_CTL_REPLEN ; + vt_reg_bits |= (adapter->num_vfs << +IXGBE_VT_CTL_POOL_SHIFT ); +IXGBE_WRITE_REG (hw,IXGBE_VT_CTL , vmdctl | vt_reg_bits); +IXGBE_WRITE_REG (hw,IXGBE_MRQC ,0 ); + + vf_shift = adapter->num_vfs %32 ; + reg_offset = adapter->num_vfs /32 ; +IXGBE_WRITE_REG (hw,IXGBE_VFRE (0 ),0 ); +IXGBE_WRITE_REG (hw,IXGBE_VFRE (1 ),0 ); +IXGBE_WRITE_REG (hw,IXGBE_VFTE (0 ),0 ); +IXGBE_WRITE_REG (hw,IXGBE_VFTE (1 ),0 ); +/* Enable only the PF's pool for Tx/Rx */ +IXGBE_WRITE_REG (hw,IXGBE_VFRE (reg_offset), (1 << vf_shift)); +IXGBE_WRITE_REG (hw,IXGBE_VFTE (reg_offset), (1 << vf_shift)); +IXGBE_WRITE_REG (hw,IXGBE_PFDTXGSWC ,IXGBE_PFDTXGSWC_VT_LBEN ); +ixgbe_set_vmolr (hw, adapter->num_vfs); + } +/* Program MRQC for the distribution of queues */ mrqc =ixgbe_setup_mrqc (adapter);
@@ -2274,6 +2380,20 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) }IXGBE_WRITE_REG (hw,IXGBE_MRQC , mrqc); +if (adapter->num_vfs) { +u32 reg; + +/* Map PF MAC address in RAR Entry 0 to first pool +* following VFs */ + hw->mac.ops.set_vmdq (hw,0 , adapter->num_vfs); + +/* Set up VF register offsets for selected VT Mode, i.e. +* 64 VFs for SR-IOV */ + reg =IXGBE_READ_REG (hw,IXGBE_GCR_EXT ); + reg |=IXGBE_GCR_EXT_SRIOV ; +IXGBE_WRITE_REG (hw,IXGBE_GCR_EXT , reg); + } + rxcsum =IXGBE_READ_REG (hw,IXGBE_RXCSUM ); if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
@@ -2454,6 +2574,8 @@ void ixgbe_set_rx_mode(struct net_device *netdev) addr_list = netdev->mc_list->dmi_addr; hw->mac.ops.update_mc_addr_list (hw, addr_list, addr_count, ixgbe_addr_list_itr); +if (adapter->num_vfs) +ixgbe_restore_vf_multicasts (adapter); }static void ixgbe_napi_enable_all (struct ixgbe_adapter *adapter)
@@ -2714,6 +2836,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)/* MSI only */ gpie =0 ; } +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) { + gpie &= ~IXGBE_GPIE_VTMODE_MASK ; + gpie |=IXGBE_GPIE_VTMODE_64 ; + }/* XXX: to interrupt immediately for EICS writes, enable this */ /* gpie |= IXGBE_GPIE_EIMEN; */ IXGBE_WRITE_REG (hw,IXGBE_GPIE , gpie);
@@ -2788,6 +2914,18 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) txdctl =IXGBE_READ_REG (hw,IXGBE_TXDCTL (j)); txdctl |=IXGBE_TXDCTL_ENABLE ;IXGBE_WRITE_REG (hw,IXGBE_TXDCTL (j), txdctl); +if (hw->mac.type == ixgbe_mac_82599EB) { +int wait_loop =10 ; +/* poll for Tx Enable ready */ +do { +msleep (1 ); + txdctl =IXGBE_READ_REG (hw,IXGBE_TXDCTL (j)); + }while (--wait_loop && + !(txdctl &IXGBE_TXDCTL_ENABLE )); +if (!wait_loop) +DPRINTK (DRV ,ERR ,"Could not enable " +"Tx Queue %d\n" , j); + } }for (i =0 ; i < num_rx_rings; i++) {
@@ -2923,7 +3061,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) }/* reprogram the RAR[0] in case user changed it. */ - hw->mac.ops.set_rar (hw,0 , hw->mac.addr,0 ,IXGBE_RAH_AV ); + hw->mac.ops.set_rar (hw,0 , hw->mac.addr, adapter->num_vfs, +IXGBE_RAH_AV ); }/**
@@ -3291,6 +3430,19 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) }#endif /* IXGBE_FCOE */ +/** +* ixgbe_set_sriov_queues: Allocate queues for IOV use +* @adapter: board private structure to initialize +* +* IOV doesn't actually use anything, so just NAK the +* request for now and let the other queue routines +* figure out what to do. +*/ +static inline bool ixgbe_set_sriov_queues (struct ixgbe_adapter *adapter) +{ +return false; +} +/* * ixgbe_set_num_queues: Allocate queues for device, feature dependant * @adapter: board private structure to initialize
@@ -3304,6 +3456,15 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)**/ static void ixgbe_set_num_queues (struct ixgbe_adapter *adapter) { +/* Start with base case */ + adapter->num_rx_queues =1 ; + adapter->num_tx_queues =1 ; + adapter->num_rx_pools = adapter->num_rx_queues; + adapter->num_rx_queues_per_pool =1 ; + +if (ixgbe_set_sriov_queues (adapter)) +return ; +#ifdef IXGBE_FCOE if (ixgbe_set_fcoe_queues (adapter)) goto done;
@@ -3575,6 +3736,24 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)#endif /* IXGBE_FCOE */ /** +* ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov +* @adapter: board private structure to initialize +* +* SR-IOV doesn't use any descriptor rings but changes the default if +* no other mapping is used. +* +*/ +static inline bool ixgbe_cache_ring_sriov (struct ixgbe_adapter *adapter) +{ + adapter->rx_ring[0 ].reg_idx = adapter->num_vfs *2 ; + adapter->tx_ring[0 ].reg_idx = adapter->num_vfs *2 ; +if (adapter->num_vfs) +return true; +else +return false; +} + +/** * ixgbe_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize *
@@ -3591,6 +3770,9 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) adapter->rx_ring[0 ].reg_idx =0 ; adapter->tx_ring[0 ].reg_idx =0 ; +if (ixgbe_cache_ring_sriov (adapter)) +return ; +#ifdef IXGBE_FCOE if (ixgbe_cache_ring_fcoe (adapter))return ;
@@ -3700,6 +3882,9 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE ; adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE ; adapter->atr_sample_rate =0 ; +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) +ixgbe_disable_sriov (adapter); +ixgbe_set_num_queues (adapter); err =pci_enable_msi (adapter->pdev);
@@ -5484,7 +5669,8 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p)memcpy (netdev->dev_addr, addr->sa_data, netdev->addr_len);memcpy (hw->mac.addr, addr->sa_data, netdev->addr_len); - hw->mac.ops.set_rar (hw,0 , hw->mac.addr,0 ,IXGBE_RAH_AV ); + hw->mac.ops.set_rar (hw,0 , hw->mac.addr, adapter->num_vfs, +IXGBE_RAH_AV );return 0 ; }
@@ -5617,6 +5803,61 @@ static const struct net_device_ops ixgbe_netdev_ops = {#endif /* IXGBE_FCOE */ }; +static void __devinit ixgbe_probe_vf (struct ixgbe_adapter *adapter, +const struct ixgbe_info *ii) +{ +#ifdef CONFIG_PCI_IOV +struct ixgbe_hw *hw = &adapter->hw; +int err; + +if (hw->mac.type != ixgbe_mac_82599EB || !max_vfs) +return ; + +/* The 82599 supports up to 64 VFs per physical function +* but this implementation limits allocation to 63 so that +* basic networking resources are still available to the +* physical function +*/ + adapter->num_vfs = (max_vfs >63 ) ?63 : max_vfs; + adapter->flags |=IXGBE_FLAG_SRIOV_ENABLED ; + err =pci_enable_sriov (adapter->pdev, adapter->num_vfs); +if (err) { +DPRINTK (PROBE ,ERR , +"Failed to enable PCI sriov: %d\n" , err); + goto err_novfs; + } +/* If call to enable VFs succeeded then allocate memory +* for per VF control structures. +*/ + adapter->vfinfo = +kcalloc (adapter->num_vfs, +sizeof (struct vf_data_storage ),GFP_KERNEL ); +if (adapter->vfinfo) { +/* Now that we're sure SR-IOV is enabled +* and memory allocated set up the mailbox parameters +*/ +ixgbe_init_mbx_params_pf (hw); +memcpy (&hw->mbx.ops, ii->mbx_ops, +sizeof (hw->mbx.ops)); + +/* Disable RSC when in SR-IOV mode */ + adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE | +IXGBE_FLAG2_RSC_ENABLED ); +return ; + } + +/* Oh oh */ +DPRINTK (PROBE ,ERR , +"Unable to allocate memory for VF " +"Data Storage - SRIOV disabled\n" ); +pci_disable_sriov (adapter->pdev); + +err_novfs: + adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED ; + adapter->num_vfs =0 ; +#endif /* CONFIG_PCI_IOV */ +} +/** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct
@@ -5791,6 +6032,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, goto err_sw_init; } +ixgbe_probe_vf (adapter, ii); + netdev->features =NETIF_F_SG |NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX |
@@ -5811,6 +6054,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->vlan_features |=NETIF_F_IPV6_CSUM ; netdev->vlan_features |=NETIF_F_SG ; +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) + adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED | +IXGBE_FLAG_DCB_ENABLED );if (adapter->flags &IXGBE_FLAG_DCB_ENABLED ) adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED ;
@@ -5937,6 +6183,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, ixgbe_setup_dca(adapter); }#endif +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) { +DPRINTK (PROBE ,INFO ,"IOV is enabled with %d VFs\n" , + adapter->num_vfs); +for (i =0 ; i < adapter->num_vfs; i++) +ixgbe_vf_configuration (pdev, (i |0x10000000 )); + } +/* add san mac addr to netdev */ ixgbe_add_sanmac_netdev (netdev);
@@ -5949,6 +6202,8 @@ err_register:ixgbe_clear_interrupt_scheme (adapter); err_sw_init: err_eeprom: +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) +ixgbe_disable_sriov (adapter);clear_bit (__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);del_timer_sync (&adapter->sfp_timer);cancel_work_sync (&adapter->sfp_task);
@@ -6017,6 +6272,9 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)if (netdev->reg_state ==NETREG_REGISTERED )unregister_netdev (netdev); +if (adapter->flags &IXGBE_FLAG_SRIOV_ENABLED ) +ixgbe_disable_sriov (adapter); +ixgbe_clear_interrupt_scheme (adapter);ixgbe_release_hw_control (adapter);
PATCH 13/13 ixgbe: Fix ethtool diag test for VT mode operation
In reply to Jeff KirsherFrom: Greg Rose <[email protected]>
Skip MAC loopback test when the adapter is set to a VT mode such as SR-IOV or VMDq
---
drivers/net/ixgbe/ixgbe_ethtool.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
drivers/net/ixgbe/ixgbe_ethtool.c +11 -0
@@ -1867,11 +1867,22 @@ static void ixgbe_diag_test(struct net_device *netdev,if (ixgbe_intr_test (adapter, &data[2 ])) eth_test->flags |=ETH_TEST_FL_FAILED ; +/* If SRIOV or VMDq is enabled then skip MAC +* loopback diagnostic. */ +if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED | +IXGBE_FLAG_VMDQ_ENABLED )) { +DPRINTK (HW ,INFO ,"Skip MAC loopback diagnostic in VT " +"mode\n" ); + data[3 ] =0 ; + goto skip_loopback; + } +ixgbe_reset (adapter);DPRINTK (HW ,INFO ,"loopback testing starting\n" );if (ixgbe_loopback_test (adapter, &data[3 ])) eth_test->flags |=ETH_TEST_FL_FAILED ; +skip_loopback:ixgbe_reset (adapter);clear_bit (__IXGBE_TESTING, &adapter->state);
From: Jeff Kirsher <[email protected]>
Date: Sat, 09 Jan 2010 04:22:54 -0800
Quoted 10 lines
The following series implements the ixgbevf driver. This series of patches has the following known issues:
- ixgbevf multiple load/unload can cause a panic
- loading ixgbevf before ixgbe does not work
- Tx hangs on VF interfaces - this happens when various resets, mostly due to ethtool operations are executed while passing trafficWe are looking for inclusion into net-next-2.6 so that we can get assistance from the community in testing and further development of this driver.
Applied.
We can pull it out if things can't be resolve sufficiently, but I seriously doubt these problems will persist that long :-)