You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
igb: Add support for enabling VFs to PF driver.
This patch adds the support to handle requests from the VF to perform operations such as completing resets, setting/reading mac address, adding vlans, adding multicast addresses, setting rlpml, and general communications between the PF and all VFs. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
e173952257
commit
4ae196dfd6
@@ -33,5 +33,5 @@
|
||||
obj-$(CONFIG_IGB) += igb.o
|
||||
|
||||
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
|
||||
e1000_mac.o e1000_nvm.o e1000_phy.o
|
||||
e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o
|
||||
|
||||
|
||||
@@ -213,6 +213,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
|
||||
return -E1000_ERR_PHY;
|
||||
}
|
||||
|
||||
/* if 82576 then initialize mailbox parameters */
|
||||
if (mac->type == e1000_82576)
|
||||
igb_init_mbx_params_pf(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1413,6 +1417,44 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw)
|
||||
rd32(E1000_MPC);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_vmdq_set_loopback_pf - enable or disable vmdq loopback
|
||||
* @hw: pointer to the hardware struct
|
||||
* @enable: state to enter, either enabled or disabled
|
||||
*
|
||||
* enables/disables L2 switch loopback functionality.
|
||||
**/
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
|
||||
{
|
||||
u32 dtxswc = rd32(E1000_DTXSWC);
|
||||
|
||||
if (enable)
|
||||
dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
|
||||
else
|
||||
dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
|
||||
|
||||
wr32(E1000_DTXSWC, dtxswc);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_vmdq_set_replication_pf - enable or disable vmdq replication
|
||||
* @hw: pointer to the hardware struct
|
||||
* @enable: state to enter, either enabled or disabled
|
||||
*
|
||||
* enables/disables replication of packets across multiple pools.
|
||||
**/
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
|
||||
{
|
||||
u32 vt_ctl = rd32(E1000_VT_CTL);
|
||||
|
||||
if (enable)
|
||||
vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
|
||||
else
|
||||
vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
|
||||
|
||||
wr32(E1000_VT_CTL, vt_ctl);
|
||||
}
|
||||
|
||||
static struct e1000_mac_operations e1000_mac_ops_82575 = {
|
||||
.reset_hw = igb_reset_hw_82575,
|
||||
.init_hw = igb_init_hw_82575,
|
||||
|
||||
@@ -162,6 +162,10 @@ struct e1000_adv_tx_context_desc {
|
||||
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
|
||||
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
|
||||
|
||||
#define MAX_NUM_VFS 8
|
||||
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
|
||||
@@ -181,8 +185,21 @@ struct e1000_adv_tx_context_desc {
|
||||
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
|
||||
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
|
||||
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_VLVF_ARRAY_SIZE 32
|
||||
#define E1000_VLVF_VLANID_MASK 0x00000FFF
|
||||
#define E1000_VLVF_POOLSEL_SHIFT 12
|
||||
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
|
||||
#define E1000_VLVF_LVLAN 0x00100000
|
||||
#define E1000_VLVF_VLANID_ENABLE 0x80000000
|
||||
|
||||
#define E1000_IOVCTL 0x05BBC
|
||||
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
|
||||
|
||||
#define ALL_QUEUES 0xFFFF
|
||||
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
|
||||
/* Extended Device Control */
|
||||
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
|
||||
/* Physical Func Reset Done Indication */
|
||||
#define E1000_CTRL_EXT_PFRSTD 0x00004000
|
||||
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
|
||||
#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
|
||||
#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
|
||||
@@ -325,6 +327,7 @@
|
||||
#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
|
||||
#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
|
||||
#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
|
||||
#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define E1000_ICR_INT_ASSERTED 0x80000000
|
||||
/* LAN connected device generates an interrupt */
|
||||
@@ -362,6 +365,7 @@
|
||||
/* Interrupt Mask Set */
|
||||
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
|
||||
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
|
||||
#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
|
||||
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
|
||||
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
|
||||
@@ -413,6 +417,7 @@
|
||||
#define E1000_BLK_PHY_RESET 12
|
||||
#define E1000_ERR_SWFW_SYNC 13
|
||||
#define E1000_NOT_IMPLEMENTED 14
|
||||
#define E1000_ERR_MBX 15
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
@@ -659,4 +664,8 @@
|
||||
#define E1000_GEN_CTL_ADDRESS_SHIFT 8
|
||||
#define E1000_GEN_POLL_TIMEOUT 640
|
||||
|
||||
#define E1000_VFTA_ENTRY_SHIFT 5
|
||||
#define E1000_VFTA_ENTRY_MASK 0x7F
|
||||
#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_regs.h"
|
||||
#include "e1000_defines.h"
|
||||
|
||||
@@ -272,6 +271,7 @@ struct e1000_host_mng_command_info {
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_phy.h"
|
||||
#include "e1000_nvm.h"
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
@@ -427,6 +427,34 @@ struct e1000_fc_info {
|
||||
enum e1000_fc_type original_type;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*write)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 (*check_for_msg)(struct e1000_hw *, u16);
|
||||
s32 (*check_for_ack)(struct e1000_hw *, u16);
|
||||
s32 (*check_for_rst)(struct e1000_hw *, u16);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_82575 {
|
||||
bool sgmii_active;
|
||||
};
|
||||
@@ -443,6 +471,7 @@ struct e1000_hw {
|
||||
struct e1000_phy_info phy;
|
||||
struct e1000_nvm_info nvm;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_mbx_info mbx;
|
||||
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||
|
||||
union {
|
||||
|
||||
@@ -117,6 +117,30 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
|
||||
wrfl();
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_vfta_set - enable or disable vlan in VLAN filter table
|
||||
* @hw: pointer to the HW structure
|
||||
* @vid: VLAN id to add or remove
|
||||
* @add: if true add filter, if false remove
|
||||
*
|
||||
* Sets or clears a bit in the VLAN filter table array based on VLAN id
|
||||
* and if we are adding or removing the filter
|
||||
**/
|
||||
void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add)
|
||||
{
|
||||
u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
|
||||
u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
|
||||
u32 vfta;
|
||||
|
||||
vfta = array_rd32(E1000_VFTA, index);
|
||||
if (add)
|
||||
vfta |= mask;
|
||||
else
|
||||
vfta &= ~mask;
|
||||
|
||||
igb_write_vfta(hw, index, vfta);
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_check_alt_mac_addr - Check for alternate MAC addr
|
||||
* @hw: pointer to the HW structure
|
||||
|
||||
@@ -58,6 +58,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
|
||||
|
||||
void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
|
||||
void igb_clear_vfta(struct e1000_hw *hw);
|
||||
void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
|
||||
void igb_config_collision_dist(struct e1000_hw *hw);
|
||||
void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
|
||||
void igb_put_hw_semaphore(struct e1000_hw *hw);
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) Gigabit Ethernet Linux driver
|
||||
Copyright(c) 2007-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 <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
/**
|
||||
* igb_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 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (size > mbx->size)
|
||||
ret_val = -E1000_ERR_MBX;
|
||||
|
||||
else if (mbx->ops.write)
|
||||
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_msg)
|
||||
ret_val = mbx->ops.check_for_msg(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_ack)
|
||||
ret_val = mbx->ops.check_for_ack(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbx->ops.check_for_rst)
|
||||
ret_val = mbx->ops.check_for_rst(hw, mbx_id);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (mbx->ops.check_for_msg(hw, mbx_id)) {
|
||||
if (!countdown)
|
||||
break;
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (mbx->ops.check_for_ack(hw, mbx_id)) {
|
||||
if (!countdown)
|
||||
break;
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
out:
|
||||
return countdown ? 0 : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = igb_poll_for_msg(hw, mbx_id);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (!mbx->ops.write)
|
||||
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 = igb_poll_for_ack(hw, mbx_id);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mbx_ops_generic - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups up the function pointers to no-op functions
|
||||
**/
|
||||
void e1000_init_mbx_ops_generic(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
mbx->ops.read_posted = igb_read_posted_mbx;
|
||||
mbx->ops.write_posted = igb_write_posted_mbx;
|
||||
}
|
||||
|
||||
static s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 mbvficr = rd32(E1000_MBVFICR);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (mbvficr & mask) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_MBVFICR, mask);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
|
||||
{
|
||||
u32 vflre = rd32(E1000_VFLRE);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (vflre & (1 << vf_number)) {
|
||||
ret_val = 0;
|
||||
wr32(E1000_VFLRE, (1 << vf_number));
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number)
|
||||
{
|
||||
u32 p2v_mailbox;
|
||||
s32 ret_val = 0;
|
||||
u16 i;
|
||||
|
||||
/* Take ownership of the buffer */
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* Make sure we have ownership now... */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) {
|
||||
/* failed to grab ownership */
|
||||
ret_val = -E1000_ERR_MBX;
|
||||
goto out_no_write;
|
||||
}
|
||||
|
||||
/*
|
||||
* flush any ack or msg which may already be in the queue
|
||||
* as they are likely the result of an error
|
||||
*/
|
||||
igb_check_for_ack_pf(hw, vf_number);
|
||||
igb_check_for_msg_pf(hw, vf_number);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
|
||||
|
||||
/* Interrupt VF to tell it a message has been sent and release buffer*/
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
out_no_write:
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* igb_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 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 vf_number)
|
||||
{
|
||||
u32 p2v_mailbox;
|
||||
s32 ret_val = 0;
|
||||
u16 i;
|
||||
|
||||
/* Take ownership of the buffer */
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
|
||||
|
||||
/* Make sure we have ownership now... */
|
||||
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
|
||||
if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) {
|
||||
/* failed to grab ownership */
|
||||
ret_val = -E1000_ERR_MBX;
|
||||
goto out_no_read;
|
||||
}
|
||||
|
||||
/* copy the message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
|
||||
|
||||
/* Acknowledge the message and release buffer */
|
||||
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
ret_val = 0;
|
||||
|
||||
out_no_read:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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
|
||||
*/
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
if (hw->mac.type == e1000_82576) {
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = 0;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = igb_read_mbx_pf;
|
||||
mbx->ops.write = igb_write_mbx_pf;
|
||||
mbx->ops.read_posted = igb_read_posted_mbx;
|
||||
mbx->ops.write_posted = igb_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = igb_check_for_msg_pf;
|
||||
mbx->ops.check_for_ack = igb_check_for_ack_pf;
|
||||
mbx->ops.check_for_rst = igb_check_for_rst_pf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) Gigabit Ethernet Linux driver
|
||||
Copyright(c) 2007-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 <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_MBX_H_
|
||||
#define _E1000_MBX_H_
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */
|
||||
#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
|
||||
#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
|
||||
|
||||
#define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */
|
||||
#define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */
|
||||
#define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */
|
||||
#define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
|
||||
* this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
|
||||
* this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
|
||||
clear to send requests */
|
||||
#define E1000_VT_MSGINFO_SHIFT 16
|
||||
/* bits 23:16 are used for exra info for certain messages */
|
||||
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_VF_RESET 0x01 /* VF requests reset */
|
||||
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
|
||||
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
|
||||
#define E1000_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
|
||||
#define E1000_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
|
||||
|
||||
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
|
||||
|
||||
s32 igb_read_mbx(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 igb_write_mbx(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 igb_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 igb_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16);
|
||||
s32 igb_check_for_msg(struct e1000_hw *, u16);
|
||||
s32 igb_check_for_ack(struct e1000_hw *, u16);
|
||||
s32 igb_check_for_rst(struct e1000_hw *, u16);
|
||||
s32 igb_init_mbx_params_pf(struct e1000_hw *);
|
||||
|
||||
#endif /* _E1000_MBX_H_ */
|
||||
@@ -321,9 +321,21 @@ enum {
|
||||
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */
|
||||
|
||||
/* VT Registers */
|
||||
#define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */
|
||||
#define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */
|
||||
#define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */
|
||||
#define E1000_VFRE 0x00C8C /* VF Receive Enables */
|
||||
#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
|
||||
#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
|
||||
#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
|
||||
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
|
||||
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
|
||||
/* These act per VF so an array friendly macro is used */
|
||||
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
|
||||
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
|
||||
* Filter - RW */
|
||||
|
||||
#define wr32(reg, value) (writel(value, hw->hw_addr + reg))
|
||||
#define rd32(reg) (readl(hw->hw_addr + reg))
|
||||
|
||||
@@ -62,6 +62,17 @@ struct igb_adapter;
|
||||
#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES
|
||||
#define IGB_ABS_MAX_TX_QUEUES 4
|
||||
|
||||
#define IGB_MAX_VF_MC_ENTRIES 30
|
||||
#define IGB_MAX_VF_FUNCTIONS 8
|
||||
#define IGB_MAX_VFTA_ENTRIES 128
|
||||
|
||||
struct vf_data_storage {
|
||||
unsigned char vf_mac_addresses[ETH_ALEN];
|
||||
u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
|
||||
u16 num_vf_mc_hashes;
|
||||
bool clear_to_send;
|
||||
};
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
@@ -272,6 +283,7 @@ struct igb_adapter {
|
||||
unsigned int tx_ring_count;
|
||||
unsigned int rx_ring_count;
|
||||
unsigned int vfs_allocated_count;
|
||||
struct vf_data_storage *vf_data;
|
||||
};
|
||||
|
||||
#define IGB_FLAG_HAS_MSI (1 << 0)
|
||||
|
||||
+405
-24
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user