Wang Jingjin [Sat, 16 Jul 2022 02:07:41 +0000 (10:07 +0800)]
drm/vc4: Add explicit declaration of 'drmm_of_get_bridge'
Fix the error of implicit declaration of function 'drmm_of_get_bridge':
drivers/gpu/drm/vc4/vc4_dpi.c:278:11: error: implicit declaration of function ‘drmm_of_get_bridge’; did you mean ‘devm_drm_of_get_bridge’? [-Werror=implicit-function-declaration]
bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
drm/bridge: ti-sn65dsi86: support DRM_BRIDGE_ATTACH_NO_CONNECTOR
Now as the driver does not depend on pdata->connector, add support for
attaching the bridge with DRM_BRIDGE_ATTACH_NO_CONNECTOR.
Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Tested-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220711092117.360797-3-dmitry.baryshkov@linaro.org
drm/bridge: ti-sn65dsi86: fetch bpc using drm_atomic_state
Rather than reading the pdata->connector directly, fetch the connector
using drm_atomic_state. This allows us to make pdata->connector optional
(and thus supporting DRM_BRIDGE_ATTACH_NO_CONNECTOR).
Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Tested-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Tested-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220711092117.360797-2-dmitry.baryshkov@linaro.org
We already discussed that the call to drm_sched_entity_select_rq() needs
to move to drm_sched_job_arm() to be able to set a new scheduler list
between _init() and _arm(). This was just not applied for some reason.
drm/gud: Fix endianness in gud_xrgb8888_to_color() helper
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set. Hence when converting from one
format to another, multi-byte pixel values loaded from memory must be
converted from little-endian to host-endian. Conversely, multi-byte
pixel values written to memory must be converted from host-endian to
little-endian. Currently only drm_fb_xrgb8888_to_rgb332_line() includes
endianness handling.
Fix gud_xrgb8888_to_color() on big-endian platforms by adding the
missing endianness handling.
drm/format-helper: Fix endianness in drm_fb_*_to_*() conversion helpers
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set. Hence when converting from one
format to another, multi-byte pixel values loaded from memory must be
converted from little-endian to host-endian. Conversely, multi-byte
pixel values written to memory must be converted from host-endian to
little-endian. Currently only drm_fb_xrgb8888_to_rgb332_line() includes
endianness handling.
Fix this by adding endianness handling to all conversion functions that
process multi-byte pixel values.
Note that the conversion to RGB565 is special, as there are two
versions: with and without byteswapping of the RGB565 pixel data.
Liang He [Tue, 19 Jul 2022 06:54:47 +0000 (14:54 +0800)]
drm/bridge: tc358767: Add of_node_put() when breaking out of loop
In tc_probe_bridge_endpoint(), we should call of_node_put() when
breaking out of the for_each_endpoint_of_node() which will automatically
increase and decrease the refcount.
Liang He [Tue, 19 Jul 2022 06:54:46 +0000 (14:54 +0800)]
drm/bridge: anx7625: Fix refcount bug in anx7625_parse_dt()
In anx7625_parse_dt(), 'pdata->mipi_host_node' will be assigned a
new reference with of_graph_get_remote_node() which will increase
the refcount of the object, correspondingly, we should call
of_node_put() for the old reference stored in the 'pdata->mipi_host_node'.
Dmitry Osipenko [Thu, 30 Jun 2022 20:07:26 +0000 (23:07 +0300)]
drm/virtio: Return proper error codes instead of -1
Don't return -1 in error cases, return proper error code. The returned
error codes propagate to error messages and to userspace and it's always
good to have a meaningful error number for debugging purposes.
Dmitry Osipenko [Thu, 30 Jun 2022 20:07:24 +0000 (23:07 +0300)]
drm/virtio: Improve DMA API usage for shmem BOs
DRM API requires the DRM's driver to be backed with the device that can
be used for generic DMA operations. The VirtIO-GPU device can't perform
DMA operations if it uses PCI transport because PCI device driver creates
a virtual VirtIO-GPU device that isn't associated with the PCI. Use PCI's
GPU device for the DRM's device instead of the VirtIO-GPU device and drop
DMA-related hacks from the VirtIO-GPU driver.
Dmitry Osipenko [Thu, 30 Jun 2022 20:07:23 +0000 (23:07 +0300)]
drm/virtio: Simplify error handling of virtio_gpu_object_create()
Change the order of SHMEM initialization and reservation locking
to make code cleaner and to prepare for transitioning of the common
GEM SHMEM code to use the GEM's reservation lock instead of the
shmem.page_lock.
There is no need to lock reservation during allocation of the SHMEM pages
because the lock is needed only to avoid racing with the async host-side
allocation. Hence we can safely move the SHMEM initialization out of the
reservation lock.
Dmitry Osipenko [Thu, 30 Jun 2022 20:07:22 +0000 (23:07 +0300)]
drm/virtio: Use appropriate atomic state in virtio_gpu_plane_cleanup_fb()
Make virtio_gpu_plane_cleanup_fb() to clean the state which DRM core
wants to clean up and not the current plane's state. Normally the older
atomic state is cleaned up, but the newer state could also be cleaned up
in case of aborted commits.
Dmitry Osipenko [Thu, 30 Jun 2022 20:07:20 +0000 (23:07 +0300)]
drm/virtio: Unlock reservations on virtio_gpu_object_shmem_init() error
Unlock reservations in the error code path of virtio_gpu_object_create()
to silence debug warning splat produced by ww_mutex_destroy(&obj->lock)
when GEM is released with the held lock.
Previous commit fixed checking of the ERR_PTR value returned by
drm_gem_shmem_get_sg_table(), but it missed to zero out the shmem->pages,
which will crash virtio_gpu_cleanup_object(). Add the missing zeroing of
the shmem->pages.
Remove the call to do_remove_conflicting_framebuffers() from the
framebuffer registration. Aperture helpers take care of removing
conflicting devices. With all ownership information stored in the
aperture datastrcutures, remove remove_conflicting_framebuffers()
entirely.
This change also rectifies DRM generic-framebuffer registration, which
tried to unregister conflicting framebuffers, even though it's entirely
build on top of DRM.
v2:
* remove internal aperture-overlap helpers, which are
now unused
fbdev: Acquire framebuffer apertures for firmware devices
When registering a generic framebuffer, automatically acquire ownership
of the framebuffer's I/O range. The device will now be handled by the
aperture helpers. Fbdev-based conflict handling is no longer required.
video/aperture: Remove conflicting VGA devices, if any
On the primary graphics adapter, a driver might conflict with a VGA
driver that controls the VGA framebuffer I/O range. Remove the VGA
driver from the aperture helpers. Until now, this case has been
hendled by fbdev, but it should work even with fbdev disabled.
Provide VGA_FB_ constants for the VGA framebuffer I/O range and convert
fbdev code. In the case of vga16fb, this is a rename of the existing
constants VGA_FB_PHYS and VGA_FB_PHYS_LEN.
v2:
* clarify relationship with old constants in vga16fb (Javier)
Remove firmware devices on the PCI bus, by calling
aperture_remove_conflicting_pci_devices() in the probe function of
each related fbdev driver. iSo far, most of these drivers did not
remove conflicting VESA or EFI devices, or outride failed for
resource conflicts (i.e., matroxfb.) This must have been broken
for quite some time.
Convert fbdev drivers from fbdev's remove_conflicting_framebuffers() to
the framework-independent aperture_remove_conflicting_devices(). Calling
this function will also remove conflicting DRM drivers.
Remove remove_conflicting_pci_framebuffers() and implement similar
functionality in aperture_remove_conflicting_pci_device(), which was
the only caller. Removes an otherwise unused interface and streamlines
the aperture helper. No functional changes.
Move vgag16fb's option parsing into the driver's probe function and
generate the rest of the module's init/exit functions from macros.
Keep the options code, although there are no options defined.
v2:
* no options are supported, remove the code (Javier)
fbdev/vga16fb: Create EGA/VGA devices in sysfb code
Move the device-creation from vga16fb to sysfb code. The driver's
videomode checks are independent from device creation, so move them
into vga16fb's probe function. This will allow to create the module
init/exit code automatically.
The vga16fb driver requires a screen_info for type VIDEO_TYPE_VGAC
or VIDEO_TYPE_EGAC. Such code is nowhere present in the kernel, except
for some MIPS systems. It's not clear if the vga16fb driver actually
works in practice.
v2:
* keep driver name to "vga16fb" (Javier)
* give rational for moving mode checks (Javier)
Marek Vasut [Sun, 10 Jul 2022 19:44:37 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Split GIP and init sequences
The ST7701 initialization sequence is well parametrized, split the GIP
programming sequence, which is fully custom completely undocumented
TFT matrix specific magic register programming sequence into separate
callback so other TFT matrix definitions can add their own GIP sequence.
Marek Vasut [Sun, 10 Jul 2022 19:44:36 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Parametrize voltage and timing
Instead of hard-coding TFT matrix voltage and timing settings, which can
even lead to permanent TFT matrix damage, parametrize them in TFT matrix
descriptor.
Marek Vasut [Sun, 10 Jul 2022 19:44:35 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Infer horizontal pixel count from TFT mode
The horizontal pixel count is a property of the TFT matrix. Currently the
driver hard-codes content of this register to specific value which is
only compatible with one TFT matrix, likely the TS8550B one.
Calculate the horizontal pixel count from the mode instead.
Marek Vasut [Sun, 10 Jul 2022 19:44:34 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Adjust porch control bitfield name
Define DSI_CMD2_BK0_PORCTRL_VBP_MASK and DSI_CMD2_BK0_PORCTRL_VFP_MASK
and move the vertical back and front porch calculation from macros into
the st7701_init_sequence() function, so it is clear what this does.
Marek Vasut [Sun, 10 Jul 2022 19:44:33 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Infer vertical line count from TFT mode
The vertical line count is a property of the TFT matrix. Currently the
driver hard-codes content of this register to specific value which is
only compatible with one TFT matrix, likely the TS8550B one.
Calculate the vertical line count from the mode instead.
Marek Vasut [Sun, 10 Jul 2022 19:44:32 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Make gamma correction TFT specific
The gamma correction values are specific to the TFT which is attached to
the ST7701 TFT matrix driver, move the gamma correction values from what
incorrectly looks like common init sequence into TFT matrix specific
settings.
While doing so, add macros which defined fields within the gamma register
file and a macro which mimics FIELD_PREP except works with constant
expressions.
Marek Vasut [Sun, 10 Jul 2022 19:44:31 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Make voltage supplies common to ST7701
The ST7701 and ST7701S all have two voltage supplies, one for internal
logic and one for the TFT matrix driver. The supplies are not property
of the TFT matrix driver, so move them to common ST7701 code.
The ST7701(S) is capable of DSI burst mode, which is more energy
efficient than the non-burst modes. Make use of it.
The ST7701(S) is capable of DSI non-continuous clock, since it
sources the TFT matrix driver clock from internal clock source.
The DSI non-continuous clock further reduce power utilization.
The ST7701(S) uses DSI LPM for command transmissions, make sure
this is configured correctly in the DSI mode flags.
Marek Vasut [Sun, 10 Jul 2022 19:44:29 +0000 (21:44 +0200)]
drm/panel/panel-sitronix-st7701: Make DSI mode flags common to ST7701
The ST7701 and ST7701S are TFT matrix drivers with integrated multi
protocol decoder capable of DSI/DPI/SPI input and 480x360...864 line
TFT matrix output. Currently the only supported input is DSI.
The protocol decoder is separate from the TFT matrix driver and is
always capable of handling all of DSI non-burst mode with sync pulses
or sync events as well as DSI burst mode.
Move the DSI mode configuration from TFT matrix driver properties to
common ST7701 code, because this is common to all TFT matrices.
Make it clear that DMA_RESV_USAGE_BOOKKEEP can be used for explicit synced
user space submissions as well and document the rules around adding the
same fence with different usages.
Pin-Yen Lin [Thu, 14 Jul 2022 09:39:20 +0000 (17:39 +0800)]
drm/bridge: it6505: Power on downstream device in .atomic_enable
Send DPCD DP_SET_POWER_D0 command to the monitor in .atomic_enable
callback. Without this command, some monitors won't show up again after
changing the resolution.
drm/ssd130x: Use new regmap bulk write support to drop custom bus
Data writes for the ssd130x 4-wire SPI protocol need special handling, due
the Data/Command control (D/C) pin having to be toggled prior to the write.
The regmap API only allowed drivers to provide .reg_{read,write} callbacks
to do per register read/write, but didn't provide a way for drivers to do
the same for bulk read/writes.
For this reason, a custom regmap bus was used by the driver just to define
a bulk write callback that implements the D/C pin toggling. But the regmap
API has been extended to support defining bulk read/write handlers, so the
custom regmap bus is not needed anymore and could just be dropped.
Laurent Pinchart [Thu, 16 Jun 2022 18:52:10 +0000 (21:52 +0300)]
drm/fourcc: Add formats for packed YUV 4:4:4 AVUY and XVUY permutations
Add FourCCs for two missing permutations of the packed YUV 4:4:4 color
components, namely AVUY and XVUY.
These formats are needed by the NXP i.MX8 ISI. While the ISI is
supported by a V4L2 device (corresponding formats have been submitted to
V4L2), it is handled in userspace by libcamera, which uses DRM FourCCs
for pixel formats.
Sam Ravnborg [Wed, 13 Jul 2022 17:02:01 +0000 (19:02 +0200)]
drm/via: Make macros readable in the via_3d_reg header
The macros for texture 1 setting all used continuation on a new line,
resulting in a highly ureadable definition.
Merge the lines so they are each on a single line.
As a nice side-effect this fixes a number of checkpatch warnings:
"WARNING: please, no spaces at the start of a line".
Sam Ravnborg [Wed, 13 Jul 2022 17:01:58 +0000 (19:01 +0200)]
drm/via: Embed via_drv.h in via_dri1
With this change the driver is now a signle file driver.
The only remaning heder file describes the HW and can be shared with the
new openchrome driver.
Sam Ravnborg [Wed, 13 Jul 2022 17:01:56 +0000 (19:01 +0200)]
drm/via: Embed via_dmablit in via_dri1
Embed some of the header file in via_drv.h and
the rest in via_dri1.c
While embedding deleted extra empty lines and functions that
has no external users are made static.
Sam Ravnborg [Wed, 13 Jul 2022 17:01:50 +0000 (19:01 +0200)]
drm/via: Rename via_drv to via_dri1
The via driver implements the DRI1 interface, and we have a new
implementation of the via driver coming that supports atomic
modesetting.
It is not acceptable just to replace the existing driver so
this is first step to make it a single-file implementation allowing
it to stay without interfering with the new driver.
Tom Rix [Sat, 2 Jul 2022 15:39:04 +0000 (11:39 -0400)]
drm/nouveau/bios: set info only when the return is not 0
clang static analysis reports
drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c:68:17: warning: The right operand of '*' is a garbage value [core.UndefinedBinaryOperatorResult]
switch (!!data * *ver) {
^ ~~~~
A switch statement with only a default should be reduced to an if.
If nvbios_pmuEp() returns 0, via the data variable, the output info parameter
is not used. So set info only when data is not 0.
The struct nvbios_pmuE only has the type and data elements. Since both of these
are explicitly set, memset is not needed. So remove it.
drm: Use size_t type for len variable in drm_copy_field()
The strlen() function returns a size_t which is an unsigned int on 32-bit
arches and an unsigned long on 64-bit arches. But in the drm_copy_field()
function, the strlen() return value is assigned to an 'int len' variable.
Later, the len variable is passed as copy_from_user() third argument that
is an unsigned long parameter as well.
In theory, this can lead to an integer overflow via type conversion. Since
the assignment happens to a signed int lvalue instead of a size_t lvalue.
In practice though, that's unlikely since the values copied are set by DRM
drivers and not controlled by userspace. But using a size_t for len is the
correct thing to do anyways.
Maxime Ripard [Mon, 11 Jul 2022 17:39:38 +0000 (19:39 +0200)]
drm/vc4: v3d: Rework the runtime_pm setup
At bind time, vc4_v3d_bind() will read a register to retrieve the v3d
version and make sure it's a version we're compatible with.
However, the v3d has an optional clock that is enabled only after the
register read-out and a power domain that wasn't enabled at all in the bind
implementation. This was working fine at boot because both were enabled,
but resulted in the version check failing if we were unbinding and
rebinding the driver because the unbinding would have turned them off.
The fix isn't as easy as calling pm_runtime_resume_and_get() prior to the
register access to power up the power domain though.
Indeed, the runtime_resume implementation will enable the clock mentioned
above, call vc4_v3d_init_hw() and then vc4_irq_enable().
Prior to the previous patch, vc4_irq_enable() needed to occur after our
call to platform_get_irq() and vc4_irq_install(), since vc4_irq_enable()
used to call enable_irq() and vc4_irq_install() will call request_irq().
vc4_irq_install() will also do some register access, so needs the power
domain to be on. So we ended up in a situation where
vc4_v3d_runtime_resume() needed vc4_irq_install() to have been called
before, and vc4_irq_install() needed vc4_v3d_runtime_resume().
The previous patch removed the enable_irq() call in vc4_irq_enable() and
thus removed the dependency of vc4_v3d_runtime_resume() on
vc4_irq_install().
Thus, we can now rework our bind implementation to call
pm_runtime_resume_and_get() before our register access to make sure the
power domain is on. vc4_v3d_runtime_resume() also takes care of turning the
clock on and calling vc4_v3d_init_hw() so we can remove them from bind.
Maxime Ripard [Mon, 11 Jul 2022 17:39:37 +0000 (19:39 +0200)]
drm/vc4: v3d: Stop disabling interrupts
The vc4_irq_disable(), among other things, will call disable_irq() to
complete any in-flight interrupts.
This requires its counterpart, vc4_irq_enable(), to call enable_irq() which
causes issues addressed in a later patch.
However, vc4_irq_disable() is called by two callees: vc4_irq_uninstall()
and vc4_v3d_runtime_suspend().
vc4_irq_uninstall() also calls free_irq() which already disables the
interrupt line. We thus don't require an explicit disable_irq() for that
call site.
vc4_v3d_runtime_suspend() doesn't have any other code. However, the rest of
vc4_irq_disable() masks the interrupts coming from the v3d, so explictly
disabling the interrupt line is also redundant.
The only thing we really care about is thus to make sure we don't have any
handler in-flight, as suggested by the comment. We can thus replace
disable_irq() by synchronize_irq().
Maxime Ripard [Mon, 11 Jul 2022 17:39:34 +0000 (19:39 +0200)]
drm/vc4: debugfs: Simplify debugfs registration
The vc4 has a custom API to allow components to register a debugfs file
before the DRM driver has been registered and the debugfs_init hook has
been called.
However, the .late_register hook allows to have the debugfs file creation
deferred after that time already.
Let's remove our custom code to only register later our debugfs entries as
part of either debugfs_init or after it.
Maxime Ripard [Mon, 11 Jul 2022 17:39:32 +0000 (19:39 +0200)]
drm/vc4: debugfs: Protect device resources
Our current code now mixes some resources whose lifetime are tied to the
device (clocks, IO mappings, etc.) and some that are tied to the DRM device
(encoder, bridge).
The device one will be freed at unbind time, but the DRM one will only be
freed when the last user of the DRM device closes its file handle.
So we end up with a time window during which we can call the encoder hooks,
but we don't have access to the underlying resources and device.
Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so
that we bail out if we are during that window.
Maxime Ripard [Mon, 11 Jul 2022 17:39:30 +0000 (19:39 +0200)]
drm/vc4: vec: Protect device resources after removal
Whenever the device and driver are unbound, the main device and all the
subdevices will be removed by calling their unbind() method.
However, the DRM device itself will only be freed when the last user will
have closed it.
It means that there is a time window where the device and its resources
aren't there anymore, but the userspace can still call into our driver.
Fortunately, the DRM framework provides the drm_dev_enter() and
drm_dev_exit() functions to make sure our underlying device is still there
for the section protected by those calls. Let's add them to the VEC driver.
Maxime Ripard [Mon, 11 Jul 2022 17:39:29 +0000 (19:39 +0200)]
drm/vc4: vec: Switch to DRM-managed connector initialization
The current code will call drm_connector_unregister() and
drm_connector_cleanup() when the device is unbound. However, by then, there
might still be some references held to that connector, including by the
userspace that might still have the DRM device open.
Let's switch to a DRM-managed initialization to clean up after ourselves
only once the DRM device has been last closed.
Maxime Ripard [Mon, 11 Jul 2022 17:39:28 +0000 (19:39 +0200)]
drm/vc4: vec: Switch to DRM-managed encoder initialization
The current code will call drm_encoder_cleanup() when the device is
unbound. However, by then, there might still be some references held to
that encoder, including by the userspace that might still have the DRM
device open.
Let's switch to a DRM-managed initialization to clean up after ourselves
only once the DRM device has been last closed.
Maxime Ripard [Mon, 11 Jul 2022 17:39:27 +0000 (19:39 +0200)]
drm/vc4: vec: Remove call to drm_connector_unregister()
drm_connector_unregister() is only to be used for connectors that have been
registered through drm_connector_register() after drm_dev_register() has
been called. This is our case here so let's remove the call.
Maxime Ripard [Mon, 11 Jul 2022 17:39:26 +0000 (19:39 +0200)]
drm/vc4: vec: Switch to drmm_kzalloc
Our internal structure that stores the DRM entities structure is allocated
through a device-managed kzalloc.
This means that this will eventually be freed whenever the device is
removed. In our case, the most likely source of removal is that the main
device is going to be unbound, and component_unbind_all() is being run.
However, it occurs while the DRM device is still registered, which will
create dangling pointers, eventually resulting in use-after-free.
Switch to a DRM-managed allocation to keep our structure until the DRM
driver doesn't need it anymore.
Maxime Ripard [Mon, 11 Jul 2022 17:39:25 +0000 (19:39 +0200)]
drm/vc4: vec: Embed DRM structures into the private structure
The VC4 VEC driver private structure contains only a pointer to the
encoder and connector it implements. This makes the overall structure
somewhat inconsistent with the rest of the driver, and complicates its
initialisation without any apparent gain.
Let's embed the drm_encoder structure (through the vc4_encoder one) and
drm_connector into struct vc4_vec to fix both issues.
Maxime Ripard [Mon, 11 Jul 2022 17:39:23 +0000 (19:39 +0200)]
drm/vc4: txp: Protect device resources
Our current code now mixes some resources whose lifetime are tied to the
device (clocks, IO mappings, etc.) and some that are tied to the DRM device
(encoder, bridge).
The device one will be freed at unbind time, but the DRM one will only be
freed when the last user of the DRM device closes its file handle.
So we end up with a time window during which we can call the encoder hooks,
but we don't have access to the underlying resources and device.
Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so
that we bail out if we are during that window.
Maxime Ripard [Mon, 11 Jul 2022 17:39:22 +0000 (19:39 +0200)]
drm/vc4: txp: Remove call to drm_connector_unregister()
drm_connector_unregister() is only to be used for connectors that have been
registered through drm_connector_register() after drm_dev_register() has
been called. This is our case here so let's remove the call.
Maxime Ripard [Mon, 11 Jul 2022 17:39:21 +0000 (19:39 +0200)]
drm/vc4: txp: Switch to drmm_kzalloc
Our internal structure that stores the DRM entities structure is allocated
through a device-managed kzalloc.
This means that this will eventually be freed whenever the device is
removed. In our case, the most likely source of removal is that the main
device is going to be unbound, and component_unbind_all() is being run.
However, it occurs while the DRM device is still registered, which will
create dangling pointers, eventually resulting in use-after-free.
Switch to a DRM-managed allocation to keep our structure until the DRM
driver doesn't need it anymore.
Maxime Ripard [Mon, 11 Jul 2022 17:39:17 +0000 (19:39 +0200)]
drm/vc4: hdmi: Protect device resources after removal
Whenever the device and driver are unbound, the main device and all the
subdevices will be removed by calling their unbind() method.
However, the DRM device itself will only be freed when the last user will
have closed it.
It means that there is a time window where the device and its resources
aren't there anymore, but the userspace can still call into our driver.
Fortunately, the DRM framework provides the drm_dev_enter() and
drm_dev_exit() functions to make sure our underlying device is still there
for the section protected by those calls. Let's add them to the HDMI driver.
Maxime Ripard [Mon, 11 Jul 2022 17:39:16 +0000 (19:39 +0200)]
drm/vc4: hdmi: Move audio structure offset checks
The HDMI driver unbind hook doesn't have any ALSA-related code anymore, so
let's move the ALSA sanity checks and comments we have to some other part
of the driver dedicated to ALSA.
Maxime Ripard [Mon, 11 Jul 2022 17:39:15 +0000 (19:39 +0200)]
drm/vc4: hdmi: Use devm to register hotplug interrupts
Commit 776efe800fed ("drm/vc4: hdmi: Drop devm interrupt handler for
hotplug interrupts") dropped the device-managed interrupt registration
because it was creating bugs and races whenever an interrupt was coming in
while the device was removed.
However, our latest patches to the HDMI controller driver fix this as well,
so we can use device-managed interrupt handlers again.
Maxime Ripard [Mon, 11 Jul 2022 17:39:14 +0000 (19:39 +0200)]
drm/vc4: hdmi: Switch to DRM-managed kfree to build regsets
The current code to build the registers set later exposed in debugfs for
the HDMI controller relies on traditional allocations, that are later
free'd as part of the driver unbind hook.
Since krealloc doesn't have a DRM-managed equivalent, let's add an action
to free the buffer later on.
Maxime Ripard [Mon, 11 Jul 2022 17:39:12 +0000 (19:39 +0200)]
drm/vc4: hdmi: Switch to device-managed CEC initialization
The current code to unregister our CEC device needs to be undone manually
when we remove the HDMI driver.
Since the CEC framework will allocate its main structure, and will defer
its deallocation to when the last user will have closed it, we don't really
need to take any particular measure to prevent any use-after-free and can
thus use any managed action.
Maxime Ripard [Mon, 11 Jul 2022 17:39:11 +0000 (19:39 +0200)]
drm/vc4: hdmi: Switch to device-managed ALSA initialization
The current code to unregister our ALSA device needs to be undone manually
when we remove the HDMI driver.
Since ALSA doesn't seem to support any mechanism to defer freeing something
until the last user of the ALSA device is gone, we can either use a
device-managed or a DRM-managed action.
The consistent way would be to use a DRM-managed one, just like pretty much
any framework-facing structure should be doing. However, ALSA does a lot of
allocation and registration using device-managed calls. Thus, if we're
going that way, by the time the DRM-managed action would run all of those
allocation would have been freed and we would end up with a use-after-free.
Thus, let's do a device-managed action. It's been tested with KASAN enabled
and doesn't seem to trigger any issue, so it's as good as anything.
Maxime Ripard [Mon, 11 Jul 2022 17:39:10 +0000 (19:39 +0200)]
drm/vc4: hdmi: Switch to DRM-managed connector initialization
The current code will call drm_connector_unregister() and
drm_connector_cleanup() when the device is unbound. However, by then, there
might still be some references held to that connector, including by the
userspace that might still have the DRM device open.
Let's switch to a DRM-managed initialization to clean up after ourselves
only once the DRM device has been last closed.