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