1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 5 #include <rte_malloc.h> 6 #include <rte_log.h> 7 #include <rte_errno.h> 8 #include <rte_bus_pci.h> 9 #include <rte_pci.h> 10 #include <rte_regexdev.h> 11 #include <rte_regexdev_core.h> 12 #include <rte_regexdev_driver.h> 13 14 #include <mlx5_glue.h> 15 #include <mlx5_devx_cmds.h> 16 #include <mlx5_prm.h> 17 18 #include "mlx5_regex.h" 19 #include "mlx5_regex_utils.h" 20 21 int mlx5_regex_logtype; 22 23 static const struct rte_regexdev_ops mlx5_regexdev_ops = {0}; 24 25 static struct ibv_device * 26 mlx5_regex_get_ib_device_match(struct rte_pci_addr *addr) 27 { 28 int n; 29 struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n); 30 struct ibv_device *ibv_match = NULL; 31 32 if (!ibv_list) { 33 rte_errno = ENOSYS; 34 return NULL; 35 } 36 while (n-- > 0) { 37 struct rte_pci_addr pci_addr; 38 39 DRV_LOG(DEBUG, "Checking device \"%s\"..", ibv_list[n]->name); 40 if (mlx5_dev_to_pci_addr(ibv_list[n]->ibdev_path, &pci_addr)) 41 continue; 42 if (rte_pci_addr_cmp(addr, &pci_addr)) 43 continue; 44 ibv_match = ibv_list[n]; 45 break; 46 } 47 if (!ibv_match) 48 rte_errno = ENOENT; 49 mlx5_glue->free_device_list(ibv_list); 50 return ibv_match; 51 } 52 53 static void 54 mlx5_regex_get_name(char *name, struct rte_pci_device *pci_dev __rte_unused) 55 { 56 sprintf(name, "mlx5_regex_%02x:%02x.%02x", pci_dev->addr.bus, 57 pci_dev->addr.devid, pci_dev->addr.function); 58 } 59 60 static int 61 mlx5_regex_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 62 struct rte_pci_device *pci_dev) 63 { 64 struct ibv_device *ibv; 65 struct mlx5_regex_priv *priv = NULL; 66 struct ibv_context *ctx = NULL; 67 struct mlx5_hca_attr attr; 68 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 69 int ret; 70 71 ibv = mlx5_regex_get_ib_device_match(&pci_dev->addr); 72 if (!ibv) { 73 DRV_LOG(ERR, "No matching IB device for PCI slot " 74 PCI_PRI_FMT ".", pci_dev->addr.domain, 75 pci_dev->addr.bus, pci_dev->addr.devid, 76 pci_dev->addr.function); 77 return -rte_errno; 78 } 79 DRV_LOG(INFO, "PCI information matches for device \"%s\".", 80 ibv->name); 81 ctx = mlx5_glue->dv_open_device(ibv); 82 if (!ctx) { 83 DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name); 84 rte_errno = ENODEV; 85 return -rte_errno; 86 } 87 ret = mlx5_devx_cmd_query_hca_attr(ctx, &attr); 88 if (ret) { 89 DRV_LOG(ERR, "Unable to read HCA capabilities."); 90 rte_errno = ENOTSUP; 91 goto error; 92 } else if (!attr.regex || attr.regexp_num_of_engines == 0) { 93 DRV_LOG(ERR, "Not enough capabilities to support RegEx, maybe " 94 "old FW/OFED version?"); 95 rte_errno = ENOTSUP; 96 goto error; 97 } 98 priv = rte_zmalloc("mlx5 regex device private", sizeof(*priv), 99 RTE_CACHE_LINE_SIZE); 100 if (!priv) { 101 DRV_LOG(ERR, "Failed to allocate private memory."); 102 rte_errno = ENOMEM; 103 goto error; 104 } 105 priv->ctx = ctx; 106 mlx5_regex_get_name(name, pci_dev); 107 priv->regexdev = rte_regexdev_register(name); 108 if (priv->regexdev == NULL) { 109 DRV_LOG(ERR, "Failed to register RegEx device."); 110 rte_errno = rte_errno ? rte_errno : EINVAL; 111 goto error; 112 } 113 priv->regexdev->dev_ops = &mlx5_regexdev_ops; 114 priv->regexdev->device = (struct rte_device *)pci_dev; 115 priv->regexdev->data->dev_private = priv; 116 return 0; 117 118 error: 119 if (ctx) 120 mlx5_glue->close_device(ctx); 121 if (priv) 122 rte_free(priv); 123 return -rte_errno; 124 } 125 126 static int 127 mlx5_regex_pci_remove(struct rte_pci_device *pci_dev) 128 { 129 char name[RTE_REGEXDEV_NAME_MAX_LEN]; 130 struct rte_regexdev *dev; 131 struct mlx5_regex_priv *priv = NULL; 132 133 mlx5_regex_get_name(name, pci_dev); 134 dev = rte_regexdev_get_device_by_name(name); 135 if (!dev) 136 return 0; 137 priv = dev->data->dev_private; 138 if (priv) { 139 if (priv->ctx) 140 mlx5_glue->close_device(priv->ctx); 141 if (priv->regexdev) 142 rte_regexdev_unregister(priv->regexdev); 143 rte_free(priv); 144 } 145 return 0; 146 } 147 148 static const struct rte_pci_id mlx5_regex_pci_id_map[] = { 149 { 150 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, 151 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF) 152 }, 153 { 154 .vendor_id = 0 155 } 156 }; 157 158 static struct rte_pci_driver mlx5_regex_driver = { 159 .driver = { 160 .name = "mlx5_regex", 161 }, 162 .id_table = mlx5_regex_pci_id_map, 163 .probe = mlx5_regex_pci_probe, 164 .remove = mlx5_regex_pci_remove, 165 .drv_flags = 0, 166 }; 167 168 RTE_INIT(rte_mlx5_regex_init) 169 { 170 if (mlx5_glue) 171 rte_pci_register(&mlx5_regex_driver); 172 } 173 174 RTE_LOG_REGISTER(mlx5_regex_logtype, pmd.regex.mlx5, NOTICE) 175 RTE_PMD_EXPORT_NAME(net_mlx5_regex, __COUNTER__); 176 RTE_PMD_REGISTER_PCI_TABLE(net_mlx5_regex, mlx5_regex_pci_id_map); 177 RTE_PMD_REGISTER_KMOD_DEP(net_mlx5_regex, "* ib_uverbs & mlx5_core & mlx5_ib"); 178