LCOV - code coverage report
Current view: top level - dev/pci/drm - drm_linux.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 470 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 81 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: drm_linux.c,v 1.32 2018/09/11 20:25:58 kettenis Exp $ */
       2             : /*
       3             :  * Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
       4             :  * Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <dev/pci/drm/drmP.h>
      20             : #include <dev/pci/ppbreg.h>
      21             : #include <sys/event.h>
      22             : #include <sys/file.h>
      23             : #include <sys/filedesc.h>
      24             : #include <sys/stat.h>
      25             : #include <sys/unistd.h>
      26             : 
      27             : struct mutex sch_mtx = MUTEX_INITIALIZER(IPL_SCHED);
      28             : void *sch_ident;
      29             : int sch_priority;
      30             : 
      31             : void
      32           0 : flush_barrier(void *arg)
      33             : {
      34           0 :         int *barrier = arg;
      35             : 
      36           0 :         *barrier = 1;
      37           0 :         wakeup(barrier);
      38           0 : }
      39             : 
      40             : void
      41           0 : flush_workqueue(struct workqueue_struct *wq)
      42             : {
      43           0 :         struct sleep_state sls;
      44           0 :         struct task task;
      45           0 :         int barrier = 0;
      46             : 
      47           0 :         if (cold)
      48           0 :                 return;
      49             : 
      50           0 :         task_set(&task, flush_barrier, &barrier);
      51           0 :         task_add((struct taskq *)wq, &task);
      52           0 :         while (!barrier) {
      53           0 :                 sleep_setup(&sls, &barrier, PWAIT, "flwqbar");
      54           0 :                 sleep_finish(&sls, !barrier);
      55             :         }
      56           0 : }
      57             : 
      58             : void
      59           0 : flush_work(struct work_struct *work)
      60             : {
      61           0 :         struct sleep_state sls;
      62           0 :         struct task task;
      63           0 :         int barrier = 0;
      64             : 
      65           0 :         if (cold)
      66           0 :                 return;
      67             : 
      68           0 :         task_set(&task, flush_barrier, &barrier);
      69           0 :         task_add(work->tq, &task);
      70           0 :         while (!barrier) {
      71           0 :                 sleep_setup(&sls, &barrier, PWAIT, "flwkbar");
      72           0 :                 sleep_finish(&sls, !barrier);
      73             :         }
      74           0 : }
      75             : 
      76             : void
      77           0 : flush_delayed_work(struct delayed_work *dwork)
      78             : {
      79           0 :         struct sleep_state sls;
      80           0 :         struct task task;
      81           0 :         int barrier = 0;
      82             : 
      83           0 :         if (cold)
      84           0 :                 return;
      85             : 
      86           0 :         while (timeout_pending(&dwork->to))
      87           0 :                 tsleep(&barrier, PWAIT, "fldwto", 1);
      88             : 
      89           0 :         task_set(&task, flush_barrier, &barrier);
      90           0 :         task_add(dwork->tq ? dwork->tq : systq, &task);
      91           0 :         while (!barrier) {
      92           0 :                 sleep_setup(&sls, &barrier, PWAIT, "fldwbar");
      93           0 :                 sleep_finish(&sls, !barrier);
      94             :         }
      95           0 : }
      96             : 
      97             : struct timespec
      98           0 : ns_to_timespec(const int64_t nsec)
      99             : {
     100             :         struct timespec ts;
     101             :         int32_t rem;
     102             : 
     103           0 :         if (nsec == 0) {
     104             :                 ts.tv_sec = 0;
     105             :                 ts.tv_nsec = 0;
     106           0 :                 return (ts);
     107             :         }
     108             : 
     109           0 :         ts.tv_sec = nsec / NSEC_PER_SEC;
     110           0 :         rem = nsec % NSEC_PER_SEC;
     111           0 :         if (rem < 0) {
     112           0 :                 ts.tv_sec--;
     113           0 :                 rem += NSEC_PER_SEC;
     114           0 :         }
     115           0 :         ts.tv_nsec = rem;
     116           0 :         return (ts);
     117           0 : }
     118             : 
     119             : int64_t
     120           0 : timeval_to_ns(const struct timeval *tv)
     121             : {
     122           0 :         return ((int64_t)tv->tv_sec * NSEC_PER_SEC) +
     123           0 :                 tv->tv_usec * NSEC_PER_USEC;
     124             : }
     125             : 
     126             : struct timeval
     127           0 : ns_to_timeval(const int64_t nsec)
     128             : {
     129             :         struct timeval tv;
     130             :         int32_t rem;
     131             : 
     132           0 :         if (nsec == 0) {
     133             :                 tv.tv_sec = 0;
     134             :                 tv.tv_usec = 0;
     135           0 :                 return (tv);
     136             :         }
     137             : 
     138           0 :         tv.tv_sec = nsec / NSEC_PER_SEC;
     139           0 :         rem = nsec % NSEC_PER_SEC;
     140           0 :         if (rem < 0) {
     141           0 :                 tv.tv_sec--;
     142           0 :                 rem += NSEC_PER_SEC;
     143           0 :         }
     144           0 :         tv.tv_usec = rem / 1000;
     145           0 :         return (tv);
     146           0 : }
     147             : 
     148             : int64_t
     149           0 : timeval_to_us(const struct timeval *tv)
     150             : {
     151           0 :         return ((int64_t)tv->tv_sec * 1000000) + tv->tv_usec;
     152             : }
     153             : 
     154             : extern char *hw_vendor, *hw_prod, *hw_ver;
     155             : 
     156             : bool
     157           0 : dmi_match(int slot, const char *str)
     158             : {
     159           0 :         switch (slot) {
     160             :         case DMI_SYS_VENDOR:
     161             :         case DMI_BOARD_VENDOR:
     162           0 :                 if (hw_vendor != NULL &&
     163           0 :                     !strcmp(hw_vendor, str))
     164           0 :                         return true;
     165             :                 break;
     166             :         case DMI_PRODUCT_NAME:
     167             :         case DMI_BOARD_NAME:
     168           0 :                 if (hw_prod != NULL &&
     169           0 :                     !strcmp(hw_prod, str))
     170           0 :                         return true;
     171             :                 break;
     172             :         case DMI_PRODUCT_VERSION:
     173             :         case DMI_BOARD_VERSION:
     174           0 :                 if (hw_ver != NULL &&
     175           0 :                     !strcmp(hw_ver, str))
     176           0 :                         return true;
     177             :                 break;
     178             :         case DMI_NONE:
     179             :         default:
     180           0 :                 return false;
     181             :         }
     182             : 
     183           0 :         return false;
     184           0 : }
     185             : 
     186             : static bool
     187           0 : dmi_found(const struct dmi_system_id *dsi)
     188             : {
     189             :         int i, slot;
     190             : 
     191           0 :         for (i = 0; i < nitems(dsi->matches); i++) {
     192           0 :                 slot = dsi->matches[i].slot;
     193           0 :                 if (slot == DMI_NONE)
     194             :                         break;
     195           0 :                 if (!dmi_match(slot, dsi->matches[i].substr))
     196           0 :                         return false;
     197             :         }
     198             : 
     199           0 :         return true;
     200           0 : }
     201             : 
     202             : int
     203           0 : dmi_check_system(const struct dmi_system_id *sysid)
     204             : {
     205             :         const struct dmi_system_id *dsi;
     206             :         int num = 0;
     207             : 
     208           0 :         for (dsi = sysid; dsi->matches[0].slot != 0 ; dsi++) {
     209           0 :                 if (dmi_found(dsi)) {
     210           0 :                         num++;
     211           0 :                         if (dsi->callback && dsi->callback(dsi))
     212             :                                 break;
     213             :                 }
     214             :         }
     215           0 :         return (num);
     216             : }
     217             : 
     218             : struct vm_page *
     219           0 : alloc_pages(unsigned int gfp_mask, unsigned int order)
     220             : {
     221           0 :         int flags = (gfp_mask & M_NOWAIT) ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK;
     222           0 :         struct pglist mlist;
     223             : 
     224           0 :         if (gfp_mask & M_CANFAIL)
     225           0 :                 flags |= UVM_PLA_FAILOK;
     226           0 :         if (gfp_mask & M_ZERO)
     227           0 :                 flags |= UVM_PLA_ZERO;
     228             : 
     229           0 :         TAILQ_INIT(&mlist);
     230           0 :         if (uvm_pglistalloc(PAGE_SIZE << order, dma_constraint.ucr_low,
     231           0 :             dma_constraint.ucr_high, PAGE_SIZE, 0, &mlist, 1, flags))
     232           0 :                 return NULL;
     233           0 :         return TAILQ_FIRST(&mlist);
     234           0 : }
     235             : 
     236             : void
     237           0 : __free_pages(struct vm_page *page, unsigned int order)
     238             : {
     239           0 :         struct pglist mlist;
     240             :         int i;
     241             :         
     242           0 :         TAILQ_INIT(&mlist);
     243           0 :         for (i = 0; i < (1 << order); i++)
     244           0 :                 TAILQ_INSERT_TAIL(&mlist, &page[i], pageq);
     245           0 :         uvm_pglistfree(&mlist);
     246           0 : }
     247             : 
     248             : void *
     249           0 : kmap(struct vm_page *pg)
     250             : {
     251             :         vaddr_t va;
     252             : 
     253             : #if defined (__HAVE_PMAP_DIRECT)
     254           0 :         va = pmap_map_direct(pg);
     255             : #else
     256             :         va = uvm_km_valloc_wait(phys_map, PAGE_SIZE);
     257             :         pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), PROT_READ | PROT_WRITE);
     258             :         pmap_update(pmap_kernel());
     259             : #endif
     260           0 :         return (void *)va;
     261             : }
     262             : 
     263             : void
     264           0 : kunmap(void *addr)
     265             : {
     266           0 :         vaddr_t va = (vaddr_t)addr;
     267             : 
     268             : #if defined (__HAVE_PMAP_DIRECT)
     269           0 :         pmap_unmap_direct(va);
     270             : #else
     271             :         pmap_kremove(va, PAGE_SIZE);
     272             :         pmap_update(pmap_kernel());
     273             :         uvm_km_free_wakeup(phys_map, va, PAGE_SIZE);
     274             : #endif
     275           0 : }
     276             : 
     277             : void *
     278           0 : vmap(struct vm_page **pages, unsigned int npages, unsigned long flags,
     279             :      pgprot_t prot)
     280             : {
     281             :         vaddr_t va;
     282             :         paddr_t pa;
     283             :         int i;
     284             : 
     285           0 :         va = uvm_km_valloc(kernel_map, PAGE_SIZE * npages);
     286           0 :         if (va == 0)
     287           0 :                 return NULL;
     288           0 :         for (i = 0; i < npages; i++) {
     289           0 :                 pa = VM_PAGE_TO_PHYS(pages[i]) | prot;
     290           0 :                 pmap_enter(pmap_kernel(), va + (i * PAGE_SIZE), pa,
     291             :                     PROT_READ | PROT_WRITE,
     292             :                     PROT_READ | PROT_WRITE | PMAP_WIRED);
     293             :                 pmap_update(pmap_kernel());
     294             :         }
     295             : 
     296           0 :         return (void *)va;
     297           0 : }
     298             : 
     299             : void
     300           0 : vunmap(void *addr, size_t size)
     301             : {
     302           0 :         vaddr_t va = (vaddr_t)addr;
     303             : 
     304           0 :         pmap_remove(pmap_kernel(), va, va + size);
     305             :         pmap_update(pmap_kernel());
     306           0 :         uvm_km_free(kernel_map, va, size);
     307           0 : }
     308             : 
     309             : void
     310           0 : print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
     311             :     int rowsize, int groupsize, const void *buf, size_t len, bool ascii)
     312             : {
     313             :         const uint8_t *cbuf = buf;
     314             :         int i;
     315             : 
     316           0 :         for (i = 0; i < len; i++) {
     317           0 :                 if ((i % rowsize) == 0)
     318           0 :                         printf("%s", prefix_str);
     319           0 :                 printf("%02x", cbuf[i]);
     320           0 :                 if ((i % rowsize) == (rowsize - 1))
     321           0 :                         printf("\n");
     322             :                 else
     323           0 :                         printf(" ");
     324             :         }
     325           0 : }
     326             : 
     327             : void *
     328           0 : memchr_inv(const void *s, int c, size_t n)
     329             : {
     330           0 :         if (n != 0) {
     331             :                 const unsigned char *p = s;
     332             : 
     333           0 :                 do {
     334           0 :                         if (*p++ != (unsigned char)c)
     335           0 :                                 return ((void *)(p - 1));
     336           0 :                 }while (--n != 0);
     337           0 :         }
     338           0 :         return (NULL);
     339           0 : }
     340             : 
     341             : int
     342           0 : panic_cmp(struct rb_node *a, struct rb_node *b)
     343             : {
     344           0 :         panic(__func__);
     345             : }
     346             : 
     347             : #undef RB_ROOT
     348             : #define RB_ROOT(head)   (head)->rbh_root
     349             : 
     350           0 : RB_GENERATE(linux_root, rb_node, __entry, panic_cmp);
     351             : 
     352             : /*
     353             :  * This is a fairly minimal implementation of the Linux "idr" API.  It
     354             :  * probably isn't very efficient, and defenitely isn't RCU safe.  The
     355             :  * pre-load buffer is global instead of per-cpu; we rely on the kernel
     356             :  * lock to make this work.  We do randomize our IDs in order to make
     357             :  * them harder to guess.
     358             :  */
     359             : 
     360             : int idr_cmp(struct idr_entry *, struct idr_entry *);
     361           0 : SPLAY_PROTOTYPE(idr_tree, idr_entry, entry, idr_cmp);
     362             : 
     363             : struct pool idr_pool;
     364             : struct idr_entry *idr_entry_cache;
     365             : 
     366             : void
     367           0 : idr_init(struct idr *idr)
     368             : {
     369             :         static int initialized;
     370             : 
     371           0 :         if (!initialized) {
     372           0 :                 pool_init(&idr_pool, sizeof(struct idr_entry), 0, IPL_TTY, 0,
     373             :                     "idrpl", NULL);
     374           0 :                 initialized = 1;
     375           0 :         }
     376           0 :         SPLAY_INIT(&idr->tree);
     377           0 : }
     378             : 
     379             : void
     380           0 : idr_destroy(struct idr *idr)
     381             : {
     382             :         struct idr_entry *id;
     383             : 
     384           0 :         while ((id = SPLAY_MIN(idr_tree, &idr->tree))) {
     385           0 :                 SPLAY_REMOVE(idr_tree, &idr->tree, id);
     386           0 :                 pool_put(&idr_pool, id);
     387             :         }
     388           0 : }
     389             : 
     390             : void
     391           0 : idr_preload(unsigned int gfp_mask)
     392             : {
     393           0 :         int flags = (gfp_mask & GFP_NOWAIT) ? PR_NOWAIT : PR_WAITOK;
     394             : 
     395           0 :         KERNEL_ASSERT_LOCKED();
     396             : 
     397           0 :         if (idr_entry_cache == NULL)
     398           0 :                 idr_entry_cache = pool_get(&idr_pool, flags);
     399           0 : }
     400             : 
     401             : int
     402           0 : idr_alloc(struct idr *idr, void *ptr, int start, int end,
     403             :     unsigned int gfp_mask)
     404             : {
     405           0 :         int flags = (gfp_mask & GFP_NOWAIT) ? PR_NOWAIT : PR_WAITOK;
     406             :         struct idr_entry *id;
     407             :         int begin;
     408             : 
     409           0 :         KERNEL_ASSERT_LOCKED();
     410             : 
     411           0 :         if (idr_entry_cache) {
     412             :                 id = idr_entry_cache;
     413           0 :                 idr_entry_cache = NULL;
     414           0 :         } else {
     415           0 :                 id = pool_get(&idr_pool, flags);
     416           0 :                 if (id == NULL)
     417           0 :                         return -ENOMEM;
     418             :         }
     419             : 
     420           0 :         if (end <= 0)
     421           0 :                 end = INT_MAX;
     422             : 
     423             : #ifdef notyet
     424             :         id->id = begin = start + arc4random_uniform(end - start);
     425             : #else
     426           0 :         id->id = begin = start;
     427             : #endif
     428           0 :         while (SPLAY_INSERT(idr_tree, &idr->tree, id)) {
     429           0 :                 if (++id->id == end)
     430           0 :                         id->id = start;
     431           0 :                 if (id->id == begin) {
     432           0 :                         pool_put(&idr_pool, id);
     433           0 :                         return -ENOSPC;
     434             :                 }
     435             :         }
     436           0 :         id->ptr = ptr;
     437           0 :         return id->id;
     438           0 : }
     439             : 
     440             : void *
     441           0 : idr_replace(struct idr *idr, void *ptr, int id)
     442             : {
     443           0 :         struct idr_entry find, *res;
     444             :         void *old;
     445             : 
     446           0 :         find.id = id;
     447           0 :         res = SPLAY_FIND(idr_tree, &idr->tree, &find);
     448           0 :         if (res == NULL)
     449           0 :                 return ERR_PTR(-ENOENT);
     450           0 :         old = res->ptr;
     451           0 :         res->ptr = ptr;
     452           0 :         return old;
     453           0 : }
     454             : 
     455             : void
     456           0 : idr_remove(struct idr *idr, int id)
     457             : {
     458           0 :         struct idr_entry find, *res;
     459             : 
     460           0 :         find.id = id;
     461           0 :         res = SPLAY_FIND(idr_tree, &idr->tree, &find);
     462           0 :         if (res) {
     463           0 :                 SPLAY_REMOVE(idr_tree, &idr->tree, res);
     464           0 :                 pool_put(&idr_pool, res);
     465           0 :         }
     466           0 : }
     467             : 
     468             : void *
     469           0 : idr_find(struct idr *idr, int id)
     470             : {
     471           0 :         struct idr_entry find, *res;
     472             : 
     473           0 :         find.id = id;
     474           0 :         res = SPLAY_FIND(idr_tree, &idr->tree, &find);
     475           0 :         if (res == NULL)
     476           0 :                 return NULL;
     477           0 :         return res->ptr;
     478           0 : }
     479             : 
     480             : void *
     481           0 : idr_get_next(struct idr *idr, int *id)
     482             : {
     483             :         struct idr_entry *res;
     484             : 
     485           0 :         res = idr_find(idr, *id);
     486           0 :         if (res == NULL)
     487           0 :                 res = SPLAY_MIN(idr_tree, &idr->tree);
     488             :         else
     489           0 :                 res = SPLAY_NEXT(idr_tree, &idr->tree, res);
     490           0 :         if (res == NULL)
     491           0 :                 return NULL;
     492           0 :         *id = res->id;
     493           0 :         return res->ptr;
     494           0 : }
     495             : 
     496             : int
     497           0 : idr_for_each(struct idr *idr, int (*func)(int, void *, void *), void *data)
     498             : {
     499             :         struct idr_entry *id;
     500             :         int ret;
     501             : 
     502           0 :         SPLAY_FOREACH(id, idr_tree, &idr->tree) {
     503           0 :                 ret = func(id->id, id->ptr, data);
     504           0 :                 if (ret)
     505           0 :                         return ret;
     506             :         }
     507             : 
     508           0 :         return 0;
     509           0 : }
     510             : 
     511             : int
     512           0 : idr_cmp(struct idr_entry *a, struct idr_entry *b)
     513             : {
     514           0 :         return (a->id < b->id ? -1 : a->id > b->id);
     515             : }
     516             : 
     517           0 : SPLAY_GENERATE(idr_tree, idr_entry, entry, idr_cmp);
     518             : 
     519             : void
     520           0 : ida_init(struct ida *ida)
     521             : {
     522           0 :         ida->counter = 0;
     523           0 : }
     524             : 
     525             : void
     526           0 : ida_destroy(struct ida *ida)
     527             : {
     528           0 : }
     529             : 
     530             : void
     531           0 : ida_remove(struct ida *ida, int id)
     532             : {
     533           0 : }
     534             : 
     535             : int
     536           0 : ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
     537             :     int flags)
     538             : {
     539           0 :         if (end <= 0)
     540           0 :                 end = INT_MAX;
     541             : 
     542           0 :         if (start > ida->counter)
     543           0 :                 ida->counter = start;
     544             : 
     545           0 :         if (ida->counter >= end)
     546           0 :                 return -ENOSPC;
     547             : 
     548           0 :         return ida->counter++;
     549           0 : }
     550             : 
     551             : int
     552           0 : sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
     553             : {
     554           0 :         table->sgl = mallocarray(nents, sizeof(struct scatterlist),
     555             :             M_DRM, gfp_mask);
     556           0 :         if (table->sgl == NULL)
     557           0 :                 return -ENOMEM;
     558           0 :         table->nents = table->orig_nents = nents;
     559           0 :         return 0;
     560           0 : }
     561             : 
     562             : void
     563           0 : sg_free_table(struct sg_table *table)
     564             : {
     565           0 :         free(table->sgl, M_DRM,
     566           0 :             table->orig_nents * sizeof(struct scatterlist));
     567           0 : }
     568             : 
     569             : size_t
     570           0 : sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
     571             :     const void *buf, size_t buflen)
     572             : {
     573           0 :         panic("%s", __func__);
     574             : }
     575             : 
     576             : int
     577           0 : i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
     578             : {
     579             :         void *cmd = NULL;
     580             :         int cmdlen = 0;
     581             :         int err, ret = 0;
     582             :         int op;
     583             : 
     584           0 :         iic_acquire_bus(&adap->ic, 0);
     585             : 
     586           0 :         while (num > 2) {
     587           0 :                 op = (msgs->flags & I2C_M_RD) ? I2C_OP_READ : I2C_OP_WRITE;
     588           0 :                 err = iic_exec(&adap->ic, op, msgs->addr, NULL, 0,
     589           0 :                     msgs->buf, msgs->len, 0);
     590           0 :                 if (err) {
     591           0 :                         ret = -err;
     592           0 :                         goto fail;
     593             :                 }
     594           0 :                 msgs++;
     595           0 :                 num--;
     596           0 :                 ret++;
     597             :         }
     598             : 
     599           0 :         if (num > 1) {
     600           0 :                 cmd = msgs->buf;
     601           0 :                 cmdlen = msgs->len;
     602           0 :                 msgs++;
     603             :                 num--;
     604           0 :                 ret++;
     605           0 :         }
     606             : 
     607           0 :         op = (msgs->flags & I2C_M_RD) ?
     608             :             I2C_OP_READ_WITH_STOP : I2C_OP_WRITE_WITH_STOP;
     609           0 :         err = iic_exec(&adap->ic, op, msgs->addr, cmd, cmdlen,
     610           0 :             msgs->buf, msgs->len, 0);
     611           0 :         if (err) {
     612           0 :                 ret = -err;
     613           0 :                 goto fail;
     614             :         }
     615             :         msgs++;
     616           0 :         ret++;
     617             : 
     618             : fail:
     619           0 :         iic_release_bus(&adap->ic, 0);
     620             : 
     621           0 :         return ret;
     622             : }
     623             : 
     624             : int
     625           0 : i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
     626             : {
     627           0 :         if (adap->algo)
     628           0 :                 return adap->algo->master_xfer(adap, msgs, num);
     629             : 
     630           0 :         return i2c_master_xfer(adap, msgs, num);
     631           0 : }
     632             : 
     633             : int
     634           0 : i2c_bb_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
     635             : {
     636           0 :         struct i2c_algo_bit_data *algo = adap->algo_data;
     637           0 :         struct i2c_adapter bb;
     638             : 
     639           0 :         memset(&bb, 0, sizeof(bb));
     640           0 :         bb.ic = algo->ic;
     641           0 :         bb.retries = adap->retries;
     642           0 :         return i2c_master_xfer(&bb, msgs, num);
     643           0 : }
     644             : 
     645             : uint32_t
     646           0 : i2c_bb_functionality(struct i2c_adapter *adap)
     647             : {
     648           0 :         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
     649             : }
     650             : 
     651             : struct i2c_algorithm i2c_bit_algo = {
     652             :         .master_xfer = i2c_bb_master_xfer,
     653             :         .functionality = i2c_bb_functionality
     654             : };
     655             : 
     656             : int
     657           0 : i2c_bit_add_bus(struct i2c_adapter *adap)
     658             : {
     659           0 :         adap->algo = &i2c_bit_algo;
     660           0 :         adap->retries = 3;
     661             : 
     662           0 :         return 0;
     663             : }
     664             : 
     665             : #if defined(__amd64__) || defined(__i386__)
     666             : 
     667             : /*
     668             :  * This is a minimal implementation of the Linux vga_get/vga_put
     669             :  * interface.  In all likelyhood, it will only work for inteldrm(4) as
     670             :  * it assumes that if there is another active VGA device in the
     671             :  * system, it is sitting behind a PCI bridge.
     672             :  */
     673             : 
     674             : extern int pci_enumerate_bus(struct pci_softc *,
     675             :     int (*)(struct pci_attach_args *), struct pci_attach_args *);
     676             : 
     677             : pcitag_t vga_bridge_tag;
     678             : int vga_bridge_disabled;
     679             : 
     680             : int
     681           0 : vga_disable_bridge(struct pci_attach_args *pa)
     682             : {
     683             :         pcireg_t bhlc, bc;
     684             : 
     685           0 :         if (pa->pa_domain != 0)
     686           0 :                 return 0;
     687             : 
     688           0 :         bhlc = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
     689           0 :         if (PCI_HDRTYPE_TYPE(bhlc) != 1)
     690           0 :                 return 0;
     691             : 
     692           0 :         bc = pci_conf_read(pa->pa_pc, pa->pa_tag, PPB_REG_BRIDGECONTROL);
     693           0 :         if ((bc & PPB_BC_VGA_ENABLE) == 0)
     694           0 :                 return 0;
     695           0 :         bc &= ~PPB_BC_VGA_ENABLE;
     696           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, PPB_REG_BRIDGECONTROL, bc);
     697             : 
     698           0 :         vga_bridge_tag = pa->pa_tag;
     699           0 :         vga_bridge_disabled = 1;
     700             : 
     701           0 :         return 1;
     702           0 : }
     703             : 
     704             : void
     705           0 : vga_get_uninterruptible(struct pci_dev *pdev, int rsrc)
     706             : {
     707           0 :         KASSERT(pdev->pci->sc_bridgetag == NULL);
     708           0 :         pci_enumerate_bus(pdev->pci, vga_disable_bridge, NULL);
     709           0 : }
     710             : 
     711             : void
     712           0 : vga_put(struct pci_dev *pdev, int rsrc)
     713             : {
     714             :         pcireg_t bc;
     715             : 
     716           0 :         if (!vga_bridge_disabled)
     717           0 :                 return;
     718             : 
     719           0 :         bc = pci_conf_read(pdev->pc, vga_bridge_tag, PPB_REG_BRIDGECONTROL);
     720           0 :         bc |= PPB_BC_VGA_ENABLE;
     721           0 :         pci_conf_write(pdev->pc, vga_bridge_tag, PPB_REG_BRIDGECONTROL, bc);
     722             : 
     723           0 :         vga_bridge_disabled = 0;
     724           0 : }
     725             : 
     726             : #endif
     727             : 
     728             : /*
     729             :  * ACPI types and interfaces.
     730             :  */
     731             : 
     732             : #ifdef __HAVE_ACPI
     733             : #include "acpi.h"
     734             : #endif
     735             : 
     736             : #if NACPI > 0
     737             : 
     738             : #include <dev/acpi/acpireg.h>
     739             : #include <dev/acpi/acpivar.h>
     740             : 
     741             : acpi_status
     742           0 : acpi_get_table_with_size(const char *sig, int instance,
     743             :     struct acpi_table_header **hdr, acpi_size *size)
     744             : {
     745           0 :         struct acpi_softc *sc = acpi_softc;
     746             :         struct acpi_q *entry;
     747             : 
     748           0 :         KASSERT(instance == 1);
     749             : 
     750           0 :         if (sc == NULL)
     751           0 :                 return AE_NOT_FOUND;
     752             : 
     753           0 :         SIMPLEQ_FOREACH(entry, &sc->sc_tables, q_next) {
     754           0 :                 if (memcmp(entry->q_table, sig, strlen(sig)) == 0) {
     755           0 :                         *hdr = entry->q_table;
     756           0 :                         *size = (*hdr)->length;
     757           0 :                         return 0;
     758             :                 }
     759             :         }
     760             : 
     761           0 :         return AE_NOT_FOUND;
     762           0 : }
     763             : 
     764             : #endif
     765             : 
     766             : void
     767           0 : backlight_do_update_status(void *arg)
     768             : {
     769           0 :         backlight_update_status(arg);
     770           0 : }
     771             : 
     772             : struct backlight_device *
     773           0 : backlight_device_register(const char *name, void *kdev, void *data,
     774             :     const struct backlight_ops *ops, struct backlight_properties *props)
     775             : {
     776             :         struct backlight_device *bd;
     777             : 
     778           0 :         bd = malloc(sizeof(*bd), M_DRM, M_WAITOK);
     779           0 :         bd->ops = ops;
     780           0 :         bd->props = *props;
     781           0 :         bd->data = data;
     782             : 
     783           0 :         task_set(&bd->task, backlight_do_update_status, bd);
     784             :         
     785           0 :         return bd;
     786             : }
     787             : 
     788             : void
     789           0 : backlight_device_unregister(struct backlight_device *bd)
     790             : {
     791           0 :         free(bd, M_DRM, sizeof(*bd));
     792           0 : }
     793             : 
     794             : void
     795           0 : backlight_schedule_update_status(struct backlight_device *bd)
     796             : {
     797           0 :         task_add(systq, &bd->task);
     798           0 : }
     799             : 
     800             : void
     801           0 : drm_sysfs_hotplug_event(struct drm_device *dev)
     802             : {
     803           0 :         KNOTE(&dev->note, NOTE_CHANGE);
     804           0 : }
     805             : 
     806             : unsigned int drm_fence_count;
     807             : 
     808             : unsigned int
     809           0 : fence_context_alloc(unsigned int num)
     810             : {
     811           0 :         return __sync_add_and_fetch(&drm_fence_count, num) - num;
     812             : }
     813             : 
     814             : int
     815           0 : dmabuf_read(struct file *fp, struct uio *uio, int fflags)
     816             : {
     817           0 :         return (ENXIO);
     818             : }
     819             : 
     820             : int
     821           0 : dmabuf_write(struct file *fp, struct uio *uio, int fflags)
     822             : {
     823           0 :         return (ENXIO);
     824             : }
     825             : 
     826             : int
     827           0 : dmabuf_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
     828             : {
     829           0 :         return (ENOTTY);
     830             : }
     831             : 
     832             : int
     833           0 : dmabuf_poll(struct file *fp, int events, struct proc *p)
     834             : {
     835           0 :         return (0);
     836             : }
     837             : 
     838             : int
     839           0 : dmabuf_kqfilter(struct file *fp, struct knote *kn)
     840             : {
     841           0 :         return (EINVAL);
     842             : }
     843             : 
     844             : int
     845           0 : dmabuf_stat(struct file *fp, struct stat *st, struct proc *p)
     846             : {
     847           0 :         struct dma_buf *dmabuf = fp->f_data;
     848             : 
     849           0 :         memset(st, 0, sizeof(*st));
     850           0 :         st->st_size = dmabuf->size;
     851           0 :         st->st_mode = S_IFIFO;       /* XXX */
     852           0 :         return (0);
     853             : }
     854             : 
     855             : int
     856           0 : dmabuf_close(struct file *fp, struct proc *p)
     857             : {
     858           0 :         struct dma_buf *dmabuf = fp->f_data;
     859             : 
     860           0 :         fp->f_data = NULL;
     861           0 :         KERNEL_LOCK();
     862           0 :         dmabuf->ops->release(dmabuf);
     863           0 :         KERNEL_UNLOCK();
     864           0 :         free(dmabuf, M_DRM, sizeof(struct dma_buf));
     865           0 :         return (0);
     866             : }
     867             : 
     868             : int
     869           0 : dmabuf_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
     870             : {
     871           0 :         struct dma_buf *dmabuf = fp->f_data;
     872             :         off_t newoff;
     873             : 
     874           0 :         if (*offset != 0)
     875           0 :                 return (EINVAL);
     876             : 
     877           0 :         switch (whence) {
     878             :         case SEEK_SET:
     879             :                 newoff = 0;
     880           0 :                 break;
     881             :         case SEEK_END:
     882           0 :                 newoff = dmabuf->size;
     883           0 :                 break;
     884             :         default:
     885           0 :                 return (EINVAL);
     886             :         }
     887           0 :         fp->f_offset = *offset = newoff;
     888           0 :         return (0);
     889           0 : }
     890             : 
     891             : struct fileops dmabufops = {
     892             :         .fo_read        = dmabuf_read,
     893             :         .fo_write       = dmabuf_write,
     894             :         .fo_ioctl       = dmabuf_ioctl,
     895             :         .fo_poll        = dmabuf_poll,
     896             :         .fo_kqfilter    = dmabuf_kqfilter,
     897             :         .fo_stat        = dmabuf_stat,
     898             :         .fo_close       = dmabuf_close,
     899             :         .fo_seek        = dmabuf_seek,
     900             : };
     901             : 
     902             : struct dma_buf *
     903           0 : dma_buf_export(const struct dma_buf_export_info *info)
     904             : {
     905           0 :         struct proc *p = curproc;
     906             :         struct dma_buf *dmabuf;
     907             :         struct file *fp;
     908             : 
     909           0 :         fp = fnew(p);
     910           0 :         if (fp == NULL)
     911           0 :                 return ERR_PTR(-ENFILE);
     912           0 :         fp->f_type = DTYPE_DMABUF;
     913           0 :         fp->f_ops = &dmabufops;
     914           0 :         dmabuf = malloc(sizeof(struct dma_buf), M_DRM, M_WAITOK | M_ZERO);
     915           0 :         dmabuf->priv = info->priv;
     916           0 :         dmabuf->ops = info->ops;
     917           0 :         dmabuf->size = info->size;
     918           0 :         dmabuf->file = fp;
     919           0 :         fp->f_data = dmabuf;
     920           0 :         return dmabuf;
     921           0 : }
     922             : 
     923             : struct dma_buf *
     924           0 : dma_buf_get(int fd)
     925             : {
     926           0 :         struct proc *p = curproc;
     927           0 :         struct filedesc *fdp = p->p_fd;
     928             :         struct file *fp;
     929             : 
     930           0 :         if ((fp = fd_getfile(fdp, fd)) == NULL)
     931           0 :                 return ERR_PTR(-EBADF);
     932             : 
     933           0 :         if (fp->f_type != DTYPE_DMABUF) {
     934           0 :                 FRELE(fp, p);
     935           0 :                 return ERR_PTR(-EINVAL);
     936             :         }
     937             : 
     938           0 :         return fp->f_data;
     939           0 : }
     940             : 
     941             : void
     942           0 : dma_buf_put(struct dma_buf *dmabuf)
     943             : {
     944           0 :         KASSERT(dmabuf);
     945           0 :         KASSERT(dmabuf->file);
     946             : 
     947           0 :         FRELE(dmabuf->file, curproc);
     948           0 : }
     949             : 
     950             : int
     951           0 : dma_buf_fd(struct dma_buf *dmabuf, int flags)
     952             : {
     953           0 :         struct proc *p = curproc;
     954           0 :         struct filedesc *fdp = p->p_fd;
     955           0 :         struct file *fp = dmabuf->file;
     956           0 :         int fd, cloexec, error;
     957             : 
     958           0 :         cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
     959             : 
     960           0 :         fdplock(fdp);
     961             : restart:
     962           0 :         if ((error = fdalloc(p, 0, &fd)) != 0) {
     963           0 :                 if (error == ENOSPC) {
     964           0 :                         fdexpand(p);
     965           0 :                         goto restart;
     966             :                 }
     967           0 :                 fdpunlock(fdp);
     968           0 :                 return -error;
     969             :         }
     970             : 
     971           0 :         fdinsert(fdp, fd, cloexec, fp);
     972           0 :         fdpunlock(fdp);
     973             : 
     974           0 :         return fd;
     975           0 : }
     976             : 
     977             : void
     978           0 : get_dma_buf(struct dma_buf *dmabuf)
     979             : {
     980           0 :         FREF(dmabuf->file);
     981           0 : }

Generated by: LCOV version 1.13