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 * 46 * @param eth_dev 47 * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. 48 * @param pci_dev 49 * The *pci_dev* pointer is the address of the *rte_pci_device* structure. 50 */ 51 static inline void 52 rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, 53 struct rte_pci_device *pci_dev) 54 { 55 if ((eth_dev == NULL) || (pci_dev == NULL)) { 56 RTE_ETHDEV_LOG(ERR, "NULL pointer eth_dev=%p pci_dev=%p", 57 (void *)eth_dev, (void *)pci_dev); 58 return; 59 } 60 61 eth_dev->intr_handle = &pci_dev->intr_handle; 62 63 eth_dev->data->dev_flags = 0; 64 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) 65 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; 66 if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV) 67 eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV; 68 69 eth_dev->data->kdrv = pci_dev->kdrv; 70 eth_dev->data->numa_node = pci_dev->device.numa_node; 71 } 72 73 static inline int 74 eth_dev_pci_specific_init(struct rte_eth_dev *eth_dev, void *bus_device) { 75 struct rte_pci_device *pci_dev = bus_device; 76 77 if (!pci_dev) 78 return -ENODEV; 79 80 rte_eth_copy_pci_info(eth_dev, pci_dev); 81 82 return 0; 83 } 84 85 /** 86 * @internal 87 * Allocates a new ethdev slot for an ethernet device and returns the pointer 88 * to that slot for the driver to use. 89 * 90 * @param dev 91 * Pointer to the PCI device 92 * 93 * @param private_data_size 94 * Size of private data structure 95 * 96 * @return 97 * A pointer to a rte_eth_dev or NULL if allocation failed. 98 */ 99 static inline struct rte_eth_dev * 100 rte_eth_dev_pci_allocate(struct rte_pci_device *dev, size_t private_data_size) 101 { 102 struct rte_eth_dev *eth_dev; 103 const char *name; 104 105 if (!dev) 106 return NULL; 107 108 name = dev->device.name; 109 110 if (rte_eal_process_type() == RTE_PROC_PRIMARY) { 111 eth_dev = rte_eth_dev_allocate(name); 112 if (!eth_dev) 113 return NULL; 114 115 if (private_data_size) { 116 eth_dev->data->dev_private = rte_zmalloc_socket(name, 117 private_data_size, RTE_CACHE_LINE_SIZE, 118 dev->device.numa_node); 119 if (!eth_dev->data->dev_private) { 120 rte_eth_dev_release_port(eth_dev); 121 return NULL; 122 } 123 } 124 } else { 125 eth_dev = rte_eth_dev_attach_secondary(name); 126 if (!eth_dev) 127 return NULL; 128 } 129 130 eth_dev->device = &dev->device; 131 rte_eth_copy_pci_info(eth_dev, dev); 132 return eth_dev; 133 } 134 135 static inline void 136 rte_eth_dev_pci_release(struct rte_eth_dev *eth_dev) 137 { 138 eth_dev->device = NULL; 139 eth_dev->intr_handle = NULL; 140 141 /* free ether device */ 142 rte_eth_dev_release_port(eth_dev); 143 } 144 145 typedef int (*eth_dev_pci_callback_t)(struct rte_eth_dev *eth_dev); 146 147 /** 148 * @internal 149 * Wrapper for use by pci drivers in a .probe function to attach to a ethdev 150 * interface. 151 */ 152 static inline int 153 rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev, 154 size_t private_data_size, eth_dev_pci_callback_t dev_init) 155 { 156 struct rte_eth_dev *eth_dev; 157 int ret; 158 159 eth_dev = rte_eth_dev_pci_allocate(pci_dev, private_data_size); 160 if (!eth_dev) 161 return -ENOMEM; 162 163 RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL); 164 ret = dev_init(eth_dev); 165 if (ret) 166 rte_eth_dev_pci_release(eth_dev); 167 else 168 rte_eth_dev_probing_finish(eth_dev); 169 170 return ret; 171 } 172 173 /** 174 * @internal 175 * Wrapper for use by pci drivers in a .remove function to detach a ethdev 176 * interface. 177 */ 178 static inline int 179 rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev, 180 eth_dev_pci_callback_t dev_uninit) 181 { 182 struct rte_eth_dev *eth_dev; 183 int ret; 184 185 eth_dev = rte_eth_dev_allocated(pci_dev->device.name); 186 if (!eth_dev) 187 return -ENODEV; 188 189 if (dev_uninit) { 190 ret = dev_uninit(eth_dev); 191 if (ret) 192 return ret; 193 } 194 195 rte_eth_dev_pci_release(eth_dev); 196 return 0; 197 } 198 199 #endif /* _RTE_ETHDEV_PCI_H_ */ 200