1 /*- 2 * Copyright (c) 2015-2016 Mellanox Technologies, Ltd. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/malloc.h> 33 #include <sys/kernel.h> 34 #include <sys/sysctl.h> 35 #include <sys/lock.h> 36 #include <sys/mutex.h> 37 #include <sys/bus.h> 38 #include <sys/fcntl.h> 39 #include <sys/file.h> 40 #include <sys/filio.h> 41 #include <sys/rwlock.h> 42 43 #include <vm/vm.h> 44 #include <vm/pmap.h> 45 46 #include <machine/stdarg.h> 47 48 #include <linux/kobject.h> 49 #include <linux/device.h> 50 #include <linux/slab.h> 51 #include <linux/module.h> 52 #include <linux/cdev.h> 53 #include <linux/file.h> 54 #include <linux/sysfs.h> 55 #include <linux/mm.h> 56 #include <linux/io.h> 57 #include <linux/vmalloc.h> 58 #include <linux/pci.h> 59 #include <linux/compat.h> 60 61 static device_probe_t linux_pci_probe; 62 static device_attach_t linux_pci_attach; 63 static device_detach_t linux_pci_detach; 64 static device_suspend_t linux_pci_suspend; 65 static device_resume_t linux_pci_resume; 66 static device_shutdown_t linux_pci_shutdown; 67 68 static device_method_t pci_methods[] = { 69 DEVMETHOD(device_probe, linux_pci_probe), 70 DEVMETHOD(device_attach, linux_pci_attach), 71 DEVMETHOD(device_detach, linux_pci_detach), 72 DEVMETHOD(device_suspend, linux_pci_suspend), 73 DEVMETHOD(device_resume, linux_pci_resume), 74 DEVMETHOD(device_shutdown, linux_pci_shutdown), 75 DEVMETHOD_END 76 }; 77 78 static struct pci_driver * 79 linux_pci_find(device_t dev, const struct pci_device_id **idp) 80 { 81 const struct pci_device_id *id; 82 struct pci_driver *pdrv; 83 uint16_t vendor; 84 uint16_t device; 85 uint16_t subvendor; 86 uint16_t subdevice; 87 88 vendor = pci_get_vendor(dev); 89 device = pci_get_device(dev); 90 subvendor = pci_get_subvendor(dev); 91 subdevice = pci_get_subdevice(dev); 92 93 spin_lock(&pci_lock); 94 list_for_each_entry(pdrv, &pci_drivers, links) { 95 for (id = pdrv->id_table; id->vendor != 0; id++) { 96 if (vendor == id->vendor && 97 (PCI_ANY_ID == id->device || device == id->device) && 98 (PCI_ANY_ID == id->subvendor || subvendor == id->subvendor) && 99 (PCI_ANY_ID == id->subdevice || subdevice == id->subdevice)) { 100 *idp = id; 101 spin_unlock(&pci_lock); 102 return (pdrv); 103 } 104 } 105 } 106 spin_unlock(&pci_lock); 107 return (NULL); 108 } 109 110 static int 111 linux_pci_probe(device_t dev) 112 { 113 const struct pci_device_id *id; 114 struct pci_driver *pdrv; 115 116 if ((pdrv = linux_pci_find(dev, &id)) == NULL) 117 return (ENXIO); 118 if (device_get_driver(dev) != &pdrv->bsddriver) 119 return (ENXIO); 120 device_set_desc(dev, pdrv->name); 121 return (0); 122 } 123 124 static int 125 linux_pci_attach(device_t dev) 126 { 127 struct resource_list_entry *rle; 128 struct pci_bus *pbus; 129 struct pci_dev *pdev; 130 struct pci_devinfo *dinfo; 131 struct pci_driver *pdrv; 132 const struct pci_device_id *id; 133 device_t parent; 134 devclass_t devclass; 135 int error; 136 137 linux_set_current(curthread); 138 139 pdrv = linux_pci_find(dev, &id); 140 pdev = device_get_softc(dev); 141 142 parent = device_get_parent(dev); 143 devclass = device_get_devclass(parent); 144 if (pdrv->isdrm) { 145 dinfo = device_get_ivars(parent); 146 device_set_ivars(dev, dinfo); 147 } else { 148 dinfo = device_get_ivars(dev); 149 } 150 151 pdev->dev.parent = &linux_root_device; 152 pdev->dev.bsddev = dev; 153 INIT_LIST_HEAD(&pdev->dev.irqents); 154 pdev->devfn = PCI_DEVFN(pci_get_slot(dev), pci_get_function(dev)); 155 pdev->device = dinfo->cfg.device; 156 pdev->vendor = dinfo->cfg.vendor; 157 pdev->subsystem_vendor = dinfo->cfg.subvendor; 158 pdev->subsystem_device = dinfo->cfg.subdevice; 159 pdev->class = pci_get_class(dev); 160 pdev->revision = pci_get_revid(dev); 161 pdev->dev.dma_mask = &pdev->dma_mask; 162 pdev->pdrv = pdrv; 163 kobject_init(&pdev->dev.kobj, &linux_dev_ktype); 164 kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); 165 kobject_add(&pdev->dev.kobj, &linux_root_device.kobj, 166 kobject_name(&pdev->dev.kobj)); 167 rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 0); 168 if (rle != NULL) 169 pdev->dev.irq = rle->start; 170 else 171 pdev->dev.irq = LINUX_IRQ_INVALID; 172 pdev->irq = pdev->dev.irq; 173 174 if (pdev->bus == NULL) { 175 pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK | M_ZERO); 176 pbus->self = pdev; 177 pbus->number = pci_get_bus(dev); 178 pdev->bus = pbus; 179 } 180 181 spin_lock(&pci_lock); 182 list_add(&pdev->links, &pci_devices); 183 spin_unlock(&pci_lock); 184 185 error = pdrv->probe(pdev, id); 186 if (error) { 187 spin_lock(&pci_lock); 188 list_del(&pdev->links); 189 spin_unlock(&pci_lock); 190 put_device(&pdev->dev); 191 error = -error; 192 } 193 return (error); 194 } 195 196 static int 197 linux_pci_detach(device_t dev) 198 { 199 struct pci_dev *pdev; 200 201 linux_set_current(curthread); 202 pdev = device_get_softc(dev); 203 204 pdev->pdrv->remove(pdev); 205 206 spin_lock(&pci_lock); 207 list_del(&pdev->links); 208 spin_unlock(&pci_lock); 209 device_set_desc(dev, NULL); 210 put_device(&pdev->dev); 211 212 return (0); 213 } 214 215 static int 216 linux_pci_suspend(device_t dev) 217 { 218 const struct dev_pm_ops *pmops; 219 struct pm_message pm = { }; 220 struct pci_dev *pdev; 221 int error; 222 223 error = 0; 224 linux_set_current(curthread); 225 pdev = device_get_softc(dev); 226 pmops = pdev->pdrv->driver.pm; 227 228 if (pdev->pdrv->suspend != NULL) 229 error = -pdev->pdrv->suspend(pdev, pm); 230 else if (pmops != NULL && pmops->suspend != NULL) { 231 error = -pmops->suspend(&pdev->dev); 232 if (error == 0 && pmops->suspend_late != NULL) 233 error = -pmops->suspend_late(&pdev->dev); 234 } 235 return (error); 236 } 237 238 static int 239 linux_pci_resume(device_t dev) 240 { 241 const struct dev_pm_ops *pmops; 242 struct pci_dev *pdev; 243 int error; 244 245 error = 0; 246 linux_set_current(curthread); 247 pdev = device_get_softc(dev); 248 pmops = pdev->pdrv->driver.pm; 249 250 if (pdev->pdrv->resume != NULL) 251 error = -pdev->pdrv->resume(pdev); 252 else if (pmops != NULL && pmops->resume != NULL) { 253 if (pmops->resume_early != NULL) 254 error = -pmops->resume_early(&pdev->dev); 255 if (error == 0 && pmops->resume != NULL) 256 error = -pmops->resume(&pdev->dev); 257 } 258 return (error); 259 } 260 261 static int 262 linux_pci_shutdown(device_t dev) 263 { 264 struct pci_dev *pdev; 265 266 linux_set_current(curthread); 267 pdev = device_get_softc(dev); 268 if (pdev->pdrv->shutdown != NULL) 269 pdev->pdrv->shutdown(pdev); 270 return (0); 271 } 272 273 static int 274 _linux_pci_register_driver(struct pci_driver *pdrv, devclass_t dc) 275 { 276 int error; 277 278 linux_set_current(curthread); 279 spin_lock(&pci_lock); 280 list_add(&pdrv->links, &pci_drivers); 281 spin_unlock(&pci_lock); 282 pdrv->bsddriver.name = pdrv->name; 283 pdrv->bsddriver.methods = pci_methods; 284 pdrv->bsddriver.size = sizeof(struct pci_dev); 285 286 mtx_lock(&Giant); 287 error = devclass_add_driver(dc, &pdrv->bsddriver, 288 BUS_PASS_DEFAULT, &pdrv->bsdclass); 289 mtx_unlock(&Giant); 290 return (-error); 291 } 292 293 int 294 linux_pci_register_driver(struct pci_driver *pdrv) 295 { 296 devclass_t dc; 297 298 dc = devclass_find("pci"); 299 if (dc == NULL) 300 return (-ENXIO); 301 pdrv->isdrm = false; 302 return (_linux_pci_register_driver(pdrv, dc)); 303 } 304 305 int 306 linux_pci_register_drm_driver(struct pci_driver *pdrv) 307 { 308 devclass_t dc; 309 310 dc = devclass_create("vgapci"); 311 if (dc == NULL) 312 return (-ENXIO); 313 pdrv->isdrm = true; 314 pdrv->name = "drmn"; 315 return (_linux_pci_register_driver(pdrv, dc)); 316 } 317 318 void 319 linux_pci_unregister_driver(struct pci_driver *pdrv) 320 { 321 devclass_t bus; 322 323 bus = devclass_find("pci"); 324 325 spin_lock(&pci_lock); 326 list_del(&pdrv->links); 327 spin_unlock(&pci_lock); 328 mtx_lock(&Giant); 329 if (bus != NULL) 330 devclass_delete_driver(bus, &pdrv->bsddriver); 331 mtx_unlock(&Giant); 332 } 333