Commit 4ae196df authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

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: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e1739522
...@@ -33,5 +33,5 @@ ...@@ -33,5 +33,5 @@
obj-$(CONFIG_IGB) += igb.o obj-$(CONFIG_IGB) += igb.o
igb-objs := igb_main.o igb_ethtool.o e1000_82575.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) ...@@ -213,6 +213,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
return -E1000_ERR_PHY; return -E1000_ERR_PHY;
} }
/* if 82576 then initialize mailbox parameters */
if (mac->type == e1000_82576)
igb_init_mbx_params_pf(hw);
return 0; return 0;
} }
...@@ -1413,6 +1417,44 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw) ...@@ -1413,6 +1417,44 @@ void igb_rx_fifo_flush_82575(struct e1000_hw *hw)
rd32(E1000_MPC); 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 = { static struct e1000_mac_operations e1000_mac_ops_82575 = {
.reset_hw = igb_reset_hw_82575, .reset_hw = igb_reset_hw_82575,
.init_hw = igb_init_hw_82575, .init_hw = igb_init_hw_82575,
......
...@@ -162,6 +162,10 @@ struct e1000_adv_tx_context_desc { ...@@ -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_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 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 */ /* 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_SHIFT 7
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) #define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
...@@ -181,8 +185,21 @@ struct e1000_adv_tx_context_desc { ...@@ -181,8 +185,21 @@ struct e1000_adv_tx_context_desc {
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ #define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ #define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ #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 #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 #endif
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
/* Extended Device Control */ /* Extended Device Control */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ #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_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000
...@@ -325,6 +327,7 @@ ...@@ -325,6 +327,7 @@
#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ #define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ #define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 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 */ /* If this bit asserted, the driver should claim the interrupt */
#define E1000_ICR_INT_ASSERTED 0x80000000 #define E1000_ICR_INT_ASSERTED 0x80000000
/* LAN connected device generates an interrupt */ /* LAN connected device generates an interrupt */
...@@ -362,6 +365,7 @@ ...@@ -362,6 +365,7 @@
/* Interrupt Mask Set */ /* Interrupt Mask Set */
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ #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_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
...@@ -413,6 +417,7 @@ ...@@ -413,6 +417,7 @@
#define E1000_BLK_PHY_RESET 12 #define E1000_BLK_PHY_RESET 12
#define E1000_ERR_SWFW_SYNC 13 #define E1000_ERR_SWFW_SYNC 13
#define E1000_NOT_IMPLEMENTED 14 #define E1000_NOT_IMPLEMENTED 14
#define E1000_ERR_MBX 15
/* Loop limit on how long we wait for auto-negotiation to complete */ /* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10 #define COPPER_LINK_UP_LIMIT 10
...@@ -659,4 +664,8 @@ ...@@ -659,4 +664,8 @@
#define E1000_GEN_CTL_ADDRESS_SHIFT 8 #define E1000_GEN_CTL_ADDRESS_SHIFT 8
#define E1000_GEN_POLL_TIMEOUT 640 #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 #endif
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include "e1000_mac.h"
#include "e1000_regs.h" #include "e1000_regs.h"
#include "e1000_defines.h" #include "e1000_defines.h"
...@@ -272,6 +271,7 @@ struct e1000_host_mng_command_info { ...@@ -272,6 +271,7 @@ struct e1000_host_mng_command_info {
#include "e1000_mac.h" #include "e1000_mac.h"
#include "e1000_phy.h" #include "e1000_phy.h"
#include "e1000_nvm.h" #include "e1000_nvm.h"
#include "e1000_mbx.h"
struct e1000_mac_operations { struct e1000_mac_operations {
s32 (*check_for_link)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *);
...@@ -427,6 +427,34 @@ struct e1000_fc_info { ...@@ -427,6 +427,34 @@ struct e1000_fc_info {
enum e1000_fc_type original_type; 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 { struct e1000_dev_spec_82575 {
bool sgmii_active; bool sgmii_active;
}; };
...@@ -443,6 +471,7 @@ struct e1000_hw { ...@@ -443,6 +471,7 @@ struct e1000_hw {
struct e1000_phy_info phy; struct e1000_phy_info phy;
struct e1000_nvm_info nvm; struct e1000_nvm_info nvm;
struct e1000_bus_info bus; struct e1000_bus_info bus;
struct e1000_mbx_info mbx;
struct e1000_host_mng_dhcp_cookie mng_cookie; struct e1000_host_mng_dhcp_cookie mng_cookie;
union { union {
......
...@@ -117,6 +117,30 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) ...@@ -117,6 +117,30 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
wrfl(); 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 * igb_check_alt_mac_addr - Check for alternate MAC addr
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
......
...@@ -58,6 +58,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, ...@@ -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_hw_cntrs_base(struct e1000_hw *hw);
void igb_clear_vfta(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_config_collision_dist(struct e1000_hw *hw);
void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
void igb_put_hw_semaphore(struct e1000_hw *hw); void igb_put_hw_semaphore(struct e1000_hw *hw);
......
/*******************************************************************************
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;
}
/*******************************************************************************
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 { ...@@ -321,9 +321,21 @@ enum {
#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */ #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */
/* VT Registers */ /* 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_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 */ /* 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_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 wr32(reg, value) (writel(value, hw->hw_addr + reg))
#define rd32(reg) (readl(hw->hw_addr + reg)) #define rd32(reg) (readl(hw->hw_addr + reg))
......
...@@ -62,6 +62,17 @@ struct igb_adapter; ...@@ -62,6 +62,17 @@ struct igb_adapter;
#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES #define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES
#define IGB_ABS_MAX_TX_QUEUES 4 #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. /* RX descriptor control thresholds.
* PTHRESH - MAC will consider prefetch if it has fewer than this number of * PTHRESH - MAC will consider prefetch if it has fewer than this number of
* descriptors available in its onboard memory. * descriptors available in its onboard memory.
...@@ -272,6 +283,7 @@ struct igb_adapter { ...@@ -272,6 +283,7 @@ struct igb_adapter {
unsigned int tx_ring_count; unsigned int tx_ring_count;
unsigned int rx_ring_count; unsigned int rx_ring_count;
unsigned int vfs_allocated_count; unsigned int vfs_allocated_count;
struct vf_data_storage *vf_data;
}; };
#define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_HAS_MSI (1 << 0)
......
...@@ -122,10 +122,16 @@ static void igb_vlan_rx_register(struct net_device *, struct vlan_group *); ...@@ -122,10 +122,16 @@ static void igb_vlan_rx_register(struct net_device *, struct vlan_group *);
static void igb_vlan_rx_add_vid(struct net_device *, u16); static void igb_vlan_rx_add_vid(struct net_device *, u16);
static void igb_vlan_rx_kill_vid(struct net_device *, u16); static void igb_vlan_rx_kill_vid(struct net_device *, u16);
static void igb_restore_vlan(struct igb_adapter *); static void igb_restore_vlan(struct igb_adapter *);
static void igb_ping_all_vfs(struct igb_adapter *);
static void igb_msg_task(struct igb_adapter *);
static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
static inline void igb_set_rah_pool(struct e1000_hw *, int , int); static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); static void igb_set_mc_list_pools(struct igb_adapter *, int, u16);
static void igb_vmm_control(struct igb_adapter *);
static inline void igb_set_vmolr(struct e1000_hw *, int); static inline void igb_set_vmolr(struct e1000_hw *, int);
static inline void igb_set_vf_rlpml(struct igb_adapter *, int, int); static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int);
static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
static int igb_suspend(struct pci_dev *, pm_message_t); static int igb_suspend(struct pci_dev *, pm_message_t);
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -768,7 +774,10 @@ static void igb_irq_enable(struct igb_adapter *adapter) ...@@ -768,7 +774,10 @@ static void igb_irq_enable(struct igb_adapter *adapter)
wr32(E1000_EIAC, adapter->eims_enable_mask); wr32(E1000_EIAC, adapter->eims_enable_mask);
wr32(E1000_EIAM, adapter->eims_enable_mask); wr32(E1000_EIAM, adapter->eims_enable_mask);
wr32(E1000_EIMS, adapter->eims_enable_mask); wr32(E1000_EIMS, adapter->eims_enable_mask);
wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); if (adapter->vfs_allocated_count)
wr32(E1000_MBVFIMR, 0xFF);
wr32(E1000_IMS, (E1000_IMS_LSC | E1000_IMS_VMMB |
E1000_IMS_DOUTSYNC));
} else { } else {
wr32(E1000_IMS, IMS_ENABLE_MASK); wr32(E1000_IMS, IMS_ENABLE_MASK);
wr32(E1000_IAM, IMS_ENABLE_MASK); wr32(E1000_IAM, IMS_ENABLE_MASK);
...@@ -892,6 +901,7 @@ int igb_up(struct igb_adapter *adapter) ...@@ -892,6 +901,7 @@ int igb_up(struct igb_adapter *adapter)
if (adapter->msix_entries) if (adapter->msix_entries)
igb_configure_msix(adapter); igb_configure_msix(adapter);
igb_vmm_control(adapter);
igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0);
igb_set_vmolr(hw, adapter->vfs_allocated_count); igb_set_vmolr(hw, adapter->vfs_allocated_count);
...@@ -1047,6 +1057,20 @@ void igb_reset(struct igb_adapter *adapter) ...@@ -1047,6 +1057,20 @@ void igb_reset(struct igb_adapter *adapter)
fc->send_xon = 1; fc->send_xon = 1;
fc->type = fc->original_type; fc->type = fc->original_type;
/* disable receive for all VFs and wait one second */
if (adapter->vfs_allocated_count) {
int i;
for (i = 0 ; i < adapter->vfs_allocated_count; i++)
adapter->vf_data[i].clear_to_send = false;
/* ping all the active vfs to let them know we are going down */
igb_ping_all_vfs(adapter);
/* disable transmits and receives */
wr32(E1000_VFRE, 0);
wr32(E1000_VFTE, 0);
}
/* Allow time for pending master requests to run */ /* Allow time for pending master requests to run */
adapter->hw.mac.ops.reset_hw(&adapter->hw); adapter->hw.mac.ops.reset_hw(&adapter->hw);
wr32(E1000_WUC, 0); wr32(E1000_WUC, 0);
...@@ -1624,6 +1648,7 @@ static int igb_open(struct net_device *netdev) ...@@ -1624,6 +1648,7 @@ static int igb_open(struct net_device *netdev)
* clean_rx handler before we do so. */ * clean_rx handler before we do so. */
igb_configure(adapter); igb_configure(adapter);
igb_vmm_control(adapter);
igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0);
igb_set_vmolr(hw, adapter->vfs_allocated_count); igb_set_vmolr(hw, adapter->vfs_allocated_count);
...@@ -2456,6 +2481,8 @@ static void igb_set_multi(struct net_device *netdev) ...@@ -2456,6 +2481,8 @@ static void igb_set_multi(struct net_device *netdev)
mac->rar_entry_count); mac->rar_entry_count);
igb_set_mc_list_pools(adapter, i, mac->rar_entry_count); igb_set_mc_list_pools(adapter, i, mac->rar_entry_count);
igb_restore_vf_multicasts(adapter);
kfree(mta_list); kfree(mta_list);
} }
...@@ -2571,6 +2598,8 @@ static void igb_watchdog_task(struct work_struct *work) ...@@ -2571,6 +2598,8 @@ static void igb_watchdog_task(struct work_struct *work)
netif_carrier_on(netdev); netif_carrier_on(netdev);
netif_tx_wake_all_queues(netdev); netif_tx_wake_all_queues(netdev);
igb_ping_all_vfs(adapter);
/* link state has changed, schedule phy info update */ /* link state has changed, schedule phy info update */
if (!test_bit(__IGB_DOWN, &adapter->state)) if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->phy_info_timer, mod_timer(&adapter->phy_info_timer,
...@@ -2586,6 +2615,8 @@ static void igb_watchdog_task(struct work_struct *work) ...@@ -2586,6 +2615,8 @@ static void igb_watchdog_task(struct work_struct *work)
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
igb_ping_all_vfs(adapter);
/* link state has changed, schedule phy info update */ /* link state has changed, schedule phy info update */
if (!test_bit(__IGB_DOWN, &adapter->state)) if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->phy_info_timer, mod_timer(&adapter->phy_info_timer,
...@@ -3523,15 +3554,19 @@ static irqreturn_t igb_msix_other(int irq, void *data) ...@@ -3523,15 +3554,19 @@ static irqreturn_t igb_msix_other(int irq, void *data)
/* HW is reporting DMA is out of sync */ /* HW is reporting DMA is out of sync */
adapter->stats.doosync++; adapter->stats.doosync++;
} }
if (!(icr & E1000_ICR_LSC))
goto no_link_interrupt;
hw->mac.get_link_status = 1;
/* guard against interrupt when we're going down */
if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
no_link_interrupt: /* Check for a mailbox event */
wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC); if (icr & E1000_ICR_VMMB)
igb_msg_task(adapter);
if (icr & E1000_ICR_LSC) {
hw->mac.get_link_status = 1;
/* guard against interrupt when we're going down */
if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_VMMB);
wr32(E1000_EIMS, adapter->eims_other); wr32(E1000_EIMS, adapter->eims_other);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -3719,6 +3754,317 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, ...@@ -3719,6 +3754,317 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event,
} }
#endif /* CONFIG_IGB_DCA */ #endif /* CONFIG_IGB_DCA */
static void igb_ping_all_vfs(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 ping;
int i;
for (i = 0 ; i < adapter->vfs_allocated_count; i++) {
ping = E1000_PF_CONTROL_MSG;
if (adapter->vf_data[i].clear_to_send)
ping |= E1000_VT_MSGTYPE_CTS;
igb_write_mbx(hw, &ping, 1, i);
}
}
static int igb_set_vf_multicasts(struct igb_adapter *adapter,
u32 *msgbuf, u32 vf)
{
int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT;
u16 *hash_list = (u16 *)&msgbuf[1];
struct vf_data_storage *vf_data = &adapter->vf_data[vf];
int i;
/* only up to 30 hash values supported */
if (n > 30)
n = 30;
/* salt away the number of multi cast addresses assigned
* to this VF for later use to restore when the PF multi cast
* list changes
*/
vf_data->num_vf_mc_hashes = n;
/* VFs are limited to using the MTA hash table for their multicast
* addresses */
for (i = 0; i < n; i++)
vf_data->vf_mc_hashes[i] = hash_list[i];;
/* Flush and reset the mta with the new values */
igb_set_multi(adapter->netdev);
return 0;
}
static void igb_restore_vf_multicasts(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct vf_data_storage *vf_data;
int i, j;
for (i = 0; i < adapter->vfs_allocated_count; i++) {
vf_data = &adapter->vf_data[i];
for (j = 0; j < vf_data[i].num_vf_mc_hashes; j++)
igb_mta_set(hw, vf_data->vf_mc_hashes[j]);
}
}
static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf)
{
struct e1000_hw *hw = &adapter->hw;
u32 pool_mask, reg, vid;
int i;
pool_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf);
/* Find the vlan filter for this id */
for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {
reg = rd32(E1000_VLVF(i));
/* remove the vf from the pool */
reg &= ~pool_mask;
/* if pool is empty then remove entry from vfta */
if (!(reg & E1000_VLVF_POOLSEL_MASK) &&
(reg & E1000_VLVF_VLANID_ENABLE)) {
reg = 0;
vid = reg & E1000_VLVF_VLANID_MASK;
igb_vfta_set(hw, vid, false);
}
wr32(E1000_VLVF(i), reg);
}
}
static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
{
struct e1000_hw *hw = &adapter->hw;
u32 reg, i;
/* It is an error to call this function when VFs are not enabled */
if (!adapter->vfs_allocated_count)
return -1;
/* Find the vlan filter for this id */
for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {
reg = rd32(E1000_VLVF(i));
if ((reg & E1000_VLVF_VLANID_ENABLE) &&
vid == (reg & E1000_VLVF_VLANID_MASK))
break;
}
if (add) {
if (i == E1000_VLVF_ARRAY_SIZE) {
/* Did not find a matching VLAN ID entry that was
* enabled. Search for a free filter entry, i.e.
* one without the enable bit set
*/
for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {
reg = rd32(E1000_VLVF(i));
if (!(reg & E1000_VLVF_VLANID_ENABLE))
break;
}
}
if (i < E1000_VLVF_ARRAY_SIZE) {
/* Found an enabled/available entry */
reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + vf);
/* if !enabled we need to set this up in vfta */
if (!(reg & E1000_VLVF_VLANID_ENABLE)) {
/* add VID to filter table */
igb_vfta_set(hw, vid, true);
reg |= E1000_VLVF_VLANID_ENABLE;
}
wr32(E1000_VLVF(i), reg);
return 0;
}
} else {
if (i < E1000_VLVF_ARRAY_SIZE) {
/* remove vf from the pool */
reg &= ~(1 << (E1000_VLVF_POOLSEL_SHIFT + vf));
/* if pool is empty then remove entry from vfta */
if (!(reg & E1000_VLVF_POOLSEL_MASK)) {
reg = 0;
igb_vfta_set(hw, vid, false);
}
wr32(E1000_VLVF(i), reg);
return 0;
}
}
return -1;
}
static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
{
int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT;
int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK);
return igb_vlvf_set(adapter, vid, add, vf);
}
static inline void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf)
{
struct e1000_hw *hw = &adapter->hw;
/* disable mailbox functionality for vf */
adapter->vf_data[vf].clear_to_send = false;
/* reset offloads to defaults */
igb_set_vmolr(hw, vf);
/* reset vlans for device */
igb_clear_vf_vfta(adapter, vf);
/* reset multicast table array for vf */
adapter->vf_data[vf].num_vf_mc_hashes = 0;
/* Flush and reset the mta with the new values */
igb_set_multi(adapter->netdev);
}
static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf)
{
struct e1000_hw *hw = &adapter->hw;
unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses;
u32 reg, msgbuf[3];
u8 *addr = (u8 *)(&msgbuf[1]);
/* process all the same items cleared in a function level reset */
igb_vf_reset_event(adapter, vf);
/* set vf mac address */
igb_rar_set(hw, vf_mac, vf + 1);
igb_set_rah_pool(hw, vf, vf + 1);
/* enable transmit and receive for vf */
reg = rd32(E1000_VFTE);
wr32(E1000_VFTE, reg | (1 << vf));
reg = rd32(E1000_VFRE);
wr32(E1000_VFRE, reg | (1 << vf));
/* enable mailbox functionality for vf */
adapter->vf_data[vf].clear_to_send = true;
/* reply to reset with ack and vf mac address */
msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK;
memcpy(addr, vf_mac, 6);
igb_write_mbx(hw, msgbuf, 3, vf);
}
static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf)
{
unsigned char *addr = (char *)&msg[1];
int err = -1;
if (is_valid_ether_addr(addr))
err = igb_set_vf_mac(adapter, vf, addr);
return err;
}
static void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf)
{
struct e1000_hw *hw = &adapter->hw;
u32 msg = E1000_VT_MSGTYPE_NACK;
/* if device isn't clear to send it shouldn't be reading either */
if (!adapter->vf_data[vf].clear_to_send)
igb_write_mbx(hw, &msg, 1, vf);
}
static void igb_msg_task(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 vf;
for (vf = 0; vf < adapter->vfs_allocated_count; vf++) {
/* process any reset requests */
if (!igb_check_for_rst(hw, vf)) {
adapter->vf_data[vf].clear_to_send = false;
igb_vf_reset_event(adapter, vf);
}
/* process any messages pending */
if (!igb_check_for_msg(hw, vf))
igb_rcv_msg_from_vf(adapter, vf);
/* process any acks */
if (!igb_check_for_ack(hw, vf))
igb_rcv_ack_from_vf(adapter, vf);
}
}
static int igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
{
u32 mbx_size = E1000_VFMAILBOX_SIZE;
u32 msgbuf[mbx_size];
struct e1000_hw *hw = &adapter->hw;
s32 retval;
retval = igb_read_mbx(hw, msgbuf, mbx_size, vf);
if (retval)
dev_err(&adapter->pdev->dev,
"Error receiving message from VF\n");
/* this is a message we already processed, do nothing */
if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK))
return retval;
/*
* until the vf completes a reset it should not be
* allowed to start any configuration.
*/
if (msgbuf[0] == E1000_VF_RESET) {
igb_vf_reset_msg(adapter, vf);
return retval;
}
if (!adapter->vf_data[vf].clear_to_send) {
msgbuf[0] |= E1000_VT_MSGTYPE_NACK;
igb_write_mbx(hw, msgbuf, 1, vf);
return retval;
}
switch ((msgbuf[0] & 0xFFFF)) {
case E1000_VF_SET_MAC_ADDR:
retval = igb_set_vf_mac_addr(adapter, msgbuf, vf);
break;
case E1000_VF_SET_MULTICAST:
retval = igb_set_vf_multicasts(adapter, msgbuf, vf);
break;
case E1000_VF_SET_LPE:
retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf);
break;
case E1000_VF_SET_VLAN:
retval = igb_set_vf_vlan(adapter, msgbuf, vf);
break;
default:
dev_err(&adapter->pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]);
retval = -1;
break;
}
/* notify the VF of the results of what it sent us */
if (retval)
msgbuf[0] |= E1000_VT_MSGTYPE_NACK;
else
msgbuf[0] |= E1000_VT_MSGTYPE_ACK;
msgbuf[0] |= E1000_VT_MSGTYPE_CTS;
igb_write_mbx(hw, msgbuf, 1, vf);
return retval;
}
/** /**
* igb_intr_msi - Interrupt Handler * igb_intr_msi - Interrupt Handler
* @irq: interrupt number * @irq: interrupt number
...@@ -4582,24 +4928,25 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) ...@@ -4582,24 +4928,25 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{ {
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 vfta, index; int pf_id = adapter->vfs_allocated_count;
if ((hw->mng_cookie.status & if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
(vid == adapter->mng_vlan_id)) (vid == adapter->mng_vlan_id))
return; return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F; /* add vid to vlvf if sr-iov is enabled,
vfta = array_rd32(E1000_VFTA, index); * if that fails add directly to filter table */
vfta |= (1 << (vid & 0x1F)); if (igb_vlvf_set(adapter, vid, true, pf_id))
igb_write_vfta(&adapter->hw, index, vfta); igb_vfta_set(hw, vid, true);
} }
static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{ {
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 vfta, index; int pf_id = adapter->vfs_allocated_count;
igb_irq_disable(adapter); igb_irq_disable(adapter);
vlan_group_set_device(adapter->vlgrp, vid, NULL); vlan_group_set_device(adapter->vlgrp, vid, NULL);
...@@ -4615,11 +4962,10 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ...@@ -4615,11 +4962,10 @@ static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
return; return;
} }
/* remove VID from filter table */ /* remove vid from vlvf if sr-iov is enabled,
index = (vid >> 5) & 0x7F; * if not in vlvf remove from vfta */
vfta = array_rd32(E1000_VFTA, index); if (igb_vlvf_set(adapter, vid, false, pf_id))
vfta &= ~(1 << (vid & 0x1F)); igb_vfta_set(hw, vid, false);
igb_write_vfta(&adapter->hw, index, vfta);
} }
static void igb_restore_vlan(struct igb_adapter *adapter) static void igb_restore_vlan(struct igb_adapter *adapter)
...@@ -4950,8 +5296,8 @@ static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn) ...@@ -4950,8 +5296,8 @@ static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
wr32(E1000_VMOLR(vfn), reg_data); wr32(E1000_VMOLR(vfn), reg_data);
} }
static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size, static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
int vfn) int vfn)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 vmolr; u32 vmolr;
...@@ -4960,6 +5306,8 @@ static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size, ...@@ -4960,6 +5306,8 @@ static inline void igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
vmolr &= ~E1000_VMOLR_RLPML_MASK; vmolr &= ~E1000_VMOLR_RLPML_MASK;
vmolr |= size | E1000_VMOLR_LPE; vmolr |= size | E1000_VMOLR_LPE;
wr32(E1000_VMOLR(vfn), vmolr); wr32(E1000_VMOLR(vfn), vmolr);
return 0;
} }
static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry) static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
...@@ -4985,4 +5333,37 @@ static void igb_set_mc_list_pools(struct igb_adapter *adapter, ...@@ -4985,4 +5333,37 @@ static void igb_set_mc_list_pools(struct igb_adapter *adapter,
igb_set_rah_pool(hw, adapter->vfs_allocated_count, i); igb_set_rah_pool(hw, adapter->vfs_allocated_count, i);
} }
static int igb_set_vf_mac(struct igb_adapter *adapter,
int vf, unsigned char *mac_addr)
{
struct e1000_hw *hw = &adapter->hw;
int rar_entry = vf + 1; /* VF MAC addresses start at entry 1 */
igb_rar_set(hw, mac_addr, rar_entry);
memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, 6);
igb_set_rah_pool(hw, vf, rar_entry);
return 0;
}
static void igb_vmm_control(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 reg_data;
if (!adapter->vfs_allocated_count)
return;
/* VF's need PF reset indication before they
* can send/receive mail */
reg_data = rd32(E1000_CTRL_EXT);
reg_data |= E1000_CTRL_EXT_PFRSTD;
wr32(E1000_CTRL_EXT, reg_data);
igb_vmdq_set_loopback_pf(hw, true);
igb_vmdq_set_replication_pf(hw, true);
}
/* igb_main.c */ /* igb_main.c */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment