Branch data Line data Source code
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 <bus_pci_driver.h> 12 : : #include <rte_config.h> 13 : : #include <ethdev_driver.h> 14 : : 15 : : #ifdef __cplusplus 16 : : extern "C" { 17 : : #endif 18 : : 19 : : /** 20 : : * Copy pci device info to the Ethernet device data. 21 : : * Shared memory (eth_dev->data) only updated by primary process, so it is safe 22 : : * to call this function from both primary and secondary processes. 23 : : * 24 : : * @param eth_dev 25 : : * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. 26 : : * @param pci_dev 27 : : * The *pci_dev* pointer is the address of the *rte_pci_device* structure. 28 : : */ 29 : : static inline void 30 : 0 : rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, 31 : : struct rte_pci_device *pci_dev) 32 : : { 33 [ # # ]: 0 : if ((eth_dev == NULL) || (pci_dev == NULL)) { 34 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "NULL pointer eth_dev=%p pci_dev=%p", 35 : : (void *)eth_dev, (void *)pci_dev); 36 : 0 : return; 37 : : } 38 : : 39 : 0 : eth_dev->intr_handle = pci_dev->intr_handle; 40 : : 41 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 42 : 0 : eth_dev->data->dev_flags = 0; 43 [ # # ]: 0 : if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) 44 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 45 [ # # ]: 0 : if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV) 46 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV; 47 : : 48 : 0 : eth_dev->data->numa_node = pci_dev->device.numa_node; 49 : : } 50 : : } 51 : : 52 : : static inline int 53 : 0 : eth_dev_pci_specific_init(struct rte_eth_dev *eth_dev, void *bus_device) 54 : : { 55 : : struct rte_pci_device *pci_dev = (struct rte_pci_device *)bus_device; 56 : : 57 [ # # ]: 0 : if (!pci_dev) 58 : : return -ENODEV; 59 : : 60 : 0 : rte_eth_copy_pci_info(eth_dev, pci_dev); 61 : : 62 : 0 : return 0; 63 : : } 64 : : 65 : : /** 66 : : * @internal 67 : : * Allocates a new ethdev slot for an Ethernet device and returns the pointer 68 : : * to that slot for the driver to use. 69 : : * 70 : : * @param dev 71 : : * Pointer to the PCI device 72 : : * 73 : : * @param private_data_size 74 : : * Size of private data structure 75 : : * 76 : : * @return 77 : : * A pointer to a rte_eth_dev or NULL if allocation failed. 78 : : */ 79 : : static inline struct rte_eth_dev * 80 : 0 : rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size) 81 : : { 82 : : struct rte_eth_dev *eth_dev; 83 : : const char *name; 84 : : 85 [ # # ]: 0 : if (!dev) 86 : : return NULL; 87 : : 88 : 0 : name = dev->device.name; 89 : : 90 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 91 : 0 : eth_dev = rte_eth_dev_allocate(name); 92 [ # # ]: 0 : if (!eth_dev) 93 : : return NULL; 94 : : 95 [ # # ]: 0 : if (private_data_size) { 96 : : /* Try and alloc the private-data structure on socket local to the device */ 97 : 0 : eth_dev->data->dev_private = rte_zmalloc_socket(name, 98 : : private_data_size, RTE_CACHE_LINE_SIZE, 99 : : dev->device.numa_node); 100 : : 101 : : /* if cannot allocate memory on the socket local to the device 102 : : * use rte_malloc to allocate memory on some other socket, if available. 103 : : */ 104 [ # # ]: 0 : if (eth_dev->data->dev_private == NULL) { 105 : 0 : eth_dev->data->dev_private = rte_zmalloc(name, 106 : : private_data_size, RTE_CACHE_LINE_SIZE); 107 : : 108 [ # # ]: 0 : if (eth_dev->data->dev_private == NULL) { 109 : 0 : rte_eth_dev_release_port(eth_dev); 110 : 0 : return NULL; 111 : : } 112 : : /* got memory, but not local, so issue warning */ 113 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, 114 : : "Private data for ethdev '%s' not allocated on local NUMA node %d", 115 : : dev->device.name, dev->device.numa_node); 116 : : } 117 : : } 118 : : } else { 119 : 0 : eth_dev = rte_eth_dev_attach_secondary(name); 120 [ # # ]: 0 : if (!eth_dev) 121 : : return NULL; 122 : : } 123 : : 124 : 0 : eth_dev->device = &dev->device; 125 : 0 : rte_eth_copy_pci_info(eth_dev, dev); 126 : 0 : return eth_dev; 127 : : } 128 : : 129 : : typedef int (*eth_dev_pci_callback_t)(struct rte_eth_dev *eth_dev); 130 : : 131 : : /** 132 : : * @internal 133 : : * Wrapper for use by pci drivers in a .probe function to attach to a ethdev 134 : : * interface. 135 : : */ 136 : : static inline int 137 : 0 : rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev, 138 : : size_t private_data_size, eth_dev_pci_callback_t dev_init) 139 : : { 140 : : struct rte_eth_dev *eth_dev; 141 : : int ret; 142 : : 143 [ # # ]: 0 : if (*dev_init == NULL) 144 : : return -EINVAL; 145 : : 146 : 0 : eth_dev = rte_eth_dev_pci_allocate(pci_dev, private_data_size); 147 [ # # ]: 0 : if (!eth_dev) 148 : : return -ENOMEM; 149 : : 150 : 0 : ret = dev_init(eth_dev); 151 [ # # ]: 0 : if (ret) 152 : 0 : rte_eth_dev_release_port(eth_dev); 153 : : else 154 : 0 : rte_eth_dev_probing_finish(eth_dev); 155 : : 156 : : return ret; 157 : : } 158 : : 159 : : /** 160 : : * @internal 161 : : * Wrapper for use by pci drivers in a .remove function to detach a ethdev 162 : : * interface. 163 : : */ 164 : : static inline int 165 : 0 : rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev, 166 : : eth_dev_pci_callback_t dev_uninit) 167 : : { 168 : : struct rte_eth_dev *eth_dev; 169 : : int ret; 170 : : 171 : 0 : eth_dev = rte_eth_dev_allocated(pci_dev->device.name); 172 [ # # ]: 0 : if (!eth_dev) 173 : : return 0; 174 : : 175 : : /* 176 : : * In secondary process, a released eth device can be found by its name 177 : : * in shared memory. 178 : : * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 179 : : * eth device has been released. 180 : : */ 181 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY && 182 [ # # ]: 0 : eth_dev->state == RTE_ETH_DEV_UNUSED) 183 : : return 0; 184 : : 185 [ # # ]: 0 : if (dev_uninit) { 186 : 0 : ret = dev_uninit(eth_dev); 187 [ # # ]: 0 : if (ret) 188 : : return ret; 189 : : } 190 : : 191 : 0 : rte_eth_dev_release_port(eth_dev); 192 : 0 : return 0; 193 : : } 194 : : 195 : : #ifdef __cplusplus 196 : : } 197 : : #endif 198 : : 199 : : #endif /* _RTE_ETHDEV_PCI_H_ */