i40e: Fix for extra Flow Director filter in table after error
authorCarolyn Wyborny <carolyn.wyborny@intel.com>
Thu, 27 Aug 2015 15:42:38 +0000 (11:42 -0400)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 8 Oct 2015 22:24:28 +0000 (15:24 -0700)
This patch fixes a problem where the PF's fdir filter table would have an
entry that the hw was unable to add. This notification happens in the hot
path, so instead of trying to fix it then, we note the location in the
failure case and delete it during regular fdir subtask callback. Without
this patch, a case can occur where an invalid entry gets replayed and a
valid one is not.

Change-ID: I67831c183b5d0309876de807cc434809b74c9cb7
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Signed-off-by: Shannon Nelson <shannon.nelson@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c

index 7a3c9397235613eda8bb2fc74d4aa9d7ee71ddaf..a662e3961951c7aebcdc889de30f1e43158aa3eb 100644 (file)
@@ -410,6 +410,7 @@ struct i40e_pf {
        u32 npar_min_bw;
 
        u32 ioremap_len;
+       u32 fd_inv;
 };
 
 struct i40e_mac_filter {
index 2c5921483dc8443680e20253a975df6c1989951a..949535684fa9f1bc0fecfe1480296c39d24fa44f 100644 (file)
@@ -5614,7 +5614,9 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf)
  **/
 void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
 {
+       struct i40e_fdir_filter *filter;
        u32 fcnt_prog, fcnt_avail;
+       struct hlist_node *node;
 
        if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
                return;
@@ -5643,6 +5645,18 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
                                dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table now\n");
                }
        }
+
+       /* if hw had a problem adding a filter, delete it */
+       if (pf->fd_inv > 0) {
+               hlist_for_each_entry_safe(filter, node,
+                                         &pf->fdir_filter_list, fdir_node) {
+                       if (filter->fd_id == pf->fd_inv) {
+                               hlist_del(&filter->fdir_node);
+                               kfree(filter);
+                               pf->fdir_pf_active_filters--;
+                       }
+               }
+       }
 }
 
 #define I40E_MIN_FD_FLUSH_INTERVAL 10
index 889ed10f588b18612f5338c369d7fadbef3d308e..8ab7ab1623f2fb3f7c8ff32c7e88a7c83ee8f71e 100644 (file)
@@ -465,10 +465,11 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
                I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
 
        if (error == BIT(I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) {
+               pf->fd_inv = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fd_id);
                if ((rx_desc->wb.qword0.hi_dword.fd_id != 0) ||
                    (I40E_DEBUG_FD & pf->hw.debug_mask))
                        dev_warn(&pdev->dev, "ntuple filter loc = %d, could not be added\n",
-                                rx_desc->wb.qword0.hi_dword.fd_id);
+                                pf->fd_inv);
 
                /* Check if the programming error is for ATR.
                 * If so, auto disable ATR and set a state for