Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/jkirsher/next-queue

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-04-11

This series contains updates to iflink, ixgbe and ixgbevf.

The entire set of changes come from Vlad Zolotarov to ultimately add
the ethtool ops to VF driver to allow querying the RSS indirection table
and RSS random key.

Currently we support only 82599 and x540 devices.  On those devices, VFs
share the RSS redirection table and hash key with a PF.  Letting the VF
query this information may introduce some security risks, therefore this
feature will be disabled by default.

The new netdev op allows a system administrator to change the default
behaviour with "ip link set" command.  The relevant iproute2 patch has
already been sent and awaits for this series upstream.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 13, 2015
2 parents 1ceb0b8 + b641173 commit e60a9de
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 53 deletions.
11 changes: 11 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct vf_data_storage {
u16 tx_rate;
u16 vlan_count;
u8 spoofchk_enabled;
bool rss_query_enabled;
unsigned int vf_api;
};

Expand Down Expand Up @@ -766,6 +767,15 @@ struct ixgbe_adapter {

u8 default_up;
unsigned long fwd_bitmask; /* Bitmask indicating in use pools */

/* maximum number of RETA entries among all devices supported by ixgbe
* driver: currently it's x550 device in non-SRIOV mode
*/
#define IXGBE_MAX_RETA_ENTRIES 512
u8 rss_indir_tbl[IXGBE_MAX_RETA_ENTRIES];

#define IXGBE_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
u32 rss_key[IXGBE_RSS_KEY_SIZE / sizeof(u32)];
};

static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
Expand Down Expand Up @@ -955,4 +965,5 @@ void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter);
netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring);
u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter);
#endif /* _IXGBE_H_ */
42 changes: 42 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -2853,6 +2853,45 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return ret;
}

static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);

return sizeof(adapter->rss_key);
}

static u32 ixgbe_rss_indir_size(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);

return ixgbe_rss_indir_tbl_entries(adapter);
}

static void ixgbe_get_reta(struct ixgbe_adapter *adapter, u32 *indir)
{
int i, reta_size = ixgbe_rss_indir_tbl_entries(adapter);

for (i = 0; i < reta_size; i++)
indir[i] = adapter->rss_indir_tbl[i];
}

static int ixgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);

if (hfunc)
*hfunc = ETH_RSS_HASH_TOP;

if (indir)
ixgbe_get_reta(adapter, indir);

if (key)
memcpy(key, adapter->rss_key, ixgbe_get_rxfh_key_size(netdev));

return 0;
}

static int ixgbe_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
Expand Down Expand Up @@ -3110,6 +3149,9 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_coalesce = ixgbe_set_coalesce,
.get_rxnfc = ixgbe_get_rxnfc,
.set_rxnfc = ixgbe_set_rxnfc,
.get_rxfh_indir_size = ixgbe_rss_indir_size,
.get_rxfh_key_size = ixgbe_get_rxfh_key_size,
.get_rxfh = ixgbe_get_rxfh,
.get_channels = ixgbe_get_channels,
.set_channels = ixgbe_set_channels,
.get_ts_info = ixgbe_get_ts_info,
Expand Down
152 changes: 108 additions & 44 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -8101,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
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
Expand All @@ -97,6 +98,10 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */
#define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */

/* mailbox API, version 1.2 VF requests */
#define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */
#define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS key */

/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
Expand Down
Loading

0 comments on commit e60a9de

Please sign in to comment.