Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright 2020 Mellanox Technologies Ltd 3 : : */ 4 : : 5 : : #include <stdlib.h> 6 : : 7 : : #include <rte_malloc.h> 8 : : #include <rte_devargs.h> 9 : : #include <rte_errno.h> 10 : : #include <rte_class.h> 11 : : #include <rte_pci.h> 12 : : #include <bus_driver.h> 13 : : #include <bus_pci_driver.h> 14 : : 15 : : #include "mlx5_common_log.h" 16 : : #include "mlx5_common_private.h" 17 : : 18 : : static struct rte_pci_driver mlx5_common_pci_driver; 19 : : 20 : : /* PCI ID table is build dynamically based on registered mlx5 drivers. */ 21 : : static struct rte_pci_id *mlx5_pci_id_table; 22 : : 23 : : static int 24 : : pci_id_table_size_get(const struct rte_pci_id *id_table) 25 : : { 26 : : int table_size = 0; 27 : : 28 [ + + + + ]: 29736 : for (; id_table->vendor_id != 0; id_table++) 29 : 28224 : table_size++; 30 : : return table_size; 31 : : } 32 : : 33 : : static bool 34 : : pci_id_exists(const struct rte_pci_id *id, const struct rte_pci_id *table, 35 : : int next_idx) 36 : : { 37 : 9324 : int current_size = next_idx - 1; 38 : : int i; 39 : : 40 [ + + ]: 110376 : for (i = 0; i < current_size; i++) { 41 [ + + ]: 105588 : if (id->device_id == table[i].device_id && 42 : : id->vendor_id == table[i].vendor_id && 43 [ - + ]: 4536 : id->subsystem_vendor_id == table[i].subsystem_vendor_id && 44 : : id->subsystem_device_id == table[i].subsystem_device_id) 45 : : return true; 46 : : } 47 : : return false; 48 : : } 49 : : 50 : : static void 51 : 1260 : pci_id_insert(struct rte_pci_id *new_table, int *next_idx, 52 : : const struct rte_pci_id *id_table) 53 : : { 54 : : /* Traverse the id_table, check if entry exists in new_table; 55 : : * Add non duplicate entries to new table. 56 : : */ 57 [ + + ]: 10584 : for (; id_table->vendor_id != 0; id_table++) { 58 [ + + ]: 18648 : if (!pci_id_exists(id_table, new_table, *next_idx)) { 59 : : /* New entry; add to the table. */ 60 : 4788 : new_table[*next_idx] = *id_table; 61 : 4788 : (*next_idx)++; 62 : : } 63 : : } 64 : 1260 : } 65 : : 66 : : static int 67 : 1512 : pci_ids_table_update(const struct rte_pci_id *driver_id_table) 68 : : { 69 : : const struct rte_pci_id *id_iter; 70 : : struct rte_pci_id *updated_table; 71 : : struct rte_pci_id *old_table; 72 : : int num_ids = 0; 73 : 1512 : int i = 0; 74 : : 75 : 1512 : old_table = mlx5_pci_id_table; 76 [ + + ]: 1512 : if (old_table) 77 : : num_ids = pci_id_table_size_get(old_table); 78 : 1512 : num_ids += pci_id_table_size_get(driver_id_table); 79 : : /* Increase size by one for the termination entry of vendor_id = 0. */ 80 : 1512 : num_ids += 1; 81 : 1512 : updated_table = calloc(num_ids, sizeof(*updated_table)); 82 [ + - ]: 1512 : if (!updated_table) 83 : : return -ENOMEM; 84 [ + + ]: 1512 : if (old_table == NULL) { 85 : : /* Copy the first driver's ID table. */ 86 [ - + ]: 252 : for (id_iter = driver_id_table; id_iter->vendor_id != 0; 87 : 0 : id_iter++, i++) 88 : 0 : updated_table[i] = *id_iter; 89 : : } else { 90 : : /* First copy existing table entries. */ 91 [ + + ]: 20160 : for (id_iter = old_table; id_iter->vendor_id != 0; 92 : 18900 : id_iter++, i++) 93 : 18900 : updated_table[i] = *id_iter; 94 : : /* New id to be added at the end of current ID table. */ 95 : 1260 : pci_id_insert(updated_table, &i, driver_id_table); 96 : : } 97 : : /* Terminate table with empty entry. */ 98 : 1512 : updated_table[i].vendor_id = 0; 99 : 1512 : mlx5_common_pci_driver.id_table = updated_table; 100 : 1512 : mlx5_pci_id_table = updated_table; 101 : 1512 : free(old_table); 102 : 1512 : return 0; 103 : : } 104 : : 105 : : bool 106 : 0 : mlx5_dev_is_pci(const struct rte_device *dev) 107 : : { 108 : 0 : return strcmp(dev->bus->name, "pci") == 0; 109 : : } 110 : : 111 : : bool 112 : 0 : mlx5_dev_is_vf_pci(const struct rte_pci_device *pci_dev) 113 : : { 114 [ # # ]: 0 : switch (pci_dev->id.device_id) { 115 : : case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF: 116 : : case PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF: 117 : : case PCI_DEVICE_ID_MELLANOX_CONNECTX5VF: 118 : : case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF: 119 : : case PCI_DEVICE_ID_MELLANOX_BLUEFIELDVF: 120 : : case PCI_DEVICE_ID_MELLANOX_CONNECTX6VF: 121 : : case PCI_DEVICE_ID_MELLANOX_CONNECTXVF: 122 : : return true; 123 : : default: 124 : : break; 125 : : } 126 : 0 : return false; 127 : : } 128 : : 129 : : bool 130 : 0 : mlx5_dev_pci_match(const struct mlx5_class_driver *drv, 131 : : const struct rte_device *dev) 132 : : { 133 : : const struct rte_pci_device *pci_dev; 134 : : const struct rte_pci_id *id_table; 135 : : 136 [ # # ]: 0 : if (!mlx5_dev_is_pci(dev)) 137 : : return false; 138 : 0 : pci_dev = RTE_DEV_TO_PCI_CONST(dev); 139 [ # # ]: 0 : for (id_table = drv->id_table; id_table->vendor_id != 0; 140 : 0 : id_table++) { 141 : : /* Check if device's ids match the class driver's ids. */ 142 [ # # # # ]: 0 : if (id_table->vendor_id != pci_dev->id.vendor_id && 143 : : id_table->vendor_id != RTE_PCI_ANY_ID) 144 : 0 : continue; 145 [ # # # # ]: 0 : if (id_table->device_id != pci_dev->id.device_id && 146 : : id_table->device_id != RTE_PCI_ANY_ID) 147 : 0 : continue; 148 : 0 : if (id_table->subsystem_vendor_id != 149 [ # # # # ]: 0 : pci_dev->id.subsystem_vendor_id && 150 : : id_table->subsystem_vendor_id != RTE_PCI_ANY_ID) 151 : 0 : continue; 152 : 0 : if (id_table->subsystem_device_id != 153 [ # # # # ]: 0 : pci_dev->id.subsystem_device_id && 154 : : id_table->subsystem_device_id != RTE_PCI_ANY_ID) 155 : 0 : continue; 156 [ # # # # ]: 0 : if (id_table->class_id != pci_dev->id.class_id && 157 : : id_table->class_id != RTE_CLASS_ANY_ID) 158 : 0 : continue; 159 : : return true; 160 : : } 161 : : return false; 162 : : } 163 : : 164 : : static int 165 : 0 : mlx5_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 166 : : struct rte_pci_device *pci_dev) 167 : : { 168 : 0 : return mlx5_common_dev_probe(&pci_dev->device); 169 : : } 170 : : 171 : : static int 172 : 0 : mlx5_common_pci_remove(struct rte_pci_device *pci_dev) 173 : : { 174 : 0 : return mlx5_common_dev_remove(&pci_dev->device); 175 : : } 176 : : 177 : : static int 178 : 0 : mlx5_common_pci_dma_map(struct rte_pci_device *pci_dev, void *addr, 179 : : uint64_t iova, size_t len) 180 : : { 181 : 0 : return mlx5_common_dev_dma_map(&pci_dev->device, addr, iova, len); 182 : : } 183 : : 184 : : static int 185 : 0 : mlx5_common_pci_dma_unmap(struct rte_pci_device *pci_dev, void *addr, 186 : : uint64_t iova, size_t len) 187 : : { 188 : 0 : return mlx5_common_dev_dma_unmap(&pci_dev->device, addr, iova, len); 189 : : } 190 : : 191 : : void 192 : 1260 : mlx5_common_driver_on_register_pci(struct mlx5_class_driver *driver) 193 : : { 194 [ + - ]: 1260 : if (driver->id_table != NULL) { 195 [ + - ]: 1260 : if (pci_ids_table_update(driver->id_table) != 0) 196 : : return; 197 : : } 198 [ + + ]: 1260 : if (driver->probe_again) 199 : 252 : mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_PROBE_AGAIN; 200 [ + + ]: 1260 : if (driver->intr_lsc) 201 : 252 : mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_LSC; 202 [ + + ]: 1260 : if (driver->intr_rmv) 203 : 252 : mlx5_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_RMV; 204 : : } 205 : : 206 : : static struct rte_pci_driver mlx5_common_pci_driver = { 207 : : .driver = { 208 : : .name = MLX5_PCI_DRIVER_NAME, 209 : : }, 210 : : .probe = mlx5_common_pci_probe, 211 : : .remove = mlx5_common_pci_remove, 212 : : .dma_map = mlx5_common_pci_dma_map, 213 : : .dma_unmap = mlx5_common_pci_dma_unmap, 214 : : }; 215 : : 216 : 252 : void mlx5_common_pci_init(void) 217 : : { 218 : 252 : const struct rte_pci_id empty_table[] = { 219 : : { 220 : : .vendor_id = 0 221 : : }, 222 : : }; 223 : : 224 : : /* All mlx5 PMDs constructor runs at same priority. So any of the PMD 225 : : * including this one can register the PCI table first. If any other 226 : : * PMD(s) have registered the PCI ID table, No need to register an empty 227 : : * default one. 228 : : */ 229 [ + - - + ]: 252 : if (mlx5_pci_id_table == NULL && pci_ids_table_update(empty_table)) 230 : 0 : return; 231 : 252 : rte_pci_register(&mlx5_common_pci_driver); 232 : : } 233 : : 234 : 252 : RTE_FINI(mlx5_common_pci_finish) 235 : : { 236 [ + - ]: 252 : if (mlx5_pci_id_table != NULL) { 237 : : /* Constructor doesn't register with PCI bus if it failed 238 : : * to build the table. 239 : : */ 240 : 252 : rte_pci_unregister(&mlx5_common_pci_driver); 241 : 252 : free(mlx5_pci_id_table); 242 : : } 243 : 252 : } 244 : : 245 : : RTE_PMD_EXPORT_NAME(mlx5_common_pci, __COUNTER__);