lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <34979a3b-e968-4ca6-867e-a90e6cb35b83@suse.de>
Date: Tue, 3 Dec 2024 10:35:45 +0100
From: Thomas Zimmermann <tzimmermann@...e.de>
To: Jocelyn Falempe <jfalempe@...hat.com>,
 Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
 Maxime Ripard <mripard@...nel.org>, David Airlie <airlied@...il.com>,
 Daniel Vetter <daniel@...ll.ch>, John Ogness <john.ogness@...utronix.de>,
 Javier Martinez Canillas <javierm@...hat.com>,
 "Guilherme G . Piccoli" <gpiccoli@...lia.com>,
 bluescreen_avenger@...izon.net, Caleb Connolly <caleb.connolly@...aro.org>,
 Petr Mladek <pmladek@...e.com>, dri-devel@...ts.freedesktop.org,
 linux-kernel@...r.kernel.org
Subject: Re: [PATCH v8 2/6] drm/log: Introduce a new boot logger to draw the
 kmsg on the screen

Hi


Am 03.12.24 um 10:22 schrieb Jocelyn Falempe:
> On 03/12/2024 09:48, Thomas Zimmermann wrote:
>> Hi
>>
>>
>> Am 15.11.24 um 14:40 schrieb Jocelyn Falempe:
>>> drm_log is a simple logger that uses the drm_client API to print the
>>> kmsg boot log on the screen. This is not a full replacement to fbcon,
>>> as it will only print the kmsg. It will never handle user input, or a
>>> terminal because this is better done in userspace.
>>>
>>> Design decisions:
>>>   * It uses the drm_client API, so it should work on all drm drivers
>>>     from the start.
>>>   * It doesn't scroll the message, that way it doesn't need to redraw
>>>     the whole screen for each new message.
>>>     It also means it doesn't have to keep drawn messages in memory, to
>>>     redraw them when scrolling.
>>>   * It uses the new non-blocking console API, so it should work well
>>>     with PREEMPT_RT.
>>>
>>> This patch also adds a Kconfig menu to select the drm client to use.
>>> It can be overwritten on the kernel command line with:
>>> drm_client_lib.default=log or drm_client_lib.default=fbdev
>>>
>>> Signed-off-by: Jocelyn Falempe <jfalempe@...hat.com>
>>> Reviewed-by: John Ogness <john.ogness@...utronix.de> # console API
>>> ---
>>>
>>> v2:
>>>   * Use vmap_local() api, with that change, I've tested it 
>>> successfully on simpledrm, virtio-gpu, amdgpu, and nouveau.
>>>   * Stop drawing when the drm_master is taken. This avoid wasting 
>>> CPU cycle if the buffer is not visible.
>>>   * Use deferred probe. Only do the probe the first time there is a 
>>> log to draw. With this, if you boot with quiet, drm_log won't do any 
>>> modeset.
>>>   * Add color support for the timestamp prefix, like what dmesg does.
>>>   * Add build dependency on  disabling the fbdev emulation, as they 
>>> are both drm_client, and there is no way to choose which one gets 
>>> the focus.
>>>
>>> v3:
>>>   * Remove the work thread and circular buffer, and use the new 
>>> write_thread() console API.
>>>   * Register a console for each drm driver.
>>>
>>> v4:
>>>   * Can be built as a module, even if that's not really useful.
>>>   * Rebased on top of "drm: Introduce DRM client library" series 
>>> from Thomas Zimmermann.
>>>   * Add a Kconfig menu to choose between drm client.
>>> v5:
>>>   * Build drm_log in drm_client_lib module, to avoid circular 
>>> dependency.
>>>
>>> v8:
>>>   * Rebased after drm client moved to drivers/gpu/drm/clients/
>>>   * Rename DRM_LOG to DRM_CLIENT_LOG (Thomas Zimmermann)
>>>   * Add an info message if no clients are initialized in 
>>> drm_client_setup()
>>>
>>>   drivers/gpu/drm/clients/Kconfig               |  48 +++
>>>   drivers/gpu/drm/clients/Makefile              |   1 +
>>>   drivers/gpu/drm/clients/drm_client_internal.h |   6 +
>>>   drivers/gpu/drm/clients/drm_client_setup.c    |  29 +-
>>>   drivers/gpu/drm/clients/drm_log.c             | 370 
>>> ++++++++++++++++++
>>>   5 files changed, 450 insertions(+), 4 deletions(-)
>>>   create mode 100644 drivers/gpu/drm/clients/drm_log.c
>>>
>>> diff --git a/drivers/gpu/drm/clients/Kconfig b/drivers/gpu/drm/ 
>>> clients/Kconfig
>>> index 01ad3b0001303..7cbdb1b881b45 100644
>>> --- a/drivers/gpu/drm/clients/Kconfig
>>> +++ b/drivers/gpu/drm/clients/Kconfig
>>> @@ -13,6 +13,7 @@ config DRM_CLIENT_SELECTION
>>>       tristate
>>>       depends on DRM
>>>       select DRM_CLIENT_LIB if DRM_FBDEV_EMULATION
>>> +    select DRM_CLIENT_LIB if DRM_CLIENT_LOG
>>
>> 'if <>' sorted alphabetically please.
>
> Yes, sure.
>>
>>>       help
>>>         Drivers that support in-kernel DRM clients have to select this
>>>         option.
>>> @@ -70,4 +71,51 @@ config DRM_FBDEV_LEAK_PHYS_SMEM
>>>         If in doubt, say "N" or spread the word to your closed source
>>>         library vendor.
>>> +config DRM_CLIENT_LOG
>>> +    bool "Print the kernel boot message on the screen"
>>> +    depends on DRM_CLIENT_SELECTION
>>> +    select DRM_DRAW
>>> +    select DRM_CLIENT
>>> +    select DRM_CLIENT_SETUP
>>
>> Select sorted alphabetically please.
>
> Agreed too
>>
>>> +    help
>>> +      This enable a drm logger, that will print the kernel messages 
>>> to the
>>> +      screen until the userspace is ready to take over.
>>> +
>>> +      If you only need logs, but no terminal, or if you prefer 
>>> userspace
>>> +      terminal, say "Y".
>>> +
>>> +choice
>>> +    prompt "Default DRM Client"
>>> +    depends on DRM_CLIENT_SELECTION
>>> +    default DRM_CLIENT_DEFAULT_FBDEV
>>> +    help
>>> +      Selects the default drm client.
>>> +
>>> +      The selection made here can be overridden by using the kernel
>>> +      command line 'drm_client_lib.default=fbdev' option.
>>> +
>>> +config DRM_CLIENT_DEFAULT_FBDEV
>>> +    bool "fbdev"
>>> +    depends on DRM_FBDEV_EMULATION
>>> +    help
>>> +      Use fbdev emulation as default drm client. This is needed to 
>>> have
>>> +      fbcon on top of a drm driver.
>>> +
>>> +config DRM_CLIENT_DEFAULT_LOG
>>> +    bool "log"
>>> +    depends on DRM_CLIENT_LOG
>>> +    help
>>> +      Use drm log as default drm client. This will display boot 
>>> logs on the
>>> +      screen, but doesn't implement a full terminal. For that you 
>>> will need
>>> +      a userspace terminal using drm/kms.
>>> +
>>> +endchoice
>>> +
>>> +config DRM_CLIENT_DEFAULT
>>> +       string
>>> +       depends on DRM_CLIENT
>>> +       default "fbdev" if DRM_CLIENT_DEFAULT_FBDEV
>>> +       default "log" if DRM_CLIENT_DEFAULT_LOG
>>> +       default ""
>>> +
>>>   endmenu
>>> diff --git a/drivers/gpu/drm/clients/Makefile b/drivers/gpu/drm/ 
>>> clients/Makefile
>>> index 1d004ec92e1ea..9fb776590efe7 100644
>>> --- a/drivers/gpu/drm/clients/Makefile
>>> +++ b/drivers/gpu/drm/clients/Makefile
>>> @@ -2,4 +2,5 @@
>>>   drm_client_lib-y := drm_client_setup.o
>>>   drm_client_lib-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fbdev_client.o
>>> +drm_client_lib-$(CONFIG_DRM_CLIENT_LOG) += drm_log.o
>>>   obj-$(CONFIG_DRM_CLIENT_LIB) += drm_client_lib.o
>>> diff --git a/drivers/gpu/drm/clients/drm_client_internal.h 
>>> b/drivers/ gpu/drm/clients/drm_client_internal.h
>>> index 23258934956aa..6dc078bf6503b 100644
>>> --- a/drivers/gpu/drm/clients/drm_client_internal.h
>>> +++ b/drivers/gpu/drm/clients/drm_client_internal.h
>>> @@ -16,4 +16,10 @@ static inline int drm_fbdev_client_setup(struct 
>>> drm_device *dev,
>>>   }
>>>   #endif
>>> +#ifdef CONFIG_DRM_CLIENT_LOG
>>> +void drm_log_register(struct drm_device *dev);
>>> +#else
>>> +static inline void drm_log_register(struct drm_device *dev) {}
>>> +#endif
>>> +
>>>   #endif
>>> diff --git a/drivers/gpu/drm/clients/drm_client_setup.c 
>>> b/drivers/gpu/ drm/clients/drm_client_setup.c
>>> index 4b211a4812b5b..92a7b3c180d19 100644
>>> --- a/drivers/gpu/drm/clients/drm_client_setup.c
>>> +++ b/drivers/gpu/drm/clients/drm_client_setup.c
>>> @@ -7,6 +7,12 @@
>>>   #include "drm_client_internal.h"
>>> +static char drm_client_default[16] = CONFIG_DRM_CLIENT_DEFAULT;
>>> +module_param_string(client, drm_client_default, 
>>> sizeof(drm_client_default), 0444);
>>> +MODULE_PARM_DESC(client,
>>> +         "Choose which drm client to start, default is"
>>> +         CONFIG_DRM_CLIENT_DEFAULT "]");
>>
>> CONFIG_DRM_CLIENT_DEFAULT is good for the config option. But using 
>> 'drm_client_lib.client=log' seems imprecise to me. The module 
>> parameter itself should maybe called something like 'setup' or 'active'.
>
> Ok, I can rename it to drm_client_lib.active=log
>
>>
>> (As a sidenote, if we ever have more clients, we could then modify 
>> the parameter to be separated by comma. The user would then be able 
>> to specify a set of clients from the ones available.)
>
> I'm a bit confused about this.
> The goal is to allow to build any number of drm clients in the kernel, 
> but only one can run. There are no way to switch from one client to 
> another at runtime. So what would be the purpose of specifying 
> multiple clients?

