LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_print.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 118 5.1 %
Date: 2023-04-06 08:38:28 Functions: 2 15 13.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2016 Red Hat
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors:
      23             :  * Rob Clark <robdclark@gmail.com>
      24             :  */
      25             : 
      26             : #include <linux/stdarg.h>
      27             : 
      28             : #include <linux/io.h>
      29             : #include <linux/moduleparam.h>
      30             : #include <linux/seq_file.h>
      31             : #include <linux/slab.h>
      32             : #include <linux/dynamic_debug.h>
      33             : 
      34             : #include <drm/drm.h>
      35             : #include <drm/drm_drv.h>
      36             : #include <drm/drm_print.h>
      37             : 
      38             : /*
      39             :  * __drm_debug: Enable debug output.
      40             :  * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
      41             :  */
      42             : unsigned long __drm_debug;
      43             : EXPORT_SYMBOL(__drm_debug);
      44             : 
      45             : MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
      46             : "\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n"
      47             : "\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n"
      48             : "\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n"
      49             : "\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n"
      50             : "\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n"
      51             : "\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n"
      52             : "\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n"
      53             : "\t\tBit 8 (0x100) will enable DP messages (displayport code)");
      54             : 
      55             : #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
      56             : module_param_named(debug, __drm_debug, ulong, 0600);
      57             : #else
      58             : /* classnames must match vals of enum drm_debug_category */
      59             : DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
      60             :                         "DRM_UT_CORE",
      61             :                         "DRM_UT_DRIVER",
      62             :                         "DRM_UT_KMS",
      63             :                         "DRM_UT_PRIME",
      64             :                         "DRM_UT_ATOMIC",
      65             :                         "DRM_UT_VBL",
      66             :                         "DRM_UT_STATE",
      67             :                         "DRM_UT_LEASE",
      68             :                         "DRM_UT_DP",
      69             :                         "DRM_UT_DRMRES");
      70             : 
      71             : static struct ddebug_class_param drm_debug_bitmap = {
      72             :         .bits = &__drm_debug,
      73             :         .flags = "p",
      74             :         .map = &drm_debug_classes,
      75             : };
      76             : module_param_cb(debug, &param_ops_dyndbg_classes, &drm_debug_bitmap, 0600);
      77             : #endif
      78             : 
      79           0 : void __drm_puts_coredump(struct drm_printer *p, const char *str)
      80             : {
      81           0 :         struct drm_print_iterator *iterator = p->arg;
      82             :         ssize_t len;
      83             : 
      84           0 :         if (!iterator->remain)
      85             :                 return;
      86             : 
      87           0 :         if (iterator->offset < iterator->start) {
      88             :                 ssize_t copy;
      89             : 
      90           0 :                 len = strlen(str);
      91             : 
      92           0 :                 if (iterator->offset + len <= iterator->start) {
      93           0 :                         iterator->offset += len;
      94           0 :                         return;
      95             :                 }
      96             : 
      97           0 :                 copy = len - (iterator->start - iterator->offset);
      98             : 
      99           0 :                 if (copy > iterator->remain)
     100           0 :                         copy = iterator->remain;
     101             : 
     102             :                 /* Copy out the bit of the string that we need */
     103           0 :                 memcpy(iterator->data,
     104           0 :                         str + (iterator->start - iterator->offset), copy);
     105             : 
     106           0 :                 iterator->offset = iterator->start + copy;
     107           0 :                 iterator->remain -= copy;
     108             :         } else {
     109           0 :                 ssize_t pos = iterator->offset - iterator->start;
     110             : 
     111           0 :                 len = min_t(ssize_t, strlen(str), iterator->remain);
     112             : 
     113           0 :                 memcpy(iterator->data + pos, str, len);
     114             : 
     115           0 :                 iterator->offset += len;
     116           0 :                 iterator->remain -= len;
     117             :         }
     118             : }
     119             : EXPORT_SYMBOL(__drm_puts_coredump);
     120             : 
     121           0 : void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
     122             : {
     123           0 :         struct drm_print_iterator *iterator = p->arg;
     124             :         size_t len;
     125             :         char *buf;
     126             : 
     127           0 :         if (!iterator->remain)
     128             :                 return;
     129             : 
     130             :         /* Figure out how big the string will be */
     131           0 :         len = snprintf(NULL, 0, "%pV", vaf);
     132             : 
     133             :         /* This is the easiest path, we've already advanced beyond the offset */
     134           0 :         if (iterator->offset + len <= iterator->start) {
     135           0 :                 iterator->offset += len;
     136           0 :                 return;
     137             :         }
     138             : 
     139             :         /* Then check if we can directly copy into the target buffer */
     140           0 :         if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
     141           0 :                 ssize_t pos = iterator->offset - iterator->start;
     142             : 
     143           0 :                 snprintf(((char *) iterator->data) + pos,
     144             :                         iterator->remain, "%pV", vaf);
     145             : 
     146           0 :                 iterator->offset += len;
     147           0 :                 iterator->remain -= len;
     148             : 
     149           0 :                 return;
     150             :         }
     151             : 
     152             :         /*
     153             :          * Finally, hit the slow path and make a temporary string to copy over
     154             :          * using _drm_puts_coredump
     155             :          */
     156           0 :         buf = kmalloc(len + 1, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
     157           0 :         if (!buf)
     158             :                 return;
     159             : 
     160           0 :         snprintf(buf, len + 1, "%pV", vaf);
     161           0 :         __drm_puts_coredump(p, (const char *) buf);
     162             : 
     163           0 :         kfree(buf);
     164             : }
     165             : EXPORT_SYMBOL(__drm_printfn_coredump);
     166             : 
     167           0 : void __drm_puts_seq_file(struct drm_printer *p, const char *str)
     168             : {
     169           0 :         seq_puts(p->arg, str);
     170           0 : }
     171             : EXPORT_SYMBOL(__drm_puts_seq_file);
     172             : 
     173           0 : void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
     174             : {
     175           0 :         seq_printf(p->arg, "%pV", vaf);
     176           0 : }
     177             : EXPORT_SYMBOL(__drm_printfn_seq_file);
     178             : 
     179           0 : void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
     180             : {
     181           0 :         dev_info(p->arg, "[" DRM_NAME "] %pV", vaf);
     182           0 : }
     183             : EXPORT_SYMBOL(__drm_printfn_info);
     184             : 
     185           0 : void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
     186             : {
     187             :         /* pr_debug callsite decorations are unhelpful here */
     188           0 :         printk(KERN_DEBUG "%s %pV", p->prefix, vaf);
     189           0 : }
     190             : EXPORT_SYMBOL(__drm_printfn_debug);
     191             : 
     192           0 : void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf)
     193             : {
     194           0 :         pr_err("*ERROR* %s %pV", p->prefix, vaf);
     195           0 : }
     196             : EXPORT_SYMBOL(__drm_printfn_err);
     197             : 
     198             : /**
     199             :  * drm_puts - print a const string to a &drm_printer stream
     200             :  * @p: the &drm printer
     201             :  * @str: const string
     202             :  *
     203             :  * Allow &drm_printer types that have a constant string
     204             :  * option to use it.
     205             :  */
     206           0 : void drm_puts(struct drm_printer *p, const char *str)
     207             : {
     208           0 :         if (p->puts)
     209           0 :                 p->puts(p, str);
     210             :         else
     211           0 :                 drm_printf(p, "%s", str);
     212           0 : }
     213             : EXPORT_SYMBOL(drm_puts);
     214             : 
     215             : /**
     216             :  * drm_printf - print to a &drm_printer stream
     217             :  * @p: the &drm_printer
     218             :  * @f: format string
     219             :  */
     220           0 : void drm_printf(struct drm_printer *p, const char *f, ...)
     221             : {
     222             :         va_list args;
     223             : 
     224           0 :         va_start(args, f);
     225           0 :         drm_vprintf(p, f, &args);
     226           0 :         va_end(args);
     227           0 : }
     228             : EXPORT_SYMBOL(drm_printf);
     229             : 
     230             : /**
     231             :  * drm_print_bits - print bits to a &drm_printer stream
     232             :  *
     233             :  * Print bits (in flag fields for example) in human readable form.
     234             :  *
     235             :  * @p: the &drm_printer
     236             :  * @value: field value.
     237             :  * @bits: Array with bit names.
     238             :  * @nbits: Size of bit names array.
     239             :  */
     240           0 : void drm_print_bits(struct drm_printer *p, unsigned long value,
     241             :                     const char * const bits[], unsigned int nbits)
     242             : {
     243           0 :         bool first = true;
     244             :         unsigned int i;
     245             : 
     246           0 :         if (WARN_ON_ONCE(nbits > BITS_PER_TYPE(value)))
     247           0 :                 nbits = BITS_PER_TYPE(value);
     248             : 
     249           0 :         for_each_set_bit(i, &value, nbits) {
     250           0 :                 if (WARN_ON_ONCE(!bits[i]))
     251           0 :                         continue;
     252           0 :                 drm_printf(p, "%s%s", first ? "" : ",",
     253             :                            bits[i]);
     254           0 :                 first = false;
     255             :         }
     256           0 :         if (first)
     257           0 :                 drm_printf(p, "(none)");
     258           0 : }
     259             : EXPORT_SYMBOL(drm_print_bits);
     260             : 
     261           0 : void drm_dev_printk(const struct device *dev, const char *level,
     262             :                     const char *format, ...)
     263             : {
     264             :         struct va_format vaf;
     265             :         va_list args;
     266             : 
     267           0 :         va_start(args, format);
     268           0 :         vaf.fmt = format;
     269           0 :         vaf.va = &args;
     270             : 
     271           0 :         if (dev)
     272           0 :                 dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
     273             :                            __builtin_return_address(0), &vaf);
     274             :         else
     275           0 :                 printk("%s" "[" DRM_NAME ":%ps] %pV",
     276             :                        level, __builtin_return_address(0), &vaf);
     277             : 
     278           0 :         va_end(args);
     279           0 : }
     280             : EXPORT_SYMBOL(drm_dev_printk);
     281             : 
     282         890 : void __drm_dev_dbg(struct _ddebug *desc, const struct device *dev,
     283             :                    enum drm_debug_category category, const char *format, ...)
     284             : {
     285             :         struct va_format vaf;
     286             :         va_list args;
     287             : 
     288         890 :         if (!__drm_debug_enabled(category))
     289         890 :                 return;
     290             : 
     291             :         /* we know we are printing for either syslog, tracefs, or both */
     292           0 :         va_start(args, format);
     293           0 :         vaf.fmt = format;
     294           0 :         vaf.va = &args;
     295             : 
     296           0 :         if (dev)
     297           0 :                 dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV",
     298             :                            __builtin_return_address(0), &vaf);
     299             :         else
     300           0 :                 printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
     301             :                        __builtin_return_address(0), &vaf);
     302             : 
     303           0 :         va_end(args);
     304             : }
     305             : EXPORT_SYMBOL(__drm_dev_dbg);
     306             : 
     307         181 : void ___drm_dbg(struct _ddebug *desc, enum drm_debug_category category, const char *format, ...)
     308             : {
     309             :         struct va_format vaf;
     310             :         va_list args;
     311             : 
     312         181 :         if (!__drm_debug_enabled(category))
     313         181 :                 return;
     314             : 
     315           0 :         va_start(args, format);
     316           0 :         vaf.fmt = format;
     317           0 :         vaf.va = &args;
     318             : 
     319           0 :         printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
     320             :                __builtin_return_address(0), &vaf);
     321             : 
     322           0 :         va_end(args);
     323             : }
     324             : EXPORT_SYMBOL(___drm_dbg);
     325             : 
     326           0 : void __drm_err(const char *format, ...)
     327             : {
     328             :         struct va_format vaf;
     329             :         va_list args;
     330             : 
     331           0 :         va_start(args, format);
     332           0 :         vaf.fmt = format;
     333           0 :         vaf.va = &args;
     334             : 
     335           0 :         printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
     336             :                __builtin_return_address(0), &vaf);
     337             : 
     338           0 :         va_end(args);
     339           0 : }
     340             : EXPORT_SYMBOL(__drm_err);
     341             : 
     342             : /**
     343             :  * drm_print_regset32 - print the contents of registers to a
     344             :  * &drm_printer stream.
     345             :  *
     346             :  * @p: the &drm printer
     347             :  * @regset: the list of registers to print.
     348             :  *
     349             :  * Often in driver debug, it's useful to be able to either capture the
     350             :  * contents of registers in the steady state using debugfs or at
     351             :  * specific points during operation.  This lets the driver have a
     352             :  * single list of registers for both.
     353             :  */
     354           0 : void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset)
     355             : {
     356           0 :         int namelen = 0;
     357             :         int i;
     358             : 
     359           0 :         for (i = 0; i < regset->nregs; i++)
     360           0 :                 namelen = max(namelen, (int)strlen(regset->regs[i].name));
     361             : 
     362           0 :         for (i = 0; i < regset->nregs; i++) {
     363           0 :                 drm_printf(p, "%*s = 0x%08x\n",
     364           0 :                            namelen, regset->regs[i].name,
     365           0 :                            readl(regset->base + regset->regs[i].offset));
     366             :         }
     367           0 : }
     368             : EXPORT_SYMBOL(drm_print_regset32);

Generated by: LCOV version 1.14