17b4f1e6bSMatan Azrad /* SPDX-License-Identifier: BSD-3-Clause 27b4f1e6bSMatan Azrad * Copyright 2019 Mellanox Technologies, Ltd 37b4f1e6bSMatan Azrad */ 47b4f1e6bSMatan Azrad 57b4f1e6bSMatan Azrad #include <unistd.h> 67b4f1e6bSMatan Azrad #include <string.h> 793e30982SMatan Azrad #include <stdio.h> 8a6e7cd81STonghao Zhang #ifdef RTE_IBVERBS_LINK_DLOPEN 9a6e7cd81STonghao Zhang #include <dlfcn.h> 10a6e7cd81STonghao Zhang #endif 117b4f1e6bSMatan Azrad 127b4f1e6bSMatan Azrad #include <rte_errno.h> 137b4f1e6bSMatan Azrad 147b4f1e6bSMatan Azrad #include "mlx5_common.h" 157b4f1e6bSMatan Azrad #include "mlx5_common_utils.h" 167b4f1e6bSMatan Azrad #include "mlx5_glue.h" 177b4f1e6bSMatan Azrad 187b4f1e6bSMatan Azrad 197b4f1e6bSMatan Azrad int mlx5_common_logtype; 207b4f1e6bSMatan Azrad 212889d382SThomas Monjalon #ifdef MLX5_GLUE 222889d382SThomas Monjalon const struct mlx5_glue *mlx5_glue; 232889d382SThomas Monjalon #endif 247b4f1e6bSMatan Azrad 25*4c204fe5SShiri Kuzin uint8_t haswell_broadwell_cpu; 26*4c204fe5SShiri Kuzin 2793e30982SMatan Azrad /** 2893e30982SMatan Azrad * Get PCI information by sysfs device path. 2993e30982SMatan Azrad * 3093e30982SMatan Azrad * @param dev_path 3193e30982SMatan Azrad * Pointer to device sysfs folder name. 3293e30982SMatan Azrad * @param[out] pci_addr 3393e30982SMatan Azrad * PCI bus address output buffer. 3493e30982SMatan Azrad * 3593e30982SMatan Azrad * @return 3693e30982SMatan Azrad * 0 on success, a negative errno value otherwise and rte_errno is set. 3793e30982SMatan Azrad */ 3893e30982SMatan Azrad int 3993e30982SMatan Azrad mlx5_dev_to_pci_addr(const char *dev_path, 4093e30982SMatan Azrad struct rte_pci_addr *pci_addr) 4193e30982SMatan Azrad { 4293e30982SMatan Azrad FILE *file; 4393e30982SMatan Azrad char line[32]; 4493e30982SMatan Azrad MKSTR(path, "%s/device/uevent", dev_path); 4593e30982SMatan Azrad 4693e30982SMatan Azrad file = fopen(path, "rb"); 4793e30982SMatan Azrad if (file == NULL) { 4893e30982SMatan Azrad rte_errno = errno; 4993e30982SMatan Azrad return -rte_errno; 5093e30982SMatan Azrad } 5193e30982SMatan Azrad while (fgets(line, sizeof(line), file) == line) { 5293e30982SMatan Azrad size_t len = strlen(line); 5393e30982SMatan Azrad int ret; 5493e30982SMatan Azrad 5593e30982SMatan Azrad /* Truncate long lines. */ 5693e30982SMatan Azrad if (len == (sizeof(line) - 1)) 5793e30982SMatan Azrad while (line[(len - 1)] != '\n') { 5893e30982SMatan Azrad ret = fgetc(file); 5993e30982SMatan Azrad if (ret == EOF) 6093e30982SMatan Azrad break; 6193e30982SMatan Azrad line[(len - 1)] = ret; 6293e30982SMatan Azrad } 6393e30982SMatan Azrad /* Extract information. */ 6493e30982SMatan Azrad if (sscanf(line, 6593e30982SMatan Azrad "PCI_SLOT_NAME=" 6693e30982SMatan Azrad "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", 6793e30982SMatan Azrad &pci_addr->domain, 6893e30982SMatan Azrad &pci_addr->bus, 6993e30982SMatan Azrad &pci_addr->devid, 7093e30982SMatan Azrad &pci_addr->function) == 4) { 7193e30982SMatan Azrad ret = 0; 7293e30982SMatan Azrad break; 7393e30982SMatan Azrad } 7493e30982SMatan Azrad } 7593e30982SMatan Azrad fclose(file); 7693e30982SMatan Azrad return 0; 7793e30982SMatan Azrad } 7893e30982SMatan Azrad 79d768f324SMatan Azrad static int 80d768f324SMatan Azrad mlx5_class_check_handler(__rte_unused const char *key, const char *value, 81d768f324SMatan Azrad void *opaque) 82d768f324SMatan Azrad { 83d768f324SMatan Azrad enum mlx5_class *ret = opaque; 84d768f324SMatan Azrad 85d768f324SMatan Azrad if (strcmp(value, "vdpa") == 0) { 86d768f324SMatan Azrad *ret = MLX5_CLASS_VDPA; 87d768f324SMatan Azrad } else if (strcmp(value, "net") == 0) { 88d768f324SMatan Azrad *ret = MLX5_CLASS_NET; 89d768f324SMatan Azrad } else { 90d768f324SMatan Azrad DRV_LOG(ERR, "Invalid mlx5 class %s. Maybe typo in device" 91d768f324SMatan Azrad " class argument setting?", value); 92d768f324SMatan Azrad *ret = MLX5_CLASS_INVALID; 93d768f324SMatan Azrad } 94d768f324SMatan Azrad return 0; 95d768f324SMatan Azrad } 96d768f324SMatan Azrad 97d768f324SMatan Azrad enum mlx5_class 98d768f324SMatan Azrad mlx5_class_get(struct rte_devargs *devargs) 99d768f324SMatan Azrad { 100d768f324SMatan Azrad struct rte_kvargs *kvlist; 101d768f324SMatan Azrad const char *key = MLX5_CLASS_ARG_NAME; 102d768f324SMatan Azrad enum mlx5_class ret = MLX5_CLASS_NET; 103d768f324SMatan Azrad 104d768f324SMatan Azrad if (devargs == NULL) 105d768f324SMatan Azrad return ret; 106d768f324SMatan Azrad kvlist = rte_kvargs_parse(devargs->args, NULL); 107d768f324SMatan Azrad if (kvlist == NULL) 108d768f324SMatan Azrad return ret; 109d768f324SMatan Azrad if (rte_kvargs_count(kvlist, key)) 110d768f324SMatan Azrad rte_kvargs_process(kvlist, key, mlx5_class_check_handler, &ret); 111d768f324SMatan Azrad rte_kvargs_free(kvlist); 112d768f324SMatan Azrad return ret; 113d768f324SMatan Azrad } 114d768f324SMatan Azrad 115654810b5SMatan Azrad /** 116654810b5SMatan Azrad * Extract port name, as a number, from sysfs or netlink information. 117654810b5SMatan Azrad * 118654810b5SMatan Azrad * @param[in] port_name_in 119654810b5SMatan Azrad * String representing the port name. 120654810b5SMatan Azrad * @param[out] port_info_out 121654810b5SMatan Azrad * Port information, including port name as a number and port name 122654810b5SMatan Azrad * type if recognized 123654810b5SMatan Azrad * 124654810b5SMatan Azrad * @return 125654810b5SMatan Azrad * port_name field set according to recognized name format. 126654810b5SMatan Azrad */ 127654810b5SMatan Azrad void 128654810b5SMatan Azrad mlx5_translate_port_name(const char *port_name_in, 129654810b5SMatan Azrad struct mlx5_switch_info *port_info_out) 130654810b5SMatan Azrad { 131654810b5SMatan Azrad char pf_c1, pf_c2, vf_c1, vf_c2; 132654810b5SMatan Azrad char *end; 133654810b5SMatan Azrad int sc_items; 134654810b5SMatan Azrad 135654810b5SMatan Azrad /* 136654810b5SMatan Azrad * Check for port-name as a string of the form pf0vf0 137654810b5SMatan Azrad * (support kernel ver >= 5.0 or OFED ver >= 4.6). 138654810b5SMatan Azrad */ 139654810b5SMatan Azrad sc_items = sscanf(port_name_in, "%c%c%d%c%c%d", 140654810b5SMatan Azrad &pf_c1, &pf_c2, &port_info_out->pf_num, 141654810b5SMatan Azrad &vf_c1, &vf_c2, &port_info_out->port_name); 142654810b5SMatan Azrad if (sc_items == 6 && 143654810b5SMatan Azrad pf_c1 == 'p' && pf_c2 == 'f' && 144654810b5SMatan Azrad vf_c1 == 'v' && vf_c2 == 'f') { 145654810b5SMatan Azrad port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF; 146654810b5SMatan Azrad return; 147654810b5SMatan Azrad } 148654810b5SMatan Azrad /* 149654810b5SMatan Azrad * Check for port-name as a string of the form p0 150654810b5SMatan Azrad * (support kernel ver >= 5.0, or OFED ver >= 4.6). 151654810b5SMatan Azrad */ 152654810b5SMatan Azrad sc_items = sscanf(port_name_in, "%c%d", 153654810b5SMatan Azrad &pf_c1, &port_info_out->port_name); 154654810b5SMatan Azrad if (sc_items == 2 && pf_c1 == 'p') { 155654810b5SMatan Azrad port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK; 156654810b5SMatan Azrad return; 157654810b5SMatan Azrad } 158654810b5SMatan Azrad /* Check for port-name as a number (support kernel ver < 5.0 */ 159654810b5SMatan Azrad errno = 0; 160654810b5SMatan Azrad port_info_out->port_name = strtol(port_name_in, &end, 0); 161654810b5SMatan Azrad if (!errno && 162654810b5SMatan Azrad (size_t)(end - port_name_in) == strlen(port_name_in)) { 163654810b5SMatan Azrad port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY; 164654810b5SMatan Azrad return; 165654810b5SMatan Azrad } 166654810b5SMatan Azrad port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; 167654810b5SMatan Azrad return; 168654810b5SMatan Azrad } 169654810b5SMatan Azrad 17083c99c36SThomas Monjalon #ifdef MLX5_GLUE 1717b4f1e6bSMatan Azrad 1727b4f1e6bSMatan Azrad /** 1737b4f1e6bSMatan Azrad * Suffix RTE_EAL_PMD_PATH with "-glue". 1747b4f1e6bSMatan Azrad * 1757b4f1e6bSMatan Azrad * This function performs a sanity check on RTE_EAL_PMD_PATH before 1767b4f1e6bSMatan Azrad * suffixing its last component. 1777b4f1e6bSMatan Azrad * 1787b4f1e6bSMatan Azrad * @param buf[out] 1797b4f1e6bSMatan Azrad * Output buffer, should be large enough otherwise NULL is returned. 1807b4f1e6bSMatan Azrad * @param size 1817b4f1e6bSMatan Azrad * Size of @p out. 1827b4f1e6bSMatan Azrad * 1837b4f1e6bSMatan Azrad * @return 1847b4f1e6bSMatan Azrad * Pointer to @p buf or @p NULL in case suffix cannot be appended. 1857b4f1e6bSMatan Azrad */ 1867b4f1e6bSMatan Azrad static char * 1877b4f1e6bSMatan Azrad mlx5_glue_path(char *buf, size_t size) 1887b4f1e6bSMatan Azrad { 1897b4f1e6bSMatan Azrad static const char *const bad[] = { "/", ".", "..", NULL }; 1907b4f1e6bSMatan Azrad const char *path = RTE_EAL_PMD_PATH; 1917b4f1e6bSMatan Azrad size_t len = strlen(path); 1927b4f1e6bSMatan Azrad size_t off; 1937b4f1e6bSMatan Azrad int i; 1947b4f1e6bSMatan Azrad 1957b4f1e6bSMatan Azrad while (len && path[len - 1] == '/') 1967b4f1e6bSMatan Azrad --len; 1977b4f1e6bSMatan Azrad for (off = len; off && path[off - 1] != '/'; --off) 1987b4f1e6bSMatan Azrad ; 1997b4f1e6bSMatan Azrad for (i = 0; bad[i]; ++i) 2007b4f1e6bSMatan Azrad if (!strncmp(path + off, bad[i], (int)(len - off))) 2017b4f1e6bSMatan Azrad goto error; 2027b4f1e6bSMatan Azrad i = snprintf(buf, size, "%.*s-glue", (int)len, path); 2037b4f1e6bSMatan Azrad if (i == -1 || (size_t)i >= size) 2047b4f1e6bSMatan Azrad goto error; 2057b4f1e6bSMatan Azrad return buf; 2067b4f1e6bSMatan Azrad error: 2077b4f1e6bSMatan Azrad RTE_LOG(ERR, PMD, "unable to append \"-glue\" to last component of" 2087b4f1e6bSMatan Azrad " RTE_EAL_PMD_PATH (\"" RTE_EAL_PMD_PATH "\"), please" 2097b4f1e6bSMatan Azrad " re-configure DPDK"); 2107b4f1e6bSMatan Azrad return NULL; 2117b4f1e6bSMatan Azrad } 2127b4f1e6bSMatan Azrad 21383c99c36SThomas Monjalon static int 21483c99c36SThomas Monjalon mlx5_glue_dlopen(void) 2157b4f1e6bSMatan Azrad { 2167b4f1e6bSMatan Azrad char glue_path[sizeof(RTE_EAL_PMD_PATH) - 1 + sizeof("-glue")]; 217a6e7cd81STonghao Zhang void *handle = NULL; 218a6e7cd81STonghao Zhang 2197b4f1e6bSMatan Azrad const char *path[] = { 2207b4f1e6bSMatan Azrad /* 2217b4f1e6bSMatan Azrad * A basic security check is necessary before trusting 2227b4f1e6bSMatan Azrad * MLX5_GLUE_PATH, which may override RTE_EAL_PMD_PATH. 2237b4f1e6bSMatan Azrad */ 2247b4f1e6bSMatan Azrad (geteuid() == getuid() && getegid() == getgid() ? 2257b4f1e6bSMatan Azrad getenv("MLX5_GLUE_PATH") : NULL), 2267b4f1e6bSMatan Azrad /* 2277b4f1e6bSMatan Azrad * When RTE_EAL_PMD_PATH is set, use its glue-suffixed 2287b4f1e6bSMatan Azrad * variant, otherwise let dlopen() look up libraries on its 2297b4f1e6bSMatan Azrad * own. 2307b4f1e6bSMatan Azrad */ 2317b4f1e6bSMatan Azrad (*RTE_EAL_PMD_PATH ? 2327b4f1e6bSMatan Azrad mlx5_glue_path(glue_path, sizeof(glue_path)) : ""), 2337b4f1e6bSMatan Azrad }; 2347b4f1e6bSMatan Azrad unsigned int i = 0; 2357b4f1e6bSMatan Azrad void **sym; 2367b4f1e6bSMatan Azrad const char *dlmsg; 2377b4f1e6bSMatan Azrad 2387b4f1e6bSMatan Azrad while (!handle && i != RTE_DIM(path)) { 2397b4f1e6bSMatan Azrad const char *end; 2407b4f1e6bSMatan Azrad size_t len; 2417b4f1e6bSMatan Azrad int ret; 2427b4f1e6bSMatan Azrad 2437b4f1e6bSMatan Azrad if (!path[i]) { 2447b4f1e6bSMatan Azrad ++i; 2457b4f1e6bSMatan Azrad continue; 2467b4f1e6bSMatan Azrad } 2477b4f1e6bSMatan Azrad end = strpbrk(path[i], ":;"); 2487b4f1e6bSMatan Azrad if (!end) 2497b4f1e6bSMatan Azrad end = path[i] + strlen(path[i]); 2507b4f1e6bSMatan Azrad len = end - path[i]; 2517b4f1e6bSMatan Azrad ret = 0; 2527b4f1e6bSMatan Azrad do { 2537b4f1e6bSMatan Azrad char name[ret + 1]; 2547b4f1e6bSMatan Azrad 2557b4f1e6bSMatan Azrad ret = snprintf(name, sizeof(name), "%.*s%s" MLX5_GLUE, 2567b4f1e6bSMatan Azrad (int)len, path[i], 2577b4f1e6bSMatan Azrad (!len || *(end - 1) == '/') ? "" : "/"); 2587b4f1e6bSMatan Azrad if (ret == -1) 2597b4f1e6bSMatan Azrad break; 2607b4f1e6bSMatan Azrad if (sizeof(name) != (size_t)ret + 1) 2617b4f1e6bSMatan Azrad continue; 2627b4f1e6bSMatan Azrad DRV_LOG(DEBUG, "Looking for rdma-core glue as " 2637b4f1e6bSMatan Azrad "\"%s\"", name); 2647b4f1e6bSMatan Azrad handle = dlopen(name, RTLD_LAZY); 2657b4f1e6bSMatan Azrad break; 2667b4f1e6bSMatan Azrad } while (1); 2677b4f1e6bSMatan Azrad path[i] = end + 1; 2687b4f1e6bSMatan Azrad if (!*end) 2697b4f1e6bSMatan Azrad ++i; 2707b4f1e6bSMatan Azrad } 2717b4f1e6bSMatan Azrad if (!handle) { 2727b4f1e6bSMatan Azrad rte_errno = EINVAL; 2737b4f1e6bSMatan Azrad dlmsg = dlerror(); 2747b4f1e6bSMatan Azrad if (dlmsg) 2757b4f1e6bSMatan Azrad DRV_LOG(WARNING, "Cannot load glue library: %s", dlmsg); 2767b4f1e6bSMatan Azrad goto glue_error; 2777b4f1e6bSMatan Azrad } 2787b4f1e6bSMatan Azrad sym = dlsym(handle, "mlx5_glue"); 2797b4f1e6bSMatan Azrad if (!sym || !*sym) { 2807b4f1e6bSMatan Azrad rte_errno = EINVAL; 2817b4f1e6bSMatan Azrad dlmsg = dlerror(); 2827b4f1e6bSMatan Azrad if (dlmsg) 2837b4f1e6bSMatan Azrad DRV_LOG(ERR, "Cannot resolve glue symbol: %s", dlmsg); 2847b4f1e6bSMatan Azrad goto glue_error; 2857b4f1e6bSMatan Azrad } 2867b4f1e6bSMatan Azrad mlx5_glue = *sym; 28783c99c36SThomas Monjalon return 0; 28883c99c36SThomas Monjalon 28983c99c36SThomas Monjalon glue_error: 29083c99c36SThomas Monjalon if (handle) 29183c99c36SThomas Monjalon dlclose(handle); 29283c99c36SThomas Monjalon return -1; 29383c99c36SThomas Monjalon } 29483c99c36SThomas Monjalon 29583c99c36SThomas Monjalon #endif 29683c99c36SThomas Monjalon 297*4c204fe5SShiri Kuzin /* In case this is an x86_64 intel processor to check if 298*4c204fe5SShiri Kuzin * we should use relaxed ordering. 299*4c204fe5SShiri Kuzin */ 300*4c204fe5SShiri Kuzin #ifdef RTE_ARCH_X86_64 301*4c204fe5SShiri Kuzin /** 302*4c204fe5SShiri Kuzin * This function returns processor identification and feature information 303*4c204fe5SShiri Kuzin * into the registers. 304*4c204fe5SShiri Kuzin * 305*4c204fe5SShiri Kuzin * @param eax, ebx, ecx, edx 306*4c204fe5SShiri Kuzin * Pointers to the registers that will hold cpu information. 307*4c204fe5SShiri Kuzin * @param level 308*4c204fe5SShiri Kuzin * The main category of information returned. 309*4c204fe5SShiri Kuzin */ 310*4c204fe5SShiri Kuzin static inline void mlx5_cpu_id(unsigned int level, 311*4c204fe5SShiri Kuzin unsigned int *eax, unsigned int *ebx, 312*4c204fe5SShiri Kuzin unsigned int *ecx, unsigned int *edx) 313*4c204fe5SShiri Kuzin { 314*4c204fe5SShiri Kuzin __asm__("cpuid\n\t" 315*4c204fe5SShiri Kuzin : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) 316*4c204fe5SShiri Kuzin : "0" (level)); 317*4c204fe5SShiri Kuzin } 318*4c204fe5SShiri Kuzin #endif 319*4c204fe5SShiri Kuzin 32083c99c36SThomas Monjalon RTE_INIT_PRIO(mlx5_log_init, LOG) 32183c99c36SThomas Monjalon { 32283c99c36SThomas Monjalon mlx5_common_logtype = rte_log_register("pmd.common.mlx5"); 32383c99c36SThomas Monjalon if (mlx5_common_logtype >= 0) 32483c99c36SThomas Monjalon rte_log_set_level(mlx5_common_logtype, RTE_LOG_NOTICE); 32583c99c36SThomas Monjalon } 32683c99c36SThomas Monjalon 32783c99c36SThomas Monjalon /** 32883c99c36SThomas Monjalon * Initialization routine for run-time dependency on rdma-core. 32983c99c36SThomas Monjalon */ 33083c99c36SThomas Monjalon RTE_INIT_PRIO(mlx5_glue_init, CLASS) 33183c99c36SThomas Monjalon { 33283c99c36SThomas Monjalon /* 33383c99c36SThomas Monjalon * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use 33483c99c36SThomas Monjalon * huge pages. Calling ibv_fork_init() during init allows 33583c99c36SThomas Monjalon * applications to use fork() safely for purposes other than 33683c99c36SThomas Monjalon * using this PMD, which is not supported in forked processes. 33783c99c36SThomas Monjalon */ 33883c99c36SThomas Monjalon setenv("RDMAV_HUGEPAGES_SAFE", "1", 1); 33983c99c36SThomas Monjalon /* Match the size of Rx completion entry to the size of a cacheline. */ 34083c99c36SThomas Monjalon if (RTE_CACHE_LINE_SIZE == 128) 34183c99c36SThomas Monjalon setenv("MLX5_CQE_SIZE", "128", 0); 34283c99c36SThomas Monjalon /* 34383c99c36SThomas Monjalon * MLX5_DEVICE_FATAL_CLEANUP tells ibv_destroy functions to 34483c99c36SThomas Monjalon * cleanup all the Verbs resources even when the device was removed. 34583c99c36SThomas Monjalon */ 34683c99c36SThomas Monjalon setenv("MLX5_DEVICE_FATAL_CLEANUP", "1", 1); 34783c99c36SThomas Monjalon 34883c99c36SThomas Monjalon #ifdef MLX5_GLUE 34983c99c36SThomas Monjalon if (mlx5_glue_dlopen() != 0) 35083c99c36SThomas Monjalon goto glue_error; 35183c99c36SThomas Monjalon #endif 35283c99c36SThomas Monjalon 3530afacb04SAlexander Kozyrev #ifdef RTE_LIBRTE_MLX5_DEBUG 3547b4f1e6bSMatan Azrad /* Glue structure must not contain any NULL pointers. */ 3557b4f1e6bSMatan Azrad { 3567b4f1e6bSMatan Azrad unsigned int i; 3577b4f1e6bSMatan Azrad 3587b4f1e6bSMatan Azrad for (i = 0; i != sizeof(*mlx5_glue) / sizeof(void *); ++i) 3598e46d4e1SAlexander Kozyrev MLX5_ASSERT(((const void *const *)mlx5_glue)[i]); 3607b4f1e6bSMatan Azrad } 3617b4f1e6bSMatan Azrad #endif 3627b4f1e6bSMatan Azrad if (strcmp(mlx5_glue->version, MLX5_GLUE_VERSION)) { 3637b4f1e6bSMatan Azrad rte_errno = EINVAL; 3647b4f1e6bSMatan Azrad DRV_LOG(ERR, "rdma-core glue \"%s\" mismatch: \"%s\" is " 3657b4f1e6bSMatan Azrad "required", mlx5_glue->version, MLX5_GLUE_VERSION); 3667b4f1e6bSMatan Azrad goto glue_error; 3677b4f1e6bSMatan Azrad } 3687b4f1e6bSMatan Azrad mlx5_glue->fork_init(); 3697b4f1e6bSMatan Azrad return; 37083c99c36SThomas Monjalon 3717b4f1e6bSMatan Azrad glue_error: 3727b4f1e6bSMatan Azrad DRV_LOG(WARNING, "Cannot initialize MLX5 common due to missing" 3737b4f1e6bSMatan Azrad " run-time dependency on rdma-core libraries (libibverbs," 3747b4f1e6bSMatan Azrad " libmlx5)"); 3757b4f1e6bSMatan Azrad mlx5_glue = NULL; 3767b4f1e6bSMatan Azrad return; 3777b4f1e6bSMatan Azrad } 378*4c204fe5SShiri Kuzin 379*4c204fe5SShiri Kuzin /** 380*4c204fe5SShiri Kuzin * This function is responsible of initializing the variable 381*4c204fe5SShiri Kuzin * haswell_broadwell_cpu by checking if the cpu is intel 382*4c204fe5SShiri Kuzin * and reading the data returned from mlx5_cpu_id(). 383*4c204fe5SShiri Kuzin * since haswell and broadwell cpus don't have improved performance 384*4c204fe5SShiri Kuzin * when using relaxed ordering we want to check the cpu type before 385*4c204fe5SShiri Kuzin * before deciding whether to enable RO or not. 386*4c204fe5SShiri Kuzin * if the cpu is haswell or broadwell the variable will be set to 1 387*4c204fe5SShiri Kuzin * otherwise it will be 0. 388*4c204fe5SShiri Kuzin */ 389*4c204fe5SShiri Kuzin RTE_INIT_PRIO(mlx5_is_haswell_broadwell_cpu, LOG) 390*4c204fe5SShiri Kuzin { 391*4c204fe5SShiri Kuzin #ifdef RTE_ARCH_X86_64 392*4c204fe5SShiri Kuzin unsigned int broadwell_models[4] = {0x3d, 0x47, 0x4F, 0x56}; 393*4c204fe5SShiri Kuzin unsigned int haswell_models[4] = {0x3c, 0x3f, 0x45, 0x46}; 394*4c204fe5SShiri Kuzin unsigned int i, model, family, brand_id, vendor; 395*4c204fe5SShiri Kuzin unsigned int signature_intel_ebx = 0x756e6547; 396*4c204fe5SShiri Kuzin unsigned int extended_model; 397*4c204fe5SShiri Kuzin unsigned int eax = 0; 398*4c204fe5SShiri Kuzin unsigned int ebx = 0; 399*4c204fe5SShiri Kuzin unsigned int ecx = 0; 400*4c204fe5SShiri Kuzin unsigned int edx = 0; 401*4c204fe5SShiri Kuzin int max_level; 402*4c204fe5SShiri Kuzin 403*4c204fe5SShiri Kuzin mlx5_cpu_id(0, &eax, &ebx, &ecx, &edx); 404*4c204fe5SShiri Kuzin vendor = ebx; 405*4c204fe5SShiri Kuzin max_level = eax; 406*4c204fe5SShiri Kuzin if (max_level < 1) { 407*4c204fe5SShiri Kuzin haswell_broadwell_cpu = 0; 408*4c204fe5SShiri Kuzin return; 409*4c204fe5SShiri Kuzin } 410*4c204fe5SShiri Kuzin mlx5_cpu_id(1, &eax, &ebx, &ecx, &edx); 411*4c204fe5SShiri Kuzin model = (eax >> 4) & 0x0f; 412*4c204fe5SShiri Kuzin family = (eax >> 8) & 0x0f; 413*4c204fe5SShiri Kuzin brand_id = ebx & 0xff; 414*4c204fe5SShiri Kuzin extended_model = (eax >> 12) & 0xf0; 415*4c204fe5SShiri Kuzin /* Check if the processor is Haswell or Broadwell */ 416*4c204fe5SShiri Kuzin if (vendor == signature_intel_ebx) { 417*4c204fe5SShiri Kuzin if (family == 0x06) 418*4c204fe5SShiri Kuzin model += extended_model; 419*4c204fe5SShiri Kuzin if (brand_id == 0 && family == 0x6) { 420*4c204fe5SShiri Kuzin for (i = 0; i < RTE_DIM(broadwell_models); i++) 421*4c204fe5SShiri Kuzin if (model == broadwell_models[i]) { 422*4c204fe5SShiri Kuzin haswell_broadwell_cpu = 1; 423*4c204fe5SShiri Kuzin return; 424*4c204fe5SShiri Kuzin } 425*4c204fe5SShiri Kuzin for (i = 0; i < RTE_DIM(haswell_models); i++) 426*4c204fe5SShiri Kuzin if (model == haswell_models[i]) { 427*4c204fe5SShiri Kuzin haswell_broadwell_cpu = 1; 428*4c204fe5SShiri Kuzin return; 429*4c204fe5SShiri Kuzin } 430*4c204fe5SShiri Kuzin } 431*4c204fe5SShiri Kuzin } 432*4c204fe5SShiri Kuzin #endif 433*4c204fe5SShiri Kuzin haswell_broadwell_cpu = 0; 434*4c204fe5SShiri Kuzin } 435