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 : : #ifdef __cplusplus 10 : : extern "C" { 11 : : #endif 12 : : 13 : : #include <rte_malloc.h> 14 : : #include <rte_pci.h> 15 : : #include <bus_pci_driver.h> 16 : : #include <rte_config.h> 17 : : #include <ethdev_driver.h> 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 : 0 : eth_dev->data->dev_private = rte_zmalloc_socket(name, 97 : : private_data_size, RTE_CACHE_LINE_SIZE, 98 : : dev->device.numa_node); 99 [ # # ]: 0 : if (!eth_dev->data->dev_private) { 100 : 0 : rte_eth_dev_release_port(eth_dev); 101 : 0 : return NULL; 102 : : } 103 : : } 104 : : } else { 105 : 0 : eth_dev = rte_eth_dev_attach_secondary(name); 106 [ # # ]: 0 : if (!eth_dev) 107 : : return NULL; 108 : : } 109 : : 110 : 0 : eth_dev->device = &dev->device; 111 : 0 : rte_eth_copy_pci_info(eth_dev, dev); 112 : 0 : return eth_dev; 113 : : } 114 : : 115 : : typedef int (*eth_dev_pci_callback_t)(struct rte_eth_dev *eth_dev); 116 : : 117 : : /** 118 : : * @internal 119 : : * Wrapper for use by pci drivers in a .probe function to attach to a ethdev 120 : : * interface. 121 : : */ 122 : : static inline int 123 : 0 : rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev, 124 : : size_t private_data_size, eth_dev_pci_callback_t dev_init) 125 : : { 126 : : struct rte_eth_dev *eth_dev; 127 : : int ret; 128 : : 129 [ # # ]: 0 : if (*dev_init == NULL) 130 : : return -EINVAL; 131 : : 132 : 0 : eth_dev = rte_eth_dev_pci_allocate(pci_dev, private_data_size); 133 [ # # ]: 0 : if (!eth_dev) 134 : : return -ENOMEM; 135 : : 136 : 0 : ret = dev_init(eth_dev); 137 [ # # ]: 0 : if (ret) 138 : 0 : rte_eth_dev_release_port(eth_dev); 139 : : else 140 : 0 : rte_eth_dev_probing_finish(eth_dev); 141 : : 142 : : return ret; 143 : : } 144 : : 145 : : /** 146 : : * @internal 147 : : * Wrapper for use by pci drivers in a .remove function to detach a ethdev 148 : : * interface. 149 : : */ 150 : : static inline int 151 : 0 : rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev, 152 : : eth_dev_pci_callback_t dev_uninit) 153 : : { 154 : : struct rte_eth_dev *eth_dev; 155 : : int ret; 156 : : 157 : 0 : eth_dev = rte_eth_dev_allocated(pci_dev->device.name); 158 [ # # ]: 0 : if (!eth_dev) 159 : : return 0; 160 : : 161 : : /* 162 : : * In secondary process, a released eth device can be found by its name 163 : : * in shared memory. 164 : : * If the state of the eth device is RTE_ETH_DEV_UNUSED, it means the 165 : : * eth device has been released. 166 : : */ 167 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY && 168 [ # # ]: 0 : eth_dev->state == RTE_ETH_DEV_UNUSED) 169 : : return 0; 170 : : 171 [ # # ]: 0 : if (dev_uninit) { 172 : 0 : ret = dev_uninit(eth_dev); 173 [ # # ]: 0 : if (ret) 174 : : return ret; 175 : : } 176 : : 177 : 0 : rte_eth_dev_release_port(eth_dev); 178 : 0 : return 0; 179 : : } 180 : : 181 : : #ifdef __cplusplus 182 : : } 183 : : #endif 184 : : 185 : : #endif /* _RTE_ETHDEV_PCI_H_ */