| From 55e27956e55c4775f24cfbc13b2679b8457836f6 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 27 Nov 2019 17:03:55 +0800 |
| Subject: ixgbe: Fix calculation of queue with VFs and flow director on |
| interface flap |
| |
| From: Cambda Zhu <cambda@linux.alibaba.com> |
| |
| [ Upstream commit 4fad78ad6422d9bca62135bbed8b6abc4cbb85b8 ] |
| |
| This patch fixes the calculation of queue when we restore flow director |
| filters after resetting adapter. In ixgbe_fdir_filter_restore(), filter's |
| vf may be zero which makes the queue outside of the rx_ring array. |
| |
| The calculation is changed to the same as ixgbe_add_ethtool_fdir_entry(). |
| |
| Signed-off-by: Cambda Zhu <cambda@linux.alibaba.com> |
| Tested-by: Andrew Bowers <andrewx.bowers@intel.com> |
| Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 37 ++++++++++++++----- |
| 1 file changed, 27 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |
| index c6404abf2dd18..a26f9fb95ac0a 100644 |
| --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |
| +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |
| @@ -5239,7 +5239,7 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter) |
| struct ixgbe_hw *hw = &adapter->hw; |
| struct hlist_node *node2; |
| struct ixgbe_fdir_filter *filter; |
| - u64 action; |
| + u8 queue; |
| |
| spin_lock(&adapter->fdir_perfect_lock); |
| |
| @@ -5248,17 +5248,34 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter) |
| |
| hlist_for_each_entry_safe(filter, node2, |
| &adapter->fdir_filter_list, fdir_node) { |
| - action = filter->action; |
| - if (action != IXGBE_FDIR_DROP_QUEUE && action != 0) |
| - action = |
| - (action >> ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) - 1; |
| + if (filter->action == IXGBE_FDIR_DROP_QUEUE) { |
| + queue = IXGBE_FDIR_DROP_QUEUE; |
| + } else { |
| + u32 ring = ethtool_get_flow_spec_ring(filter->action); |
| + u8 vf = ethtool_get_flow_spec_ring_vf(filter->action); |
| + |
| + if (!vf && (ring >= adapter->num_rx_queues)) { |
| + e_err(drv, "FDIR restore failed without VF, ring: %u\n", |
| + ring); |
| + continue; |
| + } else if (vf && |
| + ((vf > adapter->num_vfs) || |
| + ring >= adapter->num_rx_queues_per_pool)) { |
| + e_err(drv, "FDIR restore failed with VF, vf: %hhu, ring: %u\n", |
| + vf, ring); |
| + continue; |
| + } |
| + |
| + /* Map the ring onto the absolute queue index */ |
| + if (!vf) |
| + queue = adapter->rx_ring[ring]->reg_idx; |
| + else |
| + queue = ((vf - 1) * |
| + adapter->num_rx_queues_per_pool) + ring; |
| + } |
| |
| ixgbe_fdir_write_perfect_filter_82599(hw, |
| - &filter->filter, |
| - filter->sw_idx, |
| - (action == IXGBE_FDIR_DROP_QUEUE) ? |
| - IXGBE_FDIR_DROP_QUEUE : |
| - adapter->rx_ring[action]->reg_idx); |
| + &filter->filter, filter->sw_idx, queue); |
| } |
| |
| spin_unlock(&adapter->fdir_perfect_lock); |
| -- |
| 2.20.1 |
| |