RE: [PATCH 1/2] Enable buddy memory manager support
[AMD Public Use] Hi Christian, > And where is the patch to switch i915 and remove the Intel copy of this? Creating a patch for the switch. > In general I think that every public function here needs a kerneldoc > description what it is all about. Making a kernel doc description for each public function Thanks, Arun -Original Message- From: Koenig, Christian Sent: Wednesday, September 22, 2021 12:28 PM To: Paneer Selvam, Arunpravin ; dri-devel@lists.freedesktop.org; intel-...@lists.freedesktop.org; amd-...@lists.freedesktop.org; matthew.a...@intel.com; dan...@ffwll.ch; Deucher, Alexander Subject: Re: [PATCH 1/2] Enable buddy memory manager support Am 20.09.21 um 21:20 schrieb Arunpravin: > Port Intel buddy system manager to drm root folder Add CPU > mappable/non-mappable region support to the drm buddy manager And where is the patch to switch i915 and remove the Intel copy of this? In general I think that every public function here needs a kerneldoc description what it is all about. Regards, Christian. > > Signed-off-by: Arunpravin > --- > drivers/gpu/drm/Makefile| 2 +- > drivers/gpu/drm/drm_buddy.c | 465 > include/drm/drm_buddy.h | 154 > 3 files changed, 620 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/drm_buddy.c > create mode 100644 include/drm/drm_buddy.h > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index > a118692a6df7..fe1a2fc09675 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -18,7 +18,7 @@ drm-y := drm_aperture.o drm_auth.o drm_cache.o \ > drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ > drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \ > drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \ > - drm_managed.o drm_vblank_work.o > + drm_managed.o drm_vblank_work.o drm_buddy.o > > drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o > drm_dma.o \ > drm_legacy_misc.o drm_lock.o drm_memory.o > drm_scatter.o \ > diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c > new file mode 100644 index ..f07919a004b6 > --- /dev/null > +++ b/drivers/gpu/drm/drm_buddy.c > @@ -0,0 +1,465 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright 2021 Intel Corporation */ > + > +#include > +#include > + > +static struct drm_buddy_block *drm_block_alloc(struct drm_buddy_mm *mm, > + struct drm_buddy_block *parent, unsigned int order, > + u64 offset) > +{ > + struct drm_buddy_block *block; > + > + BUG_ON(order > DRM_BUDDY_MAX_ORDER); > + > + block = kmem_cache_zalloc(mm->slab_blocks, GFP_KERNEL); > + if (!block) > + return NULL; > + > + block->header = offset; > + block->header |= order; > + block->parent = parent; > + block->start = offset >> PAGE_SHIFT; > + block->size = (mm->chunk_size << order) >> PAGE_SHIFT; > + > + BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED); > + return block; > +} > + > +static void drm_block_free(struct drm_buddy_mm *mm, struct > +drm_buddy_block *block) { > + kmem_cache_free(mm->slab_blocks, block); } > + > +static void add_ordered(struct drm_buddy_mm *mm, struct > +drm_buddy_block *block) { > + struct drm_buddy_block *node; > + > + if (list_empty(>free_list[drm_buddy_block_order(block)])) { > + list_add(>link, > + >free_list[drm_buddy_block_order(block)]); > + return; > + } > + > + list_for_each_entry(node, >free_list[drm_buddy_block_order(block)], > link) > + if (block->start > node->start) > + break; > + > + __list_add(>link, node->link.prev, >link); } > + > +static void mark_allocated(struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_ALLOCATED; > + > + list_del(>link); > +} > + > +static void mark_free(struct drm_buddy_mm *mm, > + struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_FREE; > + > + add_ordered(mm, block); > +} > + > +static void mark_split(struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_SPLIT; > + > + list_del(>link); > +} > + > +int drm_buddy_init(struct drm_buddy_mm *mm, u64 size, u64 chunk_size) > +{ > + unsigned int i; > + u64 offset; > + > + if (size < chunk_size) > + return -EINVAL; > + > + if (chunk_size < PAGE_SIZE) > + return -EINVAL; > + > + if (!is_power_of_2(chunk_size)) > + return -EINVAL; > + > + size = round_down(size, chunk_size); > + > + mm->size = size; > + mm->chunk_size = chunk_size; > + mm->max_order =
Re: [PATCH v3 6/6] drm/ingenic: Attach bridge chain to encoders
Hi Paul, thanks for another update. We have been delayed to rework the CI20 HDMI code on top of your series but it basically works in some situations. There is for example a problem if the EDID reports DRM_COLOR_FORMAT_YCRCB422 but it appears to be outside of your series. The only issue we have is described below. > Am 22.09.2021 um 22:55 schrieb Paul Cercueil : > > Attach a top-level bridge to each encoder, which will be used for > negociating the bus format and flags. > > All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +-- > 1 file changed, 70 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > index a5e2880e07a1..a05a9fa6e115 100644 > --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -108,6 +109,19 @@ struct ingenic_drm { > struct drm_private_obj private_obj; > }; > > +struct ingenic_drm_bridge { > + struct drm_encoder encoder; > + struct drm_bridge bridge, *next_bridge; > + > + struct drm_bus_cfg bus_cfg; > +}; > + > +static inline struct ingenic_drm_bridge * > +to_ingenic_drm_bridge(struct drm_encoder *encoder) > +{ > + return container_of(encoder, struct ingenic_drm_bridge, encoder); > +} > + > static inline struct ingenic_drm_private_state * > to_ingenic_drm_priv_state(struct drm_private_state *state) > { > @@ -668,11 +682,10 @@ static void ingenic_drm_encoder_atomic_mode_set(struct > drm_encoder *encoder, > { > struct ingenic_drm *priv = drm_device_get_priv(encoder->dev); > struct drm_display_mode *mode = _state->adjusted_mode; > - struct drm_connector *conn = conn_state->connector; > - struct drm_display_info *info = >display_info; > + struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder); > unsigned int cfg, rgbcfg = 0; > > - priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; > + priv->panel_is_sharp = bridge->bus_cfg.flags & > DRM_BUS_FLAG_SHARP_SIGNALS; > > if (priv->panel_is_sharp) { > cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; > @@ -685,19 +698,19 @@ static void ingenic_drm_encoder_atomic_mode_set(struct > drm_encoder *encoder, > cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; > if (mode->flags & DRM_MODE_FLAG_NVSYNC) > cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; > - if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) > + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW) > cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; > - if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) > + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) > cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; > > if (!priv->panel_is_sharp) { > - if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { > + if (conn_state->connector->connector_type == > DRM_MODE_CONNECTOR_TV) { > if (mode->flags & DRM_MODE_FLAG_INTERLACE) > cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; > else > cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; > } else { > - switch (*info->bus_formats) { > + switch (bridge->bus_cfg.format) { > case MEDIA_BUS_FMT_RGB565_1X16: > cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; > break; > @@ -723,20 +736,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct > drm_encoder *encoder, > regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg); > } > > -static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, > - struct drm_crtc_state *crtc_state, > - struct drm_connector_state > *conn_state) > +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge, > + enum drm_bridge_attach_flags flags) > +{ > + struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); > + > + return drm_bridge_attach(bridge->encoder, ib->next_bridge, > + >bridge, flags); > +} > + > +static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge, > +struct drm_bridge_state > *bridge_state, > +struct drm_crtc_state *crtc_state, > +struct drm_connector_state > *conn_state) > { > - struct drm_display_info *info = _state->connector->display_info; > struct drm_display_mode *mode = _state->adjusted_mode; > + struct ingenic_drm_bridge *ib =
RE: [PATCH 1/2] Enable buddy memory manager support
[AMD Public Use] Hi Alex, I will fix the name and send a document in my next version. Thanks, Arun -Original Message- From: Alex Deucher Sent: Tuesday, September 21, 2021 12:54 AM To: Paneer Selvam, Arunpravin Cc: Maling list - DRI developers ; Intel Graphics Development ; amd-gfx list ; Koenig, Christian ; Matthew Auld ; Daniel Vetter ; Deucher, Alexander Subject: Re: [PATCH 1/2] Enable buddy memory manager support On Mon, Sep 20, 2021 at 3:21 PM Arunpravin wrote: Please prefix the patch subject with drm. E.g., drm: Enable buddy memory manager support Same for the second patch, but make it drm/amdgpu instead. Alex > > Port Intel buddy system manager to drm root folder Add CPU > mappable/non-mappable region support to the drm buddy manager > > Signed-off-by: Arunpravin > --- > drivers/gpu/drm/Makefile| 2 +- > drivers/gpu/drm/drm_buddy.c | 465 > include/drm/drm_buddy.h | 154 > 3 files changed, 620 insertions(+), 1 deletion(-) create mode 100644 > drivers/gpu/drm/drm_buddy.c create mode 100644 > include/drm/drm_buddy.h > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index > a118692a6df7..fe1a2fc09675 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -18,7 +18,7 @@ drm-y :=drm_aperture.o drm_auth.o drm_cache.o > \ > drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ > drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \ > drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \ > - drm_managed.o drm_vblank_work.o > + drm_managed.o drm_vblank_work.o drm_buddy.o > > drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o > drm_dma.o \ > drm_legacy_misc.o drm_lock.o drm_memory.o > drm_scatter.o \ diff --git a/drivers/gpu/drm/drm_buddy.c > b/drivers/gpu/drm/drm_buddy.c new file mode 100644 index > ..f07919a004b6 > --- /dev/null > +++ b/drivers/gpu/drm/drm_buddy.c > @@ -0,0 +1,465 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright 2021 Intel Corporation */ > + > +#include > +#include > + > +static struct drm_buddy_block *drm_block_alloc(struct drm_buddy_mm *mm, > + struct drm_buddy_block *parent, unsigned int order, > + u64 offset) > +{ > + struct drm_buddy_block *block; > + > + BUG_ON(order > DRM_BUDDY_MAX_ORDER); > + > + block = kmem_cache_zalloc(mm->slab_blocks, GFP_KERNEL); > + if (!block) > + return NULL; > + > + block->header = offset; > + block->header |= order; > + block->parent = parent; > + block->start = offset >> PAGE_SHIFT; > + block->size = (mm->chunk_size << order) >> PAGE_SHIFT; > + > + BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED); > + return block; > +} > + > +static void drm_block_free(struct drm_buddy_mm *mm, struct > +drm_buddy_block *block) { > + kmem_cache_free(mm->slab_blocks, block); } > + > +static void add_ordered(struct drm_buddy_mm *mm, struct > +drm_buddy_block *block) { > + struct drm_buddy_block *node; > + > + if (list_empty(>free_list[drm_buddy_block_order(block)])) { > + list_add(>link, > + >free_list[drm_buddy_block_order(block)]); > + return; > + } > + > + list_for_each_entry(node, > >free_list[drm_buddy_block_order(block)], link) > + if (block->start > node->start) > + break; > + > + __list_add(>link, node->link.prev, >link); } > + > +static void mark_allocated(struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_ALLOCATED; > + > + list_del(>link); > +} > + > +static void mark_free(struct drm_buddy_mm *mm, > + struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_FREE; > + > + add_ordered(mm, block); > +} > + > +static void mark_split(struct drm_buddy_block *block) { > + block->header &= ~DRM_BUDDY_HEADER_STATE; > + block->header |= DRM_BUDDY_SPLIT; > + > + list_del(>link); > +} > + > +int drm_buddy_init(struct drm_buddy_mm *mm, u64 size, u64 chunk_size) > +{ > + unsigned int i; > + u64 offset; > + > + if (size < chunk_size) > + return -EINVAL; > + > + if (chunk_size < PAGE_SIZE) > + return -EINVAL; > + > + if (!is_power_of_2(chunk_size)) > + return -EINVAL; > + > + size = round_down(size, chunk_size); > + > + mm->size = size; > + mm->chunk_size = chunk_size; > + mm->max_order = ilog2(size) - ilog2(chunk_size); > + > + BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER); > + > + mm->slab_blocks = KMEM_CACHE(drm_buddy_block, > +
RE: [PATCH 2/2] Add drm buddy manager support to amdgpu driver
[AMD Public Use] Hi Christian, Thanks for the review, I will the send the next version fixing all issues. Regards, Arun -Original Message- From: Christian König Sent: Wednesday, September 22, 2021 12:18 PM To: Paneer Selvam, Arunpravin ; Koenig, Christian ; dri-devel@lists.freedesktop.org; intel-...@lists.freedesktop.org; amd-...@lists.freedesktop.org; matthew.a...@intel.com; dan...@ffwll.ch; Deucher, Alexander Subject: Re: [PATCH 2/2] Add drm buddy manager support to amdgpu driver Am 21.09.21 um 17:51 schrieb Paneer Selvam, Arunpravin: > [AMD Public Use] > > Hi Christian, > Please find my comments. A better mail client might be helpful for mailing list communication. I use Thunderbird, but Outlook with appropriate setting should do as well. > > Thanks, > Arun > -Original Message- > From: Koenig, Christian > Sent: Tuesday, September 21, 2021 2:34 PM > To: Paneer Selvam, Arunpravin ; > dri-devel@lists.freedesktop.org; intel-...@lists.freedesktop.org; > amd-...@lists.freedesktop.org; matthew.a...@intel.com; > dan...@ffwll.ch; Deucher, Alexander > Subject: Re: [PATCH 2/2] Add drm buddy manager support to amdgpu > driver > > Am 20.09.21 um 21:21 schrieb Arunpravin: > [SNIP] >> +struct list_head blocks; >> +}; >> + >> +static inline struct amdgpu_vram_mgr_node * >> +to_amdgpu_vram_mgr_node(struct ttm_resource *res) { >> +return container_of(container_of(res, struct ttm_range_mgr_node, base), >> +struct amdgpu_vram_mgr_node, tnode); } >> + > Maybe stuff that in a separate amdgpu_vram_mgr.h file together with all the > other defines for the vram manager. > > Arun - I thought about it, will create a new header file for vram > manager Maybe make that a separate patch before this one here. >> +if (mode == DRM_BUDDY_ALLOC_RANGE) { >> +r = drm_buddy_alloc_range(mm, >blocks, >> +(uint64_t)place->fpfn << PAGE_SHIFT, pages << >> PAGE_SHIFT); > That handling won't work. It's possible that you need contiguous memory in a > specific range. > > Arun - the existing default backend range handler allocates contiguous > nodes in power of 2 finding the MSB's of the any given size. We get linked > nodes (depends on the requested size) in continuous range of address. > Example, for the size 768 pages request, we get 512 + 256 range of continuous > address in 2 nodes. > > It works by passing the fpfn and the requested size, the backend handler > calculates the lpfn by adding fpfn + size = lpfn. > The drawback here are we are not handling the specific lpfn value (as > of now it is calculated using the fpfn + requested size) and not following > the pages_per_node rule. > > Please let me know if this won't work for all specific fpfn / lpfn > cases From your description that sounds like it won't work at all for any cases. See the fpfn/lpfn specifies the range of allocation. For the most common case that's either 0..visible_vram or 0..start_of_some_hw_limitation. When you always try to allocate the range from 0 you will quickly find that you clash with existing allocations. What you need to do in general is to have a drm_buddy_alloc() which is able to limit the returned page to the desired range fpfn..lpfn. >> + >> +do { >> +unsigned int order; >> + >> +order = fls(n_pages) - 1; >> +BUG_ON(order > mm->max_order); >> + >> +spin_lock(>lock); >> +block = drm_buddy_alloc(mm, order, >> bar_limit_enabled, >> + >> visible_pfn, mode); > That doesn't seem to make much sense either. The backend allocator should not > care about the BAR size nor the visible_pfn. > > Arun - we are sending the BAR limit enable information (in case of APU > or large BAR, we take different approach) and visible_pfn Information. > > In case of bar_limit_enabled is true, I thought visible_pfn required > for the backend allocator to compare with the block start address and > find the desired blocks for the TOP-DOWN and BOTTOM-UP approach (TOP-DOWN - > return blocks higher than the visible_pfn limit, BOTTOM-UP - return blocks > lower than the visible_pfn limit). > > In case of bar_limit_enabled is false, we just return the top ordered > blocks and bottom most blocks for the TOP-DOWN and BOTTOM-UP respectively > (suitable for APU and Large BAR case). > > Please let me know if we have other way to fix this problem That is the completely wrong approach. The backend must not care about the BAR configuration and visibility of the VRAM. What it should do instead is to take the fpfn..lpfn range into account and make sure that all allocated pages are in the desired range. BOTTOM-UP vs. TOP-DOWN then just optimizes the algorithm because we insert all freed up TOP-DOWN pages at the end and all BOTTOM-UP pages at the
Re: [Intel-gfx] [PATCH] drm/i915/guc/slpc: remove unneeded clflush calls
On Tue, Sep 21, 2021 at 04:06:00PM +0300, Ville Syrjälä wrote: On Mon, Sep 20, 2021 at 10:47:08PM -0700, Lucas De Marchi wrote: On Wed, Sep 15, 2021 at 12:29:12PM -0700, John Harrison wrote: >On 9/15/2021 12:24, Belgaumkar, Vinay wrote: >>On 9/14/2021 12:51 PM, Lucas De Marchi wrote: >>>The clflush calls here aren't doing anything since we are not writting >>>something and flushing the cache lines to be visible to GuC. Here the >>>intention seems to be to make sure whatever GuC has written is visible >>>to the CPU before we read them. However a clflush from the CPU side is >>>the wrong instruction to use. >Is there a right instruction to use? Either we need to verify that no how can there be a right instruction? If the GuC needs to flush, then the GuC needs to do it, nothing to be done by the CPU. Flushing the CPU cache line here is doing nothing to guarantee that what was written by GuC hit the memory and we are reading it. Not sure why it was actually added, but since it was added by Vinay and he reviewed this patch, I'm assuming he also agrees clflush == writeback + invalidate. The invalidate is the important part when the CPU has to read something written by something else that's not cache coherent. Although the invalidate would be the important part, how would that work if there is still a flush? Wouldn't we be overriding whatever was written by the other side? Or are we using the fact that we shouldn't be writting to this cacheline so we know it's not dirty? Now, I have no idea if the guc has its own (CPU invisible) caches or not. If it does then it will need to trigger a writeback. But regardless, if the guc bypasses the CPU caches the CPU will need to invalidate before it reads anything in case it has stale data sitting in its cache. Indeed, thanks... but another case would be if caches are coherent through snoop. Do you know what is the cache architecture with GuC and CPU? Another question comes to mind, but first some context: I'm looking at this in order to support other archs besides x86... the only platforms in which this would be relevant would be on the discrete ones (I'm currently running an arm64 guest on qemu and using pci passthrough). I see that for dgfx intel_guc_allocate_vma() uses i915_gem_object_create_lmem() instead of i915_gem_object_create_shmem(). Would that make a difference? thanks Lucas De Marchi
Re: [RFC PATCH 3/4] rpmsg: Add support of AI Processor Unit (APU)
On Fri 17 Sep 07:59 CDT 2021, Alexandre Bailon wrote: > Some Mediatek SoC provides hardware accelerator for AI / ML. > This driver use the DRM driver to manage the shared memory, > and use rpmsg to execute jobs on the APU. > > Signed-off-by: Alexandre Bailon > --- > drivers/rpmsg/Kconfig | 10 +++ > drivers/rpmsg/Makefile| 1 + > drivers/rpmsg/apu_rpmsg.c | 184 ++ > 3 files changed, 195 insertions(+) > create mode 100644 drivers/rpmsg/apu_rpmsg.c > > diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig > index 0b4407abdf138..fc1668f795004 100644 > --- a/drivers/rpmsg/Kconfig > +++ b/drivers/rpmsg/Kconfig > @@ -73,4 +73,14 @@ config RPMSG_VIRTIO > select RPMSG_NS > select VIRTIO > > +config RPMSG_APU > + tristate "APU RPMSG driver" > + select REMOTEPROC > + select RPMSG_VIRTIO > + select DRM_APU > + help > + This provides a RPMSG driver that provides some facilities to > + communicate with an accelerated processing unit (APU). > + This Uses the APU DRM driver to manage memory and job scheduling. Similar to how a driver for e.g. an I2C device doesn't live in drivers/i2c, this doesn't belong in drivers/rpmsg. Probably rather directly in the DRM driver. > + > endmenu > diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile > index 8d452656f0ee3..8b336b9a817c1 100644 > --- a/drivers/rpmsg/Makefile > +++ b/drivers/rpmsg/Makefile > @@ -9,3 +9,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o > obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o > obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o > obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o > +obj-$(CONFIG_RPMSG_APU) += apu_rpmsg.o > diff --git a/drivers/rpmsg/apu_rpmsg.c b/drivers/rpmsg/apu_rpmsg.c > new file mode 100644 > index 0..7e504bd176a4d > --- /dev/null > +++ b/drivers/rpmsg/apu_rpmsg.c > @@ -0,0 +1,184 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright 2020 BayLibre SAS > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include "rpmsg_internal.h" > + > +#define APU_RPMSG_SERVICE_MT8183 "rpmsg-mt8183-apu0" > + > +struct rpmsg_apu { > + struct apu_core *core; > + struct rpmsg_device *rpdev; > +}; > + > +static int apu_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int > count, > + void *priv, u32 addr) > +{ > + struct rpmsg_apu *apu = dev_get_drvdata(>dev); > + struct apu_core *apu_core = apu->core; > + > + return apu_drm_callback(apu_core, data, count); > +} > + > +static int apu_rpmsg_send(struct apu_core *apu_core, void *data, int len) > +{ > + struct rpmsg_apu *apu = apu_drm_priv(apu_core); > + struct rpmsg_device *rpdev = apu->rpdev; > + > + return rpmsg_send(rpdev->ept, data, len); The rpmsg API is exposed outside drivers/rpmsg, so as I said above, just implement this directly in your driver, no need to lug around a dummy wrapper for things like this. > +} > + > +static struct apu_drm_ops apu_rpmsg_ops = { > + .send = apu_rpmsg_send, > +}; > + > +static int apu_init_iovad(struct rproc *rproc, struct rpmsg_apu *apu) > +{ > + struct resource_table *table; > + struct fw_rsc_carveout *rsc; > + int i; > + > + if (!rproc->table_ptr) { > + dev_err(>rpdev->dev, > + "No resource_table: has the firmware been loaded ?\n"); > + return -ENODEV; > + } > + > + table = rproc->table_ptr; > + for (i = 0; i < table->num; i++) { > + int offset = table->offset[i]; > + struct fw_rsc_hdr *hdr = (void *)table + offset; > + > + if (hdr->type != RSC_CARVEOUT) > + continue; > + > + rsc = (void *)hdr + sizeof(*hdr); > + if (apu_drm_reserve_iova(apu->core, rsc->da, rsc->len)) { > + dev_err(>rpdev->dev, > + "failed to reserve iova\n"); > + return -ENOMEM; > + } > + } > + > + return 0; > +} > + > +static struct rproc *apu_get_rproc(struct rpmsg_device *rpdev) > +{ > + /* > + * To work, the APU RPMsg driver need to get the rproc device. > + * Currently, we only use virtio so we could use that to find the > + * remoteproc parent. > + */ > + if (!rpdev->dev.parent && rpdev->dev.parent->bus) { > + dev_err(>dev, "invalid rpmsg device\n"); > + return ERR_PTR(-EINVAL); > + } > + > + if (strcmp(rpdev->dev.parent->bus->name, "virtio")) { > + dev_err(>dev, "unsupported bus\n"); > + return ERR_PTR(-EINVAL); > + } > + > + return vdev_to_rproc(dev_to_virtio(rpdev->dev.parent)); > +} > + > +static int apu_rpmsg_probe(struct rpmsg_device *rpdev) >
Re: [PATCH] vgaarb: Use ACPI HID name to find integrated GPU
On Sat, Sep 18, 2021 at 12:55 AM Bjorn Helgaas wrote: > > On Fri, Sep 17, 2021 at 11:49:45AM +0800, Kai-Heng Feng wrote: > > On Fri, Sep 17, 2021 at 12:38 AM Bjorn Helgaas wrote: > > > > > > [+cc Huacai, linux-pci] > > > > > > On Wed, May 19, 2021 at 09:57:23PM +0800, Kai-Heng Feng wrote: > > > > Commit 3d42f1ddc47a ("vgaarb: Keep adding VGA device in queue") assumes > > > > the first device is an integrated GPU. However, on AMD platforms an > > > > integrated GPU can have higher PCI device number than a discrete GPU. > > > > > > > > Integrated GPU on ACPI platform generally has _DOD and _DOS method, so > > > > use that as predicate to find integrated GPU. If the new strategy > > > > doesn't work, fallback to use the first device as boot VGA. > > > > > > > > Signed-off-by: Kai-Heng Feng > > > > --- > > > > drivers/gpu/vga/vgaarb.c | 31 ++- > > > > 1 file changed, 26 insertions(+), 5 deletions(-) > > > > > > > > diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c > > > > index 5180c5687ee5..949fde433ea2 100644 > > > > --- a/drivers/gpu/vga/vgaarb.c > > > > +++ b/drivers/gpu/vga/vgaarb.c > > > > @@ -50,6 +50,7 @@ > > > > #include > > > > #include > > > > #include > > > > +#include > > > > > > > > #include > > > > > > > > @@ -1450,9 +1451,23 @@ static struct miscdevice vga_arb_device = { > > > > MISC_DYNAMIC_MINOR, "vga_arbiter", _arb_device_fops > > > > }; > > > > > > > > +#if defined(CONFIG_ACPI) > > > > +static bool vga_arb_integrated_gpu(struct device *dev) > > > > +{ > > > > + struct acpi_device *adev = ACPI_COMPANION(dev); > > > > + > > > > + return adev && !strcmp(acpi_device_hid(adev), ACPI_VIDEO_HID); > > > > +} > > > > +#else > > > > +static bool vga_arb_integrated_gpu(struct device *dev) > > > > +{ > > > > + return false; > > > > +} > > > > +#endif > > > > + > > > > static void __init vga_arb_select_default_device(void) > > > > { > > > > - struct pci_dev *pdev; > > > > + struct pci_dev *pdev, *found = NULL; > > > > struct vga_device *vgadev; > > > > > > > > #if defined(CONFIG_X86) || defined(CONFIG_IA64) > > > > @@ -1505,20 +1520,26 @@ static void __init > > > > vga_arb_select_default_device(void) > > > > #endif > > > > > > > > if (!vga_default_device()) { > > > > - list_for_each_entry(vgadev, _list, list) { > > > > + list_for_each_entry_reverse(vgadev, _list, list) { > > > > > > Hi Kai-Heng, do you remember why you changed the order of this list > > > traversal? > > > > The descending order is to keep the original behavior. > > > > Before this patch, it breaks out of the loop as early as possible, so > > the lower numbered device is picked. > > This patch makes it only break out of the loop when ACPI_VIDEO_HID > > device is found. > > So if there are more than one device that meet "cmd & (PCI_COMMAND_IO > > | PCI_COMMAND_MEMORY)", higher numbered device will be selected. > > So the traverse order reversal is to keep the original behavior. > > Can you give an example of what you mean? I don't quite follow how it > keeps the original behavior. > > If we have this: > > 0 PCI_COMMAND_MEMORY set ACPI_VIDEO_HID > 1 PCI_COMMAND_MEMORY set ACPI_VIDEO_HID > > Previously we didn't look for ACPI_VIDEO_HID, so we chose 0, now we > choose 1, which seems wrong. In the absence of other information, I > would prefer the lower-numbered device. > > Or this: > > 0 PCI_COMMAND_MEMORY set > 1 PCI_COMMAND_MEMORY set ACPI_VIDEO_HID > > Previously we chose 0; now we choose 1, which does seem right, but > we'd choose 1 regardless of the order. > > Or this: > > 0 PCI_COMMAND_MEMORY set ACPI_VIDEO_HID > 1 PCI_COMMAND_MEMORY set > > Previously we chose 0, now we still choose 0, which seems right but > again doesn't depend on the order. > > The first case, where both devices are ACPI_VIDEO_HID, is the only one > where the order matters, and I suggest that we should be using the > original order, not the reversed order. Consider this: 0 PCI_COMMAND_MEMORY set 1 PCI_COMMAND_MEMORY set Originally device 0 will be picked. If the traverse order is kept, device 1 will be selected instead, because none of them pass vga_arb_integrated_gpu(). Kai-Heng > > > > I guess the list_add_tail() in vga_arbiter_add_pci_device() means > > > vga_list is generally ordered with small device numbers first and > > > large ones last. > > > > > > So you pick the integrated GPU with the largest device number. Are > > > there systems with more than one integrated GPU? If so, I would > > > naively expect that in the absence of an indication otherwise, we'd > > > want the one with the *smallest* device number. > > > > There's only one integrated GPU on the affected system. > > > > The approach is to keep the list traversal in one pass. > > Is there any regression introduce by this patch? > > If that's the case, we can separate the logic and find the > > ACPI_VIDEO_HID in second pass. > > No
Re: [Intel-gfx] [PATCH 15/27] drm/i915/guc: Implement multi-lrc submission
On Wed, Sep 22, 2021 at 01:15:46PM -0700, John Harrison wrote: > On 9/22/2021 09:25, Matthew Brost wrote: > > On Mon, Sep 20, 2021 at 02:48:52PM -0700, John Harrison wrote: > > > On 8/20/2021 15:44, Matthew Brost wrote: > > > > Implement multi-lrc submission via a single workqueue entry and single > > > > H2G. The workqueue entry contains an updated tail value for each > > > > request, of all the contexts in the multi-lrc submission, and updates > > > > these values simultaneously. As such, the tasklet and bypass path have > > > > been updated to coalesce requests into a single submission. > > > > > > > > Signed-off-by: Matthew Brost > > > > --- > > > >drivers/gpu/drm/i915/gt/uc/intel_guc.c| 21 ++ > > > >drivers/gpu/drm/i915/gt/uc/intel_guc.h| 8 + > > > >drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 24 +- > > > >drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 6 +- > > > >.../gpu/drm/i915/gt/uc/intel_guc_submission.c | 312 > > > > +++--- > > > >drivers/gpu/drm/i915/i915_request.h | 8 + > > > >6 files changed, 317 insertions(+), 62 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > > > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > > > index fbfcae727d7f..879aef662b2e 100644 > > > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > > > @@ -748,3 +748,24 @@ void intel_guc_load_status(struct intel_guc *guc, > > > > struct drm_printer *p) > > > > } > > > > } > > > >} > > > > + > > > > +void intel_guc_write_barrier(struct intel_guc *guc) > > > > +{ > > > > + struct intel_gt *gt = guc_to_gt(guc); > > > > + > > > > + if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { > > > > + GEM_BUG_ON(guc->send_regs.fw_domains); > > > Granted, this patch is just moving code from one file to another not > > > changing it. However, I think it would be worth adding a blank line in > > > here. > > > Otherwise the 'this register' comment below can be confusingly read as > > > referring to the send_regs.fw_domain entry above. > > > > > > And maybe add a comment why it is a bug for the send_regs value to be set? > > > I'm not seeing any obvious connection between it and the reset of this > > > code. > > > > > Can add a blank line. I think the GEM_BUG_ON relates to being able to > > use intel_uncore_write_fw vs intel_uncore_write. Can add comment. > > > > > > + /* > > > > +* This register is used by the i915 and GuC for MMIO > > > > based > > > > +* communication. Once we are in this code CTBs are the > > > > only > > > > +* method the i915 uses to communicate with the GuC so > > > > it is > > > > +* safe to write to this register (a value of 0 is NOP > > > > for MMIO > > > > +* communication). If we ever start mixing CTBs and > > > > MMIOs a new > > > > +* register will have to be chosen. > > > > +*/ > > > > + intel_uncore_write_fw(gt->uncore, > > > > GEN11_SOFT_SCRATCH(0), 0); > > > > + } else { > > > > + /* wmb() sufficient for a barrier if in smem */ > > > > + wmb(); > > > > + } > > > > +} > > > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > > > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > > > index 3f95b1b4f15c..0ead2406d03c 100644 > > > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > > > @@ -37,6 +37,12 @@ struct intel_guc { > > > > /* Global engine used to submit requests to GuC */ > > > > struct i915_sched_engine *sched_engine; > > > > struct i915_request *stalled_request; > > > > + enum { > > > > + STALL_NONE, > > > > + STALL_REGISTER_CONTEXT, > > > > + STALL_MOVE_LRC_TAIL, > > > > + STALL_ADD_REQUEST, > > > > + } submission_stall_reason; > > > > /* intel_guc_recv interrupt related state */ > > > > spinlock_t irq_lock; > > > > @@ -332,4 +338,6 @@ void intel_guc_submission_cancel_requests(struct > > > > intel_guc *guc); > > > >void intel_guc_load_status(struct intel_guc *guc, struct drm_printer > > > > *p); > > > > +void intel_guc_write_barrier(struct intel_guc *guc); > > > > + > > > >#endif > > > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > > > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > > > index 20c710a74498..10d1878d2826 100644 > > > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > > > @@ -377,28 +377,6 @@ static u32 ct_get_next_fence(struct intel_guc_ct > > > > *ct) > > > > return ++ct->requests.last_fence; > > > >} > > > > -static void write_barrier(struct intel_guc_ct *ct) > > > > -{ > > > > - struct intel_guc *guc = ct_to_guc(ct); > > >
Re: [RFC PATCH 2/4] DRM: Add support of AI Processor Unit (APU)
On Sat, 18 Sept 2021 at 07:57, Alexandre Bailon wrote: > > Some Mediatek SoC provides hardware accelerator for AI / ML. > This driver provides the infrastructure to manage memory > shared between host CPU and the accelerator, and to submit > jobs to the accelerator. > The APU itself is managed by remoteproc so this drivers > relies on remoteproc to found the APU and get some important data > from it. But, the driver is quite generic and it should possible > to manage accelerator using another ways. > This driver doesn't manage itself the data transmitions. > It must be registered by another driver implementing the transmitions. > > Signed-off-by: Alexandre Bailon > --- > drivers/gpu/drm/Kconfig| 2 + > drivers/gpu/drm/Makefile | 1 + > drivers/gpu/drm/apu/Kconfig| 10 + > drivers/gpu/drm/apu/Makefile | 7 + > drivers/gpu/drm/apu/apu_drm_drv.c | 238 +++ > drivers/gpu/drm/apu/apu_gem.c | 232 +++ > drivers/gpu/drm/apu/apu_internal.h | 89 > drivers/gpu/drm/apu/apu_sched.c| 634 + > include/drm/apu_drm.h | 59 +++ > include/uapi/drm/apu_drm.h | 106 + > 10 files changed, 1378 insertions(+) > create mode 100644 drivers/gpu/drm/apu/Kconfig > create mode 100644 drivers/gpu/drm/apu/Makefile > create mode 100644 drivers/gpu/drm/apu/apu_drm_drv.c > create mode 100644 drivers/gpu/drm/apu/apu_gem.c > create mode 100644 drivers/gpu/drm/apu/apu_internal.h > create mode 100644 drivers/gpu/drm/apu/apu_sched.c > create mode 100644 include/drm/apu_drm.h > create mode 100644 include/uapi/drm/apu_drm.h > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig > index 8fc40317f2b77..bcdca35c9eda5 100644 > --- a/drivers/gpu/drm/Kconfig > +++ b/drivers/gpu/drm/Kconfig > @@ -382,6 +382,8 @@ source "drivers/gpu/drm/xlnx/Kconfig" > > source "drivers/gpu/drm/gud/Kconfig" > > +source "drivers/gpu/drm/apu/Kconfig" > + > config DRM_HYPERV > tristate "DRM Support for Hyper-V synthetic video device" > depends on DRM && PCI && MMU && HYPERV > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > index ad11121548983..f3d8432976558 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -127,4 +127,5 @@ obj-$(CONFIG_DRM_MCDE) += mcde/ > obj-$(CONFIG_DRM_TIDSS) += tidss/ > obj-y += xlnx/ > obj-y += gud/ > +obj-$(CONFIG_DRM_APU) += apu/ > obj-$(CONFIG_DRM_HYPERV) += hyperv/ > diff --git a/drivers/gpu/drm/apu/Kconfig b/drivers/gpu/drm/apu/Kconfig > new file mode 100644 > index 0..c8471309a0351 > --- /dev/null > +++ b/drivers/gpu/drm/apu/Kconfig > @@ -0,0 +1,10 @@ > +# SPDX-License-Identifier: GPL-2.0-only > +# > + > +config DRM_APU > + tristate "APU (AI Processor Unit)" > + select REMOTEPROC > + select DRM_SCHED > + help > + This provides a DRM driver that provides some facilities to > + communicate with an accelerated processing unit (APU). > diff --git a/drivers/gpu/drm/apu/Makefile b/drivers/gpu/drm/apu/Makefile > new file mode 100644 > index 0..3e97846b091c9 > --- /dev/null > +++ b/drivers/gpu/drm/apu/Makefile > @@ -0,0 +1,7 @@ > +# SPDX-License-Identifier: GPL-2.0 > + > +apu_drm-y += apu_drm_drv.o > +apu_drm-y += apu_sched.o > +apu_drm-y += apu_gem.o > + > +obj-$(CONFIG_DRM_APU) += apu_drm.o > diff --git a/drivers/gpu/drm/apu/apu_drm_drv.c > b/drivers/gpu/drm/apu/apu_drm_drv.c > new file mode 100644 > index 0..91d8c99e373c0 > --- /dev/null > +++ b/drivers/gpu/drm/apu/apu_drm_drv.c > @@ -0,0 +1,238 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright 2020 BayLibre SAS > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > + > +#include > + > +#include "apu_internal.h" > + > +static LIST_HEAD(apu_devices); > + > +static const struct drm_ioctl_desc ioctls[] = { > + DRM_IOCTL_DEF_DRV(APU_GEM_NEW, ioctl_gem_new, > + DRM_RENDER_ALLOW), > + DRM_IOCTL_DEF_DRV(APU_GEM_QUEUE, ioctl_gem_queue, > + DRM_RENDER_ALLOW), > + DRM_IOCTL_DEF_DRV(APU_GEM_DEQUEUE, ioctl_gem_dequeue, > + DRM_RENDER_ALLOW), > + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_MAP, ioctl_gem_iommu_map, > + DRM_RENDER_ALLOW), > + DRM_IOCTL_DEF_DRV(APU_GEM_IOMMU_UNMAP, ioctl_gem_iommu_unmap, > + DRM_RENDER_ALLOW), > + DRM_IOCTL_DEF_DRV(APU_STATE, ioctl_apu_state, > + DRM_RENDER_ALLOW), > +}; > + > +DEFINE_DRM_GEM_CMA_FOPS(apu_drm_ops); > + > +static struct drm_driver apu_drm_driver = { > + .driver_features = DRIVER_GEM | DRIVER_SYNCOBJ, > + .name = "drm_apu", > + .desc = "APU DRM driver", > + .date = "20210319", > + .major = 1, > + .minor
Re: [PATCH v2 3/3] drm/bridge: ti-sn65dsi86: Add NO_CONNECTOR support
Hi Rob, Thank you for the patch. On Mon, Sep 20, 2021 at 03:58:00PM -0700, Rob Clark wrote: > From: Rob Clark > > Slightly awkward to fish out the display_info when we aren't creating > own connector. But I don't see an obvious better way. > > v2: Remove error return with NO_CONNECTOR flag > > Signed-off-by: Rob Clark > --- > drivers/gpu/drm/bridge/ti-sn65dsi86.c | 39 --- > 1 file changed, 29 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > index 6154bed0af5b..94c94cc8a4d8 100644 > --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > @@ -667,11 +667,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, > .node = NULL, >}; > > - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { > - DRM_ERROR("Fix bridge driver to make connector optional!"); > - return -EINVAL; > - } > - > pdata->aux.drm_dev = bridge->dev; > ret = drm_dp_aux_register(>aux); > if (ret < 0) { > @@ -679,9 +674,11 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, > return ret; > } > > - ret = ti_sn_bridge_connector_init(pdata); > - if (ret < 0) > - goto err_conn_init; > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { > + ret = ti_sn_bridge_connector_init(pdata); > + if (ret < 0) > + goto err_conn_init; > + } > > /* >* TODO: ideally finding host resource and dsi dev registration needs > @@ -743,7 +740,8 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, > err_dsi_attach: > mipi_dsi_device_unregister(dsi); > err_dsi_host: > - drm_connector_cleanup(>connector); > + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) > + drm_connector_cleanup(>connector); I wonder if we actually need this. The connector gets attached to the encoder, won't it be destroyed by the DRM core in the error path ? > err_conn_init: > drm_dp_aux_unregister(>aux); > return ret; > @@ -792,9 +790,30 @@ static void ti_sn_bridge_set_dsi_rate(struct > ti_sn65dsi86 *pdata) > regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); > } > > +/* > + * Find the connector and fish out the bpc from display_info. It would > + * be nice if we could get this instead from drm_bridge_state, but that > + * doesn't yet appear to be the case. You already have a bus format in the bridge state, from which you can derive the bpp. Could you give it a try ? > + */ > static unsigned int ti_sn_bridge_get_bpp(struct ti_sn65dsi86 *pdata) > { > - if (pdata->connector.display_info.bpc <= 6) > + struct drm_bridge *bridge = >bridge; > + struct drm_connector_list_iter conn_iter; > + struct drm_connector *connector; > + unsigned bpc = 0; > + > + drm_connector_list_iter_begin(bridge->dev, _iter); > + drm_for_each_connector_iter(connector, _iter) { > + if (drm_connector_has_possible_encoder(connector, > bridge->encoder)) { > + bpc = connector->display_info.bpc; > + break; > + } > + } > + drm_connector_list_iter_end(_iter); > + > + WARN_ON(bpc == 0); > + > + if (bpc <= 6) > return 18; > else > return 24; -- Regards, Laurent Pinchart
Re: [PATCH 4/4] drm/bridge: ti-sn65dsi86: Add NO_CONNECTOR support
Hi Rob and Doug, On Mon, Sep 20, 2021 at 11:32:02AM -0700, Rob Clark wrote: > On Thu, Aug 12, 2021 at 1:08 PM Doug Anderson wrote: > > On Thu, Aug 12, 2021 at 12:26 PM Laurent Pinchart wrote: > > > On Wed, Aug 11, 2021 at 04:52:50PM -0700, Rob Clark wrote: > > > > From: Rob Clark > > > > > > > > Slightly awkward to fish out the display_info when we aren't creating > > > > own connector. But I don't see an obvious better way. > > > > > > We need a bit more than this, to support the NO_CONNECTOR case, the > > > bridge has to implement a few extra operations, and set the bridge .ops > > > field. I've submitted two patches to do so a while ago: > > > > > > - [RFC PATCH 08/11] drm/bridge: ti-sn65dsi86: Implement bridge connector > > > operations ([1]) > > > > Rob asked me about this over IRC, so if he left it out and it's needed > > then it's my fault. However, I don't believe it's needed until your > > series making this bridge chip support full DP. For the the eDP case > > the bridge chip driver in ToT no longer queries the EDID itself. It > > simply provides an AUX bus to the panel driver and the panel driver > > queries the EDID. I think that means we don't need to add > > DRM_BRIDGE_OP_EDID, right? That's right. > > I was also wondering if in the full DP case we should actually model > > the physical DP jack as a drm_bridge and have it work the same way. It > > would get probed via the DP AUX bus just like a panel. I seem to > > remember Stephen Boyd was talking about modeling the DP connector as a > > drm_bridge because it would allow us to handle the fact that some TCPC > > chips could only support HBR2 whereas others could support HBR3. Maybe > > it would end up being a fairly elegant solution? Physical connectors are already handled as bridges, see drivers/gpu/drm/bridge/display-connector.c. I however don't think it should handle EDID retrieval, because that's really not an operation implemented by the connector itself. > > > - [RFC PATCH 09/11] drm/bridge: ti-sn65dsi86: Make connector creation > > > optional ([2]) > > > > > > The second patch is similar to the first half of this patch, but misses > > > the cleanup code. I'll try to rebase this and resubmit, but it may take > > > a bit of time. > > > > Whoops! You're right that Rob's patch won't work at all because we'll > > just hit the "Fix bridge driver to make connector optional!" case. I > > should have noticed that. :( > > Yes, indeed.. once I fix that, I get no display.. > > Not sure if Laurent is still working on his series, otherwise I can > try to figure out what bridge ops are missing I am, but too slowly. I don't mind fast-tracking the changes you need though. -- Regards, Laurent Pinchart
Re: [PATCH v3 6/6] drm: rcar-du: Add r8a779a0 device support
On 23/09/2021 00:59, Laurent Pinchart wrote: > Hi Kieran, > > Thank you for the patch. > > On Thu, Sep 23, 2021 at 12:47:26AM +0100, Kieran Bingham wrote: >> From: Kieran Bingham >> >> Extend the rcar_du_device_info structure and rcar_du_output enum to >> support DSI outputs and utilise these additions to provide support for >> the R8A779A0 V3U platform. >> >> While the DIDSR register field is now named "DSI/CSI-2-TX-IF0 Dot Clock >> Select" the existing define LVDS0 is used, and is directly compatible >> from other DU variants. > > That's not true anymore :-) The paragraph can simply be dropped. > Agreed. >> Signed-off-by: Kieran Bingham >> >> --- >> >> v3: >> - Introduce DIDSR_LDCS_DSI macro >> >> v2: >> - No longer requires a direct interface with the DSI encoder >> - Use correct field naming (LDCS) >> - Remove per-crtc clock feature. >> >> drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 ++ >> drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 >> drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ >> drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++ >> drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 + >> 5 files changed, 27 insertions(+) >> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h >> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h >> index 440e6b4fbb58..26e79b74898c 100644 >> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h >> @@ -96,6 +96,8 @@ struct rcar_du_crtc_state { >> enum rcar_du_output { >> RCAR_DU_OUTPUT_DPAD0, >> RCAR_DU_OUTPUT_DPAD1, >> +RCAR_DU_OUTPUT_DSI0, >> +RCAR_DU_OUTPUT_DSI1, >> RCAR_DU_OUTPUT_HDMI0, >> RCAR_DU_OUTPUT_HDMI1, >> RCAR_DU_OUTPUT_LVDS0, >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c >> b/drivers/gpu/drm/rcar-du/rcar_du_drv.c >> index 8a094d5b9c77..8b4c8851b6bc 100644 >> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c >> @@ -489,6 +489,25 @@ static const struct rcar_du_device_info >> rcar_du_r8a7799x_info = { >> .lvds_clk_mask = BIT(1) | BIT(0), >> }; >> >> +static const struct rcar_du_device_info rcar_du_r8a779a0_info = { >> +.gen = 3, >> +.features = RCAR_DU_FEATURE_CRTC_IRQ >> + | RCAR_DU_FEATURE_VSP1_SOURCE, >> +.channels_mask = BIT(1) | BIT(0), >> +.routes = { >> +/* R8A779A0 has two MIPI DSI outputs. */ >> +[RCAR_DU_OUTPUT_DSI0] = { >> +.possible_crtcs = BIT(0), >> +.port = 0, >> +}, >> +[RCAR_DU_OUTPUT_DSI1] = { >> +.possible_crtcs = BIT(1), >> +.port = 1, >> +}, >> +}, >> +.dsi_clk_mask = BIT(1) | BIT(0), >> +}; >> + >> static const struct of_device_id rcar_du_of_table[] = { >> { .compatible = "renesas,du-r8a7742", .data = _du_r8a7790_info }, >> { .compatible = "renesas,du-r8a7743", .data = _du_r8a7743_info }, >> @@ -513,6 +532,7 @@ static const struct of_device_id rcar_du_of_table[] = { >> { .compatible = "renesas,du-r8a77980", .data = _du_r8a77970_info }, >> { .compatible = "renesas,du-r8a77990", .data = _du_r8a7799x_info }, >> { .compatible = "renesas,du-r8a77995", .data = _du_r8a7799x_info }, >> +{ .compatible = "renesas,du-r8a779a0", .data = _du_r8a779a0_info }, >> { } >> }; >> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h >> b/drivers/gpu/drm/rcar-du/rcar_du_drv.h >> index 5fe9152454ff..cf98d43d72d0 100644 >> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h >> @@ -57,6 +57,7 @@ struct rcar_du_output_routing { >> * @routes: array of CRTC to output routes, indexed by output >> (RCAR_DU_OUTPUT_*) >> * @num_lvds: number of internal LVDS encoders >> * @dpll_mask: bit mask of DU channels equipped with a DPLL >> + * @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot >> clock >> * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot >> clock >> */ >> struct rcar_du_device_info { >> @@ -67,6 +68,7 @@ struct rcar_du_device_info { >> struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; >> unsigned int num_lvds; >> unsigned int dpll_mask; >> +unsigned int dsi_clk_mask; >> unsigned int lvds_clk_mask; >> }; >> >> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c >> b/drivers/gpu/drm/rcar-du/rcar_du_group.c >> index a984eef265d2..8665a1dd2186 100644 >> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c >> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c >> @@ -124,6 +124,8 @@ static void rcar_du_group_setup_didsr(struct >> rcar_du_group *rgrp) >> if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) >> didsr |= DIDSR_LDCS_LVDS0(i) >>| DIDSR_PDCS_CLK(i, 0); >> +else if (rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) >> +didsr |= DIDSR_LDCS_DSI(i); >> else >>
Re: [PATCH v2 2/3] drm/bridge: ti-sn65dsi86: Implement bridge->mode_valid()
Hi Rob, Thank you for the patch. On Mon, Sep 20, 2021 at 03:57:59PM -0700, Rob Clark wrote: > From: Rob Clark > > For the brave new world of bridges not creating their own connectors, we > need to implement the max clock limitation via bridge->mode_valid() > instead of connector->mode_valid(). > > v2: Drop unneeded connector->mode_valid() > > Signed-off-by: Rob Clark > Reviewed-by: Douglas Anderson Reviewed-by: Laurent Pinchart > --- > drivers/gpu/drm/bridge/ti-sn65dsi86.c | 25 + > 1 file changed, 13 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > index 41d48a393e7f..6154bed0af5b 100644 > --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > @@ -615,20 +615,8 @@ static int ti_sn_bridge_connector_get_modes(struct > drm_connector *connector) > return drm_bridge_get_modes(pdata->next_bridge, connector); > } > > -static enum drm_mode_status > -ti_sn_bridge_connector_mode_valid(struct drm_connector *connector, > - struct drm_display_mode *mode) > -{ > - /* maximum supported resolution is 4K at 60 fps */ > - if (mode->clock > 594000) > - return MODE_CLOCK_HIGH; > - > - return MODE_OK; > -} > - > static struct drm_connector_helper_funcs ti_sn_bridge_connector_helper_funcs > = { > .get_modes = ti_sn_bridge_connector_get_modes, > - .mode_valid = ti_sn_bridge_connector_mode_valid, > }; > > static const struct drm_connector_funcs ti_sn_bridge_connector_funcs = { > @@ -766,6 +754,18 @@ static void ti_sn_bridge_detach(struct drm_bridge > *bridge) > drm_dp_aux_unregister(_to_ti_sn65dsi86(bridge)->aux); > } > > +static enum drm_mode_status > +ti_sn_bridge_mode_valid(struct drm_bridge *bridge, > + const struct drm_display_info *info, > + const struct drm_display_mode *mode) > +{ > + /* maximum supported resolution is 4K at 60 fps */ > + if (mode->clock > 594000) > + return MODE_CLOCK_HIGH; > + > + return MODE_OK; > +} > + > static void ti_sn_bridge_disable(struct drm_bridge *bridge) > { > struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); > @@ -1127,6 +1127,7 @@ static void ti_sn_bridge_post_disable(struct drm_bridge > *bridge) > static const struct drm_bridge_funcs ti_sn_bridge_funcs = { > .attach = ti_sn_bridge_attach, > .detach = ti_sn_bridge_detach, > + .mode_valid = ti_sn_bridge_mode_valid, > .pre_enable = ti_sn_bridge_pre_enable, > .enable = ti_sn_bridge_enable, > .disable = ti_sn_bridge_disable, -- Regards, Laurent Pinchart
[PATCH] drm/i915/uncore: fwtable read handlers are now used on all forcewake platforms
With the recent refactor of the uncore mmio handling, all forcewake-based platforms (i.e., graphics version 6 and beyond) now use the 'fwtable' read handlers. Let's pull the assignment out of the per-platform if/else ladder to make this more obvious. Suggested-by: Tvrtko Ursulin Suggested-by: Lucas De Marchi Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/intel_uncore.c | 11 ++- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index c8e7c71f0896..678a99de07fe 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2088,49 +2088,42 @@ static int uncore_forcewake_init(struct intel_uncore *uncore) return ret; forcewake_early_sanitize(uncore, 0); + ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __dg2_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, dg2_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __xehp_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen12_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER(i915) >= 12) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen12_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen12_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER(i915) == 11) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen11_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen11_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (IS_GRAPHICS_VER(i915, 9, 10)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen9_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen8_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (IS_CHERRYVIEW(i915)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __chv_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen8_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER(i915) == 8) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen6_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen8_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (IS_VALLEYVIEW(i915)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __vlv_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen6); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } else if (IS_GRAPHICS_VER(i915, 6, 7)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen6_fw_ranges); ASSIGN_WRITE_MMIO_VFUNCS(uncore, gen6); - ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable); } uncore->pmic_bus_access_nb.notifier_call = i915_pmic_bus_access_notifier; -- 2.33.0
Re: [PATCH 1/3] drm/bridge: Add a function to abstract away panels
Hi Maxime, Thank you for the patch. I know this has already been merged, but I have a question. On Fri, Sep 10, 2021 at 03:09:39PM +0200, Maxime Ripard wrote: > Display drivers so far need to have a lot of boilerplate to first > retrieve either the panel or bridge that they are connected to using > drm_of_find_panel_or_bridge(), and then either deal with each with ad-hoc > functions or create a drm panel bridge through drm_panel_bridge_add. > > In order to reduce the boilerplate and hopefully create a path of least > resistance towards using the DRM panel bridge layer, let's create the > function devm_drm_of_get_next to reduce that boilerplate. > > Signed-off-by: Maxime Ripard > --- > drivers/gpu/drm/drm_bridge.c | 42 > drivers/gpu/drm/drm_of.c | 3 +++ > include/drm/drm_bridge.h | 2 ++ > 3 files changed, 43 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c > index a8ed66751c2d..10ddca4638b0 100644 > --- a/drivers/gpu/drm/drm_bridge.c > +++ b/drivers/gpu/drm/drm_bridge.c > @@ -28,6 +28,7 @@ > #include > #include > #include > +#include > #include > > #include "drm_crtc_internal.h" > @@ -51,10 +52,8 @@ > * > * Display drivers are responsible for linking encoders with the first bridge > * in the chains. This is done by acquiring the appropriate bridge with > - * of_drm_find_bridge() or drm_of_find_panel_or_bridge(), or creating it for > a > - * panel with drm_panel_bridge_add_typed() (or the managed version > - * devm_drm_panel_bridge_add_typed()). Once acquired, the bridge shall be > - * attached to the encoder with a call to drm_bridge_attach(). > + * devm_drm_of_get_bridge(). Once acquired, the bridge shall be attached to > the > + * encoder with a call to drm_bridge_attach(). > * > * Bridges are responsible for linking themselves with the next bridge in the > * chain, if any. This is done the same way as for encoders, with the call to > @@ -1233,6 +1232,41 @@ struct drm_bridge *of_drm_find_bridge(struct > device_node *np) > return NULL; > } > EXPORT_SYMBOL(of_drm_find_bridge); > + > +/** > + * devm_drm_of_get_bridge - Return next bridge in the chain > + * @dev: device to tie the bridge lifetime to > + * @np: device tree node containing encoder output ports > + * @port: port in the device tree node > + * @endpoint: endpoint in the device tree node > + * > + * Given a DT node's port and endpoint number, finds the connected node > + * and returns the associated bridge if any, or creates and returns a > + * drm panel bridge instance if a panel is connected. > + * > + * Returns a pointer to the bridge if successful, or an error pointer > + * otherwise. > + */ > +struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, > + struct device_node *np, > + unsigned int port, > + unsigned int endpoint) > +{ > + struct drm_bridge *bridge; > + struct drm_panel *panel; > + int ret; > + > + ret = drm_of_find_panel_or_bridge(np, port, endpoint, > + , ); > + if (ret) > + return ERR_PTR(ret); > + > + if (panel) > + bridge = devm_drm_panel_bridge_add(dev, panel); > + > + return bridge; I really like the idea, I've wanted to do something like this for a long time. I however wonder if this is the best approach, or if we could get the panel core to register the bridge itself. The part that bothers me here is the assymetry in the lifetime of the bridges, the returned pointer is either looked up or allocated. Bridge lifetime is such a mess that it may not make a big difference, but eventually we'll have to address that problem globally. > +} > +EXPORT_SYMBOL(devm_drm_of_get_bridge); > #endif > > MODULE_AUTHOR("Ajay Kumar "); > diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c > index 997b8827fed2..37c34146eea8 100644 > --- a/drivers/gpu/drm/drm_of.c > +++ b/drivers/gpu/drm/drm_of.c > @@ -231,6 +231,9 @@ EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); > * return either the associated struct drm_panel or drm_bridge device. Either > * @panel or @bridge must not be NULL. > * > + * This function is deprecated and should not be used in new drivers. Use > + * devm_drm_of_get_bridge() instead. > + * > * Returns zero if successful, or one of the standard error codes if it > fails. > */ > int drm_of_find_panel_or_bridge(const struct device_node *np, > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > index 46bdfa48c413..f70c88ca96ef 100644 > --- a/include/drm/drm_bridge.h > +++ b/include/drm/drm_bridge.h > @@ -911,6 +911,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct > device *dev, > struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, > struct drm_panel
Re: [PATCH v3 6/6] drm: rcar-du: Add r8a779a0 device support
Hi Kieran, Thank you for the patch. On Thu, Sep 23, 2021 at 12:47:26AM +0100, Kieran Bingham wrote: > From: Kieran Bingham > > Extend the rcar_du_device_info structure and rcar_du_output enum to > support DSI outputs and utilise these additions to provide support for > the R8A779A0 V3U platform. > > While the DIDSR register field is now named "DSI/CSI-2-TX-IF0 Dot Clock > Select" the existing define LVDS0 is used, and is directly compatible > from other DU variants. That's not true anymore :-) The paragraph can simply be dropped. > Signed-off-by: Kieran Bingham > > --- > > v3: > - Introduce DIDSR_LDCS_DSI macro > > v2: > - No longer requires a direct interface with the DSI encoder > - Use correct field naming (LDCS) > - Remove per-crtc clock feature. > > drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 ++ > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 > drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ > drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++ > drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 + > 5 files changed, 27 insertions(+) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > index 440e6b4fbb58..26e79b74898c 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > @@ -96,6 +96,8 @@ struct rcar_du_crtc_state { > enum rcar_du_output { > RCAR_DU_OUTPUT_DPAD0, > RCAR_DU_OUTPUT_DPAD1, > + RCAR_DU_OUTPUT_DSI0, > + RCAR_DU_OUTPUT_DSI1, > RCAR_DU_OUTPUT_HDMI0, > RCAR_DU_OUTPUT_HDMI1, > RCAR_DU_OUTPUT_LVDS0, > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > index 8a094d5b9c77..8b4c8851b6bc 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > @@ -489,6 +489,25 @@ static const struct rcar_du_device_info > rcar_du_r8a7799x_info = { > .lvds_clk_mask = BIT(1) | BIT(0), > }; > > +static const struct rcar_du_device_info rcar_du_r8a779a0_info = { > + .gen = 3, > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_VSP1_SOURCE, > + .channels_mask = BIT(1) | BIT(0), > + .routes = { > + /* R8A779A0 has two MIPI DSI outputs. */ > + [RCAR_DU_OUTPUT_DSI0] = { > + .possible_crtcs = BIT(0), > + .port = 0, > + }, > + [RCAR_DU_OUTPUT_DSI1] = { > + .possible_crtcs = BIT(1), > + .port = 1, > + }, > + }, > + .dsi_clk_mask = BIT(1) | BIT(0), > +}; > + > static const struct of_device_id rcar_du_of_table[] = { > { .compatible = "renesas,du-r8a7742", .data = _du_r8a7790_info }, > { .compatible = "renesas,du-r8a7743", .data = _du_r8a7743_info }, > @@ -513,6 +532,7 @@ static const struct of_device_id rcar_du_of_table[] = { > { .compatible = "renesas,du-r8a77980", .data = _du_r8a77970_info }, > { .compatible = "renesas,du-r8a77990", .data = _du_r8a7799x_info }, > { .compatible = "renesas,du-r8a77995", .data = _du_r8a7799x_info }, > + { .compatible = "renesas,du-r8a779a0", .data = _du_r8a779a0_info }, > { } > }; > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h > b/drivers/gpu/drm/rcar-du/rcar_du_drv.h > index 5fe9152454ff..cf98d43d72d0 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h > @@ -57,6 +57,7 @@ struct rcar_du_output_routing { > * @routes: array of CRTC to output routes, indexed by output > (RCAR_DU_OUTPUT_*) > * @num_lvds: number of internal LVDS encoders > * @dpll_mask: bit mask of DU channels equipped with a DPLL > + * @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot clock > * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot > clock > */ > struct rcar_du_device_info { > @@ -67,6 +68,7 @@ struct rcar_du_device_info { > struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; > unsigned int num_lvds; > unsigned int dpll_mask; > + unsigned int dsi_clk_mask; > unsigned int lvds_clk_mask; > }; > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c > b/drivers/gpu/drm/rcar-du/rcar_du_group.c > index a984eef265d2..8665a1dd2186 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c > @@ -124,6 +124,8 @@ static void rcar_du_group_setup_didsr(struct > rcar_du_group *rgrp) > if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) > didsr |= DIDSR_LDCS_LVDS0(i) > | DIDSR_PDCS_CLK(i, 0); > + else if (rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) > + didsr |= DIDSR_LDCS_DSI(i); > else > didsr |= DIDSR_LDCS_DCLKIN(i) > | DIDSR_PDCS_CLK(i, 0); > diff --git
[PATCH v3 3/6] drm: rcar-du: Only initialise TVM_TVSYNC mode when supported
The R-Car DU as found on the D3, E3, and V3U do not have support for an external synchronisation method. In these cases, the dsysr cached register should not be initialised in DSYSR_TVM_TVSYNC, but instead should be left clear to configure as DSYSR_TVM_MASTER by default. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- v2: - Remove parenthesis drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index ea7e39d03545..a0f837e8243a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -1243,7 +1243,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, rcrtc->group = rgrp; rcrtc->mmio_offset = mmio_offsets[hwindex]; rcrtc->index = hwindex; - rcrtc->dsysr = (rcrtc->index % 2 ? 0 : DSYSR_DRES) | DSYSR_TVM_TVSYNC; + rcrtc->dsysr = rcrtc->index % 2 ? 0 : DSYSR_DRES; + + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_TVM_SYNC)) + rcrtc->dsysr |= DSYSR_TVM_TVSYNC; if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) primary = >vsp->planes[rcrtc->vsp_pipe].plane; -- 2.30.2
[PATCH v3 4/6] drm: rcar-du: Fix DIDSR field name
The DIDSR fields named LDCS were incorrectly defined as LCDS. Both the Gen2 and Gen3 documentation refer to the fields as the "LVDS Dot Clock Select". Correct the definitions. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- v2: - New patch v3: - Collect tag drivers/gpu/drm/rcar-du/rcar_du_group.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_regs.h | 8 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 88a783ceb3e9..a984eef265d2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -122,10 +122,10 @@ static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp) didsr = DIDSR_CODE; for (i = 0; i < num_crtcs; ++i, ++rcrtc) { if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) - didsr |= DIDSR_LCDS_LVDS0(i) + didsr |= DIDSR_LDCS_LVDS0(i) | DIDSR_PDCS_CLK(i, 0); else - didsr |= DIDSR_LCDS_DCLKIN(i) + didsr |= DIDSR_LDCS_DCLKIN(i) | DIDSR_PDCS_CLK(i, 0); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index fb9964949368..fb7c467aa484 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -257,10 +257,10 @@ #define DIDSR 0x20028 #define DIDSR_CODE (0x7790 << 16) -#define DIDSR_LCDS_DCLKIN(n) (0 << (8 + (n) * 2)) -#define DIDSR_LCDS_LVDS0(n)(2 << (8 + (n) * 2)) -#define DIDSR_LCDS_LVDS1(n)(3 << (8 + (n) * 2)) -#define DIDSR_LCDS_MASK(n) (3 << (8 + (n) * 2)) +#define DIDSR_LDCS_DCLKIN(n) (0 << (8 + (n) * 2)) +#define DIDSR_LDCS_LVDS0(n)(2 << (8 + (n) * 2)) +#define DIDSR_LDCS_LVDS1(n)(3 << (8 + (n) * 2)) +#define DIDSR_LDCS_MASK(n) (3 << (8 + (n) * 2)) #define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2)) #define DIDSR_PDCS_MASK(n) (3 << ((n) * 2)) -- 2.30.2
[PATCH v3 6/6] drm: rcar-du: Add r8a779a0 device support
From: Kieran Bingham Extend the rcar_du_device_info structure and rcar_du_output enum to support DSI outputs and utilise these additions to provide support for the R8A779A0 V3U platform. While the DIDSR register field is now named "DSI/CSI-2-TX-IF0 Dot Clock Select" the existing define LVDS0 is used, and is directly compatible from other DU variants. Signed-off-by: Kieran Bingham --- v3: - Introduce DIDSR_LDCS_DSI macro v2: - No longer requires a direct interface with the DSI encoder - Use correct field naming (LDCS) - Remove per-crtc clock feature. drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 + 5 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 440e6b4fbb58..26e79b74898c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -96,6 +96,8 @@ struct rcar_du_crtc_state { enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, RCAR_DU_OUTPUT_DPAD1, + RCAR_DU_OUTPUT_DSI0, + RCAR_DU_OUTPUT_DSI1, RCAR_DU_OUTPUT_HDMI0, RCAR_DU_OUTPUT_HDMI1, RCAR_DU_OUTPUT_LVDS0, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 8a094d5b9c77..8b4c8851b6bc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -489,6 +489,25 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { .lvds_clk_mask = BIT(1) | BIT(0), }; +static const struct rcar_du_device_info rcar_du_r8a779a0_info = { + .gen = 3, + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_VSP1_SOURCE, + .channels_mask = BIT(1) | BIT(0), + .routes = { + /* R8A779A0 has two MIPI DSI outputs. */ + [RCAR_DU_OUTPUT_DSI0] = { + .possible_crtcs = BIT(0), + .port = 0, + }, + [RCAR_DU_OUTPUT_DSI1] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + }, + .dsi_clk_mask = BIT(1) | BIT(0), +}; + static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a7742", .data = _du_r8a7790_info }, { .compatible = "renesas,du-r8a7743", .data = _du_r8a7743_info }, @@ -513,6 +532,7 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a77980", .data = _du_r8a77970_info }, { .compatible = "renesas,du-r8a77990", .data = _du_r8a7799x_info }, { .compatible = "renesas,du-r8a77995", .data = _du_r8a7799x_info }, + { .compatible = "renesas,du-r8a779a0", .data = _du_r8a779a0_info }, { } }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 5fe9152454ff..cf98d43d72d0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -57,6 +57,7 @@ struct rcar_du_output_routing { * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) * @num_lvds: number of internal LVDS encoders * @dpll_mask: bit mask of DU channels equipped with a DPLL + * @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot clock * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock */ struct rcar_du_device_info { @@ -67,6 +68,7 @@ struct rcar_du_device_info { struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; unsigned int num_lvds; unsigned int dpll_mask; + unsigned int dsi_clk_mask; unsigned int lvds_clk_mask; }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index a984eef265d2..8665a1dd2186 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -124,6 +124,8 @@ static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp) if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) didsr |= DIDSR_LDCS_LVDS0(i) | DIDSR_PDCS_CLK(i, 0); + else if (rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) + didsr |= DIDSR_LDCS_DSI(i); else didsr |= DIDSR_LDCS_DCLKIN(i) | DIDSR_PDCS_CLK(i, 0); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index fb7c467aa484..9484215b51e2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -258,6 +258,7 @@ #define DIDSR 0x20028 #define DIDSR_CODE (0x7790 << 16) #define DIDSR_LDCS_DCLKIN(n) (0 <<
[PATCH v3 5/6] drm: rcar-du: Split CRTC IRQ and Clock features
Not all platforms require both per-crtc IRQ and per-crtc clock management. In preparation for suppporting such platforms, split the feature macro to be able to specify both features independently. The other features are incremented accordingly, to keep the two crtc features adjacent. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- v2: - New patch v3: - Collect tag drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +-- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 48 +- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 9 ++--- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index a0f837e8243a..5672830ca184 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -1206,7 +1206,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, int ret; /* Get the CRTC clock and the optional external clock. */ - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_CLOCK)) { sprintf(clk_name, "du.%u", hwindex); name = clk_name; } else { @@ -1272,7 +1272,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, drm_crtc_helper_add(crtc, _helper_funcs); /* Register the interrupt handler. */ - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ)) { /* The IRQ's are associated with the CRTC (sw)index. */ irq = platform_get_irq(pdev, swindex); irqflags = 0; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 4ac26d08ebb4..8a094d5b9c77 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -36,7 +36,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = { .gen = 2, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_INTERLACED | RCAR_DU_FEATURE_TVM_SYNC, .channels_mask = BIT(1) | BIT(0), @@ -58,7 +59,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = { static const struct rcar_du_device_info rzg1_du_r8a7745_info = { .gen = 2, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_INTERLACED | RCAR_DU_FEATURE_TVM_SYNC, .channels_mask = BIT(1) | BIT(0), @@ -79,7 +81,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = { static const struct rcar_du_device_info rzg1_du_r8a77470_info = { .gen = 2, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_INTERLACED | RCAR_DU_FEATURE_TVM_SYNC, .channels_mask = BIT(1) | BIT(0), @@ -105,7 +108,8 @@ static const struct rcar_du_device_info rzg1_du_r8a77470_info = { static const struct rcar_du_device_info rcar_du_r8a774a1_info = { .gen = 3, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_VSP1_SOURCE | RCAR_DU_FEATURE_INTERLACED | RCAR_DU_FEATURE_TVM_SYNC, @@ -134,7 +138,8 @@ static const struct rcar_du_device_info rcar_du_r8a774a1_info = { static const struct rcar_du_device_info rcar_du_r8a774b1_info = { .gen = 3, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_VSP1_SOURCE | RCAR_DU_FEATURE_INTERLACED | RCAR_DU_FEATURE_TVM_SYNC, @@ -163,7 +168,8 @@ static const struct rcar_du_device_info rcar_du_r8a774b1_info = { static const struct rcar_du_device_info rcar_du_r8a774c0_info = { .gen = 3, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_VSP1_SOURCE, .channels_mask = BIT(1) | BIT(0), .routes = { @@ -189,7 +195,8 @@ static const struct rcar_du_device_info rcar_du_r8a774c0_info = { static const struct rcar_du_device_info rcar_du_r8a774e1_info = { .gen = 3, - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + .features = RCAR_DU_FEATURE_CRTC_IRQ + | RCAR_DU_FEATURE_CRTC_CLOCK | RCAR_DU_FEATURE_VSP1_SOURCE | RCAR_DU_FEATURE_INTERLACED
[PATCH v3 2/6] drm: rcar-du: Sort the DU outputs
From: Kieran Bingham Sort the DU outputs alphabetically, with the exception of the final entry which is there as a sentinal. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- v2: - Collect tag drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 5f2940c42225..440e6b4fbb58 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -96,10 +96,10 @@ struct rcar_du_crtc_state { enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, RCAR_DU_OUTPUT_DPAD1, - RCAR_DU_OUTPUT_LVDS0, - RCAR_DU_OUTPUT_LVDS1, RCAR_DU_OUTPUT_HDMI0, RCAR_DU_OUTPUT_HDMI1, + RCAR_DU_OUTPUT_LVDS0, + RCAR_DU_OUTPUT_LVDS1, RCAR_DU_OUTPUT_TCON, RCAR_DU_OUTPUT_MAX, }; -- 2.30.2
[PATCH v3 1/6] dt-bindings: display: renesas, du: Provide bindings for r8a779a0
From: Kieran Bingham Extend the Renesas DU display bindings to support the r8a779a0 V3U. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- v2: - Collected Laurent's tag - Remove clock-names requirement - Specify only a single clock v3: - Use clocknames: 'du.0' instead of 'du' to remain consistent .../bindings/display/renesas,du.yaml | 50 +++ 1 file changed, 50 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.yaml b/Documentation/devicetree/bindings/display/renesas,du.yaml index e3ca5389c17d..6db6a3f15395 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.yaml +++ b/Documentation/devicetree/bindings/display/renesas,du.yaml @@ -39,6 +39,7 @@ properties: - renesas,du-r8a77980 # for R-Car V3H compatible DU - renesas,du-r8a77990 # for R-Car E3 compatible DU - renesas,du-r8a77995 # for R-Car D3 compatible DU + - renesas,du-r8a779a0 # for R-Car V3U compatible DU reg: maxItems: 1 @@ -773,6 +774,55 @@ allOf: - reset-names - renesas,vsps + - if: + properties: +compatible: + contains: +enum: + - renesas,du-r8a779a0 +then: + properties: +clocks: + items: +- description: Functional clock + +clock-names: + maxItems: 1 + items: +- const: du.0 + +interrupts: + maxItems: 2 + +resets: + maxItems: 1 + +reset-names: + items: +- const: du.0 + +ports: + properties: +port@0: + description: DSI 0 +port@1: + description: DSI 1 +port@2: false +port@3: false + + required: +- port@0 +- port@1 + +renesas,vsps: + minItems: 2 + + required: +- interrupts +- resets +- reset-names +- renesas,vsps + additionalProperties: false examples: -- 2.30.2
Re: [PATCH] drm/bridge: dw-hdmi-cec: Make use of the helper function devm_add_action_or_reset()
Hi Cai, Thank you for the patch. On Wed, Sep 22, 2021 at 08:59:08PM +0800, Cai Huoqing wrote: > The helper function devm_add_action_or_reset() will internally > call devm_add_action(), and if devm_add_action() fails then it will > execute the action mentioned and return the error code. So > use devm_add_action_or_reset() instead of devm_add_action() > to simplify the error handling, reduce the code. > > Signed-off-by: Cai Huoqing Reviewed-by: Laurent Pinchart > --- > drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 6 ++ > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c > index 70ab4fbdc23e..c8f44bcb298a 100644 > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c > @@ -265,11 +265,9 @@ static int dw_hdmi_cec_probe(struct platform_device > *pdev) > /* override the module pointer */ > cec->adap->owner = THIS_MODULE; > > - ret = devm_add_action(>dev, dw_hdmi_cec_del, cec); > - if (ret) { > - cec_delete_adapter(cec->adap); > + ret = devm_add_action_or_reset(>dev, dw_hdmi_cec_del, cec); > + if (ret) > return ret; > - } > > ret = devm_request_threaded_irq(>dev, cec->irq, > dw_hdmi_cec_hardirq, -- Regards, Laurent Pinchart
Re: [PATCH] drm: rcar-du: Make use of the helper function devm_platform_ioremap_resource()
Hi Cai, Thank you for the patch. On Tue, Aug 31, 2021 at 03:54:42PM +0800, Cai Huoqing wrote: > Use the devm_platform_ioremap_resource() helper instead of > calling platform_get_resource() and devm_ioremap_resource() > separately > > Signed-off-by: Cai Huoqing Reviewed-by: Laurent Pinchart > --- > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 +--- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 4 +--- > 2 files changed, 2 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > index 4ac26d08ebb4..ebec4b7269d1 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > @@ -570,7 +570,6 @@ static void rcar_du_shutdown(struct platform_device *pdev) > static int rcar_du_probe(struct platform_device *pdev) > { > struct rcar_du_device *rcdu; > - struct resource *mem; > int ret; > > /* Allocate and initialize the R-Car device structure. */ > @@ -585,8 +584,7 @@ static int rcar_du_probe(struct platform_device *pdev) > platform_set_drvdata(pdev, rcdu); > > /* I/O resources */ > - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - rcdu->mmio = devm_ioremap_resource(>dev, mem); > + rcdu->mmio = devm_platform_ioremap_resource(pdev, 0); > if (IS_ERR(rcdu->mmio)) > return PTR_ERR(rcdu->mmio); > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c > b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index d061b8de748f..a64d910b0500 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -802,7 +802,6 @@ static int rcar_lvds_probe(struct platform_device *pdev) > { > const struct soc_device_attribute *attr; > struct rcar_lvds *lvds; > - struct resource *mem; > int ret; > > lvds = devm_kzalloc(>dev, sizeof(*lvds), GFP_KERNEL); > @@ -825,8 +824,7 @@ static int rcar_lvds_probe(struct platform_device *pdev) > lvds->bridge.funcs = _lvds_bridge_ops; > lvds->bridge.of_node = pdev->dev.of_node; > > - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - lvds->mmio = devm_ioremap_resource(>dev, mem); > + lvds->mmio = devm_platform_ioremap_resource(pdev, 0); > if (IS_ERR(lvds->mmio)) > return PTR_ERR(lvds->mmio); > -- Regards, Laurent Pinchart
Re: [PATCH] drm/shmobile: Make use of the helper function devm_platform_ioremap_resource()
Hi Cai, Thank you for the patch. On Tue, Aug 31, 2021 at 09:57:30PM +0800, Cai Huoqing wrote: > Use the devm_platform_ioremap_resource() helper instead of > calling platform_get_resource() and devm_ioremap_resource() > separately > > Signed-off-by: Cai Huoqing Reviewed-by: Laurent Pinchart > --- > drivers/gpu/drm/shmobile/shmob_drm_drv.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c > b/drivers/gpu/drm/shmobile/shmob_drm_drv.c > index 7db01904d18d..80078a9fd7f6 100644 > --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c > +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c > @@ -192,7 +192,6 @@ static int shmob_drm_probe(struct platform_device *pdev) > struct shmob_drm_platform_data *pdata = pdev->dev.platform_data; > struct shmob_drm_device *sdev; > struct drm_device *ddev; > - struct resource *res; > unsigned int i; > int ret; > > @@ -215,8 +214,7 @@ static int shmob_drm_probe(struct platform_device *pdev) > > platform_set_drvdata(pdev, sdev); > > - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > - sdev->mmio = devm_ioremap_resource(>dev, res); > + sdev->mmio = devm_platform_ioremap_resource(pdev, 0); > if (IS_ERR(sdev->mmio)) > return PTR_ERR(sdev->mmio); > -- Regards, Laurent Pinchart
Re: [PATCH v2 2/2] drm: rcar-du: Add R-Car DSI driver
Hi Andrzej, On Wed, Sep 22, 2021 at 04:29:39AM +0300, Laurent Pinchart wrote: > On Tue, Sep 21, 2021 at 09:42:11PM +0200, Andrzej Hajda wrote: > > W dniu 23.06.2021 o 15:56, Laurent Pinchart pisze: > > > From: LUU HOAI > > > > > > The driver supports the MIPI DSI/CSI-2 TX encoder found in the R-Car V3U > > > SoC. It currently supports DSI mode only. > > > > > > Signed-off-by: LUU HOAI > > > Signed-off-by: Laurent Pinchart > > > > > > Reviewed-by: Kieran Bingham > > > Tested-by: Kieran Bingham > > > --- > > > drivers/gpu/drm/rcar-du/Kconfig | 6 + > > > drivers/gpu/drm/rcar-du/Makefile | 1 + > > > drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 827 +++ > > > drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 172 > > > 4 files changed, 1006 insertions(+) > > > create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c > > > create mode 100644 drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h > > > > > > diff --git a/drivers/gpu/drm/rcar-du/Kconfig > > > b/drivers/gpu/drm/rcar-du/Kconfig > > > index b47e74421e34..8cb94fe90639 100644 > > > --- a/drivers/gpu/drm/rcar-du/Kconfig > > > +++ b/drivers/gpu/drm/rcar-du/Kconfig > > > @@ -38,6 +38,12 @@ config DRM_RCAR_LVDS > > > help > > > Enable support for the R-Car Display Unit embedded LVDS > > > encoders. > > > > > > +config DRM_RCAR_MIPI_DSI > > > + tristate "R-Car DU MIPI DSI Encoder Support" > > > + depends on DRM && DRM_BRIDGE && OF > > > + help > > > + Enable support for the R-Car Display Unit embedded MIPI DSI encoders. > > > + > > > config DRM_RCAR_VSP > > > bool "R-Car DU VSP Compositor Support" if ARM > > > default y if ARM64 > > > diff --git a/drivers/gpu/drm/rcar-du/Makefile > > > b/drivers/gpu/drm/rcar-du/Makefile > > > index 4d1187ccc3e5..adc1b49d02cf 100644 > > > --- a/drivers/gpu/drm/rcar-du/Makefile > > > +++ b/drivers/gpu/drm/rcar-du/Makefile > > > @@ -19,6 +19,7 @@ obj-$(CONFIG_DRM_RCAR_CMM) += rcar_cmm.o > > > obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o > > > obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o > > > obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o > > > +obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o > > > > > > # 'remote-endpoint' is fixed up at run-time > > > DTC_FLAGS_rcar_du_of_lvds_r8a7790 += -Wno-graph_endpoint > > > diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c > > > b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c > > > new file mode 100644 > > > index ..e94245029f95 > > > --- /dev/null > > > +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c > > > @@ -0,0 +1,827 @@ > > > +// SPDX-License-Identifier: GPL-2.0 > > > +/* > > > + * rcar_mipi_dsi.c -- R-Car MIPI DSI Encoder > > > + * > > > + * Copyright (C) 2020 Renesas Electronics Corporation > > > + */ > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +#include "rcar_mipi_dsi_regs.h" > > > + > > > +struct rcar_mipi_dsi { > > > + struct device *dev; > > > + const struct rcar_mipi_dsi_device_info *info; > > > + struct reset_control *rstc; > > > + > > > + struct mipi_dsi_host host; > > > + struct drm_bridge bridge; > > > + struct drm_bridge *next_bridge; > > > + struct drm_connector connector; > > > + > > > + void __iomem *mmio; > > > + struct { > > > + struct clk *mod; > > > + struct clk *pll; > > > + struct clk *dsi; > > > + } clocks; > > > + > > > + struct drm_display_mode display_mode; > > > + enum mipi_dsi_pixel_format format; > > > + unsigned int num_data_lanes; > > > + unsigned int lanes; > > > +}; > > > + > > > +static inline struct rcar_mipi_dsi * > > > +bridge_to_rcar_mipi_dsi(struct drm_bridge *bridge) > > > +{ > > > + return container_of(bridge, struct rcar_mipi_dsi, bridge); > > > +} > > > + > > > +static inline struct rcar_mipi_dsi * > > > +host_to_rcar_mipi_dsi(struct mipi_dsi_host *host) > > > +{ > > > + return container_of(host, struct rcar_mipi_dsi, host); > > > +} > > > + > > > +static const u32 phtw[] = { > > > + 0x01020114, 0x01600115, /* General testing */ > > > + 0x01030116, 0x0102011d, /* General testing */ > > > + 0x011101a4, 0x018601a4, /* 1Gbps testing */ > > > + 0x014201a0, 0x010001a3, /* 1Gbps testing */ > > > + 0x0101011f, /* 1Gbps testing */ > > > +}; > > > + > > > +static const u32 phtw2[] = { > > > + 0x010c0130, 0x010c0140, /* General testing */ > > > + 0x010c0150, 0x010c0180, /* General testing */ > > > + 0x010c0190, > > > + 0x010a0160, 0x010a0170, > > > + 0x01800164, 0x01800174, /* 1Gbps testing */ > > > +}; > > > + > > > +static const u32 hsfreqrange_table[][2] = { > > > + { 8000, 0x00 }, { 9000, 0x10 }, { 1, 0x20 }, > > > + {
[PATCH 3/3] drm/msm: Extend gpu devcore dumps with pgtbl info
From: Rob Clark In the case of iova fault triggered devcore dumps, include additional debug information based on what we think is the current page tables, including the TTBR0 value (which should match what we have in adreno_smmu_fault_info unless things have gone horribly wrong), and the pagetable entries traversed in the process of resolving the faulting iova. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 ++ drivers/gpu/drm/msm/msm_gpu.c | 10 ++ drivers/gpu/drm/msm/msm_gpu.h | 8 drivers/gpu/drm/msm/msm_iommu.c | 17 + drivers/gpu/drm/msm/msm_mmu.h | 2 ++ 5 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 42e522a60623..d3718982be77 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -707,6 +707,16 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, drm_printf(p, " - dir: %s\n", info->flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"); drm_printf(p, " - type: %s\n", info->type); drm_printf(p, " - source: %s\n", info->block); + + /* Information extracted from what we think are the current +* pgtables. Hopefully the TTBR0 matches what we've extracted +* from the SMMU registers in smmu_info! +*/ + drm_puts(p, "pgtable-fault-info:\n"); + drm_printf(p, " - ttbr0: %.16llx\n", info->pgtbl_ttbr0); + drm_printf(p, " - asid: %d\n", info->asid); + drm_printf(p, " - ptes: %.16llx %.16llx %.16llx %.16llx\n", + info->ptes[0], info->ptes[1], info->ptes[2], info->ptes[3]); } drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 8a3a592da3a4..d1a16642ecd5 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -284,6 +284,16 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, if (submit) { int i, nr = 0; + if (state->fault_info.smmu_info.ttbr0) { + struct msm_gpu_fault_info *info = >fault_info; + struct msm_mmu *mmu = submit->aspace->mmu; + + msm_iommu_pagetable_params(mmu, >pgtbl_ttbr0, + >asid); + msm_iommu_pagetable_walk(mmu, info->iova, info->ptes, +ARRAY_SIZE(info->ptes)); + } + /* count # of buffers to dump: */ for (i = 0; i < submit->nr_bos; i++) if (should_dump(submit, i)) diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index a7a5a53536a8..32a859307e81 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -78,6 +78,14 @@ struct msm_gpu_fault_info { int flags; const char *type; const char *block; + + /* Information about what we think/expect is the current SMMU state, +* for example expected_ttbr0 should match smmu_info.ttbr0 which +* was read back from SMMU registers. +*/ + u64 pgtbl_ttbr0; + u64 ptes[4]; + int asid; }; /** diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index eed2a762e9dd..1bd985b56e35 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -116,6 +116,23 @@ int msm_iommu_pagetable_params(struct msm_mmu *mmu, return 0; } +int msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, +u64 *ptes, int num_ptes) +{ + struct msm_iommu_pagetable *pagetable; + + if (mmu->type != MSM_MMU_IOMMU_PAGETABLE) + return -EINVAL; + + pagetable = to_pagetable(mmu); + + if (!pagetable->pgtbl_ops->pgtable_walk) + return -EINVAL; + + return pagetable->pgtbl_ops->pgtable_walk(pagetable->pgtbl_ops, iova, + ptes, _ptes); +} + static const struct msm_mmu_funcs pagetable_funcs = { .map = msm_iommu_pagetable_map, .unmap = msm_iommu_pagetable_unmap, diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index de158e1bf765..519b749c61af 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -58,5 +58,7 @@ void msm_gpummu_params(struct msm_mmu *mmu, dma_addr_t *pt_base, int msm_iommu_pagetable_params(struct msm_mmu *mmu, phys_addr_t *ttbr, int *asid); +int msm_iommu_pagetable_walk(struct msm_mmu *mmu, unsigned long iova, +u64 *ptes, int num_ptes); #endif /* __MSM_MMU_H__
[PATCH 2/3] drm/msm: Show all smmu info for iova fault devcore dumps
From: Rob Clark Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 25 + drivers/gpu/drm/msm/msm_gpu.h | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 4ac652c35c43..f6a4dbef796b 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1269,7 +1269,7 @@ static int a6xx_fault_handler(void *arg, unsigned long iova, int flags, void *da /* Turn off the hangcheck timer to keep it from bothering us */ del_timer(>hangcheck_timer); - gpu->fault_info.ttbr0 = info->ttbr0; + gpu->fault_info.smmu_info = *info; gpu->fault_info.iova = iova; gpu->fault_info.flags = flags; gpu->fault_info.type = type; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 748665232d29..42e522a60623 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -685,19 +685,28 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, adreno_gpu->rev.major, adreno_gpu->rev.minor, adreno_gpu->rev.patchid); /* -* If this is state collected due to iova fault, so fault related info +* If this is state collected due to iova fault, show fault related +* info * -* TTBR0 would not be zero, so this is a good way to distinguish +* TTBR0 would not be zero in this case, so this is a good way to +* distinguish */ - if (state->fault_info.ttbr0) { + if (state->fault_info.smmu_info.ttbr0) { const struct msm_gpu_fault_info *info = >fault_info; + const struct adreno_smmu_fault_info *smmu_info = >smmu_info; drm_puts(p, "fault-info:\n"); - drm_printf(p, " - ttbr0=%.16llx\n", info->ttbr0); - drm_printf(p, " - iova=%.16lx\n", info->iova); - drm_printf(p, " - dir=%s\n", info->flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"); - drm_printf(p, " - type=%s\n", info->type); - drm_printf(p, " - source=%s\n", info->block); + drm_printf(p, " - far: %.16llx\n", smmu_info->far); + drm_printf(p, " - ttbr0: %.16llx\n", smmu_info->ttbr0); + drm_printf(p, " - contextidr: %.8x\n", smmu_info->contextidr); + drm_printf(p, " - fsr: %.8x\n", smmu_info->fsr); + drm_printf(p, " - fsynr0: %.8x\n", smmu_info->fsynr0); + drm_printf(p, " - fsynr1: %.8x\n", smmu_info->fsynr1); + drm_printf(p, " - cbfrsynra: %.8x\n", smmu_info->cbfrsynra); + drm_printf(p, " - iova: %.16lx\n", info->iova); + drm_printf(p, " - dir: %s\n", info->flags & IOMMU_FAULT_WRITE ? "WRITE" : "READ"); + drm_printf(p, " - type: %s\n", info->type); + drm_printf(p, " - source: %s\n", info->block); } drm_printf(p, "rbbm-status: 0x%08x\n", state->rbbm_status); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index e031c9b495ed..a7a5a53536a8 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -73,7 +73,7 @@ struct msm_gpu_funcs { /* Additional state for iommu faults: */ struct msm_gpu_fault_info { - u64 ttbr0; + struct adreno_smmu_fault_info smmu_info; unsigned long iova; int flags; const char *type; -- 2.31.1
[PATCH v3] drm: rcar-du: Allow importing non-contiguous dma-buf with VSP
On R-Car Gen3, the DU uses a separate IP core named VSP to perform DMA from memory and composition of planes. The DU hardware then only handles the video timings and the interface with the encoders. This differs from Gen2, where the DU included a composer with DMA engines. When sourcing from the VSP, the DU hardware performs no memory access, and thus has no requirements on imported dma-buf memory types. The GEM CMA helpers however still create a DMA mapping to the DU device, which isn't used. The mapping to the VSP is done when processing the atomic commits, in the plane .prepare_fb() handler. When the system uses an IOMMU, the VSP device is attached to it, which enables the VSP to use non physically contiguous memory. The DU, as it performs no memory access, isn't connected to the IOMMU. The GEM CMA drm_gem_cma_prime_import_sg_table() helper will in that case fail to map non-contiguous imported dma-bufs, as the DMA mapping to the DU device will have multiple entries in its sgtable. The prevents using non physically contiguous memory for display. The DRM PRIME and GEM CMA helpers are designed to create the sgtable when the dma-buf is imported. By default, the device referenced by the drm_device is used to create the dma-buf attachment. Drivers can use a different device by using the drm_gem_prime_import_dev() function. While the DU has access to the VSP device, this won't help here, as different CRTCs use different VSP instances, connected to different IOMMU channels. The driver doesn't know at import time which CRTC a GEM object will be used, and thus can't select the right VSP device to pass to drm_gem_prime_import_dev(). To support non-contiguous memory, implement a custom .gem_prime_import_sg_table() operation that accepts all imported dma-buf regardless of the number of scatterlist entries. The sgtable will be mapped to the VSP at .prepare_fb() time, which will reject the framebuffer if the VSP isn't connected to an IOMMU. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- Changes since v2: - Inline error handling in rcar_du_gem_prime_import_sg_table() Changes since v1: - Rewrote commit message to explain issue in more details - Duplicate the imported scatter gather table in rcar_du_vsp_plane_prepare_fb() - Use separate loop counter j to avoid overwritting i - Update to latest drm_gem_cma API --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +++- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 46 +++ drivers/gpu/drm/rcar-du/rcar_du_kms.h | 7 drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 36 ++--- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 62dfd1b66db0..806c68823a28 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -529,7 +529,11 @@ DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); static const struct drm_driver rcar_du_driver = { .driver_features= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(rcar_du_dumb_create), + .dumb_create= rcar_du_dumb_create, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import_sg_table = rcar_du_gem_prime_import_sg_table, + .gem_prime_mmap = drm_gem_prime_mmap, .fops = _du_fops, .name = "rcar-du", .desc = "Renesas R-Car Display Unit", diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ca29e4a62816..eacb1f17f747 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -325,6 +326,51 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc) * Frame buffer */ +static const struct drm_gem_object_funcs rcar_du_gem_funcs = { + .free = drm_gem_cma_free_object, + .print_info = drm_gem_cma_print_info, + .get_sg_table = drm_gem_cma_get_sg_table, + .vmap = drm_gem_cma_vmap, + .mmap = drm_gem_cma_mmap, + .vm_ops = _gem_cma_vm_ops, +}; + +struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt) +{ + struct rcar_du_device *rcdu = to_rcar_du_device(dev); + struct drm_gem_cma_object *cma_obj; + struct drm_gem_object *gem_obj; + int ret; + + if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) + return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + + /* Create a CMA GEM buffer. */ + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); + if (!cma_obj) + return ERR_PTR(-ENOMEM); + +
[PATCH 1/3] iommu/io-pgtable-arm: Add way to debug pgtable walk
From: Rob Clark Add an io-pgtable method to retrieve the raw PTEs that would be traversed for a given iova access. Signed-off-by: Rob Clark --- drivers/iommu/io-pgtable-arm.c | 40 +++--- include/linux/io-pgtable.h | 9 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 87def58e79b5..5571d7203f11 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -638,38 +638,61 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, return __arm_lpae_unmap(data, gather, iova, size, data->start_level, ptep); } -static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops, -unsigned long iova) +static int arm_lpae_pgtable_walk(struct io_pgtable_ops *ops, unsigned long iova, +void *_ptes, int *num_ptes) { struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops); arm_lpae_iopte pte, *ptep = data->pgd; + arm_lpae_iopte *ptes = _ptes; + int max_ptes = *num_ptes; int lvl = data->start_level; + *num_ptes = 0; + do { + if (*num_ptes >= max_ptes) + return -ENOSPC; + /* Valid IOPTE pointer? */ if (!ptep) - return 0; + return -EFAULT; /* Grab the IOPTE we're interested in */ ptep += ARM_LPAE_LVL_IDX(iova, lvl, data); pte = READ_ONCE(*ptep); + ptes[(*num_ptes)++] = pte; + /* Valid entry? */ if (!pte) - return 0; + return -EFAULT; /* Leaf entry? */ if (iopte_leaf(pte, lvl, data->iop.fmt)) - goto found_translation; + return 0; /* Take it to the next level */ ptep = iopte_deref(pte, data); } while (++lvl < ARM_LPAE_MAX_LEVELS); - /* Ran out of page tables to walk */ - return 0; + return -EFAULT; +} + +static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops, +unsigned long iova) +{ + struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops); + arm_lpae_iopte pte, ptes[ARM_LPAE_MAX_LEVELS]; + int lvl, num_ptes = ARM_LPAE_MAX_LEVELS; + int ret; + + ret = arm_lpae_pgtable_walk(ops, iova, ptes, _ptes); + if (ret) + return 0; + + pte = ptes[num_ptes - 1]; + lvl = num_ptes - 1 + data->start_level; -found_translation: iova &= (ARM_LPAE_BLOCK_SIZE(lvl, data) - 1); return iopte_to_paddr(pte, data) | iova; } @@ -752,6 +775,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg) .map= arm_lpae_map, .unmap = arm_lpae_unmap, .iova_to_phys = arm_lpae_iova_to_phys, + .pgtable_walk = arm_lpae_pgtable_walk, }; return data; diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 4d40dfa75b55..6cba731ed8d3 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -145,6 +145,13 @@ struct io_pgtable_cfg { * @map: Map a physically contiguous memory region. * @unmap:Unmap a physically contiguous memory region. * @iova_to_phys: Translate iova to physical address. + * @pgtable_walk: Return details of a page table walk for a given iova. + *This returns the array of PTEs in a format that is + *specific to the page table format. The number of + *PTEs can be format specific. The num_ptes parameter + *on input specifies the size of the ptes array, and + *on output the number of PTEs filled in (which depends + *on the number of PTEs walked to resolve the iova) * * These functions map directly onto the iommu_ops member functions with * the same names. @@ -156,6 +163,8 @@ struct io_pgtable_ops { size_t size, struct iommu_iotlb_gather *gather); phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops, unsigned long iova); + int (*pgtable_walk)(struct io_pgtable_ops *ops, unsigned long iova, + void *ptes, int *num_ptes); }; /** -- 2.31.1
[PATCH 0/3] io-pgtable-arm + drm/msm: Extend iova fault debugging
From: Rob Clark This series extends io-pgtable-arm with a method to retrieve the page table entries traversed in the process of address translation, and then beefs up drm/msm gpu devcore dump to include this (and additional info) in the devcore dump. The motivation is tracking down an obscure iova fault triggered crash on the address of the IB1 cmdstream. This is one of the few places where the GPU address written into the cmdstream is soley under control of the kernel mode driver, so I don't think it can be a userspace bug. The logged cmdstream from the devcore's I've looked at look correct, and the TTBR0 read back from arm-smmu agrees with the kernel emitted cmdstream. Unfortunately it happens infrequently enough (something like once per 1000hrs of usage, from what I can tell from our telemetry) that actually reproducing it with an instrumented debug kernel is not an option. So further spiffying out the devcore dumps and hoping we can spot a clue is the plan I'm shooting for. See https://gitlab.freedesktop.org/drm/msm/-/issues/8 for more info on the issue I'm trying to debug. Rob Clark (3): iommu/io-pgtable-arm: Add way to debug pgtable walk drm/msm: Show all smmu info for iova fault devcore dumps drm/msm: Extend gpu devcore dumps with pgtbl info drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 35 +- drivers/gpu/drm/msm/msm_gpu.c | 10 +++ drivers/gpu/drm/msm/msm_gpu.h | 10 ++- drivers/gpu/drm/msm/msm_iommu.c | 17 +++ drivers/gpu/drm/msm/msm_mmu.h | 2 ++ drivers/iommu/io-pgtable-arm.c | 40 - include/linux/io-pgtable.h | 9 ++ 8 files changed, 107 insertions(+), 18 deletions(-) -- 2.31.1
Re: [PATCH RESEND] drm/i915: Flush buffer pools on driver remove
On Fri, Sep 03, 2021 at 04:23:20PM +0200, Janusz Krzysztofik wrote: > In preparation for clean driver release, attempts to drain work queues > and release freed objects are taken at driver remove time. However, GT > buffer pools are now not flushed before the driver release phase. > Since unused objects may stay there for up to one second, some may > survive until driver release is attempted. That can potentially > explain sporadic then hardly reproducible issues observed at driver > release time, like non-zero shrink counter or outstanding address space So just to make sure I'm understanding the description here: - We currently do an explicit flush of the buffer pools within the call path of drm_driver.release(); this removes all buffers, regardless of their age. - However there may be other code that runs *earlier* within the drm_driver.release() call chain that expects buffer pools have already been flushed and are already empty. - Since buffer pools auto-flush old buffers once per second in a worker thread, there's a small window where if we remove the driver while there are still buffers with an age of less than one second, the assumptions of the other release code may be violated. So by moving the flush to driver remove (which executes earlier via the pci_driver.remove() flow) you're ensuring that all buffers are flushed before _any_ code in drm_driver.release() executes. I found the wording of the commit message here somewhat confusing since it's talking about flushes we do in driver release, but mentions problems that arise during driver release due to lack of flushing. You might want to reword the commit message somewhat to help clarify. Otherwise, the code change itself looks reasonable to me. BTW, I do notice that drm_driver.release() in general is technically deprecated at this point (with a suggestion in the drm_drv.h comments to switch to using drmm_add_action(), drmm_kmalloc(), etc. to manage the cleanup of resources). At some point in the future me may want to rework the i915 cleanup in general according to that guidance. Matt > areas. > > Flush buffer pools on GT remove as a fix. On driver release, don't > flush the pools again, just assert that the flush was called and > nothing added more in between. > > Signed-off-by: Janusz Krzysztofik > Cc: Chris Wilson > --- > Resending with Cc: dri-devel@lists.freedesktop.org as requested, and a > typo in commit description fixed. > > Thanks, > Janusz > > drivers/gpu/drm/i915/gt/intel_gt.c | 2 ++ > drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 2 -- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c > b/drivers/gpu/drm/i915/gt/intel_gt.c > index 62d40c986642..8f322a4ecd87 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c > @@ -737,6 +737,8 @@ void intel_gt_driver_remove(struct intel_gt *gt) > intel_uc_driver_remove(>uc); > > intel_engines_release(gt); > + > + intel_gt_flush_buffer_pool(gt); > } > > void intel_gt_driver_unregister(struct intel_gt *gt) > diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c > b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c > index aa0a59c5b614..acc49c56a9f3 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c > @@ -245,8 +245,6 @@ void intel_gt_fini_buffer_pool(struct intel_gt *gt) > struct intel_gt_buffer_pool *pool = >buffer_pool; > int n; > > - intel_gt_flush_buffer_pool(gt); > - > for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) > GEM_BUG_ON(!list_empty(>cache_list[n])); > } > -- > 2.25.1 > -- Matt Roper Graphics Software Engineer VTT-OSGC Platform Enablement Intel Corporation (916) 356-2795
Re: [PATCH v2] drm: rcar-du: Allow importing non-contiguous dma-buf with VSP
Hi Kieran, On Wed, Sep 22, 2021 at 10:37:29PM +0100, Kieran Bingham wrote: > On 30/07/2021 03:05, Laurent Pinchart wrote: > > On R-Car Gen3, the DU uses a separate IP core named VSP to perform DMA > > from memory and composition of planes. The DU hardware then only handles > > the video timings and the interface with the encoders. This differs from > > Gen2, where the DU included a composer with DMA engines. > > > > When sourcing from the VSP, the DU hardware performs no memory access, > > and thus has no requirements on imported dma-buf memory types. The GEM > > CMA helpers however still create a DMA mapping to the DU device, which > > isn't used. The mapping to the VSP is done when processing the atomic > > commits, in the plane .prepare_fb() handler. > > > > When the system uses an IOMMU, the VSP device is attached to it, which > > enables the VSP to use non physically contiguous memory. The DU, as it > > performs no memory access, isn't connected to the IOMMU. The GEM CMA > > drm_gem_cma_prime_import_sg_table() helper will in that case fail to map > > non-contiguous imported dma-bufs, as the DMA mapping to the DU device > > will have multiple entries in its sgtable. The prevents using non > > physically contiguous memory for display. > > > > The DRM PRIME and GEM CMA helpers are designed to create the sgtable > > when the dma-buf is imported. By default, the device referenced by the > > drm_device is used to create the dma-buf attachment. Drivers can use a > > different device by using the drm_gem_prime_import_dev() function. While > > the DU has access to the VSP device, this won't help here, as different > > CRTCs use different VSP instances, connected to different IOMMU > > channels. The driver doesn't know at import time which CRTC a GEM object > > will be used, and thus can't select the right VSP device to pass to > > drm_gem_prime_import_dev(). > > > > To support non-contiguous memory, implement a custom > > .gem_prime_import_sg_table() operation that accepts all imported dma-buf > > regardless of the number of scatterlist entries. The sgtable will be > > mapped to the VSP at .prepare_fb() time, which will reject the > > framebuffer if the VSP isn't connected to an IOMMU. > > Wow - quite a lot to digest there. I tried to make it clear, but there's lots to explain :-S > > Signed-off-by: Laurent Pinchart > > --- > > > > This can arguably be considered as a bit of a hack, as the GEM PRIME > > import still maps the dma-buf attachment to the DU, which isn't > > necessary. This is however not a big issue, as the DU isn't connected to > > any IOMMU, the DMA mapping thus doesn't waste any resource such as I/O > > memory space. Avoiding the mapping creation would require replacing the > > helpers completely, resulting in lots of code duplication. If this type > > of hardware setup was common we could create another set of helpers, but > > I don't think it would be worth it to support a single device. > > > > I have tested this patch with the cam application from libcamera, on a > > R-Car H3 ES2.x Salvator-XS board, importing buffers from the vimc > > driver: > > > > cam -c 'platform/vimc.0 Sensor B' \ > > -s pixelformat=BGR888,width=1440,height=900 \ > > -C -D HDMI-A-1 > > Are VIMC buffers always physically non-contiguous to validate this test? They're not, but with https://lore.kernel.org/linux-media/20210730001939.30769-1-laurent.pinchart+rene...@ideasonboard.com/ they can be made to be, with a module parameter. > > A set of patches to add DRM/KMS output support to cam has been posted. > > Until it gets merged (hopefully soon), it can be found at [1]. > > > > As cam doesn't support DRM/KMS scaling and overlay planes yet, the > > camera resolution needs to match the display resolution. Due to a > > peculiarity of the vimc driver, the resolution has to be divisible by 3, > > which may require changes to the resolution above depending on your > > monitor. > > > > A test patch is also needed for the kernel, to enable IOMMU support for > > the VSP, which isn't done by default (yet ?) in mainline. I have pushed > > a branch to [2] if anyone is interested. > > > > [1] > > https://lists.libcamera.org/pipermail/libcamera-devel/2021-July/022815.html > > [2] git://linuxtv.org/pinchartl/media.git drm/du/devel/gem/contig > > > > --- > > Changes since v1: > > > > - Rewrote commit message to explain issue in more details > > - Duplicate the imported scatter gather table in > > rcar_du_vsp_plane_prepare_fb() > > - Use separate loop counter j to avoid overwritting i > > - Update to latest drm_gem_cma API > > --- > > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +++- > > drivers/gpu/drm/rcar-du/rcar_du_kms.c | 49 +++ > > drivers/gpu/drm/rcar-du/rcar_du_kms.h | 7 > > drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 36 +--- > > 4 files changed, 92 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > >
[Bug 214029] [bisected] [amdgpu] Several memory leaks in amdgpu and ttm
https://bugzilla.kernel.org/show_bug.cgi?id=214029 Erhard F. (erhar...@mailbox.org) changed: What|Removed |Added Summary|[bisected] [NAVI] Several |[bisected] [amdgpu] Several |memory leaks in amdgpu and |memory leaks in amdgpu and |ttm |ttm -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
[Bug 214029] [bisected] [NAVI] Several memory leaks in amdgpu and ttm
https://bugzilla.kernel.org/show_bug.cgi?id=214029 --- Comment #14 from Erhard F. (erhar...@mailbox.org) --- Created attachment 298927 --> https://bugzilla.kernel.org/attachment.cgi?id=298927=edit kernel dmesg (kernel 5.14.6, AMD Opteron 6386 SE) Does not seem to be Navi specific after all as the leaks do happen with the Radeon R7 360 in my Opteron box too. [...] unreferenced object 0x8afeddd0c2c0 (size 176): comm "Web Content", pid 1830253, jiffies 4302445561 (age 2701.157s) hex dump (first 32 bytes): 50 c3 d0 dd fe 8a ff ff 80 51 3a c0 ff ff ff ff PQ:. 0f 89 14 e9 f1 16 00 00 48 fe b6 09 41 a7 ff ff H...A... backtrace: [] drm_sched_fence_create+0x1d/0xb0 [gpu_sched] [] drm_sched_job_init+0x58/0xa0 [gpu_sched] [] amdgpu_job_submit+0x21/0xe0 [amdgpu] [] amdgpu_copy_buffer+0x1ea/0x290 [amdgpu] [] amdgpu_ttm_copy_mem_to_mem+0x282/0x5b0 [amdgpu] [] amdgpu_bo_move+0x130/0x7d8 [amdgpu] [] ttm_bo_handle_move_mem+0x89/0x178 [ttm] [] ttm_bo_validate+0xba/0x140 [ttm] [] amdgpu_bo_fault_reserve_notify+0xb6/0x160 [amdgpu] [] amdgpu_gem_fault+0x78/0x100 [amdgpu] [] __do_fault+0x31/0xe8 [] __handle_mm_fault+0xe1a/0x1290 [] handle_mm_fault+0xb5/0x218 [] exc_page_fault+0x177/0x5d0 [] asm_exc_page_fault+0x1b/0x20 unreferenced object 0x8b01f00bd0c0 (size 72): comm "sdma0", pid 403, jiffies 4302445561 (age 2701.157s) hex dump (first 32 bytes): e0 c7 64 13 ff 8a ff ff 00 1c 30 c1 ff ff ff ff ..d...0. 65 59 16 e9 f1 16 00 00 58 28 b9 86 03 8b ff ff eY..X(.. backtrace: [] amdgpu_fence_emit+0x2b/0x1f0 [amdgpu] [] amdgpu_ib_schedule+0x2e3/0x4e8 [amdgpu] [] amdgpu_job_run+0x8b/0x1e8 [amdgpu] [] drm_sched_main+0x1b7/0x3d8 [gpu_sched] [] kthread+0x122/0x140 [] ret_from_fork+0x22/0x30 unreferenced object 0x8b02ec1796c0 (size 176): comm "Renderer", pid 108402, jiffies 4302694486 (age 1871.424s) hex dump (first 32 bytes): 50 97 17 ec 02 8b ff ff 80 51 3a c0 ff ff ff ff PQ:. 4f 9c 02 1a b3 17 00 00 48 fe b6 09 41 a7 ff ff O...H...A... backtrace: [] drm_sched_fence_create+0x1d/0xb0 [gpu_sched] [] drm_sched_job_init+0x58/0xa0 [gpu_sched] [] amdgpu_job_submit+0x21/0xe0 [amdgpu] [] amdgpu_copy_buffer+0x1ea/0x290 [amdgpu] [] amdgpu_ttm_copy_mem_to_mem+0x282/0x5b0 [amdgpu] [] amdgpu_bo_move+0x130/0x7d8 [amdgpu] [] ttm_bo_handle_move_mem+0x89/0x178 [ttm] [] ttm_bo_validate+0xba/0x140 [ttm] [] amdgpu_bo_fault_reserve_notify+0xb6/0x160 [amdgpu] [] amdgpu_gem_fault+0x78/0x100 [amdgpu] [] __do_fault+0x31/0xe8 [] __handle_mm_fault+0xe1a/0x1290 [] handle_mm_fault+0xb5/0x218 [] exc_page_fault+0x177/0x5d0 [] asm_exc_page_fault+0x1b/0x20 # lspci -s 01:00.0 -v 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Tobago PRO [Radeon R7 360 / R9 360 OEM] (rev 81) (prog-if 00 [VGA controller]) Subsystem: PC Partner Limited / Sapphire Technology Tobago PRO [Radeon R7 360 / R9 360 OEM] Flags: bus master, fast devsel, latency 0, IRQ 47, IOMMU group 11 Memory at d000 (64-bit, prefetchable) [size=256M] Memory at cf80 (64-bit, prefetchable) [size=8M] I/O ports at c000 [size=256] Memory at fdc8 (32-bit, non-prefetchable) [size=256K] Expansion ROM at 000c [disabled] [size=128K] Capabilities: [48] Vendor Specific Information: Len=08 Capabilities: [50] Power Management version 3 Capabilities: [58] Express Legacy Endpoint, MSI 00 Capabilities: [a0] MSI: Enable+ Count=1/1 Maskable- 64bit+ Capabilities: [100] Vendor Specific Information: ID=0001 Rev=1 Len=010 Capabilities: [150] Advanced Error Reporting Capabilities: [200] Physical Resizable BAR Capabilities: [270] Secondary PCI Express Capabilities: [2b0] Address Translation Service (ATS) Capabilities: [2c0] Page Request Interface (PRI) Capabilities: [2d0] Process Address Space ID (PASID) Kernel driver in use: amdgpu Kernel modules: radeon, amdgpu -- You may reply to this email to add a comment. You are receiving this mail because: You are watching the assignee of the bug.
Re: [Intel-gfx] [PATCH 14/19] drm/i915/oprom: Basic sanitization
On Mon, Sep 20, 2021 at 08:04:32AM +, Gupta, Anshuman wrote: -Original Message- From: Nikula, Jani Sent: Monday, September 20, 2021 1:12 PM To: De Marchi, Lucas Cc: Auld, Matthew ; intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; Gupta, Anshuman Subject: Re: [Intel-gfx] [PATCH 14/19] drm/i915/oprom: Basic sanitization On Fri, 17 Sep 2021, Lucas De Marchi wrote: > On Mon, May 17, 2021 at 02:57:33PM +0300, Jani Nikula wrote: >>On Mon, 12 Apr 2021, Matthew Auld wrote: >>> From: Anshuman Gupta >>> >>> Sanitize OPROM header, CPD signature and OPROM PCI version. >>> OPROM_HEADER, EXPANSION_ROM_HEADER and OPROM_MEU_BLOB structures and >>> PCI struct offsets are provided by GSC counterparts. >>> These are yet to be Documented in B.Spec. >>> After successful sanitization, extract VBT from opregion image. >> >>So I don't understand what the point is with two consecutive patches >>where the latter rewrites a lot of the former. > > I actually wonder what's the point of this. Getting it from spi is > already the fallback and looks much more complex. Yes, it's pretty > detailed and document the format pretty well, but it still looks more > complex than the initial code. Do you see additional benefit in this > one? Getting opregion image from spi is needed to get the intel_opregion and its mailboxes on discrete card. The commit message doesn't really explain much. Anshuman? I will get rework of the patches and float it again. from this patch the only thing I see it's doing is to get the VBT from inside opregion... it moves the read part to helper methods and apparently it supports multiple images...? The question here is not why we are reading from spi, but rather what this is doing that the previous commit wasn't already. Lucas De Marchi
Re: [PATCH v2] dt-bindings: display: renesas,du: Provide bindings for r8a779a0
Hello everybody, On Tue, Sep 07, 2021 at 09:17:31PM +0200, Geert Uytterhoeven wrote: > On Tue, Sep 7, 2021 at 8:45 PM Rob Herring wrote: > > On Mon, Sep 06, 2021 at 10:13:07AM +0200, Geert Uytterhoeven wrote: > > > On Thu, Sep 2, 2021 at 1:39 AM Kieran Bingham wrote: > > > > From: Kieran Bingham > > > > > > > > Extend the Renesas DU display bindings to support the r8a779a0 V3U. > > > > > > > > Reviewed-by: Laurent Pinchart > > > > Signed-off-by: Kieran Bingham > > > > --- > > > > v2: > > > > - Collected Laurent's tag > > > > - Remove clock-names requirement > > > > - Specify only a single clock > > > > > > Thanks for the update! > > > > > > > --- a/Documentation/devicetree/bindings/display/renesas,du.yaml > > > > +++ b/Documentation/devicetree/bindings/display/renesas,du.yaml > > > > @@ -39,6 +39,7 @@ properties: > > > >- renesas,du-r8a77980 # for R-Car V3H compatible DU > > > >- renesas,du-r8a77990 # for R-Car E3 compatible DU > > > >- renesas,du-r8a77995 # for R-Car D3 compatible DU > > > > + - renesas,du-r8a779a0 # for R-Car V3U compatible DU > > > > > > > >reg: > > > > maxItems: 1 > > > > @@ -773,6 +774,55 @@ allOf: > > > > - reset-names > > > > - renesas,vsps > > > > > > > > + - if: > > > > + properties: > > > > +compatible: > > > > + contains: > > > > +enum: > > > > + - renesas,du-r8a779a0 > > > > +then: > > > > + properties: > > > > +clocks: > > > > + items: > > > > +- description: Functional clock > > > > + > > > > +clock-names: > > > > + maxItems: 1 > > > > + items: > > > > +- const: du > > > > + > > > > +interrupts: > > > > + maxItems: 2 > > > > + > > > > +resets: > > > > + maxItems: 1 > > > > + > > > > +reset-names: > > > > + items: > > > > +- const: du.0 > > > > > > This is now inconsistent with clock-names, which doesn't use a suffix. > > > > But it is consistent with all the other cases of 'reset-names'. The > > problem is 'clock-names' is not consistent and should be 'du.0'. > > True. Looks fine to me. The only other SoC that has a similar shared clock architecture is H1 (R8A7779), and we use du.0 there. > > Ideally, the if/them schemas should not be defining the names. That > > should be at the top level and the if/them schema just limits the number > > of entries. That's not always possible, but I think is for clocks and > > resets in this case. > > It's a bit tricky. > For clocks, there's usually one clock per channel, but not always. > Plus clocks for external inputs, if present. Yes, it's mostly the external clocks that mess things up here. Each DU channel typically has one internal clock and one optional external clock, but not always. > For resets, there's one reset for a group of channels, with the number > of channels in a group depending on the SoC family. > And then there's the special casing for SoCs where there's a gap in > the channel numbering... For resets, H1 and M3-N are indeed special cases. H1 has no reset-names, while M3-N has du.0 and du.3 due to a gap in hardware channel numbering. All other SoCs have du.0 and optionally du.2. > Still wondering if it would be better to have one device node per > channel, and companion links... The hardware design would make that too messy. There are too many cross-channel dependencies. -- Regards, Laurent Pinchart
Re: [PATCH v2 5/5] drm: rcar-du: Add r8a779a0 device support
Hi Kieran, Thank you for the patch. On Thu, Sep 02, 2021 at 12:49:07AM +0100, Kieran Bingham wrote: > From: Kieran Bingham > > Extend the rcar_du_device_info structure and rcar_du_output enum to > support DSI outputs and utilise these additions to provide support for > the R8A779A0 V3U platform. > > While the DIDSR register field is now named "DSI/CSI-2-TX-IF0 Dot Clock > Select" the existing define LVDS0 is used, and is directly compatible > from other DU variants. > > Signed-off-by: Kieran Bingham > > --- > > I can add a macro named DIDSR_LDCS_DSI0 duplicating DIDSR_LDCS_LVDS0 if > it's deemed better. I think I'd like that a bit better if you don't mind. I'd name the macro DIDSR_LDCS_DSI though, as there's a single option (you can't pick one DSI encoder or the other as the clock source, it's DSI0 for DU0 and DSI1 for DU1). > > v2: > - No longer requires a direct interface with the DSI encoder > - Use correct field naming (LDCS) > - Remove per-crtc clock feature. > > drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 2 ++ > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 20 > drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 ++ > drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++ > 4 files changed, 26 insertions(+) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > index 440e6b4fbb58..26e79b74898c 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > @@ -96,6 +96,8 @@ struct rcar_du_crtc_state { > enum rcar_du_output { > RCAR_DU_OUTPUT_DPAD0, > RCAR_DU_OUTPUT_DPAD1, > + RCAR_DU_OUTPUT_DSI0, > + RCAR_DU_OUTPUT_DSI1, > RCAR_DU_OUTPUT_HDMI0, > RCAR_DU_OUTPUT_HDMI1, > RCAR_DU_OUTPUT_LVDS0, > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > index 8a094d5b9c77..8b4c8851b6bc 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > @@ -489,6 +489,25 @@ static const struct rcar_du_device_info > rcar_du_r8a7799x_info = { > .lvds_clk_mask = BIT(1) | BIT(0), > }; > > +static const struct rcar_du_device_info rcar_du_r8a779a0_info = { > + .gen = 3, > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_VSP1_SOURCE, > + .channels_mask = BIT(1) | BIT(0), > + .routes = { > + /* R8A779A0 has two MIPI DSI outputs. */ > + [RCAR_DU_OUTPUT_DSI0] = { > + .possible_crtcs = BIT(0), > + .port = 0, > + }, > + [RCAR_DU_OUTPUT_DSI1] = { > + .possible_crtcs = BIT(1), > + .port = 1, > + }, > + }, > + .dsi_clk_mask = BIT(1) | BIT(0), > +}; > + > static const struct of_device_id rcar_du_of_table[] = { > { .compatible = "renesas,du-r8a7742", .data = _du_r8a7790_info }, > { .compatible = "renesas,du-r8a7743", .data = _du_r8a7743_info }, > @@ -513,6 +532,7 @@ static const struct of_device_id rcar_du_of_table[] = { > { .compatible = "renesas,du-r8a77980", .data = _du_r8a77970_info }, > { .compatible = "renesas,du-r8a77990", .data = _du_r8a7799x_info }, > { .compatible = "renesas,du-r8a77995", .data = _du_r8a7799x_info }, > + { .compatible = "renesas,du-r8a779a0", .data = _du_r8a779a0_info }, While this looks good, the DT bindings need a v3, so I can't include this series in a pull request just yet :-( Could you please group the DT bindings and driver patches in a single series for v3 ? > { } > }; > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h > b/drivers/gpu/drm/rcar-du/rcar_du_drv.h > index 5fe9152454ff..cf98d43d72d0 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h > @@ -57,6 +57,7 @@ struct rcar_du_output_routing { > * @routes: array of CRTC to output routes, indexed by output > (RCAR_DU_OUTPUT_*) > * @num_lvds: number of internal LVDS encoders > * @dpll_mask: bit mask of DU channels equipped with a DPLL > + * @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot clock > * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot > clock > */ > struct rcar_du_device_info { > @@ -67,6 +68,7 @@ struct rcar_du_device_info { > struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; > unsigned int num_lvds; > unsigned int dpll_mask; > + unsigned int dsi_clk_mask; > unsigned int lvds_clk_mask; > }; > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c > b/drivers/gpu/drm/rcar-du/rcar_du_group.c > index a984eef265d2..27c912bab76e 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c > @@ -124,6 +124,8 @@ static void rcar_du_group_setup_didsr(struct > rcar_du_group *rgrp) > if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) > didsr |=
Re: [PATCH v2] drm: rcar-du: Allow importing non-contiguous dma-buf with VSP
On 30/07/2021 03:05, Laurent Pinchart wrote: > On R-Car Gen3, the DU uses a separate IP core named VSP to perform DMA > from memory and composition of planes. The DU hardware then only handles > the video timings and the interface with the encoders. This differs from > Gen2, where the DU included a composer with DMA engines. > > When sourcing from the VSP, the DU hardware performs no memory access, > and thus has no requirements on imported dma-buf memory types. The GEM > CMA helpers however still create a DMA mapping to the DU device, which > isn't used. The mapping to the VSP is done when processing the atomic > commits, in the plane .prepare_fb() handler. > > When the system uses an IOMMU, the VSP device is attached to it, which > enables the VSP to use non physically contiguous memory. The DU, as it > performs no memory access, isn't connected to the IOMMU. The GEM CMA > drm_gem_cma_prime_import_sg_table() helper will in that case fail to map > non-contiguous imported dma-bufs, as the DMA mapping to the DU device > will have multiple entries in its sgtable. The prevents using non > physically contiguous memory for display. > > The DRM PRIME and GEM CMA helpers are designed to create the sgtable > when the dma-buf is imported. By default, the device referenced by the > drm_device is used to create the dma-buf attachment. Drivers can use a > different device by using the drm_gem_prime_import_dev() function. While > the DU has access to the VSP device, this won't help here, as different > CRTCs use different VSP instances, connected to different IOMMU > channels. The driver doesn't know at import time which CRTC a GEM object > will be used, and thus can't select the right VSP device to pass to > drm_gem_prime_import_dev(). > > To support non-contiguous memory, implement a custom > .gem_prime_import_sg_table() operation that accepts all imported dma-buf > regardless of the number of scatterlist entries. The sgtable will be > mapped to the VSP at .prepare_fb() time, which will reject the > framebuffer if the VSP isn't connected to an IOMMU. Wow - quite a lot to digest there. > Signed-off-by: Laurent Pinchart > --- > > This can arguably be considered as a bit of a hack, as the GEM PRIME > import still maps the dma-buf attachment to the DU, which isn't > necessary. This is however not a big issue, as the DU isn't connected to > any IOMMU, the DMA mapping thus doesn't waste any resource such as I/O > memory space. Avoiding the mapping creation would require replacing the > helpers completely, resulting in lots of code duplication. If this type > of hardware setup was common we could create another set of helpers, but > I don't think it would be worth it to support a single device. > > I have tested this patch with the cam application from libcamera, on a > R-Car H3 ES2.x Salvator-XS board, importing buffers from the vimc > driver: > > cam -c 'platform/vimc.0 Sensor B' \ > -s pixelformat=BGR888,width=1440,height=900 \ > -C -D HDMI-A-1 Are VIMC buffers always physically non-contiguous to validate this test? > A set of patches to add DRM/KMS output support to cam has been posted. > Until it gets merged (hopefully soon), it can be found at [1]. > > As cam doesn't support DRM/KMS scaling and overlay planes yet, the > camera resolution needs to match the display resolution. Due to a > peculiarity of the vimc driver, the resolution has to be divisible by 3, > which may require changes to the resolution above depending on your > monitor. > > A test patch is also needed for the kernel, to enable IOMMU support for > the VSP, which isn't done by default (yet ?) in mainline. I have pushed > a branch to [2] if anyone is interested. > > [1] > https://lists.libcamera.org/pipermail/libcamera-devel/2021-July/022815.html > [2] git://linuxtv.org/pinchartl/media.git drm/du/devel/gem/contig > > --- > Changes since v1: > > - Rewrote commit message to explain issue in more details > - Duplicate the imported scatter gather table in > rcar_du_vsp_plane_prepare_fb() > - Use separate loop counter j to avoid overwritting i > - Update to latest drm_gem_cma API > --- > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +++- > drivers/gpu/drm/rcar-du/rcar_du_kms.c | 49 +++ > drivers/gpu/drm/rcar-du/rcar_du_kms.h | 7 > drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 36 +--- > 4 files changed, 92 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > index cb34b1e477bc..d1f8d51a10fe 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > @@ -511,7 +511,11 @@ DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); > > static const struct drm_driver rcar_du_driver = { > .driver_features= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, > - DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(rcar_du_dumb_create), > + .dumb_create= rcar_du_dumb_create, >
Re: [Intel-gfx] [PATCH] drm/i915: fix blank screen booting crashes
On Tue, Sep 21, 2021 at 06:40:41PM -0700, Matthew Brost wrote: On Tue, Sep 21, 2021 at 04:29:31PM -0700, Lucas De Marchi wrote: On Tue, Sep 21, 2021 at 03:55:15PM -0700, Matthew Brost wrote: > On Tue, Sep 21, 2021 at 11:46:37AM -0700, Lucas De Marchi wrote: > > On Tue, Sep 21, 2021 at 10:43:32AM -0700, Matthew Brost wrote: > > > From: Hugh Dickins > > > > > > 5.15-rc1 crashes with blank screen when booting up on two ThinkPads > > > using i915. Bisections converge convincingly, but arrive at different > > > and surprising "culprits", none of them the actual culprit. > > > > > > netconsole (with init_netconsole() hacked to call i915_init() when > > > logging has started, instead of by module_init()) tells the story: > > > > > > kernel BUG at drivers/gpu/drm/i915/i915_sw_fence.c:245! > > > with RSI: 814d408b pointing to sw_fence_dummy_notify(). > > > I've been building with CONFIG_CC_OPTIMIZE_FOR_SIZE=y, and that > > > function needs to be 4-byte aligned. > > > > > > v2: > > > (Jani Nikula) > > > - Change BUG_ON to WARN_ON > > > v3: > > > (Jani / Tvrtko) > > > - Short circuit __i915_sw_fence_init on WARN_ON > > > > > > Fixes: 62eaf0ae217d ("drm/i915/guc: Support request cancellation") > > > Signed-off-by: Hugh Dickins > > > Signed-off-by: Matthew Brost > > > Reviewed-by: Matthew Brost > > > --- > > > drivers/gpu/drm/i915/gt/intel_context.c | 4 ++-- > > > drivers/gpu/drm/i915/i915_sw_fence.c| 17 ++--- > > > 2 files changed, 12 insertions(+), 9 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c > > > index ff637147b1a9..e7f78bc7ebfc 100644 > > > --- a/drivers/gpu/drm/i915/gt/intel_context.c > > > +++ b/drivers/gpu/drm/i915/gt/intel_context.c > > > @@ -362,8 +362,8 @@ static int __intel_context_active(struct i915_active *active) > > > return 0; > > > } > > > > > > > > -static int sw_fence_dummy_notify(struct i915_sw_fence *sf, > > > - enum i915_sw_fence_notify state) > > > +static int __i915_sw_fence_call > > > +sw_fence_dummy_notify(struct i915_sw_fence *sf, enum i915_sw_fence_notify state) > > > { > > > return NOTIFY_DONE; > > > } > > > diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c > > > index c589a681da77..08cea73264e7 100644 > > > --- a/drivers/gpu/drm/i915/i915_sw_fence.c > > > +++ b/drivers/gpu/drm/i915/i915_sw_fence.c > > > @@ -13,9 +13,9 @@ > > > #include "i915_selftest.h" > > > > > > #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) > > > -#define I915_SW_FENCE_BUG_ON(expr) BUG_ON(expr) > > > +#define I915_SW_FENCE_WARN_ON(expr) WARN_ON(expr) > > > #else > > > -#define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) > > > +#define I915_SW_FENCE_WARN_ON(expr) BUILD_BUG_ON_INVALID(expr) > > > #endif > > > > > > static DEFINE_SPINLOCK(i915_sw_fence_lock); > > > @@ -129,7 +129,10 @@ static int __i915_sw_fence_notify(struct i915_sw_fence *fence, > > > i915_sw_fence_notify_t fn; > > > > > > fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); > > > -return fn(fence, state); > > > +if (likely(fn)) > > > +return fn(fence, state); > > > +else > > > +return 0; > > > > since the knowledge for these being NULL (or with the wrong alignment) > > are in the init/reinit functions, wouldn't it be better to just add a > > fence_nop() and assign it there instead this likely() here? > > > > Maybe? I prefer the way it is. > > > > } > > > > > > #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS > > > @@ -242,9 +245,9 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, > > >const char *name, > > >struct lock_class_key *key) > > > { > > > -BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); > > > - > > > __init_waitqueue_head(>wait, name, key); > > > +if (WARN_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK)) > > > +return; > > > > like: > > if (WARN_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK)) > > fence->flags = (unsigned long)sw_fence_dummy_notify; > > else > > fence->flags = (unsigned long)fn; > > > > > > f you return here instead of calling i915_sw_fence_reinit(), aren't you > > just going to use uninitialized memory later? At least in the selftests, > > which allocate it with kmalloc()... I didn't check others. > > > > I don't think so, maybe the fence won't work but it won't blow up > either. > > > > > For the bug fix we could just add the __aligned(4) and leave the rest to a > > separate patch. > > > > The bug was sw_fence_dummy_notify in gt/intel_context.c was not 4 byte > align which triggered a BUG_ON during boot which blank screened a > laptop. Jani / Tvrtko suggested that we make the BUG_ON to WARN_ONs so > if someone makes this mistake in the future kernel should boot albiet > with a WARNING. yes, I understood. But afaics with WARN_ON you
Re: [PATCH v3 5/8] x86/sme: Replace occurrences of sme_active() with cc_platform_has()
On Wed, Sep 22, 2021 at 09:52:07PM +0200, Borislav Petkov wrote: > On Wed, Sep 22, 2021 at 05:30:15PM +0300, Kirill A. Shutemov wrote: > > Not fine, but waiting to blowup with random build environment change. > > Why is it not fine? > > Are you suspecting that the compiler might generate something else and > not a rip-relative access? Yes. We had it before for __supported_pte_mask and other users of fixup_pointer(). See for instance 4a09f0210c8b ("x86/boot/64/clang: Use fixup_pointer() to access '__supported_pte_mask'") Unless we find other way to guarantee RIP-relative access, we must use fixup_pointer() to access any global variables. -- Kirill A. Shutemov
[PATCH v3 6/6] drm/ingenic: Attach bridge chain to encoders
Attach a top-level bridge to each encoder, which will be used for negociating the bus format and flags. All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +-- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a5e2880e07a1..a05a9fa6e115 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,19 @@ struct ingenic_drm { struct drm_private_obj private_obj; }; +struct ingenic_drm_bridge { + struct drm_encoder encoder; + struct drm_bridge bridge, *next_bridge; + + struct drm_bus_cfg bus_cfg; +}; + +static inline struct ingenic_drm_bridge * +to_ingenic_drm_bridge(struct drm_encoder *encoder) +{ + return container_of(encoder, struct ingenic_drm_bridge, encoder); +} + static inline struct ingenic_drm_private_state * to_ingenic_drm_priv_state(struct drm_private_state *state) { @@ -668,11 +682,10 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, { struct ingenic_drm *priv = drm_device_get_priv(encoder->dev); struct drm_display_mode *mode = _state->adjusted_mode; - struct drm_connector *conn = conn_state->connector; - struct drm_display_info *info = >display_info; + struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder); unsigned int cfg, rgbcfg = 0; - priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; + priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS; if (priv->panel_is_sharp) { cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; @@ -685,19 +698,19 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; if (mode->flags & DRM_MODE_FLAG_NVSYNC) cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; - if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW) cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; - if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) + if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; if (!priv->panel_is_sharp) { - if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { + if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) { if (mode->flags & DRM_MODE_FLAG_INTERLACE) cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; else cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; } else { - switch (*info->bus_formats) { + switch (bridge->bus_cfg.format) { case MEDIA_BUS_FMT_RGB565_1X16: cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; break; @@ -723,20 +736,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg); } -static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge, +enum drm_bridge_attach_flags flags) +{ + struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); + + return drm_bridge_attach(bridge->encoder, ib->next_bridge, +>bridge, flags); +} + +static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { - struct drm_display_info *info = _state->connector->display_info; struct drm_display_mode *mode = _state->adjusted_mode; + struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); - if (info->num_bus_formats != 1) - return -EINVAL; + ib->bus_cfg = bridge_state->output_bus_cfg; if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) return 0; - switch (*info->bus_formats) { + switch (bridge_state->output_bus_cfg.format) { case MEDIA_BUS_FMT_RGB888_3X8: case MEDIA_BUS_FMT_RGB888_3X8_DELTA: /* @@ -900,8 +922,16
[PATCH v3 5/6] drm/ingenic: Upload palette before frame
When using C8 color mode, make sure that the palette is always uploaded before a frame; otherwise the very first frame will have wrong colors. Do that by changing the link order of the DMA descriptors. v3: Fix ingenic_drm_get_new_priv_state() called instead of ingenic_drm_get_priv_state() Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 53 --- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index cbc76cede99e..a5e2880e07a1 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -66,6 +66,7 @@ struct jz_soc_info { struct ingenic_drm_private_state { struct drm_private_state base; + bool use_palette; }; struct ingenic_drm { @@ -113,6 +114,30 @@ to_ingenic_drm_priv_state(struct drm_private_state *state) return container_of(state, struct ingenic_drm_private_state, base); } +static struct ingenic_drm_private_state * +ingenic_drm_get_priv_state(struct ingenic_drm *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(state, >private_obj); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_ingenic_drm_priv_state(priv_state); +} + +static struct ingenic_drm_private_state * +ingenic_drm_get_new_priv_state(struct ingenic_drm *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_new_private_obj_state(state, >private_obj); + if (!priv_state) + return NULL; + + return to_ingenic_drm_priv_state(priv_state); +} + static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -183,11 +208,18 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); + struct ingenic_drm_private_state *priv_state; + unsigned int next_id; + + priv_state = ingenic_drm_get_priv_state(priv, state); + if (WARN_ON(IS_ERR(priv_state))) + return; regmap_write(priv->map, JZ_REG_LCD_STATE, 0); - /* Set address of our DMA descriptor chain */ - regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, 0)); + /* Set addresses of our DMA descriptor chains */ + next_id = priv_state->use_palette ? HWDESC_PALETTE : 0; + regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, next_id)); regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_addr(priv, 1)); regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, @@ -393,6 +425,7 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); struct ingenic_drm *priv = drm_device_get_priv(plane->dev); + struct ingenic_drm_private_state *priv_state; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; int ret; @@ -405,6 +438,10 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, if (WARN_ON(!crtc_state)) return -EINVAL; + priv_state = ingenic_drm_get_priv_state(priv, state); + if (IS_ERR(priv_state)) + return PTR_ERR(priv_state); + ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -423,6 +460,9 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, (new_plane_state->src_h >> 16) != new_plane_state->crtc_h)) return -EINVAL; + priv_state->use_palette = new_plane_state->fb && + new_plane_state->fb->format->format == DRM_FORMAT_C8; + /* * Require full modeset if enabling or disabling a plane, or changing * its position, size or depth. @@ -583,6 +623,7 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane); unsigned int width, height, cpp, next_id, plane_id; + struct ingenic_drm_private_state *priv_state; struct drm_crtc_state *crtc_state; struct ingenic_dma_hwdesc *hwdesc; dma_addr_t addr; @@ -600,19 +641,19 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, height =
[PATCH v3 4/6] drm/ingenic: Set DMA descriptor chain register when starting CRTC
Setting the DMA descriptor chain register in the probe function has been fine until now, because we only ever had one descriptor per foreground. As the driver will soon have real descriptor chains, and the DMA descriptor chain register updates itself to point to the current descriptor being processed, this register needs to be reset after a full modeset to point to the first descriptor of the chain. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 5dbeca0f8f37..cbc76cede99e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -186,6 +186,10 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, regmap_write(priv->map, JZ_REG_LCD_STATE, 0); + /* Set address of our DMA descriptor chain */ + regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, 0)); + regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_addr(priv, 1)); + regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_ENABLE | JZ_LCD_CTRL_DISABLE, JZ_LCD_CTRL_ENABLE); -- 2.33.0
[PATCH v3 3/6] drm/ingenic: Move IPU scale settings to private state
The IPU scaling information is computed in the plane's ".atomic_check" callback, and used in the ".atomic_update" callback. As such, it is state-specific, and should be moved to a private state structure. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 73 --- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index c819293b8317..2737fc521e15 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -47,6 +47,8 @@ struct soc_info { struct ingenic_ipu_private_state { struct drm_private_state base; + + unsigned int num_w, num_h, denom_w, denom_h; }; struct ingenic_ipu { @@ -58,8 +60,6 @@ struct ingenic_ipu { const struct soc_info *soc_info; bool clk_enabled; - unsigned int num_w, num_h, denom_w, denom_h; - dma_addr_t addr_y, addr_u, addr_v; struct drm_property *sharpness_prop; @@ -85,6 +85,30 @@ to_ingenic_ipu_priv_state(struct drm_private_state *state) return container_of(state, struct ingenic_ipu_private_state, base); } +static struct ingenic_ipu_private_state * +ingenic_ipu_get_priv_state(struct ingenic_ipu *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(state, >private_obj); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_ingenic_ipu_priv_state(priv_state); +} + +static struct ingenic_ipu_private_state * +ingenic_ipu_get_new_priv_state(struct ingenic_ipu *priv, struct drm_atomic_state *state) +{ + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_new_private_obj_state(state, >private_obj); + if (!priv_state) + return NULL; + + return to_ingenic_ipu_priv_state(priv_state); +} + /* * Apply conventional cubic convolution kernel. Both parameters * and return value are 15.16 signed fixed-point. @@ -305,11 +329,16 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, const struct drm_format_info *finfo; u32 ctrl, stride = 0, coef_index = 0, format = 0; bool needs_modeset, upscaling_w, upscaling_h; + struct ingenic_ipu_private_state *ipu_state; int err; if (!newstate || !newstate->fb) return; + ipu_state = ingenic_ipu_get_new_priv_state(ipu, state); + if (WARN_ON(!ipu_state)) + return; + finfo = drm_format_info(newstate->fb->format->format); if (!ipu->clk_enabled) { @@ -482,27 +511,27 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, if (ipu->soc_info->has_bicubic) ctrl |= JZ_IPU_CTRL_ZOOM_SEL; - upscaling_w = ipu->num_w > ipu->denom_w; + upscaling_w = ipu_state->num_w > ipu_state->denom_w; if (upscaling_w) ctrl |= JZ_IPU_CTRL_HSCALE; - if (ipu->num_w != 1 || ipu->denom_w != 1) { + if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) { if (!ipu->soc_info->has_bicubic && !upscaling_w) - coef_index |= (ipu->denom_w - 1) << 16; + coef_index |= (ipu_state->denom_w - 1) << 16; else - coef_index |= (ipu->num_w - 1) << 16; + coef_index |= (ipu_state->num_w - 1) << 16; ctrl |= JZ_IPU_CTRL_HRSZ_EN; } - upscaling_h = ipu->num_h > ipu->denom_h; + upscaling_h = ipu_state->num_h > ipu_state->denom_h; if (upscaling_h) ctrl |= JZ_IPU_CTRL_VSCALE; - if (ipu->num_h != 1 || ipu->denom_h != 1) { + if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) { if (!ipu->soc_info->has_bicubic && !upscaling_h) - coef_index |= ipu->denom_h - 1; + coef_index |= ipu_state->denom_h - 1; else - coef_index |= ipu->num_h - 1; + coef_index |= ipu_state->num_h - 1; ctrl |= JZ_IPU_CTRL_VRSZ_EN; } @@ -513,13 +542,13 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, /* Set the LUT index register */ regmap_write(ipu->map, JZ_REG_IPU_RSZ_COEF_INDEX, coef_index); - if (ipu->num_w != 1 || ipu->denom_w != 1) + if (ipu_state->num_w != 1 || ipu_state->denom_w != 1) ingenic_ipu_set_coefs(ipu, JZ_REG_IPU_HRSZ_COEF_LUT, - ipu->num_w, ipu->denom_w); + ipu_state->num_w, ipu_state->denom_w); - if (ipu->num_h != 1 || ipu->denom_h != 1) + if (ipu_state->num_h != 1 || ipu_state->denom_h != 1) ingenic_ipu_set_coefs(ipu, JZ_REG_IPU_VRSZ_COEF_LUT, -
[PATCH v3 2/6] drm/ingenic: Add support for private objects
Until now, the ingenic-drm as well as the ingenic-ipu drivers used to put state-specific information in their respective private structure. Add boilerplate code to support private objects in the two drivers, so that state-specific information can be put in the state-specific private structure. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 61 +++ drivers/gpu/drm/ingenic/ingenic-ipu.c | 54 2 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 95c12c2aba14..5dbeca0f8f37 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -64,6 +64,10 @@ struct jz_soc_info { unsigned int num_formats_f0, num_formats_f1; }; +struct ingenic_drm_private_state { + struct drm_private_state base; +}; + struct ingenic_drm { struct drm_device drm; /* @@ -99,8 +103,16 @@ struct ingenic_drm { struct mutex clk_mutex; bool update_clk_rate; struct notifier_block clock_nb; + + struct drm_private_obj private_obj; }; +static inline struct ingenic_drm_private_state * +to_ingenic_drm_priv_state(struct drm_private_state *state) +{ + return container_of(state, struct ingenic_drm_private_state, base); +} + static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -766,6 +778,28 @@ ingenic_drm_gem_create_object(struct drm_device *drm, size_t size) return >base; } +static struct drm_private_state * +ingenic_drm_duplicate_state(struct drm_private_obj *obj) +{ + struct ingenic_drm_private_state *state = to_ingenic_drm_priv_state(obj->state); + + state = kmemdup(state, sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_private_obj_duplicate_state(obj, >base); + + return >base; +} + +static void ingenic_drm_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct ingenic_drm_private_state *priv_state = to_ingenic_drm_priv_state(state); + + kfree(priv_state); +} + DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); static const struct drm_driver ingenic_drm_driver_data = { @@ -836,6 +870,11 @@ static struct drm_mode_config_helper_funcs ingenic_drm_mode_config_helpers = { .atomic_commit_tail = drm_atomic_helper_commit_tail, }; +static const struct drm_private_state_funcs ingenic_drm_private_state_funcs = { + .atomic_duplicate_state = ingenic_drm_duplicate_state, + .atomic_destroy_state = ingenic_drm_destroy_state, +}; + static void ingenic_drm_unbind_all(void *d) { struct ingenic_drm *priv = d; @@ -877,9 +916,15 @@ static void ingenic_drm_configure_hwdesc_plane(struct ingenic_drm *priv, ingenic_drm_configure_hwdesc(priv, plane, plane, 0xf0 | plane); } +static void ingenic_drm_atomic_private_obj_fini(struct drm_device *drm, void *private_obj) +{ + drm_atomic_private_obj_fini(private_obj); +} + static int ingenic_drm_bind(struct device *dev, bool has_components) { struct platform_device *pdev = to_platform_device(dev); + struct ingenic_drm_private_state *private_state; const struct jz_soc_info *soc_info; struct ingenic_drm *priv; struct clk *parent_clk; @@ -1148,6 +1193,20 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) goto err_devclk_disable; } + private_state = kzalloc(sizeof(*private_state), GFP_KERNEL); + if (!private_state) { + ret = -ENOMEM; + goto err_clk_notifier_unregister; + } + + drm_atomic_private_obj_init(drm, >private_obj, _state->base, + _drm_private_state_funcs); + + ret = drmm_add_action_or_reset(drm, ingenic_drm_atomic_private_obj_fini, + >private_obj); + if (ret) + goto err_private_state_free; + ret = drm_dev_register(drm, 0); if (ret) { dev_err(dev, "Failed to register DRM driver\n"); @@ -1158,6 +1217,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return 0; +err_private_state_free: + kfree(private_state); err_clk_notifier_unregister: clk_notifier_unregister(parent_clk, >clock_nb); err_devclk_disable: diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index aeb8a757d213..c819293b8317 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -45,6 +45,10 @@ struct soc_info { unsigned int weight, unsigned int offset); }; +struct ingenic_ipu_private_state { + struct drm_private_state base; +}; + struct ingenic_ipu { struct drm_plane plane;
[PATCH v3 1/6] drm/ingenic: Simplify code by using hwdescs array
Instead of having one 'hwdesc' variable for the plane #0, one for the plane #1 and one for the palette, use a 'hwdesc[3]' array, where the DMA hardware descriptors are indexed by the plane's number. v2: dma_hwdesc_addr() extended to support palette hwdesc. The palette hwdesc is now hwdesc[3] to simplify things. Add ingenic_drm_configure_hwdesc*() functions to factorize code. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 78 ++- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a5df1c8d34cd..95c12c2aba14 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -41,6 +41,8 @@ #include #include +#define HWDESC_PALETTE 2 + struct ingenic_dma_hwdesc { u32 next; u32 addr; @@ -49,9 +51,7 @@ struct ingenic_dma_hwdesc { } __aligned(16); struct ingenic_dma_hwdescs { - struct ingenic_dma_hwdesc hwdesc_f0; - struct ingenic_dma_hwdesc hwdesc_f1; - struct ingenic_dma_hwdesc hwdesc_pal; + struct ingenic_dma_hwdesc hwdesc[3]; u16 palette[256] __aligned(16); }; @@ -141,6 +141,14 @@ static inline struct ingenic_drm *drm_nb_get_priv(struct notifier_block *nb) return container_of(nb, struct ingenic_drm, clock_nb); } +static inline dma_addr_t dma_hwdesc_addr(const struct ingenic_drm *priv, +unsigned int idx) +{ + u32 offset = offsetof(struct ingenic_dma_hwdescs, hwdesc[idx]); + + return priv->dma_hwdescs_phys + offset; +} + static int ingenic_drm_update_pixclk(struct notifier_block *nb, unsigned long action, void *data) @@ -558,9 +566,9 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct ingenic_drm *priv = drm_device_get_priv(plane->dev); struct drm_plane_state *newstate = drm_atomic_get_new_plane_state(state, plane); struct drm_plane_state *oldstate = drm_atomic_get_old_plane_state(state, plane); + unsigned int width, height, cpp, next_id, plane_id; struct drm_crtc_state *crtc_state; struct ingenic_dma_hwdesc *hwdesc; - unsigned int width, height, cpp, offset; dma_addr_t addr; u32 fourcc; @@ -569,16 +577,14 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, drm_fb_cma_sync_non_coherent(>drm, oldstate, newstate); crtc_state = newstate->crtc->state; + plane_id = !!(priv->soc_info->has_osd && plane != >f0); addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0); width = newstate->src_w >> 16; height = newstate->src_h >> 16; cpp = newstate->fb->format->cpp[0]; - if (!priv->soc_info->has_osd || plane == >f0) - hwdesc = >dma_hwdescs->hwdesc_f0; - else - hwdesc = >dma_hwdescs->hwdesc_f1; + hwdesc = >dma_hwdescs->hwdesc[plane_id]; hwdesc->addr = addr; hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); @@ -588,12 +594,8 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, ingenic_drm_plane_config(priv->dev, plane, fourcc); - if (fourcc == DRM_FORMAT_C8) - offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_pal); - else - offset = offsetof(struct ingenic_dma_hwdescs, hwdesc_f0); - - priv->dma_hwdescs->hwdesc_f0.next = priv->dma_hwdescs_phys + offset; + next_id = fourcc == DRM_FORMAT_C8 ? HWDESC_PALETTE : 0; + priv->dma_hwdescs->hwdesc[0].next = dma_hwdesc_addr(priv, next_id); crtc_state->color_mgmt_changed = fourcc == DRM_FORMAT_C8; } @@ -846,6 +848,35 @@ static void __maybe_unused ingenic_drm_release_rmem(void *d) of_reserved_mem_device_release(d); } +static void ingenic_drm_configure_hwdesc(struct ingenic_drm *priv, +unsigned int hwdesc, +unsigned int next_hwdesc, u32 id) +{ + struct ingenic_dma_hwdesc *desc = >dma_hwdescs->hwdesc[hwdesc]; + + desc->next = dma_hwdesc_addr(priv, next_hwdesc); + desc->id = id; +} + +static void ingenic_drm_configure_hwdesc_palette(struct ingenic_drm *priv) +{ + struct ingenic_dma_hwdesc *desc; + + ingenic_drm_configure_hwdesc(priv, HWDESC_PALETTE, 0, 0xc0); + + desc = >dma_hwdescs->hwdesc[HWDESC_PALETTE]; + desc->addr = priv->dma_hwdescs_phys + + offsetof(struct ingenic_dma_hwdescs, palette); +
[PATCH v3 0/6] drm/ingenic: Various improvements v3
Hi, A V3 of my patchset for the ingenic-drm driver. The patches "drm/ingenic: Remove dead code" and "drm/ingenic: Use standard drm_atomic_helper_commit_tail" that were present in V1 have been merged in drm-misc-next, so they are not in this V3. Changelog since V2: [PATCH 5/6]: Fix ingenic_drm_get_new_priv_state() called instead of ingenic_drm_get_priv_state() Cheers, -Paul Paul Cercueil (6): drm/ingenic: Simplify code by using hwdescs array drm/ingenic: Add support for private objects drm/ingenic: Move IPU scale settings to private state drm/ingenic: Set DMA descriptor chain register when starting CRTC drm/ingenic: Upload palette before frame drm/ingenic: Attach bridge chain to encoders drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 278 +- drivers/gpu/drm/ingenic/ingenic-ipu.c | 127 -- 2 files changed, 333 insertions(+), 72 deletions(-) -- 2.33.0
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 1:19 PM Sudip Mukherjee wrote: > > I added some debugs to print the addresses, and I am getting: > [ 38.813809] sudip crtc > > This is from struct drm_crtc *crtc = connector->state->crtc; Yeah, that was my personal suspicion, because while the line number implied "crtc->state" being NULL, the drm data structure documentation and other drivers both imply that "crtc" was the more likely one. I suspect a simple if (!crtc) return; in vc4_hdmi_set_n_cts() is at least part of the fix for this all, but I didn't check if there is possibly something else that needs to be done too. Linus
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 7:23 PM Linus Torvalds wrote: > > On Wed, Sep 22, 2021 at 10:02 AM Sudip Mukherjee > wrote: > > > > > > Attached is a complete dmesg and also the decoded trace. > > This is done on 4357f03d6611 ("Merge tag 'pm-5.15-rc2' of > > git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm") > > drivers/gpu/drm/vc4/vc4_hdmi.c:1214 is > > tmp = (u64)(mode->clock * 1000) * n; > > in vc4_hdmi_set_n_cts(), which has apparently been inlined from > vc4_hdmi_audio_prepare() in vc4_hdmi.c:1398. > > So it looks like 'mode' is some offset off a NULL pointer. > > Which looks not impossible: > > 1207 struct drm_connector *connector = _hdmi->connector; > 1208 struct drm_crtc *crtc = connector->state->crtc; > 1209 const struct drm_display_mode *mode = > >state->adjusted_mode; > > looks like crtc->state perhaps might be NULL. I added some debugs to print the addresses, and I am getting: [ 38.813809] sudip crtc This is from struct drm_crtc *crtc = connector->state->crtc; connector and connector->state had valid addresses. [ 38.805302] sudip connector 40bac578 [ 38.809779] sudip state 57eb5400 This is the diff of the debug I added: diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4a1115043114..2a8f06948094 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1205,11 +1205,20 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) { struct drm_connector *connector = _hdmi->connector; - struct drm_crtc *crtc = connector->state->crtc; - const struct drm_display_mode *mode = >state->adjusted_mode; + struct drm_crtc *crtc; + struct drm_display_mode *mode; u32 n, cts; u64 tmp; + + pr_err("sudip connector %px\n", connector); + pr_err("sudip state %px\n", connector->state); + crtc = connector->state->crtc; + + pr_err("sudip crtc %px\n", crtc); + pr_err("sudip state %px\n", crtc->state); + pr_err("state mode %px\n", >state->adjusted_mode); + mode = >state->adjusted_mode; n = 128 * samplerate / 1000; tmp = (u64)(mode->clock * 1000) * n; do_div(tmp, 128 * samplerate); -- Regards Sudip
[PATCH] drm/rockchip: rgb: make connector a pointer in struct rockchip_rgb
As reported at [1] Coverity complains about an used value. Let's make drm_connector a pointer in struct rockchip_rgb and "remove redundant assignment of pointer connector". [1] https://lkml.org/lkml/2021/9/22/432 Fixes: 2e87bf389e13 ("drm/rockchip: add DRM_BRIDGE_ATTACH_NO_CONNECTOR flag to drm_bridge_attach") Addresses-Coverity: ("Unused value") Reported-by: Colin Ian King Signed-off-by: Alex Bee --- drivers/gpu/drm/rockchip/rockchip_rgb.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 09be9678f2bd..fe932c26c3e0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -28,7 +28,7 @@ struct rockchip_rgb { struct drm_device *drm_dev; struct drm_bridge *bridge; struct drm_encoder encoder; - struct drm_connector connector; + struct drm_connector *connector; int output_mode; }; @@ -82,7 +82,6 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, int ret = 0, child_count = 0; struct drm_panel *panel; struct drm_bridge *bridge; - struct drm_connector *connector; rgb = devm_kzalloc(dev, sizeof(*rgb), GFP_KERNEL); if (!rgb) @@ -150,17 +149,16 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, if (ret) goto err_free_encoder; - connector = >connector; - connector = drm_bridge_connector_init(rgb->drm_dev, encoder); - if (IS_ERR(connector)) { + rgb->connector = drm_bridge_connector_init(rgb->drm_dev, encoder); + if (IS_ERR(rgb->connector)) { DRM_DEV_ERROR(drm_dev->dev, "failed to initialize bridge connector: %pe\n", - connector); - ret = PTR_ERR(connector); + rgb->connector); + ret = PTR_ERR(rgb->connector); goto err_free_encoder; } - ret = drm_connector_attach_encoder(connector, encoder); + ret = drm_connector_attach_encoder(rgb->connector, encoder); if (ret < 0) { DRM_DEV_ERROR(drm_dev->dev, "failed to attach encoder: %d\n", ret); @@ -170,7 +168,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, return rgb; err_free_connector: - drm_connector_cleanup(connector); + drm_connector_cleanup(rgb->connector); err_free_encoder: drm_encoder_cleanup(encoder); return ERR_PTR(ret); @@ -180,7 +178,7 @@ EXPORT_SYMBOL_GPL(rockchip_rgb_init); void rockchip_rgb_fini(struct rockchip_rgb *rgb) { drm_panel_bridge_remove(rgb->bridge); - drm_connector_cleanup(>connector); + drm_connector_cleanup(rgb->connector); drm_encoder_cleanup(>encoder); } EXPORT_SYMBOL_GPL(rockchip_rgb_fini); -- 2.30.2
Re: [Intel-gfx] [PATCH 15/27] drm/i915/guc: Implement multi-lrc submission
On 9/22/2021 09:25, Matthew Brost wrote: On Mon, Sep 20, 2021 at 02:48:52PM -0700, John Harrison wrote: On 8/20/2021 15:44, Matthew Brost wrote: Implement multi-lrc submission via a single workqueue entry and single H2G. The workqueue entry contains an updated tail value for each request, of all the contexts in the multi-lrc submission, and updates these values simultaneously. As such, the tasklet and bypass path have been updated to coalesce requests into a single submission. Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 21 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.h| 8 + drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 24 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 6 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 312 +++--- drivers/gpu/drm/i915/i915_request.h | 8 + 6 files changed, 317 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index fbfcae727d7f..879aef662b2e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -748,3 +748,24 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p) } } } + +void intel_guc_write_barrier(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + + if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { + GEM_BUG_ON(guc->send_regs.fw_domains); Granted, this patch is just moving code from one file to another not changing it. However, I think it would be worth adding a blank line in here. Otherwise the 'this register' comment below can be confusingly read as referring to the send_regs.fw_domain entry above. And maybe add a comment why it is a bug for the send_regs value to be set? I'm not seeing any obvious connection between it and the reset of this code. Can add a blank line. I think the GEM_BUG_ON relates to being able to use intel_uncore_write_fw vs intel_uncore_write. Can add comment. + /* +* This register is used by the i915 and GuC for MMIO based +* communication. Once we are in this code CTBs are the only +* method the i915 uses to communicate with the GuC so it is +* safe to write to this register (a value of 0 is NOP for MMIO +* communication). If we ever start mixing CTBs and MMIOs a new +* register will have to be chosen. +*/ + intel_uncore_write_fw(gt->uncore, GEN11_SOFT_SCRATCH(0), 0); + } else { + /* wmb() sufficient for a barrier if in smem */ + wmb(); + } +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 3f95b1b4f15c..0ead2406d03c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -37,6 +37,12 @@ struct intel_guc { /* Global engine used to submit requests to GuC */ struct i915_sched_engine *sched_engine; struct i915_request *stalled_request; + enum { + STALL_NONE, + STALL_REGISTER_CONTEXT, + STALL_MOVE_LRC_TAIL, + STALL_ADD_REQUEST, + } submission_stall_reason; /* intel_guc_recv interrupt related state */ spinlock_t irq_lock; @@ -332,4 +338,6 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc); void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p); +void intel_guc_write_barrier(struct intel_guc *guc); + #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 20c710a74498..10d1878d2826 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -377,28 +377,6 @@ static u32 ct_get_next_fence(struct intel_guc_ct *ct) return ++ct->requests.last_fence; } -static void write_barrier(struct intel_guc_ct *ct) -{ - struct intel_guc *guc = ct_to_guc(ct); - struct intel_gt *gt = guc_to_gt(guc); - - if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { - GEM_BUG_ON(guc->send_regs.fw_domains); - /* -* This register is used by the i915 and GuC for MMIO based -* communication. Once we are in this code CTBs are the only -* method the i915 uses to communicate with the GuC so it is -* safe to write to this register (a value of 0 is NOP for MMIO -* communication). If we ever start mixing CTBs and MMIOs a new -* register will have to be chosen. -*/ - intel_uncore_write_fw(gt->uncore, GEN11_SOFT_SCRATCH(0), 0); - } else { - /* wmb() sufficient for a barrier if in smem */ - wmb(); - } -} - static int ct_write(struct
Re: [PATCH v3 5/8] x86/sme: Replace occurrences of sme_active() with cc_platform_has()
On Wed, Sep 22, 2021 at 05:30:15PM +0300, Kirill A. Shutemov wrote: > Not fine, but waiting to blowup with random build environment change. Why is it not fine? Are you suspecting that the compiler might generate something else and not a rip-relative access? -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette
[PATCH] drm/i915: Fix bug in user proto-context creation that leaked contexts
Set number of engines before attempting to create contexts so the function free_engines can clean up properly. Also check return of alloc_engines for NULL. v2: (Tvrtko) - Send as stand alone patch (John Harrison) - Check for alloc_engines returning NULL Cc: Jason Ekstrand Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create parameters (v5)") Signed-off-by: Matthew Brost Cc: --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..9627c7aac6a3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -898,6 +898,11 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, unsigned int n; e = alloc_engines(num_engines); + if (!e) { + return ERR_PTR(-ENOMEM); + } + e->num_engines = num_engines; + for (n = 0; n < num_engines; n++) { struct intel_context *ce; int ret; @@ -931,7 +936,6 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, goto free_engines; } } - e->num_engines = num_engines; return e; -- 2.32.0
Re: [PATCH][next] drm/rockchip: Remove redundant assignment of pointer connector
Hi all, Am 22.09.21 um 19:31 schrieb Alex Bee: Hi Heiko, Am 22.09.21 um 18:45 schrieb Heiko Stübner: Hi Alex, Am Mittwoch, 22. September 2021, 18:35:38 CEST schrieb Alex Bee: Hi Colin, Am 22.09.21 um 13:24 schrieb Colin King: From: Colin Ian King The pointer connector is being assigned a value that is never read, it is being updated immediately afterwards. The assignment is redundant and can be removed. The pointer to the connector is used in rockchip_rgb_fini for drm_connector_cleanup. It's pretty much the same for the encoder, btw. I think the issue is more the two lines connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); hence the connector = >connector being overwritten immediately after Now that I look at it again, the whole approach looks strange. drm_bridge_connector_init() creates the connector structure and returns a pointer to it. Totally agreed. The main reason I was doing it that way, was the way it was done already in rockchip_lvds.c, where the connector was already existent in the struct rockchip_lvds (and was already used in the panel-case - all places where it is used accept pointers also, btw) and is *no* pointer - and is done already this very strange way. I wanted to re-use it for the bridge-case and didn't want to differ in coding in rockchip-rgb to much. The only reason I can think of, why it was done that way is, that we might need a pointer to a fully initialized struct drm_connector for some reason (drm_connector_cleanup ?), what we wouldn't have if have just a pointer and something goes wrong before drm_connector_init respectivly drm_bridge_connector_init. Alex So the first line below sets the connector pointer to point to the >connector element and the second line then set a completely different address into it. So the connector element in rockchip_lvds and rockchip_rgb should actually become a pointer itself to hold the connector element returned from drm_bridge_connector_init() . It turns out, nothing bad happens (i.e. rockchip_rgb_fini, the only place where the connector is also used, isn't called if rockchip_rgb_init fails) - so it will be OK if we make the connector a pointer in struct rockchip_rgb. But we'll need to keep it a "full" struct drm_connector in struct rockchip_lvds, since in case it's a panel it gets properties assigend before drm_connector_init is called and should for that reason initialized before. I'll send a patch soon. Alex Heiko Regards, Alex Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King --- drivers/gpu/drm/rockchip/rockchip_rgb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 09be9678f2bd..18fb84068a64 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -150,7 +150,6 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, if (ret) goto err_free_encoder; - connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); if (IS_ERR(connector)) { DRM_DEV_ERROR(drm_dev->dev,
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 10:02 AM Sudip Mukherjee wrote: > > > Attached is a complete dmesg and also the decoded trace. > This is done on 4357f03d6611 ("Merge tag 'pm-5.15-rc2' of > git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm") drivers/gpu/drm/vc4/vc4_hdmi.c:1214 is tmp = (u64)(mode->clock * 1000) * n; in vc4_hdmi_set_n_cts(), which has apparently been inlined from vc4_hdmi_audio_prepare() in vc4_hdmi.c:1398. So it looks like 'mode' is some offset off a NULL pointer. Which looks not impossible: 1207 struct drm_connector *connector = _hdmi->connector; 1208 struct drm_crtc *crtc = connector->state->crtc; 1209 const struct drm_display_mode *mode = >state->adjusted_mode; looks like crtc->state perhaps might be NULL. Although it's entirely possible that it's 'crtc' itself that is NULL or one of the earlier indirection accesses. The exact line information from the debug info is very useful and mostly correct, but at the same time should always be taken with a small pinch of salt. Compiler optimizations means that code gets munged and moved around, and since this is the first access to 'mode', I would not be surprised if some of the calculations and accesses to get 'mode' might be moved around to it. Linus
Re: [RESEND] [PATCH v2 1/2] dt-bindings: display: bridge: Add binding for R-Car MIPI DSI/CSI-2 TX
Hi Laurent, On Wed, Sep 22, 2021 at 10:08 AM Laurent Pinchart wrote: > On Wed, Sep 22, 2021 at 08:43:57AM +0200, Geert Uytterhoeven wrote: > > On Wed, Sep 22, 2021 at 3:27 AM Laurent Pinchart wrote: > > > On Tue, Sep 21, 2021 at 05:53:52PM +0200, Geert Uytterhoeven wrote: > > > > On Wed, Jul 28, 2021 at 6:26 PM Laurent Pinchart wrote: > > > > > The R-Car MIPI DSI/CSI-2 TX is embedded in the Renesas R-Car V3U SoC. > > > > > It > > > > > can operate in either DSI or CSI-2 mode, with up to four data lanes. > > > > > > > > > > Signed-off-by: Laurent Pinchart > > > > > > > > > > Reviewed-by: Kieran Bingham > > > > > > > > Thanks for your patch! > > > > > > > > > --- /dev/null > > > > > +++ > > > > > b/Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml > > > > > @@ -0,0 +1,118 @@ > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > > > +%YAML 1.2 > > > > > +--- > > > > > +$id: > > > > > http://devicetree.org/schemas/display/bridge/renesas,dsi-csi2-tx.yaml# > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > > > + > > > > > +title: Renesas R-Car MIPI DSI/CSI-2 Encoder > > > > > + > > > > > +maintainers: > > > > > + - Laurent Pinchart > > > > > + > > > > > +description: | > > > > > + This binding describes the MIPI DSI/CSI-2 encoder embedded in the > > > > > Renesas > > > > > + R-Car V3U SoC. The encoder can operate in either DSI or CSI-2 > > > > > mode, with up > > > > > + to four data lanes. > > > > > + > > > > > +properties: > > > > > + compatible: > > > > > +enum: > > > > > + - renesas,r8a779a0-dsi-csi2-tx# for V3U > > > > > + > > > > > + reg: > > > > > +maxItems: 1 > > > > > + > > > > > + clocks: > > > > > +items: > > > > > + - description: Functional clock > > > > > + - description: DSI (and CSI-2) functional clock > > > > > + - description: PLL reference clock > > > > > + > > > > > + clock-names: > > > > > +items: > > > > > + - const: fck > > > > > + - const: dsi > > > > > + - const: pll > > > > > > > > No interrupts? > > > > The hardware manual says there are 9 interrupts. > > > > > > Who comes up with such insanely high numbers of interrupts ? :-) > > > > > > What the hardware manual doesn't document is how interrupts are mapped. > > > There's indeed 9 of them, and there are 9 interrupt sources, but that's > > > all we know. I can easily add a > > > > > > interrupts: > > > maxItems: 9 > > > > > > but I can add interrupt names without additional information. It may be > > > possible to deduce some of the interrupt mappings from experiments, but > > > not all of them. What do you think would be a good way forward ? Leave > > > the interrupts out for now as we don't have the information ? Only list > > > the interrupts but not their names ? Something else ? > > > > I think what we did in the past is not list the interrupts at all. > > They can be added once we receive more documentation. > > Sounds good to me, as that's what this patch does already ;-) A R-b or > A-b tag is welcome. Your wish is my command... Reviewed-by: Geert Uytterhoeven Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH v2 4/5] drm: rcar-du: Split CRTC IRQ and Clock features
Hi Kieran, Thank you for the patch. On Thu, Sep 02, 2021 at 12:49:06AM +0100, Kieran Bingham wrote: > Not all platforms require both per-crtc IRQ and per-crtc clock > management. In preparation for suppporting such platforms, split the > feature macro to be able to specify both features independently. > > The other features are incremented accordingly, to keep the two crtc > features adjacent. > > Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart > --- > v2: > - New patch > > drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 +-- > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 48 +- > drivers/gpu/drm/rcar-du/rcar_du_drv.h | 9 ++--- > 3 files changed, 39 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > index a0f837e8243a..5672830ca184 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > @@ -1206,7 +1206,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, > unsigned int swindex, > int ret; > > /* Get the CRTC clock and the optional external clock. */ > - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { > + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_CLOCK)) { > sprintf(clk_name, "du.%u", hwindex); > name = clk_name; > } else { > @@ -1272,7 +1272,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, > unsigned int swindex, > drm_crtc_helper_add(crtc, _helper_funcs); > > /* Register the interrupt handler. */ > - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { > + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ)) { > /* The IRQ's are associated with the CRTC (sw)index. */ > irq = platform_get_irq(pdev, swindex); > irqflags = 0; > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > index 4ac26d08ebb4..8a094d5b9c77 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > @@ -36,7 +36,8 @@ > > static const struct rcar_du_device_info rzg1_du_r8a7743_info = { > .gen = 2, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_INTERLACED > | RCAR_DU_FEATURE_TVM_SYNC, > .channels_mask = BIT(1) | BIT(0), > @@ -58,7 +59,8 @@ static const struct rcar_du_device_info > rzg1_du_r8a7743_info = { > > static const struct rcar_du_device_info rzg1_du_r8a7745_info = { > .gen = 2, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_INTERLACED > | RCAR_DU_FEATURE_TVM_SYNC, > .channels_mask = BIT(1) | BIT(0), > @@ -79,7 +81,8 @@ static const struct rcar_du_device_info > rzg1_du_r8a7745_info = { > > static const struct rcar_du_device_info rzg1_du_r8a77470_info = { > .gen = 2, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_INTERLACED > | RCAR_DU_FEATURE_TVM_SYNC, > .channels_mask = BIT(1) | BIT(0), > @@ -105,7 +108,8 @@ static const struct rcar_du_device_info > rzg1_du_r8a77470_info = { > > static const struct rcar_du_device_info rcar_du_r8a774a1_info = { > .gen = 3, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_VSP1_SOURCE > | RCAR_DU_FEATURE_INTERLACED > | RCAR_DU_FEATURE_TVM_SYNC, > @@ -134,7 +138,8 @@ static const struct rcar_du_device_info > rcar_du_r8a774a1_info = { > > static const struct rcar_du_device_info rcar_du_r8a774b1_info = { > .gen = 3, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_VSP1_SOURCE > | RCAR_DU_FEATURE_INTERLACED > | RCAR_DU_FEATURE_TVM_SYNC, > @@ -163,7 +168,8 @@ static const struct rcar_du_device_info > rcar_du_r8a774b1_info = { > > static const struct rcar_du_device_info rcar_du_r8a774c0_info = { > .gen = 3, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK > + .features = RCAR_DU_FEATURE_CRTC_IRQ > + | RCAR_DU_FEATURE_CRTC_CLOCK > | RCAR_DU_FEATURE_VSP1_SOURCE, > .channels_mask = BIT(1) | BIT(0), > .routes = { > @@ -189,7 +195,8 @@ static const struct rcar_du_device_info > rcar_du_r8a774c0_info = { > > static const struct rcar_du_device_info rcar_du_r8a774e1_info = { > .gen = 3, > - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
[PATCH] drm/amd/display: Only define DP 2.0 symbols if not already defined
[Why] For some reason we're defining DP 2.0 definitions inside our driver. Now that patches to introduce relevant definitions are slated to be merged into drm-next this is causing conflicts. In file included from drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c:33: In file included from ./drivers/gpu/drm/amd/amdgpu/../amdgpu/amdgpu.h:70: In file included from ./drivers/gpu/drm/amd/amdgpu/../amdgpu/amdgpu_mode.h:36: ./include/drm/drm_dp_helper.h:1322:9: error: 'DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER' macro redefined [-Werror,-Wmacro-redefined] ^ ./drivers/gpu/drm/amd/amdgpu/../display/dc/dc_dp_types.h:881:9: note: previous definition is here ^ 1 error generated. [How] Guard all display driver defines with #ifndef for now. Once we pull in the new definitions into amd-staging-drm-next we will follow up and drop definitions from our driver and provide follow-up header updates for any addition DP 2.0 definitions required by our driver. Signed-off-by: Harry Wentland --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 53 ++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index a5e798b5da79..74b8de616dcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -860,28 +860,71 @@ struct psr_caps { }; #if defined(CONFIG_DRM_AMD_DC_DCN) +#ifndef DP_MAIN_LINK_CHANNEL_CODING_CAP #define DP_MAIN_LINK_CHANNEL_CODING_CAP0x006 +#endif +#ifndef DP_SINK_VIDEO_FALLBACK_FORMATS #define DP_SINK_VIDEO_FALLBACK_FORMATS 0x020 +#endif +#ifndef DP_FEC_CAPABILITY_1 #define DP_FEC_CAPABILITY_10x091 +#endif +#ifndef DP_DFP_CAPABILITY_EXTENSION_SUPPORT #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0A3 +#endif +#ifndef DP_DSC_CONFIGURATION #define DP_DSC_CONFIGURATION 0x161 +#endif +#ifndef DP_PHY_SQUARE_PATTERN #define DP_PHY_SQUARE_PATTERN 0x249 +#endif +#ifndef DP_128b_132b_SUPPORTED_LINK_RATES #define DP_128b_132b_SUPPORTED_LINK_RATES 0x2215 +#endif +#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL #define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216 +#endif +#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0 #define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230 +#endif +#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_263_256 #define DP_TEST_264BIT_CUSTOM_PATTERN_263_256 0X2250 +#endif +#ifndef DP_DSC_SUPPORT_AND_DECODER_COUNT #define DP_DSC_SUPPORT_AND_DECODER_COUNT 0x2260 +#endif +#ifndef DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0 #define DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0 0x2270 -# define DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK (1 << 0) -# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK (0b111 << 1) -# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT1 -# define DP_DSC_DECODER_COUNT_MASK (0b111 << 5) -# define DP_DSC_DECODER_COUNT_SHIFT5 +#endif +#ifndef DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK +#define DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK (1 << 0) +#endif +#ifndef DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK +#define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK (0b111 << 1) +#endif +#ifndef DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT +#define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT 1 +#endif +#ifndef DP_DSC_DECODER_COUNT_MASK +#define DP_DSC_DECODER_COUNT_MASK (0b111 << 5) +#endif +#ifndef DP_DSC_DECODER_COUNT_SHIFT +#define DP_DSC_DECODER_COUNT_SHIFT 5 +#endif +#ifndef DP_MAIN_LINK_CHANNEL_CODING_SET #define DP_MAIN_LINK_CHANNEL_CODING_SET0x108 +#endif +#ifndef DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER #define DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER 0xF0006 +#endif +#ifndef DP_PHY_REPEATER_128b_132b_RATES #define DP_PHY_REPEATER_128b_132b_RATES0xF0007 +#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 #define DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER10xF0022 +#endif +#ifndef DP_INTRA_HOP_AUX_REPLY_INDICATION #define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3) +#endif /* TODO - Use DRM header to replace above once available */ union dp_main_line_channel_coding_cap { -- 2.33.0
Re: [PATCH][next] drm/rockchip: Remove redundant assignment of pointer connector
Hi Heiko, Am 22.09.21 um 18:45 schrieb Heiko Stübner: Hi Alex, Am Mittwoch, 22. September 2021, 18:35:38 CEST schrieb Alex Bee: Hi Colin, Am 22.09.21 um 13:24 schrieb Colin King: From: Colin Ian King The pointer connector is being assigned a value that is never read, it is being updated immediately afterwards. The assignment is redundant and can be removed. The pointer to the connector is used in rockchip_rgb_fini for drm_connector_cleanup. It's pretty much the same for the encoder, btw. I think the issue is more the two lines connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); hence the connector = >connector being overwritten immediately after Now that I look at it again, the whole approach looks strange. drm_bridge_connector_init() creates the connector structure and returns a pointer to it. Totally agreed. The main reason I was doing it that way, was the way it was done already in rockchip_lvds.c, where the connector was already existent in the struct rockchip_lvds (and was already used in the panel-case - all places where it is used accept pointers also, btw) and is *no* pointer - and is done already this very strange way. I wanted to re-use it for the bridge-case and didn't want to differ in coding in rockchip-rgb to much. The only reason I can think of, why it was done that way is, that we might need a pointer to a fully initialized struct drm_connector for some reason (drm_connector_cleanup ?), what we wouldn't have if have just a pointer and something goes wrong before drm_connector_init respectivly drm_bridge_connector_init. Alex So the first line below sets the connector pointer to point to the >connector element and the second line then set a completely different address into it. So the connector element in rockchip_lvds and rockchip_rgb should actually become a pointer itself to hold the connector element returned from drm_bridge_connector_init() . Heiko Regards, Alex Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King --- drivers/gpu/drm/rockchip/rockchip_rgb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 09be9678f2bd..18fb84068a64 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -150,7 +150,6 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, if (ret) goto err_free_encoder; - connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); if (IS_ERR(connector)) { DRM_DEV_ERROR(drm_dev->dev,
Re: [PATCH v2 3/5] drm: rcar-du: Fix DIDSR field name
Hi Kieran, Thank you for the patch. On Thu, Sep 02, 2021 at 12:49:05AM +0100, Kieran Bingham wrote: > The DIDSR fields named LDCS were incorrectly defined as LCDS. > Both the Gen2 and Gen3 documentation refer to the fields as the "LVDS > Dot Clock Select". > > Correct the definitions. > > Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart > --- > v2: > - New patch > > drivers/gpu/drm/rcar-du/rcar_du_group.c | 4 ++-- > drivers/gpu/drm/rcar-du/rcar_du_regs.h | 8 > 2 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c > b/drivers/gpu/drm/rcar-du/rcar_du_group.c > index 88a783ceb3e9..a984eef265d2 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c > @@ -122,10 +122,10 @@ static void rcar_du_group_setup_didsr(struct > rcar_du_group *rgrp) > didsr = DIDSR_CODE; > for (i = 0; i < num_crtcs; ++i, ++rcrtc) { > if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) > - didsr |= DIDSR_LCDS_LVDS0(i) > + didsr |= DIDSR_LDCS_LVDS0(i) > | DIDSR_PDCS_CLK(i, 0); > else > - didsr |= DIDSR_LCDS_DCLKIN(i) > + didsr |= DIDSR_LDCS_DCLKIN(i) > | DIDSR_PDCS_CLK(i, 0); > } > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h > b/drivers/gpu/drm/rcar-du/rcar_du_regs.h > index fb9964949368..fb7c467aa484 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h > @@ -257,10 +257,10 @@ > > #define DIDSR0x20028 > #define DIDSR_CODE (0x7790 << 16) > -#define DIDSR_LCDS_DCLKIN(n) (0 << (8 + (n) * 2)) > -#define DIDSR_LCDS_LVDS0(n) (2 << (8 + (n) * 2)) > -#define DIDSR_LCDS_LVDS1(n) (3 << (8 + (n) * 2)) > -#define DIDSR_LCDS_MASK(n) (3 << (8 + (n) * 2)) > +#define DIDSR_LDCS_DCLKIN(n) (0 << (8 + (n) * 2)) > +#define DIDSR_LDCS_LVDS0(n) (2 << (8 + (n) * 2)) > +#define DIDSR_LDCS_LVDS1(n) (3 << (8 + (n) * 2)) > +#define DIDSR_LDCS_MASK(n) (3 << (8 + (n) * 2)) > #define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2)) > #define DIDSR_PDCS_MASK(n) (3 << ((n) * 2)) > -- Regards, Laurent Pinchart
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 12:28 PM Maxime Ripard wrote: > > On Wed, Sep 22, 2021 at 11:10:34AM +0100, Sudip Mukherjee wrote: > > On Wed, Sep 22, 2021 at 10:57 AM Maxime Ripard wrote: > > > > > Still works fine (and it required some mangling of the kernel command line). > > If we summarize: > > - You initially just dumped a panic and a link to your QA, without any > more context: The SHA was also given, and I didn't know what else you would need. The openQA link was given to show the dmesg. > > - Then stating that you're not doing any test, really; Yes, and I still say that, its just a boot test. > > - Well, except for booting Ubuntu, but no other modification > > - But you're not booting the standard image > > - And with a custom initrd yes, something which has always worked in boot-testing LTS kernel or mainline kernel. > > - And that QA link states that you're booting from QEMU, but you're > not. I only found that the "WORKER_CLASS" has the name "qemu_rpi4", that is a name which I choose to give as that worker laptop is connected to rpi4 and also running qemu tests. If you want I can change the name of the WORKER_CLASS. :) iiuc, dmesg shows if its booting in a qemu or on a real hardware. > > Please provide a full documentation on what you're doing to generate > that image, from scratch, in order to get that panic you reported > previously. I have now ordered another rpi4 board and will create the image from scratch and give you the steps. > > I've spent an entire day trying to make sense of what you're doing > exactly to get into that situation. I have other things to work on and I > don't plan on figuring out any random CI system. I am not really sure why you are trying to figure out a random CI system. I can reproduce the problem in our setup everytime I test with that reverted commit and I have already said I am happy to test with a debug patch or anything else. -- Regards Sudip
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 4:25 PM Linus Torvalds wrote: > > On Wed, Sep 22, 2021 at 3:11 AM Sudip Mukherjee > wrote: > > > > That test script is triggering the openqa job, but its running only > > after lava is able to login. The trace is appearing before the login > > prompt even, so test_mainline.sh should not matter here. > > Side note: the traces might be more legible if you have debug info in > the kernel, and run the dmesg through the script in > > scripts/decode_stacktrace.sh > > which should give line numbers and inlining information. Attached is a complete dmesg and also the decoded trace. This is done on 4357f03d6611 ("Merge tag 'pm-5.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm") -- Regards Sudip [0.00] Booting Linux on physical CPU 0x00 [0x410fd083] [0.00] Linux version 5.15.0-rc1-4357f03d6611 (smukherjee@db7e030c489f) (aarch64-linux-gcc (GCC) 11.2.1 20210911, GNU ld (GNU Binutils) 2.36.1) #1 SMP PREEMPT Wed Sep 22 15:18:16 UTC 2021 [0.00] Machine model: Raspberry Pi 4 Model B [0.00] efi: UEFI not found. [0.00] Reserved memory: created CMA memory pool at 0x3280, size 64 MiB [0.00] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool [0.00] Zone ranges: [0.00] DMA [mem 0x-0x3fff] [0.00] DMA32[mem 0x4000-0xfbff] [0.00] Normal empty [0.00] Movable zone start for each node [0.00] Early memory node ranges [0.00] node 0: [mem 0x-0x3b3f] [0.00] node 0: [mem 0x4000-0xfbff] [0.00] Initmem setup node 0 [mem 0x-0xfbff] [0.00] percpu: Embedded 29 pages/cpu s80344 r8192 d30248 u118784 [0.00] pcpu-alloc: s80344 r8192 d30248 u118784 alloc=29*4096 [0.00] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0.00] Detected PIPT I-cache on CPU0 [0.00] CPU features: detected: Spectre-v2 [0.00] CPU features: detected: Spectre-v3a [0.00] CPU features: detected: Spectre-v4 [0.00] CPU features: detected: ARM errata 1165522, 1319367, or 1530923 [0.00] Built 1 zonelists, mobility grouping on. Total pages: 996912 [0.00] Kernel command line: console=ttyS0,115200n8 root=/dev/ram0 coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 bcm2708_fb.fbwidth=0 bcm2708_fb.fbheight=0 bcm2708_fb.fbswap=1 smsc95xx.macaddr=DC:A6:32:BC:4B:41 vc_mem.mem_base=0x3ec0 vc_mem.mem_size=0x4000 dwc_otg.lpm_enable=0 root=LABEL=writable1 rootfstype=ext4 elevator=deadline rootwait fixrtc loglevel=7 ip=dhcp [0.00] Kernel parameter elevator= does not have any effect anymore. Please use sysfs to set IO scheduler for individual devices. [0.00] Unknown command line parameters: fixrtc [0.00] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear) [0.00] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear) [0.00] mem auto-init: stack:off, heap alloc:off, heap free:off [0.00] software IO TLB: mapped [mem 0x2e80-0x3280] (64MB) [0.00] Memory: 3742168K/4050944K available (12928K kernel code, 1960K rwdata, 4868K rodata, 4352K init, 843K bss, 243240K reserved, 65536K cma-reserved) [0.00] random: get_random_u64 called from __kmem_cache_create+0x38/0x4e0 with crng_init=0 [0.00] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 [0.00] ftrace: allocating 40527 entries in 159 pages [0.00] ftrace: allocated 159 pages with 6 groups [0.00] trace event string verifier disabled [0.00] rcu: Preemptible hierarchical RCU implementation. [0.00] rcu: RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=4. [0.00] Trampoline variant of Tasks RCU enabled. [0.00] Rude variant of Tasks RCU enabled. [0.00] Tracing variant of Tasks RCU enabled. [0.00] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies. [0.00] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4 [0.00] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0 [0.00] Root IRQ handler: gic_handle_irq [0.00] GIC: Using split EOI/Deactivate mode [0.00] irq_brcmstb_l2: registered L2 intc (/soc/interrupt-controller@7ef00100, parent irq: 10) [0.00] arch_timer: cp15 timer(s) running at 54.00MHz (phys). [0.00] clocksource: arch_sys_counter: mask: 0xff max_cycles: 0xc743ce346, max_idle_ns: 440795203123 ns [0.01] sched_clock: 56 bits at 54MHz, resolution 18ns, wraps every 4398046511102ns [0.000189] Console: colour dummy device 80x25 [0.000266] Calibrating delay loop (skipped), value calculated using timer frequency.. 108.00 BogoMIPS
Re: [PATCH][next] drm/rockchip: Remove redundant assignment of pointer connector
Hi Alex, Am Mittwoch, 22. September 2021, 18:35:38 CEST schrieb Alex Bee: > Hi Colin, > Am 22.09.21 um 13:24 schrieb Colin King: > > From: Colin Ian King > > > > The pointer connector is being assigned a value that is never > > read, it is being updated immediately afterwards. The assignment > > is redundant and can be removed. > > The pointer to the connector is used in rockchip_rgb_fini for > drm_connector_cleanup. > It's pretty much the same for the encoder, btw. I think the issue is more the two lines connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); hence the connector = >connector being overwritten immediately after Now that I look at it again, the whole approach looks strange. drm_bridge_connector_init() creates the connector structure and returns a pointer to it. So the first line below sets the connector pointer to point to the >connector element and the second line then set a completely different address into it. So the connector element in rockchip_lvds and rockchip_rgb should actually become a pointer itself to hold the connector element returned from drm_bridge_connector_init() . Heiko > > Regards, > > Alex > > > > Addresses-Coverity: ("Unused value") > > Signed-off-by: Colin Ian King > > --- > > drivers/gpu/drm/rockchip/rockchip_rgb.c | 1 - > > 1 file changed, 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c > > b/drivers/gpu/drm/rockchip/rockchip_rgb.c > > index 09be9678f2bd..18fb84068a64 100644 > > --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c > > +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c > > @@ -150,7 +150,6 @@ struct rockchip_rgb *rockchip_rgb_init(struct device > > *dev, > > if (ret) > > goto err_free_encoder; > > > > - connector = >connector; > > connector = drm_bridge_connector_init(rgb->drm_dev, encoder); > > if (IS_ERR(connector)) { > > DRM_DEV_ERROR(drm_dev->dev, > > > >
Re: [Intel-gfx] [PATCH 20/27] drm/i915/guc: Connect UAPI to GuC multi-lrc interface
On Mon, Sep 20, 2021 at 05:09:28PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Introduce 'set parallel submit' extension to connect UAPI to GuC > > multi-lrc interface. Kernel doc in new uAPI should explain it all. > > > > IGT: https://patchwork.freedesktop.org/patch/447008/?series=93071=1 > > media UMD: link to come > Is this link still not available? > Have it now: https://github.com/intel/media-driver/pull/1252 > Also, see 'kernel test robot' emails saying that sparse is complaining about > something I don't understand but presumably needs to be fixed. > Yea, those warning need to be fixed. > > > > > v2: > > (Daniel Vetter) > >- Add IGT link and placeholder for media UMD link > > > > Cc: Tvrtko Ursulin > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/gem/i915_gem_context.c | 220 +- > > .../gpu/drm/i915/gem/i915_gem_context_types.h | 6 + > > drivers/gpu/drm/i915/gt/intel_context_types.h | 9 +- > > drivers/gpu/drm/i915/gt/intel_engine.h| 12 +- > > drivers/gpu/drm/i915/gt/intel_engine_cs.c | 6 +- > > .../drm/i915/gt/intel_execlists_submission.c | 6 +- > > drivers/gpu/drm/i915/gt/selftest_execlists.c | 12 +- > > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 114 - > > include/uapi/drm/i915_drm.h | 128 ++ > > 9 files changed, 485 insertions(+), 28 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > index bcaaf514876b..de0fd145fb47 100644 > > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > @@ -522,9 +522,149 @@ set_proto_ctx_engines_bond(struct i915_user_extension > > __user *base, void *data) > > return 0; > > } > > +static int > > +set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user > > *base, > > + void *data) > > +{ > > + struct i915_context_engines_parallel_submit __user *ext = > > + container_of_user(base, typeof(*ext), base); > > + const struct set_proto_ctx_engines *set = data; > > + struct drm_i915_private *i915 = set->i915; > > + u64 flags; > > + int err = 0, n, i, j; > > + u16 slot, width, num_siblings; > > + struct intel_engine_cs **siblings = NULL; > > + intel_engine_mask_t prev_mask; > > + > > + /* Disabling for now */ > > + return -ENODEV; > > + > > + if (!(intel_uc_uses_guc_submission(>gt.uc))) > > + return -ENODEV; > This needs a FIXME comment to say that exec list will be added later. > Sure. > > + > > + if (get_user(slot, >engine_index)) > > + return -EFAULT; > > + > > + if (get_user(width, >width)) > > + return -EFAULT; > > + > > + if (get_user(num_siblings, >num_siblings)) > > + return -EFAULT; > > + > > + if (slot >= set->num_engines) { > > + drm_dbg(>drm, "Invalid placement value, %d >= %d\n", > > + slot, set->num_engines); > > + return -EINVAL; > > + } > > + > > + if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) { > > + drm_dbg(>drm, > > + "Invalid placement[%d], already occupied\n", slot); > > + return -EINVAL; > > + } > > + > > + if (get_user(flags, >flags)) > > + return -EFAULT; > > + > > + if (flags) { > > + drm_dbg(>drm, "Unknown flags 0x%02llx", flags); > > + return -EINVAL; > > + } > > + > > + for (n = 0; n < ARRAY_SIZE(ext->mbz64); n++) { > > + err = check_user_mbz(>mbz64[n]); > > + if (err) > > + return err; > > + } > > + > > + if (width < 2) { > > + drm_dbg(>drm, "Width (%d) < 2\n", width); > > + return -EINVAL; > > + } > > + > > + if (num_siblings < 1) { > > + drm_dbg(>drm, "Number siblings (%d) < 1\n", > > + num_siblings); > > + return -EINVAL; > > + } > > + > > + siblings = kmalloc_array(num_siblings * width, > > +sizeof(*siblings), > > +GFP_KERNEL); > > + if (!siblings) > > + return -ENOMEM; > > + > > + /* Create contexts / engines */ > > + for (i = 0; i < width; ++i) { > > + intel_engine_mask_t current_mask = 0; > > + struct i915_engine_class_instance prev_engine; > > + > > + for (j = 0; j < num_siblings; ++j) { > > + struct i915_engine_class_instance ci; > > + > > + n = i * num_siblings + j; > > + if (copy_from_user(, >engines[n], sizeof(ci))) { > > + err = -EFAULT; > > + goto out_err; > > + } > > + > > + siblings[n] = > > + intel_engine_lookup_user(i915, ci.engine_class, > > +
Re: [PATCH][next] drm/rockchip: Remove redundant assignment of pointer connector
Hi Colin, Am 22.09.21 um 13:24 schrieb Colin King: From: Colin Ian King The pointer connector is being assigned a value that is never read, it is being updated immediately afterwards. The assignment is redundant and can be removed. The pointer to the connector is used in rockchip_rgb_fini for drm_connector_cleanup. It's pretty much the same for the encoder, btw. Regards, Alex Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King --- drivers/gpu/drm/rockchip/rockchip_rgb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 09be9678f2bd..18fb84068a64 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -150,7 +150,6 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev, if (ret) goto err_free_encoder; - connector = >connector; connector = drm_bridge_connector_init(rgb->drm_dev, encoder); if (IS_ERR(connector)) { DRM_DEV_ERROR(drm_dev->dev,
Re: [Intel-gfx] [PATCH 15/27] drm/i915/guc: Implement multi-lrc submission
On Mon, Sep 20, 2021 at 02:48:52PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Implement multi-lrc submission via a single workqueue entry and single > > H2G. The workqueue entry contains an updated tail value for each > > request, of all the contexts in the multi-lrc submission, and updates > > these values simultaneously. As such, the tasklet and bypass path have > > been updated to coalesce requests into a single submission. > > > > Signed-off-by: Matthew Brost > > --- > > drivers/gpu/drm/i915/gt/uc/intel_guc.c| 21 ++ > > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 8 + > > drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 24 +- > > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 6 +- > > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 312 +++--- > > drivers/gpu/drm/i915/i915_request.h | 8 + > > 6 files changed, 317 insertions(+), 62 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > index fbfcae727d7f..879aef662b2e 100644 > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c > > @@ -748,3 +748,24 @@ void intel_guc_load_status(struct intel_guc *guc, > > struct drm_printer *p) > > } > > } > > } > > + > > +void intel_guc_write_barrier(struct intel_guc *guc) > > +{ > > + struct intel_gt *gt = guc_to_gt(guc); > > + > > + if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { > > + GEM_BUG_ON(guc->send_regs.fw_domains); > Granted, this patch is just moving code from one file to another not > changing it. However, I think it would be worth adding a blank line in here. > Otherwise the 'this register' comment below can be confusingly read as > referring to the send_regs.fw_domain entry above. > > And maybe add a comment why it is a bug for the send_regs value to be set? > I'm not seeing any obvious connection between it and the reset of this code. > Can add a blank line. I think the GEM_BUG_ON relates to being able to use intel_uncore_write_fw vs intel_uncore_write. Can add comment. > > + /* > > +* This register is used by the i915 and GuC for MMIO based > > +* communication. Once we are in this code CTBs are the only > > +* method the i915 uses to communicate with the GuC so it is > > +* safe to write to this register (a value of 0 is NOP for MMIO > > +* communication). If we ever start mixing CTBs and MMIOs a new > > +* register will have to be chosen. > > +*/ > > + intel_uncore_write_fw(gt->uncore, GEN11_SOFT_SCRATCH(0), 0); > > + } else { > > + /* wmb() sufficient for a barrier if in smem */ > > + wmb(); > > + } > > +} > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > index 3f95b1b4f15c..0ead2406d03c 100644 > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h > > @@ -37,6 +37,12 @@ struct intel_guc { > > /* Global engine used to submit requests to GuC */ > > struct i915_sched_engine *sched_engine; > > struct i915_request *stalled_request; > > + enum { > > + STALL_NONE, > > + STALL_REGISTER_CONTEXT, > > + STALL_MOVE_LRC_TAIL, > > + STALL_ADD_REQUEST, > > + } submission_stall_reason; > > /* intel_guc_recv interrupt related state */ > > spinlock_t irq_lock; > > @@ -332,4 +338,6 @@ void intel_guc_submission_cancel_requests(struct > > intel_guc *guc); > > void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p); > > +void intel_guc_write_barrier(struct intel_guc *guc); > > + > > #endif > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > index 20c710a74498..10d1878d2826 100644 > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c > > @@ -377,28 +377,6 @@ static u32 ct_get_next_fence(struct intel_guc_ct *ct) > > return ++ct->requests.last_fence; > > } > > -static void write_barrier(struct intel_guc_ct *ct) > > -{ > > - struct intel_guc *guc = ct_to_guc(ct); > > - struct intel_gt *gt = guc_to_gt(guc); > > - > > - if (i915_gem_object_is_lmem(guc->ct.vma->obj)) { > > - GEM_BUG_ON(guc->send_regs.fw_domains); > > - /* > > -* This register is used by the i915 and GuC for MMIO based > > -* communication. Once we are in this code CTBs are the only > > -* method the i915 uses to communicate with the GuC so it is > > -* safe to write to this register (a value of 0 is NOP for MMIO > > -* communication). If we ever start mixing CTBs and MMIOs a new > > -* register will have to be chosen. > > -*/ > > - intel_uncore_write_fw(gt->uncore,
Re: [Intel-gfx] [PATCH 17/27] drm/i915/guc: Implement multi-lrc reset
On Mon, Sep 20, 2021 at 03:44:18PM -0700, John Harrison wrote: > On 8/20/2021 15:44, Matthew Brost wrote: > > Update context and full GPU reset to work with multi-lrc. The idea is > parent context tracks all the active requests inflight for itself and > its' children. The parent context owns the reset replaying / canceling > > its' -> its > > > requests as needed. > > Signed-off-by: Matthew Brost > --- > drivers/gpu/drm/i915/gt/intel_context.c | 11 ++-- > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 63 +-- > 2 files changed, 51 insertions(+), 23 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_context.c > b/drivers/gpu/drm/i915/gt/intel_context.c > index 00d1aee6d199..5615be32879c 100644 > --- a/drivers/gpu/drm/i915/gt/intel_context.c > +++ b/drivers/gpu/drm/i915/gt/intel_context.c > @@ -528,20 +528,21 @@ struct i915_request > *intel_context_create_request(struct intel_context *ce) > > struct i915_request *intel_context_find_active_request(struct > intel_context *ce) > { > + struct intel_context *parent = intel_context_to_parent(ce); > struct i915_request *rq, *active = NULL; > unsigned long flags; > > GEM_BUG_ON(!intel_engine_uses_guc(ce->engine)); > > Should this not check the parent as well/instead? > I don't think so. The 'ce' could be a not parallel context, a parent context, or a child context. > And to be clear, this can be called on regular contexts (where ce == parent) > and on both the parent or child contexts of multi-LRC contexts (where ce may > or > may not match parent)? > Right. The parent owns the parent->guc_state.lock/requests and search that list for the first non-completed request that matches submitted 'ce'. > > > > - spin_lock_irqsave(>guc_state.lock, flags); > - list_for_each_entry_reverse(rq, >guc_state.requests, > + spin_lock_irqsave(>guc_state.lock, flags); > + list_for_each_entry_reverse(rq, >guc_state.requests, > sched.link) { > - if (i915_request_completed(rq)) > + if (i915_request_completed(rq) && rq->context == ce) > > 'rq->context == ce' means: > > 1. single-LRC context, rq is owned by ce > 2. multi-LRC context, ce is child, rq really belongs to ce but is being > tracked by parent > 3. multi-LRC context, ce is parent, rq really is owned by ce > > So when 'rq->ce != ce', it means that the request is owned by a different > child > to 'ce' but within the same multi-LRC group. So we want to ignore that request > and keep searching until we find one that is really owned by the target ce? > All correct. > > break; > > - active = rq; > + active = (rq->context == ce) ? rq : active; > > Would be clearer to say 'if(rq->ce != ce) continue;' and leave 'active = rq;' > alone? > Yes, that is probably cleaner. > And again, the intention is to ignore requests that are owned by other members > of the same multi-LRC group? > > Would be good to add some documentation to this function to explain the above > (assuming my description is correct?). > Will add a comment explaining this. > > } > - spin_unlock_irqrestore(>guc_state.lock, flags); > + spin_unlock_irqrestore(>guc_state.lock, flags); > > return active; > } > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index f0b60fecf253..e34e0ea9136a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -670,6 +670,11 @@ static int rq_prio(const struct i915_request *rq) > return rq->sched.attr.priority; > } > > +static inline bool is_multi_lrc(struct intel_context *ce) > +{ > + return intel_context_is_parallel(ce); > +} > + > static bool is_multi_lrc_rq(struct i915_request *rq) > { > return intel_context_is_parallel(rq->context); > @@ -1179,10 +1184,13 @@ __unwind_incomplete_requests(struct intel_context > *ce) > > static void __guc_reset_context(struct intel_context *ce, bool stalled) > { > + bool local_stalled; > struct i915_request *rq; > unsigned long flags; > u32 head; > + int i, number_children = ce->guc_number_children; > > If this is a child context, does it not need to pull the child count from the > parent? Likewise the list/link pointers below? Or does each child context have > a full list of its siblings + parent? > This function shouldn't be called by a child. Will add GEM_BUG_ON(intel_context_is_child(ce)) to this function. > > bool skip = false; > + struct intel_context *parent = ce; > >
Re: [PATCH 4/4] dt-bindings: display: mediatek: add MT8195 hdmi bindings
Hi, Guillaume: Rob Herring 於 2021年9月7日 週二 下午10:51寫道: > > On Tue, 07 Sep 2021 10:37:21 +0200, Guillaume Ranquet wrote: > > Add Mediatek HDMI and HDMI-DDC bindings for MT8195 SoC. Move this patch before the driver patch which refer to this patch. > > > > Signed-off-by: Guillaume Ranquet > > --- > > .../mediatek/mediatek,mt8195-hdmi-ddc.yaml| 46 + > > .../mediatek/mediatek,mt8195-hdmi.yaml| 99 +++ > > 2 files changed, 145 insertions(+) > > create mode 100644 > > Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml I think this file should be merged into mediatek,hdmi-ddc.yaml [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi-ddc.yaml?h=v5.15-rc2 > > create mode 100644 > > Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi.yaml I think this file should be merged into mediatek,hdmi.yaml [2]. [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml?h=v5.15-rc2 Regards, Chun-Kuang. > > > > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' > on your patch (DT_CHECKER_FLAGS is new in v5.13): > > yamllint warnings/errors: > > dtschema/dtc warnings/errors: > Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi.example.dts:19:18: > fatal error: dt-bindings/clock/mt8195-clk.h: No such file or directory >19 | #include > | ^~~~ > compilation terminated. > make[1]: *** [scripts/Makefile.lib:379: > Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi.example.dt.yaml] > Error 1 > make[1]: *** Waiting for unfinished jobs > make: *** [Makefile:1438: dt_binding_check] Error 2 > > doc reference errors (make refcheckdocs): > > See https://patchwork.ozlabs.org/patch/1525170 > > This check can fail if there are any dependencies. The base for a patch > series is generally the most recent rc1. > > If you already ran 'make dt_binding_check' and didn't see the above > error(s), then make sure 'yamllint' is installed and dt-schema is up to > date: > > pip3 install dtschema --upgrade > > Please check and re-submit. >
Re: [PATCH 3/4] dt-bindings: phy: Add binding for Mediatek MT8195 HDMI PHY
Hi, Guillaume: Guillaume Ranquet 於 2021年9月7日 週二 下午4:39寫道: > > Add bindings to describe Mediatek MT8195 HDMI PHY Move this patch before the driver patch which reference this patch. > > Signed-off-by: Guillaume Ranquet > --- > .../phy/mediatek,mtk8195-hdmi-phy.yaml| 71 +++ > 1 file changed, 71 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/phy/mediatek,mtk8195-hdmi-phy.yaml I think this file should be merged into mediatek,hdmi-phy.yaml [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml?h=v5.15-rc2 Regards, Chun-Kuang. > > diff --git > a/Documentation/devicetree/bindings/phy/mediatek,mtk8195-hdmi-phy.yaml > b/Documentation/devicetree/bindings/phy/mediatek,mtk8195-hdmi-phy.yaml > new file mode 100644 > index ..f03bd3af7fd8 > --- /dev/null > +++ b/Documentation/devicetree/bindings/phy/mediatek,mtk8195-hdmi-phy.yaml > @@ -0,0 +1,71 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +# Copyright (c) 2020 MediaTek > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/phy/mediatek,hdmi-phy.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: MediaTek High Definition Multimedia Interface (HDMI) PHY binding for > mt8195 > + > +maintainers: > + - Chun-Kuang Hu > + - Philipp Zabel > + - Chunfeng Yun > + > +description: | > + The HDMI PHY serializes the HDMI encoder's three channel 10-bit parallel > + output and drives the HDMI pads. > + > +properties: > + $nodename: > +pattern: "^hdmi-phy@[0-9a-f]+$" > + > + compatible: > +- const: mediatek,mt8195-hdmi-phy > + > + reg: > +maxItems: 1 > + > + clocks: > +items: > + - description: PLL reference clock > + > + clock-names: > +items: > + - const: hdmi_xtal_sel > + > + clock-output-names: > +items: > + - const: hdmi_txpll > + > + "#phy-cells": > +const: 0 > + > + "#clock-cells": > +const: 0 > + > +required: > + - compatible > + - reg > + - clocks > + - clock-names > + - clock-output-names > + - "#phy-cells" > + - "#clock-cells" > + > +additionalProperties: false > + > +examples: > + - | > +#include > +hdmi_phy: hdmi-phy@11d5f000 { > +compatible = "mediatek,mt8195-hdmi-phy"; > +reg = <0 0x11d5f000 0 0x100>; > +clocks = < CLK_TOP_HDMI_XTAL>; > +clock-names = "hdmi_xtal_sel"; > +clock-output-names = "hdmi_txpll"; > +#clock-cells = <0>; > +#phy-cells = <0>; > +}; > + > +... > -- > 2.31.1 >
[PATCH] drm/i915: Drop stealing of bits from i915_sw_fence function pointer
Rather than stealing bits from i915_sw_fence function pointer use seperate fields for function pointer and flags. If using two different fields, the 4 byte alignment for the i915_sw_fence function pointer can also be dropped. v2: (CI) - Set new function field rather than flags in __i915_sw_fence_init v3: (Tvrtko) - Remove BUG_ON(!fence->flags) in reinit as that will now blow up - Only define fence->flags if CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is defined Signed-off-by: Matthew Brost Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_request.c | 4 +-- drivers/gpu/drm/i915/i915_sw_fence.c | 28 +++ drivers/gpu/drm/i915/i915_sw_fence.h | 23 +++ drivers/gpu/drm/i915/i915_sw_fence_work.c | 2 +- .../gpu/drm/i915/selftests/i915_sw_fence.c| 2 +- drivers/gpu/drm/i915/selftests/lib_sw_fence.c | 8 +++--- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a7ca38613f89..6d5bb55ffc82 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10323,7 +10323,7 @@ static void intel_atomic_commit_work(struct work_struct *work) intel_atomic_commit_tail(state); } -static int __i915_sw_fence_call +static int intel_atomic_commit_ready(struct i915_sw_fence *fence, enum i915_sw_fence_notify notify) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..df5fec5c3da8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -800,7 +800,7 @@ static void free_engines_rcu(struct rcu_head *rcu) free_engines(engines); } -static int __i915_sw_fence_call +static int engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_gem_engines *engines = diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ce446716d092..945d3025a0b6 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -719,7 +719,7 @@ void i915_request_cancel(struct i915_request *rq, int error) intel_context_cancel_request(rq->context, rq); } -static int __i915_sw_fence_call +static int submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *request = @@ -755,7 +755,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } -static int __i915_sw_fence_call +static int semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *rq = container_of(fence, typeof(*rq), semaphore); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index c589a681da77..f10d31818ecc 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -18,7 +18,9 @@ #define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) #endif +#ifdef CONFIG_DRM_I915_SW_FENCE_CHECK_DAG static DEFINE_SPINLOCK(i915_sw_fence_lock); +#endif #define WQ_FLAG_BITS \ BITS_PER_TYPE(typeof_member(struct wait_queue_entry, flags)) @@ -34,7 +36,7 @@ enum { static void *i915_sw_fence_debug_hint(void *addr) { - return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK); + return (void *)(((struct i915_sw_fence *)addr)->fn); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -126,10 +128,7 @@ static inline void debug_fence_assert(struct i915_sw_fence *fence) static int __i915_sw_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - i915_sw_fence_notify_t fn; - - fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); - return fn(fence, state); + return fence->fn(fence, state); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -242,10 +241,13 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, const char *name, struct lock_class_key *key) { - BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); + BUG_ON(!fn); __init_waitqueue_head(>wait, name, key); - fence->flags = (unsigned long)fn; + fence->fn = fn; +#ifdef CONFIG_DRM_I915_SW_FENCE_CHECK_DAG + fence->flags = 0; +#endif i915_sw_fence_reinit(fence); } @@ -257,7 +259,6 @@ void i915_sw_fence_reinit(struct i915_sw_fence *fence) atomic_set(>pending, 1); fence->error = 0; - I915_SW_FENCE_BUG_ON(!fence->flags); I915_SW_FENCE_BUG_ON(!list_empty(>wait.head)); } @@ -279,6 +280,7 @@ static int
[PATCH 2/7] drm/i915: Make GEM contexts track DRM clients
From: Tvrtko Ursulin Make GEM contexts keep a reference to i915_drm_client for the whole of of their lifetime which will come handy in following patches. v2: Don't bother supporting selftests contexts from debugfs. (Chris) v3 (Lucas): Finish constructing ctx before adding it to the list v4 (Ram): Rebase. v5: Trivial rebase for proto ctx changes. v6: Rebase after clients no longer track name and pid. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson # v5 Reviewed-by: Aravind Iddamsetty # v5 Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 + drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..70340663136e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -956,6 +956,9 @@ static void i915_gem_context_release_work(struct work_struct *work) if (vm) i915_vm_put(vm); + if (ctx->client) + i915_drm_client_put(ctx->client); + mutex_destroy(>engines_mutex); mutex_destroy(>lut_mutex); @@ -1373,6 +1376,8 @@ static void gem_context_register(struct i915_gem_context *ctx, ctx->file_priv = fpriv; ctx->pid = get_task_pid(current, PIDTYPE_PID); + ctx->client = i915_drm_client_get(fpriv->client); + snprintf(ctx->name, sizeof(ctx->name), "%s[%d]", current->comm, pid_nr(ctx->pid)); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index c4617e4d9fa9..598c57ac5cdf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -277,6 +277,9 @@ struct i915_gem_context { /** @link: place with _i915_private.context_list */ struct list_head link; + /** @client: struct i915_drm_client */ + struct i915_drm_client *client; + /** * @ref: reference count * -- 2.30.2
[PATCH 3/7] drm/i915: Track runtime spent in closed and unreachable GEM contexts
From: Tvrtko Ursulin As contexts are abandoned we want to remember how much GPU time they used (per class) so later we can used it for smarter purposes. As GEM contexts are closed we want to have the DRM client remember how much GPU time they used (per class) so later we can used it for smarter purposes. Signed-off-by: Tvrtko Ursulin Reviewed-by: Aravind Iddamsetty Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 25 +++-- drivers/gpu/drm/i915/i915_drm_client.h | 7 ++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 70340663136e..9b37723b70a9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -800,23 +800,44 @@ static void free_engines_rcu(struct rcu_head *rcu) free_engines(engines); } +static void accumulate_runtime(struct i915_drm_client *client, + struct i915_gem_engines *engines) +{ + struct i915_gem_engines_iter it; + struct intel_context *ce; + + if (!client) + return; + + /* Transfer accumulated runtime to the parent GEM context. */ + for_each_gem_engine(ce, engines, it) { + unsigned int class = ce->engine->uabi_class; + + GEM_BUG_ON(class >= ARRAY_SIZE(client->past_runtime)); + atomic64_add(intel_context_get_total_runtime_ns(ce), +>past_runtime[class]); + } +} + static int __i915_sw_fence_call engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_gem_engines *engines = container_of(fence, typeof(*engines), fence); + struct i915_gem_context *ctx = engines->ctx; switch (state) { case FENCE_COMPLETE: if (!list_empty(>link)) { - struct i915_gem_context *ctx = engines->ctx; unsigned long flags; spin_lock_irqsave(>stale.lock, flags); list_del(>link); spin_unlock_irqrestore(>stale.lock, flags); } - i915_gem_context_put(engines->ctx); + accumulate_runtime(ctx->client, engines); + i915_gem_context_put(ctx); + break; case FENCE_FREE: diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h index e8986ad51176..9d80d9f715ee 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.h +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -9,6 +9,8 @@ #include #include +#include "gt/intel_engine_types.h" + struct drm_i915_private; struct i915_drm_clients { @@ -24,6 +26,11 @@ struct i915_drm_client { unsigned int id; struct i915_drm_clients *clients; + + /** +* @past_runtime: Accumulation of pphwsp runtimes from closed contexts. +*/ + atomic64_t past_runtime[MAX_ENGINE_CLASS + 1]; }; void i915_drm_clients_init(struct i915_drm_clients *clients, -- 2.30.2
[PATCH 7/7] drm/i915: Expose client engine utilisation via fdinfo
From: Tvrtko Ursulin Similar to AMD commit 874442541133 ("drm/amdgpu: Add show_fdinfo() interface"), using the infrastructure added in previous patches, we add basic client info and GPU engine utilisation for i915. Example of the output: pos:0 flags: 012 mnt_id: 21 drm-driver: i915 drm-pdev: :00:02.0 drm-client-id: 7 drm-engine-render: 9288864723 ns drm-engine-copy:2035071108 ns drm-engine-video: 0 ns drm-engine-video-enhance: 0 ns v2: * Update for removal of name and pid. v3: * Use drm_driver.name. Signed-off-by: Tvrtko Ursulin Cc: David M Nieto Cc: Christian König Cc: Daniel Vetter Acked-by: Christian König --- Documentation/gpu/drm-usage-stats.rst | 6 +++ Documentation/gpu/i915.rst | 27 ++ drivers/gpu/drm/i915/i915_drm_client.c | 73 ++ drivers/gpu/drm/i915/i915_drm_client.h | 4 ++ drivers/gpu/drm/i915/i915_drv.c| 3 ++ 5 files changed, 113 insertions(+) diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst index c669026be244..6952f8389d07 100644 --- a/Documentation/gpu/drm-usage-stats.rst +++ b/Documentation/gpu/drm-usage-stats.rst @@ -95,3 +95,9 @@ object belong to this client, in the respective memory region. Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB' indicating kibi- or mebi-bytes. + +=== +Driver specific implementations +=== + +:ref:`i915-usage-stats` diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 311e10400708..36cd6f74fb1b 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -700,3 +700,30 @@ The style guide for ``i915_reg.h``. .. kernel-doc:: drivers/gpu/drm/i915/i915_reg.h :doc: The i915 register macro definition style guide + +.. _i915-usage-stats: + +i915 DRM client usage stats implementation +== + +The drm/i915 driver implements the DRM client usage stats specification as +documented in :ref:`drm-client-usage-stats`. + +Example of the output showing the implemented key value pairs and entirety of +the currenly possible format options: + +:: + + pos:0 + flags: 012 + mnt_id: 21 + drm-driver: i915 + drm-pdev: :00:02.0 + drm-client-id: 7 + drm-engine-render: 9288864723 ns + drm-engine-copy:2035071108 ns + drm-engine-video: 0 ns + drm-engine-video-enhance: 0 ns + +Possible `drm-engine-` key names are: `render`, `copy`, `video` and +`video-enhance`. diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c index 91a8559bebf7..06dbd20ce763 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.c +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -7,6 +7,11 @@ #include #include +#include + +#include + +#include "gem/i915_gem_context.h" #include "i915_drm_client.h" #include "i915_gem.h" #include "i915_utils.h" @@ -68,3 +73,71 @@ void i915_drm_clients_fini(struct i915_drm_clients *clients) GEM_BUG_ON(!xa_empty(>xarray)); xa_destroy(>xarray); } + +#ifdef CONFIG_PROC_FS +static const char * const uabi_class_names[] = { + [I915_ENGINE_CLASS_RENDER] = "render", + [I915_ENGINE_CLASS_COPY] = "copy", + [I915_ENGINE_CLASS_VIDEO] = "video", + [I915_ENGINE_CLASS_VIDEO_ENHANCE] = "video-enhance", +}; + +static u64 busy_add(struct i915_gem_context *ctx, unsigned int class) +{ + struct i915_gem_engines_iter it; + struct intel_context *ce; + u64 total = 0; + + for_each_gem_engine(ce, rcu_dereference(ctx->engines), it) { + if (ce->engine->uabi_class != class) + continue; + + total += intel_context_get_total_runtime_ns(ce); + } + + return total; +} + +static void +show_client_class(struct seq_file *m, + struct i915_drm_client *client, + unsigned int class) +{ + const struct list_head *list = >ctx_list; + u64 total = atomic64_read(>past_runtime[class]); + struct i915_gem_context *ctx; + + rcu_read_lock(); + list_for_each_entry_rcu(ctx, list, client_link) + total += busy_add(ctx, class); + rcu_read_unlock(); + + return seq_printf(m, "drm-engine-%s:\t%llu ns\n", + uabi_class_names[class], total); +} + +void i915_drm_client_fdinfo(struct seq_file *m, struct file *f) +{ + struct drm_file *file = f->private_data; + struct drm_i915_file_private *file_priv = file->driver_priv; + struct drm_i915_private *i915 = file_priv->dev_priv; + struct i915_drm_client *client = file_priv->client; + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + unsigned int i; + + /* +* ** +* For text output format description please
[PATCH 5/7] drm/i915: Track context current active time
From: Tvrtko Ursulin Track context active (on hardware) status together with the start timestamp. This will be used to provide better granularity of context runtime reporting in conjunction with already tracked pphwsp accumulated runtime. The latter is only updated on context save so does not give us visibility to any currently executing work. As part of the patch the existing runtime tracking data is moved under the new ce->stats member and updated under the seqlock. This provides the ability to atomically read out accumulated plus active runtime. v2: * Rename and make __intel_context_get_active_time unlocked. v3: * Use GRAPHICS_VER. Signed-off-by: Tvrtko Ursulin Reviewed-by: Aravind Iddamsetty # v1 Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/gt/intel_context.c | 27 ++- drivers/gpu/drm/i915/gt/intel_context.h | 15 --- drivers/gpu/drm/i915/gt/intel_context_types.h | 24 +++-- .../drm/i915/gt/intel_execlists_submission.c | 23 .../gpu/drm/i915/gt/intel_gt_clock_utils.c| 4 +++ drivers/gpu/drm/i915/gt/intel_lrc.c | 27 ++- drivers/gpu/drm/i915/gt/intel_lrc.h | 24 + drivers/gpu/drm/i915/gt/selftest_lrc.c| 10 +++ drivers/gpu/drm/i915/i915_gpu_error.c | 9 +++ drivers/gpu/drm/i915/i915_gpu_error.h | 2 +- 10 files changed, 116 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index ff637147b1a9..ae97c311d65b 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -382,7 +382,7 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) ce->ring = NULL; ce->ring_size = SZ_4K; - ewma_runtime_init(>runtime.avg); + ewma_runtime_init(>stats.runtime.avg); ce->vm = i915_vm_get(engine->gt->vm); @@ -532,6 +532,31 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce) return active; } +u64 intel_context_get_total_runtime_ns(const struct intel_context *ce) +{ + u64 total, active; + + total = ce->stats.runtime.total; + if (ce->ops->flags & COPS_RUNTIME_CYCLES) + total *= ce->engine->gt->clock_period_ns; + + active = READ_ONCE(ce->stats.active); + if (active) + active = intel_context_clock() - active; + + return total + active; +} + +u64 intel_context_get_avg_runtime_ns(struct intel_context *ce) +{ + u64 avg = ewma_runtime_read(>stats.runtime.avg); + + if (ce->ops->flags & COPS_RUNTIME_CYCLES) + avg *= ce->engine->gt->clock_period_ns; + + return avg; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_context.c" #endif diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index c41098950746..2aaffe1bb388 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -296,18 +296,13 @@ intel_context_clear_nopreempt(struct intel_context *ce) clear_bit(CONTEXT_NOPREEMPT, >flags); } -static inline u64 intel_context_get_total_runtime_ns(struct intel_context *ce) -{ - const u32 period = ce->engine->gt->clock_period_ns; - - return READ_ONCE(ce->runtime.total) * period; -} +u64 intel_context_get_total_runtime_ns(const struct intel_context *ce); +u64 intel_context_get_avg_runtime_ns(struct intel_context *ce); -static inline u64 intel_context_get_avg_runtime_ns(struct intel_context *ce) +static inline u64 intel_context_clock(void) { - const u32 period = ce->engine->gt->clock_period_ns; - - return mul_u32_u32(ewma_runtime_read(>runtime.avg), period); + /* As we mix CS cycles with CPU clocks, use the raw monotonic clock. */ + return ktime_get_raw_fast_ns(); } #endif /* __INTEL_CONTEXT_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 930569a1a01f..2a8a8d207691 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -35,6 +35,9 @@ struct intel_context_ops { #define COPS_HAS_INFLIGHT_BIT 0 #define COPS_HAS_INFLIGHT BIT(COPS_HAS_INFLIGHT_BIT) +#define COPS_RUNTIME_CYCLES_BIT 1 +#define COPS_RUNTIME_CYCLES BIT(COPS_RUNTIME_CYCLES_BIT) + int (*alloc)(struct intel_context *ce); void (*ban)(struct intel_context *ce, struct i915_request *rq); @@ -128,14 +131,19 @@ struct intel_context { } lrc; u32 tag; /* cookie passed to HW to track this context on submission */ - /* Time on GPU as tracked by the hw. */ - struct { - struct ewma_runtime avg; - u64 total; - u32 last; - I915_SELFTEST_DECLARE(u32 num_underflow); -
[PATCH 6/7] drm: Document fdinfo format specification
From: Tvrtko Ursulin Proposal to standardise the fdinfo text format as optionally output by DRM drivers. Idea is that a simple but, well defined, spec will enable generic userspace tools to be written while at the same time avoiding a more heavy handed approach of adding a mid-layer to DRM. i915 implements a subset of the spec, everything apart from the memory stats currently, and a matching intel_gpu_top tool exists. Open is to see if AMD can migrate to using the proposed GPU utilisation key-value pairs, or if they are not workable to see whether to go vendor specific, or if a standardised alternative can be found which is workable for both drivers. Same for the memory utilisation key-value pairs proposal. v2: * Update for removal of name and pid. v3: * 'Drm-driver' tag will be obtained from struct drm_driver.name. (Daniel) Signed-off-by: Tvrtko Ursulin Cc: David M Nieto Cc: Christian König Cc: Daniel Vetter Cc: Daniel Stone Acked-by: Christian König --- Documentation/gpu/drm-usage-stats.rst | 97 +++ Documentation/gpu/index.rst | 1 + 2 files changed, 98 insertions(+) create mode 100644 Documentation/gpu/drm-usage-stats.rst diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst new file mode 100644 index ..c669026be244 --- /dev/null +++ b/Documentation/gpu/drm-usage-stats.rst @@ -0,0 +1,97 @@ +.. _drm-client-usage-stats: + +== +DRM client usage stats +== + +DRM drivers can choose to export partly standardised text output via the +`fops->show_fdinfo()` as part of the driver specific file operations registered +in the `struct drm_driver` object registered with the DRM core. + +One purpose of this output is to enable writing as generic as practicaly +feasible `top(1)` like userspace monitoring tools. + +Given the differences between various DRM drivers the specification of the +output is split between common and driver specific parts. Having said that, +wherever possible effort should still be made to standardise as much as +possible. + +File format specification += + +- File shall contain one key value pair per one line of text. +- Colon character (`:`) must be used to delimit keys and values. +- All keys shall be prefixed with `drm-`. +- Whitespace between the delimiter and first non-whitespace character shall be + ignored when parsing. +- Neither keys or values are allowed to contain whitespace characters. +- Numerical key value pairs can end with optional unit string. +- Data type of the value is fixed as defined in the specification. + +Key types +- + +1. Mandatory, fully standardised. +2. Optional, fully standardised. +3. Driver specific. + +Data types +-- + +- - Unsigned integer without defining the maximum value. +- - String excluding any above defined reserved characters or whitespace. + +Mandatory fully standardised keys +- + +- drm-driver: + +String shall contain the name this driver registered as via the respective +`struct drm_driver` data structure. + +Optional fully standardised keys + + +- drm-pdev: + +For PCI devices this should contain the PCI slot address of the device in +question. + +- drm-client-id: + +Unique value relating to the open DRM file descriptor used to distinguish +duplicated and shared file descriptors. Conceptually the value should map 1:1 +to the in kernel representation of `struct drm_file` instances. + +Uniqueness of the value shall be either globally unique, or unique within the +scope of each device, in which case `drm-pdev` shall be present as well. + +Userspace should make sure to not double account any usage statistics by using +the above described criteria in order to associate data to individual clients. + +- drm-engine-: ns + +GPUs usually contain multiple execution engines. Each shall be given a stable +and unique name (str), with possible values documented in the driver specific +documentation. + +Value shall be in specified time units which the respective GPU engine spent +busy executing workloads belonging to this client. + +Values are not required to be constantly monotonic if it makes the driver +implementation easier, but are required to catch up with the previously reported +larger value within a reasonable period. Upon observing a value lower than what +was previously read, userspace is expected to stay with that larger previous +value until a monotonic update is seen. + +- drm-memory-: [KiB|MiB] + +Each possible memory type which can be used to store buffer objects by the +GPU in question shall be given a stable and unique name to be returned as the +string here. + +Value shall reflect the amount of storage currently consumed by the buffer +object belong to this client, in the respective memory region. + +Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB' +indicating kibi-
[PATCH 1/7] drm/i915: Explicitly track DRM clients
From: Tvrtko Ursulin Tracking DRM clients more explicitly will allow later patches to accumulate past and current GPU usage in a centralised place and also consolidate access to owning task pid/name. Unique client id is also assigned for the purpose of distinguishing/ consolidating between multiple file descriptors owned by the same process. v2: Chris Wilson: * Enclose new members into dedicated structs. * Protect against failed sysfs registration. v3: * sysfs_attr_init. v4: * Fix for internal clients. v5: * Use cyclic ida for client id. (Chris) * Do not leak pid reference. (Chris) * Tidy code with some locals. v6: * Use xa_alloc_cyclic to simplify locking. (Chris) * No need to unregister individial sysfs files. (Chris) * Rebase on top of fpriv kref. * Track client closed status and reflect in sysfs. v7: * Make drm_client more standalone concept. v8: * Simplify sysfs show. (Chris) * Always track name and pid. v9: * Fix cyclic id assignment. v10: * No need for a mutex around xa_alloc_cyclic. * Refactor sysfs into own function. * Unregister sysfs before freeing pid and name. * Move clients setup into own function. v11: * Call clients init directly from driver init. (Chris) v12: * Do not fail client add on id wrap. (Maciej) v13 (Lucas): Rebase. v14: * Dropped sysfs bits. v15: * Dropped tracking of pid/ and name. * Dropped RCU freeing of the client object. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson # v11 Reviewed-by: Aravind Iddamsetty # v11 Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/Makefile | 5 +- drivers/gpu/drm/i915/i915_drm_client.c | 68 ++ drivers/gpu/drm/i915/i915_drm_client.h | 50 +++ drivers/gpu/drm/i915/i915_drv.c| 6 +++ drivers/gpu/drm/i915/i915_drv.h| 5 ++ drivers/gpu/drm/i915/i915_gem.c| 21 ++-- 6 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 335a8c668848..8187c9e52a79 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -32,8 +32,9 @@ subdir-ccflags-y += -I$(srctree)/$(src) # Please keep these build lists sorted! # core driver code -i915-y += i915_drv.o \ - i915_config.o \ +i915-y += i915_config.o \ + i915_drm_client.o \ + i915_drv.o \ i915_irq.o \ i915_getparam.o \ i915_mitigations.o \ diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c new file mode 100644 index ..e61e9ba15256 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ + +#include +#include +#include + +#include "i915_drm_client.h" +#include "i915_gem.h" +#include "i915_utils.h" + +void i915_drm_clients_init(struct i915_drm_clients *clients, + struct drm_i915_private *i915) +{ + clients->i915 = i915; + clients->next_id = 0; + + xa_init_flags(>xarray, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); +} + +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients) +{ + struct i915_drm_client *client; + struct xarray *xa = >xarray; + int ret; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + xa_lock_irq(xa); + ret = __xa_alloc_cyclic(xa, >id, client, xa_limit_32b, + >next_id, GFP_KERNEL); + xa_unlock_irq(xa); + if (ret < 0) + goto err; + + kref_init(>kref); + client->clients = clients; + + return client; + +err: + kfree(client); + + return ERR_PTR(ret); +} + +void __i915_drm_client_free(struct kref *kref) +{ + struct i915_drm_client *client = + container_of(kref, typeof(*client), kref); + struct xarray *xa = >clients->xarray; + unsigned long flags; + + xa_lock_irqsave(xa, flags); + __xa_erase(xa, client->id); + xa_unlock_irqrestore(xa, flags); + kfree(client); +} + +void i915_drm_clients_fini(struct i915_drm_clients *clients) +{ + GEM_BUG_ON(!xa_empty(>xarray)); + xa_destroy(>xarray); +} diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h new file mode 100644 index ..e8986ad51176 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2020 Intel Corporation + */ + +#ifndef __I915_DRM_CLIENT_H__ +#define __I915_DRM_CLIENT_H__ + +#include +#include + +struct drm_i915_private; + +struct i915_drm_clients { + struct drm_i915_private *i915; + + struct xarray xarray; + u32 next_id; +}; + +struct
[PATCH 4/7] drm/i915: Track all user contexts per client
From: Tvrtko Ursulin We soon want to start answering questions like how much GPU time is the context belonging to a client which exited still using. To enable this we start tracking all context belonging to a client on a separate list. Signed-off-by: Tvrtko Ursulin Reviewed-by: Aravind Iddamsetty Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 12 drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 3 +++ drivers/gpu/drm/i915/i915_drm_client.c| 2 ++ drivers/gpu/drm/i915/i915_drm_client.h| 5 + 4 files changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 9b37723b70a9..a1ef6be28899 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1190,6 +1190,7 @@ static void set_closed_name(struct i915_gem_context *ctx) static void context_close(struct i915_gem_context *ctx) { + struct i915_drm_client *client; struct i915_address_space *vm; /* Flush any concurrent set_engines() */ @@ -1226,6 +1227,13 @@ static void context_close(struct i915_gem_context *ctx) list_del(>link); spin_unlock(>i915->gem.contexts.lock); + client = ctx->client; + if (client) { + spin_lock(>ctx_lock); + list_del_rcu(>client_link); + spin_unlock(>ctx_lock); + } + mutex_unlock(>mutex); /* @@ -1406,6 +1414,10 @@ static void gem_context_register(struct i915_gem_context *ctx, old = xa_store(>context_xa, id, ctx, GFP_KERNEL); WARN_ON(old); + spin_lock(>client->ctx_lock); + list_add_tail_rcu(>client_link, >client->ctx_list); + spin_unlock(>client->ctx_lock); + spin_lock(>gem.contexts.lock); list_add_tail(>link, >gem.contexts.list); spin_unlock(>gem.contexts.lock); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 598c57ac5cdf..b878e1b13b38 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -280,6 +280,9 @@ struct i915_gem_context { /** @client: struct i915_drm_client */ struct i915_drm_client *client; + /** link: _client.context_list */ + struct list_head client_link; + /** * @ref: reference count * diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c index e61e9ba15256..91a8559bebf7 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.c +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -38,6 +38,8 @@ struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients) goto err; kref_init(>kref); + spin_lock_init(>ctx_lock); + INIT_LIST_HEAD(>ctx_list); client->clients = clients; return client; diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h index 9d80d9f715ee..7416e18aa33c 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.h +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -7,6 +7,8 @@ #define __I915_DRM_CLIENT_H__ #include +#include +#include #include #include "gt/intel_engine_types.h" @@ -25,6 +27,9 @@ struct i915_drm_client { unsigned int id; + spinlock_t ctx_lock; /* For add/remove from ctx_list. */ + struct list_head ctx_list; /* List of contexts belonging to client. */ + struct i915_drm_clients *clients; /** -- 2.30.2
[PATCH 0/7] Per client GPU stats
From: Tvrtko Ursulin Same old work but now rebased and series ending with some DRM docs proposing the common specification which should enable nice common userspace tools to be written. For the moment I only have intel_gpu_top converted to use this and that seems to work okay. v2: * Added prototype of possible amdgpu changes and spec updates to align with the common spec. v3: * Documented that 'drm-driver' tag shall correspond with struct drm_driver.name. v4: * Dropped amdgpu conversion from the series for now until AMD folks can find some time to finish that patch. Tvrtko Ursulin (7): drm/i915: Explicitly track DRM clients drm/i915: Make GEM contexts track DRM clients drm/i915: Track runtime spent in closed and unreachable GEM contexts drm/i915: Track all user contexts per client drm/i915: Track context current active time drm: Document fdinfo format specification drm/i915: Expose client engine utilisation via fdinfo Documentation/gpu/drm-usage-stats.rst | 103 + Documentation/gpu/i915.rst| 27 Documentation/gpu/index.rst | 1 + drivers/gpu/drm/i915/Makefile | 5 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 42 - .../gpu/drm/i915/gem/i915_gem_context_types.h | 6 + drivers/gpu/drm/i915/gt/intel_context.c | 27 +++- drivers/gpu/drm/i915/gt/intel_context.h | 15 +- drivers/gpu/drm/i915/gt/intel_context_types.h | 24 ++- .../drm/i915/gt/intel_execlists_submission.c | 23 ++- .../gpu/drm/i915/gt/intel_gt_clock_utils.c| 4 + drivers/gpu/drm/i915/gt/intel_lrc.c | 27 ++-- drivers/gpu/drm/i915/gt/intel_lrc.h | 24 +++ drivers/gpu/drm/i915/gt/selftest_lrc.c| 10 +- drivers/gpu/drm/i915/i915_drm_client.c| 143 ++ drivers/gpu/drm/i915/i915_drm_client.h| 66 drivers/gpu/drm/i915/i915_drv.c | 9 ++ drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 21 ++- drivers/gpu/drm/i915/i915_gpu_error.c | 9 +- drivers/gpu/drm/i915/i915_gpu_error.h | 2 +- 21 files changed, 537 insertions(+), 56 deletions(-) create mode 100644 Documentation/gpu/drm-usage-stats.rst create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h -- 2.30.2
Re: [PATCH v3 1/6] drm/vc4: select PM (openrisc)
On Wed, Sep 22, 2021 at 10:41:56AM +0200, Maxime Ripard wrote: > Hi Randy, > > On Sun, Sep 19, 2021 at 09:40:44AM -0700, Randy Dunlap wrote: > > On 8/19/21 6:59 AM, Maxime Ripard wrote: > > > We already depend on runtime PM to get the power domains and clocks for > > > most of the devices supported by the vc4 driver, so let's just select it > > > to make sure it's there, and remove the ifdef. > > > > > > Signed-off-by: Maxime Ripard > > > --- > > > drivers/gpu/drm/vc4/Kconfig| 1 + > > > drivers/gpu/drm/vc4/vc4_hdmi.c | 2 -- > > > 2 files changed, 1 insertion(+), 2 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig > > > index 118e8a426b1a..f774ab340863 100644 > > > --- a/drivers/gpu/drm/vc4/Kconfig > > > +++ b/drivers/gpu/drm/vc4/Kconfig > > > @@ -9,6 +9,7 @@ config DRM_VC4 > > > select DRM_KMS_CMA_HELPER > > > select DRM_GEM_CMA_HELPER > > > select DRM_PANEL_BRIDGE > > > + select PM > > > select SND_PCM > > > select SND_PCM_ELD > > > select SND_SOC_GENERIC_DMAENGINE_PCM > > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c > > > b/drivers/gpu/drm/vc4/vc4_hdmi.c > > > index c2876731ee2d..602203b2d8e1 100644 > > > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c > > > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c > > > @@ -2107,7 +2107,6 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi > > > *vc4_hdmi) > > > return 0; > > > } > > > -#ifdef CONFIG_PM > > > static int vc4_hdmi_runtime_suspend(struct device *dev) > > > { > > > struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); > > > @@ -2128,7 +2127,6 @@ static int vc4_hdmi_runtime_resume(struct device > > > *dev) > > > return 0; > > > } > > > -#endif > > > static int vc4_hdmi_bind(struct device *dev, struct device *master, > > > void *data) > > > { > > > > > > > Hi, > > > > FYI. > > > > This still causes a build error on arch/openrisc/ since it does not support > > CONFIG_PM (it does not source "kernel/power/Kconfig" like some other arches > > do): > > > > ./arch/riscv/Kconfig:source "kernel/power/Kconfig" > > ./arch/x86/Kconfig:source "kernel/power/Kconfig" > > ./arch/nds32/Kconfig:source "kernel/power/Kconfig" > > ./arch/sh/Kconfig:source "kernel/power/Kconfig" > > ./arch/arc/Kconfig:source "kernel/power/Kconfig" > > ./arch/arm64/Kconfig:source "kernel/power/Kconfig" > > ./arch/xtensa/Kconfig:source "kernel/power/Kconfig" > > ./arch/sparc/Kconfig:source "kernel/power/Kconfig" > > ./arch/arm/Kconfig:source "kernel/power/Kconfig" > > ./arch/mips/Kconfig:source "kernel/power/Kconfig" > > ./arch/powerpc/Kconfig:source "kernel/power/Kconfig" > > ./arch/um/Kconfig:source "kernel/power/Kconfig" > > ./arch/ia64/Kconfig:source "kernel/power/Kconfig" > > > > so with > > CONFIG_DRM_VC4=y > > # CONFIG_DRM_VC4_HDMI_CEC is not set > > > > I still see > > ../drivers/gpu/drm/vc4/vc4_hdmi.c:2139:12: warning: > > 'vc4_hdmi_runtime_suspend' defined but not used [-Wunused-function] > > 2139 | static int vc4_hdmi_runtime_suspend(struct device *dev) > > |^~~~ > > With what version did you get that build error? -rc2 shouldn't have it > anymore since the runtime_pm hooks introduction got reverted. -next still contains these patches as Stephen effectively reverted the changes in Linus' tree when merging in the drm-misc-fixes tree: https://lore.kernel.org/r/20210920090729.19458...@canb.auug.org.au/ Cheers, Nathan
Re: [Intel-gfx] [PATCH] drm/i915: Drop stealing of bits from i915_sw_fence function pointer
On Wed, Sep 22, 2021 at 04:25:04PM +0100, Tvrtko Ursulin wrote: > > On 22/09/2021 16:21, Tvrtko Ursulin wrote: > > > > On 22/09/2021 15:57, Matthew Brost wrote: > > > Rather than stealing bits from i915_sw_fence function pointer use > > > seperate fields for function pointer and flags. If using two different > > > fields, the 4 byte alignment for the i915_sw_fence function pointer can > > > also be dropped. > > > > > > v2: > > > (CI) > > > - Set new function field rather than flags in __i915_sw_fence_init > > > > > > Signed-off-by: Matthew Brost > > > --- > > > drivers/gpu/drm/i915/display/intel_display.c | 2 +- > > > drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- > > > drivers/gpu/drm/i915/i915_request.c | 4 ++-- > > > drivers/gpu/drm/i915/i915_sw_fence.c | 12 +-- > > > drivers/gpu/drm/i915/i915_sw_fence.h | 21 +-- > > > drivers/gpu/drm/i915/i915_sw_fence_work.c | 2 +- > > > .../gpu/drm/i915/selftests/i915_sw_fence.c | 2 +- > > > drivers/gpu/drm/i915/selftests/lib_sw_fence.c | 4 ++-- > > > 8 files changed, 23 insertions(+), 26 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display.c > > > b/drivers/gpu/drm/i915/display/intel_display.c > > > index a7ca38613f89..6d5bb55ffc82 100644 > > > --- a/drivers/gpu/drm/i915/display/intel_display.c > > > +++ b/drivers/gpu/drm/i915/display/intel_display.c > > > @@ -10323,7 +10323,7 @@ static void intel_atomic_commit_work(struct > > > work_struct *work) > > > intel_atomic_commit_tail(state); > > > } > > > -static int __i915_sw_fence_call > > > +static int > > > intel_atomic_commit_ready(struct i915_sw_fence *fence, > > > enum i915_sw_fence_notify notify) > > > { > > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > index c2ab0e22db0a..df5fec5c3da8 100644 > > > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > > @@ -800,7 +800,7 @@ static void free_engines_rcu(struct rcu_head *rcu) > > > free_engines(engines); > > > } > > > -static int __i915_sw_fence_call > > > +static int > > > engines_notify(struct i915_sw_fence *fence, enum > > > i915_sw_fence_notify state) > > > { > > > struct i915_gem_engines *engines = > > > diff --git a/drivers/gpu/drm/i915/i915_request.c > > > b/drivers/gpu/drm/i915/i915_request.c > > > index ce446716d092..945d3025a0b6 100644 > > > --- a/drivers/gpu/drm/i915/i915_request.c > > > +++ b/drivers/gpu/drm/i915/i915_request.c > > > @@ -719,7 +719,7 @@ void i915_request_cancel(struct i915_request > > > *rq, int error) > > > intel_context_cancel_request(rq->context, rq); > > > } > > > -static int __i915_sw_fence_call > > > +static int > > > submit_notify(struct i915_sw_fence *fence, enum > > > i915_sw_fence_notify state) > > > { > > > struct i915_request *request = > > > @@ -755,7 +755,7 @@ submit_notify(struct i915_sw_fence *fence, enum > > > i915_sw_fence_notify state) > > > return NOTIFY_DONE; > > > } > > > -static int __i915_sw_fence_call > > > +static int > > > semaphore_notify(struct i915_sw_fence *fence, enum > > > i915_sw_fence_notify state) > > > { > > > struct i915_request *rq = container_of(fence, typeof(*rq), > > > semaphore); > > > diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c > > > b/drivers/gpu/drm/i915/i915_sw_fence.c > > > index c589a681da77..1c080dd1f718 100644 > > > --- a/drivers/gpu/drm/i915/i915_sw_fence.c > > > +++ b/drivers/gpu/drm/i915/i915_sw_fence.c > > > @@ -34,7 +34,7 @@ enum { > > > static void *i915_sw_fence_debug_hint(void *addr) > > > { > > > - return (void *)(((struct i915_sw_fence *)addr)->flags & > > > I915_SW_FENCE_MASK); > > > + return (void *)(((struct i915_sw_fence *)addr)->fn); > > > } > > > #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS > > > @@ -126,10 +126,7 @@ static inline void debug_fence_assert(struct > > > i915_sw_fence *fence) > > > static int __i915_sw_fence_notify(struct i915_sw_fence *fence, > > > enum i915_sw_fence_notify state) > > > { > > > - i915_sw_fence_notify_t fn; > > > - > > > - fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); > > > - return fn(fence, state); > > > + return fence->fn(fence, state); > > > } > > > #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS > > > @@ -242,10 +239,11 @@ void __i915_sw_fence_init(struct i915_sw_fence > > > *fence, > > > const char *name, > > > struct lock_class_key *key) > > > { > > > - BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); > > > + BUG_ON(!fn); > > > __init_waitqueue_head(>wait, name, key); > > > - fence->flags = (unsigned long)fn; > > > + fence->fn = fn; > > > + fence->flags = 0; > > > i915_sw_fence_reinit(fence); > > > } > > > diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h >
Re: Multiple DRI card detection in compositor systemd units
Maybe try creating multiple physical seats with logind, and start each compositor on its own seat? A physical seat is a collection of devices like DRM nodes and evdev device files. Also udev creates files in /dev/dri/by-path/, these should be stable across reboots. `udevadm settle` before a compositor start-up can wait for udev to finish its job. Out of curiosity, can you explain your use-case? Why do you need to start multiple compositors, each on its own GPU?
Re: [RFC PATCH v3 1/6] drm/doc: Color Management and HDR10 RFC
On 2021-09-22 04:31, Pekka Paalanen wrote: > On Tue, 21 Sep 2021 14:05:05 -0400 > Harry Wentland wrote: > >> On 2021-09-21 09:31, Pekka Paalanen wrote: >>> On Mon, 20 Sep 2021 20:14:50 -0400 >>> Harry Wentland wrote: >>> ... > >> Did anybody start any CM doc patches in Weston or Wayland yet? > > There is the > https://gitlab.freedesktop.org/swick/wayland-protocols/-/blob/color/unstable/color-management/color.rst > we started a long time ago, and have not really touched it for a while. > Since we last touched it, at least my understanding has developed > somewhat. > > It is linked from the overview in > https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/14 > and if you want to propose changes, the way to do it is file a MR in > https://gitlab.freedesktop.org/swick/wayland-protocols/-/merge_requests > against the 'color' branch. Patches very much welcome, that doc does > not need to limit itself to Wayland. :-) > Right, I've read all that a while back. It might be a good place to consolidate most of the Linux CM/HDR discussion, since gitlab is good with allowing discussions, we can track changes, and it's more formatting and diagram friendly than text-only email. > We also have issues tracked at > https://gitlab.freedesktop.org/swick/wayland-protocols/-/issues?scope=all=%E2%9C%93=opened > >>> Pre-curve for instance could be a combination of decoding to linear >>> light and a shaper for the 3D LUT coming next. That's why we don't call >>> them gamma or EOTF, that would be too limiting. >>> >>> (Using a shaper may help to keep the 3D LUT size reasonable - I suppose >>> very much like those multi-segmented LUTs.) >>> >> >> AFAIU a 3D LUTs will need a shaper as they don't have enough precision. >> But that's going deeper into color theory than I understand. Vitaly would >> know better all the details around 3D LUT usage. > > There is a very practical problem: the sheer number of elements in a 3D > LUT grows to the power of three. So you can't have very many taps per > channel without storage requirements blowing up. Each element needs to > be a 3-channel value, too. And then 8 bits is not enough. > And those storage requirements would have a direct impact on silicon real estate and therefore the price and power usage of the HW. Harry > I'm really happy that Vitaly is working with us on Weston and Wayland. :-) > He's a huge help, and I feel like I'm currently the one slowing things > down by being backlogged in reviews. > > > Thanks, > pq >
Re: Regression with mainline kernel on rpi4
On Wed, Sep 22, 2021 at 3:11 AM Sudip Mukherjee wrote: > > That test script is triggering the openqa job, but its running only > after lava is able to login. The trace is appearing before the login > prompt even, so test_mainline.sh should not matter here. Side note: the traces might be more legible if you have debug info in the kernel, and run the dmesg through the script in scripts/decode_stacktrace.sh which should give line numbers and inlining information. That often makes it much easier to see which access it is that hits a NULL pointer dereference. On x86-64, generally just decode the instruction stream, and look at the instruction patterns and try to figure out where an oops is coming from, but that's much less useful on arm64 (partly because I'm not as used to it, but because the arm64 oopses don't print out much of the instructions so there's often little to go by). Linus
Re: [Intel-gfx] [PATCH] drm/i915: Drop stealing of bits from i915_sw_fence function pointer
On 22/09/2021 16:21, Tvrtko Ursulin wrote: On 22/09/2021 15:57, Matthew Brost wrote: Rather than stealing bits from i915_sw_fence function pointer use seperate fields for function pointer and flags. If using two different fields, the 4 byte alignment for the i915_sw_fence function pointer can also be dropped. v2: (CI) - Set new function field rather than flags in __i915_sw_fence_init Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_request.c | 4 ++-- drivers/gpu/drm/i915/i915_sw_fence.c | 12 +-- drivers/gpu/drm/i915/i915_sw_fence.h | 21 +-- drivers/gpu/drm/i915/i915_sw_fence_work.c | 2 +- .../gpu/drm/i915/selftests/i915_sw_fence.c | 2 +- drivers/gpu/drm/i915/selftests/lib_sw_fence.c | 4 ++-- 8 files changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a7ca38613f89..6d5bb55ffc82 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10323,7 +10323,7 @@ static void intel_atomic_commit_work(struct work_struct *work) intel_atomic_commit_tail(state); } -static int __i915_sw_fence_call +static int intel_atomic_commit_ready(struct i915_sw_fence *fence, enum i915_sw_fence_notify notify) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..df5fec5c3da8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -800,7 +800,7 @@ static void free_engines_rcu(struct rcu_head *rcu) free_engines(engines); } -static int __i915_sw_fence_call +static int engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_gem_engines *engines = diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ce446716d092..945d3025a0b6 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -719,7 +719,7 @@ void i915_request_cancel(struct i915_request *rq, int error) intel_context_cancel_request(rq->context, rq); } -static int __i915_sw_fence_call +static int submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *request = @@ -755,7 +755,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } -static int __i915_sw_fence_call +static int semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *rq = container_of(fence, typeof(*rq), semaphore); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index c589a681da77..1c080dd1f718 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -34,7 +34,7 @@ enum { static void *i915_sw_fence_debug_hint(void *addr) { - return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK); + return (void *)(((struct i915_sw_fence *)addr)->fn); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -126,10 +126,7 @@ static inline void debug_fence_assert(struct i915_sw_fence *fence) static int __i915_sw_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - i915_sw_fence_notify_t fn; - - fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); - return fn(fence, state); + return fence->fn(fence, state); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -242,10 +239,11 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, const char *name, struct lock_class_key *key) { - BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); + BUG_ON(!fn); __init_waitqueue_head(>wait, name, key); - fence->flags = (unsigned long)fn; + fence->fn = fn; + fence->flags = 0; i915_sw_fence_reinit(fence); } diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 30a863353ee6..70ba1789aa89 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -17,26 +17,25 @@ struct completion; struct dma_resv; +struct i915_sw_fence; + +enum i915_sw_fence_notify { + FENCE_COMPLETE, + FENCE_FREE +}; + +typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *, + enum i915_sw_fence_notify state); struct i915_sw_fence { wait_queue_head_t wait; + i915_sw_fence_notify_t fn; unsigned long flags; Looks good to me. I'd just make the flags narrower now that they can be, and put them down.. atomic_t pending; .. here as unsigned int and so we save 4 bytes,
Re: [Intel-gfx] [PATCH] drm/i915: Drop stealing of bits from i915_sw_fence function pointer
On 22/09/2021 15:57, Matthew Brost wrote: Rather than stealing bits from i915_sw_fence function pointer use seperate fields for function pointer and flags. If using two different fields, the 4 byte alignment for the i915_sw_fence function pointer can also be dropped. v2: (CI) - Set new function field rather than flags in __i915_sw_fence_init Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_request.c | 4 ++-- drivers/gpu/drm/i915/i915_sw_fence.c | 12 +-- drivers/gpu/drm/i915/i915_sw_fence.h | 21 +-- drivers/gpu/drm/i915/i915_sw_fence_work.c | 2 +- .../gpu/drm/i915/selftests/i915_sw_fence.c| 2 +- drivers/gpu/drm/i915/selftests/lib_sw_fence.c | 4 ++-- 8 files changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a7ca38613f89..6d5bb55ffc82 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10323,7 +10323,7 @@ static void intel_atomic_commit_work(struct work_struct *work) intel_atomic_commit_tail(state); } -static int __i915_sw_fence_call +static int intel_atomic_commit_ready(struct i915_sw_fence *fence, enum i915_sw_fence_notify notify) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..df5fec5c3da8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -800,7 +800,7 @@ static void free_engines_rcu(struct rcu_head *rcu) free_engines(engines); } -static int __i915_sw_fence_call +static int engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_gem_engines *engines = diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ce446716d092..945d3025a0b6 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -719,7 +719,7 @@ void i915_request_cancel(struct i915_request *rq, int error) intel_context_cancel_request(rq->context, rq); } -static int __i915_sw_fence_call +static int submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *request = @@ -755,7 +755,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } -static int __i915_sw_fence_call +static int semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *rq = container_of(fence, typeof(*rq), semaphore); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index c589a681da77..1c080dd1f718 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -34,7 +34,7 @@ enum { static void *i915_sw_fence_debug_hint(void *addr) { - return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK); + return (void *)(((struct i915_sw_fence *)addr)->fn); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -126,10 +126,7 @@ static inline void debug_fence_assert(struct i915_sw_fence *fence) static int __i915_sw_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - i915_sw_fence_notify_t fn; - - fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); - return fn(fence, state); + return fence->fn(fence, state); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -242,10 +239,11 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, const char *name, struct lock_class_key *key) { - BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); + BUG_ON(!fn); __init_waitqueue_head(>wait, name, key); - fence->flags = (unsigned long)fn; + fence->fn = fn; + fence->flags = 0; i915_sw_fence_reinit(fence); } diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 30a863353ee6..70ba1789aa89 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -17,26 +17,25 @@ struct completion; struct dma_resv; +struct i915_sw_fence; + +enum i915_sw_fence_notify { + FENCE_COMPLETE, + FENCE_FREE +}; + +typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *, + enum i915_sw_fence_notify state); struct i915_sw_fence { wait_queue_head_t wait; + i915_sw_fence_notify_t fn; unsigned long flags; Looks good to me. I'd just make the flags narrower now that they can be, and
[PATCH] backlight: hx8357: Add SPI device ID table
Currently autoloading for SPI devices does not use the DT ID table, it uses SPI modalises. Supporting OF modalises is going to be difficult if not impractical, an attempt was made but has been reverted, so ensure that module autoloading works for this driver by adding a SPI device ID table. Fixes: 96c8395e2166 ("spi: Revert modalias changes") Signed-off-by: Mark Brown --- drivers/video/backlight/hx8357.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c index 9b50bc96e00f..c64b1fbe027f 100644 --- a/drivers/video/backlight/hx8357.c +++ b/drivers/video/backlight/hx8357.c @@ -565,6 +565,19 @@ static struct lcd_ops hx8357_ops = { .get_power = hx8357_get_power, }; +static const struct spi_device_id hx8357_spi_ids[] = { + { + .name = "hx8357", + .driver_data = (kernel_ulong_t)hx8357_lcd_init, + }, + { + .name = "hx8369", + .driver_data = (kernel_ulong_t)hx8369_lcd_init, + }, + {}, +}; +MODULE_DEVICE_TABLE(spi, hx8357_spi_ids); + static const struct of_device_id hx8357_dt_ids[] = { { .compatible = "himax,hx8357", @@ -672,6 +685,7 @@ static struct spi_driver hx8357_driver = { .name = "hx8357", .of_match_table = hx8357_dt_ids, }, + .id_table = hx8357_spi_ids, }; module_spi_driver(hx8357_driver); -- 2.20.1
Re: [PATCH 01/26] dma-buf: add dma_resv_for_each_fence_unlocked v4
On 22/09/2021 15:50, Christian König wrote: Am 22.09.21 um 16:36 schrieb Tvrtko Ursulin: + +/** + * dma_resv_iter_first_unlocked - first fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the first fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor) +{ + rcu_read_lock(); + do { + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_first_unlocked); Why is this one split from dma_resv_iter_begin and even exported? I've split it to be able to use dma_resv_iter_begin in both the unlocked and locked iterator. Ok. I couldn't find any users in the series. This is used in the dma_resv_for_each_fence_unlocked() macro to return the first fence. Doh! + +/** + * dma_resv_iter_next_unlocked - next fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the next fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor) +{ + bool restart; + + rcu_read_lock(); + cursor->is_restarted = false; + restart = read_seqcount_retry(>obj->seq, cursor->seq); + do { + if (restart) + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + restart = true; + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_next_unlocked); Couldn't dma_resv_iter_first_unlocked and dma_resv_iter_next_unlocked share the same implementation? Especially if you are able to replace cursor->is_restarted with cursor->index == -1. That's what I had initially, but Daniel disliked it for some reason. You then need a centralized walk function instead of first/next. I had some ideas to only consolidate "first" and "next" helpers but never mind, yours is fine as well. Regards, Tvrtko Thanks, Christian. Regards, Tvrtko
Re: [RFC PATCH v3 1/6] drm/doc: Color Management and HDR10 RFC
On 2021-09-20 20:14, Harry Wentland wrote: > On 2021-09-15 10:01, Pekka Paalanen wrote:> On Fri, 30 Jul 2021 16:41:29 -0400 >> Harry Wentland wrote: >> >>> +If a display's maximum HDR white level is correctly reported it is trivial >>> +to convert between all of the above representations of SDR white level. If >>> +it is not, defining SDR luminance as a nits value, or a ratio vs a fixed >>> +nits value is preferred, assuming we are blending in linear space. >>> + >>> +It is our experience that many HDR displays do not report maximum white >>> +level correctly >> >> Which value do you refer to as "maximum white", and how did you measure >> it? >> > Good question. I haven't played with those displays myself but I'll try to > find out a bit more background behind this statement. > Some TVs report the EOTF but not the luminance values. For an example edid-code capture of my eDP HDR panel: HDR Static Metadata Data Block: Electro optical transfer functions: Traditional gamma - SDR luminance range SMPTE ST2084 Supported static metadata descriptors: Static metadata type 1 Desired content max luminance: 115 (603.666 cd/m^2) Desired content max frame-average luminance: 109 (530.095 cd/m^2) Desired content min luminance: 7 (0.005 cd/m^2) I suspect on those TVs it looks like this: HDR Static Metadata Data Block: Electro optical transfer functions: Traditional gamma - SDR luminance range SMPTE ST2084 Supported static metadata descriptors: Static metadata type 1 Windows has some defaults in this case and our Windows driver also has some defaults. Using defaults in the 1000-2000 nits range would yield much better tone-mapping results than assuming the monitor can support a full 10k nits. As an aside, recently we've come across displays where the max average luminance is higher than the max peak luminance. This is not a mistake but due to how the display's dimming zones work. Not sure what impact this might have on tone-mapping, other than to keep in mind that we can assume that max_avg < max_peak. Harry
[PATCH] drm/i915: Drop stealing of bits from i915_sw_fence function pointer
Rather than stealing bits from i915_sw_fence function pointer use seperate fields for function pointer and flags. If using two different fields, the 4 byte alignment for the i915_sw_fence function pointer can also be dropped. v2: (CI) - Set new function field rather than flags in __i915_sw_fence_init Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_request.c | 4 ++-- drivers/gpu/drm/i915/i915_sw_fence.c | 12 +-- drivers/gpu/drm/i915/i915_sw_fence.h | 21 +-- drivers/gpu/drm/i915/i915_sw_fence_work.c | 2 +- .../gpu/drm/i915/selftests/i915_sw_fence.c| 2 +- drivers/gpu/drm/i915/selftests/lib_sw_fence.c | 4 ++-- 8 files changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a7ca38613f89..6d5bb55ffc82 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10323,7 +10323,7 @@ static void intel_atomic_commit_work(struct work_struct *work) intel_atomic_commit_tail(state); } -static int __i915_sw_fence_call +static int intel_atomic_commit_ready(struct i915_sw_fence *fence, enum i915_sw_fence_notify notify) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c2ab0e22db0a..df5fec5c3da8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -800,7 +800,7 @@ static void free_engines_rcu(struct rcu_head *rcu) free_engines(engines); } -static int __i915_sw_fence_call +static int engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_gem_engines *engines = diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ce446716d092..945d3025a0b6 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -719,7 +719,7 @@ void i915_request_cancel(struct i915_request *rq, int error) intel_context_cancel_request(rq->context, rq); } -static int __i915_sw_fence_call +static int submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *request = @@ -755,7 +755,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } -static int __i915_sw_fence_call +static int semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { struct i915_request *rq = container_of(fence, typeof(*rq), semaphore); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index c589a681da77..1c080dd1f718 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -34,7 +34,7 @@ enum { static void *i915_sw_fence_debug_hint(void *addr) { - return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK); + return (void *)(((struct i915_sw_fence *)addr)->fn); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -126,10 +126,7 @@ static inline void debug_fence_assert(struct i915_sw_fence *fence) static int __i915_sw_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - i915_sw_fence_notify_t fn; - - fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); - return fn(fence, state); + return fence->fn(fence, state); } #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS @@ -242,10 +239,11 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, const char *name, struct lock_class_key *key) { - BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); + BUG_ON(!fn); __init_waitqueue_head(>wait, name, key); - fence->flags = (unsigned long)fn; + fence->fn = fn; + fence->flags = 0; i915_sw_fence_reinit(fence); } diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 30a863353ee6..70ba1789aa89 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -17,26 +17,25 @@ struct completion; struct dma_resv; +struct i915_sw_fence; + +enum i915_sw_fence_notify { + FENCE_COMPLETE, + FENCE_FREE +}; + +typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *, + enum i915_sw_fence_notify state); struct i915_sw_fence { wait_queue_head_t wait; + i915_sw_fence_notify_t fn; unsigned long flags; atomic_t pending; int error; }; #define I915_SW_FENCE_CHECKED_BIT 0 /* used internally for DAG checking */ -#define I915_SW_FENCE_PRIVATE_BIT 1
Re: [PATCH v3 4/9] drm/scheduler: Add fence deadline support
On Wed, Sep 22, 2021 at 7:31 AM Andrey Grodzovsky wrote: > > > On 2021-09-21 11:32 p.m., Rob Clark wrote: > > On Tue, Sep 21, 2021 at 7:18 PM Andrey Grodzovsky > > wrote: > >> > >> On 2021-09-21 4:47 p.m., Rob Clark wrote: > >>> On Tue, Sep 21, 2021 at 1:09 PM Andrey Grodzovsky > >>> wrote: > On 2021-09-03 2:47 p.m., Rob Clark wrote: > > > From: Rob Clark > > > > As the finished fence is the one that is exposed to userspace, and > > therefore the one that other operations, like atomic update, would > > block on, we need to propagate the deadline from from the finished > > fence to the actual hw fence. > > > > v2: Split into drm_sched_fence_set_parent() (ckoenig) > > > > Signed-off-by: Rob Clark > > --- > > drivers/gpu/drm/scheduler/sched_fence.c | 34 > > + > > drivers/gpu/drm/scheduler/sched_main.c | 2 +- > > include/drm/gpu_scheduler.h | 8 ++ > > 3 files changed, 43 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/scheduler/sched_fence.c > > b/drivers/gpu/drm/scheduler/sched_fence.c > > index bcea035cf4c6..4fc41a71d1c7 100644 > > --- a/drivers/gpu/drm/scheduler/sched_fence.c > > +++ b/drivers/gpu/drm/scheduler/sched_fence.c > > @@ -128,6 +128,30 @@ static void > > drm_sched_fence_release_finished(struct dma_fence *f) > > dma_fence_put(>scheduled); > > } > > > > +static void drm_sched_fence_set_deadline_finished(struct dma_fence *f, > > + ktime_t deadline) > > +{ > > + struct drm_sched_fence *fence = to_drm_sched_fence(f); > > + unsigned long flags; > > + > > + spin_lock_irqsave(>lock, flags); > > + > > + /* If we already have an earlier deadline, keep it: */ > > + if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags) && > > + ktime_before(fence->deadline, deadline)) { > > + spin_unlock_irqrestore(>lock, flags); > > + return; > > + } > > + > > + fence->deadline = deadline; > > + set_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags); > > + > > + spin_unlock_irqrestore(>lock, flags); > > + > > + if (fence->parent) > > + dma_fence_set_deadline(fence->parent, deadline); > > +} > > + > > static const struct dma_fence_ops drm_sched_fence_ops_scheduled = { > > .get_driver_name = drm_sched_fence_get_driver_name, > > .get_timeline_name = drm_sched_fence_get_timeline_name, > > @@ -138,6 +162,7 @@ static const struct dma_fence_ops > > drm_sched_fence_ops_finished = { > > .get_driver_name = drm_sched_fence_get_driver_name, > > .get_timeline_name = drm_sched_fence_get_timeline_name, > > .release = drm_sched_fence_release_finished, > > + .set_deadline = drm_sched_fence_set_deadline_finished, > > }; > > > > struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f) > > @@ -152,6 +177,15 @@ struct drm_sched_fence *to_drm_sched_fence(struct > > dma_fence *f) > > } > > EXPORT_SYMBOL(to_drm_sched_fence); > > > > +void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence, > > + struct dma_fence *fence) > > +{ > > + s_fence->parent = dma_fence_get(fence); > > + if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, > > + _fence->finished.flags)) > > + dma_fence_set_deadline(fence, s_fence->deadline); > I believe above you should pass be s_fence->finished to > dma_fence_set_deadline > instead it fence which is the HW fence itself. > >>> Hmm, unless this has changed recently with some patches I don't have, > >>> s_fence->parent is the one signalled by hw, so it is the one we want > >>> to set the deadline on > >>> > >>> BR, > >>> -R > >> > >> No it didn't change. But then when exactly will > >> drm_sched_fence_set_deadline_finished > >> execute such that fence->parent != NULL ? In other words, I am not clear > >> how propagation > >> happens otherwise - if dma_fence_set_deadline is called with the HW > >> fence then the assumption > >> here is that driver provided driver specific > >> dma_fence_ops.dma_fence_set_deadline callback executes > >> but I was under impression that drm_sched_fence_set_deadline_finished is > >> the one that propagates > >> the deadline to the HW fence's callback and for it to execute > >> dma_fence_set_deadline needs to be called > >> with s_fence->finished. > > Assuming I didn't screw up drm/msm conversion to scheduler, > > _fence->finished is the one that will be returned to userspace.. and > > later passed back to kernel for atomic commit (or to the compositor). > > So it is the one that fence->set_deadline() will be called on. But
Re: [PATCH 01/26] dma-buf: add dma_resv_for_each_fence_unlocked v4
Am 22.09.21 um 16:36 schrieb Tvrtko Ursulin: + +/** + * dma_resv_iter_first_unlocked - first fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the first fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor) +{ + rcu_read_lock(); + do { + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_first_unlocked); Why is this one split from dma_resv_iter_begin and even exported? I've split it to be able to use dma_resv_iter_begin in both the unlocked and locked iterator. I couldn't find any users in the series. This is used in the dma_resv_for_each_fence_unlocked() macro to return the first fence. + +/** + * dma_resv_iter_next_unlocked - next fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the next fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor) +{ + bool restart; + + rcu_read_lock(); + cursor->is_restarted = false; + restart = read_seqcount_retry(>obj->seq, cursor->seq); + do { + if (restart) + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + restart = true; + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_next_unlocked); Couldn't dma_resv_iter_first_unlocked and dma_resv_iter_next_unlocked share the same implementation? Especially if you are able to replace cursor->is_restarted with cursor->index == -1. That's what I had initially, but Daniel disliked it for some reason. You then need a centralized walk function instead of first/next. Thanks, Christian. Regards, Tvrtko
Re: [PATCH v9 2/4] dt-bindings: mfd: logicvc: Add patternProperties for the display
On Tue, 14 Sep 2021, Paul Kocialkowski wrote: > The LogiCVC multi-function device has a display part which is now > described in its binding. Add a patternProperties match for it. > > Signed-off-by: Paul Kocialkowski > --- > Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml | 3 +++ > 1 file changed, 3 insertions(+) Applied, thanks. -- Lee Jones [李琼斯] Senior Technical Lead - Developer Services Linaro.org │ Open source software for Arm SoCs Follow Linaro: Facebook | Twitter | Blog
Re: [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl
On 22/09/2021 15:31, Christian König wrote: Am 22.09.21 um 12:21 schrieb Tvrtko Ursulin: On 22/09/2021 10:10, Christian König wrote: This makes the function much simpler since the complex retry logic is now handled else where. Signed-off-by: Christian König --- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 35 ++-- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c index 6234e17259c1..313afb4a11c7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c @@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; - struct dma_resv_list *list; - unsigned int seq; + struct dma_resv_iter cursor; + struct dma_fence *fence; int err; err = -ENOENT; @@ -109,27 +109,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * to report the overall busyness. This is what the wait-ioctl does. * */ -retry: - seq = raw_read_seqcount(>base.resv->seq); - - /* Translate the exclusive fence to the READ *and* WRITE engine */ - args->busy = busy_check_writer(dma_resv_excl_fence(obj->base.resv)); - - /* Translate shared fences to READ set of engines */ - list = dma_resv_shared_list(obj->base.resv); - if (list) { - unsigned int shared_count = list->shared_count, i; - - for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence = - rcu_dereference(list->shared[i]); - + args->busy = false; You can drop this line, especially since it is not a boolean. With that: I just realized that this won't work. We still need to initialize the return value when there is no fence at all in the resv object. Reviewed-by: Tvrtko Ursulin Does that still counts if I set args->busy to zero? Ah yes, my bad, apologies. You can keep the r-b. Regards, Tvrtko Thanks, Christian. Regards, Tvrtko + dma_resv_iter_begin(, obj->base.resv, true); + dma_resv_for_each_fence_unlocked(, fence) { + if (dma_resv_iter_is_restarted()) + args->busy = 0; + + if (dma_resv_iter_is_exclusive()) + /* Translate the exclusive fence to the READ *and* WRITE engine */ + args->busy |= busy_check_writer(fence); + else + /* Translate shared fences to READ set of engines */ args->busy |= busy_check_reader(fence); - } } - - if (args->busy && read_seqcount_retry(>base.resv->seq, seq)) - goto retry; + dma_resv_iter_end(); err = 0; out:
Re: [PATCH 01/26] dma-buf: add dma_resv_for_each_fence_unlocked v4
On 22/09/2021 10:10, Christian König wrote: Abstract the complexity of iterating over all the fences in a dma_resv object. The new loop handles the whole RCU and retry dance and returns only fences where we can be sure we grabbed the right one. v2: fix accessing the shared fences while they might be freed, improve kerneldoc, rename _cursor to _iter, add dma_resv_iter_is_exclusive, add dma_resv_iter_begin/end v3: restructor the code, move rcu_read_lock()/unlock() into the iterator, add dma_resv_iter_is_restarted() v4: fix NULL deref when no explicit fence exists, drop superflous rcu_read_lock()/unlock() calls. Signed-off-by: Christian König --- drivers/dma-buf/dma-resv.c | 95 ++ include/linux/dma-resv.h | 95 ++ 2 files changed, 190 insertions(+) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 84fbe60629e3..7768140ab36d 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -323,6 +323,101 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) } EXPORT_SYMBOL(dma_resv_add_excl_fence); +/** + * dma_resv_iter_restart_unlocked - restart the unlocked iterator + * @cursor: The dma_resv_iter object to restart + * + * Restart the unlocked iteration by initializing the cursor object. + */ +static void dma_resv_iter_restart_unlocked(struct dma_resv_iter *cursor) +{ + cursor->seq = read_seqcount_begin(>obj->seq); + cursor->index = -1; + if (cursor->all_fences) + cursor->fences = dma_resv_shared_list(cursor->obj); + else + cursor->fences = NULL; + cursor->is_restarted = true; +} + +/** + * dma_resv_iter_walk_unlocked - walk over fences in a dma_resv obj + * @cursor: cursor to record the current position + * + * Return all the fences in the dma_resv object which are not yet signaled. + * The returned fence has an extra local reference so will stay alive. + * If a concurrent modify is detected the whole iterration is started over again. iteration + */ +static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor) +{ + struct dma_resv *obj = cursor->obj; + + do { + /* Drop the reference from the previous round */ + dma_fence_put(cursor->fence); + + if (cursor->index++ == -1) { + cursor->fence = dma_resv_excl_fence(obj); + + } else if (!cursor->fences || + cursor->index >= cursor->fences->shared_count) { + cursor->fence = NULL; + + } else { + struct dma_resv_list *fences = cursor->fences; + unsigned int idx = cursor->index; + + cursor->fence = rcu_dereference(fences->shared[idx]); + } + if (cursor->fence) + cursor->fence = dma_fence_get_rcu(cursor->fence); + } while (cursor->fence && dma_fence_is_signaled(cursor->fence)); +} + +/** + * dma_resv_iter_first_unlocked - first fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the first fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor) +{ + rcu_read_lock(); + do { + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_first_unlocked); Why is this one split from dma_resv_iter_begin and even exported? I couldn't find any users in the series. + +/** + * dma_resv_iter_next_unlocked - next fence in an unlocked dma_resv obj. + * @cursor: the cursor with the current position + * + * Returns the next fence from an unlocked dma_resv obj. + */ +struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor) +{ + bool restart; + + rcu_read_lock(); + cursor->is_restarted = false; + restart = read_seqcount_retry(>obj->seq, cursor->seq); + do { + if (restart) + dma_resv_iter_restart_unlocked(cursor); + dma_resv_iter_walk_unlocked(cursor); + restart = true; + } while (read_seqcount_retry(>obj->seq, cursor->seq)); + rcu_read_unlock(); + + return cursor->fence; +} +EXPORT_SYMBOL(dma_resv_iter_next_unlocked); Couldn't dma_resv_iter_first_unlocked and dma_resv_iter_next_unlocked share the same implementation? Especially if you are able to replace cursor->is_restarted with cursor->index == -1. + /** * dma_resv_copy_fences - Copy all fences from src to dst. * @dst: the destination reservation object diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 9100dd3dc21f..baf77a542392
Re: [PATCH v3 5/8] x86/sme: Replace occurrences of sme_active() with cc_platform_has()
On Wed, Sep 22, 2021 at 08:40:43AM -0500, Tom Lendacky wrote: > On 9/21/21 4:58 PM, Kirill A. Shutemov wrote: > > On Tue, Sep 21, 2021 at 04:43:59PM -0500, Tom Lendacky wrote: > > > On 9/21/21 4:34 PM, Kirill A. Shutemov wrote: > > > > On Tue, Sep 21, 2021 at 11:27:17PM +0200, Borislav Petkov wrote: > > > > > On Wed, Sep 22, 2021 at 12:20:59AM +0300, Kirill A. Shutemov wrote: > > > > > > I still believe calling cc_platform_has() from __startup_64() is > > > > > > totally > > > > > > broken as it lacks proper wrapping while accessing global variables. > > > > > > > > > > Well, one of the issues on the AMD side was using boot_cpu_data too > > > > > early and the Intel side uses it too. Can you replace those checks > > > > > with > > > > > is_tdx_guest() or whatever was the helper's name which would check > > > > > whether the the kernel is running as a TDX guest, and see if that > > > > > helps? > > > > > > > > There's no need in Intel check this early. Only AMD need it. Maybe just > > > > opencode them? > > > > > > Any way you can put a gzipped/bzipped copy of your vmlinux file somewhere > > > I > > > can grab it from and take a look at it? > > > > You can find broken vmlinux and bzImage here: > > > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdrive.google.com%2Fdrive%2Ffolders%2F1n74vUQHOGebnF70Im32qLFY8iS3wvjIs%3Fusp%3Dsharingdata=04%7C01%7Cthomas.lendacky%40amd.com%7C1c7adf380cbe4c1a6bb708d97d4af6ff%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637678583935705530%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000sdata=gA30x%2Bfu97tUx0p2UqI8HgjiL8bxDbK1GqgJBbUrUE4%3Dreserved=0 > > > > Let me know when I can remove it. > > Looking at everything, it is all RIP relative addressing, so those > accesses should be fine. Not fine, but waiting to blowup with random build environment change. > Your image has the intel_cc_platform_has() > function, does it work if you remove that call? Because I think it may be > the early call into that function which looks like it has instrumentation > that uses %gs in __sanitizer_cov_trace_pc and %gs is not setup properly > yet. And since boot_cpu_data.x86_vendor will likely be zero this early it > will match X86_VENDOR_INTEL and call into that function. Right removing call to intel_cc_platform_has() or moving it to cc_platform.c fixes the issue. -- Kirill A. Shutemov
Re: [PATCH v3 4/9] drm/scheduler: Add fence deadline support
On 2021-09-21 11:32 p.m., Rob Clark wrote: On Tue, Sep 21, 2021 at 7:18 PM Andrey Grodzovsky wrote: On 2021-09-21 4:47 p.m., Rob Clark wrote: On Tue, Sep 21, 2021 at 1:09 PM Andrey Grodzovsky wrote: On 2021-09-03 2:47 p.m., Rob Clark wrote: From: Rob Clark As the finished fence is the one that is exposed to userspace, and therefore the one that other operations, like atomic update, would block on, we need to propagate the deadline from from the finished fence to the actual hw fence. v2: Split into drm_sched_fence_set_parent() (ckoenig) Signed-off-by: Rob Clark --- drivers/gpu/drm/scheduler/sched_fence.c | 34 + drivers/gpu/drm/scheduler/sched_main.c | 2 +- include/drm/gpu_scheduler.h | 8 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index bcea035cf4c6..4fc41a71d1c7 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -128,6 +128,30 @@ static void drm_sched_fence_release_finished(struct dma_fence *f) dma_fence_put(>scheduled); } +static void drm_sched_fence_set_deadline_finished(struct dma_fence *f, + ktime_t deadline) +{ + struct drm_sched_fence *fence = to_drm_sched_fence(f); + unsigned long flags; + + spin_lock_irqsave(>lock, flags); + + /* If we already have an earlier deadline, keep it: */ + if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags) && + ktime_before(fence->deadline, deadline)) { + spin_unlock_irqrestore(>lock, flags); + return; + } + + fence->deadline = deadline; + set_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, >flags); + + spin_unlock_irqrestore(>lock, flags); + + if (fence->parent) + dma_fence_set_deadline(fence->parent, deadline); +} + static const struct dma_fence_ops drm_sched_fence_ops_scheduled = { .get_driver_name = drm_sched_fence_get_driver_name, .get_timeline_name = drm_sched_fence_get_timeline_name, @@ -138,6 +162,7 @@ static const struct dma_fence_ops drm_sched_fence_ops_finished = { .get_driver_name = drm_sched_fence_get_driver_name, .get_timeline_name = drm_sched_fence_get_timeline_name, .release = drm_sched_fence_release_finished, + .set_deadline = drm_sched_fence_set_deadline_finished, }; struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f) @@ -152,6 +177,15 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f) } EXPORT_SYMBOL(to_drm_sched_fence); +void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence, + struct dma_fence *fence) +{ + s_fence->parent = dma_fence_get(fence); + if (test_bit(DMA_FENCE_FLAG_HAS_DEADLINE_BIT, + _fence->finished.flags)) + dma_fence_set_deadline(fence, s_fence->deadline); I believe above you should pass be s_fence->finished to dma_fence_set_deadline instead it fence which is the HW fence itself. Hmm, unless this has changed recently with some patches I don't have, s_fence->parent is the one signalled by hw, so it is the one we want to set the deadline on BR, -R No it didn't change. But then when exactly will drm_sched_fence_set_deadline_finished execute such that fence->parent != NULL ? In other words, I am not clear how propagation happens otherwise - if dma_fence_set_deadline is called with the HW fence then the assumption here is that driver provided driver specific dma_fence_ops.dma_fence_set_deadline callback executes but I was under impression that drm_sched_fence_set_deadline_finished is the one that propagates the deadline to the HW fence's callback and for it to execute dma_fence_set_deadline needs to be called with s_fence->finished. Assuming I didn't screw up drm/msm conversion to scheduler, _fence->finished is the one that will be returned to userspace.. and later passed back to kernel for atomic commit (or to the compositor). So it is the one that fence->set_deadline() will be called on. But s_fence->parent is the actual hw fence that needs to know about the deadline. Depending on whether or not the job has been written into hw ringbuffer or not, there are two cases: 1) not scheduled yet, s_fence will store the deadline and propagate it later once s_fence->parent is known And by later you mean the call to drm_sched_fence_set_parent after HW fence is returned ? If yes I think i get it now. Andrey 2) already scheduled, in which case s_fence->finished.set_deadline will propagate it directly to the real fence BR, -R Andrey Andrey +} + struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity, void *owner) { diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index
Re: [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl
Am 22.09.21 um 12:21 schrieb Tvrtko Ursulin: On 22/09/2021 10:10, Christian König wrote: This makes the function much simpler since the complex retry logic is now handled else where. Signed-off-by: Christian König --- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 35 ++-- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c index 6234e17259c1..313afb4a11c7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c @@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; - struct dma_resv_list *list; - unsigned int seq; + struct dma_resv_iter cursor; + struct dma_fence *fence; int err; err = -ENOENT; @@ -109,27 +109,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * to report the overall busyness. This is what the wait-ioctl does. * */ -retry: - seq = raw_read_seqcount(>base.resv->seq); - - /* Translate the exclusive fence to the READ *and* WRITE engine */ - args->busy = busy_check_writer(dma_resv_excl_fence(obj->base.resv)); - - /* Translate shared fences to READ set of engines */ - list = dma_resv_shared_list(obj->base.resv); - if (list) { - unsigned int shared_count = list->shared_count, i; - - for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence = - rcu_dereference(list->shared[i]); - + args->busy = false; You can drop this line, especially since it is not a boolean. With that: I just realized that this won't work. We still need to initialize the return value when there is no fence at all in the resv object. Reviewed-by: Tvrtko Ursulin Does that still counts if I set args->busy to zero? Thanks, Christian. Regards, Tvrtko + dma_resv_iter_begin(, obj->base.resv, true); + dma_resv_for_each_fence_unlocked(, fence) { + if (dma_resv_iter_is_restarted()) + args->busy = 0; + + if (dma_resv_iter_is_exclusive()) + /* Translate the exclusive fence to the READ *and* WRITE engine */ + args->busy |= busy_check_writer(fence); + else + /* Translate shared fences to READ set of engines */ args->busy |= busy_check_reader(fence); - } } - - if (args->busy && read_seqcount_retry(>base.resv->seq, seq)) - goto retry; + dma_resv_iter_end(); err = 0; out:
Re: [PATCH 0/5] drm/gma500: Managed cleanup
On Mon, Sep 20, 2021 at 4:10 PM Thomas Zimmermann wrote: > > Switch gma500 to managed cleanup and remove the manual cleanup > code from the driver's PCI callbacks. > > Managed cleanup involves embedding the DRM device structure in the > driver's structure. In preparation, patch 1 replaces references all > references to dev_private with a helper function. > > Patch 2 adds managed cleanup for pci_enable_device(). > > Patches 3 and 4 embed struct drm_device in struct_drm_psb_private. The > structure's memory is being automatically released. > > Patch 5 adds managed cleanup for the device resources. Instead of > calling the large, monolithic function psb_driver_unload(), the release > code could be split up split into smaller helpers and reuse exising > functionality from devres. > > Future work: for a number of drivers, the PCI remove callback contains > only a single call to drm_device_unregister(). In a later patchset, > this could be implemented as another shared helper within DRM. > > Tested on Atom N2800 hardware. Thanks for the patches! For the entire series: Reviewed-by: Patrik Jakobsson I'll let you apply this to drm-misc-next yourself Cheers Patrik > > Thomas Zimmermann (5): > drm/gma500: Replace references to dev_private with helper function > drm/gma500: Disable PCI device during shutdown > drm/gma500: Embed struct drm_device in struct drm_psb_private > drm/gma500: Remove dev_priv branch from unload function > drm/gma500: Managed device release > > drivers/gpu/drm/gma500/backlight.c | 12 +- > drivers/gpu/drm/gma500/cdv_device.c| 24 ++-- > drivers/gpu/drm/gma500/cdv_intel_display.c | 10 +- > drivers/gpu/drm/gma500/cdv_intel_dp.c | 12 +- > drivers/gpu/drm/gma500/cdv_intel_lvds.c| 22 +-- > drivers/gpu/drm/gma500/framebuffer.c | 16 +-- > drivers/gpu/drm/gma500/gem.c | 2 +- > drivers/gpu/drm/gma500/gma_device.c| 2 +- > drivers/gpu/drm/gma500/gma_display.c | 14 +- > drivers/gpu/drm/gma500/gtt.c | 18 +-- > drivers/gpu/drm/gma500/intel_bios.c| 10 +- > drivers/gpu/drm/gma500/intel_gmbus.c | 12 +- > drivers/gpu/drm/gma500/mid_bios.c | 11 +- > drivers/gpu/drm/gma500/mmu.c | 12 +- > drivers/gpu/drm/gma500/oaktrail_crtc.c | 8 +- > drivers/gpu/drm/gma500/oaktrail_device.c | 20 +-- > drivers/gpu/drm/gma500/oaktrail_hdmi.c | 18 +-- > drivers/gpu/drm/gma500/oaktrail_lvds.c | 14 +- > drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c | 2 +- > drivers/gpu/drm/gma500/opregion.c | 14 +- > drivers/gpu/drm/gma500/power.c | 20 +-- > drivers/gpu/drm/gma500/psb_device.c| 16 +-- > drivers/gpu/drm/gma500/psb_drv.c | 147 ++--- > drivers/gpu/drm/gma500/psb_drv.h | 24 ++-- > drivers/gpu/drm/gma500/psb_intel_display.c | 10 +- > drivers/gpu/drm/gma500/psb_intel_lvds.c| 31 ++--- > drivers/gpu/drm/gma500/psb_intel_sdvo.c| 10 +- > drivers/gpu/drm/gma500/psb_irq.c | 26 ++-- > drivers/gpu/drm/gma500/psb_lid.c | 2 +- > 29 files changed, 261 insertions(+), 278 deletions(-) > > -- > 2.33.0 >
Re: [PATCH v4 10/14] drm/i915/ttm: hide shmem objects from TTM LRU
Am 22.09.21 um 15:34 schrieb Matthew Auld: On 21/09/2021 12:48, Christian König wrote: Am 21.09.21 um 13:01 schrieb Matthew Auld: This is probably a NAK. But ideally we need to somehow prevent TTM from seeing shmem objects when doing its LRU swap walk. Since these are EXTERNAL they are ignored anyway, but keeping them in the LRU seems pretty wasteful. Trying to use bo_pin() for this is all kinds of nasty since we need to be able to do the bo_unpin() from the unpopulate hook, but since that can be called from the BO destroy path we will likely go down in flames. An alternative is to maybe just add EXTERNAL objects to some bdev->external LRU in TTM, or just don't add them at all? Yeah, that goes into the same direction as why I want to push the LRU into the resource for some time. The problem is that the LRU is needed for multiple things. E.g. swapping, GART management, resource constrains, IOMMU teardown etc.. So for now I think that everything should be on the LRU even if it isn't valid to be there for some use case. Ok. Is it a no-go to keep TT_FLAG_EXTERNAL on say bdev->external? We could add that as a workaround, but I would rather aim for cleaning that up more thoughtfully. Regards, Christian. Regards, Christian. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Christian König --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 174aebe11264..b438ddb52764 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -800,6 +800,22 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo, return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs; } +static void i915_ttm_del_from_lru_notify(struct ttm_buffer_object *bo) +{ + struct i915_ttm_tt *i915_tt = + container_of(bo->ttm, typeof(*i915_tt), ttm); + + /* Idealy we need to prevent TTM from seeing shmem objects when doing + * its LRU swap walk. Since these are EXTERNAL they are ignored anyway, + * but keeping them in the LRU is pretty waseful. Trying to use bo_pin() + * for this is very nasty since we need to be able to do the bo_unpin() + * from the unpopulate hook, but since that can be called from the BO + * destroy path we will go down in flames. + */ + if (bo->ttm && ttm_tt_is_populated(bo->ttm) && i915_tt->is_shmem) + list_del_init(>lru); +} + static struct ttm_device_funcs i915_ttm_bo_driver = { .ttm_tt_create = i915_ttm_tt_create, .ttm_tt_populate = i915_ttm_tt_populate, @@ -810,6 +826,7 @@ static struct ttm_device_funcs i915_ttm_bo_driver = { .move = i915_ttm_move, .swap_notify = i915_ttm_swap_notify, .delete_mem_notify = i915_ttm_delete_mem_notify, + .del_from_lru_notify = i915_ttm_del_from_lru_notify, .io_mem_reserve = i915_ttm_io_mem_reserve, .io_mem_pfn = i915_ttm_io_mem_pfn, };