summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_main.c')
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c259
1 files changed, 191 insertions, 68 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 395dc6bb5d82..d3f4b0ceb3f7 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -3228,89 +3228,148 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl);
}
-static void ixgbe_setup_reta(struct ixgbe_adapter *adapter, const u32 *seed)
+/**
+ * Return a number of entries in the RSS indirection table
+ *
+ * @adapter: device handle
+ *
+ * - 82598/82599/X540: 128
+ * - X550(non-SRIOV mode): 512
+ * - X550(SRIOV mode): 64
+ */
+u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter)
+{
+ if (adapter->hw.mac.type < ixgbe_mac_X550)
+ return 128;
+ else if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ return 64;
+ else
+ return 512;
+}
+
+/**
+ * Write the RETA table to HW
+ *
+ * @adapter: device handle
+ *
+ * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW.
+ */
+static void ixgbe_store_reta(struct ixgbe_adapter *adapter)
{
+ u32 i, reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
struct ixgbe_hw *hw = &adapter->hw;
u32 reta = 0;
- int i, j;
- int reta_entries = 128;
- u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
- int indices_multi;
-
- /*
- * Program table for at least 2 queues w/ SR-IOV so that VFs can
- * make full use of any rings they may have. We will use the
- * PSRTYPE register to control how many rings we use within the PF.
- */
- if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && (rss_i < 2))
- rss_i = 2;
-
- /* Fill out hash function seeds */
- for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
+ u32 indices_multi;
+ u8 *indir_tbl = adapter->rss_indir_tbl;
/* Fill out the redirection table as follows:
- * 82598: 128 (8 bit wide) entries containing pair of 4 bit RSS indices
- * 82599/X540: 128 (8 bit wide) entries containing 4 bit RSS index
- * X550: 512 (8 bit wide) entries containing 6 bit RSS index
+ * - 82598: 8 bit wide entries containing pair of 4 bit RSS
+ * indices.
+ * - 82599/X540: 8 bit wide entries containing 4 bit RSS index
+ * - X550: 8 bit wide entries containing 6 bit RSS index
*/
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
indices_multi = 0x11;
else
indices_multi = 0x1;
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_X550:
- case ixgbe_mac_X550EM_x:
- if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
- reta_entries = 512;
- default:
- break;
- }
-
- /* Fill out redirection table */
- for (i = 0, j = 0; i < reta_entries; i++, j++) {
- if (j == rss_i)
- j = 0;
- reta = (reta << 8) | (j * indices_multi);
+ /* Write redirection table to HW */
+ for (i = 0; i < reta_entries; i++) {
+ reta |= indices_multi * indir_tbl[i] << (i & 0x3) * 8;
if ((i & 3) == 3) {
if (i < 128)
IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
else
IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
reta);
+ reta = 0;
}
}
}
-static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter, const u32 *seed)
+/**
+ * Write the RETA table to HW (for x550 devices in SRIOV mode)
+ *
+ * @adapter: device handle
+ *
+ * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW.
+ */
+static void ixgbe_store_vfreta(struct ixgbe_adapter *adapter)
{
+ u32 i, reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
struct ixgbe_hw *hw = &adapter->hw;
u32 vfreta = 0;
+ unsigned int pf_pool = adapter->num_vfs;
+
+ /* Write redirection table to HW */
+ for (i = 0; i < reta_entries; i++) {
+ vfreta |= (u32)adapter->rss_indir_tbl[i] << (i & 0x3) * 8;
+ if ((i & 3) == 3) {
+ IXGBE_WRITE_REG(hw, IXGBE_PFVFRETA(i >> 2, pf_pool),
+ vfreta);
+ vfreta = 0;
+ }
+ }
+}
+
+static void ixgbe_setup_reta(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 i, j;
+ u32 reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
+ u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
+
+ /* Program table for at least 2 queues w/ SR-IOV so that VFs can
+ * make full use of any rings they may have. We will use the
+ * PSRTYPE register to control how many rings we use within the PF.
+ */
+ if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && (rss_i < 2))
+ rss_i = 2;
+
+ /* Fill out hash function seeds */
+ for (i = 0; i < 10; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), adapter->rss_key[i]);
+
+ /* Fill out redirection table */
+ memset(adapter->rss_indir_tbl, 0, sizeof(adapter->rss_indir_tbl));
+
+ for (i = 0, j = 0; i < reta_entries; i++, j++) {
+ if (j == rss_i)
+ j = 0;
+
+ adapter->rss_indir_tbl[i] = j;
+ }
+
+ ixgbe_store_reta(adapter);
+}
+
+static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
u16 rss_i = adapter->ring_feature[RING_F_RSS].indices;
unsigned int pf_pool = adapter->num_vfs;
int i, j;
/* Fill out hash function seeds */
for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool), seed[i]);
+ IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool),
+ adapter->rss_key[i]);
/* Fill out the redirection table */
for (i = 0, j = 0; i < 64; i++, j++) {
if (j == rss_i)
j = 0;
- vfreta = (vfreta << 8) | j;
- if ((i & 3) == 3)
- IXGBE_WRITE_REG(hw, IXGBE_PFVFRETA(i >> 2, pf_pool),
- vfreta);
+
+ adapter->rss_indir_tbl[i] = j;
}
+
+ ixgbe_store_vfreta(adapter);
}
static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 mrqc = 0, rss_field = 0, vfmrqc = 0;
- u32 rss_key[10];
u32 rxcsum;
/* Disable indicating checksum in descriptor, enables RSS hash */
@@ -3354,7 +3413,7 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
- netdev_rss_key_fill(rss_key, sizeof(rss_key));
+ netdev_rss_key_fill(adapter->rss_key, sizeof(adapter->rss_key));
if ((hw->mac.type >= ixgbe_mac_X550) &&
(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) {
unsigned int pf_pool = adapter->num_vfs;
@@ -3364,12 +3423,12 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
/* Setup RSS through the VF registers */
- ixgbe_setup_vfreta(adapter, rss_key);
+ ixgbe_setup_vfreta(adapter);
vfmrqc = IXGBE_MRQC_RSSEN;
vfmrqc |= rss_field;
IXGBE_WRITE_REG(hw, IXGBE_PFVFMRQC(pf_pool), vfmrqc);
} else {
- ixgbe_setup_reta(adapter, rss_key);
+ ixgbe_setup_reta(adapter);
mrqc |= rss_field;
IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
@@ -3553,7 +3612,7 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1);
- if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+ if (adapter->bridge_mode == BRIDGE_MODE_VEB)
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
@@ -3599,6 +3658,10 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
/* enable ethertype anti spoofing if hw supports it */
if (hw->mac.ops.set_ethertype_anti_spoofing)
hw->mac.ops.set_ethertype_anti_spoofing(hw, true, i);
+
+ /* Enable/Disable RSS query feature */
+ ixgbe_ndo_set_vf_rss_query_en(adapter->netdev, i,
+ adapter->vfinfo[i].rss_query_enabled);
}
}
@@ -7870,6 +7933,80 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags);
}
+/**
+ * ixgbe_configure_bridge_mode - set various bridge modes
+ * @adapter - the private structure
+ * @mode - requested bridge mode
+ *
+ * Configure some settings require for various bridge modes.
+ **/
+static int ixgbe_configure_bridge_mode(struct ixgbe_adapter *adapter,
+ __u16 mode)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ unsigned int p, num_pools;
+ u32 vmdctl;
+
+ switch (mode) {
+ case BRIDGE_MODE_VEPA:
+ /* disable Tx loopback, rely on switch hairpin mode */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, 0);
+
+ /* must enable Rx switching replication to allow multicast
+ * packet reception on all VFs, and to enable source address
+ * pruning.
+ */
+ vmdctl = IXGBE_READ_REG(hw, IXGBE_VMD_CTL);
+ vmdctl |= IXGBE_VT_CTL_REPLEN;
+ IXGBE_WRITE_REG(hw, IXGBE_VMD_CTL, vmdctl);
+
+ /* enable Rx source address pruning. Note, this requires
+ * replication to be enabled or else it does nothing.
+ */
+ num_pools = adapter->num_vfs + adapter->num_rx_pools;
+ for (p = 0; p < num_pools; p++) {
+ if (hw->mac.ops.set_source_address_pruning)
+ hw->mac.ops.set_source_address_pruning(hw,
+ true,
+ p);
+ }
+ break;
+ case BRIDGE_MODE_VEB:
+ /* enable Tx loopback for internal VF/PF communication */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC,
+ IXGBE_PFDTXGSWC_VT_LBEN);
+
+ /* disable Rx switching replication unless we have SR-IOV
+ * virtual functions
+ */
+ vmdctl = IXGBE_READ_REG(hw, IXGBE_VMD_CTL);
+ if (!adapter->num_vfs)
+ vmdctl &= ~IXGBE_VT_CTL_REPLEN;
+ IXGBE_WRITE_REG(hw, IXGBE_VMD_CTL, vmdctl);
+
+ /* disable Rx source address pruning, since we don't expect to
+ * be receiving external loopback of our transmitted frames.
+ */
+ num_pools = adapter->num_vfs + adapter->num_rx_pools;
+ for (p = 0; p < num_pools; p++) {
+ if (hw->mac.ops.set_source_address_pruning)
+ hw->mac.ops.set_source_address_pruning(hw,
+ false,
+ p);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adapter->bridge_mode = mode;
+
+ e_info(drv, "enabling bridge mode: %s\n",
+ mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+
+ return 0;
+}
+
static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
struct nlmsghdr *nlh, u16 flags)
{
@@ -7885,8 +8022,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
return -EINVAL;
nla_for_each_nested(attr, br_spec, rem) {
+ u32 status;
__u16 mode;
- u32 reg = 0;
if (nla_type(attr) != IFLA_BRIDGE_MODE)
continue;
@@ -7895,19 +8032,11 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
return -EINVAL;
mode = nla_get_u16(attr);
- if (mode == BRIDGE_MODE_VEPA) {
- reg = 0;
- adapter->flags2 &= ~IXGBE_FLAG2_BRIDGE_MODE_VEB;
- } else if (mode == BRIDGE_MODE_VEB) {
- reg = IXGBE_PFDTXGSWC_VT_LBEN;
- adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
- } else
- return -EINVAL;
-
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg);
+ status = ixgbe_configure_bridge_mode(adapter, mode);
+ if (status)
+ return status;
- e_info(drv, "enabling bridge mode: %s\n",
- mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+ break;
}
return 0;
@@ -7918,17 +8047,12 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
u32 filter_mask)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- u16 mode;
if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
return 0;
- if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
- mode = BRIDGE_MODE_VEB;
- else
- mode = BRIDGE_MODE_VEPA;
-
- return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0);
+ return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
+ adapter->bridge_mode, 0, 0);
}
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
@@ -8040,6 +8164,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_vlan = ixgbe_ndo_set_vf_vlan,
.ndo_set_vf_rate = ixgbe_ndo_set_vf_bw,
.ndo_set_vf_spoofchk = ixgbe_ndo_set_vf_spoofchk,
+ .ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
#ifdef CONFIG_IXGBE_DCB
@@ -8394,7 +8519,6 @@ skip_sriov:
NETIF_F_IPV6_CSUM |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_RXHASH |
@@ -8416,6 +8540,7 @@ skip_sriov:
}
netdev->hw_features |= NETIF_F_RXALL;
+ netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_TSO6;
@@ -8977,8 +9102,6 @@ static void __exit ixgbe_exit_module(void)
pci_unregister_driver(&ixgbe_driver);
ixgbe_dbg_exit();
-
- rcu_barrier(); /* Wait for completion of call_rcu()'s */
}
#ifdef CONFIG_IXGBE_DCA