X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fwindows%2Fmlx5_flow_os.c;h=c4d57907267623dd8a4d13689aea924963c5c5cd;hb=05b405d581486651305551a9f7295f40388d95db;hp=0ade5189106182cf8a6cddb37156ec69c2480f52;hpb=03e1f7f760d8ce247638d6a917b5d4cb55ccec27;p=dpdk.git diff --git a/drivers/net/mlx5/windows/mlx5_flow_os.c b/drivers/net/mlx5/windows/mlx5_flow_os.c index 0ade518910..c4d5790726 100644 --- a/drivers/net/mlx5/windows/mlx5_flow_os.c +++ b/drivers/net/mlx5/windows/mlx5_flow_os.c @@ -5,6 +5,8 @@ #include "mlx5_flow_os.h" #include "mlx5_win_ext.h" +#include + /** * Verify the @p attributes will be correctly understood by the NIC and store * them in the @p flow if everything is correct. @@ -134,10 +136,19 @@ int mlx5_flow_os_create_flow_action_dest_devx_tir(struct mlx5_devx_obj *tir, void **action) { - RTE_SET_USED(tir); - *action = NULL; - rte_errno = ENOTSUP; - return -rte_errno; + struct mlx5_action *mlx5_action = + mlx5_malloc(MLX5_MEM_ZERO, + sizeof(struct mlx5_action), + 0, SOCKET_ID_ANY); + + if (!mlx5_action) { + rte_errno = ENOMEM; + return -rte_errno; + } + mlx5_action->type = MLX5_FLOW_CONTEXT_DEST_TYPE_TIR; + mlx5_action->dest_tir.id = tir->id; + *action = mlx5_action; + return 0; } /** @@ -152,9 +163,8 @@ mlx5_flow_os_create_flow_action_dest_devx_tir(struct mlx5_devx_obj *tir, int mlx5_flow_os_destroy_flow_action(void *action) { - RTE_SET_USED(action); - rte_errno = ENOTSUP; - return -rte_errno; + mlx5_free(action); + return 0; } /** @@ -179,13 +189,41 @@ mlx5_flow_os_create_flow(void *matcher, void *match_value, size_t num_actions, void *actions[], void **flow) { - RTE_SET_USED(matcher); - RTE_SET_USED(match_value); - RTE_SET_USED(num_actions); - RTE_SET_USED(actions); - *flow = NULL; - rte_errno = ENOTSUP; - return -rte_errno; + struct mlx5_action *action; + size_t i; + struct mlx5_matcher *mlx5_matcher = matcher; + struct mlx5_flow_dv_match_params *mlx5_match_value = match_value; + uint32_t in[MLX5_ST_SZ_DW(devx_fs_rule_add_in)] = {0}; + void *matcher_c = MLX5_ADDR_OF(devx_fs_rule_add_in, in, + match_criteria); + void *matcher_v = MLX5_ADDR_OF(devx_fs_rule_add_in, in, + match_value); + + MLX5_ASSERT(mlx5_matcher->ctx); + memcpy(matcher_c, mlx5_matcher->match_buf, + mlx5_match_value->size); + /* Use mlx5_match_value->size for match criteria */ + memcpy(matcher_v, mlx5_match_value->buf, + mlx5_match_value->size); + for (i = 0; i < num_actions; i++) { + action = actions[i]; + switch (action->type) { + case MLX5_FLOW_CONTEXT_DEST_TYPE_TIR: + MLX5_SET(devx_fs_rule_add_in, in, + dest.destination_type, + MLX5_FLOW_CONTEXT_DEST_TYPE_TIR); + MLX5_SET(devx_fs_rule_add_in, in, + dest.destination_id, + action->dest_tir.id); + break; + default: + break; + } + MLX5_SET(devx_fs_rule_add_in, in, match_criteria_enable, + MLX5_MATCH_OUTER_HEADERS); + } + *flow = mlx5_glue->devx_fs_rule_add(mlx5_matcher->ctx, in, sizeof(in)); + return (*flow) ? 0 : -1; } /** @@ -200,7 +238,181 @@ mlx5_flow_os_create_flow(void *matcher, void *match_value, int mlx5_flow_os_destroy_flow(void *drv_flow_ptr) { - RTE_SET_USED(dev_flow_ptr); - rte_errno = ENOTSUP; - return -rte_errno; + return mlx5_glue->devx_fs_rule_del(drv_flow_ptr); +} + +struct mlx5_workspace_thread { + HANDLE thread_handle; + struct mlx5_flow_workspace *mlx5_ws; + struct mlx5_workspace_thread *next; +}; + +/** + * Static pointer array for multi thread support of mlx5_flow_workspace. + */ +static struct mlx5_workspace_thread *curr; +static struct mlx5_workspace_thread *first; +rte_thread_key ws_tls_index; +static pthread_mutex_t lock_thread_list; + +static bool +mlx5_is_thread_alive(HANDLE thread_handle) +{ + DWORD result = WaitForSingleObject(thread_handle, 0); + + if (result == WAIT_OBJECT_0) + return false; + return false; +} + +static int +mlx5_get_current_thread(HANDLE *p_handle) +{ + BOOL ret = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), p_handle, 0, 0, DUPLICATE_SAME_ACCESS); + + if (!ret) { + RTE_LOG_WIN32_ERR("DuplicateHandle()"); + return -1; + } + return 0; +} + +static void +mlx5_clear_thread_list(void) +{ + struct mlx5_workspace_thread *temp = first; + struct mlx5_workspace_thread *next, *prev = NULL; + HANDLE curr_thread; + + if (!temp) + return; + if (mlx5_get_current_thread(&curr_thread)) { + DRV_LOG(ERR, "Failed to get current thread " + "handle."); + return; + } + while (temp) { + next = temp->next; + if (temp->thread_handle != curr_thread && + !mlx5_is_thread_alive(temp->thread_handle)) { + if (temp == first) { + if (curr == temp) + curr = temp->next; + first = temp->next; + } else if (temp == curr) { + curr = prev; + } + flow_release_workspace(temp->mlx5_ws); + CloseHandle(temp->thread_handle); + free(temp); + if (prev) + prev->next = next; + temp = next; + continue; + } + prev = temp; + temp = temp->next; + } + CloseHandle(curr_thread); +} + +/** + * Release workspaces before exit. + */ +void +mlx5_flow_os_release_workspace(void) +{ + mlx5_clear_thread_list(); + if (first) { + MLX5_ASSERT(!first->next); + flow_release_workspace(first->mlx5_ws); + free(first); + } + rte_thread_key_delete(ws_tls_index); + pthread_mutex_destroy(&lock_thread_list); +} + +static int +mlx5_add_workspace_to_list(struct mlx5_flow_workspace *data) +{ + HANDLE curr_thread; + struct mlx5_workspace_thread *temp = calloc(1, sizeof(*temp)); + + if (!temp) { + DRV_LOG(ERR, "Failed to allocate thread workspace " + "memory."); + return -1; + } + if (mlx5_get_current_thread(&curr_thread)) { + DRV_LOG(ERR, "Failed to get current thread " + "handle."); + free(temp); + return -1; + } + temp->mlx5_ws = data; + temp->thread_handle = curr_thread; + pthread_mutex_lock(&lock_thread_list); + mlx5_clear_thread_list(); + if (!first) { + first = temp; + curr = temp; + } else { + curr->next = temp; + curr = curr->next; + } + pthread_mutex_unlock(&lock_thread_list); + return 0; +} + +int +mlx5_flow_os_init_workspace_once(void) +{ + int err = rte_thread_key_create(&ws_tls_index, NULL); + + if (err) { + DRV_LOG(ERR, "Can't create flow workspace data thread key."); + return err; + } + pthread_mutex_init(&lock_thread_list, NULL); + return 0; +} + +void * +mlx5_flow_os_get_specific_workspace(void) +{ + return rte_thread_value_get(ws_tls_index); +} + +int +mlx5_flow_os_set_specific_workspace(struct mlx5_flow_workspace *data) +{ + int err = 0; + int old_err = rte_errno; + + rte_errno = 0; + if (!rte_thread_value_get(ws_tls_index)) { + if (rte_errno) { + DRV_LOG(ERR, "Failed checking specific workspace."); + rte_errno = old_err; + return -1; + } + /* + * set_specific_workspace when current value is NULL + * can happen only once per thread, mark this thread in + * linked list to be able to release reasorces later on. + */ + err = mlx5_add_workspace_to_list(data); + if (err) { + DRV_LOG(ERR, "Failed adding workspace to list."); + rte_errno = old_err; + return -1; + } + } + if (rte_thread_value_set(ws_tls_index, data)) { + DRV_LOG(ERR, "Failed setting specific workspace."); + err = -1; + } + rte_errno = old_err; + return err; }