Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: igb: remove sysfs entry that was used to set the number of vfs igbvf: add new driver to support 82576 virtual functions drivers/net/eql.c: Fix a dev leakage. niu: Fix unused variable warning. r6040: set MODULE_VERSION bnx2: Don't use reserved names FEC driver: add missing #endif niu: Fix error handling mv643xx_eth: don't reset the rx coal timer on interface up smsc911x: correct debugging message on mii read timeout ethoc: fix library build errors netfilter: ctnetlink: fix regression in expectation handling netfilter: fix selection of "LED" target in netfilter netfilter: ip6tables regression fix
This commit is contained in:
commit
c71d9caf6c
|
@ -977,6 +977,8 @@ config ETHOC
|
|||
depends on NET_ETHERNET && HAS_IOMEM
|
||||
select MII
|
||||
select PHYLIB
|
||||
select CRC32
|
||||
select BITREVERSE
|
||||
help
|
||||
Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
|
||||
|
||||
|
@ -2056,6 +2058,27 @@ config IGB_DCA
|
|||
driver. DCA is a method for warming the CPU cache before data
|
||||
is used, with the intent of lessening the impact of cache misses.
|
||||
|
||||
config IGBVF
|
||||
tristate "Intel(R) 82576 Virtual Function Ethernet support"
|
||||
depends on PCI
|
||||
---help---
|
||||
This driver supports Intel(R) 82576 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/adapter/pro100/21397.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/e1000.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called igbvf.
|
||||
|
||||
source "drivers/net/ixp2000/Kconfig"
|
||||
|
||||
config MYRI_SBUS
|
||||
|
|
|
@ -6,6 +6,7 @@ obj-$(CONFIG_E1000) += e1000/
|
|||
obj-$(CONFIG_E1000E) += e1000e/
|
||||
obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
|
||||
obj-$(CONFIG_IGB) += igb/
|
||||
obj-$(CONFIG_IGBVF) += igbvf/
|
||||
obj-$(CONFIG_IXGBE) += ixgbe/
|
||||
obj-$(CONFIG_IXGB) += ixgb/
|
||||
obj-$(CONFIG_IP1000) += ipg.o
|
||||
|
|
|
@ -3427,8 +3427,8 @@ static int __devinit
|
|||
bnx2_request_firmware(struct bnx2 *bp)
|
||||
{
|
||||
const char *mips_fw_file, *rv2p_fw_file;
|
||||
const struct bnx2_mips_fw_file *mips;
|
||||
const struct bnx2_rv2p_fw_file *rv2p;
|
||||
const struct bnx2_mips_fw_file *mips_fw;
|
||||
const struct bnx2_rv2p_fw_file *rv2p_fw;
|
||||
int rc;
|
||||
|
||||
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
|
||||
|
@ -3452,21 +3452,21 @@ bnx2_request_firmware(struct bnx2 *bp)
|
|||
rv2p_fw_file);
|
||||
return rc;
|
||||
}
|
||||
mips = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
|
||||
rv2p = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
|
||||
if (bp->mips_firmware->size < sizeof(*mips) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->com) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->cp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->rxp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->tpat) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->txp)) {
|
||||
mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
|
||||
rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
|
||||
if (bp->mips_firmware->size < sizeof(*mips_fw) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->com) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->cp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
|
||||
printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
|
||||
mips_fw_file);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (bp->rv2p_firmware->size < sizeof(*rv2p) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p->proc1.rv2p, 8, true) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p->proc2.rv2p, 8, true)) {
|
||||
if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
|
||||
printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
|
||||
rv2p_fw_file);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -542,6 +542,8 @@ static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
|
|||
}
|
||||
spin_unlock_bh(&eql->queue.lock);
|
||||
|
||||
dev_put(slave_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1240,6 +1240,7 @@ static void __inline__ fec_phy_ack_intr(void)
|
|||
icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
|
||||
*icrp = 0x0d000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_M5272
|
||||
static void __inline__ fec_get_mac(struct net_device *dev)
|
||||
|
|
|
@ -152,14 +152,13 @@ static struct notifier_block dca_notifier = {
|
|||
/* for netdump / net console */
|
||||
static void igb_netpoll(struct net_device *);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static ssize_t igb_set_num_vfs(struct device *, struct device_attribute *,
|
||||
const char *, size_t);
|
||||
static ssize_t igb_show_num_vfs(struct device *, struct device_attribute *,
|
||||
char *);
|
||||
DEVICE_ATTR(num_vfs, S_IRUGO | S_IWUSR, igb_show_num_vfs, igb_set_num_vfs);
|
||||
#endif
|
||||
static unsigned int max_vfs = 0;
|
||||
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 */
|
||||
|
||||
static pci_ers_result_t igb_io_error_detected(struct pci_dev *,
|
||||
pci_channel_state_t);
|
||||
static pci_ers_result_t igb_io_slot_reset(struct pci_dev *);
|
||||
|
@ -671,6 +670,21 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter)
|
|||
|
||||
/* If we can't do MSI-X, try MSI */
|
||||
msi_only:
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* disable SR-IOV for non MSI-X configurations */
|
||||
if (adapter->vf_data) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
/* disable iov and allow time for transactions to clear */
|
||||
pci_disable_sriov(adapter->pdev);
|
||||
msleep(500);
|
||||
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
|
||||
msleep(100);
|
||||
dev_info(&adapter->pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
#endif
|
||||
adapter->num_rx_queues = 1;
|
||||
adapter->num_tx_queues = 1;
|
||||
if (!pci_enable_msi(adapter->pdev))
|
||||
|
@ -1238,6 +1252,39 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
|||
if (err)
|
||||
goto err_sw_init;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* since iov functionality isn't critical to base device function we
|
||||
* can accept failure. If it fails we don't allow iov to be enabled */
|
||||
if (hw->mac.type == e1000_82576) {
|
||||
/* 82576 supports a maximum of 7 VFs in addition to the PF */
|
||||
unsigned int num_vfs = (max_vfs > 7) ? 7 : max_vfs;
|
||||
int i;
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
|
||||
if (num_vfs)
|
||||
adapter->vf_data = kcalloc(num_vfs,
|
||||
sizeof(struct vf_data_storage),
|
||||
GFP_KERNEL);
|
||||
if (!adapter->vf_data) {
|
||||
dev_err(&pdev->dev, "Could not allocate VF private "
|
||||
"data - IOV enable failed\n");
|
||||
} else {
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (!err) {
|
||||
adapter->vfs_allocated_count = num_vfs;
|
||||
dev_info(&pdev->dev, "%d vfs allocated\n", num_vfs);
|
||||
for (i = 0; i < adapter->vfs_allocated_count; i++) {
|
||||
random_ether_addr(mac_addr);
|
||||
igb_set_vf_mac(adapter, i, mac_addr);
|
||||
}
|
||||
} else {
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/* setup the private structure */
|
||||
err = igb_sw_init(adapter);
|
||||
if (err)
|
||||
|
@ -1397,19 +1444,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
|||
if (err)
|
||||
goto err_register;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* since iov functionality isn't critical to base device function we
|
||||
* can accept failure. If it fails we don't allow iov to be enabled */
|
||||
if (hw->mac.type == e1000_82576) {
|
||||
err = pci_enable_sriov(pdev, 0);
|
||||
if (!err)
|
||||
err = device_create_file(&netdev->dev,
|
||||
&dev_attr_num_vfs);
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "Failed to initialize IOV\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
|
@ -5422,89 +5456,4 @@ static void igb_vmm_control(struct igb_adapter *adapter)
|
|||
igb_vmdq_set_replication_pf(hw, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static ssize_t igb_show_num_vfs(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(to_net_dev(dev));
|
||||
|
||||
return sprintf(buf, "%d\n", adapter->vfs_allocated_count);
|
||||
}
|
||||
|
||||
static ssize_t igb_set_num_vfs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
unsigned int num_vfs, i;
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
int err;
|
||||
|
||||
sscanf(buf, "%u", &num_vfs);
|
||||
|
||||
if (num_vfs > 7)
|
||||
num_vfs = 7;
|
||||
|
||||
/* value unchanged do nothing */
|
||||
if (num_vfs == adapter->vfs_allocated_count)
|
||||
return count;
|
||||
|
||||
if (netdev->flags & IFF_UP)
|
||||
igb_close(netdev);
|
||||
|
||||
igb_reset_interrupt_capability(adapter);
|
||||
igb_free_queues(adapter);
|
||||
adapter->tx_ring = NULL;
|
||||
adapter->rx_ring = NULL;
|
||||
adapter->vfs_allocated_count = 0;
|
||||
|
||||
/* reclaim resources allocated to VFs since we are changing count */
|
||||
if (adapter->vf_data) {
|
||||
/* disable iov and allow time for transactions to clear */
|
||||
pci_disable_sriov(pdev);
|
||||
msleep(500);
|
||||
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
|
||||
msleep(100);
|
||||
dev_info(&pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
|
||||
if (num_vfs) {
|
||||
adapter->vf_data = kcalloc(num_vfs,
|
||||
sizeof(struct vf_data_storage),
|
||||
GFP_KERNEL);
|
||||
if (!adapter->vf_data) {
|
||||
dev_err(&pdev->dev, "Could not allocate VF private "
|
||||
"data - IOV enable failed\n");
|
||||
} else {
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (!err) {
|
||||
adapter->vfs_allocated_count = num_vfs;
|
||||
dev_info(&pdev->dev, "%d vfs allocated\n", num_vfs);
|
||||
for (i = 0; i < adapter->vfs_allocated_count; i++) {
|
||||
random_ether_addr(mac_addr);
|
||||
igb_set_vf_mac(adapter, i, mac_addr);
|
||||
}
|
||||
} else {
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
igb_set_interrupt_capability(adapter);
|
||||
igb_alloc_queues(adapter);
|
||||
igb_reset(adapter);
|
||||
|
||||
if (netdev->flags & IFF_UP)
|
||||
igb_open(netdev);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
/* igb_main.c */
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
################################################################################
|
||||
#
|
||||
# Intel(R) 82576 Virtual Function Linux driver
|
||||
# Copyright(c) 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
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Makefile for the Intel(R) 82576 VF ethernet driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IGBVF) += igbvf.o
|
||||
|
||||
igbvf-objs := vf.o \
|
||||
mbx.o \
|
||||
ethtool.o \
|
||||
netdev.o
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function 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 <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_DEFINES_H_
|
||||
#define _E1000_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
/* IVAR valid bit */
|
||||
#define E1000_IVAR_VALID 0x80
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
|
||||
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
|
||||
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
|
||||
|
||||
#define E1000_RXDEXT_STATERR_CE 0x01000000
|
||||
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
||||
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
|
||||
#define E1000_RXDEXT_STATERR_CXE 0x10000000
|
||||
#define E1000_RXDEXT_STATERR_TCPE 0x20000000
|
||||
#define E1000_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define E1000_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
|
||||
/* Same mask, but for extended and packet split descriptors */
|
||||
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
|
||||
E1000_RXDEXT_STATERR_CE | \
|
||||
E1000_RXDEXT_STATERR_SE | \
|
||||
E1000_RXDEXT_STATERR_SEQ | \
|
||||
E1000_RXDEXT_STATERR_CXE | \
|
||||
E1000_RXDEXT_STATERR_RXE)
|
||||
|
||||
/* Device Control */
|
||||
#define E1000_CTRL_RST 0x04000000 /* Global reset */
|
||||
|
||||
/* Device Status */
|
||||
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
|
||||
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
|
||||
#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x3F00
|
||||
|
||||
/* 802.1q VLAN Packet Size */
|
||||
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
|
||||
|
||||
/* Error Codes */
|
||||
#define E1000_SUCCESS 0
|
||||
#define E1000_ERR_CONFIG 3
|
||||
#define E1000_ERR_MAC_INIT 5
|
||||
#define E1000_ERR_MBX 15
|
||||
|
||||
#ifndef ETH_ADDR_LEN
|
||||
#define ETH_ADDR_LEN 6
|
||||
#endif
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
|
||||
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
|
||||
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
|
||||
|
||||
/* Additional Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
|
||||
|
||||
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
|
||||
|
||||
#endif /* _E1000_DEFINES_H_ */
|
|
@ -0,0 +1,540 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/* ethtool support for igbvf */
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igbvf.h"
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
|
||||
struct igbvf_stats {
|
||||
char stat_string[ETH_GSTRING_LEN];
|
||||
int sizeof_stat;
|
||||
int stat_offset;
|
||||
int base_stat_offset;
|
||||
};
|
||||
|
||||
#define IGBVF_STAT(current, base) \
|
||||
sizeof(((struct igbvf_adapter *)0)->current), \
|
||||
offsetof(struct igbvf_adapter, current), \
|
||||
offsetof(struct igbvf_adapter, base)
|
||||
|
||||
static const struct igbvf_stats igbvf_gstrings_stats[] = {
|
||||
{ "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
|
||||
{ "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
|
||||
{ "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
|
||||
{ "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
|
||||
{ "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
|
||||
{ "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
|
||||
{ "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
|
||||
{ "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
|
||||
{ "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
|
||||
{ "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
|
||||
{ "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
|
||||
{ "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
|
||||
{ "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
|
||||
};
|
||||
|
||||
#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
|
||||
|
||||
static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
|
||||
"Link test (on/offline)"
|
||||
};
|
||||
|
||||
#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
|
||||
|
||||
static int igbvf_get_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *ecmd)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 status;
|
||||
|
||||
ecmd->supported = SUPPORTED_1000baseT_Full;
|
||||
|
||||
ecmd->advertising = ADVERTISED_1000baseT_Full;
|
||||
|
||||
ecmd->port = -1;
|
||||
ecmd->transceiver = XCVR_DUMMY1;
|
||||
|
||||
status = er32(STATUS);
|
||||
if (status & E1000_STATUS_LU) {
|
||||
if (status & E1000_STATUS_SPEED_1000)
|
||||
ecmd->speed = 1000;
|
||||
else if (status & E1000_STATUS_SPEED_100)
|
||||
ecmd->speed = 100;
|
||||
else
|
||||
ecmd->speed = 10;
|
||||
|
||||
if (status & E1000_STATUS_FD)
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
else
|
||||
ecmd->duplex = DUPLEX_HALF;
|
||||
} else {
|
||||
ecmd->speed = -1;
|
||||
ecmd->duplex = -1;
|
||||
}
|
||||
|
||||
ecmd->autoneg = AUTONEG_DISABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_link(struct net_device *netdev)
|
||||
{
|
||||
return netif_carrier_ok(netdev);
|
||||
}
|
||||
|
||||
static int igbvf_set_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *ecmd)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void igbvf_get_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int igbvf_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_tx_csum(struct net_device *netdev)
|
||||
{
|
||||
return ((netdev->features & NETIF_F_IP_CSUM) != 0);
|
||||
}
|
||||
|
||||
static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
|
||||
{
|
||||
if (data)
|
||||
netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
|
||||
else
|
||||
netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_set_tso(struct net_device *netdev, u32 data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
struct net_device *v_netdev;
|
||||
|
||||
if (data) {
|
||||
netdev->features |= NETIF_F_TSO;
|
||||
netdev->features |= NETIF_F_TSO6;
|
||||
} else {
|
||||
netdev->features &= ~NETIF_F_TSO;
|
||||
netdev->features &= ~NETIF_F_TSO6;
|
||||
/* disable TSO on all VLANs if they're present */
|
||||
if (!adapter->vlgrp)
|
||||
goto tso_out;
|
||||
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
|
||||
v_netdev = vlan_group_get_device(adapter->vlgrp, i);
|
||||
if (!v_netdev)
|
||||
continue;
|
||||
|
||||
v_netdev->features &= ~NETIF_F_TSO;
|
||||
v_netdev->features &= ~NETIF_F_TSO6;
|
||||
vlan_group_set_device(adapter->vlgrp, i, v_netdev);
|
||||
}
|
||||
}
|
||||
|
||||
tso_out:
|
||||
dev_info(&adapter->pdev->dev, "TSO is %s\n",
|
||||
data ? "Enabled" : "Disabled");
|
||||
adapter->flags |= FLAG_TSO_FORCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_msglevel(struct net_device *netdev)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
return adapter->msg_enable;
|
||||
}
|
||||
|
||||
static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
adapter->msg_enable = data;
|
||||
}
|
||||
|
||||
static int igbvf_get_regs_len(struct net_device *netdev)
|
||||
{
|
||||
#define IGBVF_REGS_LEN 8
|
||||
return IGBVF_REGS_LEN * sizeof(u32);
|
||||
}
|
||||
|
||||
static void igbvf_get_regs(struct net_device *netdev,
|
||||
struct ethtool_regs *regs, void *p)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 *regs_buff = p;
|
||||
u8 revision_id;
|
||||
|
||||
memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
|
||||
|
||||
pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
|
||||
|
||||
regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
|
||||
|
||||
regs_buff[0] = er32(CTRL);
|
||||
regs_buff[1] = er32(STATUS);
|
||||
|
||||
regs_buff[2] = er32(RDLEN(0));
|
||||
regs_buff[3] = er32(RDH(0));
|
||||
regs_buff[4] = er32(RDT(0));
|
||||
|
||||
regs_buff[5] = er32(TDLEN(0));
|
||||
regs_buff[6] = er32(TDH(0));
|
||||
regs_buff[7] = er32(TDT(0));
|
||||
}
|
||||
|
||||
static int igbvf_get_eeprom_len(struct net_device *netdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_get_eeprom(struct net_device *netdev,
|
||||
struct ethtool_eeprom *eeprom, u8 *bytes)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int igbvf_set_eeprom(struct net_device *netdev,
|
||||
struct ethtool_eeprom *eeprom, u8 *bytes)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void igbvf_get_drvinfo(struct net_device *netdev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
char firmware_version[32] = "N/A";
|
||||
|
||||
strncpy(drvinfo->driver, igbvf_driver_name, 32);
|
||||
strncpy(drvinfo->version, igbvf_driver_version, 32);
|
||||
strncpy(drvinfo->fw_version, firmware_version, 32);
|
||||
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
||||
drvinfo->regdump_len = igbvf_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void igbvf_get_ringparam(struct net_device *netdev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct igbvf_ring *tx_ring = adapter->tx_ring;
|
||||
struct igbvf_ring *rx_ring = adapter->rx_ring;
|
||||
|
||||
ring->rx_max_pending = IGBVF_MAX_RXD;
|
||||
ring->tx_max_pending = IGBVF_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 igbvf_set_ringparam(struct net_device *netdev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct igbvf_ring *temp_ring;
|
||||
int err;
|
||||
u32 new_rx_count, new_tx_count;
|
||||
|
||||
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
|
||||
new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
|
||||
new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
|
||||
new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
|
||||
new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
|
||||
new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
|
||||
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
|
||||
if ((new_tx_count == adapter->tx_ring->count) &&
|
||||
(new_rx_count == adapter->rx_ring->count)) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp_ring = vmalloc(sizeof(struct igbvf_ring));
|
||||
if (!temp_ring)
|
||||
return -ENOMEM;
|
||||
|
||||
while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
|
||||
msleep(1);
|
||||
|
||||
if (netif_running(adapter->netdev))
|
||||
igbvf_down(adapter);
|
||||
|
||||
/*
|
||||
* We can't just free everything and then setup again,
|
||||
* because the ISRs in MSI-X mode get passed pointers
|
||||
* to the tx and rx ring structs.
|
||||
*/
|
||||
if (new_tx_count != adapter->tx_ring->count) {
|
||||
memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
|
||||
|
||||
temp_ring->count = new_tx_count;
|
||||
err = igbvf_setup_tx_resources(adapter, temp_ring);
|
||||
if (err)
|
||||
goto err_setup;
|
||||
|
||||
igbvf_free_tx_resources(adapter->tx_ring);
|
||||
|
||||
memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
|
||||
}
|
||||
|
||||
if (new_rx_count != adapter->rx_ring->count) {
|
||||
memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
|
||||
|
||||
temp_ring->count = new_rx_count;
|
||||
err = igbvf_setup_rx_resources(adapter, temp_ring);
|
||||
if (err)
|
||||
goto err_setup;
|
||||
|
||||
igbvf_free_rx_resources(adapter->rx_ring);
|
||||
|
||||
memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
|
||||
}
|
||||
|
||||
err = 0;
|
||||
err_setup:
|
||||
if (netif_running(adapter->netdev))
|
||||
igbvf_up(adapter);
|
||||
|
||||
clear_bit(__IGBVF_RESETTING, &adapter->state);
|
||||
vfree(temp_ring);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
*data = 0;
|
||||
|
||||
hw->mac.ops.check_for_link(hw);
|
||||
|
||||
if (!(er32(STATUS) & E1000_STATUS_LU))
|
||||
*data = 1;
|
||||
|
||||
return *data;
|
||||
}
|
||||
|
||||
static int igbvf_get_self_test_count(struct net_device *netdev)
|
||||
{
|
||||
return IGBVF_TEST_LEN;
|
||||
}
|
||||
|
||||
static int igbvf_get_stats_count(struct net_device *netdev)
|
||||
{
|
||||
return IGBVF_GLOBAL_STATS_LEN;
|
||||
}
|
||||
|
||||
static void igbvf_diag_test(struct net_device *netdev,
|
||||
struct ethtool_test *eth_test, u64 *data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
set_bit(__IGBVF_TESTING, &adapter->state);
|
||||
|
||||
/*
|
||||
* Link test performed before hardware reset so autoneg doesn't
|
||||
* interfere with test result
|
||||
*/
|
||||
if (igbvf_link_test(adapter, &data[0]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
clear_bit(__IGBVF_TESTING, &adapter->state);
|
||||
msleep_interruptible(4 * 1000);
|
||||
}
|
||||
|
||||
static void igbvf_get_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int igbvf_set_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int igbvf_phys_id(struct net_device *netdev, u32 data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_get_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (adapter->itr_setting <= 3)
|
||||
ec->rx_coalesce_usecs = adapter->itr_setting;
|
||||
else
|
||||
ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
|
||||
((ec->rx_coalesce_usecs > 3) &&
|
||||
(ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
|
||||
(ec->rx_coalesce_usecs == 2))
|
||||
return -EINVAL;
|
||||
|
||||
/* convert to rate of irq's per second */
|
||||
if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
|
||||
adapter->itr = IGBVF_START_ITR;
|
||||
adapter->itr_setting = ec->rx_coalesce_usecs;
|
||||
} else {
|
||||
adapter->itr = ec->rx_coalesce_usecs << 2;
|
||||
adapter->itr_setting = adapter->itr;
|
||||
}
|
||||
|
||||
writel(adapter->itr,
|
||||
hw->hw_addr + adapter->rx_ring[0].itr_register);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_nway_reset(struct net_device *netdev)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
if (netif_running(netdev))
|
||||
igbvf_reinit_locked(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void igbvf_get_ethtool_stats(struct net_device *netdev,
|
||||
struct ethtool_stats *stats,
|
||||
u64 *data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
igbvf_update_stats(adapter);
|
||||
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
|
||||
char *p = (char *)adapter +
|
||||
igbvf_gstrings_stats[i].stat_offset;
|
||||
char *b = (char *)adapter +
|
||||
igbvf_gstrings_stats[i].base_stat_offset;
|
||||
data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
|
||||
sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
|
||||
(*(u32 *)p - *(u32 *)b));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
|
||||
u8 *data)
|
||||
{
|
||||
u8 *p = data;
|
||||
int i;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_TEST:
|
||||
memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
|
||||
break;
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
|
||||
memcpy(p, igbvf_gstrings_stats[i].stat_string,
|
||||
ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ethtool_ops igbvf_ethtool_ops = {
|
||||
.get_settings = igbvf_get_settings,
|
||||
.set_settings = igbvf_set_settings,
|
||||
.get_drvinfo = igbvf_get_drvinfo,
|
||||
.get_regs_len = igbvf_get_regs_len,
|
||||
.get_regs = igbvf_get_regs,
|
||||
.get_wol = igbvf_get_wol,
|
||||
.set_wol = igbvf_set_wol,
|
||||
.get_msglevel = igbvf_get_msglevel,
|
||||
.set_msglevel = igbvf_set_msglevel,
|
||||
.nway_reset = igbvf_nway_reset,
|
||||
.get_link = igbvf_get_link,
|
||||
.get_eeprom_len = igbvf_get_eeprom_len,
|
||||
.get_eeprom = igbvf_get_eeprom,
|
||||
.set_eeprom = igbvf_set_eeprom,
|
||||
.get_ringparam = igbvf_get_ringparam,
|
||||
.set_ringparam = igbvf_set_ringparam,
|
||||
.get_pauseparam = igbvf_get_pauseparam,
|
||||
.set_pauseparam = igbvf_set_pauseparam,
|
||||
.get_tx_csum = igbvf_get_tx_csum,
|
||||
.set_tx_csum = igbvf_set_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = igbvf_set_tso,
|
||||
.self_test = igbvf_diag_test,
|
||||
.get_strings = igbvf_get_strings,
|
||||
.phys_id = igbvf_phys_id,
|
||||
.get_ethtool_stats = igbvf_get_ethtool_stats,
|
||||
.self_test_count = igbvf_get_self_test_count,
|
||||
.get_stats_count = igbvf_get_stats_count,
|
||||
.get_coalesce = igbvf_get_coalesce,
|
||||
.set_coalesce = igbvf_set_coalesce,
|
||||
};
|
||||
|
||||
void igbvf_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
/* have to "undeclare" const on this struct to remove warnings */
|
||||
SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _IGBVF_H_
|
||||
#define _IGBVF_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
|
||||
#include "vf.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct igbvf_info;
|
||||
struct igbvf_adapter;
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
|
||||
|
||||
/* Interrupt modes, as used by the IntMode paramter */
|
||||
#define IGBVF_INT_MODE_LEGACY 0
|
||||
#define IGBVF_INT_MODE_MSI 1
|
||||
#define IGBVF_INT_MODE_MSIX 2
|
||||
|
||||
/* Tx/Rx descriptor defines */
|
||||
#define IGBVF_DEFAULT_TXD 256
|
||||
#define IGBVF_MAX_TXD 4096
|
||||
#define IGBVF_MIN_TXD 80
|
||||
|
||||
#define IGBVF_DEFAULT_RXD 256
|
||||
#define IGBVF_MAX_RXD 4096
|
||||
#define IGBVF_MIN_RXD 80
|
||||
|
||||
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGBVF_RX_PTHRESH 16
|
||||
#define IGBVF_RX_HTHRESH 8
|
||||
#define IGBVF_RX_WTHRESH 1
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define IGBVF_TX_QUEUE_WAKE 32
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGBVF_EEPROM_APME 0x0400
|
||||
|
||||
#define IGBVF_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* Number of packet split data buffers (not including the header buffer) */
|
||||
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
|
||||
|
||||
enum igbvf_boards {
|
||||
board_vf,
|
||||
};
|
||||
|
||||
struct igbvf_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
* wrappers around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igbvf_buffer {
|
||||
dma_addr_t dma;
|
||||
struct sk_buff *skb;
|
||||
union {
|
||||
/* Tx */
|
||||
struct {
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
/* Rx */
|
||||
struct {
|
||||
struct page *page;
|
||||
u64 page_dma;
|
||||
unsigned int page_offset;
|
||||
};
|
||||
};
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
union igbvf_desc {
|
||||
union e1000_adv_rx_desc rx_desc;
|
||||
union e1000_adv_tx_desc tx_desc;
|
||||
struct e1000_adv_tx_context_desc tx_context_desc;
|
||||
};
|
||||
|
||||
struct igbvf_ring {
|
||||
struct igbvf_adapter *adapter; /* backlink */
|
||||
union igbvf_desc *desc; /* pointer to ring memory */
|
||||
dma_addr_t dma; /* phys address of ring */
|
||||
unsigned int size; /* length of ring in bytes */
|
||||
unsigned int count; /* number of desc. in ring */
|
||||
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
u16 head;
|
||||
u16 tail;
|
||||
|
||||
/* array of buffer information structs */
|
||||
struct igbvf_buffer *buffer_info;
|
||||
struct napi_struct napi;
|
||||
|
||||
char name[IFNAMSIZ + 5];
|
||||
u32 eims_value;
|
||||
u32 itr_val;
|
||||
u16 itr_register;
|
||||
int set_itr;
|
||||
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
struct igbvf_queue_stats stats;
|
||||
};
|
||||
|
||||
/* board specific private data structure */
|
||||
struct igbvf_adapter {
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list blink_timer;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
|
||||
const struct igbvf_info *ei;
|
||||
|
||||
struct vlan_group *vlgrp;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 polling_interval;
|
||||
u16 mng_vlan_id;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
|
||||
|
||||
/* track device up/down/testing state */
|
||||
unsigned long state;
|
||||
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
/*
|
||||
* Tx
|
||||
*/
|
||||
struct igbvf_ring *tx_ring /* One per active queue */
|
||||
____cacheline_aligned_in_smp;
|
||||
|
||||
unsigned long tx_queue_len;
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
|
||||
bool detect_tx_hung;
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
|
||||
/* Tx stats */
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u32 tx_dma_failed;
|
||||
|
||||
/*
|
||||
* Rx
|
||||
*/
|
||||
struct igbvf_ring *rx_ring;
|
||||
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
|
||||
/* Rx stats */
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u64 rx_hdr_split;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_dma_failed;
|
||||
|
||||
unsigned int rx_ps_hdr_size;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
spinlock_t stats_lock; /* prevent concurrent stats updates */
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
|
||||
/* The VF counters don't clear on read so we have to get a base
|
||||
* count on driver start up and always subtract that base on
|
||||
* on the first update, thus the flag..
|
||||
*/
|
||||
struct e1000_vf_stats stats;
|
||||
u64 zero_base;
|
||||
|
||||
struct igbvf_ring test_tx_ring;
|
||||
struct igbvf_ring test_rx_ring;
|
||||
u32 test_icr;
|
||||
|
||||
u32 msg_enable;
|
||||
struct msix_entry *msix_entries;
|
||||
int int_mode;
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
u32 int_counter0;
|
||||
u32 int_counter1;
|
||||
|
||||
u32 eeprom_wol;
|
||||
u32 wol;
|
||||
u32 pba;
|
||||
|
||||
bool fc_autoneg;
|
||||
|
||||
unsigned long led_status;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct igbvf_info {
|
||||
enum e1000_mac_type mac;
|
||||
unsigned int flags;
|
||||
u32 pba;
|
||||
void (*init_ops)(struct e1000_hw *);
|
||||
s32 (*get_variants)(struct igbvf_adapter *);
|
||||
};
|
||||
|
||||
/* hardware capability, feature, and workaround flags */
|
||||
#define FLAG_HAS_HW_VLAN_FILTER (1 << 0)
|
||||
#define FLAG_HAS_JUMBO_FRAMES (1 << 1)
|
||||
#define FLAG_MSI_ENABLED (1 << 2)
|
||||
#define FLAG_RX_CSUM_ENABLED (1 << 3)
|
||||
#define FLAG_TSO_FORCE (1 << 4)
|
||||
|
||||
#define IGBVF_RX_DESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].rx_desc))
|
||||
#define IGBVF_TX_DESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].tx_desc))
|
||||
#define IGBVF_TX_CTXTDESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].tx_context_desc))
|
||||
|
||||
enum igbvf_state_t {
|
||||
__IGBVF_TESTING,
|
||||
__IGBVF_RESETTING,
|
||||
__IGBVF_DOWN
|
||||
};
|
||||
|
||||
enum latency_range {
|
||||
lowest_latency = 0,
|
||||
low_latency = 1,
|
||||
bulk_latency = 2,
|
||||
latency_invalid = 255
|
||||
};
|
||||
|
||||
extern char igbvf_driver_name[];
|
||||
extern const char igbvf_driver_version[];
|
||||
|
||||
extern void igbvf_check_options(struct igbvf_adapter *);
|
||||
extern void igbvf_set_ethtool_ops(struct net_device *);
|
||||
|
||||
extern int igbvf_up(struct igbvf_adapter *);
|
||||
extern void igbvf_down(struct igbvf_adapter *);
|
||||
extern void igbvf_reinit_locked(struct igbvf_adapter *);
|
||||
extern void igbvf_reset(struct igbvf_adapter *);
|
||||
extern int igbvf_setup_rx_resources(struct igbvf_adapter *, struct igbvf_ring *);
|
||||
extern int igbvf_setup_tx_resources(struct igbvf_adapter *, struct igbvf_ring *);
|
||||
extern void igbvf_free_rx_resources(struct igbvf_ring *);
|
||||
extern void igbvf_free_tx_resources(struct igbvf_ring *);
|
||||
extern void igbvf_update_stats(struct igbvf_adapter *);
|
||||
extern void igbvf_set_interrupt_capability(struct igbvf_adapter *);
|
||||
extern void igbvf_reset_interrupt_capability(struct igbvf_adapter *);
|
||||
|
||||
extern unsigned int copybreak;
|
||||
|
||||
#endif /* _IGBVF_H_ */
|
|
@ -0,0 +1,350 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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 "mbx.h"
|
||||
|
||||
/**
|
||||
* e1000_poll_for_msg - Wait for message notification
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification
|
||||
**/
|
||||
static s32 e1000_poll_for_msg(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_msg(hw)) {
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_poll_for_ack - Wait for message acknowledgement
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message acknowledgement
|
||||
**/
|
||||
static s32 e1000_poll_for_ack(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_ack(hw)) {
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 SUCCESS if it successfully received a message notification and
|
||||
* copied it into the receive buffer.
|
||||
**/
|
||||
static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_poll_for_msg(hw);
|
||||
|
||||
/* if ack received read message, otherwise we timed out */
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 SUCCESS if it successfully copied message into the buffer and
|
||||
* received an ack to that message within delay * timeout period
|
||||
**/
|
||||
static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* exit if we either 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);
|
||||
|
||||
/* if msg sent wait until we receive an ack */
|
||||
if (!ret_val)
|
||||
ret_val = e1000_poll_for_ack(hw);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 e1000_read_v2p_mailbox(struct e1000_hw *hw)
|
||||
{
|
||||
u32 v2p_mailbox = er32(V2PMAILBOX(0));
|
||||
|
||||
v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
|
||||
hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
|
||||
|
||||
return v2p_mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (v2p_mailbox & mask)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
hw->dev_spec.vf.v2p_mailbox &= ~mask;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_msg_vf - checks to see if the PF has sent mail
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_ack_vf - checks to see if the PF has ACK'd
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
|
||||
**/
|
||||
static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 e1000_check_for_rst_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
|
||||
E1000_V2PMAILBOX_RSTI))) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_obtain_mbx_lock_vf - obtain mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* return SUCCESS if we obtained the mailbox lock
|
||||
**/
|
||||
static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* Take ownership of the buffer */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
|
||||
|
||||
/* reserve mailbox for vf use */
|
||||
if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_mbx_vf - Write a message to the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
s32 err;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
err = e1000_obtain_mbx_lock_vf(hw);
|
||||
if (err)
|
||||
goto out_no_write;
|
||||
|
||||
/* flush any ack or msg as we are going to overwrite mailbox */
|
||||
e1000_check_for_ack_vf(hw);
|
||||
e1000_check_for_msg_vf(hw);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
array_ew32(VMBMEM(0), i, msg[i]);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
/* Drop VFU and interrupt the PF to tell it a message has been sent */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
|
||||
|
||||
out_no_write:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 SUCCESS if it successfuly read message from buffer
|
||||
**/
|
||||
static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
s32 err;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
err = e1000_obtain_mbx_lock_vf(hw);
|
||||
if (err)
|
||||
goto out_no_read;
|
||||
|
||||
/* copy the message from the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = array_er32(VMBMEM(0), i);
|
||||
|
||||
/* Acknowledge receipt and release mailbox, then we're done */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
out_no_read:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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 e1000_init_mbx_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
/* start mailbox as timed out and let the reset_hw call set the timeout
|
||||
* value to being communications */
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = e1000_read_mbx_vf;
|
||||
mbx->ops.write = e1000_write_mbx_vf;
|
||||
mbx->ops.read_posted = e1000_read_posted_mbx;
|
||||
mbx->ops.write_posted = e1000_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = e1000_check_for_msg_vf;
|
||||
mbx->ops.check_for_ack = e1000_check_for_ack_vf;
|
||||
mbx->ops.check_for_rst = e1000_check_for_rst_vf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function 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 <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 "vf.h"
|
||||
|
||||
#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
|
||||
#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
|
||||
#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
|
||||
#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
|
||||
#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
|
||||
#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
|
||||
#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
|
||||
* this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
|
||||
* this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
|
||||
clear to send requests */
|
||||
|
||||
/* We have a total wait time of 1s for vf mailbox posted messages */
|
||||
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* retry count for mailbox timeout */
|
||||
#define E1000_VF_MBX_INIT_DELAY 500 /* usec delay between retries */
|
||||
|
||||
#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 */
|
||||
|
||||
void e1000_init_mbx_ops_generic(struct e1000_hw *hw);
|
||||
s32 e1000_init_mbx_params_vf(struct e1000_hw *);
|
||||
|
||||
#endif /* _E1000_MBX_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,108 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
|
||||
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
/*
|
||||
* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
|
||||
(0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
|
||||
(0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
|
||||
(0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
|
||||
(0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
|
||||
(0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
|
||||
(0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
|
||||
(0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
|
||||
(0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
|
||||
(0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
|
||||
(0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
|
||||
(0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
|
||||
(0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
|
||||
(0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
|
||||
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
|
||||
/* Statistics registers */
|
||||
#define E1000_VFGPRC 0x00F10
|
||||
#define E1000_VFGORC 0x00F18
|
||||
#define E1000_VFMPRC 0x00F3C
|
||||
#define E1000_VFGPTC 0x00F14
|
||||
#define E1000_VFGOTC 0x00F34
|
||||
#define E1000_VFGOTLBC 0x00F50
|
||||
#define E1000_VFGPTLBC 0x00F44
|
||||
#define E1000_VFGORLBC 0x00F48
|
||||
#define E1000_VFGPRLBC 0x00F40
|
||||
|
||||
/* These act per VF so an array friendly macro is used */
|
||||
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
|
||||
/* Define macros for handling registers */
|
||||
#define er32(reg) readl(hw->hw_addr + E1000_##reg)
|
||||
#define ew32(reg, val) writel((val), hw->hw_addr + E1000_##reg)
|
||||
#define array_er32(reg, offset) \
|
||||
readl(hw->hw_addr + E1000_##reg + (offset << 2))
|
||||
#define array_ew32(reg, offset, val) \
|
||||
writel((val), hw->hw_addr + E1000_##reg + (offset << 2))
|
||||
#define e1e_flush() er32(STATUS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,398 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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 "vf.h"
|
||||
|
||||
static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
|
||||
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
static s32 e1000_init_hw_vf(struct e1000_hw *hw);
|
||||
static s32 e1000_reset_hw_vf(struct e1000_hw *hw);
|
||||
|
||||
static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *,
|
||||
u32, u32, u32);
|
||||
static void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
|
||||
static s32 e1000_read_mac_addr_vf(struct e1000_hw *);
|
||||
static s32 e1000_set_vfta_vf(struct e1000_hw *, u16, bool);
|
||||
|
||||
/**
|
||||
* e1000_init_mac_params_vf - Inits MAC params
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 e1000_init_mac_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
|
||||
/* VF's have no MTA Registers - PF feature only */
|
||||
mac->mta_reg_count = 128;
|
||||
/* VF's have no access to RAR entries */
|
||||
mac->rar_entry_count = 1;
|
||||
|
||||
/* Function pointers */
|
||||
/* reset */
|
||||
mac->ops.reset_hw = e1000_reset_hw_vf;
|
||||
/* hw initialization */
|
||||
mac->ops.init_hw = e1000_init_hw_vf;
|
||||
/* check for link */
|
||||
mac->ops.check_for_link = e1000_check_for_link_vf;
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info = e1000_get_link_up_info_vf;
|
||||
/* multicast address update */
|
||||
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf;
|
||||
/* set mac address */
|
||||
mac->ops.rar_set = e1000_rar_set_vf;
|
||||
/* read mac address */
|
||||
mac->ops.read_mac_addr = e1000_read_mac_addr_vf;
|
||||
/* set vlan filter table array */
|
||||
mac->ops.set_vfta = e1000_set_vfta_vf;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_function_pointers_vf - Inits function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
void e1000_init_function_pointers_vf(struct e1000_hw *hw)
|
||||
{
|
||||
hw->mac.ops.init_params = e1000_init_mac_params_vf;
|
||||
hw->mbx.ops.init_params = e1000_init_mbx_params_vf;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_link_up_info_vf - Gets link info.
|
||||
* @hw: pointer to the HW structure
|
||||
* @speed: pointer to 16 bit value to store link speed.
|
||||
* @duplex: pointer to 16 bit value to store duplex.
|
||||
*
|
||||
* Since we cannot read the PHY and get accurate link info, we must rely upon
|
||||
* the status register's data which is often stale and inaccurate.
|
||||
**/
|
||||
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex)
|
||||
{
|
||||
s32 status;
|
||||
|
||||
status = er32(STATUS);
|
||||
if (status & E1000_STATUS_SPEED_1000)
|
||||
*speed = SPEED_1000;
|
||||
else if (status & E1000_STATUS_SPEED_100)
|
||||
*speed = SPEED_100;
|
||||
else
|
||||
*speed = SPEED_10;
|
||||
|
||||
if (status & E1000_STATUS_FD)
|
||||
*duplex = FULL_DUPLEX;
|
||||
else
|
||||
*duplex = HALF_DUPLEX;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reset_hw_vf - Resets the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
|
||||
* This is all the reset we can perform on a VF.
|
||||
**/
|
||||
static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 timeout = E1000_VF_INIT_TIMEOUT;
|
||||
u32 ret_val = -E1000_ERR_MAC_INIT;
|
||||
u32 msgbuf[3];
|
||||
u8 *addr = (u8 *)(&msgbuf[1]);
|
||||
u32 ctrl;
|
||||
|
||||
/* assert vf queue/interrupt reset */
|
||||
ctrl = er32(CTRL);
|
||||
ew32(CTRL, ctrl | E1000_CTRL_RST);
|
||||
|
||||
/* we cannot initialize while the RSTI / RSTD bits are asserted */
|
||||
while (!mbx->ops.check_for_rst(hw) && timeout) {
|
||||
timeout--;
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
/* mailbox timeout can now become active */
|
||||
mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
|
||||
|
||||
/* notify pf of vf reset completion */
|
||||
msgbuf[0] = E1000_VF_RESET;
|
||||
mbx->ops.write_posted(hw, msgbuf, 1);
|
||||
|
||||
msleep(10);
|
||||
|
||||
/* set our "perm_addr" based on info provided by PF */
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
|
||||
if (!ret_val) {
|
||||
if (msgbuf[0] == (E1000_VF_RESET | E1000_VT_MSGTYPE_ACK))
|
||||
memcpy(hw->mac.perm_addr, addr, 6);
|
||||
else
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_hw_vf - Inits the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Not much to do here except clear the PF Reset indication if there is one.
|
||||
**/
|
||||
static s32 e1000_init_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
/* attempt to set and restore our mac address */
|
||||
e1000_rar_set_vf(hw, hw->mac.addr, 0);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_hash_mc_addr_vf - Generate a multicast hash value
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr: pointer to a multicast address
|
||||
*
|
||||
* Generates a multicast address hash value which is used to determine
|
||||
* the multicast filter table array address and new table value. See
|
||||
* e1000_mta_set_generic()
|
||||
**/
|
||||
static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
|
||||
{
|
||||
u32 hash_value, hash_mask;
|
||||
u8 bit_shift = 0;
|
||||
|
||||
/* Register count multiplied by bits per register */
|
||||
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
|
||||
|
||||
/*
|
||||
* The bit_shift is the number of left-shifts
|
||||
* where 0xFF would still fall within the hash mask.
|
||||
*/
|
||||
while (hash_mask >> bit_shift != 0xFF)
|
||||
bit_shift++;
|
||||
|
||||
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
|
||||
(((u16) mc_addr[5]) << bit_shift)));
|
||||
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_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
|
||||
* @rar_used_count: the first RAR register free to program
|
||||
* @rar_count: total number of supported Receive Address Registers
|
||||
*
|
||||
* Updates the Receive Address Registers and Multicast Table Array.
|
||||
* The caller must have a packed mc_addr_list of multicast addresses.
|
||||
* The parameter rar_count will usually be hw->mac.rar_entry_count
|
||||
* unless there are workarounds that change this.
|
||||
**/
|
||||
void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count,
|
||||
u32 rar_used_count, u32 rar_count)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[E1000_VFMAILBOX_SIZE];
|
||||
u16 *hash_list = (u16 *)&msgbuf[1];
|
||||
u32 hash_value;
|
||||
u32 cnt, i;
|
||||
|
||||
/* 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] = E1000_VF_SET_MULTICAST;
|
||||
msgbuf[0] |= cnt << E1000_VT_MSGINFO_SHIFT;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list);
|
||||
hash_list[i] = hash_value & 0x0FFFF;
|
||||
mc_addr_list += ETH_ADDR_LEN;
|
||||
}
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_set_vfta_vf - Set/Unset vlan filter table address
|
||||
* @hw: pointer to the HW structure
|
||||
* @vid: determines the vfta register and bit to set/unset
|
||||
* @set: if true then set bit, else clear bit
|
||||
**/
|
||||
static s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
s32 err;
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_VLAN;
|
||||
msgbuf[1] = vid;
|
||||
/* Setting the 8 bit field MSG INFO to true indicates "add" */
|
||||
if (set)
|
||||
msgbuf[0] |= 1 << E1000_VT_MSGINFO_SHIFT;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2);
|
||||
|
||||
err = mbx->ops.read_posted(hw, msgbuf, 2);
|
||||
|
||||
/* if nacked the vlan was rejected */
|
||||
if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK)))
|
||||
err = -E1000_ERR_MAC_INIT;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/** e1000_rlpml_set_vf - Set the maximum receive packet length
|
||||
* @hw: pointer to the HW structure
|
||||
* @max_size: value to assign to max frame size
|
||||
**/
|
||||
void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_LPE;
|
||||
msgbuf[1] = max_size;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_rar_set_vf - set device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: pointer to the receive address
|
||||
* @index receive address array register
|
||||
**/
|
||||
static void e1000_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[3];
|
||||
u8 *msg_addr = (u8 *)(&msgbuf[1]);
|
||||
s32 ret_val;
|
||||
|
||||
memset(msgbuf, 0, 12);
|
||||
msgbuf[0] = E1000_VF_SET_MAC_ADDR;
|
||||
memcpy(msg_addr, addr, 6);
|
||||
ret_val = mbx->ops.write_posted(hw, msgbuf, 3);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
|
||||
|
||||
/* if nacked the address was rejected, use "perm_addr" */
|
||||
if (!ret_val &&
|
||||
(msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
|
||||
e1000_read_mac_addr_vf(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_mac_addr_vf - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_read_mac_addr_vf(struct e1000_hw *hw)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_link_vf - Check for link for a virtual interface
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Checks to see if the underlying PF is still talking to the VF and
|
||||
* if it is then it reports the link state to the hardware, otherwise
|
||||
* it reports link down and returns an error.
|
||||
**/
|
||||
static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u32 in_msg = 0;
|
||||
|
||||
/*
|
||||
* We only want to run this if there has been a rst asserted.
|
||||
* in this case that could mean a link change, device reset,
|
||||
* or a virtual function reset
|
||||
*/
|
||||
|
||||
/* If we were hit with a reset drop the link */
|
||||
if (!mbx->ops.check_for_rst(hw))
|
||||
mac->get_link_status = true;
|
||||
|
||||
if (!mac->get_link_status)
|
||||
goto out;
|
||||
|
||||
/* if link status is down no point in checking to see if pf is up */
|
||||
if (!(er32(STATUS) & E1000_STATUS_LU))
|
||||
goto out;
|
||||
|
||||
/* if the read failed it could just be a mailbox collision, best wait
|
||||
* until we are called again and don't report an error */
|
||||
if (mbx->ops.read(hw, &in_msg, 1))
|
||||
goto out;
|
||||
|
||||
/* if incoming message isn't clear to send we are waiting on response */
|
||||
if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
|
||||
/* message is not CTS and is NACK we must have lost CTS status */
|
||||
if (in_msg & E1000_VT_MSGTYPE_NACK)
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the pf is talking, if we timed out in the past we reinit */
|
||||
if (!mbx->timeout) {
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if we passed all the tests above then the link is up and we no
|
||||
* longer need to check for link */
|
||||
mac->get_link_status = false;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 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_VF_H_
|
||||
#define _E1000_VF_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "regs.h"
|
||||
#include "defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576_VF 0x10CA
|
||||
#define E1000_REVISION_0 0
|
||||
#define E1000_REVISION_1 1
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_3 3
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_0 0
|
||||
#define E1000_FUNC_1 1
|
||||
|
||||
/*
|
||||
* Receive Address Register Count
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* These entries are also used for MAC-based filtering.
|
||||
*/
|
||||
#define E1000_RAR_ENTRIES_VF 1
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
u64 pkt_addr; /* Packet buffer address */
|
||||
u64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u16 pkt_info; /* RSS/Packet type */
|
||||
u16 hdr_info; /* Split Header,
|
||||
* hdr buffer length */
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length; /* Packet length */
|
||||
u16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
u64 buffer_addr; /* Address of descriptor's data buf */
|
||||
u32 cmd_type_len;
|
||||
u32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
u64 rsvd; /* Reserved */
|
||||
u32 nxtseq_seed;
|
||||
u32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
u32 vlan_macip_lens;
|
||||
u32 seqnum_seed;
|
||||
u32 type_tucmd_mlhl;
|
||||
u32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_vfadapt,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
struct e1000_vf_stats {
|
||||
u64 base_gprc;
|
||||
u64 base_gptc;
|
||||
u64 base_gorc;
|
||||
u64 base_gotc;
|
||||
u64 base_mprc;
|
||||
u64 base_gotlbc;
|
||||
u64 base_gptlbc;
|
||||
u64 base_gorlbc;
|
||||
u64 base_gprlbc;
|
||||
|
||||
u32 last_gprc;
|
||||
u32 last_gptc;
|
||||
u32 last_gorc;
|
||||
u32 last_gotc;
|
||||
u32 last_mprc;
|
||||
u32 last_gotlbc;
|
||||
u32 last_gptlbc;
|
||||
u32 last_gorlbc;
|
||||
u32 last_gprlbc;
|
||||
|
||||
u64 gprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 mprc;
|
||||
u64 gotlbc;
|
||||
u64 gptlbc;
|
||||
u64 gorlbc;
|
||||
u64 gprlbc;
|
||||
};
|
||||
|
||||
#include "mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
/* Function pointers for the MAC. */
|
||||
s32 (*init_params)(struct e1000_hw *);
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
void (*clear_vfta)(struct e1000_hw *);
|
||||
s32 (*get_bus_info)(struct e1000_hw *);
|
||||
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
|
||||
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
s32 (*setup_link)(struct e1000_hw *);
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
void (*mta_set)(struct e1000_hw *, u32);
|
||||
void (*rar_set)(struct e1000_hw *, u8*, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*set_vfta)(struct e1000_hw *, u16, bool);
|
||||
};
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 rar_entry_count;
|
||||
|
||||
bool get_link_status;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*write)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*read_posted)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*write_posted)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*check_for_msg)(struct e1000_hw *);
|
||||
s32 (*check_for_ack)(struct e1000_hw *);
|
||||
s32 (*check_for_rst)(struct e1000_hw *);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_vf {
|
||||
u32 vf_number;
|
||||
u32 v2p_mailbox;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_mbx_info mbx;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_vf vf;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
|
||||
void e1000_init_function_pointers_vf(struct e1000_hw *hw);
|
||||
s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
|
||||
|
||||
|
||||
#endif /* _E1000_VF_H_ */
|
|
@ -2274,8 +2274,6 @@ static void port_start(struct mv643xx_eth_private *mp)
|
|||
pscr |= FORCE_LINK_PASS;
|
||||
wrlp(mp, PORT_SERIAL_CONTROL, pscr);
|
||||
|
||||
wrlp(mp, SDMA_CONFIG, PORT_SDMA_CONFIG_DEFAULT_VALUE);
|
||||
|
||||
/*
|
||||
* Configure TX path and queues.
|
||||
*/
|
||||
|
@ -2957,6 +2955,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
|
|||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
wrlp(mp, SDMA_CONFIG, PORT_SDMA_CONFIG_DEFAULT_VALUE);
|
||||
|
||||
set_rx_coal(mp, 250);
|
||||
set_tx_coal(mp, 0);
|
||||
|
||||
|
|
|
@ -4834,6 +4834,7 @@ static int niu_compute_rbr_cfig_b(struct rx_ring_info *rp, u64 *ret)
|
|||
{
|
||||
u64 val = 0;
|
||||
|
||||
*ret = 0;
|
||||
switch (rp->rbr_block_size) {
|
||||
case 4 * 1024:
|
||||
val |= (RBR_BLKSIZE_4K << RBR_CFIG_B_BLKSIZE_SHIFT);
|
||||
|
@ -9542,7 +9543,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np,
|
|||
|
||||
plat_dev = platform_device_register_simple("niu", niu_parent_index,
|
||||
NULL, 0);
|
||||
if (!plat_dev)
|
||||
if (IS_ERR(plat_dev))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; attr_name(niu_parent_attributes[i]); i++) {
|
||||
|
|
|
@ -160,6 +160,7 @@ MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>,"
|
|||
"Florian Fainelli <florian@openwrt.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
|
||||
MODULE_VERSION(DRV_VERSION " " DRV_RELDATE);
|
||||
|
||||
/* RX and TX interrupts that we handle */
|
||||
#define RX_INTS (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
|
||||
|
|
|
@ -317,7 +317,7 @@ static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
|
|||
goto out;
|
||||
}
|
||||
|
||||
SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
|
||||
SMSC_WARNING(HW, "Timed out waiting for MII read to finish");
|
||||
reg = -EIO;
|
||||
|
||||
out:
|
||||
|
|
|
@ -99,9 +99,12 @@ void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
|
|||
const union nf_inet_addr *,
|
||||
u_int8_t, const __be16 *, const __be16 *);
|
||||
void nf_ct_expect_put(struct nf_conntrack_expect *exp);
|
||||
int nf_ct_expect_related(struct nf_conntrack_expect *expect);
|
||||
int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
|
||||
u32 pid, int report);
|
||||
static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
|
||||
{
|
||||
return nf_ct_expect_related_report(expect, 0, 0);
|
||||
}
|
||||
|
||||
#endif /*_NF_CONNTRACK_EXPECT_H*/
|
||||
|
||||
|
|
|
@ -1033,6 +1033,8 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
|
|||
|
||||
xt_free_table_info(info);
|
||||
|
||||
return counters;
|
||||
|
||||
free_counters:
|
||||
vfree(counters);
|
||||
nomem:
|
||||
|
|
|
@ -374,7 +374,7 @@ config NETFILTER_XT_TARGET_HL
|
|||
|
||||
config NETFILTER_XT_TARGET_LED
|
||||
tristate '"LED" target support'
|
||||
depends on LEDS_CLASS && LED_TRIGGERS
|
||||
depends on LEDS_CLASS && LEDS_TRIGGERS
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
This option adds a `LED' target, which allows you to blink LEDs in
|
||||
|
|
|
@ -372,7 +372,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
|
|||
struct net *net = nf_ct_exp_net(expect);
|
||||
struct hlist_node *n;
|
||||
unsigned int h;
|
||||
int ret = 0;
|
||||
int ret = 1;
|
||||
|
||||
if (!master_help->helper) {
|
||||
ret = -ESHUTDOWN;
|
||||
|
@ -412,27 +412,6 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int nf_ct_expect_related(struct nf_conntrack_expect *expect)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
ret = __nf_ct_expect_check(expect);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
nf_ct_expect_insert(expect);
|
||||
atomic_inc(&expect->use);
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
nf_ct_expect_event(IPEXP_NEW, expect);
|
||||
nf_ct_expect_put(expect);
|
||||
return ret;
|
||||
out:
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_expect_related);
|
||||
|
||||
int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
|
||||
u32 pid, int report)
|
||||
{
|
||||
|
@ -440,13 +419,16 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
|
|||
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
ret = __nf_ct_expect_check(expect);
|
||||
if (ret < 0)
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
nf_ct_expect_insert(expect);
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report);
|
||||
return ret;
|
||||
out:
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
if (ret == 0)
|
||||
nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
|
||||
|
|
Loading…
Reference in New Issue