1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2017 Brocade Communications Systems, Inc. 5 * Author: Jan Blunck <[email protected]> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef _RTE_ETHDEV_PCI_H_ 35 #define _RTE_ETHDEV_PCI_H_ 36 37 #include <rte_malloc.h> 38 #include <rte_pci.h> 39 #include <rte_bus_pci.h> 40 #include <rte_config.h> 41 #include <rte_ethdev_driver.h> 42 43 /** 44 * Copy pci device info to the Ethernet device data. 45 * Shared memory (eth_dev->data) only updated by primary process, so it is safe 46 * to call this function from both primary and secondary processes. 47 * 48 * @param eth_dev 49 * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. 50 * @param pci_dev 51 * The *pci_dev* pointer is the address of the *rte_pci_device* structure. 52 */ 53 static inline void 54 rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, 55 struct rte_pci_device *pci_dev) 56 { 57 if ((eth_dev == NULL) || (pci_dev == NULL)) { 58 RTE_ETHDEV_LOG(ERR, "NULL pointer eth_dev=%p pci_dev=%p", 59 (void *)eth_dev, (void *)pci_dev); 60 return; 61 } 62 63 eth_dev->intr_handle = &pci_dev->intr_handle; 64 65 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 66 eth_dev->data->dev_flags = 0; 67 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) 68 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 69 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV) 70 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV; 71 72 eth_dev->data->kdrv = pci_dev->kdrv; 73 eth_dev->data->numa_node = pci_dev->device.numa_node; 74 } 75 } 76 77 static inline int 78 eth_dev_pci_specific_init(struct rte_eth_dev *eth_dev, void *bus_device) { 79 struct rte_pci_device *pci_dev = bus_device; 80 81 if (!pci_dev) 82 return -ENODEV; 83 84 rte_eth_copy_pci_info(eth_dev, pci_dev); 85 86 return 0; 87 } 88 89 /** 90 * @internal 91 * Allocates a new ethdev slot for an ethernet device and returns the pointer 92 * to that slot for the driver to use. 93 * 94 * @param dev 95 * Pointer to the PCI device 96 * 97 * @param private_data_size 98 * Size of private data structure 99 * 100 * @return 101 * A pointer to a rte_eth_dev or NULL if allocation failed. 102 */ 103 static inline struct rte_eth_dev * 104 rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size) 105 { 106 struct rte_eth_dev *eth_dev; 107 const char *name; 108 109 if (!dev) 110 return NULL; 111 112 name = dev->device.name; 113 114 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 115 eth_dev = rte_eth_dev_allocate(name); 116 if (!eth_dev) 117 return NULL; 118 119 if (private_data_size) { 120 eth_dev->data->dev_private = rte_zmalloc_socket(name, 121 private_data_size, RTE_CACHE_LINE_SIZE, 122 dev->device.numa_node); 123 if (!eth_dev->data->dev_private) { 124 rte_eth_dev_release_port(eth_dev); 125 return NULL; 126 } 127 } 128 } else { 129 eth_dev = rte_eth_dev_attach_secondary(name); 130 if (!eth_dev) 131 return NULL; 132 } 133 134 eth_dev->device = &dev->device; 135 rte_eth_copy_pci_info(eth_dev, dev); 136 return eth_dev; 137 } 138 139 static inline void 140 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev) 141 { 142 eth_dev->device = NULL; 143 eth_dev->intr_handle = NULL; 144 145 /* free ether device */ 146 rte_eth_dev_release_port(eth_dev); 147 } 148 149 typedef int (*eth_dev_pci_callback_t)(struct rte_eth_dev *eth_dev); 150 151 /** 152 * @internal 153 * Wrapper for use by pci drivers in a .probe function to attach to a ethdev 154 * interface. 155 */ 156 static inline int 157 rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev, 158 size_t private_data_size, eth_dev_pci_callback_t dev_init) 159 { 160 struct rte_eth_dev *eth_dev; 161 int ret; 162 163 eth_dev = rte_eth_dev_pci_allocate(pci_dev, private_data_size); 164 if (!eth_dev) 165 return -ENOMEM; 166 167 RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL); 168 ret = dev_init(eth_dev); 169 if (ret) 170 rte_eth_dev_pci_release(eth_dev); 171 else 172 rte_eth_dev_probing_finish(eth_dev); 173 174 return ret; 175 } 176 177 /** 178 * @internal 179 * Wrapper for use by pci drivers in a .remove function to detach a ethdev 180 * interface. 181 */ 182 static inline int 183 rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev, 184 eth_dev_pci_callback_t dev_uninit) 185 { 186 struct rte_eth_dev *eth_dev; 187 int ret; 188 189 eth_dev = rte_eth_dev_allocated(pci_dev->device.name); 190 if (!eth_dev) 191 return 0; 192 193 if (dev_uninit) { 194 ret = dev_uninit(eth_dev); 195 if (ret) 196 return ret; 197 } 198 199 rte_eth_dev_pci_release(eth_dev); 200 return 0; 201 } 202 203 #endif /* _RTE_ETHDEV_PCI_H_ */ 204