1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Brocade Communications Systems, Inc. 3 * Author: Jan Blunck <jblunck@infradead.org> 4 */ 5 6 #ifndef _RTE_ETHDEV_PCI_H_ 7 #define _RTE_ETHDEV_PCI_H_ 8 9 #include <rte_malloc.h> 10 #include <rte_pci.h> 11 #include <rte_bus_pci.h> 12 #include <rte_config.h> 13 #include <ethdev_driver.h> 14 15 /** 16 * Copy pci device info to the Ethernet device data. 17 * Shared memory (eth_dev->data) only updated by primary process, so it is safe 18 * to call this function from both primary and secondary processes. 19 * 20 * @param eth_dev 21 * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. 22 * @param pci_dev 23 * The *pci_dev* pointer is the address of the *rte_pci_device* structure. 24 */ 25 static inline void 26 rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, 27 struct rte_pci_device *pci_dev) 28 { 29 if ((eth_dev == NULL) || (pci_dev == NULL)) { 30 RTE_ETHDEV_LOG(ERR, "NULL pointer eth_dev=%p pci_dev=%p", 31 (void *)eth_dev, (void *)pci_dev); 32 return; 33 } 34 35 eth_dev->intr_handle = pci_dev->intr_handle; 36 37 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 38 eth_dev->data->dev_flags = 0; 39 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) 40 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 41 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV) 42 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV; 43 44 eth_dev->data->numa_node = pci_dev->device.numa_node; 45 } 46 } 47 48 static inline int 49 eth_dev_pci_specific_init(struct rte_eth_dev *eth_dev, void *bus_device) { 50 struct rte_pci_device *pci_dev = bus_device; 51 52 if (!pci_dev) 53 return -ENODEV; 54 55 rte_eth_copy_pci_info(eth_dev, pci_dev); 56 57 return 0; 58 } 59 60 /** 61 * @internal 62 * Allocates a new ethdev slot for an Ethernet device and returns the pointer 63 * to that slot for the driver to use. 64 * 65 * @param dev 66 * Pointer to the PCI device 67 * 68 * @param private_data_size 69 * Size of private data structure 70 * 71 * @return 72 * A pointer to a rte_eth_dev or NULL if allocation failed. 73 */ 74 static inline struct rte_eth_dev * 75 rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size) 76 { 77 struct rte_eth_dev *eth_dev; 78 const char *name; 79 80 if (!dev) 81 return NULL; 82 83 name = dev->device.name; 84 85 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 86 eth_dev = rte_eth_dev_allocate(name); 87 if (!eth_dev) 88 return NULL; 89 90 if (private_data_size) { 91 eth_dev->data->dev_private = rte_zmalloc_socket(name, 92 private_data_size, RTE_CACHE_LINE_SIZE, 93 dev->device.numa_node); 94 if (!eth_dev->data->dev_private) { 95 rte_eth_dev_release_port(eth_dev); 96 return NULL; 97 } 98 } 99 } else { 100 eth_dev = rte_eth_dev_attach_secondary(name); 101 if (!eth_dev) 102 return NULL; 103 } 104 105 eth_dev->device = &dev->device; 106 rte_eth_copy_pci_info(eth_dev, dev); 107 return eth_dev; 108 } 109 110 typedef int (*eth_dev_pci_callback_t)(struct rte_eth_dev *eth_dev); 111 112 /** 113 * @internal 114 * Wrapper for use by pci drivers in a .probe function to attach to a ethdev 115 * interface. 116 */ 117 static inline int 118 rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev, 119 size_t private_data_size, eth_dev_pci_callback_t dev_init) 120 { 121 struct rte_eth_dev *eth_dev; 122 int ret; 123 124 eth_dev = rte_eth_dev_pci_allocate(pci_dev, private_data_size); 125 if (!eth_dev) 126 return -ENOMEM; 127 128 RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL); 129 ret = dev_init(eth_dev); 130 if (ret) 131 rte_eth_dev_release_port(eth_dev); 132 else 133 rte_eth_dev_probing_finish(eth_dev); 134 135 return ret; 136 } 137 138 /** 139 * @internal 140 * Wrapper for use by pci drivers in a .remove function to detach a ethdev 141 * interface. 142 */ 143 static inline int 144 rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev, 145 eth_dev_pci_callback_t dev_uninit) 146 { 147 struct rte_eth_dev *eth_dev; 148 int ret; 149 150 eth_dev = rte_eth_dev_allocated(pci_dev->device.name); 151 if (!eth_dev) 152 return 0; 153 154 /* 155 * In secondary process, a released eth device can be found by its name 156 * in shared memory. 157 * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 158 * eth device has been released. 159 */ 160 if (rte_eal_process_type() == RTE_PROC_SECONDARY && 161 eth_dev->state == RTE_ETH_DEV_UNUSED) 162 return 0; 163 164 if (dev_uninit) { 165 ret = dev_uninit(eth_dev); 166 if (ret) 167 return ret; 168 } 169 170 rte_eth_dev_release_port(eth_dev); 171 return 0; 172 } 173 174 #endif /* _RTE_ETHDEV_PCI_H_ */ 175