The user could then specify the order of trying them, like in 
'active=log, fdev, bootsplash,foo, bar'. And the kernel would try them 
in this precise order. Only make sense if there are more than two 
clients available of course.

>
>>
>>
>>> +
>>>   /**
>>>    * drm_client_setup() - Setup in-kernel DRM clients
>>>    * @dev: DRM device
>>> @@ -25,11 +31,26 @@
>>>    */
>>>   void drm_client_setup(struct drm_device *dev, const struct 
>>> drm_format_info *format)
>>>   {
>>> -    int ret;
>>> -    ret = drm_fbdev_client_setup(dev, format);
>>> -    if (ret)
>>> -        drm_warn(dev, "Failed to set up DRM client; error %d\n", ret);
>>> +#ifdef CONFIG_DRM_FBDEV_EMULATION
>>> +    if (!strcmp(drm_client_default, "fbdev")) {
>>> +        int ret;
>>> +
>>> +        ret = drm_fbdev_client_setup(dev, format);
>>> +        if (ret)
>>> +            drm_warn(dev, "Failed to set up DRM client; error 
>>> %d\n", ret);
>>> +        return;
>>> +    }
>>> +#endif
>>> +
>>> +#ifdef CONFIG_DRM_CLIENT_LOG
>>> +    if (!strcmp(drm_client_default, "log")) {
>>> +        drm_log_register(dev);
>>> +        return;
>>> +    }
>>> +#endif
>>> +
>>> +    drm_info(dev, "No drm client registered\n");
>>
>> Let's remain silent here. If anything, debug please.
>
> If you get there, it's either a typo, or a misconfiguration, but yes I 
> can move it as debug.

It should be a warning then. Something like

   if (strcmp(drm_client_log, ""))
       drm_warn("Unknown DRM client %s\n", drm_client_log)

>
>>
>>>   }
>>>   EXPORT_SYMBOL(drm_client_setup);
>>> diff --git a/drivers/gpu/drm/clients/drm_log.c b/drivers/gpu/drm/ 
>>> clients/drm_log.c
>>> new file mode 100644
>>> index 0000000000000..cb793a348f1f9
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/clients/drm_log.c
>>> @@ -0,0 +1,370 @@
>>> +// SPDX-License-Identifier: GPL-2.0 or MIT
>>> +/*
>>> + * Copyright (c) 2024 Red Hat.
>>> + * Author: Jocelyn Falempe <jfalempe@...hat.com>
>>> + */
>>> +
>>> +#include <linux/console.h>
>>> +#include <linux/font.h>
>>> +#include <linux/init.h>
>>> +#include <linux/iosys-map.h>
>>> +#include <linux/module.h>
>>> +#include <linux/types.h>
>>> +
>>> +#include <drm/drm_client.h>
>>> +#include <drm/drm_drv.h>
>>> +#include <drm/drm_fourcc.h>
>>> +#include <drm/drm_framebuffer.h>
>>> +#include <drm/drm_print.h>
>>> +
>>> +#include "drm_client_internal.h"
>>> +#include "../drm_draw.h"
>>> +
>>> +MODULE_AUTHOR("Jocelyn Falempe");
>>> +MODULE_DESCRIPTION("DRM boot logger");
>>> +MODULE_LICENSE("GPL");
>>> +
>>> +/**
>>> + * DOC: overview
>>> + *
>>> + * This is a simple graphic logger, to print the kernel message on 
>>> screen, until
>>> + * a userspace application is able to take over.
>>> + * It is only for debugging purpose.
>>> + */
>>> +
>>> +struct drm_log_scanout {
>>> +    struct drm_client_buffer *buffer;
>>> +    const struct font_desc *font;
>>> +    u32 rows;
>>> +    u32 columns;
>>> +    u32 line;
>>> +    u32 format;
>>> +    u32 px_width;
>>> +    u32 front_color;
>>> +};
>>> +
>>> +struct drm_log {
>>> +    struct mutex lock;
>>> +    struct drm_client_dev client;
>>> +    struct console con;
>>> +    bool probed;
>>> +    u32 n_scanout;
>>> +    struct drm_log_scanout *scanout;
>>> +};
>>> +
>>> +static struct drm_log *client_to_drm_log(struct drm_client_dev 
>>> *client)
>>> +{
>>> +    return container_of(client, struct drm_log, client);
>>> +}
>>> +
>>> +static struct drm_log *console_to_drm_log(struct console *con)
>>> +{
>>> +    return container_of(con, struct drm_log, con);
>>> +}
>>> +
>>> +static void drm_log_blit(struct iosys_map *dst, unsigned int 
>>> dst_pitch,
>>> +             const u8 *src, unsigned int src_pitch,
>>> +             u32 height, u32 width, u32 scale, u32 px_width, u32 
>>> color)
>>> +{
>>> +    switch (px_width) {
>>> +    case 2:
>>> +        drm_draw_blit16(dst, dst_pitch, src, src_pitch, height, 
>>> width, scale, color);
>>> +        break;
>>> +    case 3:
>>> +        drm_draw_blit24(dst, dst_pitch, src, src_pitch, height, 
>>> width, scale, color);
>>> +        break;
>>> +    case 4:
>>> +        drm_draw_blit32(dst, dst_pitch, src, src_pitch, height, 
>>> width, scale, color);
>>> +        break;
>>> +    default:
>>> +        WARN_ONCE(1, "Can't blit with pixel width %d\n", px_width);
>>> +    }
>>> +}
>>> +
>>> +static void drm_log_clear_line(struct drm_log_scanout *scanout, u32 
>>> line)
>>> +{
>>> +    struct drm_framebuffer *fb = scanout->buffer->fb;
>>> +    unsigned long height = scanout->font->height;
>>> +    struct iosys_map map;
>>> +    struct drm_rect r = DRM_RECT_INIT(0, line * height, fb->width, 
>>> height);
>>> +
>>> +    if (drm_client_buffer_vmap_local(scanout->buffer, &map))
>>> +        return;
>>> +    iosys_map_memset(&map, r.y1 * fb->pitches[0], 0, height * fb- 
>>> >pitches[0]);
>>> +    drm_client_buffer_vunmap_local(scanout->buffer);
>>> +    drm_client_framebuffer_flush(scanout->buffer, &r);
>>> +}
>>> +
>>> +static void drm_log_draw_line(struct drm_log_scanout *scanout, 
>>> const char *s,
>>> +                  unsigned int len)
>>> +{
>>> +    struct drm_framebuffer *fb = scanout->buffer->fb;
>>> +    struct iosys_map map;
>>> +    const struct font_desc *font = scanout->font;
>>> +    size_t font_pitch = DIV_ROUND_UP(font->width, 8);
>>> +    const u8 *src;
>>> +    u32 px_width = fb->format->cpp[0];
>>> +    struct drm_rect r = DRM_RECT_INIT(0, scanout->line * font->height,
>>> +                      fb->width, (scanout->line + 1) * font->height);
>>> +    u32 i;
>>> +
>>> +    if (drm_client_buffer_vmap_local(scanout->buffer, &map))
>>> +        return;
>>> +
>>> +    iosys_map_incr(&map, r.y1 * fb->pitches[0]);
>>> +    for (i = 0; i < len && i < scanout->columns; i++) {
>>> +        src = drm_draw_get_char_bitmap(font, s[i], font_pitch);
>>> +        drm_log_blit(&map, fb->pitches[0], src, font_pitch, font- 
>>> >height, font->width,
>>> +                 1, px_width, scanout->front_color);
>>> +        iosys_map_incr(&map, font->width * px_width);
>>> +    }
>>> +
>>> +    scanout->line++;
>>> +    if (scanout->line >= scanout->rows)
>>> +        scanout->line = 0;
>>> +    drm_client_buffer_vunmap_local(scanout->buffer);
>>> +    drm_client_framebuffer_flush(scanout->buffer, &r);
>>> +}
>>> +
>>> +static void drm_log_draw_new_line(struct drm_log_scanout *scanout,
>>> +                  const char *s, unsigned int len)
>>> +{
>>> +    if (scanout->line == 0) {
>>> +        drm_log_clear_line(scanout, 0);
>>> +        drm_log_clear_line(scanout, 1);
>>> +        drm_log_clear_line(scanout, 2);
>>> +    } else if (scanout->line + 2 < scanout->rows)
>>> +        drm_log_clear_line(scanout, scanout->line + 2);
>>> +
>>> +    drm_log_draw_line(scanout, s, len);
>>> +}
>>> +
>>> +static void drm_log_draw_kmsg_record(struct drm_log_scanout *scanout,
>>> +                     const char *s, unsigned int len)
>>> +{
>>> +    /* do not print the ending \n character */
>>> +    if (s[len - 1] == '\n')
>>> +        len--;
>>> +
>>> +    while (len > scanout->columns) {
>>> +        drm_log_draw_new_line(scanout, s, scanout->columns);
>>> +        s += scanout->columns;
>>> +        len -= scanout->columns;
>>> +    }
>>> +    if (len)
>>> +        drm_log_draw_new_line(scanout, s, len);
>>> +}
>>> +
>>> +static u32 drm_log_find_usable_format(struct drm_plane *plane)
>>> +{
>>> +    int i;
>>> +
>>> +    for (i = 0; i < plane->format_count; i++)
>>> +        if (drm_draw_color_from_xrgb8888(0xffffff, plane- 
>>> >format_types[i]) != 0)
>>> +            return plane->format_types[i];
>>> +    return DRM_FORMAT_INVALID;
>>> +}
>>> +
>>> +static int drm_log_setup_modeset(struct drm_client_dev *client,
>>> +                 struct drm_mode_set *mode_set,
>>> +                 struct drm_log_scanout *scanout)
>>> +{
>>> +    struct drm_crtc *crtc = mode_set->crtc;
>>> +    u32 width = mode_set->mode->hdisplay;
>>> +    u32 height = mode_set->mode->vdisplay;
>>> +    u32 format;
>>> +
>>> +    scanout->font = get_default_font(width, height, NULL, NULL);
>>> +    if (!scanout->font)
>>> +        return -ENOENT;
>>> +
>>> +    format = drm_log_find_usable_format(crtc->primary);
>>> +    if (format == DRM_FORMAT_INVALID)
>>> +        return -EINVAL;
>>> +
>>> +    scanout->buffer = drm_client_framebuffer_create(client, width, 
>>> height, format);
>>> +    if (IS_ERR(scanout->buffer)) {
>>> +        drm_warn(client->dev, "drm_log can't create framebuffer %d 
>>> %d %p4cc\n",
>>> +             width, height, &format);
>>> +        return -ENOMEM;
>>> +    }
>>> +    mode_set->fb = scanout->buffer->fb;
>>> +    scanout->rows = height / scanout->font->height;
>>> +    scanout->columns = width / scanout->font->width;
>>> +    scanout->front_color = drm_draw_color_from_xrgb8888(0xffffff, 
>>> format);
>>> +    return 0;
>>> +}
>>> +
>>> +static int drm_log_count_modeset(struct drm_client_dev *client)
>>> +{
>>> +    struct drm_mode_set *mode_set;
>>> +    int count = 0;
>>> +
>>> +    mutex_lock(&client->modeset_mutex);
>>> +    drm_client_for_each_modeset(mode_set, client)
>>> +        count++;
>>> +    mutex_unlock(&client->modeset_mutex);
>>> +    return count;
>>> +}
>>> +
>>> +static void drm_log_init_client(struct drm_log *dlog)
>>> +{
>>> +    struct drm_client_dev *client = &dlog->client;
>>> +    struct drm_mode_set *mode_set;
>>> +    int i, max_modeset;
>>> +    int n_modeset = 0;
>>> +
>>> +    dlog->probed = true;
>>> +
>>> +    if (drm_client_modeset_probe(client, 0, 0))
>>> +        return;
>>> +
>>> +    max_modeset = drm_log_count_modeset(client);
>>> +    if (!max_modeset)
>>> +        return;
>>> +
>>> +    dlog->scanout = kcalloc(max_modeset, sizeof(*dlog->scanout), 
>>> GFP_KERNEL);
>>> +    if (!dlog->scanout)
>>> +        return;
>>> +
>>> +    mutex_lock(&client->modeset_mutex);
>>> +    drm_client_for_each_modeset(mode_set, client) {
>>> +        if (!mode_set->mode)
>>> +            continue;
>>> +        if (drm_log_setup_modeset(client, mode_set, &dlog- 
>>> >scanout[n_modeset]))
>>> +            continue;
>>> +        n_modeset++;
>>> +    }
>>> +    mutex_unlock(&client->modeset_mutex);
>>> +    if (n_modeset == 0)
>>> +        goto err_nomodeset;
>>> +
>>> +    if (drm_client_modeset_commit(client))
>>> +        goto err_failed_commit;
>>> +
>>> +    dlog->n_scanout = n_modeset;
>>> +    return;
>>> +
>>> +err_failed_commit:
>>> +    for (i = 0; i < n_modeset; i++)
>>> + drm_client_framebuffer_delete(dlog->scanout[i].buffer);
>>> +
>>> +err_nomodeset:
>>> +    kfree(dlog->scanout);
>>> +    dlog->scanout = NULL;
>>> +}
>>> +
>>> +static void drm_log_free_scanout(struct drm_client_dev *client)
>>> +{
>>> +    struct drm_log *dlog = client_to_drm_log(client);
>>> +    int i;
>>> +
>>> +    if (dlog->n_scanout) {
>>> +        for (i = 0; i < dlog->n_scanout; i++)
>>> + drm_client_framebuffer_delete(dlog->scanout[i].buffer);
>>> +        dlog->n_scanout = 0;
>>> +        kfree(dlog->scanout);
>>> +        dlog->scanout = NULL;
>>> +    }
>>> +}
>>> +
>>> +static void drm_log_client_unregister(struct drm_client_dev *client)
>>> +{
>>> +    struct drm_log *dlog = client_to_drm_log(client);
>>> +    struct drm_device *dev = client->dev;
>>> +
>>> +    unregister_console(&dlog->con);
>>> +
>>> +    mutex_lock(&dlog->lock);
>>> +    drm_log_free_scanout(client);
>>> +    drm_client_release(client);
>>> +    mutex_unlock(&dlog->lock);
>>> +    kfree(dlog);
>>> +    drm_info(dev, "Unregistered with drm log\n");
>>
>> We don't do such messages anywhere. So if anything, debug output here.
>
> Agreed.
>>
>>> +}
>>> +
>>> +static int drm_log_client_hotplug(struct drm_client_dev *client)
>>> +{
>>> +    struct drm_log *dlog = client_to_drm_log(client);
>>> +
>>> +    mutex_lock(&dlog->lock);
>>> +    drm_log_free_scanout(client);
>>> +    dlog->probed = false;
>>> +    mutex_unlock(&dlog->lock);
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct drm_client_funcs drm_log_client_funcs = {
>>> +    .owner        = THIS_MODULE,
>>> +    .unregister    = drm_log_client_unregister,
>>> +    .hotplug    = drm_log_client_hotplug,
>>> +};
>>> +
>>> +static void drm_log_write_thread(struct console *con, struct 
>>> nbcon_write_context *wctxt)
>>> +{
>>> +    struct drm_log *dlog = console_to_drm_log(con);
>>> +    int i;
>>> +
>>> +    if (!dlog->probed)
>>> +        drm_log_init_client(dlog);
>>> +
>>> +    for (i = 0; i < dlog->n_scanout; i++)
>>> +        drm_log_draw_kmsg_record(&dlog->scanout[i], wctxt->outbuf, 
>>> wctxt->len);
>>> +}
>>> +
>>> +static void drm_log_lock(struct console *con, unsigned long *flags)
>>> +{
>>> +    struct drm_log *dlog = console_to_drm_log(con);
>>> +
>>> +    mutex_lock(&dlog->lock);
>>> +    migrate_disable();
>>> +}
>>> +
>>> +static void drm_log_unlock(struct console *con, unsigned long flags)
>>> +{
>>> +    struct drm_log *dlog = console_to_drm_log(con);
>>> +
>>> +    migrate_enable();
>>> +    mutex_unlock(&dlog->lock);
>>> +}
>>> +
>>> +static void drm_log_register_console(struct console *con)
>>> +{
>>> +    strscpy(con->name, "drm_log");
>>> +    con->write_thread = drm_log_write_thread;
>>> +    con->device_lock = drm_log_lock;
>>> +    con->device_unlock = drm_log_unlock;
>>> +    con->flags = CON_PRINTBUFFER | CON_NBCON;
>>> +    con->index = -1;
>>> +
>>> +    register_console(con);
>>> +}
>>> +
>>> +/**
>>> + * drm_log_register() - Register a drm device to drm_log
>>> + * @dev: the drm device to register.
>>> + */
>>> +void drm_log_register(struct drm_device *dev)
>>> +{
>>> +    struct drm_log *new;
>>> +
>>> +    new = kzalloc(sizeof(*new), GFP_KERNEL);
>>> +    if (!new)
>>> +        goto err_warn;
>>> +
>>> +    mutex_init(&new->lock);
>>> +    if (drm_client_init(dev, &new->client, "drm_log", 
>>> &drm_log_client_funcs))
>>> +        goto err_free;
>>> +
>>> +    drm_client_register(&new->client);
>>> +
>>> +    drm_log_register_console(&new->con);
>>> +
>>> +    drm_info(dev, "Registered with drm log as %s\n", new->con.name);
>>
>> Debug please. Don't spam the kernel log with status messages.
>
> Yes I will move that to debug, but it's still much less verbose than 
> the current situation with fbdev/fbcon.
>
> [    1.631473] fbcon: Deferring console take-over
> [    1.631475] simple-framebuffer simple-framebuffer.0: [drm] fb0: 
> simpledrmdrmfb frame buffer device
> [    7.058770] fbcon: i915drmfb (fb0) is primary device
> [    7.058772] fbcon: Deferring console take-over
> [    7.058774] i915 0000:00:02.0: [drm] fb0: i915drmfb frame buffer 
> device

I don't like this either. Such output distracts from the important 
messages. But it's been there for ages so I don't dare to remove it.

Best regards
Thomas

>
>>
>> Best regards
>> Thomas
>>
>>> +    return;
>>> +
>>> +err_free:
>>> +    kfree(new);
>>> +err_warn:
>>> +    drm_warn(dev, "Failed to register with drm log\n");
>>> +}
>>
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nuernberg, Germany
GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman
HRB 36809 (AG Nuernberg)


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