i40e: Allow RSS Hash set with less than four parameters
This patch implements a feature change which allows using ethtool to set RSS hash opts using less than four parameters if desired. Change-ID: I0fbb91255d81e997c456697c21ac39cc9754821b Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com> Signed-off-by: Kiran Patil <kiran.patil@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Родитель
b7d2cd951f
Коммит
eb0dd6e4a3
|
@ -586,9 +586,6 @@ struct i40e_vsi {
|
||||||
|
|
||||||
/* VSI specific handlers */
|
/* VSI specific handlers */
|
||||||
irqreturn_t (*irq_handler)(int irq, void *data);
|
irqreturn_t (*irq_handler)(int irq, void *data);
|
||||||
|
|
||||||
/* current rxnfc data */
|
|
||||||
struct ethtool_rxnfc rxnfc; /* current rss hash opts */
|
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
struct i40e_netdev_priv {
|
struct i40e_netdev_priv {
|
||||||
|
|
|
@ -2141,41 +2141,72 @@ static int i40e_set_per_queue_coalesce(struct net_device *netdev, u32 queue,
|
||||||
**/
|
**/
|
||||||
static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
|
static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
|
||||||
{
|
{
|
||||||
|
struct i40e_hw *hw = &pf->hw;
|
||||||
|
u8 flow_pctype = 0;
|
||||||
|
u64 i_set = 0;
|
||||||
|
|
||||||
cmd->data = 0;
|
cmd->data = 0;
|
||||||
|
|
||||||
if (pf->vsi[pf->lan_vsi]->rxnfc.data != 0) {
|
|
||||||
cmd->data = pf->vsi[pf->lan_vsi]->rxnfc.data;
|
|
||||||
cmd->flow_type = pf->vsi[pf->lan_vsi]->rxnfc.flow_type;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Report default options for RSS on i40e */
|
|
||||||
switch (cmd->flow_type) {
|
switch (cmd->flow_type) {
|
||||||
case TCP_V4_FLOW:
|
case TCP_V4_FLOW:
|
||||||
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
|
||||||
|
break;
|
||||||
case UDP_V4_FLOW:
|
case UDP_V4_FLOW:
|
||||||
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
|
||||||
/* fall through to add IP fields */
|
break;
|
||||||
|
case TCP_V6_FLOW:
|
||||||
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
|
||||||
|
break;
|
||||||
|
case UDP_V6_FLOW:
|
||||||
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
|
||||||
|
break;
|
||||||
case SCTP_V4_FLOW:
|
case SCTP_V4_FLOW:
|
||||||
case AH_ESP_V4_FLOW:
|
case AH_ESP_V4_FLOW:
|
||||||
case AH_V4_FLOW:
|
case AH_V4_FLOW:
|
||||||
case ESP_V4_FLOW:
|
case ESP_V4_FLOW:
|
||||||
case IPV4_FLOW:
|
case IPV4_FLOW:
|
||||||
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
|
|
||||||
break;
|
|
||||||
case TCP_V6_FLOW:
|
|
||||||
case UDP_V6_FLOW:
|
|
||||||
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
|
||||||
/* fall through to add IP fields */
|
|
||||||
case SCTP_V6_FLOW:
|
case SCTP_V6_FLOW:
|
||||||
case AH_ESP_V6_FLOW:
|
case AH_ESP_V6_FLOW:
|
||||||
case AH_V6_FLOW:
|
case AH_V6_FLOW:
|
||||||
case ESP_V6_FLOW:
|
case ESP_V6_FLOW:
|
||||||
case IPV6_FLOW:
|
case IPV6_FLOW:
|
||||||
|
/* Default is src/dest for IP, no matter the L4 hashing */
|
||||||
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
|
cmd->data |= RXH_IP_SRC | RXH_IP_DST;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read flow based hash input set register */
|
||||||
|
if (flow_pctype) {
|
||||||
|
i_set = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0,
|
||||||
|
flow_pctype)) |
|
||||||
|
((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1,
|
||||||
|
flow_pctype)) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process bits of hash input set */
|
||||||
|
if (i_set) {
|
||||||
|
if (i_set & I40E_L4_SRC_MASK)
|
||||||
|
cmd->data |= RXH_L4_B_0_1;
|
||||||
|
if (i_set & I40E_L4_DST_MASK)
|
||||||
|
cmd->data |= RXH_L4_B_2_3;
|
||||||
|
|
||||||
|
if (cmd->flow_type == TCP_V4_FLOW ||
|
||||||
|
cmd->flow_type == UDP_V4_FLOW) {
|
||||||
|
if (i_set & I40E_L3_SRC_MASK)
|
||||||
|
cmd->data |= RXH_IP_SRC;
|
||||||
|
if (i_set & I40E_L3_DST_MASK)
|
||||||
|
cmd->data |= RXH_IP_DST;
|
||||||
|
} else if (cmd->flow_type == TCP_V6_FLOW ||
|
||||||
|
cmd->flow_type == UDP_V6_FLOW) {
|
||||||
|
if (i_set & I40E_L3_V6_SRC_MASK)
|
||||||
|
cmd->data |= RXH_IP_SRC;
|
||||||
|
if (i_set & I40E_L3_V6_DST_MASK)
|
||||||
|
cmd->data |= RXH_IP_DST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2317,6 +2348,51 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40e_get_rss_hash_bits - Read RSS Hash bits from register
|
||||||
|
* @nfc: pointer to user request
|
||||||
|
* @i_setc bits currently set
|
||||||
|
*
|
||||||
|
* Returns value of bits to be set per user request
|
||||||
|
**/
|
||||||
|
static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc)
|
||||||
|
{
|
||||||
|
u64 i_set = i_setc;
|
||||||
|
u64 src_l3 = 0, dst_l3 = 0;
|
||||||
|
|
||||||
|
if (nfc->data & RXH_L4_B_0_1)
|
||||||
|
i_set |= I40E_L4_SRC_MASK;
|
||||||
|
else
|
||||||
|
i_set &= ~I40E_L4_SRC_MASK;
|
||||||
|
if (nfc->data & RXH_L4_B_2_3)
|
||||||
|
i_set |= I40E_L4_DST_MASK;
|
||||||
|
else
|
||||||
|
i_set &= ~I40E_L4_DST_MASK;
|
||||||
|
|
||||||
|
if (nfc->flow_type == TCP_V6_FLOW || nfc->flow_type == UDP_V6_FLOW) {
|
||||||
|
src_l3 = I40E_L3_V6_SRC_MASK;
|
||||||
|
dst_l3 = I40E_L3_V6_DST_MASK;
|
||||||
|
} else if (nfc->flow_type == TCP_V4_FLOW ||
|
||||||
|
nfc->flow_type == UDP_V4_FLOW) {
|
||||||
|
src_l3 = I40E_L3_SRC_MASK;
|
||||||
|
dst_l3 = I40E_L3_DST_MASK;
|
||||||
|
} else {
|
||||||
|
/* Any other flow type are not supported here */
|
||||||
|
return i_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfc->data & RXH_IP_SRC)
|
||||||
|
i_set |= src_l3;
|
||||||
|
else
|
||||||
|
i_set &= ~src_l3;
|
||||||
|
if (nfc->data & RXH_IP_DST)
|
||||||
|
i_set |= dst_l3;
|
||||||
|
else
|
||||||
|
i_set &= ~dst_l3;
|
||||||
|
|
||||||
|
return i_set;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash
|
* i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash
|
||||||
* @pf: pointer to the physical function struct
|
* @pf: pointer to the physical function struct
|
||||||
|
@ -2329,6 +2405,8 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
|
||||||
struct i40e_hw *hw = &pf->hw;
|
struct i40e_hw *hw = &pf->hw;
|
||||||
u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) |
|
u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) |
|
||||||
((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32);
|
((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32);
|
||||||
|
u8 flow_pctype = 0;
|
||||||
|
u64 i_set, i_setc;
|
||||||
|
|
||||||
/* RSS does not support anything other than hashing
|
/* RSS does not support anything other than hashing
|
||||||
* to queues on src and dst IPs and ports
|
* to queues on src and dst IPs and ports
|
||||||
|
@ -2337,75 +2415,39 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
|
||||||
RXH_L4_B_0_1 | RXH_L4_B_2_3))
|
RXH_L4_B_0_1 | RXH_L4_B_2_3))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* We need at least the IP SRC and DEST fields for hashing */
|
|
||||||
if (!(nfc->data & RXH_IP_SRC) ||
|
|
||||||
!(nfc->data & RXH_IP_DST))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
switch (nfc->flow_type) {
|
switch (nfc->flow_type) {
|
||||||
case TCP_V4_FLOW:
|
case TCP_V4_FLOW:
|
||||||
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
|
||||||
case 0:
|
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
||||||
return -EINVAL;
|
hena |=
|
||||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
|
||||||
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
|
||||||
hena |=
|
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
|
|
||||||
|
|
||||||
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TCP_V6_FLOW:
|
case TCP_V6_FLOW:
|
||||||
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
|
||||||
case 0:
|
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
||||||
return -EINVAL;
|
hena |=
|
||||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
|
||||||
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
||||||
hena |=
|
hena |=
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
|
||||||
|
|
||||||
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case UDP_V4_FLOW:
|
case UDP_V4_FLOW:
|
||||||
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
|
||||||
case 0:
|
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
||||||
return -EINVAL;
|
hena |=
|
||||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
|
||||||
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
|
||||||
hena |=
|
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
|
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
|
|
||||||
|
|
||||||
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
|
hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4);
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case UDP_V6_FLOW:
|
case UDP_V6_FLOW:
|
||||||
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
|
flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
|
||||||
case 0:
|
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
||||||
return -EINVAL;
|
hena |=
|
||||||
case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
|
||||||
if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE)
|
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
|
||||||
hena |=
|
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
|
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
|
|
||||||
|
|
||||||
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
|
hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6);
|
||||||
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case AH_ESP_V4_FLOW:
|
case AH_ESP_V4_FLOW:
|
||||||
case AH_V4_FLOW:
|
case AH_V4_FLOW:
|
||||||
|
@ -2437,13 +2479,23 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow_pctype) {
|
||||||
|
i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0,
|
||||||
|
flow_pctype)) |
|
||||||
|
((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1,
|
||||||
|
flow_pctype)) << 32);
|
||||||
|
i_set = i40e_get_rss_hash_bits(nfc, i_setc);
|
||||||
|
i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype),
|
||||||
|
(u32)i_set);
|
||||||
|
i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype),
|
||||||
|
(u32)(i_set >> 32));
|
||||||
|
hena |= BIT_ULL(flow_pctype);
|
||||||
|
}
|
||||||
|
|
||||||
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena);
|
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena);
|
||||||
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
|
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
|
||||||
i40e_flush(hw);
|
i40e_flush(hw);
|
||||||
|
|
||||||
/* Save setting for future output/update */
|
|
||||||
pf->vsi[pf->lan_vsi]->rxnfc = *nfc;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче