summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmritha Nambiar <amritha.nambiar@intel.com>2016-05-06 22:09:51 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-06-29 13:05:24 -0400
commit1ecedc926be12a91271e41913ebeba8cf32e9a6c (patch)
treec60995b4f0b9faed57b949356bb09a8ea33a511e
parent3d05b15b03daa4e8c350a97d0d83d2c2abc8b8ef (diff)
ixgbe: Fix deleting link filters for cls_u32 offloads
On deleting filters which are links to a child hash table, the filters in the child hash table must be cleared from the hardware if there is no link between the parent and child hash table. Verified with the following filters: Create a child hash table: handle 1: u32 divisor 1 Link to the child hash table from parent hash table: handle 800:0:10 u32 ht 800: link 1: \ offset at 0 mask 0f00 shift 6 plus 0 eat \ match ip protocol 6 ff match ip dst 15.0.0.1/32 Add filters into child hash table: handle 1:0:2 u32 ht 1: \ match tcp src 22 ffff action drop handle 1:0:3 u32 ht 1: \ match tcp src 33 ffff action drop Delete link filter from parent hash table: handle 800:0:10 u32 Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com> Acked-by: Sridhar Samudrala <sridhar.samudrala@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c75
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_model.h4
2 files changed, 72 insertions, 7 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 468fa9ddfa06..75e6855e2c13 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8300,14 +8300,50 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
8300static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter, 8300static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter,
8301 struct tc_cls_u32_offload *cls) 8301 struct tc_cls_u32_offload *cls)
8302{ 8302{
8303 u32 hdl = cls->knode.handle;
8303 u32 uhtid = TC_U32_USERHTID(cls->knode.handle); 8304 u32 uhtid = TC_U32_USERHTID(cls->knode.handle);
8304 u32 loc; 8305 u32 loc = cls->knode.handle & 0xfffff;
8305 int err; 8306 int err = 0, i, j;
8307 struct ixgbe_jump_table *jump = NULL;
8308
8309 if (loc > IXGBE_MAX_HW_ENTRIES)
8310 return -EINVAL;
8306 8311
8307 if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE)) 8312 if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE))
8308 return -EINVAL; 8313 return -EINVAL;
8309 8314
8310 loc = cls->knode.handle & 0xfffff; 8315 /* Clear this filter in the link data it is associated with */
8316 if (uhtid != 0x800) {
8317 jump = adapter->jump_tables[uhtid];
8318 if (jump)
8319 clear_bit(loc - 1, jump->child_loc_map);
8320 }
8321
8322 /* Check if the filter being deleted is a link */
8323 for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++) {
8324 jump = adapter->jump_tables[i];
8325 if (jump && jump->link_hdl == hdl) {
8326 /* Delete filters in the hardware in the child hash
8327 * table associated with this link
8328 */
8329 for (j = 0; j < IXGBE_MAX_HW_ENTRIES; j++) {
8330 if (!test_bit(j, jump->child_loc_map))
8331 continue;
8332 spin_lock(&adapter->fdir_perfect_lock);
8333 err = ixgbe_update_ethtool_fdir_entry(adapter,
8334 NULL,
8335 j + 1);
8336 spin_unlock(&adapter->fdir_perfect_lock);
8337 clear_bit(j, jump->child_loc_map);
8338 }
8339 /* Remove resources for this link */
8340 kfree(jump->input);
8341 kfree(jump->mask);
8342 kfree(jump);
8343 adapter->jump_tables[i] = NULL;
8344 return err;
8345 }
8346 }
8311 8347
8312 spin_lock(&adapter->fdir_perfect_lock); 8348 spin_lock(&adapter->fdir_perfect_lock);
8313 err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc); 8349 err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc);
@@ -8541,6 +8577,18 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
8541 if (!test_bit(link_uhtid - 1, &adapter->tables)) 8577 if (!test_bit(link_uhtid - 1, &adapter->tables))
8542 return err; 8578 return err;
8543 8579
8580 /* Multiple filters as links to the same hash table are not
8581 * supported. To add a new filter with the same next header
8582 * but different match/jump conditions, create a new hash table
8583 * and link to it.
8584 */
8585 if (adapter->jump_tables[link_uhtid] &&
8586 (adapter->jump_tables[link_uhtid])->link_hdl) {
8587 e_err(drv, "Link filter exists for link: %x\n",
8588 link_uhtid);
8589 return err;
8590 }
8591
8544 for (i = 0; nexthdr[i].jump; i++) { 8592 for (i = 0; nexthdr[i].jump; i++) {
8545 if (nexthdr[i].o != cls->knode.sel->offoff || 8593 if (nexthdr[i].o != cls->knode.sel->offoff ||
8546 nexthdr[i].s != cls->knode.sel->offshift || 8594 nexthdr[i].s != cls->knode.sel->offshift ||
@@ -8558,10 +8606,12 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
8558 mask = kzalloc(sizeof(*mask), GFP_KERNEL); 8606 mask = kzalloc(sizeof(*mask), GFP_KERNEL);
8559 if (!mask) { 8607 if (!mask) {
8560 err = -ENOMEM; 8608 err = -ENOMEM;
8561 goto free_input; 8609 goto err_out;
8562 } 8610 }
8563 jump->input = input; 8611 jump->input = input;
8564 jump->mask = mask; 8612 jump->mask = mask;
8613 jump->link_hdl = cls->knode.handle;
8614
8565 err = ixgbe_clsu32_build_input(input, mask, cls, 8615 err = ixgbe_clsu32_build_input(input, mask, cls,
8566 field_ptr, &nexthdr[i]); 8616 field_ptr, &nexthdr[i]);
8567 if (!err) { 8617 if (!err) {
@@ -8579,7 +8629,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
8579 mask = kzalloc(sizeof(*mask), GFP_KERNEL); 8629 mask = kzalloc(sizeof(*mask), GFP_KERNEL);
8580 if (!mask) { 8630 if (!mask) {
8581 err = -ENOMEM; 8631 err = -ENOMEM;
8582 goto free_input; 8632 goto err_out;
8583 } 8633 }
8584 8634
8585 if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) { 8635 if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
@@ -8620,14 +8670,25 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
8620 ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); 8670 ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
8621 spin_unlock(&adapter->fdir_perfect_lock); 8671 spin_unlock(&adapter->fdir_perfect_lock);
8622 8672
8673 if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
8674 struct ixgbe_jump_table *link = adapter->jump_tables[uhtid];
8675
8676 if (test_bit(loc - 1, link->child_loc_map)) {
8677 e_err(drv, "Filter: %x exists in hash table: %x\n",
8678 loc, uhtid);
8679 err = -EINVAL;
8680 goto free_mask;
8681 }
8682 set_bit(loc - 1, link->child_loc_map);
8683 }
8623 kfree(mask); 8684 kfree(mask);
8624 return err; 8685 return err;
8625err_out_w_lock: 8686err_out_w_lock:
8626 spin_unlock(&adapter->fdir_perfect_lock); 8687 spin_unlock(&adapter->fdir_perfect_lock);
8627err_out: 8688err_out:
8628 kfree(mask);
8629free_input:
8630 kfree(input); 8689 kfree(input);
8690free_mask:
8691 kfree(mask);
8631free_jump: 8692free_jump:
8632 kfree(jump); 8693 kfree(jump);
8633 return err; 8694 return err;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
index a8bed3d887f7..538a1c5475b6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h
@@ -42,8 +42,12 @@ struct ixgbe_jump_table {
42 struct ixgbe_mat_field *mat; 42 struct ixgbe_mat_field *mat;
43 struct ixgbe_fdir_filter *input; 43 struct ixgbe_fdir_filter *input;
44 union ixgbe_atr_input *mask; 44 union ixgbe_atr_input *mask;
45 u32 link_hdl;
46 unsigned long child_loc_map[32];
45}; 47};
46 48
49#define IXGBE_MAX_HW_ENTRIES 2045
50
47static inline int ixgbe_mat_prgm_sip(struct ixgbe_fdir_filter *input, 51static inline int ixgbe_mat_prgm_sip(struct ixgbe_fdir_filter *input,
48 union ixgbe_atr_input *mask, 52 union ixgbe_atr_input *mask,
49 u32 val, u32 m) 53 u32 val, u32 m)