X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fhns3%2Fhns3_fdir.c;h=d043f5786dce4c8976fb437f23ad32c93d9a2a34;hb=7fe741821337f3cbeecac768b8ef3a16bf21c938;hp=e6a065b6bc3522411f4fd9b36fd74c52635d3005;hpb=9a7d3af22c9b8a9042cc54601a7ac066cb57d16c;p=dpdk.git diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c index e6a065b6bc..d043f5786d 100644 --- a/drivers/net/hns3/hns3_fdir.c +++ b/drivers/net/hns3/hns3_fdir.c @@ -1,9 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018-2019 Hisilicon Limited. + * Copyright(c) 2018-2021 HiSilicon Limited. */ -#include -#include +#include #include #include #include @@ -46,6 +45,8 @@ #define HNS3_FD_AD_QUEUE_REGION_SIZE_M GENMASK(20, 17) #define HNS3_FD_AD_COUNTER_HIGH_BIT 7 #define HNS3_FD_AD_COUNTER_HIGH_BIT_B 26 +#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT 10 +#define HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B 21 enum HNS3_PORT_TYPE { HOST_PORT, @@ -319,7 +320,7 @@ int hns3_init_fd_config(struct hns3_adapter *hns) hns3_warn(hw, "Unsupported tunnel filter in 4K*200Bit"); break; default: - hns3_err(hw, "Unsupported flow director mode %d", + hns3_err(hw, "Unsupported flow director mode %u", pf->fdir.fd_cfg.fd_mode); return -EOPNOTSUPP; } @@ -335,6 +336,8 @@ int hns3_init_fd_config(struct hns3_adapter *hns) BIT(INNER_IP_PROTO) | BIT(INNER_IP_TOS) | BIT(INNER_SRC_IP) | BIT(INNER_DST_IP) | BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT); + hns3_dbg(hw, "fdir tuple: inner"); /* If use max 400bit key, we can support tuples for ether type */ if (pf->fdir.fd_cfg.max_key_length == MAX_KEY_LENGTH) { @@ -344,6 +347,9 @@ int hns3_init_fd_config(struct hns3_adapter *hns) BIT(OUTER_DST_PORT) | BIT(INNER_VLAN_TAG2) | BIT(OUTER_TUN_VNI) | BIT(OUTER_TUN_FLOW_ID) | BIT(OUTER_ETH_TYPE) | BIT(OUTER_IP_PROTO); + hns3_dbg(hw, "fdir tuple more: inner outer"); } /* roce_type is used to filter roce frames @@ -351,6 +357,7 @@ int hns3_init_fd_config(struct hns3_adapter *hns) */ key_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET) | BIT(VLAN_NUMBER); + hns3_dbg(hw, "fdir meta data: dst_vport tunnel_packet vlan_number"); ret = hns3_get_fd_allocation(hw, &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1], @@ -360,6 +367,13 @@ int hns3_init_fd_config(struct hns3_adapter *hns) if (ret) return ret; + hns3_dbg(hw, "fdir: stage1 stage2", + pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1], + pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1], + pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2], + pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]); + return hns3_set_fd_key_config(hns); } @@ -437,6 +451,9 @@ static int hns3_fd_ad_config(struct hns3_hw *hw, int loc, /* set extend bit if counter_id is in [128 ~ 255] */ if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT)) hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1); + /* set extend bit if queue id > 1024 */ + if (action->queue_id & BIT(HNS3_FD_AD_QUEUE_ID_HIGH_BIT)) + hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_ID_HIGH_BIT_B, 1); ad_data <<= HNS3_FD_AD_DATA_S; hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet); if (action->nb_queues == 1) @@ -613,7 +630,7 @@ static bool hns3_fd_convert_tuple(struct hns3_hw *hw, key_conf->mask.ip_proto); break; default: - hns3_warn(hw, "not support tuple of (%d)", tuple); + hns3_warn(hw, "not support tuple of (%u)", tuple); break; } return true; @@ -740,14 +757,14 @@ static int hns3_config_key(struct hns3_adapter *hns, ret = hns3_fd_tcam_config(hw, false, rule->location, key_y, true); if (ret) { - hns3_err(hw, "Config fd key_y fail, loc=%d, ret=%d", + hns3_err(hw, "Config fd key_y fail, loc=%u, ret=%d", rule->queue_id, ret); return ret; } ret = hns3_fd_tcam_config(hw, true, rule->location, key_x, true); if (ret) - hns3_err(hw, "Config fd key_x fail, loc=%d, ret=%d", + hns3_err(hw, "Config fd key_x fail, loc=%u, ret=%d", rule->queue_id, ret); return ret; } @@ -826,7 +843,6 @@ int hns3_fdir_filter_init(struct hns3_adapter *hns) fdir_hash_params.socket_id = rte_socket_id(); TAILQ_INIT(&fdir_info->fdir_list); - rte_spinlock_init(&fdir_info->flows_lock); snprintf(fdir_hash_name, RTE_HASH_NAMESIZE, "%s", hns->hw.data->name); fdir_info->hash_handle = rte_hash_create(&fdir_hash_params); if (fdir_info->hash_handle == NULL) { @@ -852,7 +868,6 @@ void hns3_fdir_filter_uninit(struct hns3_adapter *hns) struct hns3_fdir_info *fdir_info = &pf->fdir; struct hns3_fdir_rule_ele *fdir_filter; - rte_spinlock_lock(&fdir_info->flows_lock); if (fdir_info->hash_map) { rte_free(fdir_info->hash_map); fdir_info->hash_map = NULL; @@ -861,7 +876,6 @@ void hns3_fdir_filter_uninit(struct hns3_adapter *hns) rte_hash_free(fdir_info->hash_handle); fdir_info->hash_handle = NULL; } - rte_spinlock_unlock(&fdir_info->flows_lock); fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list); while (fdir_filter) { @@ -887,10 +901,8 @@ static int hns3_fdir_filter_lookup(struct hns3_fdir_info *fdir_info, hash_sig_t sig; int ret; - rte_spinlock_lock(&fdir_info->flows_lock); sig = rte_hash_crc(key, sizeof(*key), 0); ret = rte_hash_lookup_with_hash(fdir_info->hash_handle, key, sig); - rte_spinlock_unlock(&fdir_info->flows_lock); return ret; } @@ -904,11 +916,9 @@ static int hns3_insert_fdir_filter(struct hns3_hw *hw, int ret; key = &fdir_filter->fdir_conf.key_conf; - rte_spinlock_lock(&fdir_info->flows_lock); sig = rte_hash_crc(key, sizeof(*key), 0); ret = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig); if (ret < 0) { - rte_spinlock_unlock(&fdir_info->flows_lock); hns3_err(hw, "Hash table full? err:%d(%s)!", ret, strerror(-ret)); return ret; @@ -916,7 +926,6 @@ static int hns3_insert_fdir_filter(struct hns3_hw *hw, fdir_info->hash_map[ret] = fdir_filter; TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries); - rte_spinlock_unlock(&fdir_info->flows_lock); return ret; } @@ -929,11 +938,9 @@ static int hns3_remove_fdir_filter(struct hns3_hw *hw, hash_sig_t sig; int ret; - rte_spinlock_lock(&fdir_info->flows_lock); sig = rte_hash_crc(key, sizeof(*key), 0); ret = rte_hash_del_key_with_hash(fdir_info->hash_handle, key, sig); if (ret < 0) { - rte_spinlock_unlock(&fdir_info->flows_lock); hns3_err(hw, "Delete hash key fail ret=%d", ret); return ret; } @@ -941,7 +948,6 @@ static int hns3_remove_fdir_filter(struct hns3_hw *hw, fdir_filter = fdir_info->hash_map[ret]; fdir_info->hash_map[ret] = NULL; TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries); - rte_spinlock_unlock(&fdir_info->flows_lock); rte_free(fdir_filter); @@ -961,8 +967,8 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns, ret = hns3_fd_tcam_config(hw, true, rule->location, NULL, false); if (ret) - hns3_err(hw, "Failed to delete fdir: %d src_ip:%x " - "dst_ip:%x src_port:%d dst_port:%d ret = %d", + hns3_err(hw, "Failed to delete fdir: %u src_ip:%x " + "dst_ip:%x src_port:%u dst_port:%u ret = %d", rule->location, rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID], rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID], @@ -996,14 +1002,12 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns, rule->location = ret; node->fdir_conf.location = ret; - rte_spinlock_lock(&fdir_info->flows_lock); ret = hns3_config_action(hw, rule); if (!ret) ret = hns3_config_key(hns, rule); - rte_spinlock_unlock(&fdir_info->flows_lock); if (ret) { - hns3_err(hw, "Failed to config fdir: %d src_ip:%x dst_ip:%x " - "src_port:%d dst_port:%d ret = %d", + hns3_err(hw, "Failed to config fdir: %u src_ip:%x dst_ip:%x " + "src_port:%u dst_port:%u ret = %d", rule->location, rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID], rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID], @@ -1022,27 +1026,37 @@ int hns3_clear_all_fdir_filter(struct hns3_adapter *hns) struct hns3_fdir_info *fdir_info = &pf->fdir; struct hns3_fdir_rule_ele *fdir_filter; struct hns3_hw *hw = &hns->hw; + int succ_cnt = 0; + int fail_cnt = 0; int ret = 0; /* flush flow director */ - rte_spinlock_lock(&fdir_info->flows_lock); rte_hash_reset(fdir_info->hash_handle); - rte_spinlock_unlock(&fdir_info->flows_lock); + + memset(fdir_info->hash_map, 0, + sizeof(struct hns3_fdir_rule_ele *) * + fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1]); fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list); while (fdir_filter) { TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries); - ret += hns3_fd_tcam_config(hw, true, - fdir_filter->fdir_conf.location, - NULL, false); + ret = hns3_fd_tcam_config(hw, true, + fdir_filter->fdir_conf.location, + NULL, false); + if (ret == 0) + succ_cnt++; + else + fail_cnt++; rte_free(fdir_filter); fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list); } - if (ret) { - hns3_err(hw, "Fail to delete FDIR filter, ret = %d", ret); + if (fail_cnt > 0) { + hns3_err(hw, "fail to delete all FDIR filter, success num = %d " + "fail num = %d", succ_cnt, fail_cnt); ret = -EIO; } + return ret; } @@ -1055,6 +1069,17 @@ int hns3_restore_all_fdir_filter(struct hns3_adapter *hns) bool err = false; int ret; + /* + * This API is called in the reset recovery process, the parent function + * must hold hw->lock. + * There maybe deadlock if acquire hw->flows_lock directly because rte + * flow driver ops first acquire hw->flows_lock and then may acquire + * hw->lock. + * So here first release the hw->lock and then acquire the + * hw->flows_lock to avoid deadlock. + */ + rte_spinlock_unlock(&hw->lock); + pthread_mutex_lock(&hw->flows_lock); TAILQ_FOREACH(fdir_filter, &fdir_info->fdir_list, entries) { ret = hns3_config_action(hw, &fdir_filter->fdir_conf); if (!ret) @@ -1065,6 +1090,8 @@ int hns3_restore_all_fdir_filter(struct hns3_adapter *hns) break; } } + pthread_mutex_unlock(&hw->flows_lock); + rte_spinlock_lock(&hw->lock); if (err) { hns3_err(hw, "Fail to restore FDIR filter, ret = %d", ret);