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/bus.h> 33 #include <sys/malloc.h> 34 #include <sys/kernel.h> 35 #include <sys/sysctl.h> 36 #include <sys/lock.h> 37 #include <sys/mutex.h> 38 #include <sys/fcntl.h> 39 #include <sys/file.h> 40 #include <sys/filio.h> 41 #include <sys/pciio.h> 42 #include <sys/pctrie.h> 43 #include <sys/rwlock.h> 44 45 #include <vm/vm.h> 46 #include <vm/pmap.h> 47 48 #include <machine/stdarg.h> 49 50 #include <dev/pci/pcivar.h> 51 #include <dev/pci/pci_private.h> 52 #include <dev/pci/pci_iov.h> 53 #include <dev/backlight/backlight.h> 54 55 #include <linux/kobject.h> 56 #include <linux/device.h> 57 #include <linux/slab.h> 58 #include <linux/module.h> 59 #include <linux/cdev.h> 60 #include <linux/file.h> 61 #include <linux/sysfs.h> 62 #include <linux/mm.h> 63 #include <linux/io.h> 64 #include <linux/vmalloc.h> 65 #include <linux/pci.h> 66 #include <linux/compat.h> 67 68 #include <linux/backlight.h> 69 70 #include "backlight_if.h" 71 72 static device_probe_t linux_pci_probe; 73 static device_attach_t linux_pci_attach; 74 static device_detach_t linux_pci_detach; 75 static device_suspend_t linux_pci_suspend; 76 static device_resume_t linux_pci_resume; 77 static device_shutdown_t linux_pci_shutdown; 78 static pci_iov_init_t linux_pci_iov_init; 79 static pci_iov_uninit_t linux_pci_iov_uninit; 80 static pci_iov_add_vf_t linux_pci_iov_add_vf; 81 static int linux_backlight_get_status(device_t dev, struct backlight_props *props); 82 static int linux_backlight_update_status(device_t dev, struct backlight_props *props); 83 static int linux_backlight_get_info(device_t dev, struct backlight_info *info); 84 85 static device_method_t pci_methods[] = { 86 DEVMETHOD(device_probe, linux_pci_probe), 87 DEVMETHOD(device_attach, linux_pci_attach), 88 DEVMETHOD(device_detach, linux_pci_detach), 89 DEVMETHOD(device_suspend, linux_pci_suspend), 90 DEVMETHOD(device_resume, linux_pci_resume), 91 DEVMETHOD(device_shutdown, linux_pci_shutdown), 92 DEVMETHOD(pci_iov_init, linux_pci_iov_init), 93 DEVMETHOD(pci_iov_uninit, linux_pci_iov_uninit), 94 DEVMETHOD(pci_iov_add_vf, linux_pci_iov_add_vf), 95 96 /* backlight interface */ 97 DEVMETHOD(backlight_update_status, linux_backlight_update_status), 98 DEVMETHOD(backlight_get_status, linux_backlight_get_status), 99 DEVMETHOD(backlight_get_info, linux_backlight_get_info), 100 DEVMETHOD_END 101 }; 102 103 struct linux_dma_priv { 104 uint64_t dma_mask; 105 struct mtx lock; 106 bus_dma_tag_t dmat; 107 struct pctrie ptree; 108 }; 109 #define DMA_PRIV_LOCK(priv) mtx_lock(&(priv)->lock) 110 #define DMA_PRIV_UNLOCK(priv) mtx_unlock(&(priv)->lock) 111 112 static int 113 linux_pdev_dma_init(struct pci_dev *pdev) 114 { 115 struct linux_dma_priv *priv; 116 int error; 117 118 priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO); 119 pdev->dev.dma_priv = priv; 120 121 mtx_init(&priv->lock, "lkpi-priv-dma", NULL, MTX_DEF); 122 123 pctrie_init(&priv->ptree); 124 125 /* create a default DMA tag */ 126 error = linux_dma_tag_init(&pdev->dev, DMA_BIT_MASK(64)); 127 if (error) { 128 mtx_destroy(&priv->lock); 129 free(priv, M_DEVBUF); 130 pdev->dev.dma_priv = NULL; 131 } 132 return (error); 133 } 134 135 static int 136 linux_pdev_dma_uninit(struct pci_dev *pdev) 137 { 138 struct linux_dma_priv *priv; 139 140 priv = pdev->dev.dma_priv; 141 if (priv->dmat) 142 bus_dma_tag_destroy(priv->dmat); 143 mtx_destroy(&priv->lock); 144 free(priv, M_DEVBUF); 145 pdev->dev.dma_priv = NULL; 146 return (0); 147 } 148 149 int 150 linux_dma_tag_init(struct device *dev, u64 dma_mask) 151 { 152 struct linux_dma_priv *priv; 153 int error; 154 155 priv = dev->dma_priv; 156 157 if (priv->dmat) { 158 if (priv->dma_mask == dma_mask) 159 return (0); 160 161 bus_dma_tag_destroy(priv->dmat); 162 } 163 164 priv->dma_mask = dma_mask; 165 166 error = bus_dma_tag_create(bus_get_dma_tag(dev->bsddev), 167 1, 0, /* alignment, boundary */ 168 dma_mask, /* lowaddr */ 169 BUS_SPACE_MAXADDR, /* highaddr */ 170 NULL, NULL, /* filtfunc, filtfuncarg */ 171 BUS_SPACE_MAXSIZE, /* maxsize */ 172 1, /* nsegments */ 173 BUS_SPACE_MAXSIZE, /* maxsegsz */ 174 0, /* flags */ 175 NULL, NULL, /* lockfunc, lockfuncarg */ 176 &priv->dmat); 177 return (-error); 178 } 179 180 static struct pci_driver * 181 linux_pci_find(device_t dev, const struct pci_device_id **idp) 182 { 183 const struct pci_device_id *id; 184 struct pci_driver *pdrv; 185 uint16_t vendor; 186 uint16_t device; 187 uint16_t subvendor; 188 uint16_t subdevice; 189 190 vendor = pci_get_vendor(dev); 191 device = pci_get_device(dev); 192 subvendor = pci_get_subvendor(dev); 193 subdevice = pci_get_subdevice(dev); 194 195 spin_lock(&pci_lock); 196 list_for_each_entry(pdrv, &pci_drivers, links) { 197 for (id = pdrv->id_table; id->vendor != 0; id++) { 198 if (vendor == id->vendor && 199 (PCI_ANY_ID == id->device || device == id->device) && 200 (PCI_ANY_ID == id->subvendor || subvendor == id->subvendor) && 201 (PCI_ANY_ID == id->subdevice || subdevice == id->subdevice)) { 202 *idp = id; 203 spin_unlock(&pci_lock); 204 return (pdrv); 205 } 206 } 207 } 208 spin_unlock(&pci_lock); 209 return (NULL); 210 } 211 212 static int 213 linux_pci_probe(device_t dev) 214 { 215 const struct pci_device_id *id; 216 struct pci_driver *pdrv; 217 218 if ((pdrv = linux_pci_find(dev, &id)) == NULL) 219 return (ENXIO); 220 if (device_get_driver(dev) != &pdrv->bsddriver) 221 return (ENXIO); 222 device_set_desc(dev, pdrv->name); 223 return (0); 224 } 225 226 static int 227 linux_pci_attach(device_t dev) 228 { 229 const struct pci_device_id *id; 230 struct pci_driver *pdrv; 231 struct pci_dev *pdev; 232 233 pdrv = linux_pci_find(dev, &id); 234 pdev = device_get_softc(dev); 235 236 MPASS(pdrv != NULL); 237 MPASS(pdev != NULL); 238 239 return (linux_pci_attach_device(dev, pdrv, id, pdev)); 240 } 241 242 int 243 linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, 244 const struct pci_device_id *id, struct pci_dev *pdev) 245 { 246 struct resource_list_entry *rle; 247 struct pci_bus *pbus; 248 struct pci_devinfo *dinfo; 249 device_t parent; 250 int error; 251 252 linux_set_current(curthread); 253 254 if (pdrv != NULL && pdrv->isdrm) { 255 parent = device_get_parent(dev); 256 dinfo = device_get_ivars(parent); 257 device_set_ivars(dev, dinfo); 258 } else { 259 dinfo = device_get_ivars(dev); 260 } 261 262 pdev->dev.parent = &linux_root_device; 263 pdev->dev.bsddev = dev; 264 INIT_LIST_HEAD(&pdev->dev.irqents); 265 pdev->devfn = PCI_DEVFN(pci_get_slot(dev), pci_get_function(dev)); 266 pdev->device = dinfo->cfg.device; 267 pdev->vendor = dinfo->cfg.vendor; 268 pdev->subsystem_vendor = dinfo->cfg.subvendor; 269 pdev->subsystem_device = dinfo->cfg.subdevice; 270 pdev->class = pci_get_class(dev); 271 pdev->revision = pci_get_revid(dev); 272 pdev->pdrv = pdrv; 273 kobject_init(&pdev->dev.kobj, &linux_dev_ktype); 274 kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); 275 kobject_add(&pdev->dev.kobj, &linux_root_device.kobj, 276 kobject_name(&pdev->dev.kobj)); 277 rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 0); 278 if (rle != NULL) 279 pdev->dev.irq = rle->start; 280 else 281 pdev->dev.irq = LINUX_IRQ_INVALID; 282 pdev->irq = pdev->dev.irq; 283 error = linux_pdev_dma_init(pdev); 284 if (error) 285 goto out_dma_init; 286 287 TAILQ_INIT(&pdev->mmio); 288 pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK | M_ZERO); 289 pbus->self = pdev; 290 pbus->number = pci_get_bus(dev); 291 pbus->domain = pci_get_domain(dev); 292 pdev->bus = pbus; 293 294 spin_lock(&pci_lock); 295 list_add(&pdev->links, &pci_devices); 296 spin_unlock(&pci_lock); 297 298 if (pdrv != NULL) { 299 error = pdrv->probe(pdev, id); 300 if (error) 301 goto out_probe; 302 } 303 return (0); 304 305 out_probe: 306 free(pdev->bus, M_DEVBUF); 307 linux_pdev_dma_uninit(pdev); 308 out_dma_init: 309 spin_lock(&pci_lock); 310 list_del(&pdev->links); 311 spin_unlock(&pci_lock); 312 put_device(&pdev->dev); 313 return (-error); 314 } 315 316 static int 317 linux_pci_detach(device_t dev) 318 { 319 struct pci_dev *pdev; 320 321 pdev = device_get_softc(dev); 322 323 MPASS(pdev != NULL); 324 325 device_set_desc(dev, NULL); 326 327 return (linux_pci_detach_device(pdev)); 328 } 329 330 int 331 linux_pci_detach_device(struct pci_dev *pdev) 332 { 333 334 linux_set_current(curthread); 335 336 if (pdev->pdrv != NULL) 337 pdev->pdrv->remove(pdev); 338 339 free(pdev->bus, M_DEVBUF); 340 linux_pdev_dma_uninit(pdev); 341 342 spin_lock(&pci_lock); 343 list_del(&pdev->links); 344 spin_unlock(&pci_lock); 345 put_device(&pdev->dev); 346 347 return (0); 348 } 349 350 static int 351 linux_pci_suspend(device_t dev) 352 { 353 const struct dev_pm_ops *pmops; 354 struct pm_message pm = { }; 355 struct pci_dev *pdev; 356 int error; 357 358 error = 0; 359 linux_set_current(curthread); 360 pdev = device_get_softc(dev); 361 pmops = pdev->pdrv->driver.pm; 362 363 if (pdev->pdrv->suspend != NULL) 364 error = -pdev->pdrv->suspend(pdev, pm); 365 else if (pmops != NULL && pmops->suspend != NULL) { 366 error = -pmops->suspend(&pdev->dev); 367 if (error == 0 && pmops->suspend_late != NULL) 368 error = -pmops->suspend_late(&pdev->dev); 369 } 370 return (error); 371 } 372 373 static int 374 linux_pci_resume(device_t dev) 375 { 376 const struct dev_pm_ops *pmops; 377 struct pci_dev *pdev; 378 int error; 379 380 error = 0; 381 linux_set_current(curthread); 382 pdev = device_get_softc(dev); 383 pmops = pdev->pdrv->driver.pm; 384 385 if (pdev->pdrv->resume != NULL) 386 error = -pdev->pdrv->resume(pdev); 387 else if (pmops != NULL && pmops->resume != NULL) { 388 if (pmops->resume_early != NULL) 389 error = -pmops->resume_early(&pdev->dev); 390 if (error == 0 && pmops->resume != NULL) 391 error = -pmops->resume(&pdev->dev); 392 } 393 return (error); 394 } 395 396 static int 397 linux_pci_shutdown(device_t dev) 398 { 399 struct pci_dev *pdev; 400 401 linux_set_current(curthread); 402 pdev = device_get_softc(dev); 403 if (pdev->pdrv->shutdown != NULL) 404 pdev->pdrv->shutdown(pdev); 405 return (0); 406 } 407 408 static int 409 linux_pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *pf_config) 410 { 411 struct pci_dev *pdev; 412 int error; 413 414 linux_set_current(curthread); 415 pdev = device_get_softc(dev); 416 if (pdev->pdrv->bsd_iov_init != NULL) 417 error = pdev->pdrv->bsd_iov_init(dev, num_vfs, pf_config); 418 else 419 error = EINVAL; 420 return (error); 421 } 422 423 static void 424 linux_pci_iov_uninit(device_t dev) 425 { 426 struct pci_dev *pdev; 427 428 linux_set_current(curthread); 429 pdev = device_get_softc(dev); 430 if (pdev->pdrv->bsd_iov_uninit != NULL) 431 pdev->pdrv->bsd_iov_uninit(dev); 432 } 433 434 static int 435 linux_pci_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *vf_config) 436 { 437 struct pci_dev *pdev; 438 int error; 439 440 linux_set_current(curthread); 441 pdev = device_get_softc(dev); 442 if (pdev->pdrv->bsd_iov_add_vf != NULL) 443 error = pdev->pdrv->bsd_iov_add_vf(dev, vfnum, vf_config); 444 else 445 error = EINVAL; 446 return (error); 447 } 448 449 static int 450 _linux_pci_register_driver(struct pci_driver *pdrv, devclass_t dc) 451 { 452 int error; 453 454 linux_set_current(curthread); 455 spin_lock(&pci_lock); 456 list_add(&pdrv->links, &pci_drivers); 457 spin_unlock(&pci_lock); 458 pdrv->bsddriver.name = pdrv->name; 459 pdrv->bsddriver.methods = pci_methods; 460 pdrv->bsddriver.size = sizeof(struct pci_dev); 461 462 mtx_lock(&Giant); 463 error = devclass_add_driver(dc, &pdrv->bsddriver, 464 BUS_PASS_DEFAULT, &pdrv->bsdclass); 465 mtx_unlock(&Giant); 466 return (-error); 467 } 468 469 int 470 linux_pci_register_driver(struct pci_driver *pdrv) 471 { 472 devclass_t dc; 473 474 dc = devclass_find("pci"); 475 if (dc == NULL) 476 return (-ENXIO); 477 pdrv->isdrm = false; 478 return (_linux_pci_register_driver(pdrv, dc)); 479 } 480 481 unsigned long 482 pci_resource_start(struct pci_dev *pdev, int bar) 483 { 484 struct resource_list_entry *rle; 485 rman_res_t newstart; 486 device_t dev; 487 488 if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) 489 return (0); 490 dev = pci_find_dbsf(pdev->bus->domain, pdev->bus->number, 491 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 492 MPASS(dev != NULL); 493 if (BUS_TRANSLATE_RESOURCE(dev, rle->type, rle->start, &newstart)) { 494 device_printf(pdev->dev.bsddev, "translate of %#jx failed\n", 495 (uintmax_t)rle->start); 496 return (0); 497 } 498 return (newstart); 499 } 500 501 unsigned long 502 pci_resource_len(struct pci_dev *pdev, int bar) 503 { 504 struct resource_list_entry *rle; 505 506 if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) 507 return (0); 508 return (rle->count); 509 } 510 511 int 512 linux_pci_register_drm_driver(struct pci_driver *pdrv) 513 { 514 devclass_t dc; 515 516 dc = devclass_create("vgapci"); 517 if (dc == NULL) 518 return (-ENXIO); 519 pdrv->isdrm = true; 520 pdrv->name = "drmn"; 521 return (_linux_pci_register_driver(pdrv, dc)); 522 } 523 524 void 525 linux_pci_unregister_driver(struct pci_driver *pdrv) 526 { 527 devclass_t bus; 528 529 bus = devclass_find("pci"); 530 531 spin_lock(&pci_lock); 532 list_del(&pdrv->links); 533 spin_unlock(&pci_lock); 534 mtx_lock(&Giant); 535 if (bus != NULL) 536 devclass_delete_driver(bus, &pdrv->bsddriver); 537 mtx_unlock(&Giant); 538 } 539 540 void 541 linux_pci_unregister_drm_driver(struct pci_driver *pdrv) 542 { 543 devclass_t bus; 544 545 bus = devclass_find("vgapci"); 546 547 spin_lock(&pci_lock); 548 list_del(&pdrv->links); 549 spin_unlock(&pci_lock); 550 mtx_lock(&Giant); 551 if (bus != NULL) 552 devclass_delete_driver(bus, &pdrv->bsddriver); 553 mtx_unlock(&Giant); 554 } 555 556 CTASSERT(sizeof(dma_addr_t) <= sizeof(uint64_t)); 557 558 struct linux_dma_obj { 559 void *vaddr; 560 uint64_t dma_addr; 561 bus_dmamap_t dmamap; 562 }; 563 564 static uma_zone_t linux_dma_trie_zone; 565 static uma_zone_t linux_dma_obj_zone; 566 567 static void 568 linux_dma_init(void *arg) 569 { 570 571 linux_dma_trie_zone = uma_zcreate("linux_dma_pctrie", 572 pctrie_node_size(), NULL, NULL, pctrie_zone_init, NULL, 573 UMA_ALIGN_PTR, 0); 574 linux_dma_obj_zone = uma_zcreate("linux_dma_object", 575 sizeof(struct linux_dma_obj), NULL, NULL, NULL, NULL, 576 UMA_ALIGN_PTR, 0); 577 578 } 579 SYSINIT(linux_dma, SI_SUB_DRIVERS, SI_ORDER_THIRD, linux_dma_init, NULL); 580 581 static void 582 linux_dma_uninit(void *arg) 583 { 584 585 uma_zdestroy(linux_dma_obj_zone); 586 uma_zdestroy(linux_dma_trie_zone); 587 } 588 SYSUNINIT(linux_dma, SI_SUB_DRIVERS, SI_ORDER_THIRD, linux_dma_uninit, NULL); 589 590 static void * 591 linux_dma_trie_alloc(struct pctrie *ptree) 592 { 593 594 return (uma_zalloc(linux_dma_trie_zone, M_NOWAIT)); 595 } 596 597 static void 598 linux_dma_trie_free(struct pctrie *ptree, void *node) 599 { 600 601 uma_zfree(linux_dma_trie_zone, node); 602 } 603 604 PCTRIE_DEFINE(LINUX_DMA, linux_dma_obj, dma_addr, linux_dma_trie_alloc, 605 linux_dma_trie_free); 606 607 void * 608 linux_dma_alloc_coherent(struct device *dev, size_t size, 609 dma_addr_t *dma_handle, gfp_t flag) 610 { 611 struct linux_dma_priv *priv; 612 vm_paddr_t high; 613 size_t align; 614 void *mem; 615 616 if (dev == NULL || dev->dma_priv == NULL) { 617 *dma_handle = 0; 618 return (NULL); 619 } 620 priv = dev->dma_priv; 621 if (priv->dma_mask) 622 high = priv->dma_mask; 623 else if (flag & GFP_DMA32) 624 high = BUS_SPACE_MAXADDR_32BIT; 625 else 626 high = BUS_SPACE_MAXADDR; 627 align = PAGE_SIZE << get_order(size); 628 mem = (void *)kmem_alloc_contig(size, flag, 0, high, align, 0, 629 VM_MEMATTR_DEFAULT); 630 if (mem != NULL) { 631 *dma_handle = linux_dma_map_phys(dev, vtophys(mem), size); 632 if (*dma_handle == 0) { 633 kmem_free((vm_offset_t)mem, size); 634 mem = NULL; 635 } 636 } else { 637 *dma_handle = 0; 638 } 639 return (mem); 640 } 641 642 #if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) 643 dma_addr_t 644 linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len) 645 { 646 struct linux_dma_priv *priv; 647 struct linux_dma_obj *obj; 648 int error, nseg; 649 bus_dma_segment_t seg; 650 651 priv = dev->dma_priv; 652 653 /* 654 * If the resultant mapping will be entirely 1:1 with the 655 * physical address, short-circuit the remainder of the 656 * bus_dma API. This avoids tracking collisions in the pctrie 657 * with the additional benefit of reducing overhead. 658 */ 659 if (bus_dma_id_mapped(priv->dmat, phys, len)) 660 return (phys); 661 662 obj = uma_zalloc(linux_dma_obj_zone, M_NOWAIT); 663 if (obj == NULL) { 664 return (0); 665 } 666 667 DMA_PRIV_LOCK(priv); 668 if (bus_dmamap_create(priv->dmat, 0, &obj->dmamap) != 0) { 669 DMA_PRIV_UNLOCK(priv); 670 uma_zfree(linux_dma_obj_zone, obj); 671 return (0); 672 } 673 674 nseg = -1; 675 if (_bus_dmamap_load_phys(priv->dmat, obj->dmamap, phys, len, 676 BUS_DMA_NOWAIT, &seg, &nseg) != 0) { 677 bus_dmamap_destroy(priv->dmat, obj->dmamap); 678 DMA_PRIV_UNLOCK(priv); 679 uma_zfree(linux_dma_obj_zone, obj); 680 return (0); 681 } 682 683 KASSERT(++nseg == 1, ("More than one segment (nseg=%d)", nseg)); 684 obj->dma_addr = seg.ds_addr; 685 686 error = LINUX_DMA_PCTRIE_INSERT(&priv->ptree, obj); 687 if (error != 0) { 688 bus_dmamap_unload(priv->dmat, obj->dmamap); 689 bus_dmamap_destroy(priv->dmat, obj->dmamap); 690 DMA_PRIV_UNLOCK(priv); 691 uma_zfree(linux_dma_obj_zone, obj); 692 return (0); 693 } 694 DMA_PRIV_UNLOCK(priv); 695 return (obj->dma_addr); 696 } 697 #else 698 dma_addr_t 699 linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len) 700 { 701 return (phys); 702 } 703 #endif 704 705 #if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) 706 void 707 linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len) 708 { 709 struct linux_dma_priv *priv; 710 struct linux_dma_obj *obj; 711 712 priv = dev->dma_priv; 713 714 if (pctrie_is_empty(&priv->ptree)) 715 return; 716 717 DMA_PRIV_LOCK(priv); 718 obj = LINUX_DMA_PCTRIE_LOOKUP(&priv->ptree, dma_addr); 719 if (obj == NULL) { 720 DMA_PRIV_UNLOCK(priv); 721 return; 722 } 723 LINUX_DMA_PCTRIE_REMOVE(&priv->ptree, dma_addr); 724 bus_dmamap_unload(priv->dmat, obj->dmamap); 725 bus_dmamap_destroy(priv->dmat, obj->dmamap); 726 DMA_PRIV_UNLOCK(priv); 727 728 uma_zfree(linux_dma_obj_zone, obj); 729 } 730 #else 731 void 732 linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t len) 733 { 734 } 735 #endif 736 737 int 738 linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents, 739 enum dma_data_direction dir, struct dma_attrs *attrs) 740 { 741 struct linux_dma_priv *priv; 742 struct scatterlist *sg; 743 int i, nseg; 744 bus_dma_segment_t seg; 745 746 priv = dev->dma_priv; 747 748 DMA_PRIV_LOCK(priv); 749 750 /* create common DMA map in the first S/G entry */ 751 if (bus_dmamap_create(priv->dmat, 0, &sgl->dma_map) != 0) { 752 DMA_PRIV_UNLOCK(priv); 753 return (0); 754 } 755 756 /* load all S/G list entries */ 757 for_each_sg(sgl, sg, nents, i) { 758 nseg = -1; 759 if (_bus_dmamap_load_phys(priv->dmat, sgl->dma_map, 760 sg_phys(sg), sg->length, BUS_DMA_NOWAIT, 761 &seg, &nseg) != 0) { 762 bus_dmamap_unload(priv->dmat, sgl->dma_map); 763 bus_dmamap_destroy(priv->dmat, sgl->dma_map); 764 DMA_PRIV_UNLOCK(priv); 765 return (0); 766 } 767 KASSERT(nseg == 0, 768 ("More than one segment (nseg=%d)", nseg + 1)); 769 770 sg_dma_address(sg) = seg.ds_addr; 771 } 772 DMA_PRIV_UNLOCK(priv); 773 774 return (nents); 775 } 776 777 void 778 linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, 779 int nents, enum dma_data_direction dir, struct dma_attrs *attrs) 780 { 781 struct linux_dma_priv *priv; 782 783 priv = dev->dma_priv; 784 785 DMA_PRIV_LOCK(priv); 786 bus_dmamap_unload(priv->dmat, sgl->dma_map); 787 bus_dmamap_destroy(priv->dmat, sgl->dma_map); 788 DMA_PRIV_UNLOCK(priv); 789 } 790 791 struct dma_pool { 792 struct device *pool_device; 793 uma_zone_t pool_zone; 794 struct mtx pool_lock; 795 bus_dma_tag_t pool_dmat; 796 size_t pool_entry_size; 797 struct pctrie pool_ptree; 798 }; 799 800 #define DMA_POOL_LOCK(pool) mtx_lock(&(pool)->pool_lock) 801 #define DMA_POOL_UNLOCK(pool) mtx_unlock(&(pool)->pool_lock) 802 803 static inline int 804 dma_pool_obj_ctor(void *mem, int size, void *arg, int flags) 805 { 806 struct linux_dma_obj *obj = mem; 807 struct dma_pool *pool = arg; 808 int error, nseg; 809 bus_dma_segment_t seg; 810 811 nseg = -1; 812 DMA_POOL_LOCK(pool); 813 error = _bus_dmamap_load_phys(pool->pool_dmat, obj->dmamap, 814 vtophys(obj->vaddr), pool->pool_entry_size, BUS_DMA_NOWAIT, 815 &seg, &nseg); 816 DMA_POOL_UNLOCK(pool); 817 if (error != 0) { 818 return (error); 819 } 820 KASSERT(++nseg == 1, ("More than one segment (nseg=%d)", nseg)); 821 obj->dma_addr = seg.ds_addr; 822 823 return (0); 824 } 825 826 static void 827 dma_pool_obj_dtor(void *mem, int size, void *arg) 828 { 829 struct linux_dma_obj *obj = mem; 830 struct dma_pool *pool = arg; 831 832 DMA_POOL_LOCK(pool); 833 bus_dmamap_unload(pool->pool_dmat, obj->dmamap); 834 DMA_POOL_UNLOCK(pool); 835 } 836 837 static int 838 dma_pool_obj_import(void *arg, void **store, int count, int domain __unused, 839 int flags) 840 { 841 struct dma_pool *pool = arg; 842 struct linux_dma_priv *priv; 843 struct linux_dma_obj *obj; 844 int error, i; 845 846 priv = pool->pool_device->dma_priv; 847 for (i = 0; i < count; i++) { 848 obj = uma_zalloc(linux_dma_obj_zone, flags); 849 if (obj == NULL) 850 break; 851 852 error = bus_dmamem_alloc(pool->pool_dmat, &obj->vaddr, 853 BUS_DMA_NOWAIT, &obj->dmamap); 854 if (error!= 0) { 855 uma_zfree(linux_dma_obj_zone, obj); 856 break; 857 } 858 859 store[i] = obj; 860 } 861 862 return (i); 863 } 864 865 static void 866 dma_pool_obj_release(void *arg, void **store, int count) 867 { 868 struct dma_pool *pool = arg; 869 struct linux_dma_priv *priv; 870 struct linux_dma_obj *obj; 871 int i; 872 873 priv = pool->pool_device->dma_priv; 874 for (i = 0; i < count; i++) { 875 obj = store[i]; 876 bus_dmamem_free(pool->pool_dmat, obj->vaddr, obj->dmamap); 877 uma_zfree(linux_dma_obj_zone, obj); 878 } 879 } 880 881 struct dma_pool * 882 linux_dma_pool_create(char *name, struct device *dev, size_t size, 883 size_t align, size_t boundary) 884 { 885 struct linux_dma_priv *priv; 886 struct dma_pool *pool; 887 888 priv = dev->dma_priv; 889 890 pool = kzalloc(sizeof(*pool), GFP_KERNEL); 891 pool->pool_device = dev; 892 pool->pool_entry_size = size; 893 894 if (bus_dma_tag_create(bus_get_dma_tag(dev->bsddev), 895 align, boundary, /* alignment, boundary */ 896 priv->dma_mask, /* lowaddr */ 897 BUS_SPACE_MAXADDR, /* highaddr */ 898 NULL, NULL, /* filtfunc, filtfuncarg */ 899 size, /* maxsize */ 900 1, /* nsegments */ 901 size, /* maxsegsz */ 902 0, /* flags */ 903 NULL, NULL, /* lockfunc, lockfuncarg */ 904 &pool->pool_dmat)) { 905 kfree(pool); 906 return (NULL); 907 } 908 909 pool->pool_zone = uma_zcache_create(name, -1, dma_pool_obj_ctor, 910 dma_pool_obj_dtor, NULL, NULL, dma_pool_obj_import, 911 dma_pool_obj_release, pool, 0); 912 913 mtx_init(&pool->pool_lock, "lkpi-dma-pool", NULL, MTX_DEF); 914 pctrie_init(&pool->pool_ptree); 915 916 return (pool); 917 } 918 919 void 920 linux_dma_pool_destroy(struct dma_pool *pool) 921 { 922 923 uma_zdestroy(pool->pool_zone); 924 bus_dma_tag_destroy(pool->pool_dmat); 925 mtx_destroy(&pool->pool_lock); 926 kfree(pool); 927 } 928 929 void * 930 linux_dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags, 931 dma_addr_t *handle) 932 { 933 struct linux_dma_obj *obj; 934 935 obj = uma_zalloc_arg(pool->pool_zone, pool, mem_flags); 936 if (obj == NULL) 937 return (NULL); 938 939 DMA_POOL_LOCK(pool); 940 if (LINUX_DMA_PCTRIE_INSERT(&pool->pool_ptree, obj) != 0) { 941 DMA_POOL_UNLOCK(pool); 942 uma_zfree_arg(pool->pool_zone, obj, pool); 943 return (NULL); 944 } 945 DMA_POOL_UNLOCK(pool); 946 947 *handle = obj->dma_addr; 948 return (obj->vaddr); 949 } 950 951 void 952 linux_dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma_addr) 953 { 954 struct linux_dma_obj *obj; 955 956 DMA_POOL_LOCK(pool); 957 obj = LINUX_DMA_PCTRIE_LOOKUP(&pool->pool_ptree, dma_addr); 958 if (obj == NULL) { 959 DMA_POOL_UNLOCK(pool); 960 return; 961 } 962 LINUX_DMA_PCTRIE_REMOVE(&pool->pool_ptree, dma_addr); 963 DMA_POOL_UNLOCK(pool); 964 965 uma_zfree_arg(pool->pool_zone, obj, pool); 966 } 967 968 static int 969 linux_backlight_get_status(device_t dev, struct backlight_props *props) 970 { 971 struct pci_dev *pdev; 972 973 linux_set_current(curthread); 974 pdev = device_get_softc(dev); 975 976 props->brightness = pdev->dev.bd->props.brightness; 977 props->brightness = props->brightness * 100 / pdev->dev.bd->props.max_brightness; 978 props->nlevels = 0; 979 980 return (0); 981 } 982 983 static int 984 linux_backlight_get_info(device_t dev, struct backlight_info *info) 985 { 986 struct pci_dev *pdev; 987 988 linux_set_current(curthread); 989 pdev = device_get_softc(dev); 990 991 info->type = BACKLIGHT_TYPE_PANEL; 992 strlcpy(info->name, pdev->dev.bd->name, BACKLIGHTMAXNAMELENGTH); 993 return (0); 994 } 995 996 static int 997 linux_backlight_update_status(device_t dev, struct backlight_props *props) 998 { 999 struct pci_dev *pdev; 1000 1001 linux_set_current(curthread); 1002 pdev = device_get_softc(dev); 1003 1004 pdev->dev.bd->props.brightness = pdev->dev.bd->props.max_brightness * 1005 props->brightness / 100; 1006 return (pdev->dev.bd->ops->update_status(pdev->dev.bd)); 1007 } 1008 1009 struct backlight_device * 1010 linux_backlight_device_register(const char *name, struct device *dev, 1011 void *data, const struct backlight_ops *ops, struct backlight_properties *props) 1012 { 1013 1014 dev->bd = malloc(sizeof(*dev->bd), M_DEVBUF, M_WAITOK | M_ZERO); 1015 dev->bd->ops = ops; 1016 dev->bd->props.type = props->type; 1017 dev->bd->props.max_brightness = props->max_brightness; 1018 dev->bd->props.brightness = props->brightness; 1019 dev->bd->props.power = props->power; 1020 dev->bd->data = data; 1021 dev->bd->dev = dev; 1022 dev->bd->name = strdup(name, M_DEVBUF); 1023 1024 dev->backlight_dev = backlight_register(name, dev->bsddev); 1025 1026 return (dev->bd); 1027 } 1028 1029 void 1030 linux_backlight_device_unregister(struct backlight_device *bd) 1031 { 1032 1033 backlight_destroy(bd->dev->backlight_dev); 1034 free(bd->name, M_DEVBUF); 1035 free(bd, M_DEVBUF); 1036 } 1037