The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm2/drm_sysctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 2003 Eric Anholt
    3  * All Rights Reserved.
    4  *
    5  * Permission is hereby granted, free of charge, to any person obtaining a
    6  * copy of this software and associated documentation files (the "Software"),
    7  * to deal in the Software without restriction, including without limitation
    8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    9  * and/or sell copies of the Software, and to permit persons to whom the
   10  * Software is furnished to do so, subject to the following conditions:
   11  *
   12  * The above copyright notice and this permission notice (including the next
   13  * paragraph) shall be included in all copies or substantial portions of the
   14  * Software.
   15  *
   16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   19  * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   22  */
   23 
   24 #include <sys/cdefs.h>
   25 __FBSDID("$FreeBSD$");
   26 
   27 /** @file drm_sysctl.c
   28  * Implementation of various sysctls for controlling DRM behavior and reporting
   29  * debug information.
   30  */
   31 
   32 #include <dev/drm2/drmP.h>
   33 #include <dev/drm2/drm.h>
   34 
   35 #include <sys/sysctl.h>
   36 
   37 static int         drm_name_info DRM_SYSCTL_HANDLER_ARGS;
   38 static int         drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
   39 static int         drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
   40 static int         drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
   41 static int         drm_vblank_info DRM_SYSCTL_HANDLER_ARGS;
   42 
   43 struct drm_sysctl_list {
   44         const char *name;
   45         int        (*f) DRM_SYSCTL_HANDLER_ARGS;
   46 } drm_sysctl_list[] = {
   47         {"name",    drm_name_info},
   48         {"vm",      drm_vm_info},
   49         {"clients", drm_clients_info},
   50         {"bufs",    drm_bufs_info},
   51         {"vblank",    drm_vblank_info},
   52 };
   53 #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
   54 
   55 struct drm_sysctl_info {
   56         struct sysctl_ctx_list ctx;
   57         char                   name[2];
   58 };
   59 
   60 int drm_sysctl_init(struct drm_device *dev)
   61 {
   62         struct drm_sysctl_info *info;
   63         struct sysctl_oid *oid;
   64         struct sysctl_oid *top, *drioid;
   65         int               i;
   66 
   67         info = malloc(sizeof *info, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
   68         dev->sysctl = info;
   69 
   70         /* Add the sysctl node for DRI if it doesn't already exist */
   71         drioid = SYSCTL_ADD_NODE(&info->ctx, SYSCTL_CHILDREN(&sysctl___hw), OID_AUTO,
   72             "dri", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "DRI Graphics");
   73         if (!drioid) {
   74                 free(dev->sysctl, DRM_MEM_DRIVER);
   75                 dev->sysctl = NULL;
   76                 return (-ENOMEM);
   77         }
   78 
   79         /* Find the next free slot under hw.dri */
   80         i = 0;
   81         SYSCTL_FOREACH(oid, SYSCTL_CHILDREN(drioid)) {
   82                 if (i <= oid->oid_arg2)
   83                         i = oid->oid_arg2 + 1;
   84         }
   85         if (i > 9) {
   86                 drm_sysctl_cleanup(dev);
   87                 return (-ENOSPC);
   88         }
   89 
   90         dev->sysctl_node_idx = i;
   91         /* Add the hw.dri.x for our device */
   92         info->name[0] = '' + i;
   93         info->name[1] = 0;
   94         top = SYSCTL_ADD_NODE(&info->ctx, SYSCTL_CHILDREN(drioid),
   95             OID_AUTO, info->name, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, NULL);
   96         if (!top) {
   97                 drm_sysctl_cleanup(dev);
   98                 return (-ENOMEM);
   99         }
  100 
  101         for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
  102                 oid = SYSCTL_ADD_OID(&info->ctx, SYSCTL_CHILDREN(top),
  103                         OID_AUTO, drm_sysctl_list[i].name,
  104                         CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
  105                         dev, 0, drm_sysctl_list[i].f, "A", NULL);
  106                 if (!oid) {
  107                         drm_sysctl_cleanup(dev);
  108                         return (-ENOMEM);
  109                 }
  110         }
  111         SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "debug",
  112             CTLFLAG_RW, &drm_debug, sizeof(drm_debug),
  113             "Enable debugging output");
  114         SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "notyet",
  115             CTLFLAG_RW, &drm_notyet, sizeof(drm_debug),
  116             "Enable notyet reminders");
  117 
  118         if (dev->driver->sysctl_init != NULL)
  119                 dev->driver->sysctl_init(dev, &info->ctx, top);
  120 
  121         SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO,
  122             "vblank_offdelay", CTLFLAG_RW, &drm_vblank_offdelay,
  123             sizeof(drm_vblank_offdelay),
  124             "");
  125         SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO,
  126             "timestamp_precision", CTLFLAG_RW, &drm_timestamp_precision,
  127             sizeof(drm_timestamp_precision),
  128             "");
  129 
  130         return (0);
  131 }
  132 
  133 int drm_sysctl_cleanup(struct drm_device *dev)
  134 {
  135         int error;
  136 
  137         if (dev->sysctl == NULL)
  138                 return (0);
  139 
  140         error = sysctl_ctx_free(&dev->sysctl->ctx);
  141         free(dev->sysctl, DRM_MEM_DRIVER);
  142         dev->sysctl = NULL;
  143         if (dev->driver->sysctl_cleanup != NULL)
  144                 dev->driver->sysctl_cleanup(dev);
  145 
  146         return (-error);
  147 }
  148 
  149 #define DRM_SYSCTL_PRINT(fmt, arg...)                           \
  150 do {                                                            \
  151         snprintf(buf, sizeof(buf), fmt, ##arg);                 \
  152         retcode = SYSCTL_OUT(req, buf, strlen(buf));            \
  153         if (retcode)                                            \
  154                 goto done;                                      \
  155 } while (0)
  156 
  157 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
  158 {
  159         struct drm_device *dev = arg1;
  160         struct drm_minor *minor;
  161         struct drm_master *master;
  162         char buf[128];
  163         int retcode;
  164         int hasunique = 0;
  165 
  166         /* FIXME: This still uses primary minor. */
  167         minor = dev->primary;
  168         DRM_SYSCTL_PRINT("%s 0x%jx", dev->driver->name,
  169             (uintmax_t)dev2udev(minor->device));
  170 
  171         DRM_LOCK(dev);
  172         master = minor->master;
  173         if (master != NULL && master->unique) {
  174                 snprintf(buf, sizeof(buf), " %s", master->unique);
  175                 hasunique = 1;
  176         }
  177         DRM_UNLOCK(dev);
  178 
  179         if (hasunique)
  180                 SYSCTL_OUT(req, buf, strlen(buf));
  181 
  182         SYSCTL_OUT(req, "", 1);
  183 
  184 done:
  185         return retcode;
  186 }
  187 
  188 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
  189 {
  190         struct drm_device *dev = arg1;
  191         struct drm_map_list *entry;
  192         struct drm_local_map *map, *tempmaps;
  193         const char *types[] = {
  194                 [_DRM_FRAME_BUFFER] = "FB",
  195                 [_DRM_REGISTERS] = "REG",
  196                 [_DRM_SHM] = "SHM",
  197                 [_DRM_AGP] = "AGP",
  198                 [_DRM_SCATTER_GATHER] = "SG",
  199                 [_DRM_CONSISTENT] = "CONS",
  200                 [_DRM_GEM] = "GEM"
  201         };
  202         const char *type, *yesno;
  203         int i, mapcount;
  204         char buf[128];
  205         int retcode;
  206 
  207         /* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
  208          * temporary copy of all the map entries and then SYSCTL_OUT that.
  209          */
  210         DRM_LOCK(dev);
  211 
  212         mapcount = 0;
  213         list_for_each_entry(entry, &dev->maplist, head) {
  214                 if (entry->map != NULL)
  215                         mapcount++;
  216         }
  217 
  218         tempmaps = malloc(sizeof(*tempmaps) * mapcount, DRM_MEM_DRIVER,
  219             M_NOWAIT);
  220         if (tempmaps == NULL) {
  221                 DRM_UNLOCK(dev);
  222                 return ENOMEM;
  223         }
  224 
  225         i = 0;
  226         list_for_each_entry(entry, &dev->maplist, head) {
  227                 if (entry->map != NULL)
  228                         tempmaps[i++] = *entry->map;
  229         }
  230 
  231         DRM_UNLOCK(dev);
  232 
  233         DRM_SYSCTL_PRINT("\nslot offset         size       "
  234             "type flags address            mtrr\n");
  235 
  236         for (i = 0; i < mapcount; i++) {
  237                 map = &tempmaps[i];
  238 
  239                 switch(map->type) {
  240                 default:
  241                         type = "??";
  242                         break;
  243                 case _DRM_FRAME_BUFFER:
  244                 case _DRM_REGISTERS:
  245                 case _DRM_SHM:
  246                 case _DRM_AGP:
  247                 case _DRM_SCATTER_GATHER:
  248                 case _DRM_CONSISTENT:
  249                 case _DRM_GEM:
  250                         type = types[map->type];
  251                         break;
  252                 }
  253 
  254                 if (map->mtrr < 0)
  255                         yesno = "no";
  256                 else
  257                         yesno = "yes";
  258 
  259                 DRM_SYSCTL_PRINT(
  260                     "%4d 0x%016llx 0x%08lx %4.4s  0x%02x 0x%016lx %s\n",
  261                     i, (unsigned long long)map->offset, map->size, type,
  262                     map->flags, (unsigned long)map->handle, yesno);
  263         }
  264         SYSCTL_OUT(req, "", 1);
  265 
  266 done:
  267         free(tempmaps, DRM_MEM_DRIVER);
  268         return retcode;
  269 }
  270 
  271 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
  272 {
  273         struct drm_device        *dev = arg1;
  274         struct drm_device_dma *dma = dev->dma;
  275         struct drm_device_dma tempdma;
  276         int *templists;
  277         int i;
  278         char buf[128];
  279         int retcode;
  280 
  281         /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
  282          * copy of the whole structure and the relevant data from buflist.
  283          */
  284         DRM_LOCK(dev);
  285         if (dma == NULL) {
  286                 DRM_UNLOCK(dev);
  287                 return 0;
  288         }
  289         DRM_SPINLOCK(&dev->dma_lock);
  290         tempdma = *dma;
  291         templists = malloc(sizeof(int) * dma->buf_count, DRM_MEM_DRIVER,
  292             M_NOWAIT);
  293         for (i = 0; i < dma->buf_count; i++)
  294                 templists[i] = dma->buflist[i]->list;
  295         dma = &tempdma;
  296         DRM_SPINUNLOCK(&dev->dma_lock);
  297         DRM_UNLOCK(dev);
  298 
  299         DRM_SYSCTL_PRINT("\n o     size count  free      segs pages    kB\n");
  300         for (i = 0; i <= DRM_MAX_ORDER; i++) {
  301                 if (dma->bufs[i].buf_count)
  302                         DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
  303                                        i,
  304                                        dma->bufs[i].buf_size,
  305                                        dma->bufs[i].buf_count,
  306                                        atomic_read(&dma->bufs[i]
  307                                                    .freelist.count),
  308                                        dma->bufs[i].seg_count,
  309                                        dma->bufs[i].seg_count
  310                                        *(1 << dma->bufs[i].page_order),
  311                                        (dma->bufs[i].seg_count
  312                                         * (1 << dma->bufs[i].page_order))
  313                                        * (int)PAGE_SIZE / 1024);
  314         }
  315         DRM_SYSCTL_PRINT("\n");
  316         for (i = 0; i < dma->buf_count; i++) {
  317                 if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
  318                 DRM_SYSCTL_PRINT(" %d", templists[i]);
  319         }
  320         DRM_SYSCTL_PRINT("\n");
  321 
  322         SYSCTL_OUT(req, "", 1);
  323 done:
  324         free(templists, DRM_MEM_DRIVER);
  325         return retcode;
  326 }
  327 
  328 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
  329 {
  330         struct drm_device *dev = arg1;
  331         struct drm_file *priv, *tempprivs;
  332         char buf[128];
  333         int retcode;
  334         int privcount, i;
  335 
  336         DRM_LOCK(dev);
  337 
  338         privcount = 0;
  339         list_for_each_entry(priv, &dev->filelist, lhead)
  340                 privcount++;
  341 
  342         tempprivs = malloc(sizeof(struct drm_file) * privcount, DRM_MEM_DRIVER,
  343             M_NOWAIT);
  344         if (tempprivs == NULL) {
  345                 DRM_UNLOCK(dev);
  346                 return ENOMEM;
  347         }
  348         i = 0;
  349         list_for_each_entry(priv, &dev->filelist, lhead)
  350                 tempprivs[i++] = *priv;
  351 
  352         DRM_UNLOCK(dev);
  353 
  354         DRM_SYSCTL_PRINT(
  355             "\na dev            pid   uid      magic     ioctls\n");
  356         for (i = 0; i < privcount; i++) {
  357                 priv = &tempprivs[i];
  358                 DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
  359                                priv->authenticated ? 'y' : 'n',
  360                                devtoname(priv->minor->device),
  361                                priv->pid,
  362                                priv->uid,
  363                                priv->magic,
  364                                priv->ioctl_count);
  365         }
  366 
  367         SYSCTL_OUT(req, "", 1);
  368 done:
  369         free(tempprivs, DRM_MEM_DRIVER);
  370         return retcode;
  371 }
  372 
  373 static int drm_vblank_info DRM_SYSCTL_HANDLER_ARGS
  374 {
  375         struct drm_device *dev = arg1;
  376         char buf[128];
  377         int retcode;
  378         int i;
  379 
  380         DRM_SYSCTL_PRINT("\ncrtc ref count    last     enabled inmodeset\n");
  381         DRM_LOCK(dev);
  382         if (dev->_vblank_count == NULL)
  383                 goto done;
  384         for (i = 0 ; i < dev->num_crtcs ; i++) {
  385                 DRM_SYSCTL_PRINT("  %02d  %02d %08d %08d %02d      %02d\n",
  386                     i, dev->vblank_refcount[i],
  387                     dev->_vblank_count[i],
  388                     dev->last_vblank[i],
  389                     dev->vblank_enabled[i],
  390                     dev->vblank_inmodeset[i]);
  391         }
  392 done:
  393         DRM_UNLOCK(dev);
  394 
  395         SYSCTL_OUT(req, "", -1);
  396         return retcode;
  397 }

Cache object: f9dce67ce7266983652806e4c8d8bd2d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.