net/ixgbe: fix queue resource leak
[dpdk.git] / drivers / net / hinic / hinic_pmd_flow.c
index cc0744d..d71a42a 100644 (file)
@@ -694,6 +694,7 @@ static int hinic_ntuple_item_check_end(const struct rte_flow_item *item,
                        item, "Not supported by ntuple filter");
                return -rte_errno;
        }
+
        return 0;
 }
 
@@ -1900,6 +1901,8 @@ void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev)
 {
        (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false);
 
+       (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false);
+
        (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_DPORT);
 
        (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT);
@@ -2349,6 +2352,8 @@ hinic_add_del_ethertype_filter(struct rte_eth_dev *dev,
                ethertype_filter.pkt_proto = filter->ether_type;
                i = hinic_ethertype_filter_lookup(filter_info,
                                                &ethertype_filter);
+               if (i < 0)
+                       return -EINVAL;
 
                if ((filter_info->type_mask & (1 << i))) {
                        filter_info->pkt_filters[i].enable = FALSE;
@@ -2801,6 +2806,19 @@ static int hinic_add_tcam_filter(struct rte_eth_dev *dev,
                                                fdir_tcam_rule->index);
                        return rc;
                }
+
+               rc = hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true);
+               if (rc && rc != HINIC_MGMT_CMD_UNSUPPORTED) {
+                       /*
+                        * hinic supports two methods: linear table and tcam
+                        * table, if tcam filter enables failed but linear table
+                        * is ok, which also needs to enable filter, so for this
+                        * scene, driver should not close fdir switch.
+                        */
+                       (void)hinic_del_tcam_rule(nic_dev->hwdev,
+                                               fdir_tcam_rule->index);
+                       return rc;
+               }
        }
 
        TAILQ_INSERT_TAIL(&tcam_info->tcam_list, tcam_filter, entries);
@@ -2966,6 +2984,12 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
                if (!ret) {
                        ntuple_filter_ptr = rte_zmalloc("hinic_ntuple_filter",
                                sizeof(struct hinic_ntuple_filter_ele), 0);
+                       if (ntuple_filter_ptr == NULL) {
+                               PMD_DRV_LOG(ERR, "Failed to allocate ntuple_filter_ptr");
+                               (void)hinic_add_del_ntuple_filter(dev,
+                                                       &ntuple_filter, FALSE);
+                               goto out;
+                       }
                        rte_memcpy(&ntuple_filter_ptr->filter_info,
                                   &ntuple_filter,
                                   sizeof(struct rte_eth_ntuple_filter));
@@ -2992,6 +3016,12 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
                        ethertype_filter_ptr =
                                rte_zmalloc("hinic_ethertype_filter",
                                sizeof(struct hinic_ethertype_filter_ele), 0);
+                       if (ethertype_filter_ptr == NULL) {
+                               PMD_DRV_LOG(ERR, "Failed to allocate ethertype_filter_ptr");
+                               (void)hinic_add_del_ethertype_filter(dev,
+                                               &ethertype_filter, FALSE);
+                               goto out;
+                       }
                        rte_memcpy(&ethertype_filter_ptr->filter_info,
                                &ethertype_filter,
                                sizeof(struct rte_eth_ethertype_filter));
@@ -3013,11 +3043,10 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
                                      actions, &fdir_rule, error);
        if (!ret) {
                if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) {
-                       ret = hinic_add_del_fdir_filter(dev,
-                                       &fdir_rule, TRUE);
+                       ret = hinic_add_del_fdir_filter(dev, &fdir_rule, TRUE);
                } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) {
-                       ret = hinic_add_del_tcam_fdir_filter(dev,
-                                       &fdir_rule, TRUE);
+                       ret = hinic_add_del_tcam_fdir_filter(dev, &fdir_rule,
+                                                            TRUE);
                }  else {
                        PMD_DRV_LOG(INFO, "flow fdir rule create failed, rule mode wrong");
                        goto out;
@@ -3025,6 +3054,17 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
                if (!ret) {
                        fdir_rule_ptr = rte_zmalloc("hinic_fdir_rule",
                                sizeof(struct hinic_fdir_rule_ele), 0);
+                       if (fdir_rule_ptr == NULL) {
+                               PMD_DRV_LOG(ERR, "Failed to allocate fdir_rule_ptr");
+                               if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL)
+                                       hinic_add_del_fdir_filter(dev,
+                                               &fdir_rule, FALSE);
+                               else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM)
+                                       hinic_add_del_tcam_fdir_filter(dev,
+                                               &fdir_rule, FALSE);
+
+                               goto out;
+                       }
                        rte_memcpy(&fdir_rule_ptr->filter_info, &fdir_rule,
                                sizeof(struct hinic_fdir_rule));
                        TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list,
@@ -3197,6 +3237,8 @@ static void hinic_clear_all_fdir_filter(struct rte_eth_dev *dev)
 
        (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false);
 
+       (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false);
+
        (void)hinic_flush_tcam_rule(nic_dev->hwdev);
 }