Re: [PATCH v3] drm/plane: Add documentation about software color conversion.
On Fri, 25 Aug 2023 16:04:18 +0200 Jocelyn Falempe wrote: > After discussions on IRC, the consensus is that the DRM drivers should > avoid software color conversion, and only advertise the formats supported > by hardware. > Update the doc accordingly so that the rule and exceptions are clear for > everyone. > > Acked-by: Simon Ser > Signed-off-by: Jocelyn Falempe > --- > drivers/gpu/drm/drm_plane.c | 24 > 1 file changed, 24 insertions(+) > > diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c > index 24e7998d1731..d05642033202 100644 > --- a/drivers/gpu/drm/drm_plane.c > +++ b/drivers/gpu/drm/drm_plane.c > @@ -140,6 +140,30 @@ > * DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have > been > * various bugs in this area with inconsistencies between the capability > * flag and per-plane properties. > + * > + * All drivers should support XRGB, even if the hardware cannot > support > + * it. This has become the de-facto standard and a lot of user-space > assume > + * it will be present. If XRGB is not natively supported, then it > + * shouldn't be the default for preferred depth or fbdev emulation. > + * > + * DRM drivers should not do software color conversion, and > + * only advertise the formats they support in hardware. This is for > + * performance reason, and to avoid multiple conversions in userspace and > + * kernel space. KMS page flips are generally expected to be very cheap > + * operations. > + * > + * But there are two exceptions only for dumb buffers: > + * * To support XRGB if it's not supported by the hardware. > + * * Any driver is free to modify its internal representation of the > format, > + * as long as it doesn't alter the visible content in any way, and > doesn't > + * modify the user-provided buffer. An example would be to drop the > + * padding component from a format to save some memory bandwidth. > + * On most hardware, VRAM read access are slow, so when doing the > software > + * conversion, the dumb buffer should be allocated in system RAM in > order to > + * have decent performance. > + * Extra care should be taken when doing software conversion with > + * DRM_CAP_DUMB_PREFER_SHADOW, there are more detailed explanations here: > + * https://lore.kernel.org/dri-devel/20230818162415.2185f8e3@eldfell/ > */ Acked-by: Pekka Paalanen Thanks, pq pgpvAcp793rZI.pgp Description: OpenPGP digital signature
Re: [RFC PATCH 04/10] drm/panel_helper: Introduce drm_panel_helper
On Fri, Aug 25, 2023 at 02:58:02PM -0700, Doug Anderson wrote: > Maxime, > > On Sun, Aug 6, 2023 at 11:41 PM Maxime Ripard wrote: > > > > Hi Doug, > > > > Thanks for working on this :) > > > > On Fri, Aug 04, 2023 at 02:06:07PM -0700, Douglas Anderson wrote: > > > The goal of this file is to contain helper functions for panel drivers > > > to use. To start off with, let's add drm_panel_helper_shutdown() for > > > use by panels that want to make sure they're powered off at > > > shutdown/remove time if they happen to be powered on. > > > > > > The main goal of introducting this function is so that panel drivers > > > don't need to track the enabled/prepared state themselves. > > > > > > Signed-off-by: Douglas Anderson > > > > It shouldn't be necessary at all: drivers should call > > drm_atomic_helper_shutdown at removal time which will disable the > > connector (which in turn should unprepare/disable its panel). > > > > If either the driver is missing drm_atomic_helper_shutdown, or if the > > connector doesn't properly disable the panel, then I would consider that > > a bug. > > Hmmm. I'm a bit hesitant here. I guess I'm less worried about the > removal time and more worried about the shutdown time. > > For removal I'd be fine with just dropping the call and saying it's > the responsibility of the driver to call drm_atomic_helper_shutdown(), > as you suggest. I'd tend to believe that removal of DRM drivers is not > used anywhere in "production" code (or at least not common) and I > think it's super hard to get it right, to unregister and unbind all > the DRM components in the right order. It depends on the kind of devices. USB devices are very likely to be removed, platform devices very unlikely, and PCIe cards somewhere in the middle :) I'm not sure the likelyhood of the device getting removed has much to do with it though, and likely or not, it's definitely something we should address and fix if an issue is to be found. > Presumably anyone trying to remove a DRM panel in a generic case > supporting lots of different hardware is used to it being a bit > broken... It's not. Most drivers might be broken, but it's totally something we support and should strive for. > Not that it's a super great situation to be in for remove() not to > work reliably, but that's how I think it is right now. > > For shutdown, however, I'm not really OK with just blindly removing > the code that tries to power off the panel. I disagree with that statement. It's not "blindly removing the code", that code is still there, in the disable hook. > Shutdown is called any time you reboot a device. That means that if a > DRM driver is _not_ calling drm_atomic_helper_shutdown() on the > panel's behalf at shutdown time then the panel won't be powered off > properly. This feels to me like something that might actually matter. It does matter. What I disagree on is that you suggest working around that brokenness in the core framework. What I'm saying is driver is broken, we should keep the core framework sane and fix it in the driver. It should be fairly easy with a coccinelle script to figure out which panels are affected, and to add that call in remove. > Panels tend to be one of those things that really care about their > power sequencing and can even get damaged (or not turn on properly > next time) if sequencing is not done properly, so just removing this > code and putting the blame on the DRM driver seems scary to me. Sure, it's bad. But there's no difference compared to the approach you suggest in that patch: you created a helper, yes, but every driver will still have to call that helper and if they don't, the panel will still be called and it's a bug. And we would have to convert everything to that new helper. It's fundamentally the same discussion than what you were opposed to above. > Sure enough, a quick survey of DRM drivers shows that many don't call > drm_atomic_helper_shutdown() at .shutdown time. A _very_ quick skim of > callers to drm_atomic_helper_shutdown(): > > * omapdrm/omap_drv.c - calls at remove, not shutdown > * arm/hdlcd_drv.c - calls at unbind, not shutdown > * arm/malidp_drv.c - calls at unbind, not shutdown > * armada/armada_drv.c - calls at unbind, not shutdown > > ...huh, actually, there are probably too many to list that don't call > it at shutdown. There are some that do, but also quite a few that > don't. I'm not sure I really want to blindly add > drm_atomic_helper_shutdown() to all those DRM driver's shutdown > callbacks... That feels like asking for someone to flame me... No one will flame you, and if they do, we'll take care of it. And yes, those are bugs, so let's fix them instead of working around them? > ...but then, what's the way forward? I think normally the panel's > shutdown() callback would happen _before_ the DRM driver's shutdown() > callback, Is there such a guarantee? > so we can't easily write logic in the panel's shutdown like "if the > DRM panel didn't shut the pan
[PATCH v2] fs: clean up usage of noop_dirty_folio
In folio_mark_dirty(), it can automatically fallback to noop_dirty_folio() if a_ops->dirty_folio is not registered. As anon_aops, dev_dax_aops and fb_deferred_io_aops becames empty, remove them too. Signed-off-by: Xueshi Hu --- Changes in v2: - make noop_dirty_folio() inline as suggested by Matthew - v1: https://lore.kernel.org/linux-mm/zoxafrz9etovu...@infradead.org/T/#m073d45909b1df03ff09f382557dc4e84d0607c49 drivers/dax/device.c| 5 - drivers/video/fbdev/core/fb_defio.c | 5 - fs/aio.c| 1 - fs/ext2/inode.c | 1 - fs/ext4/inode.c | 1 - fs/fuse/dax.c | 1 - fs/hugetlbfs/inode.c| 1 - fs/libfs.c | 5 - fs/xfs/xfs_aops.c | 1 - include/linux/pagemap.h | 1 - mm/page-writeback.c | 18 +- mm/secretmem.c | 1 - mm/shmem.c | 1 - mm/swap_state.c | 1 - 14 files changed, 5 insertions(+), 38 deletions(-) diff --git a/drivers/dax/device.c b/drivers/dax/device.c index 30665a3ff6ea..018aa9f88ec7 100644 --- a/drivers/dax/device.c +++ b/drivers/dax/device.c @@ -345,10 +345,6 @@ static unsigned long dax_get_unmapped_area(struct file *filp, return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); } -static const struct address_space_operations dev_dax_aops = { - .dirty_folio= noop_dirty_folio, -}; - static int dax_open(struct inode *inode, struct file *filp) { struct dax_device *dax_dev = inode_dax(inode); @@ -358,7 +354,6 @@ static int dax_open(struct inode *inode, struct file *filp) dev_dbg(&dev_dax->dev, "trace\n"); inode->i_mapping = __dax_inode->i_mapping; inode->i_mapping->host = __dax_inode; - inode->i_mapping->a_ops = &dev_dax_aops; filp->f_mapping = inode->i_mapping; filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping); filp->f_sb_err = file_sample_sb_err(filp); diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 274f5d0fa247..08be3592281f 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -221,10 +221,6 @@ static const struct vm_operations_struct fb_deferred_io_vm_ops = { .page_mkwrite = fb_deferred_io_mkwrite, }; -static const struct address_space_operations fb_deferred_io_aops = { - .dirty_folio= noop_dirty_folio, -}; - int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) { vma->vm_ops = &fb_deferred_io_vm_ops; @@ -307,7 +303,6 @@ void fb_deferred_io_open(struct fb_info *info, { struct fb_deferred_io *fbdefio = info->fbdefio; - file->f_mapping->a_ops = &fb_deferred_io_aops; fbdefio->open_count++; } EXPORT_SYMBOL_GPL(fb_deferred_io_open); diff --git a/fs/aio.c b/fs/aio.c index 77e33619de40..4cf386f9cb1c 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -484,7 +484,6 @@ static int aio_migrate_folio(struct address_space *mapping, struct folio *dst, #endif static const struct address_space_operations aio_ctx_aops = { - .dirty_folio= noop_dirty_folio, .migrate_folio = aio_migrate_folio, }; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 75983215c7a1..ce191bdf1c78 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -971,7 +971,6 @@ const struct address_space_operations ext2_aops = { static const struct address_space_operations ext2_dax_aops = { .writepages = ext2_dax_writepages, .direct_IO = noop_direct_IO, - .dirty_folio= noop_dirty_folio, }; /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 43775a6ca505..67c1710c01b0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3561,7 +3561,6 @@ static const struct address_space_operations ext4_da_aops = { static const struct address_space_operations ext4_dax_aops = { .writepages = ext4_dax_writepages, .direct_IO = noop_direct_IO, - .dirty_folio= noop_dirty_folio, .bmap = ext4_bmap, .swap_activate = ext4_iomap_swap_activate, }; diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c index 8e74f278a3f6..50ca767cbd5e 100644 --- a/fs/fuse/dax.c +++ b/fs/fuse/dax.c @@ -1326,7 +1326,6 @@ bool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi) static const struct address_space_operations fuse_dax_file_aops = { .writepages = fuse_dax_writepages, .direct_IO = noop_direct_IO, - .dirty_folio= noop_dirty_folio, }; static bool fuse_should_enable_dax(struct inode *inode, unsigned int flags) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 7b17ccfa039d..5404286f0c13 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -1266,7 +1266,6 @@ static void hu
Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes
On Fri, Aug 25, 2023 at 05:07:58PM +0200, Frank Oltmanns wrote: > Thank you for your feedback, Maxime! > > On 2023-08-25 at 10:13:53 +0200, Maxime Ripard wrote: > > [[PGP Signed Part:Undecided]] > > Hi, > > > > On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote: > >> I would like to make the Allwinner A64's pll-mipi to keep its rate when > >> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is > >> required, to let the A64 drive both an LCD and HDMI display at the same > >> time, because both have pll-video0 as an ancestor. > >> > >> PATCH 1 adds this functionality as a feature into the clk framework (new > >> flag: CLK_KEEP_RATE). > >> > >> Cores that use this flag, store a rate as req_rate when it or one of its > >> descendants requests a new rate. > >> > >> That rate is then restored in the clk_change_rate recursion, which walks > >> through the tree. It will reach the flagged core (e.g. pll-mipi) after > >> the parent's rate (e.g. pll-video0) has already been set to the new > >> rate. It will then call determine_rate (which requests the parent's > >> current, i.e. new, rate) to determine a rate that is close to the > >> flagged core's previous rate. Afterward it will re-calculate the rates > >> for the flagged core's subtree. > > > > I don't think it's the right way forward. It makes the core logic more > > complicated, for something that is redundant with the notifiers > > mechanism that has been the go-to for that kind of things so far. > > Yeah, that was my initial idea as well. But I couldn't get it to work. > See details below. > > Do you have an example of a clock that restores its previous rate after > the parent rate has changed? I've looked left and right, but to me it > seems that notifiers are mainly used for setting clocks into some kind > of "safe mode" prior to the rate change. Examples: > > sunxi-ng: > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273 > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60 > > but also others: > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248 > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755 > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546 There's examples for phases and parents, but not for rates afaics. We shouldn't behave any differently though. > > It's not really obvious to me why the notifiers don't work there. > > > >> This work is inspired by an out-of-tree patchset [1] [2] [3]. > >> Unfortunately, the patchset uses clk_set_rate() in a notifier callback, > >> which the following comment on clk_notifier_register() forbids: "The > >> callbacks associated with the notifier must not re-enter into the clk > >> framework by calling any top-level clk APIs." [4] Furthermore, that > >> out-of-tree patchset no longer works with the current linux-next, > >> because setting pll-mipi is now also resetting pll-video0 [5]. > > > > Is it because of the "The callbacks associated with the notifier must > > not re-enter into the clk framework by calling any top-level clk APIs." > > comment? > > I don't think that's the reason. I'm not sure I follow you there. How can we find a solution to a problem you don't know about or can't know for sure? > I'm fairly certain that the problem is, that pll-mipi tries to set the > parent rate. Maybe it should check if the parent is locked, before > determining a rate that requires the parent rate to change. 🤔 Why would the clock framework documentation mention an issue that only arises with a single clock on a single SoC? That comment in the clock framework you linked to clearly stated that you can't use a top-level clock function in a notifier, and that's because of the locking. If it's not what you're trying to fix, then I'd really like to know what issue you're trying to fix *in the framework* (so, not on the pll-mipi clock, or the A64). > Currently, it only calls clk_hw_can_set_rate_parent() which only > checks the flag, but does not check if it is really possible to change > the parent's rate. > > Regardless, please don't prematurely dismiss my proposal. It has the > advantage that it is not specific for sunxi-ng, but could be used for > other drivers as well. Just like the two solutions I provided. > Maybe there other instances of exclusive locks today where the > CLK_KEEP_RATE flag might work equally well. 🤷 If exclusive locks work equally well, why would we need CLK_KEEP_RATE? > > If so, I think the thing we should emphasize is that it's about *any > > top-level clk API*, as in clk_set_rate() or clk_set_parent(). > > > > The issue is that any consumer-facing API is taking the clk_prepare lock > > and thus we would have reentrancy. But we're a provider there, and none > > of the clk_hw_* functions are taking that lock. Neither do our own function. > > > > So we could call in that notifier our set_rate callb
[v5,0/7] Adds support for ConfigFS to VKMS!
Since Jim is busy with other work and I'm working on some things that rely on this, I've taken up the task of doing the iterations. I've addressed the comments as best I can (those replies are to each individual change) and here is the patch set to go with those. I added my own signoff to each commit, but I've left jshargo@ as the author of all the commits he wrote. I'm sure there is still more to address and the ICT tests that were writtein parallel to this may also need some additions, but I'm hoping we're in a good enough state to get this in and iterate from there soon. Since V5: Fixed some bad merge conflicts and locking behaviours as well as clarified some documentation, should be good to go now :) Since V4: Fixed up some documentation as suggested by Marius Fixed up some bad locking as suggested by Marius Small fixes here and there (most have email responses to previous chain emails) Since V3: I've added hotplug support in the latest patch. This has been reviewed some and the notes from that review are addressed here as well. Relevant/Utilizing work: === I've built a while test framework based on this as proof it functions (though I'm sure there may be lingering bugs!). You can check that out on crrev.com if you are interested and need to get started yourself (but be aware of any licensing that may differ from the kernel itself! Make sure you understand the license: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/tast-tests/LICENSE That said, you can see the changes in review on the crrev gerrit: https://chromium-review.googlesource.com/c/chromiumos/platform/tast-tests/+/469 Outro: = I really appreciate everyone's input and tolerance in getting these changes in. Jim's first patch series was this, and other than some small cleanups and documentation, taking over it is also mine. Thank you everyone :) Brandon Pollack (1): drm/vkms Add hotplug support via configfs to VKMS. Jim Shargo (6): drm/vkms: Back VKMS with DRM memory management instead of static objects drm/vkms: Support multiple DRM objects (crtcs, etc.) per VKMS device drm/vkms: Provide platform data when creating VKMS devices drm/vkms: Add ConfigFS scaffolding to VKMS drm/vkms: Support enabling ConfigFS devices drm/vkms: Add a module param to enable/disable the default device Documentation/gpu/vkms.rst| 20 +- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/vkms/Makefile | 1 + drivers/gpu/drm/vkms/vkms_composer.c | 30 +- drivers/gpu/drm/vkms/vkms_configfs.c | 721 ++ drivers/gpu/drm/vkms/vkms_crtc.c | 102 ++-- drivers/gpu/drm/vkms/vkms_drv.c | 206 +--- drivers/gpu/drm/vkms/vkms_drv.h | 182 +-- drivers/gpu/drm/vkms/vkms_output.c| 405 +-- drivers/gpu/drm/vkms/vkms_plane.c | 44 +- drivers/gpu/drm/vkms/vkms_writeback.c | 31 +- 11 files changed, 1508 insertions(+), 235 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 1/7] drm/vkms: Back VKMS with DRM memory management instead of static objects
From: Jim Shargo This is a small refactor to make ConfigFS support easier. Once we support ConfigFS, there can be multiple devices instantiated by the driver, and so moving everything into managed memory makes things much easier. This should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c| 128 +++-- drivers/gpu/drm/vkms/vkms_drv.h| 4 +- drivers/gpu/drm/vkms/vkms_output.c | 6 +- 3 files changed, 71 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index dd0af086e7fa..387c832f5dc9 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -9,10 +9,12 @@ * the GPU in DRM API tests. */ +#include #include #include #include +#include #include #include #include @@ -37,8 +39,6 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 -static struct vkms_config *default_config; - static bool enable_cursor = true; module_param_named(enable_cursor, enable_cursor, bool, 0444); MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); @@ -96,9 +96,9 @@ static int vkms_config_show(struct seq_file *m, void *data) struct drm_device *dev = entry->dev; struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); - seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback); - seq_printf(m, "cursor=%d\n", vkmsdev->config->cursor); - seq_printf(m, "overlay=%d\n", vkmsdev->config->overlay); + seq_printf(m, "writeback=%d\n", vkmsdev->config.writeback); + seq_printf(m, "cursor=%d\n", vkmsdev->config.cursor); + seq_printf(m, "overlay=%d\n", vkmsdev->config.overlay); return 0; } @@ -166,121 +166,127 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.cursor_height = 512; /* FIXME: There's a confusion between bpp and depth between this and * fbdev helpers. We have to go with 0, meaning "pick the default", -* which ix XRGB in all cases. */ +* which ix XRGB in all cases. +*/ dev->mode_config.preferred_depth = 0; dev->mode_config.helper_private = &vkms_mode_config_helpers; return vkms_output_init(vkmsdev, 0); } -static int vkms_create(struct vkms_config *config) +static int vkms_platform_probe(struct platform_device *pdev) { int ret; - struct platform_device *pdev; struct vkms_device *vkms_device; + void *grp; - pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { - ret = -ENOMEM; - goto out_unregister; - } + grp = devres_open_group(&pdev->dev, NULL, GFP_KERNEL); + if (!grp) + return -ENOMEM; vkms_device = devm_drm_dev_alloc(&pdev->dev, &vkms_driver, struct vkms_device, drm); if (IS_ERR(vkms_device)) { ret = PTR_ERR(vkms_device); - goto out_devres; + goto out_release_group; } + vkms_device->platform = pdev; - vkms_device->config = config; - config->dev = vkms_device; + vkms_device->config.cursor = enable_cursor; + vkms_device->config.writeback = enable_writeback; + vkms_device->config.overlay = enable_overlay; ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64)); - if (ret) { DRM_ERROR("Could not initialize DMA support\n"); - goto out_devres; + goto out_release_group; } ret = drm_vblank_init(&vkms_device->drm, 1); if (ret) { DRM_ERROR("Failed to vblank\n"); - goto out_devres; + goto out_release_group; } ret = vkms_modeset_init(vkms_device); - if (ret) - goto out_devres; + if (ret) { + DRM_ERROR("Unable to initialize modesetting\n"); + goto out_release_group; + } drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, ARRAY_SIZE(vkms_config_debugfs_list)); ret = drm_dev_register(&vkms_device->drm, 0); - if (ret) - goto out_devres; + if (ret) { + DRM_ERROR("Unable to register device with id %d\n", pdev->id); + goto out_release_group; + } drm_fbdev_generic_setup(&vkms_device->drm, 0); + platform_set_drvdata(pdev, vkms_device); + devres_close_group(&pdev->dev, grp); return 0; -out_devres: - devres_release_group(&pdev->dev, NULL); -out_unregister: - platform_device_unregister(pdev); +out_release_group: + devres_rele
[PATCH v5 2/7] drm/vkms: Support multiple DRM objects (crtcs, etc.) per VKMS device
From: Jim Shargo This change supports multiple CRTCs, encoders, connectors instead of one of each per device. Since ConfigFS-based devices will support multiple crtcs, it's useful to move all of the writeback/composition data from being per-"output" to being per-CRTC. Since there's still only ever one CRTC, this should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_composer.c | 30 +++ drivers/gpu/drm/vkms/vkms_crtc.c | 100 - drivers/gpu/drm/vkms/vkms_drv.c | 12 +-- drivers/gpu/drm/vkms/vkms_drv.h | 70 +-- drivers/gpu/drm/vkms/vkms_output.c| 122 ++ drivers/gpu/drm/vkms/vkms_plane.c | 38 ++-- drivers/gpu/drm/vkms/vkms_writeback.c | 31 +++ 7 files changed, 256 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index d5d4f642d367..a59eb75a21c4 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -300,13 +300,13 @@ void vkms_composer_worker(struct work_struct *work) composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; struct vkms_writeback_job *active_wb = crtc_state->active_writeback; - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); + struct vkms_crtc *vkms_crtc = drm_crtc_to_vkms_crtc(crtc); bool crc_pending, wb_pending; u64 frame_start, frame_end; u32 crc32 = 0; int ret; - spin_lock_irq(&out->composer_lock); + spin_lock_irq(&vkms_crtc->composer_lock); frame_start = crtc_state->frame_start; frame_end = crtc_state->frame_end; crc_pending = crtc_state->crc_pending; @@ -330,7 +330,7 @@ void vkms_composer_worker(struct work_struct *work) crtc_state->gamma_lut.base = NULL; } - spin_unlock_irq(&out->composer_lock); + spin_unlock_irq(&vkms_crtc->composer_lock); /* * We raced with the vblank hrtimer and previous work already computed @@ -348,10 +348,10 @@ void vkms_composer_worker(struct work_struct *work) return; if (wb_pending) { - drm_writeback_signal_completion(&out->wb_connector, 0); - spin_lock_irq(&out->composer_lock); + drm_writeback_signal_completion(&vkms_crtc->wb_connector, 0); + spin_lock_irq(&vkms_crtc->composer_lock); crtc_state->wb_pending = false; - spin_unlock_irq(&out->composer_lock); + spin_unlock_irq(&vkms_crtc->composer_lock); } /* @@ -401,30 +401,30 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } -void vkms_set_composer(struct vkms_output *out, bool enabled) +void vkms_set_composer(struct vkms_crtc *vkms_crtc, bool enabled) { bool old_enabled; if (enabled) - drm_crtc_vblank_get(&out->crtc); + drm_crtc_vblank_get(&vkms_crtc->base); - mutex_lock(&out->enabled_lock); - old_enabled = out->composer_enabled; - out->composer_enabled = enabled; + mutex_lock(&vkms_crtc->enabled_lock); + old_enabled = vkms_crtc->composer_enabled; + vkms_crtc->composer_enabled = enabled; /* the composition wasn't enabled, so unlock the lock to make sure the lock * will be balanced even if we have a failed commit */ - if (!out->composer_enabled) - mutex_unlock(&out->enabled_lock); + if (!vkms_crtc->composer_enabled) + mutex_unlock(&vkms_crtc->enabled_lock); if (old_enabled) - drm_crtc_vblank_put(&out->crtc); + drm_crtc_vblank_put(&vkms_crtc->base); } int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) { - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); + struct vkms_crtc *out = drm_crtc_to_vkms_crtc(crtc); bool enabled = false; int ret = 0; diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 3c5ebf106b66..74bbd675464b 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include "linux/mutex.h" #include #include @@ -11,17 +12,16 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) { - struct vkms_output *output = container_of(timer, struct vkms_output, - vblank_hrtimer); - struct drm_crtc *crtc = &output->crtc; + struct vkms_crtc *vkms_crtc = timer_to_vkms_crtc(timer); + struct drm_crtc *crtc = &vkms_crtc->base; struct vkms_crtc_state *state; u64 ret_overrun; bool ret, fence_cookie, composer_enabled; fence_cookie = dma_fence
[PATCH v5 3/7] drm/vkms: Provide platform data when creating VKMS devices
From: Jim Shargo This is a small refactor to make ConfigFS support easier. This should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c| 14 -- drivers/gpu/drm/vkms/vkms_drv.h| 9 ++--- drivers/gpu/drm/vkms/vkms_output.c | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 65b1e2c52106..6c94c2b5d529 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -9,6 +9,7 @@ * the GPU in DRM API tests. */ +#include "asm-generic/errno-base.h" #include #include #include @@ -171,12 +172,14 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.preferred_depth = 0; dev->mode_config.helper_private = &vkms_mode_config_helpers; - return vkms_output_init(vkmsdev, 0); + return vkmsdev->is_default ? vkms_output_init_default(vkmsdev) : +-EINVAL; } static int vkms_platform_probe(struct platform_device *pdev) { int ret; + struct vkms_device_setup *vkms_device_setup = pdev->dev.platform_data; struct vkms_device *vkms_device; void *grp; @@ -195,6 +198,7 @@ static int vkms_platform_probe(struct platform_device *pdev) vkms_device->config.cursor = enable_cursor; vkms_device->config.writeback = enable_writeback; vkms_device->config.overlay = enable_overlay; + vkms_device->is_default = vkms_device_setup->is_default; ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64)); @@ -258,6 +262,9 @@ static int __init vkms_init(void) { int ret; struct platform_device *pdev; + struct vkms_device_setup vkms_device_setup = { + .is_default = true, + }; ret = platform_driver_register(&vkms_platform_driver); if (ret) { @@ -265,8 +272,11 @@ static int __init vkms_init(void) return ret; } - pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + pdev = platform_device_register_data(NULL, DRIVER_NAME, 0, +&vkms_device_setup, +sizeof(vkms_device_setup)); if (IS_ERR(pdev)) { + DRM_ERROR("Unable to register default vkms device\n"); platform_driver_unregister(&vkms_platform_driver); return PTR_ERR(pdev); } diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 761cd809617e..4262dcffd7e1 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -132,17 +132,20 @@ struct vkms_output { struct vkms_plane planes[VKMS_MAX_PLANES]; }; -struct vkms_device; - struct vkms_config { bool writeback; bool cursor; bool overlay; }; +struct vkms_device_setup { + bool is_default; +}; + struct vkms_device { struct drm_device drm; struct platform_device *platform; + bool is_default; struct vkms_output output; struct vkms_config config; }; @@ -166,7 +169,7 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, struct drm_plane *cursor); -int vkms_output_init(struct vkms_device *vkmsdev, int index); +int vkms_output_init_default(struct vkms_device *vkmsdev); struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, enum drm_plane_type type); diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 86faf94f7408..bfc2e2362c6d 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -80,7 +80,7 @@ static struct drm_encoder *vkms_encoder_init(struct vkms_device *vkms_device) return encoder; } -int vkms_output_init(struct vkms_device *vkmsdev, int index) +int vkms_output_init_default(struct vkms_device *vkmsdev) { struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 4/7] drm/vkms: Add ConfigFS scaffolding to VKMS
From: Jim Shargo This change adds the basic scaffolding for ConfigFS, including setting up the default directories. It does not allow for the registration of configfs-backed devices, which is complex and provided in a follow-up commit. This CL includes docs about using ConfigFS with VKMS, but I'll summarize in brief here as well (assuming ConfigFS is mounted at /config/): To create a new device, you can do so via `mkdir /config/vkms/my-device`. This will create a number of directories and files automatically: /config `-- vkms `-- my-device |-- connectors |-- crtcs |-- encoders |-- planes `-- enabled You can then configure objects by mkdir'ing in each of the directories. When you're satisfied, you can `echo 1 > /config/vkms/my-device/enabled`. This will create a new device according to your configuration. For now, this will fail, but the next change will add support for it. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- Documentation/gpu/vkms.rst | 18 +- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/vkms/Makefile| 1 + drivers/gpu/drm/vkms/vkms_configfs.c | 648 +++ drivers/gpu/drm/vkms/vkms_drv.c | 56 ++- drivers/gpu/drm/vkms/vkms_drv.h | 92 +++- drivers/gpu/drm/vkms/vkms_output.c | 5 + 7 files changed, 804 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index ba04ac7c2167..c3875bf66dba 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -51,6 +51,12 @@ To disable the driver, use :: sudo modprobe -r vkms +Configuration With ConfigFS +=== + +.. kernel-doc:: drivers/gpu/drm/vkms/vkms_configfs.c + :doc: ConfigFS Support for VKMS + Testing With IGT @@ -135,22 +141,16 @@ project. Runtime Configuration - -We want to be able to reconfigure vkms instance without having to reload the -module. Use/Test-cases: +We want to be able to manipulate vkms instances without having to reload the +module. Such configuration can be added as extensions to vkms's ConfigFS +support. Use-cases: - Hotplug/hotremove connectors on the fly (to be able to test DP MST handling of compositors). -- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of - them first). - - Change output configuration: Plug/unplug screens, change EDID, allow changing the refresh rate. -The currently proposed solution is to expose vkms configuration through -configfs. All existing module options should be supported through configfs -too. - Writeback support - diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ab9ef1c20349..e39ee0e8ca06 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -284,6 +284,7 @@ config DRM_VKMS depends on DRM && MMU select DRM_KMS_HELPER select DRM_GEM_SHMEM_HELPER + select CONFIGFS_FS select CRC32 default n help diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 1b28a6a32948..6b83907ad554 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only vkms-y := \ + vkms_configfs.o \ vkms_drv.o \ vkms_plane.o \ vkms_output.o \ diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c new file mode 100644 index ..f2439629b37b --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include + +#include +#include + +#include "vkms_drv.h" + +/** + * DOC: ConfigFS Support for VKMS + * + * VKMS is instrumented with support for configuration via :doc:`ConfigFS + * <../filesystems/configfs>`. + * + * With VKMS installed, you can mount ConfigFS at ``/config/`` like so:: + * + * mkdir -p /config/ + * sudo mount -t configfs none /config + * + * This allows you to configure multiple virtual devices. Note + * that the default device which can be enabled in the module params with:: + * + * modprobe vkms default_device=1 + * + * is immutable because we cannot pre-populate ConfigFS directories with normal + * files. + * + * To set up a new device, create a new directory under the VKMS configfs + * directory:: + * + * mkdir /config/vkms/test + * + * With your device created you'll find an new directory ready to be + * configured:: + * + * /config + * `-- vkms + * `-- test + * |-- connectors + * |-- crtcs + * |-- encoders + * |-- planes + * `-- enabled + * + * Each directory you add within the connectors, crtcs, encoders, and planes + * directories will let you conf
[PATCH v5 6/7] drm/vkms: Add a module param to enable/disable the default device
From: Jim Shargo In many testing circumstances, we will want to just create a new device and test against that. If we create a default device, it can be annoying to have to manually select the new device instead of choosing the only one that exists. The param, enable_default, is defaulted to true to maintain backwards compatibility. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c | 45 ++--- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 6e7f20681890..293bebf8e8ce 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -42,17 +42,26 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 +static bool enable_default_device = true; +module_param_named(enable_default_device, enable_default_device, bool, 0444); +MODULE_PARM_DESC(enable_default_device, +"Enable/Disable creating the default device"); + static bool enable_cursor = true; module_param_named(enable_cursor, enable_cursor, bool, 0444); -MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); +MODULE_PARM_DESC(enable_cursor, +"Enable/Disable cursor support for the default device"); static bool enable_writeback = true; module_param_named(enable_writeback, enable_writeback, bool, 0444); -MODULE_PARM_DESC(enable_writeback, "Enable/Disable writeback connector support"); +MODULE_PARM_DESC( + enable_writeback, + "Enable/Disable writeback connector support for the default device"); static bool enable_overlay; module_param_named(enable_overlay, enable_overlay, bool, 0444); -MODULE_PARM_DESC(enable_overlay, "Enable/Disable overlay support"); +MODULE_PARM_DESC(enable_overlay, +"Enable/Disable overlay support for the default device"); DEFINE_DRM_GEM_FOPS(vkms_driver_fops); @@ -99,6 +108,7 @@ static int vkms_config_show(struct seq_file *m, void *data) struct drm_device *dev = entry->dev; struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); + seq_printf(m, "default_device=%d\n", enable_default_device); seq_printf(m, "writeback=%d\n", vkmsdev->config.writeback); seq_printf(m, "cursor=%d\n", vkmsdev->config.cursor); seq_printf(m, "overlay=%d\n", vkmsdev->config.overlay); @@ -297,10 +307,7 @@ void vkms_remove_device(struct vkms_device *vkms_device) static int __init vkms_init(void) { int ret; - struct platform_device *pdev; - struct vkms_device_setup vkms_device_setup = { - .configfs = NULL, - }; + struct platform_device *default_pdev = NULL; ret = platform_driver_register(&vkms_platform_driver); if (ret) { @@ -308,19 +315,27 @@ static int __init vkms_init(void) return ret; } - pdev = platform_device_register_data(NULL, DRIVER_NAME, 0, -&vkms_device_setup, -sizeof(vkms_device_setup)); - if (IS_ERR(pdev)) { - DRM_ERROR("Unable to register default vkms device\n"); - platform_driver_unregister(&vkms_platform_driver); - return PTR_ERR(pdev); + if (enable_default_device) { + struct vkms_device_setup vkms_device_setup = { + .configfs = NULL, + }; + + default_pdev = platform_device_register_data( + NULL, DRIVER_NAME, 0, &vkms_device_setup, + sizeof(vkms_device_setup)); + if (IS_ERR(default_pdev)) { + DRM_ERROR("Unable to register default vkms device\n"); + platform_driver_unregister(&vkms_platform_driver); + return PTR_ERR(default_pdev); + } } ret = vkms_init_configfs(); if (ret) { DRM_ERROR("Unable to initialize configfs\n"); - platform_device_unregister(pdev); + if (default_pdev) + platform_device_unregister(default_pdev); + platform_driver_unregister(&vkms_platform_driver); } -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 7/7] drm/vkms Add hotplug support via configfs to VKMS.
This change adds the ability to read or write a "1" or a "0" to the newly added "connected" attribute of a connector in the vkms entry in configfs. A write will trigger a call to drm_kms_helper_hotplug_event, causing a hotplug uevent. With this we can write virtualized multidisplay tests that involve hotplugging displays (eg recompositing windows when a monitor is turned off). Signed-off-by: Brandon Pollack --- Documentation/gpu/vkms.rst | 2 +- drivers/gpu/drm/vkms/vkms_configfs.c | 68 ++-- drivers/gpu/drm/vkms/vkms_drv.h | 11 + drivers/gpu/drm/vkms/vkms_output.c | 47 ++- 4 files changed, 123 insertions(+), 5 deletions(-) diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index c3875bf66dba..7f715097539c 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -145,7 +145,7 @@ We want to be able to manipulate vkms instances without having to reload the module. Such configuration can be added as extensions to vkms's ConfigFS support. Use-cases: -- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling +- Hotremove connectors on the fly (to be able to test DP MST handling of compositors). - Change output configuration: Plug/unplug screens, change EDID, allow changing diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index c28fa87c196e..fd97511c394f 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include "drm/drm_probe_helper.h" #include #include #include @@ -40,6 +41,7 @@ * `-- vkms * `-- test * |-- connectors + *`-- connected * |-- crtcs * |-- encoders * |-- planes @@ -89,6 +91,14 @@ * * echo 1 > /config/vkms/test/enabled * + * By default no display is "connected" so to connect a connector you'll also + * have to write 1 to a connectors "connected" attribute:: + * + * echo 1 > /config/vkms/test/connectors/connector/connected + * + * One can verify that this is worked using the `modetest` utility or the + * equivalent for your platform. + * * When you're done with the virtual device, you can clean up the device like * so:: * @@ -234,7 +244,58 @@ static void add_possible_encoders(struct config_group *parent, /* Connector item, e.g. /config/vkms/device/connectors/ID */ +static ssize_t connector_connected_show(struct config_item *item, char *buf) +{ + struct vkms_config_connector *connector = + item_to_config_connector(item); + struct vkms_configfs *configfs = connector_item_to_configfs(item); + bool connected = false; + + mutex_lock(&configfs->lock); + connected = connector->connected; + mutex_unlock(&configfs->lock); + + return sprintf(buf, "%d\n", connected); +} + +static ssize_t connector_connected_store(struct config_item *item, +const char *buf, size_t len) +{ + struct vkms_config_connector *connector = + item_to_config_connector(item); + struct vkms_configfs *configfs = connector_item_to_configfs(item); + int val, ret; + + ret = kstrtouint(buf, 10, &val); + if (ret) + return ret; + + if (val != 1 && val != 0) + return -EINVAL; + + mutex_lock(&configfs->lock); + connector->connected = val; + if (!connector->connector) { + pr_info("VKMS Device %s is not yet enabled, connector will be enabled on start", + configfs->device_group.cg_item.ci_name); + } + mutex_unlock(&configfs->lock); + + if (connector->connector) + drm_kms_helper_hotplug_event(connector->connector->dev); + + return len; +} + +CONFIGFS_ATTR(connector_, connected); + +static struct configfs_attribute *connector_attrs[] = { + &connector_attr_connected, + NULL, +}; + static struct config_item_type connector_type = { + .ct_attrs = connector_attrs, .ct_owner = THIS_MODULE, }; @@ -262,7 +323,7 @@ static ssize_t plane_type_show(struct config_item *item, char *buf) plane_type = plane->type; mutex_unlock(&configfs->lock); - return sprintf(buf, "%u", plane_type); + return sprintf(buf, "%u\n", plane_type); } static ssize_t plane_type_store(struct config_item *item, const char *buf, @@ -317,6 +378,7 @@ static struct config_group *connectors_group_make(struct config_group *group, &connector_type); add_possible_encoders(&connector->config_group, &connector->possible_encoders.group); + connector->connected = false; return &connector->config_group; } @@ -498,7 +560,7 @@ static ssize_t device_enabled_show(struct config_item *item, char *buf) is_enabled =
[PATCH v5 5/7] drm/vkms: Support enabling ConfigFS devices
From: Jim Shargo VKMS now supports creating and using virtual devices! In addition to the enabling logic, this commit also prevents users from adding new objects once a card is registered. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_configfs.c | 37 ++-- drivers/gpu/drm/vkms/vkms_crtc.c | 4 +- drivers/gpu/drm/vkms/vkms_drv.c | 1 + drivers/gpu/drm/vkms/vkms_drv.h | 4 +- drivers/gpu/drm/vkms/vkms_output.c | 283 +++ drivers/gpu/drm/vkms/vkms_plane.c| 10 +- 6 files changed, 283 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index f2439629b37b..c28fa87c196e 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -506,29 +506,40 @@ static ssize_t device_enabled_store(struct config_item *item, const char *buf, { struct vkms_configfs *configfs = item_to_configfs(item); struct vkms_device *device; - int value, ret; + int enabled, ret; - ret = kstrtoint(buf, 0, &value); + ret = kstrtoint(buf, 0, &enabled); if (ret) return ret; - if (value != 1) - return -EINVAL; - - mutex_lock(&configfs->lock); - - if (configfs->vkms_device) { + if (enabled == 0) { + mutex_lock(&configfs->lock); + if (configfs->vkms_device) { + vkms_remove_device(configfs->vkms_device); + configfs->vkms_device = NULL; + } mutex_unlock(&configfs->lock); + return len; } - device = vkms_add_device(configfs); - mutex_unlock(&configfs->lock); + if (enabled == 1) { + mutex_lock(&configfs->lock); + if (!configfs->vkms_device) { + device = vkms_add_device(configfs); + if (IS_ERR(device)) { + mutex_unlock(&configfs->lock); + return -PTR_ERR(device); + } + + configfs->vkms_device = device; + } + mutex_unlock(&configfs->lock); - if (IS_ERR(device)) - return -PTR_ERR(device); + return len; + } - return len; + return -EINVAL; } CONFIGFS_ATTR(device_, enabled); diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 74bbd675464b..2aa1c5246b7e 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -279,7 +279,7 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = { struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, -struct drm_plane *cursor) +struct drm_plane *cursor, const char *name) { struct drm_device *dev = &vkmsdev->drm; struct vkms_crtc *vkms_crtc; @@ -291,7 +291,7 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, vkms_crtc = &vkmsdev->output.crtcs[vkmsdev->output.num_crtcs++]; ret = drmm_crtc_init_with_planes(dev, &vkms_crtc->base, primary, cursor, -&vkms_crtc_funcs, NULL); +&vkms_crtc_funcs, name); if (ret) { DRM_ERROR("Failed to init CRTC\n"); goto out_error; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 819e880a8cf7..6e7f20681890 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -275,6 +275,7 @@ struct vkms_device *vkms_add_device(struct vkms_configfs *configfs) dev, &vkms_platform_driver.driver))) { pdev = to_platform_device(dev); max_id = max(max_id, pdev->id); + put_device(dev); } pdev = platform_device_register_data(NULL, DRIVER_NAME, max_id + 1, diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8cdd7949f661..2b9545ada9c2 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -250,13 +250,13 @@ void vkms_remove_device(struct vkms_device *vkms_device); /* CRTC */ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, -struct drm_plane *cursor); +struct drm_plane *cursor, const char *name); int vkms_output_init(struct vkms_device *vkmsdev); int vkms_output_init_default(struct vkms_device *vkmsdev); struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type); + enum drm_plane_type typ
Re: [PATCH v2 19/34] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
On Fri, 25 Aug 2023 13:29:44 -0100 Melissa Wen wrote: > On 08/22, Pekka Paalanen wrote: > > On Thu, 10 Aug 2023 15:02:59 -0100 > > Melissa Wen wrote: > > > > > The next patch adds pre-blending degamma to AMD color mgmt pipeline, but > > > pre-blending degamma caps (DPP) is currently in use to provide DRM CRTC > > > atomic degamma or implict degamma on legacy gamma. Detach degamma usage > > > regarging CRTC color properties to manage plane and CRTC color > > > correction combinations. > > > > > > Reviewed-by: Harry Wentland > > > Signed-off-by: Melissa Wen > > > --- > > > .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 59 +-- > > > 1 file changed, 41 insertions(+), 18 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > > index 68e9f2c62f2e..74eb02655d96 100644 > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > > @@ -764,20 +764,9 @@ int amdgpu_dm_update_crtc_color_mgmt(struct > > > dm_crtc_state *crtc) > > > return 0; > > > } > > > > > > -/** > > > - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC > > > plane. > > > - * @crtc: amdgpu_dm crtc state > > > - * @dc_plane_state: target DC surface > > > - * > > > - * Update the underlying dc_stream_state's input transfer function (ITF) > > > in > > > - * preparation for hardware commit. The transfer function used depends on > > > - * the preparation done on the stream for color management. > > > - * > > > - * Returns: > > > - * 0 on success. -ENOMEM if mem allocation fails. > > > - */ > > > -int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, > > > - struct dc_plane_state *dc_plane_state) > > > +static int > > > +map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, > > > + struct dc_plane_state *dc_plane_state) > > > { > > > const struct drm_color_lut *degamma_lut; > > > enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; > > > @@ -800,8 +789,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct > > > dm_crtc_state *crtc, > > >°amma_size); > > > ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); > > > > > > - dc_plane_state->in_transfer_func->type = > > > - TF_TYPE_DISTRIBUTED_POINTS; > > > + dc_plane_state->in_transfer_func->type = > > > TF_TYPE_DISTRIBUTED_POINTS; > > > > > > /* > > >* This case isn't fully correct, but also fairly > > > @@ -837,7 +825,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct > > > dm_crtc_state *crtc, > > > degamma_lut, degamma_size); > > > if (r) > > > return r; > > > - } else if (crtc->cm_is_degamma_srgb) { > > > + } else { > > > /* > > >* For legacy gamma support we need the regamma input > > >* in linear space. Assume that the input is sRGB. > > > @@ -847,8 +835,43 @@ int amdgpu_dm_update_plane_color_mgmt(struct > > > dm_crtc_state *crtc, > > > > > > if (tf != TRANSFER_FUNCTION_SRGB && > > > !mod_color_calculate_degamma_params(NULL, > > > - dc_plane_state->in_transfer_func, NULL, false)) > > > + > > > dc_plane_state->in_transfer_func, > > > + NULL, false)) > > > return -ENOMEM; > > > + } > > > + > > > + return 0; > > > +} > > > + > > > +/** > > > + * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC > > > plane. > > > + * @crtc: amdgpu_dm crtc state > > > + * @dc_plane_state: target DC surface > > > + * > > > + * Update the underlying dc_stream_state's input transfer function (ITF) > > > in > > > + * preparation for hardware commit. The transfer function used depends on > > > + * the preparation done on the stream for color management. > > > + * > > > + * Returns: > > > + * 0 on success. -ENOMEM if mem allocation fails. > > > + */ > > > +int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, > > > + struct dc_plane_state *dc_plane_state) > > > +{ > > > + bool has_crtc_cm_degamma; > > > + int ret; > > > + > > > + has_crtc_cm_degamma = (crtc->cm_has_degamma || > > > crtc->cm_is_degamma_srgb); > > > + if (has_crtc_cm_degamma){ > > > + /* AMD HW doesn't have post-blending degamma caps. When DRM > > > + * CRTC atomic degamma is set, we maps it to DPP degamma block > > > + * (pre-blending) or, on legacy gamma, we use DPP degamma to > > > + * linearize (implicit degamma) from sRGB/BT709 according to > > > + * the input space. > > > > Uhh, you can't just move degamma before blending if KMS userspace > > wants it after blending. That would be inc
[PATCH v5 0/7] Adds support for ConfigFS to VKMS!
Since Jim is busy with other work and I'm working on some things that rely on this, I've taken up the task of doing the iterations. I've addressed the comments as best I can (those replies are to each individual change) and here is the patch set to go with those. I added my own signoff to each commit, but I've left jshargo@ as the author of all the commits he wrote. I'm sure there is still more to address and the ICT tests that were writtein parallel to this may also need some additions, but I'm hoping we're in a good enough state to get this in and iterate from there soon. Since V5: Fixed some bad merge conflicts and locking behaviours as well as clarified some documentation, should be good to go now : Since V4: Fixed up some documentation as suggested by Marius Fixed up some bad locking as suggested by Marius Small fixes here and there (most have email responses to previous chain emails) Since V3: I've added hotplug support in the latest patch. This has been reviewed some and the notes from that review are addressed here as well. Relevant/Utilizing work: === I've built a while test framework based on this as proof it functions (though I'm sure there may be lingering bugs!). You can check that out on crrev.com if you are interested and need to get started yourself (but be aware of any licensing that may differ from the kernel itself! Make sure you understand the license: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/tast-tests/LICENSE That said, you can see the changes in review on the crrev gerrit: https://chromium-review.googlesource.com/c/chromiumos/platform/tast-tests/+/469 Outro: = I really appreciate everyone's input and tolerance in getting these changes in. Jim's first patch series was this, and other than some small cleanups and documentation, taking over it is also mine. Thank you everyone :) Brandon Pollack (1): drm/vkms Add hotplug support via configfs to VKMS. Jim Shargo (6): drm/vkms: Back VKMS with DRM memory management instead of static objects drm/vkms: Support multiple DRM objects (crtcs, etc.) per VKMS device drm/vkms: Provide platform data when creating VKMS devices drm/vkms: Add ConfigFS scaffolding to VKMS drm/vkms: Support enabling ConfigFS devices drm/vkms: Add a module param to enable/disable the default device Documentation/gpu/vkms.rst| 20 +- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/vkms/Makefile | 1 + drivers/gpu/drm/vkms/vkms_composer.c | 30 +- drivers/gpu/drm/vkms/vkms_configfs.c | 721 ++ drivers/gpu/drm/vkms/vkms_crtc.c | 102 ++-- drivers/gpu/drm/vkms/vkms_drv.c | 206 +--- drivers/gpu/drm/vkms/vkms_drv.h | 182 +-- drivers/gpu/drm/vkms/vkms_output.c| 405 +-- drivers/gpu/drm/vkms/vkms_plane.c | 44 +- drivers/gpu/drm/vkms/vkms_writeback.c | 31 +- 11 files changed, 1508 insertions(+), 235 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 1/7] drm/vkms: Back VKMS with DRM memory management instead of static objects
From: Jim Shargo This is a small refactor to make ConfigFS support easier. Once we support ConfigFS, there can be multiple devices instantiated by the driver, and so moving everything into managed memory makes things much easier. This should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c| 128 +++-- drivers/gpu/drm/vkms/vkms_drv.h| 4 +- drivers/gpu/drm/vkms/vkms_output.c | 6 +- 3 files changed, 71 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index dd0af086e7fa..387c832f5dc9 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -9,10 +9,12 @@ * the GPU in DRM API tests. */ +#include #include #include #include +#include #include #include #include @@ -37,8 +39,6 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 -static struct vkms_config *default_config; - static bool enable_cursor = true; module_param_named(enable_cursor, enable_cursor, bool, 0444); MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); @@ -96,9 +96,9 @@ static int vkms_config_show(struct seq_file *m, void *data) struct drm_device *dev = entry->dev; struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); - seq_printf(m, "writeback=%d\n", vkmsdev->config->writeback); - seq_printf(m, "cursor=%d\n", vkmsdev->config->cursor); - seq_printf(m, "overlay=%d\n", vkmsdev->config->overlay); + seq_printf(m, "writeback=%d\n", vkmsdev->config.writeback); + seq_printf(m, "cursor=%d\n", vkmsdev->config.cursor); + seq_printf(m, "overlay=%d\n", vkmsdev->config.overlay); return 0; } @@ -166,121 +166,127 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.cursor_height = 512; /* FIXME: There's a confusion between bpp and depth between this and * fbdev helpers. We have to go with 0, meaning "pick the default", -* which ix XRGB in all cases. */ +* which ix XRGB in all cases. +*/ dev->mode_config.preferred_depth = 0; dev->mode_config.helper_private = &vkms_mode_config_helpers; return vkms_output_init(vkmsdev, 0); } -static int vkms_create(struct vkms_config *config) +static int vkms_platform_probe(struct platform_device *pdev) { int ret; - struct platform_device *pdev; struct vkms_device *vkms_device; + void *grp; - pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { - ret = -ENOMEM; - goto out_unregister; - } + grp = devres_open_group(&pdev->dev, NULL, GFP_KERNEL); + if (!grp) + return -ENOMEM; vkms_device = devm_drm_dev_alloc(&pdev->dev, &vkms_driver, struct vkms_device, drm); if (IS_ERR(vkms_device)) { ret = PTR_ERR(vkms_device); - goto out_devres; + goto out_release_group; } + vkms_device->platform = pdev; - vkms_device->config = config; - config->dev = vkms_device; + vkms_device->config.cursor = enable_cursor; + vkms_device->config.writeback = enable_writeback; + vkms_device->config.overlay = enable_overlay; ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64)); - if (ret) { DRM_ERROR("Could not initialize DMA support\n"); - goto out_devres; + goto out_release_group; } ret = drm_vblank_init(&vkms_device->drm, 1); if (ret) { DRM_ERROR("Failed to vblank\n"); - goto out_devres; + goto out_release_group; } ret = vkms_modeset_init(vkms_device); - if (ret) - goto out_devres; + if (ret) { + DRM_ERROR("Unable to initialize modesetting\n"); + goto out_release_group; + } drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, ARRAY_SIZE(vkms_config_debugfs_list)); ret = drm_dev_register(&vkms_device->drm, 0); - if (ret) - goto out_devres; + if (ret) { + DRM_ERROR("Unable to register device with id %d\n", pdev->id); + goto out_release_group; + } drm_fbdev_generic_setup(&vkms_device->drm, 0); + platform_set_drvdata(pdev, vkms_device); + devres_close_group(&pdev->dev, grp); return 0; -out_devres: - devres_release_group(&pdev->dev, NULL); -out_unregister: - platform_device_unregister(pdev); +out_release_group: + devres_rele
[PATCH v5 2/7] drm/vkms: Support multiple DRM objects (crtcs, etc.) per VKMS device
From: Jim Shargo This change supports multiple CRTCs, encoders, connectors instead of one of each per device. Since ConfigFS-based devices will support multiple crtcs, it's useful to move all of the writeback/composition data from being per-"output" to being per-CRTC. Since there's still only ever one CRTC, this should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_composer.c | 30 +++ drivers/gpu/drm/vkms/vkms_crtc.c | 100 - drivers/gpu/drm/vkms/vkms_drv.c | 12 +-- drivers/gpu/drm/vkms/vkms_drv.h | 70 +-- drivers/gpu/drm/vkms/vkms_output.c| 122 ++ drivers/gpu/drm/vkms/vkms_plane.c | 38 ++-- drivers/gpu/drm/vkms/vkms_writeback.c | 31 +++ 7 files changed, 256 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index d5d4f642d367..a59eb75a21c4 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -300,13 +300,13 @@ void vkms_composer_worker(struct work_struct *work) composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; struct vkms_writeback_job *active_wb = crtc_state->active_writeback; - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); + struct vkms_crtc *vkms_crtc = drm_crtc_to_vkms_crtc(crtc); bool crc_pending, wb_pending; u64 frame_start, frame_end; u32 crc32 = 0; int ret; - spin_lock_irq(&out->composer_lock); + spin_lock_irq(&vkms_crtc->composer_lock); frame_start = crtc_state->frame_start; frame_end = crtc_state->frame_end; crc_pending = crtc_state->crc_pending; @@ -330,7 +330,7 @@ void vkms_composer_worker(struct work_struct *work) crtc_state->gamma_lut.base = NULL; } - spin_unlock_irq(&out->composer_lock); + spin_unlock_irq(&vkms_crtc->composer_lock); /* * We raced with the vblank hrtimer and previous work already computed @@ -348,10 +348,10 @@ void vkms_composer_worker(struct work_struct *work) return; if (wb_pending) { - drm_writeback_signal_completion(&out->wb_connector, 0); - spin_lock_irq(&out->composer_lock); + drm_writeback_signal_completion(&vkms_crtc->wb_connector, 0); + spin_lock_irq(&vkms_crtc->composer_lock); crtc_state->wb_pending = false; - spin_unlock_irq(&out->composer_lock); + spin_unlock_irq(&vkms_crtc->composer_lock); } /* @@ -401,30 +401,30 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } -void vkms_set_composer(struct vkms_output *out, bool enabled) +void vkms_set_composer(struct vkms_crtc *vkms_crtc, bool enabled) { bool old_enabled; if (enabled) - drm_crtc_vblank_get(&out->crtc); + drm_crtc_vblank_get(&vkms_crtc->base); - mutex_lock(&out->enabled_lock); - old_enabled = out->composer_enabled; - out->composer_enabled = enabled; + mutex_lock(&vkms_crtc->enabled_lock); + old_enabled = vkms_crtc->composer_enabled; + vkms_crtc->composer_enabled = enabled; /* the composition wasn't enabled, so unlock the lock to make sure the lock * will be balanced even if we have a failed commit */ - if (!out->composer_enabled) - mutex_unlock(&out->enabled_lock); + if (!vkms_crtc->composer_enabled) + mutex_unlock(&vkms_crtc->enabled_lock); if (old_enabled) - drm_crtc_vblank_put(&out->crtc); + drm_crtc_vblank_put(&vkms_crtc->base); } int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) { - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); + struct vkms_crtc *out = drm_crtc_to_vkms_crtc(crtc); bool enabled = false; int ret = 0; diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 3c5ebf106b66..74bbd675464b 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include "linux/mutex.h" #include #include @@ -11,17 +12,16 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) { - struct vkms_output *output = container_of(timer, struct vkms_output, - vblank_hrtimer); - struct drm_crtc *crtc = &output->crtc; + struct vkms_crtc *vkms_crtc = timer_to_vkms_crtc(timer); + struct drm_crtc *crtc = &vkms_crtc->base; struct vkms_crtc_state *state; u64 ret_overrun; bool ret, fence_cookie, composer_enabled; fence_cookie = dma_fence
[PATCH v5 3/7] drm/vkms: Provide platform data when creating VKMS devices
From: Jim Shargo This is a small refactor to make ConfigFS support easier. This should be a no-op refactor. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c| 14 -- drivers/gpu/drm/vkms/vkms_drv.h| 9 ++--- drivers/gpu/drm/vkms/vkms_output.c | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 65b1e2c52106..6c94c2b5d529 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -9,6 +9,7 @@ * the GPU in DRM API tests. */ +#include "asm-generic/errno-base.h" #include #include #include @@ -171,12 +172,14 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.preferred_depth = 0; dev->mode_config.helper_private = &vkms_mode_config_helpers; - return vkms_output_init(vkmsdev, 0); + return vkmsdev->is_default ? vkms_output_init_default(vkmsdev) : +-EINVAL; } static int vkms_platform_probe(struct platform_device *pdev) { int ret; + struct vkms_device_setup *vkms_device_setup = pdev->dev.platform_data; struct vkms_device *vkms_device; void *grp; @@ -195,6 +198,7 @@ static int vkms_platform_probe(struct platform_device *pdev) vkms_device->config.cursor = enable_cursor; vkms_device->config.writeback = enable_writeback; vkms_device->config.overlay = enable_overlay; + vkms_device->is_default = vkms_device_setup->is_default; ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64)); @@ -258,6 +262,9 @@ static int __init vkms_init(void) { int ret; struct platform_device *pdev; + struct vkms_device_setup vkms_device_setup = { + .is_default = true, + }; ret = platform_driver_register(&vkms_platform_driver); if (ret) { @@ -265,8 +272,11 @@ static int __init vkms_init(void) return ret; } - pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + pdev = platform_device_register_data(NULL, DRIVER_NAME, 0, +&vkms_device_setup, +sizeof(vkms_device_setup)); if (IS_ERR(pdev)) { + DRM_ERROR("Unable to register default vkms device\n"); platform_driver_unregister(&vkms_platform_driver); return PTR_ERR(pdev); } diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 761cd809617e..4262dcffd7e1 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -132,17 +132,20 @@ struct vkms_output { struct vkms_plane planes[VKMS_MAX_PLANES]; }; -struct vkms_device; - struct vkms_config { bool writeback; bool cursor; bool overlay; }; +struct vkms_device_setup { + bool is_default; +}; + struct vkms_device { struct drm_device drm; struct platform_device *platform; + bool is_default; struct vkms_output output; struct vkms_config config; }; @@ -166,7 +169,7 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, struct drm_plane *cursor); -int vkms_output_init(struct vkms_device *vkmsdev, int index); +int vkms_output_init_default(struct vkms_device *vkmsdev); struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, enum drm_plane_type type); diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 86faf94f7408..bfc2e2362c6d 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -80,7 +80,7 @@ static struct drm_encoder *vkms_encoder_init(struct vkms_device *vkms_device) return encoder; } -int vkms_output_init(struct vkms_device *vkmsdev, int index) +int vkms_output_init_default(struct vkms_device *vkmsdev) { struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 6/7] drm/vkms: Add a module param to enable/disable the default device
From: Jim Shargo In many testing circumstances, we will want to just create a new device and test against that. If we create a default device, it can be annoying to have to manually select the new device instead of choosing the only one that exists. The param, enable_default, is defaulted to true to maintain backwards compatibility. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_drv.c | 45 ++--- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 6e7f20681890..293bebf8e8ce 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -42,17 +42,26 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 +static bool enable_default_device = true; +module_param_named(enable_default_device, enable_default_device, bool, 0444); +MODULE_PARM_DESC(enable_default_device, +"Enable/Disable creating the default device"); + static bool enable_cursor = true; module_param_named(enable_cursor, enable_cursor, bool, 0444); -MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support"); +MODULE_PARM_DESC(enable_cursor, +"Enable/Disable cursor support for the default device"); static bool enable_writeback = true; module_param_named(enable_writeback, enable_writeback, bool, 0444); -MODULE_PARM_DESC(enable_writeback, "Enable/Disable writeback connector support"); +MODULE_PARM_DESC( + enable_writeback, + "Enable/Disable writeback connector support for the default device"); static bool enable_overlay; module_param_named(enable_overlay, enable_overlay, bool, 0444); -MODULE_PARM_DESC(enable_overlay, "Enable/Disable overlay support"); +MODULE_PARM_DESC(enable_overlay, +"Enable/Disable overlay support for the default device"); DEFINE_DRM_GEM_FOPS(vkms_driver_fops); @@ -99,6 +108,7 @@ static int vkms_config_show(struct seq_file *m, void *data) struct drm_device *dev = entry->dev; struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); + seq_printf(m, "default_device=%d\n", enable_default_device); seq_printf(m, "writeback=%d\n", vkmsdev->config.writeback); seq_printf(m, "cursor=%d\n", vkmsdev->config.cursor); seq_printf(m, "overlay=%d\n", vkmsdev->config.overlay); @@ -297,10 +307,7 @@ void vkms_remove_device(struct vkms_device *vkms_device) static int __init vkms_init(void) { int ret; - struct platform_device *pdev; - struct vkms_device_setup vkms_device_setup = { - .configfs = NULL, - }; + struct platform_device *default_pdev = NULL; ret = platform_driver_register(&vkms_platform_driver); if (ret) { @@ -308,19 +315,27 @@ static int __init vkms_init(void) return ret; } - pdev = platform_device_register_data(NULL, DRIVER_NAME, 0, -&vkms_device_setup, -sizeof(vkms_device_setup)); - if (IS_ERR(pdev)) { - DRM_ERROR("Unable to register default vkms device\n"); - platform_driver_unregister(&vkms_platform_driver); - return PTR_ERR(pdev); + if (enable_default_device) { + struct vkms_device_setup vkms_device_setup = { + .configfs = NULL, + }; + + default_pdev = platform_device_register_data( + NULL, DRIVER_NAME, 0, &vkms_device_setup, + sizeof(vkms_device_setup)); + if (IS_ERR(default_pdev)) { + DRM_ERROR("Unable to register default vkms device\n"); + platform_driver_unregister(&vkms_platform_driver); + return PTR_ERR(default_pdev); + } } ret = vkms_init_configfs(); if (ret) { DRM_ERROR("Unable to initialize configfs\n"); - platform_device_unregister(pdev); + if (default_pdev) + platform_device_unregister(default_pdev); + platform_driver_unregister(&vkms_platform_driver); } -- 2.42.0.rc1.204.g551eb34607-goog
[PATCH v5 5/7] drm/vkms: Support enabling ConfigFS devices
From: Jim Shargo VKMS now supports creating and using virtual devices! In addition to the enabling logic, this commit also prevents users from adding new objects once a card is registered. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- drivers/gpu/drm/vkms/vkms_configfs.c | 37 ++-- drivers/gpu/drm/vkms/vkms_crtc.c | 4 +- drivers/gpu/drm/vkms/vkms_drv.c | 1 + drivers/gpu/drm/vkms/vkms_drv.h | 4 +- drivers/gpu/drm/vkms/vkms_output.c | 283 +++ drivers/gpu/drm/vkms/vkms_plane.c| 10 +- 6 files changed, 283 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index f2439629b37b..c28fa87c196e 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -506,29 +506,40 @@ static ssize_t device_enabled_store(struct config_item *item, const char *buf, { struct vkms_configfs *configfs = item_to_configfs(item); struct vkms_device *device; - int value, ret; + int enabled, ret; - ret = kstrtoint(buf, 0, &value); + ret = kstrtoint(buf, 0, &enabled); if (ret) return ret; - if (value != 1) - return -EINVAL; - - mutex_lock(&configfs->lock); - - if (configfs->vkms_device) { + if (enabled == 0) { + mutex_lock(&configfs->lock); + if (configfs->vkms_device) { + vkms_remove_device(configfs->vkms_device); + configfs->vkms_device = NULL; + } mutex_unlock(&configfs->lock); + return len; } - device = vkms_add_device(configfs); - mutex_unlock(&configfs->lock); + if (enabled == 1) { + mutex_lock(&configfs->lock); + if (!configfs->vkms_device) { + device = vkms_add_device(configfs); + if (IS_ERR(device)) { + mutex_unlock(&configfs->lock); + return -PTR_ERR(device); + } + + configfs->vkms_device = device; + } + mutex_unlock(&configfs->lock); - if (IS_ERR(device)) - return -PTR_ERR(device); + return len; + } - return len; + return -EINVAL; } CONFIGFS_ATTR(device_, enabled); diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 74bbd675464b..2aa1c5246b7e 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -279,7 +279,7 @@ static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = { struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, -struct drm_plane *cursor) +struct drm_plane *cursor, const char *name) { struct drm_device *dev = &vkmsdev->drm; struct vkms_crtc *vkms_crtc; @@ -291,7 +291,7 @@ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, vkms_crtc = &vkmsdev->output.crtcs[vkmsdev->output.num_crtcs++]; ret = drmm_crtc_init_with_planes(dev, &vkms_crtc->base, primary, cursor, -&vkms_crtc_funcs, NULL); +&vkms_crtc_funcs, name); if (ret) { DRM_ERROR("Failed to init CRTC\n"); goto out_error; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 819e880a8cf7..6e7f20681890 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -275,6 +275,7 @@ struct vkms_device *vkms_add_device(struct vkms_configfs *configfs) dev, &vkms_platform_driver.driver))) { pdev = to_platform_device(dev); max_id = max(max_id, pdev->id); + put_device(dev); } pdev = platform_device_register_data(NULL, DRIVER_NAME, max_id + 1, diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8cdd7949f661..2b9545ada9c2 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -250,13 +250,13 @@ void vkms_remove_device(struct vkms_device *vkms_device); /* CRTC */ struct vkms_crtc *vkms_crtc_init(struct vkms_device *vkmsdev, struct drm_plane *primary, -struct drm_plane *cursor); +struct drm_plane *cursor, const char *name); int vkms_output_init(struct vkms_device *vkmsdev); int vkms_output_init_default(struct vkms_device *vkmsdev); struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type); + enum drm_plane_type typ
[PATCH v5 4/7] drm/vkms: Add ConfigFS scaffolding to VKMS
From: Jim Shargo This change adds the basic scaffolding for ConfigFS, including setting up the default directories. It does not allow for the registration of configfs-backed devices, which is complex and provided in a follow-up commit. This CL includes docs about using ConfigFS with VKMS, but I'll summarize in brief here as well (assuming ConfigFS is mounted at /config/): To create a new device, you can do so via `mkdir /config/vkms/my-device`. This will create a number of directories and files automatically: /config `-- vkms `-- my-device |-- connectors |-- crtcs |-- encoders |-- planes `-- enabled You can then configure objects by mkdir'ing in each of the directories. When you're satisfied, you can `echo 1 > /config/vkms/my-device/enabled`. This will create a new device according to your configuration. For now, this will fail, but the next change will add support for it. Signed-off-by: Jim Shargo Signed-off-by: Brandon Pollack --- Documentation/gpu/vkms.rst | 18 +- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/vkms/Makefile| 1 + drivers/gpu/drm/vkms/vkms_configfs.c | 648 +++ drivers/gpu/drm/vkms/vkms_drv.c | 56 ++- drivers/gpu/drm/vkms/vkms_drv.h | 92 +++- drivers/gpu/drm/vkms/vkms_output.c | 5 + 7 files changed, 804 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index ba04ac7c2167..c3875bf66dba 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -51,6 +51,12 @@ To disable the driver, use :: sudo modprobe -r vkms +Configuration With ConfigFS +=== + +.. kernel-doc:: drivers/gpu/drm/vkms/vkms_configfs.c + :doc: ConfigFS Support for VKMS + Testing With IGT @@ -135,22 +141,16 @@ project. Runtime Configuration - -We want to be able to reconfigure vkms instance without having to reload the -module. Use/Test-cases: +We want to be able to manipulate vkms instances without having to reload the +module. Such configuration can be added as extensions to vkms's ConfigFS +support. Use-cases: - Hotplug/hotremove connectors on the fly (to be able to test DP MST handling of compositors). -- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of - them first). - - Change output configuration: Plug/unplug screens, change EDID, allow changing the refresh rate. -The currently proposed solution is to expose vkms configuration through -configfs. All existing module options should be supported through configfs -too. - Writeback support - diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ab9ef1c20349..e39ee0e8ca06 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -284,6 +284,7 @@ config DRM_VKMS depends on DRM && MMU select DRM_KMS_HELPER select DRM_GEM_SHMEM_HELPER + select CONFIGFS_FS select CRC32 default n help diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 1b28a6a32948..6b83907ad554 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only vkms-y := \ + vkms_configfs.o \ vkms_drv.o \ vkms_plane.o \ vkms_output.o \ diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c new file mode 100644 index ..f2439629b37b --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include + +#include +#include + +#include "vkms_drv.h" + +/** + * DOC: ConfigFS Support for VKMS + * + * VKMS is instrumented with support for configuration via :doc:`ConfigFS + * <../filesystems/configfs>`. + * + * With VKMS installed, you can mount ConfigFS at ``/config/`` like so:: + * + * mkdir -p /config/ + * sudo mount -t configfs none /config + * + * This allows you to configure multiple virtual devices. Note + * that the default device which can be enabled in the module params with:: + * + * modprobe vkms default_device=1 + * + * is immutable because we cannot pre-populate ConfigFS directories with normal + * files. + * + * To set up a new device, create a new directory under the VKMS configfs + * directory:: + * + * mkdir /config/vkms/test + * + * With your device created you'll find an new directory ready to be + * configured:: + * + * /config + * `-- vkms + * `-- test + * |-- connectors + * |-- crtcs + * |-- encoders + * |-- planes + * `-- enabled + * + * Each directory you add within the connectors, crtcs, encoders, and planes + * directories will let you conf
[PATCH v5 7/7] drm/vkms Add hotplug support via configfs to VKMS.
This change adds the ability to read or write a "1" or a "0" to the newly added "connected" attribute of a connector in the vkms entry in configfs. A write will trigger a call to drm_kms_helper_hotplug_event, causing a hotplug uevent. With this we can write virtualized multidisplay tests that involve hotplugging displays (eg recompositing windows when a monitor is turned off). Signed-off-by: Brandon Pollack --- Documentation/gpu/vkms.rst | 2 +- drivers/gpu/drm/vkms/vkms_configfs.c | 68 ++-- drivers/gpu/drm/vkms/vkms_drv.h | 11 + drivers/gpu/drm/vkms/vkms_output.c | 47 ++- 4 files changed, 123 insertions(+), 5 deletions(-) diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index c3875bf66dba..7f715097539c 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -145,7 +145,7 @@ We want to be able to manipulate vkms instances without having to reload the module. Such configuration can be added as extensions to vkms's ConfigFS support. Use-cases: -- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling +- Hotremove connectors on the fly (to be able to test DP MST handling of compositors). - Change output configuration: Plug/unplug screens, change EDID, allow changing diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c b/drivers/gpu/drm/vkms/vkms_configfs.c index c28fa87c196e..fd97511c394f 100644 --- a/drivers/gpu/drm/vkms/vkms_configfs.c +++ b/drivers/gpu/drm/vkms/vkms_configfs.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include "drm/drm_probe_helper.h" #include #include #include @@ -40,6 +41,7 @@ * `-- vkms * `-- test * |-- connectors + *`-- connected * |-- crtcs * |-- encoders * |-- planes @@ -89,6 +91,14 @@ * * echo 1 > /config/vkms/test/enabled * + * By default no display is "connected" so to connect a connector you'll also + * have to write 1 to a connectors "connected" attribute:: + * + * echo 1 > /config/vkms/test/connectors/connector/connected + * + * One can verify that this is worked using the `modetest` utility or the + * equivalent for your platform. + * * When you're done with the virtual device, you can clean up the device like * so:: * @@ -234,7 +244,58 @@ static void add_possible_encoders(struct config_group *parent, /* Connector item, e.g. /config/vkms/device/connectors/ID */ +static ssize_t connector_connected_show(struct config_item *item, char *buf) +{ + struct vkms_config_connector *connector = + item_to_config_connector(item); + struct vkms_configfs *configfs = connector_item_to_configfs(item); + bool connected = false; + + mutex_lock(&configfs->lock); + connected = connector->connected; + mutex_unlock(&configfs->lock); + + return sprintf(buf, "%d\n", connected); +} + +static ssize_t connector_connected_store(struct config_item *item, +const char *buf, size_t len) +{ + struct vkms_config_connector *connector = + item_to_config_connector(item); + struct vkms_configfs *configfs = connector_item_to_configfs(item); + int val, ret; + + ret = kstrtouint(buf, 10, &val); + if (ret) + return ret; + + if (val != 1 && val != 0) + return -EINVAL; + + mutex_lock(&configfs->lock); + connector->connected = val; + if (!connector->connector) { + pr_info("VKMS Device %s is not yet enabled, connector will be enabled on start", + configfs->device_group.cg_item.ci_name); + } + mutex_unlock(&configfs->lock); + + if (connector->connector) + drm_kms_helper_hotplug_event(connector->connector->dev); + + return len; +} + +CONFIGFS_ATTR(connector_, connected); + +static struct configfs_attribute *connector_attrs[] = { + &connector_attr_connected, + NULL, +}; + static struct config_item_type connector_type = { + .ct_attrs = connector_attrs, .ct_owner = THIS_MODULE, }; @@ -262,7 +323,7 @@ static ssize_t plane_type_show(struct config_item *item, char *buf) plane_type = plane->type; mutex_unlock(&configfs->lock); - return sprintf(buf, "%u", plane_type); + return sprintf(buf, "%u\n", plane_type); } static ssize_t plane_type_store(struct config_item *item, const char *buf, @@ -317,6 +378,7 @@ static struct config_group *connectors_group_make(struct config_group *group, &connector_type); add_possible_encoders(&connector->config_group, &connector->possible_encoders.group); + connector->connected = false; return &connector->config_group; } @@ -498,7 +560,7 @@ static ssize_t device_enabled_show(struct config_item *item, char *buf) is_enabled =
Re: [PATCH v2 31/34] drm/amd/display: set stream gamut remap matrix to MPC for DCN301
On Fri, 25 Aug 2023 13:37:08 -0100 Melissa Wen wrote: > On 08/22, Pekka Paalanen wrote: > > On Thu, 10 Aug 2023 15:03:11 -0100 > > Melissa Wen wrote: > > > > > dc->caps.color.mpc.gamut_remap says there is a post-blending color block > > > for gamut remap matrix for DCN3 HW family and newer versions. However, > > > those drivers still follow DCN10 programming that remap stream > > > gamut_remap_matrix to DPP (pre-blending). > > > > That's ok only as long as CRTC degamma is pass-through. Blending itself > > is a linear operation, so it doesn't matter if a matrix is applied to > > the blending result or to all blending inputs. But you cannot move a > > matrix operation to the other side of a non-linear operation, and you > > cannot move a non-linear operation across blending. > > Oh, I'm not moving it, what I'm doing here is the opposite and fixing > it. This patch puts each pre- and post-blending CTM in their right > place, since we have the HW caps for it on DCN3+... Or are you just > pointing out the implementation mistake on old driver versions? It's just the old mistake. I hope no-one complains, forcing you to revert this fix as a regression. Thanks, pq > > > To enable pre-blending and post-blending gamut_remap matrix supports at > > > the same time, set stream gamut_remap to MPC and plane gamut_remap to > > > DPP for DCN301 that support both. > > > > > > It was tested using IGT KMS color tests for DRM CRTC CTM property and it > > > preserves test results. > > > > > > Signed-off-by: Melissa Wen > > > --- > > > .../drm/amd/display/dc/dcn30/dcn30_hwseq.c| 37 +++ > > > .../drm/amd/display/dc/dcn30/dcn30_hwseq.h| 3 ++ > > > .../drm/amd/display/dc/dcn301/dcn301_init.c | 2 +- > > > 3 files changed, 41 insertions(+), 1 deletion(-) pgp_Lo7dCqd2A.pgp Description: OpenPGP digital signature
Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes
On Sat, Aug 26, 2023 at 11:12:16AM +0200, Frank Oltmanns wrote: > > On 2023-08-25 at 17:07:58 +0200, Frank Oltmanns wrote: > > Thank you for your feedback, Maxime! > > > > On 2023-08-25 at 10:13:53 +0200, Maxime Ripard wrote: > >> [[PGP Signed Part:Undecided]] > >> Hi, > >> > >> On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote: > >>> I would like to make the Allwinner A64's pll-mipi to keep its rate when > >>> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is > >>> required, to let the A64 drive both an LCD and HDMI display at the same > >>> time, because both have pll-video0 as an ancestor. > >>> > >>> PATCH 1 adds this functionality as a feature into the clk framework (new > >>> flag: CLK_KEEP_RATE). > >>> > >>> Cores that use this flag, store a rate as req_rate when it or one of its > >>> descendants requests a new rate. > >>> > >>> That rate is then restored in the clk_change_rate recursion, which walks > >>> through the tree. It will reach the flagged core (e.g. pll-mipi) after > >>> the parent's rate (e.g. pll-video0) has already been set to the new > >>> rate. It will then call determine_rate (which requests the parent's > >>> current, i.e. new, rate) to determine a rate that is close to the > >>> flagged core's previous rate. Afterward it will re-calculate the rates > >>> for the flagged core's subtree. > >> > >> I don't think it's the right way forward. It makes the core logic more > >> complicated, for something that is redundant with the notifiers > >> mechanism that has been the go-to for that kind of things so far. > > > > Yeah, that was my initial idea as well. But I couldn't get it to work. > > See details below. > > > > Do you have an example of a clock that restores its previous rate after > > the parent rate has changed? I've looked left and right, but to me it > > seems that notifiers are mainly used for setting clocks into some kind > > of "safe mode" prior to the rate change. Examples: > > > > sunxi-ng: > > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273 > > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60 > > > > but also others: > > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248 > > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755 > > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546 > > > >> It's not really obvious to me why the notifiers don't work there. > >> > >>> This work is inspired by an out-of-tree patchset [1] [2] [3]. > >>> Unfortunately, the patchset uses clk_set_rate() in a notifier callback, > >>> which the following comment on clk_notifier_register() forbids: "The > >>> callbacks associated with the notifier must not re-enter into the clk > >>> framework by calling any top-level clk APIs." [4] Furthermore, that > >>> out-of-tree patchset no longer works with the current linux-next, > >>> because setting pll-mipi is now also resetting pll-video0 [5]. > >> > >> Is it because of the "The callbacks associated with the notifier must > >> not re-enter into the clk framework by calling any top-level clk APIs." > >> comment? > > > > I don't think that's the reason. I'm fairly certain that the problem is, > > that pll-mipi tries to set the parent rate. Maybe it should check if the > > parent is locked, before determining a rate that requires the parent > > rate to change. 🤔 Currently, it only calls clk_hw_can_set_rate_parent() > > which only checks the flag, but does not check if it is really possible > > to change the parent's rate. > > > > Regardless, please don't prematurely dismiss my proposal. It has the > > advantage that it is not specific for sunxi-ng, but could be used for > > other drivers as well. Maybe there other instances of exclusive locks > > today where the CLK_KEEP_RATE flag might work equally well. 🤷 > > > >> If so, I think the thing we should emphasize is that it's about *any > >> top-level clk API*, as in clk_set_rate() or clk_set_parent(). > >> > >> The issue is that any consumer-facing API is taking the clk_prepare lock > >> and thus we would have reentrancy. But we're a provider there, and none > >> of the clk_hw_* functions are taking that lock. Neither do our own > >> function. > >> > >> So we could call in that notifier our set_rate callback directly, or we > >> could create a clk_hw_set_rate() function. > >> > >> The first one will create cache issue between the actual rate that the > >> common clock framework is running and the one we actually enforced, but > >> we could create a function to flush the CCF cache. > >> > >> The second one is probably simpler. > > > > I'm probably missing something, because I don't think this would work. > > For reference, this is our tree: > > > > pll-video0 > >hdmi-phy-clk > >hdmi > >tcon1 > >pll-mipi > > tcon0 > > tcon-data-clock > > > > When pll-vid
Re: [PATCH v2 19/34] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
Degamma has always been on the plane on AMD. CRTC DEGAMMA_LUT has actually just been applying it to every plane pre-blend. Degamma makes no sense after blending anyway. The entire point is for it to happen before blending to blend in linear space. Otherwise DEGAMMA_LUT and REGAMMA_LUT are the exact same thing... - Joshie 🐸 On Tuesday, 22 August 2023, Pekka Paalanen wrote: > On Thu, 10 Aug 2023 15:02:59 -0100 > Melissa Wen wrote: > >> The next patch adds pre-blending degamma to AMD color mgmt pipeline, but >> pre-blending degamma caps (DPP) is currently in use to provide DRM CRTC >> atomic degamma or implict degamma on legacy gamma. Detach degamma usage >> regarging CRTC color properties to manage plane and CRTC color >> correction combinations. >> >> Reviewed-by: Harry Wentland >> Signed-off-by: Melissa Wen >> --- >> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 59 +-- >> 1 file changed, 41 insertions(+), 18 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c >> index 68e9f2c62f2e..74eb02655d96 100644 >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c >> @@ -764,20 +764,9 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) >> return 0; >> } >> >> -/** >> - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane. >> - * @crtc: amdgpu_dm crtc state >> - * @dc_plane_state: target DC surface >> - * >> - * Update the underlying dc_stream_state's input transfer function (ITF) in >> - * preparation for hardware commit. The transfer function used depends on >> - * the preparation done on the stream for color management. >> - * >> - * Returns: >> - * 0 on success. -ENOMEM if mem allocation fails. >> - */ >> -int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, >> - struct dc_plane_state *dc_plane_state) >> +static int >> +map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, >> + struct dc_plane_state *dc_plane_state) >> { >> const struct drm_color_lut *degamma_lut; >> enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; >> @@ -800,8 +789,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, >>°amma_size); >> ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); >> >> - dc_plane_state->in_transfer_func->type = >> - TF_TYPE_DISTRIBUTED_POINTS; >> + dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; >> >> /* >>* This case isn't fully correct, but also fairly >> @@ -837,7 +825,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, >> degamma_lut, degamma_size); >> if (r) >> return r; >> - } else if (crtc->cm_is_degamma_srgb) { >> + } else { >> /* >>* For legacy gamma support we need the regamma input >>* in linear space. Assume that the input is sRGB. >> @@ -847,8 +835,43 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, >> >> if (tf != TRANSFER_FUNCTION_SRGB && >> !mod_color_calculate_degamma_params(NULL, >> - dc_plane_state->in_transfer_func, NULL, false)) >> + dc_plane_state->in_transfer_func, >> + NULL, false)) >> return -ENOMEM; >> + } >> + >> + return 0; >> +} >> + >> +/** >> + * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane. >> + * @crtc: amdgpu_dm crtc state >> + * @dc_plane_state: target DC surface >> + * >> + * Update the underlying dc_stream_state's input transfer function (ITF) in >> + * preparation for hardware commit. The transfer function used depends on >> + * the preparation done on the stream for color management. >> + * >> + * Returns: >> + * 0 on success. -ENOMEM if mem allocation fails. >> + */ >> +int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, >> + struct dc_plane_state *dc_plane_state) >> +{ >> + bool has_crtc_cm_degamma; >> + int ret; >> + >> + has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb); >> + if (has_crtc_cm_degamma){ >> + /* AMD HW doesn't have post-blending degamma caps. When DRM >> + * CRTC atomic degamma is set, we maps it to DPP degamma block >> + * (pre-blending) or, on legacy gamma, we use DPP degamma to >> + * linearize (implicit degamma) from sRGB/BT709 according to >> + * the input space. > > Uhh, you can't just move degamma before blending if KMS userspace > wants it after blending. That would be incorrect behavi
Re: [PATCH] drm/panel: Add prepare_prev_first flag to Visionox VTDR6130
Hi Jessica, On 25/08/2023 20:37, Jessica Zhang wrote: On 8/21/2023 3:01 AM, neil.armstr...@linaro.org wrote: Hi Maxime, On 21/08/2023 10:17, Maxime Ripard wrote: Hi, On Fri, Aug 18, 2023 at 10:25:48AM +0200, neil.armstr...@linaro.org wrote: On 17/08/2023 20:35, Dmitry Baryshkov wrote: On 16/08/2023 10:51, neil.armstr...@linaro.org wrote: Sending HS commands will always work on any controller, it's all about LP commands. The Samsung panels you listed only send HS commands so they can use prepare_prev_first and work on any controllers. I think there is some misunderstanding there, supported by the description of the flag. If I remember correctly, some hosts (sunxi) can not send DCS commands after enabling video stream and switching to HS mode, see [1]. Thus, as you know, most of the drivers have all DSI panel setup commands in drm_panel_funcs::prepare() / drm_bridge_funcs::pre_enable() callbacks, not paying attention whether these commands are to be sent in LP or in HS mode. Previously DSI source drivers could power on the DSI link either in mode_set() or in pre_enable() callbacks, with mode_set() being the hack to make panel/bridge drivers to be able to send commands from their prepare() / pre_enable() callbacks. With the prev_first flags being introduced, we have established that DSI link should be enabled in DSI host's pre_enable() callback and switched to HS mode (be it command or video) in the enable() callback. So far so good. It seems coherent, I would like first to have a state of all DSI host drivers and make this would actually work first before adding the prev_first flag to all the required panels. This is definitely what we should do in an ideal world, but at least for sunxi there's no easy way for it at the moment. There's no documentation for it and the driver provided doesn't allow this to happen. Note that I'm not trying to discourage you or something here, I'm simply pointing out that this will be something that we will have to take into account. And it's possible that other drivers are in a similar situation. Unfortunately this change is not fully backwards-compatible. This requires that all DSI panels sending commands from prepare() should have the prepare_prev_first flag. In some sense, all such patches might have Fixes: 5ea6b1702781 ("drm/panel: Add prepare_prev_first flag to drm_panel"). This kind of migration should be done *before* any possible regression, not the other way round. If all panels sending commands from prepare() should have the prepare_prev_first flag, then it should be first, check for regressions then continue. I understand, but this patch doesn't qualify as a fix for 9e15123eca79 and is too late to be merged in drm-misc-next for v6.6, and since 9e15123eca79 actually breaks some support it should be reverted (+ deps) since we are late in the rc cycles. If we go this way, we can never reapply these patches. There will be no guarantee that all panel drivers are completely converted. We already have a story without an observable end - DRM_BRIDGE_ATTACH_NO_CONNECTOR. I don't understand this point, who would block re-applying the patches ? The migration to DRM_BRIDGE_ATTACH_NO_CONNECTOR was done over multiple Linux version and went smoothly because we reverted regressing patches and restarted when needed, I don't understand why we can't do this here aswell. I'd consider that the DSI driver is correct here and it is about the panel drivers that require fixes patches. If you care about the particular Fixes tag, I have provided one several lines above. Unfortunately it should be done in the other way round, prepare for migration, then migrate, I mean if it's a required migration, then it should be done and I'll support it from both bridge and panel PoV. So, first this patch has the wrong Fixes tag, and I would like a better explanation on the commit message in any case. Then I would like to have an ack from some drm-misc maintainers before applying it because it fixes a patch that was sent via the msm tree thus per the drm-misc rules I cannot apply it via the drm-misc-next-fixes tree. Sorry, it's not clear to me what you'd like our feedback on exactly? So let me resume the situation: - pre_enable_prev_first was introduced in [1] - some panels made use of pre_enable_prev_first - Visionox VTDR6130 was enabled on SM8550 systems and works on v6.5 kernels and before - patch [2] was introduced on MSM DRM tree, breaking VTDR6130 on SM8550 systems (and probably other Video mode panels on Qcom platforms) - this fix was sent late, and is now too late to be merged via drm-misc-next Hi Neil and Maxime, I agree with Neil that 9e15123eca79 was the commit that introduced the issue (since it changed the MSM DSI host behavior). However, I'm not too keen on simply reverting that patch because 1) it's not wrong to have the dsi_power_on in pre_enable. Arguably, it actually makes more sense to power on DSI host in pre_enable than in modeset
Re: [PATCH 00/11] fbdev/sbus: Initializers for struct fb_ops
Hi Sam Am 07.08.23 um 19:11 schrieb Sam Ravnborg: ... Reviewed-by: Sam Ravnborg I completely missed your review. Thanks a lot. I've now pushed the patches to drm-misc-next. Best regards Thomas Sam -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstrasse 146, 90461 Nuernberg, Germany GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman HRB 36809 (AG Nuernberg) OpenPGP_signature Description: OpenPGP digital signature
Re: [PATCH v2 01/15] drm/shmem-helper: Make pages_use_count an atomic_t
On Sat, 19 Aug 2023 05:13:06 +0300 Dmitry Osipenko wrote: > On 8/11/23 16:08, Steven Price wrote: > > On 09/08/2023 17:53, Boris Brezillon wrote: > >> This way we can grab a pages ref without acquiring the resv lock when > >> pages_use_count > 0. Need to implement asynchronous map using the > > > > NIT: s/Need/This is needed/ > > > >> drm_gpuva_mgr when the map/unmap operation triggers a mapping split, > >> requiring the new left/right regions to grab an additional page ref > >> to guarantee that the pages stay pinned when the middle section is > >> unmapped. > >> > >> Signed-off-by: Boris Brezillon > >> --- > >> drivers/gpu/drm/drm_gem_shmem_helper.c | 28 + > >> drivers/gpu/drm/lima/lima_gem.c | 2 +- > >> drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- > >> include/drm/drm_gem_shmem_helper.h | 2 +- > >> 4 files changed, 18 insertions(+), 16 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > >> b/drivers/gpu/drm/drm_gem_shmem_helper.c > >> index a783d2245599..ca6938ea1b82 100644 > >> --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > >> +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > >> @@ -155,7 +155,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > >> *shmem) > >>if (shmem->pages) > >>drm_gem_shmem_put_pages(shmem); > >> > >> - drm_WARN_ON(obj->dev, shmem->pages_use_count); > >> + drm_WARN_ON(obj->dev, atomic_read(&shmem->pages_use_count)); > >> > >>dma_resv_unlock(shmem->base.resv); > >>} > >> @@ -172,14 +172,14 @@ static int drm_gem_shmem_get_pages(struct > >> drm_gem_shmem_object *shmem) > >> > >>dma_resv_assert_held(shmem->base.resv); > >> > >> - if (shmem->pages_use_count++ > 0) > >> + if (atomic_inc_return(&shmem->pages_use_count) > 1) > >>return 0; > >> > >>pages = drm_gem_get_pages(obj); > >>if (IS_ERR(pages)) { > >>drm_dbg_kms(obj->dev, "Failed to get pages (%ld)\n", > >>PTR_ERR(pages)); > >> - shmem->pages_use_count = 0; > >> + atomic_set(&shmem->pages_use_count, 0); > >>return PTR_ERR(pages); > >>} > >> > >> @@ -210,10 +210,10 @@ void drm_gem_shmem_put_pages(struct > >> drm_gem_shmem_object *shmem) > >> > >>dma_resv_assert_held(shmem->base.resv); > >> > >> - if (drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count)) > >> + if (drm_WARN_ON_ONCE(obj->dev, !atomic_read(&shmem->pages_use_count))) > >>return; > >> > >> - if (--shmem->pages_use_count > 0) > >> + if (atomic_dec_return(&shmem->pages_use_count) > 0) > >>return; > >> > >> #ifdef CONFIG_X86 > >> @@ -263,6 +263,10 @@ int drm_gem_shmem_pin(struct drm_gem_shmem_object > >> *shmem) > >> > >>drm_WARN_ON(obj->dev, obj->import_attach); > >> > >> + /* If we are the first owner, we need to grab the lock. */ > >> + if (atomic_inc_not_zero(&shmem->pages_use_count)) > >> + return 0; > >> + > > > > Unless I'm misunderstanding I think this introduces a race where two > > threads call drm_gem_shmem_pin() at the same time: > > > > Thread1 | Thread 2 > > +-- > > drm_gem_shmem_pin() | > > - pages_use_count == 0 so not | > >incremented | > > - lock taken | > > drm_gem_shmem_pin_locked() | > > drm_gem_shmem_get_pages() | > > - pages_use_count incremented | > > | drm_gem_shmem_pin() > > | - pages_use_count == 1 so is it > > |incremented and returns early > > |without taking the lock > > | Code tries to use shmem->pages > > | and blows up > > drm_gem_get_pages() | > > shmem->pages populated | > > lock released | > > > > I think you need to modify drm_gem_shmem_get_pages() to only increment > > pages_use_count when shmem->pages has been populated. Oops, didn't spot that race. Thanks for pointing it out. > > This is correct, both pin() and get_pages() should use > atomic_inc_not_zero(). > > Note that we shouldn't use atomic functions open-coded, there is kref > helper for that which uses refcount_t underneath and has additional > checks/warnings for count underflow/overflow. I'm going to post patches > converting drm-shmem to kref around next week, Boris is aware about it > and we should then sync shrinker/panthor patchsets to the common > drm-shmem base. Thanks, I'll have a look at these patches pretty soon.
Re: [PATCH v15 10/23] locking/refcount, kref: Add kref_put_ww_mutex()
On Sun, 27 Aug 2023 20:54:36 +0300 Dmitry Osipenko wrote: > Introduce kref_put_ww_mutex() helper that will handle the wait-wound > mutex auto-locking on kref_put(). This helper is wanted by DRM drivers > that extensively use dma-reservation locking which in turns uses ww-mutex. > > Signed-off-by: Dmitry Osipenko > --- > include/linux/kref.h | 12 > include/linux/refcount.h | 5 + > lib/refcount.c | 34 ++ > 3 files changed, 51 insertions(+) > > diff --git a/include/linux/kref.h b/include/linux/kref.h > index d32e21a2538c..b2d8dc6e9ae0 100644 > --- a/include/linux/kref.h > +++ b/include/linux/kref.h > @@ -90,6 +90,18 @@ static inline int kref_put_lock(struct kref *kref, > return 0; > } > > +static inline int kref_put_ww_mutex(struct kref *kref, > + void (*release)(struct kref *kref), > + struct ww_mutex *lock, > + struct ww_acquire_ctx *ctx) > +{ > + if (refcount_dec_and_ww_mutex_lock(&kref->refcount, lock, ctx)) { > + release(kref); > + return 1; > + } > + return 0; > +} > + > /** > * kref_get_unless_zero - Increment refcount for object unless it is zero. > * @kref: object. > diff --git a/include/linux/refcount.h b/include/linux/refcount.h > index a62fcca97486..be9ad272bc77 100644 > --- a/include/linux/refcount.h > +++ b/include/linux/refcount.h > @@ -99,6 +99,8 @@ > #include > > struct mutex; > +struct ww_mutex; > +struct ww_acquire_ctx; > > /** > * typedef refcount_t - variant of atomic_t specialized for reference counts > @@ -366,4 +368,7 @@ extern __must_check bool refcount_dec_and_lock(refcount_t > *r, spinlock_t *lock) > extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r, > spinlock_t *lock, > unsigned long *flags) > __cond_acquires(lock); > +extern __must_check bool refcount_dec_and_ww_mutex_lock(refcount_t *r, > + struct ww_mutex *lock, > + struct ww_acquire_ctx > *ctx) __cond_acquires(&lock->base); > #endif /* _LINUX_REFCOUNT_H */ > diff --git a/lib/refcount.c b/lib/refcount.c > index a207a8f22b3c..3f6fd0ceed02 100644 > --- a/lib/refcount.c > +++ b/lib/refcount.c > @@ -6,6 +6,7 @@ > #include > #include > #include > +#include > #include > > #define REFCOUNT_WARN(str) WARN_ONCE(1, "refcount_t: " str ".\n") > @@ -184,3 +185,36 @@ bool refcount_dec_and_lock_irqsave(refcount_t *r, > spinlock_t *lock, > return true; > } > EXPORT_SYMBOL(refcount_dec_and_lock_irqsave); > + > +/** > + * refcount_dec_and_ww_mutex_lock - return holding ww-mutex if able to > + * decrement refcount to 0 > + * @r: the refcount > + * @lock: the ww-mutex to be locked > + * @ctx: wait-wound context > + * > + * Similar to atomic_dec_and_lock(), it will WARN on underflow and fail to > + * decrement when saturated at REFCOUNT_SATURATED. > + * > + * Provides release memory ordering, such that prior loads and stores are > done > + * before, and provides a control dependency such that free() must come > after. > + * See the comment on top. > + * > + * Return: true and hold ww-mutex lock if able to decrement refcount to 0, > + * false otherwise > + */ > +bool refcount_dec_and_ww_mutex_lock(refcount_t *r, struct ww_mutex *lock, > + struct ww_acquire_ctx *ctx) > +{ > + if (refcount_dec_not_one(r)) > + return false; > + > + ww_mutex_lock(lock, ctx); Unless I'm wrong, ww_mutex_lock() can return -EDEADLK when ctx != NULL, in which case, the lock is not held when it returns. Question is, do we really have a use case for ctx != NULL in that kref_put_ww_mutex() path. If we need to acquire other ww_locks, this lock, and the other locks should have been acquired beforehand, and we can simply call kref_put() when we want to release the ref on the resource. > + if (!refcount_dec_and_test(r)) { > + ww_mutex_unlock(lock); > + return false; > + } > + > + return true; > +} > +EXPORT_SYMBOL(refcount_dec_and_ww_mutex_lock);
Re: [PATCH v15 12/23] drm/shmem-helper: Add and use pages_pin_count
On Sun, 27 Aug 2023 20:54:38 +0300 Dmitry Osipenko wrote: > Add separate pages_pin_count for tracking of whether drm-shmem pages are > moveable or not. With the addition of memory shrinker support to drm-shmem, > the pages_use_count will no longer determine whether pages are hard-pinned > in memory, but whether pages exit and are soft-pinned (and could be swapped ^exist > out). The pages_pin_count > 1 will hard-pin pages in memory. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 22 +- > include/drm/drm_gem_shmem_helper.h | 10 ++ > 2 files changed, 27 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index d545d3d227d7..1a7e5c332fd8 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -234,14 +234,22 @@ static int drm_gem_shmem_pin_locked(struct > drm_gem_shmem_object *shmem) > > dma_resv_assert_held(shmem->base.resv); > > + if (kref_get_unless_zero(&shmem->pages_pin_count)) > + return 0; > + > ret = drm_gem_shmem_get_pages_locked(shmem); > + if (!ret) > + kref_init(&shmem->pages_pin_count); > > return ret; > } > > -static void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem) > +static void drm_gem_shmem_kref_unpin_pages(struct kref *kref) > { > - dma_resv_assert_held(shmem->base.resv); > + struct drm_gem_shmem_object *shmem; > + > + shmem = container_of(kref, struct drm_gem_shmem_object, > + pages_pin_count); > > drm_gem_shmem_put_pages_locked(shmem); > } > @@ -263,6 +271,9 @@ int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem) > > drm_WARN_ON(obj->dev, obj->import_attach); > > + if (kref_get_unless_zero(&shmem->pages_pin_count)) > + return 0; > + > ret = dma_resv_lock_interruptible(shmem->base.resv, NULL); > if (ret) > return ret; > @@ -286,9 +297,10 @@ void drm_gem_shmem_unpin(struct drm_gem_shmem_object > *shmem) > > drm_WARN_ON(obj->dev, obj->import_attach); > > - dma_resv_lock(shmem->base.resv, NULL); > - drm_gem_shmem_unpin_locked(shmem); > - dma_resv_unlock(shmem->base.resv); > + if (kref_put_dma_resv(&shmem->pages_pin_count, > + drm_gem_shmem_kref_unpin_pages, > + obj->resv, NULL)) > + dma_resv_unlock(obj->resv); > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_unpin); > > diff --git a/include/drm/drm_gem_shmem_helper.h > b/include/drm/drm_gem_shmem_helper.h > index ec2d8b24e3cf..afb7cd671e2a 100644 > --- a/include/drm/drm_gem_shmem_helper.h > +++ b/include/drm/drm_gem_shmem_helper.h > @@ -39,6 +39,16 @@ struct drm_gem_shmem_object { >*/ > unsigned int pages_use_count; > > + /** > + * @pages_pin_count: > + * > + * Reference count on the pinned pages table. > + * The pages allowed to be evicted and purged by memory > + * shrinker only when the count is zero, otherwise pages > + * are hard-pinned in memory. > + */ > + struct kref pages_pin_count; > + > /** >* @madv: State for madvise >*
[PATCH v2 0/9] accel/ivpu: Update for -next 2023.08.25
Update for -next: - various cleanups - begin preparation for conversion to GEM SHMEM - print information about used workarounds v2: Fix compilation without CONFIG_PM Jacek Lawrynowicz (4): accel/ivpu: Remove duplicated error messages accel/ivpu: Move ivpu_fw_load() to ivpu_fw_init() accel/ivpu: Add ivpu_bo_vaddr() and ivpu_bo_size() accel/ivpu: Move MMU register definitions to ivpu_mmu.c Karol Wachowski (1): accel/ivpu: Initialize context with SSID = 1 Krystian Pradzynski (1): accel/ivpu: Move set autosuspend delay to HW specific code Stanislaw Gruszka (3): accel/ivpu: Print information about used workarounds accel/ivpu/37xx: Change register rename leftovers accel/ivpu/37xx: White space cleanup drivers/accel/ivpu/ivpu_drv.c | 65 +++-- drivers/accel/ivpu/ivpu_drv.h | 18 ++- drivers/accel/ivpu/ivpu_fw.c | 26 ++-- drivers/accel/ivpu/ivpu_fw.h | 2 +- drivers/accel/ivpu/ivpu_fw_log.c | 6 +- drivers/accel/ivpu/ivpu_gem.c | 30 ++--- drivers/accel/ivpu/ivpu_gem.h | 22 ++- drivers/accel/ivpu/ivpu_hw_37xx.c | 75 ++- drivers/accel/ivpu/ivpu_hw_37xx_reg.h | 187 +++--- drivers/accel/ivpu/ivpu_hw_40xx.c | 7 + drivers/accel/ivpu/ivpu_ipc.c | 19 ++- drivers/accel/ivpu/ivpu_job.c | 8 +- drivers/accel/ivpu/ivpu_mmu.c | 117 ++-- drivers/accel/ivpu/ivpu_mmu_context.c | 16 ++- drivers/accel/ivpu/ivpu_mmu_context.h | 2 + drivers/accel/ivpu/ivpu_pm.c | 18 +-- drivers/accel/ivpu/ivpu_pm.h | 2 +- 17 files changed, 323 insertions(+), 297 deletions(-) -- 2.25.1
[PATCH v2 1/9] accel/ivpu: Move set autosuspend delay to HW specific code
From: Krystian Pradzynski Configure autosuspend values per HW generation and per platform. For non silicon platforms disable autosuspend for now, for silicon reduce it to 10 ms. Signed-off-by: Krystian Pradzynski Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_hw_37xx.c | 2 ++ drivers/accel/ivpu/ivpu_hw_40xx.c | 3 +++ drivers/accel/ivpu/ivpu_pm.c | 14 -- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 9e8c075fe9ef..44d857094bbc 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -117,6 +117,7 @@ struct ivpu_device { int jsm; int tdr; int reschedule_suspend; + int autosuspend; } timeout; }; diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 9eae1c241bc0..1090c91e1ba3 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -113,11 +113,13 @@ static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) vdev->timeout.jsm = 5; vdev->timeout.tdr = 200; vdev->timeout.reschedule_suspend = 1000; + vdev->timeout.autosuspend = -1; } else { vdev->timeout.boot = 1000; vdev->timeout.jsm = 500; vdev->timeout.tdr = 2000; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = 10; } } diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index 34626d66fa10..09ba07443396 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -135,16 +135,19 @@ static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) vdev->timeout.jsm = 5; vdev->timeout.tdr = 200; vdev->timeout.reschedule_suspend = 1000; + vdev->timeout.autosuspend = -1; } else if (ivpu_is_simics(vdev)) { vdev->timeout.boot = 50; vdev->timeout.jsm = 500; vdev->timeout.tdr = 1; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = -1; } else { vdev->timeout.boot = 1000; vdev->timeout.jsm = 500; vdev->timeout.tdr = 2000; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = 10; } } diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index e6f27daf5560..954c9ecd3e14 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -286,6 +286,7 @@ int ivpu_pm_init(struct ivpu_device *vdev) { struct device *dev = vdev->drm.dev; struct ivpu_pm_info *pm = vdev->pm; + int delay; pm->vdev = vdev; pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; @@ -293,14 +294,15 @@ int ivpu_pm_init(struct ivpu_device *vdev) atomic_set(&pm->in_reset, 0); INIT_WORK(&pm->recovery_work, ivpu_pm_recovery_work); - pm_runtime_use_autosuspend(dev); - if (ivpu_disable_recovery) - pm_runtime_set_autosuspend_delay(dev, -1); - else if (ivpu_is_silicon(vdev)) - pm_runtime_set_autosuspend_delay(dev, 100); + delay = -1; else - pm_runtime_set_autosuspend_delay(dev, 6); + delay = vdev->timeout.autosuspend; + + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, delay); + + ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay); return 0; } -- 2.25.1
[PATCH v2 2/9] accel/ivpu: Remove duplicated error messages
From: Jacek Lawrynowicz Reduce the number of error messages per single failure in ivpu_dev_init(). Error messages are already printed by functions called from ivpu_dev_init(). Signed-off-by: Jacek Lawrynowicz Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_drv.c | 54 +++ drivers/accel/ivpu/ivpu_fw.c | 2 +- drivers/accel/ivpu/ivpu_ipc.c | 13 +-- drivers/accel/ivpu/ivpu_mmu_context.c | 6 ++- drivers/accel/ivpu/ivpu_pm.c | 4 +- drivers/accel/ivpu/ivpu_pm.h | 2 +- 6 files changed, 29 insertions(+), 52 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index ba79f397c9e8..b10b2909f05f 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -518,78 +518,52 @@ static int ivpu_dev_init(struct ivpu_device *vdev) lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); ret = ivpu_pci_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize PCI device: %d\n", ret); + if (ret) goto err_xa_destroy; - } ret = ivpu_irq_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize IRQs: %d\n", ret); + if (ret) goto err_xa_destroy; - } /* Init basic HW info based on buttress registers which are accessible before power up */ ret = ivpu_hw_info_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize HW info: %d\n", ret); + if (ret) goto err_xa_destroy; - } /* Power up early so the rest of init code can access VPU registers */ ret = ivpu_hw_power_up(vdev); - if (ret) { - ivpu_err(vdev, "Failed to power up HW: %d\n", ret); + if (ret) goto err_xa_destroy; - } ret = ivpu_mmu_global_context_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize global MMU context: %d\n", ret); + if (ret) goto err_power_down; - } ret = ivpu_mmu_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize MMU device: %d\n", ret); + if (ret) goto err_mmu_gctx_fini; - } ret = ivpu_fw_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize firmware: %d\n", ret); + if (ret) goto err_mmu_gctx_fini; - } ret = ivpu_ipc_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize IPC: %d\n", ret); + if (ret) goto err_fw_fini; - } - ret = ivpu_pm_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize PM: %d\n", ret); - goto err_ipc_fini; - } + ivpu_pm_init(vdev); ret = ivpu_job_done_thread_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize job done thread: %d\n", ret); + if (ret) goto err_ipc_fini; - } ret = ivpu_fw_load(vdev); - if (ret) { - ivpu_err(vdev, "Failed to load firmware: %d\n", ret); + if (ret) goto err_job_done_thread_fini; - } ret = ivpu_boot(vdev); - if (ret) { - ivpu_err(vdev, "Failed to boot: %d\n", ret); + if (ret) goto err_job_done_thread_fini; - } ivpu_pm_enable(vdev); @@ -651,10 +625,8 @@ static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, vdev); ret = ivpu_dev_init(vdev); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize VPU device: %d\n", ret); + if (ret) return ret; - } ret = drm_dev_register(&vdev->drm, 0); if (ret) { diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 9827ea4d7b83..9b6ecd3e9537 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -78,7 +78,7 @@ static int ivpu_fw_request(struct ivpu_device *vdev) } } - ivpu_err(vdev, "Failed to request firmware: %d\n", ret); + ivpu_err(vdev, "Failed to load firmware: %d\n", ret); return ret; } diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index fa0af59e39ab..6b2e9dbb284a 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -426,15 +426,20 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev) int ivpu_ipc_init(struct ivpu_device *vdev) { struct ivpu_ipc_info *ipc = vdev->ipc; - int ret = -ENOMEM; + int ret; ipc->mem_tx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC); - if (!ipc->mem_tx) - return ret; + if (!ipc->mem_tx)
[PATCH v2 3/9] accel/ivpu: Print information about used workarounds
Use ivpu_dbg(MISC) to print information about workarounds. Reviewed-by: Karol Wachowski Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_drv.h | 5 + drivers/accel/ivpu/ivpu_hw_37xx.c | 5 + drivers/accel/ivpu/ivpu_hw_40xx.c | 4 3 files changed, 14 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 44d857094bbc..060c09402227 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -75,6 +75,11 @@ #define IVPU_WA(wa_name) (vdev->wa.wa_name) +#define IVPU_PRINT_WA(wa_name) do {\ + if (IVPU_WA(wa_name)) \ + ivpu_dbg(vdev, MISC, "Using WA: " #wa_name "\n"); \ +} while (0) + struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 1090c91e1ba3..bf3432b68879 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -104,6 +104,11 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4) vdev->wa.interrupt_clear_with_0 = true; + + IVPU_PRINT_WA(punit_disabled); + IVPU_PRINT_WA(clear_runtime_mem); + IVPU_PRINT_WA(d3hot_after_power_off); + IVPU_PRINT_WA(interrupt_clear_with_0); } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index 09ba07443396..1c2528549635 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -126,6 +126,10 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) if (ivpu_hw_gen(vdev) == IVPU_HW_40XX) vdev->wa.disable_clock_relinquish = true; + + IVPU_PRINT_WA(punit_disabled); + IVPU_PRINT_WA(clear_runtime_mem); + IVPU_PRINT_WA(disable_clock_relinquish); } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) -- 2.25.1
[PATCH v2 5/9] accel/ivpu: Move ivpu_fw_load() to ivpu_fw_init()
From: Jacek Lawrynowicz ivpu_fw_load() doesn't have to be called separately in ivpu_dev_init(). Signed-off-by: Jacek Lawrynowicz Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_drv.c | 4 drivers/accel/ivpu/ivpu_fw.c | 6 +++--- drivers/accel/ivpu/ivpu_fw.h | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 5310b54f036d..fa0680ba9340 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -561,10 +561,6 @@ static int ivpu_dev_init(struct ivpu_device *vdev) if (ret) goto err_ipc_fini; - ret = ivpu_fw_load(vdev); - if (ret) - goto err_job_done_thread_fini; - ret = ivpu_boot(vdev); if (ret) goto err_job_done_thread_fini; diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 9b6ecd3e9537..32a1ea322ca2 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -301,6 +301,8 @@ int ivpu_fw_init(struct ivpu_device *vdev) if (ret) goto err_fw_release; + ivpu_fw_load(vdev); + return 0; err_fw_release: @@ -314,7 +316,7 @@ void ivpu_fw_fini(struct ivpu_device *vdev) ivpu_fw_release(vdev); } -int ivpu_fw_load(struct ivpu_device *vdev) +void ivpu_fw_load(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; u64 image_end_offset = fw->image_load_offset + fw->image_size; @@ -331,8 +333,6 @@ int ivpu_fw_load(struct ivpu_device *vdev) } wmb(); /* Flush WC buffers after writing fw->mem */ - - return 0; } static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_params *boot_params) diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h index 8567fdf925fe..10ae2847f0ef 100644 --- a/drivers/accel/ivpu/ivpu_fw.h +++ b/drivers/accel/ivpu/ivpu_fw.h @@ -31,7 +31,7 @@ struct ivpu_fw_info { int ivpu_fw_init(struct ivpu_device *vdev); void ivpu_fw_fini(struct ivpu_device *vdev); -int ivpu_fw_load(struct ivpu_device *vdev); +void ivpu_fw_load(struct ivpu_device *vdev); void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *bp); static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev) -- 2.25.1
[PATCH v2 4/9] accel/ivpu: Initialize context with SSID = 1
From: Karol Wachowski Context with SSID = 1 is reserved and accesses on that context happen only when context is uninitialized on the VPU side. Such access triggers MMU fault (0xa) "Invalid CD Fetch", which doesn't contain any useful information besides context ID. This commit will change that state, now (0x10) "Translation fault" will be triggered and accessed address will shown in the log. Signed-off-by: Karol Wachowski Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_drv.c | 9 - drivers/accel/ivpu/ivpu_drv.h | 12 +++- drivers/accel/ivpu/ivpu_mmu_context.c | 10 ++ drivers/accel/ivpu/ivpu_mmu_context.h | 2 ++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index b10b2909f05f..5310b54f036d 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -543,10 +543,14 @@ static int ivpu_dev_init(struct ivpu_device *vdev) if (ret) goto err_mmu_gctx_fini; - ret = ivpu_fw_init(vdev); + ret = ivpu_mmu_reserved_context_init(vdev); if (ret) goto err_mmu_gctx_fini; + ret = ivpu_fw_init(vdev); + if (ret) + goto err_mmu_rctx_fini; + ret = ivpu_ipc_init(vdev); if (ret) goto err_fw_fini; @@ -575,6 +579,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev) ivpu_ipc_fini(vdev); err_fw_fini: ivpu_fw_fini(vdev); +err_mmu_rctx_fini: + ivpu_mmu_reserved_context_fini(vdev); err_mmu_gctx_fini: ivpu_mmu_global_context_fini(vdev); err_power_down: @@ -598,6 +604,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev) ivpu_ipc_fini(vdev); ivpu_fw_fini(vdev); + ivpu_mmu_reserved_context_fini(vdev); ivpu_mmu_global_context_fini(vdev); drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 060c09402227..12a63f8a73e8 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -28,12 +28,13 @@ #define IVPU_HW_37XX 37 #define IVPU_HW_40XX 40 -#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 -/* SSID 1 is used by the VPU to represent invalid context */ -#define IVPU_USER_CONTEXT_MIN_SSID 2 -#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63) +#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 +/* SSID 1 is used by the VPU to represent reserved context */ +#define IVPU_RESERVED_CONTEXT_MMU_SSID 1 +#define IVPU_USER_CONTEXT_MIN_SSID 2 +#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63) -#define IVPU_NUM_ENGINES2 +#define IVPU_NUM_ENGINES 2 #define IVPU_PLATFORM_SILICON 0 #define IVPU_PLATFORM_SIMICS 2 @@ -109,6 +110,7 @@ struct ivpu_device { struct ivpu_pm_info *pm; struct ivpu_mmu_context gctx; + struct ivpu_mmu_context rctx; struct xarray context_xa; struct xa_limit context_xa_limit; diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 1144d6eb5120..e5336adc5e59 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -469,6 +469,16 @@ void ivpu_mmu_global_context_fini(struct ivpu_device *vdev) return ivpu_mmu_context_fini(vdev, &vdev->gctx); } +int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev) +{ + return ivpu_mmu_user_context_init(vdev, &vdev->rctx, IVPU_RESERVED_CONTEXT_MMU_SSID); +} + +void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev) +{ + return ivpu_mmu_user_context_fini(vdev, &vdev->rctx); +} + void ivpu_mmu_user_context_mark_invalid(struct ivpu_device *vdev, u32 ssid) { struct ivpu_file_priv *file_priv; diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h index 961a0d6a6c7f..f15d8c630d8a 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.h +++ b/drivers/accel/ivpu/ivpu_mmu_context.h @@ -32,6 +32,8 @@ struct ivpu_mmu_context { int ivpu_mmu_global_context_init(struct ivpu_device *vdev); void ivpu_mmu_global_context_fini(struct ivpu_device *vdev); +int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev); +void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev); int ivpu_mmu_user_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u32 ctx_id); void ivpu_mmu_user_context_fini(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); -- 2.25.1
[PATCH v2 7/9] accel/ivpu/37xx: Change register rename leftovers
Change remaining MTL_VPU_ register names to generation based names. Reviewed-by: Karol Wachowski Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_hw_37xx.c | 68 - drivers/accel/ivpu/ivpu_hw_37xx_reg.h | 72 +-- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index bf3432b68879..edd4d860f135 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -352,10 +352,10 @@ static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -363,10 +363,10 @@ static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QACCEPTN); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -374,10 +374,10 @@ static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_va static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QDENY); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -430,15 +430,15 @@ static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable int ret; u32 val; - val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); + val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); if (enable) { - val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); } else { - val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); } - REGV_WR32(MTL_VPU_TOP_NOC_QREQN, val); + REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val); ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); if (ret) { @@ -570,17 +570,17 @@ static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) { u32 val; - val = REGV_RD32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); - val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); + val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); - val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val);
[PATCH v2 8/9] accel/ivpu/37xx: White space cleanup
No functional change, adjust code formatting after previous changes. Reviewed-by: Karol Wachowski Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_hw_37xx_reg.h | 100 +- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h index 0f106f192f7c..531a68c1cce8 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h @@ -8,65 +8,65 @@ #include -#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0xu +#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0xu -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x0004u -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) +#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x0004u +#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) #define VPU_37XX_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x0008u -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x0008u +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x000cu -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x000cu +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x0010u +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x0010u #define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x0014u +#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x0014u #define VPU_37XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_WP_DOWNLOAD 0x0018u #define VPU_37XX_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0) #define VPU_37XX_BUTTRESS_CURRENT_PLL 0x001cu -#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x0020u +#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x0020u -#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x0024u -#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) -#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) +#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x0024u +#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) +#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) -#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x0028u -#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) +#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x0028u +#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) -#define VPU_37XX_BUTTRESS_TILE_FUSE 0x002cu +#define VPU_37XX_BUTTRESS_TILE_FUSE 0x002cu #define VPU_37XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) +#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) -#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x0030u -#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK
[PATCH v2 9/9] accel/ivpu: Move MMU register definitions to ivpu_mmu.c
From: Jacek Lawrynowicz MMU registers are not platform specific so they should be defined separate to platform regs. Signed-off-by: Jacek Lawrynowicz Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_hw_37xx_reg.h | 33 drivers/accel/ivpu/ivpu_mmu.c | 117 +- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h index 531a68c1cce8..4083beb5e9db 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h @@ -191,39 +191,6 @@ #define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_FINAL_PLL_FREQ_MASK GENMASK(15, 0) #define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_CONFIG_ID_MASK GENMASK(31, 16) -#define VPU_37XX_HOST_MMU_IDR0 0x0020u -#define VPU_37XX_HOST_MMU_IDR1 0x0024u -#define VPU_37XX_HOST_MMU_IDR3 0x002cu -#define VPU_37XX_HOST_MMU_IDR5 0x00200014u -#define VPU_37XX_HOST_MMU_CR0 0x00200020u -#define VPU_37XX_HOST_MMU_CR0ACK 0x00200024u -#define VPU_37XX_HOST_MMU_CR1 0x00200028u -#define VPU_37XX_HOST_MMU_CR2 0x0020002cu -#define VPU_37XX_HOST_MMU_IRQ_CTRL 0x00200050u -#define VPU_37XX_HOST_MMU_IRQ_CTRLACK 0x00200054u - -#define VPU_37XX_HOST_MMU_GERROR 0x00200060u -#define VPU_37XX_HOST_MMU_GERROR_CMDQ_MASK BIT_MASK(0) -#define VPU_37XX_HOST_MMU_GERROR_EVTQ_ABT_MASK BIT_MASK(2) -#define VPU_37XX_HOST_MMU_GERROR_PRIQ_ABT_MASK BIT_MASK(3) -#define VPU_37XX_HOST_MMU_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4) -#define VPU_37XX_HOST_MMU_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5) -#define VPU_37XX_HOST_MMU_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6) -#define VPU_37XX_HOST_MMU_GERROR_MSI_ABT_MASK BIT_MASK(7) - -#define VPU_37XX_HOST_MMU_GERRORN 0x00200064u - -#define VPU_37XX_HOST_MMU_STRTAB_BASE 0x00200080u -#define VPU_37XX_HOST_MMU_STRTAB_BASE_CFG 0x00200088u -#define VPU_37XX_HOST_MMU_CMDQ_BASE 0x00200090u -#define VPU_37XX_HOST_MMU_CMDQ_PROD 0x00200098u -#define VPU_37XX_HOST_MMU_CMDQ_CONS 0x0020009cu -#define VPU_37XX_HOST_MMU_EVTQ_BASE 0x002000a0u -#define VPU_37XX_HOST_MMU_EVTQ_PROD 0x002000a8u -#define VPU_37XX_HOST_MMU_EVTQ_CONS 0x002000acu -#define VPU_37XX_HOST_MMU_EVTQ_PROD_SEC (0x002000a8u + SZ_64K) -#define VPU_37XX_HOST_MMU_EVTQ_CONS_SEC (0x002000acu + SZ_64K) - #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES 0x0036u #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_CACHE_OVERRIDE_EN_MASK BIT_MASK(0) #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1) diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index baefaf7bb3cb..473e1fc686a7 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -7,12 +7,45 @@ #include #include "ivpu_drv.h" -#include "ivpu_hw_37xx_reg.h" #include "ivpu_hw_reg_io.h" #include "ivpu_mmu.h" #include "ivpu_mmu_context.h" #include "ivpu_pm.h" +#define IVPU_MMU_REG_IDR00x0020u +#define IVPU_MMU_REG_IDR10x0024u +#define IVPU_MMU_REG_IDR30x002cu +#define IVPU_MMU_REG_IDR50x00200014u +#define IVPU_MMU_REG_CR0 0x00200020u +#define IVPU_MMU_REG_CR0ACK 0x00200024u +#define IVPU_MMU_REG_CR1 0x00200028u +#define IVPU_MMU_REG_CR2 0x0020002cu +#define IVPU_MMU_REG_IRQ_CTRL0x00200050u +#define IVPU_MMU_REG_IRQ_CTRLACK 0x00200054u + +#define IVPU_MMU_REG_GERROR 0x00200060u +#define IVPU_MMU_REG_GERROR_CMDQ_MASKBIT_MASK(0) +#define IVPU_MMU_REG_GERROR_EVTQ_ABT_MASK BIT_MASK(2) +#define IVPU_MMU_REG_GERROR_PRIQ_ABT_MASK BIT_MASK(3) +#define IVPU_MMU_REG_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4) +#define IVPU_MMU_REG_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5) +#define IVPU_MMU_REG_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6) +#define IVPU_MMU_REG_GERROR_M
[PATCH v2 6/9] accel/ivpu: Add ivpu_bo_vaddr() and ivpu_bo_size()
From: Jacek Lawrynowicz Use: - ivpu_bo_vaddr(bo) instead of bo->kvaddr - ivpu_bo_size(bo) instead of bo->base.size This is a preparation for switch to a drm_gem_shmem_object as a base for ivpu_bo, where: - bo->kvaddr becomes bo->base.vaddr - bo->base.size becomes bo->base.base.size Using ivpu_bo_vaddr() and ivpu_bo_size() increases the readability of the code. Signed-off-by: Jacek Lawrynowicz Reviewed-by: Stanislaw Gruszka Signed-off-by: Stanislaw Gruszka --- drivers/accel/ivpu/ivpu_fw.c | 18 +- drivers/accel/ivpu/ivpu_fw_log.c | 6 +++--- drivers/accel/ivpu/ivpu_gem.c| 30 +++--- drivers/accel/ivpu/ivpu_gem.h| 22 -- drivers/accel/ivpu/ivpu_ipc.c| 6 +++--- drivers/accel/ivpu/ivpu_job.c| 8 drivers/accel/ivpu/ivpu_pm.c | 2 +- 7 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 32a1ea322ca2..2fef9fe154aa 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -321,13 +321,13 @@ void ivpu_fw_load(struct ivpu_device *vdev) struct ivpu_fw_info *fw = vdev->fw; u64 image_end_offset = fw->image_load_offset + fw->image_size; - memset(fw->mem->kvaddr, 0, fw->image_load_offset); - memcpy(fw->mem->kvaddr + fw->image_load_offset, + memset(ivpu_bo_vaddr(fw->mem), 0, fw->image_load_offset); + memcpy(ivpu_bo_vaddr(fw->mem) + fw->image_load_offset, fw->file->data + FW_FILE_IMAGE_OFFSET, fw->image_size); if (IVPU_WA(clear_runtime_mem)) { - u8 *start = fw->mem->kvaddr + image_end_offset; - u64 size = fw->mem->base.size - image_end_offset; + u8 *start = ivpu_bo_vaddr(fw->mem) + image_end_offset; + u64 size = ivpu_bo_size(fw->mem) - image_end_offset; memset(start, 0, size); } @@ -450,10 +450,10 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params vdev->hw->ranges.global.start; boot_params->ipc_header_area_start = ipc_mem_rx->vpu_addr; - boot_params->ipc_header_area_size = ipc_mem_rx->base.size / 2; + boot_params->ipc_header_area_size = ivpu_bo_size(ipc_mem_rx) / 2; - boot_params->ipc_payload_area_start = ipc_mem_rx->vpu_addr + ipc_mem_rx->base.size / 2; - boot_params->ipc_payload_area_size = ipc_mem_rx->base.size / 2; + boot_params->ipc_payload_area_start = ipc_mem_rx->vpu_addr + ivpu_bo_size(ipc_mem_rx) / 2; + boot_params->ipc_payload_area_size = ivpu_bo_size(ipc_mem_rx) / 2; boot_params->global_aliased_pio_base = vdev->hw->ranges.user.start; boot_params->global_aliased_pio_size = ivpu_hw_range_size(&vdev->hw->ranges.user); @@ -485,9 +485,9 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->trace_destination_mask = vdev->fw->trace_destination_mask; boot_params->trace_hw_component_mask = vdev->fw->trace_hw_component_mask; boot_params->crit_tracing_buff_addr = vdev->fw->mem_log_crit->vpu_addr; - boot_params->crit_tracing_buff_size = vdev->fw->mem_log_crit->base.size; + boot_params->crit_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_crit); boot_params->verbose_tracing_buff_addr = vdev->fw->mem_log_verb->vpu_addr; - boot_params->verbose_tracing_buff_size = vdev->fw->mem_log_verb->base.size; + boot_params->verbose_tracing_buff_size = ivpu_bo_size(vdev->fw->mem_log_verb); boot_params->punit_telemetry_sram_base = ivpu_hw_reg_telemetry_offset_get(vdev); boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev); diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c index 95065cac9fbd..f6770f5e82a2 100644 --- a/drivers/accel/ivpu/ivpu_fw_log.c +++ b/drivers/accel/ivpu/ivpu_fw_log.c @@ -31,10 +31,10 @@ static int fw_log_ptr(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *offset, { struct vpu_tracing_buffer_header *log; - if ((*offset + sizeof(*log)) > bo->base.size) + if ((*offset + sizeof(*log)) > ivpu_bo_size(bo)) return -EINVAL; - log = bo->kvaddr + *offset; + log = ivpu_bo_vaddr(bo) + *offset; if (log->vpu_canary_start != VPU_TRACING_BUFFER_CANARY) return -EINVAL; @@ -43,7 +43,7 @@ static int fw_log_ptr(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *offset, ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", log->header_size); return -EINVAL; } - if ((char *)log + log->size > (char *)bo->kvaddr + bo->base.size) { + if ((char *)log + log->size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) { ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size); return -EINVAL; } dif
Re: [PATCH v15 16/23] drm/shmem-helper: Use kref for vmap_use_count
On Sun, 27 Aug 2023 20:54:42 +0300 Dmitry Osipenko wrote: > Use kref helper for vmap_use_count to make refcounting consistent with > pages_use_count and pages_pin_count that use kref. This will allow to > optimize unlocked vmappings by skipping reservation locking if refcnt > 1. The core is taking the resv lock before calling ->v[un]map(), so switching to a kref sounds a bit premature/useless, unless there are plans to delegate the locking to the drivers. The only thing it brings is standard overflow/underflow checks. Not really sure it's worth transitioning to a kref for this field until we have a real use case. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 37 ++ > include/drm/drm_gem_shmem_helper.h | 2 +- > 2 files changed, 21 insertions(+), 18 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index 17a0177acb5d..d96fee3d6166 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -144,7 +144,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > } else if (!shmem->imported_sgt) { > dma_resv_lock(shmem->base.resv, NULL); > > - drm_WARN_ON(obj->dev, shmem->vmap_use_count); > + drm_WARN_ON(obj->dev, kref_read(&shmem->vmap_use_count)); > > if (shmem->sgt) { > dma_unmap_sgtable(obj->dev->dev, shmem->sgt, > @@ -359,23 +359,25 @@ int drm_gem_shmem_vmap_locked(struct > drm_gem_shmem_object *shmem, > > dma_resv_assert_held(shmem->base.resv); > > - if (shmem->vmap_use_count++ > 0) { > + if (kref_get_unless_zero(&shmem->vmap_use_count)) { > iosys_map_set_vaddr(map, shmem->vaddr); > return 0; > } > > ret = drm_gem_shmem_pin_locked(shmem); > if (ret) > - goto err_zero_use; > + return ret; > > if (shmem->map_wc) > prot = pgprot_writecombine(prot); > shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT, > VM_MAP, prot); > - if (!shmem->vaddr) > + if (!shmem->vaddr) { > ret = -ENOMEM; > - else > + } else { > iosys_map_set_vaddr(map, shmem->vaddr); > + kref_init(&shmem->vmap_use_count); > + } > } > > if (ret) { > @@ -388,13 +390,22 @@ int drm_gem_shmem_vmap_locked(struct > drm_gem_shmem_object *shmem, > err_put_pages: > if (!obj->import_attach) > drm_gem_shmem_unpin_locked(shmem); > -err_zero_use: > - shmem->vmap_use_count = 0; > > return ret; > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_vmap_locked); > > +static void drm_gem_shmem_kref_vunmap(struct kref *kref) > +{ > + struct drm_gem_shmem_object *shmem; > + > + shmem = container_of(kref, struct drm_gem_shmem_object, > + vmap_use_count); > + > + vunmap(shmem->vaddr); > + drm_gem_shmem_unpin_locked(shmem); > +} > + > /* > * drm_gem_shmem_vunmap_locked - Unmap a virtual mapping for a shmem GEM > object > * @shmem: shmem GEM object > @@ -416,15 +427,7 @@ void drm_gem_shmem_vunmap_locked(struct > drm_gem_shmem_object *shmem, > dma_buf_vunmap(obj->import_attach->dmabuf, map); > } else { > dma_resv_assert_held(shmem->base.resv); > - > - if (drm_WARN_ON_ONCE(obj->dev, !shmem->vmap_use_count)) > - return; > - > - if (--shmem->vmap_use_count > 0) > - return; > - > - vunmap(shmem->vaddr); > - drm_gem_shmem_unpin_locked(shmem); > + kref_put(&shmem->vmap_use_count, drm_gem_shmem_kref_vunmap); > } > > shmem->vaddr = NULL; > @@ -663,7 +666,7 @@ void drm_gem_shmem_print_info(const struct > drm_gem_shmem_object *shmem, > return; > > drm_printf_indent(p, indent, "pages_use_count=%u\n", > kref_read(&shmem->pages_use_count)); > - drm_printf_indent(p, indent, "vmap_use_count=%u\n", > shmem->vmap_use_count); > + drm_printf_indent(p, indent, "vmap_use_count=%u\n", > kref_read(&shmem->vmap_use_count)); > drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr); > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_print_info); > diff --git a/include/drm/drm_gem_shmem_helper.h > b/include/drm/drm_gem_shmem_helper.h > index 400ecd63f45f..0e0ccd380f66 100644 > --- a/include/drm/drm_gem_shmem_helper.h > +++ b/include/drm/drm_gem_shmem_helper.h > @@ -81,7 +81,7 @@ struct drm_gem_shmem_object { >* Reference count on the virtual address. >* The address are un-mapped when the count reaches zero. >*/ > - unsigned
Re: [PATCH v15 17/23] drm/shmem-helper: Add and use drm_gem_shmem_resv_assert_held() helper
On Sun, 27 Aug 2023 20:54:43 +0300 Dmitry Osipenko wrote: > In a preparation of adding drm-shmem memory shrinker, move all reservation > locking lockdep checks to use new drm_gem_shmem_resv_assert_held() that > will resolve spurious lockdep warning about wrong locking order vs > fs_reclam code paths during freeing of shmem GEM, where lockdep isn't > aware that it's impossible to have locking contention with the fs_reclam > at this special time. > > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 37 +- > 1 file changed, 25 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index d96fee3d6166..ca5da976aafa 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -128,6 +128,23 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct > drm_device *dev, size_t > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_create); > > +static void drm_gem_shmem_resv_assert_held(struct drm_gem_shmem_object > *shmem) > +{ > + /* > + * Destroying the object is a special case.. drm_gem_shmem_free() > + * calls many things that WARN_ON if the obj lock is not held. But > + * acquiring the obj lock in drm_gem_shmem_free() can cause a locking > + * order inversion between reservation_ww_class_mutex and fs_reclaim. > + * > + * This deadlock is not actually possible, because no one should > + * be already holding the lock when drm_gem_shmem_free() is called. > + * Unfortunately lockdep is not aware of this detail. So when the > + * refcount drops to zero, we pretend it is already locked. > + */ > + if (kref_read(&shmem->base.refcount)) > + drm_gem_shmem_resv_assert_held(shmem); > +} > + > /** > * drm_gem_shmem_free - Free resources associated with a shmem GEM object > * @shmem: shmem GEM object to free > @@ -142,8 +159,6 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > if (obj->import_attach) { > drm_prime_gem_destroy(obj, shmem->sgt); > } else if (!shmem->imported_sgt) { > - dma_resv_lock(shmem->base.resv, NULL); > - > drm_WARN_ON(obj->dev, kref_read(&shmem->vmap_use_count)); > > if (shmem->sgt) { > @@ -156,8 +171,6 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > drm_gem_shmem_put_pages_locked(shmem); AFAICT, drm_gem_shmem_put_pages_locked() is the only function that's called in the free path and would complain about resv-lock not being held. I think I'd feel more comfortable if we were adding a drm_gem_shmem_free_pages() function that did everything drm_gem_shmem_put_pages_locked() does except for the lock_held() check and the refcount dec, and have it called here (and in drm_gem_shmem_put_pages_locked()). This way we can keep using dma_resv_assert_held() instead of having our own variant. > > drm_WARN_ON(obj->dev, kref_read(&shmem->pages_use_count)); > - > - dma_resv_unlock(shmem->base.resv); > } > > drm_gem_object_release(obj); > @@ -170,7 +183,7 @@ static int drm_gem_shmem_get_pages_locked(struct > drm_gem_shmem_object *shmem) > struct drm_gem_object *obj = &shmem->base; > struct page **pages; > > - dma_resv_assert_held(shmem->base.resv); > + drm_gem_shmem_resv_assert_held(shmem); > > if (kref_get_unless_zero(&shmem->pages_use_count)) > return 0; > @@ -228,7 +241,7 @@ static void drm_gem_shmem_kref_release_pages(struct kref > *kref) > */ > void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem) > { > - dma_resv_assert_held(shmem->base.resv); > + drm_gem_shmem_resv_assert_held(shmem); > > kref_put(&shmem->pages_use_count, drm_gem_shmem_kref_release_pages); > } > @@ -252,7 +265,7 @@ static int drm_gem_shmem_pin_locked(struct > drm_gem_shmem_object *shmem) > { > int ret; > > - dma_resv_assert_held(shmem->base.resv); > + drm_gem_shmem_resv_assert_held(shmem); > > if (kref_get_unless_zero(&shmem->pages_pin_count)) > return 0; > @@ -276,7 +289,7 @@ static void drm_gem_shmem_kref_unpin_pages(struct kref > *kref) > > static void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem) > { > - dma_resv_assert_held(shmem->base.resv); > + drm_gem_shmem_resv_assert_held(shmem); > > kref_put(&shmem->pages_pin_count, drm_gem_shmem_kref_unpin_pages); > } > @@ -357,7 +370,7 @@ int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object > *shmem, > } else { > pgprot_t prot = PAGE_KERNEL; > > - dma_resv_assert_held(shmem->base.resv); > + drm_gem_shmem_resv_assert_held(shmem); > > if (kref_get_unless_zero(&shmem->vmap_use_count)) { > iosys_map_set_vaddr(map, shmem->vaddr); > @@ -426,7
Re: [PATCH v15 11/23] dma-resv: Add kref_put_dma_resv()
Am 27.08.23 um 19:54 schrieb Dmitry Osipenko: Add simple kref_put_dma_resv() helper that wraps around kref_put_ww_mutex() for drivers that needs to lock dma-resv on kref_put(). It's not possible to easily add this helper to kref.h because of the headers inclusion dependency, hence add it to dma-resv.h. I was never really a big fan of kref_put_mutex() in the first place. The main advantage comes from the included memory barrier, but this actually doesn't work like most people think it works and is usually pretty dangerous. And IIRC this was done because of the some special behavior mutexes have with memory barriers and that isn't necessary with ww-mutex. Christian. Signed-off-by: Dmitry Osipenko --- include/linux/dma-resv.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 8d0e34dad446..c5cf302e4194 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -464,6 +465,14 @@ static inline void dma_resv_unlock(struct dma_resv *obj) ww_mutex_unlock(&obj->lock); } +static inline int kref_put_dma_resv(struct kref *kref, + void (*release)(struct kref *kref), + struct dma_resv *resv, + struct ww_acquire_ctx *ctx) +{ + return kref_put_ww_mutex(kref, release, &resv->lock, ctx); +} + void dma_resv_init(struct dma_resv *obj); void dma_resv_fini(struct dma_resv *obj); int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences);
[PATCH 6.4 073/129] drm/i915: Fix HPD polling, reenabling the output poll work as needed
6.4-stable review patch. If anyone has any objections, please let me know. -- From: Imre Deak commit 1dcc437427bbcebc8381226352f7ade08a271191 upstream. After the commit in the Fixes: line below, HPD polling stopped working on i915, since after that change calling drm_kms_helper_poll_enable() doesn't restart drm_mode_config::output_poll_work if the work was stopped (no connectors needing polling) and enabling polling for a connector (during runtime suspend or detecting an HPD IRQ storm). After the above change calling drm_kms_helper_poll_enable() is a nop after it's been called already and polling for some connectors was disabled/re-enabled. Fix this by calling drm_kms_helper_poll_reschedule() added in the previous patch instead, which reschedules the work whenever expected. Fixes: d33a54e3991d ("drm/probe_helper: sort out poll_running vs poll_enabled") CC: sta...@vger.kernel.org # 6.4+ Cc: Dmitry Baryshkov Cc: dri-devel@lists.freedesktop.org Reviewed-by: Jouni Högander Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20230822113015.41224-2-imre.d...@intel.com (cherry picked from commit 50452f2f76852322620b63e62922b85e955abe94) Signed-off-by: Rodrigo Vivi Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/display/intel_hotplug.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -210,7 +210,7 @@ intel_hpd_irq_storm_switch_to_polling(st /* Enable polling and queue hotplug re-enabling. */ if (hpd_disabled) { - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mod_delayed_work(system_wq, &dev_priv->display.hotplug.reenable_work, msecs_to_jiffies(HPD_STORM_REENABLE_DELAY)); } @@ -644,7 +644,7 @@ static void i915_hpd_poll_init_work(stru drm_connector_list_iter_end(&conn_iter); if (enabled) - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mutex_unlock(&dev_priv->drm.mode_config.mutex);
[PATCH 6.4 069/129] drm: Add an HPD poll helper to reschedule the poll work
6.4-stable review patch. If anyone has any objections, please let me know. -- From: Imre Deak commit a94e7ccfc400c024976f3c2f31689ed843498b7c upstream. Add a helper to reschedule drm_mode_config::output_poll_work after polling has been enabled for a connector (and needing a reschedule, since previously polling was disabled for all connectors and hence output_poll_work was not running). This is needed by the next patch fixing HPD polling on i915. CC: sta...@vger.kernel.org # 6.4+ Cc: Dmitry Baryshkov Cc: dri-devel@lists.freedesktop.org Reviewed-by: Jouni Högander Reviewed-by: Dmitry Baryshkov Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20230822113015.41224-1-imre.d...@intel.com (cherry picked from commit fe2352fd64029918174de4b460dfe6df0c6911cd) Signed-off-by: Rodrigo Vivi Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_probe_helper.c | 68 -- include/drm/drm_probe_helper.h | 1 + 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 2fb9bf901a2c..3f479483d7d8 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -262,6 +262,26 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev) } #define DRM_OUTPUT_POLL_PERIOD (10*HZ) +static void reschedule_output_poll_work(struct drm_device *dev) +{ + unsigned long delay = DRM_OUTPUT_POLL_PERIOD; + + if (dev->mode_config.delayed_event) + /* +* FIXME: +* +* Use short (1s) delay to handle the initial delayed event. +* This delay should not be needed, but Optimus/nouveau will +* fail in a mysterious way if the delayed event is handled as +* soon as possible like it is done in +* drm_helper_probe_single_connector_modes() in case the poll +* was enabled before. +*/ + delay = HZ; + + schedule_delayed_work(&dev->mode_config.output_poll_work, delay); +} + /** * drm_kms_helper_poll_enable - re-enable output polling. * @dev: drm_device @@ -279,37 +299,41 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev) */ void drm_kms_helper_poll_enable(struct drm_device *dev) { - bool poll = false; - unsigned long delay = DRM_OUTPUT_POLL_PERIOD; - if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll || dev->mode_config.poll_running) return; - poll = drm_kms_helper_enable_hpd(dev); - - if (dev->mode_config.delayed_event) { - /* -* FIXME: -* -* Use short (1s) delay to handle the initial delayed event. -* This delay should not be needed, but Optimus/nouveau will -* fail in a mysterious way if the delayed event is handled as -* soon as possible like it is done in -* drm_helper_probe_single_connector_modes() in case the poll -* was enabled before. -*/ - poll = true; - delay = HZ; - } - - if (poll) - schedule_delayed_work(&dev->mode_config.output_poll_work, delay); + if (drm_kms_helper_enable_hpd(dev) || + dev->mode_config.delayed_event) + reschedule_output_poll_work(dev); dev->mode_config.poll_running = true; } EXPORT_SYMBOL(drm_kms_helper_poll_enable); +/** + * drm_kms_helper_poll_reschedule - reschedule the output polling work + * @dev: drm_device + * + * This function reschedules the output polling work, after polling for a + * connector has been enabled. + * + * Drivers must call this helper after enabling polling for a connector by + * setting %DRM_CONNECTOR_POLL_CONNECT / %DRM_CONNECTOR_POLL_DISCONNECT flags + * in drm_connector::polled. Note that after disabling polling by clearing these + * flags for a connector will stop the output polling work automatically if + * the polling is disabled for all other connectors as well. + * + * The function can be called only after polling has been enabled by calling + * drm_kms_helper_poll_init() / drm_kms_helper_poll_enable(). + */ +void drm_kms_helper_poll_reschedule(struct drm_device *dev) +{ + if (dev->mode_config.poll_running) + reschedule_output_poll_work(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_reschedule); + static enum drm_connector_status drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) { diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index 4977e0ab72db..fad3c4003b2b 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -25,6 +25,7 @@ void drm_kms_helper_connector_hotplug_event(struct drm_connector *connector); void drm_kms_helper_poll_disable(struct drm
Re: [PATCH v2 19/34] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
On Mon, 28 Aug 2023 09:45:44 +0100 Joshua Ashton wrote: > Degamma has always been on the plane on AMD. CRTC DEGAMMA_LUT has actually > just been applying it to every plane pre-blend. I've never seen that documented anywhere. It has seemed obvious, that since we have KMS objects for planes and CRTCs, stuff on the CRTC does not do plane stuff before blending. That also has not been documented in the past, but it seemed the most logical choice. Even today https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#color-management-properties make no mention of whether they apply before or after blending. > Degamma makes no sense after blending anyway. If the goal is to allow blending in optical or other space, you are correct. However, APIs do not need to make sense to exist, like most of the options of "Colorspace" connector property. I have always thought the CRTC DEGAMMA only exists to allow the CRTC CTM to work in linear or other space. I have at times been puzzled by what the DEGAMMA and CTM are actually good for. > The entire point is for it to happen before blending to blend in linear > space. Otherwise DEGAMMA_LUT and REGAMMA_LUT are the exact same thing... The CRTC CTM is between CRTC DEGAMMA and CRTC GAMMA, meaning they are not interchangeable. I have literally believed that DRM KMS UAPI simply does not support blending in optical space, unless your framebuffers are in optical which no-one does, until the color management properties are added to KMS planes. This never even seemed weird, because non-linear blending is so common. So I have been misunderstanding the CRTC DEGAMMA property forever. Am I the only one? Do all drivers agree today at what point does CRTC DEGAMMA apply, before blending on all planes or after blending? Does anyone know of any doc about that? If drivers do not agree on the behaviour of a KMS property, then that property is useless for generic userspace. Thanks, pq > On Tuesday, 22 August 2023, Pekka Paalanen > wrote: > > On Thu, 10 Aug 2023 15:02:59 -0100 > > Melissa Wen wrote: > > > >> The next patch adds pre-blending degamma to AMD color mgmt pipeline, but > >> pre-blending degamma caps (DPP) is currently in use to provide DRM CRTC > >> atomic degamma or implict degamma on legacy gamma. Detach degamma usage > >> regarging CRTC color properties to manage plane and CRTC color > >> correction combinations. > >> > >> Reviewed-by: Harry Wentland > >> Signed-off-by: Melissa Wen > >> --- > >> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 59 +-- > >> 1 file changed, 41 insertions(+), 18 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > >> index 68e9f2c62f2e..74eb02655d96 100644 > >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > >> @@ -764,20 +764,9 @@ int amdgpu_dm_update_crtc_color_mgmt(struct > dm_crtc_state *crtc) > >> return 0; > >> } > >> > >> -/** > >> - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC > plane. > >> - * @crtc: amdgpu_dm crtc state > >> - * @dc_plane_state: target DC surface > >> - * > >> - * Update the underlying dc_stream_state's input transfer function > (ITF) in > >> - * preparation for hardware commit. The transfer function used depends > on > >> - * the preparation done on the stream for color management. > >> - * > >> - * Returns: > >> - * 0 on success. -ENOMEM if mem allocation fails. > >> - */ > >> -int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, > >> - struct dc_plane_state > *dc_plane_state) > >> +static int > >> +map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, > >> + struct dc_plane_state *dc_plane_state) > >> { > >> const struct drm_color_lut *degamma_lut; > >> enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; > >> @@ -800,8 +789,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct > dm_crtc_state *crtc, > >>°amma_size); > >> ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); > >> > >> - dc_plane_state->in_transfer_func->type = > >> - TF_TYPE_DISTRIBUTED_POINTS; > >> + dc_plane_state->in_transfer_func->type = > TF_TYPE_DISTRIBUTED_POINTS; > >> > >> /* > >>* This case isn't fully correct, but also fairly > >> @@ -837,7 +825,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct > dm_crtc_state *crtc, > >> degamma_lut, degamma_size); > >> if (r) > >> return r; > >> - } else if (crtc->cm_is_degamma_srgb) { > >> + } else { > >> /* > >>* For legacy gamma support we need the regamma input > >>* in linear space. Assume that the input is
Re: [PATCH v15 02/23] drm/shmem-helper: Use flag for tracking page count bumped by get_pages_sgt()
On Sun, 27 Aug 2023 20:54:28 +0300 Dmitry Osipenko wrote: > Use separate flag for tracking page count bumped by shmem->sgt to avoid > imbalanced page counter during of drm_gem_shmem_free() time. It's fragile > to assume that populated shmem->pages at a freeing time means that the > count was bumped by drm_gem_shmem_get_pages_sgt(), using a flag removes > the ambiguity. > > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 3 ++- > drivers/gpu/drm/lima/lima_gem.c| 1 + > include/drm/drm_gem_shmem_helper.h | 7 +++ > 3 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index 78d9cf2355a5..db20b9123891 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -152,7 +152,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > sg_free_table(shmem->sgt); > kfree(shmem->sgt); > } > - if (shmem->pages) > + if (shmem->got_sgt) > drm_gem_shmem_put_pages(shmem); Can't we just move this drm_gem_shmem_put_pages() call in the if (shmem->sgt) block? > > drm_WARN_ON(obj->dev, shmem->pages_use_count); > @@ -687,6 +687,7 @@ static struct sg_table > *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_ > if (ret) > goto err_free_sgt; > > + shmem->got_sgt = true; > shmem->sgt = sgt; > > return sgt; > diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c > index 4f9736e5f929..28602302c281 100644 > --- a/drivers/gpu/drm/lima/lima_gem.c > +++ b/drivers/gpu/drm/lima/lima_gem.c > @@ -89,6 +89,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm) > } > > *bo->base.sgt = sgt; > + bo->base.got_sgt = true; > > if (vm) { > ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT); > diff --git a/include/drm/drm_gem_shmem_helper.h > b/include/drm/drm_gem_shmem_helper.h > index ec70a98a8fe1..f87124629bb5 100644 > --- a/include/drm/drm_gem_shmem_helper.h > +++ b/include/drm/drm_gem_shmem_helper.h > @@ -73,6 +73,13 @@ struct drm_gem_shmem_object { >*/ > unsigned int vmap_use_count; > > + /** > + * @got_sgt: > + * > + * True if SG table was retrieved using drm_gem_shmem_get_pages_sgt() > + */ > + bool got_sgt : 1; > + > /** >* @imported_sgt: >*
Re: [PATCH v2] fs: clean up usage of noop_dirty_folio
On Mon 28-08-23 15:54:49, Xueshi Hu wrote: > In folio_mark_dirty(), it can automatically fallback to > noop_dirty_folio() if a_ops->dirty_folio is not registered. > > As anon_aops, dev_dax_aops and fb_deferred_io_aops becames empty, remove > them too. > > Signed-off-by: Xueshi Hu Looks good to me. Feel free to add: Reviewed-by: Jan Kara Honza > --- > Changes in v2: > - make noop_dirty_folio() inline as suggested by Matthew > - v1: > https://lore.kernel.org/linux-mm/zoxafrz9etovu...@infradead.org/T/#m073d45909b1df03ff09f382557dc4e84d0607c49 > > drivers/dax/device.c| 5 - > drivers/video/fbdev/core/fb_defio.c | 5 - > fs/aio.c| 1 - > fs/ext2/inode.c | 1 - > fs/ext4/inode.c | 1 - > fs/fuse/dax.c | 1 - > fs/hugetlbfs/inode.c| 1 - > fs/libfs.c | 5 - > fs/xfs/xfs_aops.c | 1 - > include/linux/pagemap.h | 1 - > mm/page-writeback.c | 18 +- > mm/secretmem.c | 1 - > mm/shmem.c | 1 - > mm/swap_state.c | 1 - > 14 files changed, 5 insertions(+), 38 deletions(-) > > diff --git a/drivers/dax/device.c b/drivers/dax/device.c > index 30665a3ff6ea..018aa9f88ec7 100644 > --- a/drivers/dax/device.c > +++ b/drivers/dax/device.c > @@ -345,10 +345,6 @@ static unsigned long dax_get_unmapped_area(struct file > *filp, > return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); > } > > -static const struct address_space_operations dev_dax_aops = { > - .dirty_folio= noop_dirty_folio, > -}; > - > static int dax_open(struct inode *inode, struct file *filp) > { > struct dax_device *dax_dev = inode_dax(inode); > @@ -358,7 +354,6 @@ static int dax_open(struct inode *inode, struct file > *filp) > dev_dbg(&dev_dax->dev, "trace\n"); > inode->i_mapping = __dax_inode->i_mapping; > inode->i_mapping->host = __dax_inode; > - inode->i_mapping->a_ops = &dev_dax_aops; > filp->f_mapping = inode->i_mapping; > filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping); > filp->f_sb_err = file_sample_sb_err(filp); > diff --git a/drivers/video/fbdev/core/fb_defio.c > b/drivers/video/fbdev/core/fb_defio.c > index 274f5d0fa247..08be3592281f 100644 > --- a/drivers/video/fbdev/core/fb_defio.c > +++ b/drivers/video/fbdev/core/fb_defio.c > @@ -221,10 +221,6 @@ static const struct vm_operations_struct > fb_deferred_io_vm_ops = { > .page_mkwrite = fb_deferred_io_mkwrite, > }; > > -static const struct address_space_operations fb_deferred_io_aops = { > - .dirty_folio= noop_dirty_folio, > -}; > - > int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) > { > vma->vm_ops = &fb_deferred_io_vm_ops; > @@ -307,7 +303,6 @@ void fb_deferred_io_open(struct fb_info *info, > { > struct fb_deferred_io *fbdefio = info->fbdefio; > > - file->f_mapping->a_ops = &fb_deferred_io_aops; > fbdefio->open_count++; > } > EXPORT_SYMBOL_GPL(fb_deferred_io_open); > diff --git a/fs/aio.c b/fs/aio.c > index 77e33619de40..4cf386f9cb1c 100644 > --- a/fs/aio.c > +++ b/fs/aio.c > @@ -484,7 +484,6 @@ static int aio_migrate_folio(struct address_space > *mapping, struct folio *dst, > #endif > > static const struct address_space_operations aio_ctx_aops = { > - .dirty_folio= noop_dirty_folio, > .migrate_folio = aio_migrate_folio, > }; > > diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c > index 75983215c7a1..ce191bdf1c78 100644 > --- a/fs/ext2/inode.c > +++ b/fs/ext2/inode.c > @@ -971,7 +971,6 @@ const struct address_space_operations ext2_aops = { > static const struct address_space_operations ext2_dax_aops = { > .writepages = ext2_dax_writepages, > .direct_IO = noop_direct_IO, > - .dirty_folio= noop_dirty_folio, > }; > > /* > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c > index 43775a6ca505..67c1710c01b0 100644 > --- a/fs/ext4/inode.c > +++ b/fs/ext4/inode.c > @@ -3561,7 +3561,6 @@ static const struct address_space_operations > ext4_da_aops = { > static const struct address_space_operations ext4_dax_aops = { > .writepages = ext4_dax_writepages, > .direct_IO = noop_direct_IO, > - .dirty_folio= noop_dirty_folio, > .bmap = ext4_bmap, > .swap_activate = ext4_iomap_swap_activate, > }; > diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c > index 8e74f278a3f6..50ca767cbd5e 100644 > --- a/fs/fuse/dax.c > +++ b/fs/fuse/dax.c > @@ -1326,7 +1326,6 @@ bool fuse_dax_inode_alloc(struct super_block *sb, > struct fuse_inode *fi) > static const struct address_space_operations fuse_dax_file_aops = { > .writepages = fuse
Re: [PATCH] drm: bridge: it66121: Fix invalid connector dereference
Hi Jai, Thanks for debugging the issue. On 25-Aug-23 16:32, Jai Luthra wrote: > Fix the NULL pointer dereference when no monitor is connected, and the > sound card is opened from userspace. > > Instead return an error as EDID information cannot be provided to > the sound framework if there is no connector attached. > > Fixes: e0fd83dbe924 ("drm: bridge: it66121: Add audio support") > Reported-by: Nishanth Menon > Closes: https://lore.kernel.org/all/20230825105849.crhon42qndxqif4i@gondola/ > Signed-off-by: Jai Luthra > --- > drivers/gpu/drm/bridge/ite-it66121.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/gpu/drm/bridge/ite-it66121.c > b/drivers/gpu/drm/bridge/ite-it66121.c > index 466641c77fe9..d6fa00dea464 100644 > --- a/drivers/gpu/drm/bridge/ite-it66121.c > +++ b/drivers/gpu/drm/bridge/ite-it66121.c > @@ -1446,6 +1446,11 @@ static int it66121_audio_get_eld(struct device *dev, > void *data, > { > struct it66121_ctx *ctx = dev_get_drvdata(dev); > > + if (!ctx->connector) { > + dev_dbg(dev, "No connector present, cannot provide EDID data"); > + return -EINVAL; > + } > + There are not many HDMI bridges that support codecs in the kernel, but upon a quick look, bridge/analogix/anx7625.c and bridge/synopsys/dw-hdmi* gracefully return a buffer of 0s when the connector is unavailable. I am not sure why that is done, but I also don't see the hdmi-codec driver handle the 0s situation properly. It is business as usual for the hdmi-codec. Did you come across some observation when you were testing? Regards Aradhya > mutex_lock(&ctx->lock); > > memcpy(buf, ctx->connector->eld, > > --- > base-commit: 6269320850097903b30be8f07a5c61d9f7592393 > change-id: 20230825-it66121_edid-6ee98517808b > > Best regards,
Re: [PATCH 1/2] dt-bindings: display/panel: Add AUO G156HAN04.0 LVDS display
On 28/08/2023 11:49, Elmar Albert wrote: > From: Elmar Albert > > Document support for the AUO G156HAN04.0 LVDS display. > > G156HAN04.0 is a Color Active Matrix Liquid Crystal Display composed of > a TFT LCD panel, a driver circuit, and LED backlight system. The screen > format is intended to supportthe 16:9 FHD, 1920(H) x 1080(V) screen > and 16.7M colors (RGB 8-bits ) with LED backlight driving circuit. > All input signals are LVDS interface compatible. > > G156HAN04.0 is designed for a display unit of notebook style > personal computer and industrial machine. > Acked-by: Krzysztof Kozlowski Best regards, Krzysztof
Re: [PATCH v15 01/23] drm/shmem-helper: Fix UAF in error path when freeing SGT of imported GEM
On Sun, 27 Aug 2023 20:54:27 +0300 Dmitry Osipenko wrote: > Freeing drm-shmem GEM right after creating it using > drm_gem_shmem_prime_import_sg_table() frees SGT of the imported dma-buf > and then dma-buf frees this SGT second time. > > The v3d_prime_import_sg_table() is example of a error code path where > dma-buf's SGT is freed by drm-shmem and then it's freed second time by > dma_buf_unmap_attachment() in drm_gem_prime_import_dev(). > > Add drm-shmem GEM flag telling that this is imported SGT shall not be > treated as own SGT, fixing the use-after-free bug. > > Cc: sta...@vger.kernel.org > Fixes: 2194a63a818d ("drm: Add library for shmem backed GEM objects") > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 3 ++- > include/drm/drm_gem_shmem_helper.h | 7 +++ > 2 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index a783d2245599..78d9cf2355a5 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -141,7 +141,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > > if (obj->import_attach) { > drm_prime_gem_destroy(obj, shmem->sgt); > - } else { > + } else if (!shmem->imported_sgt) { > dma_resv_lock(shmem->base.resv, NULL); > > drm_WARN_ON(obj->dev, shmem->vmap_use_count); > @@ -758,6 +758,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device > *dev, > return ERR_CAST(shmem); > > shmem->sgt = sgt; > + shmem->imported_sgt = true; I feel like adding more fields that can be used to do the is_imported() check is going to be even more confusing. Can we instead have /* drm_gem_shmem_prime_import_sg_table() can be called from a * driver specific ->import_sg_table() implementations that * have extra failable initialization steps. Assign * drm_gem_object::import_attach here (even though it's * assigned in drm_gem_prime_import_dev()), so we don't end up * with driver error paths calling drm_gem_shmem_free() with an * imported sg_table assigned to drm_gem_shmem_object::sgt and * drm_gem_object::import_attach left uninitialized. */ shmem->base.import_attach = attach; here? > > drm_dbg_prime(dev, "size = %zu\n", size); > > diff --git a/include/drm/drm_gem_shmem_helper.h > b/include/drm/drm_gem_shmem_helper.h > index bf0c31aa8fbe..ec70a98a8fe1 100644 > --- a/include/drm/drm_gem_shmem_helper.h > +++ b/include/drm/drm_gem_shmem_helper.h > @@ -73,6 +73,13 @@ struct drm_gem_shmem_object { >*/ > unsigned int vmap_use_count; > > + /** > + * @imported_sgt: > + * > + * True if SG table belongs to imported dma-buf. > + */ > + bool imported_sgt : 1; > + > /** >* @pages_mark_dirty_on_put: >*
Re: [PATCH v4 2/2] drm/bridge: Drop conditionals around of_node pointers
On Sat, Aug 26, 2023 at 08:19:01AM +0100, Biju Das wrote: > Having conditional around the of_node pointers turns out to make driver > code use ugly #ifdef and #if blocks. So drop the conditionals. ... > -#ifdef CONFIG_OF > /** @of_node: device node pointer to the bridge */ > struct device_node *of_node; > -#endif This simply has to be struct fwnode_handle to begin with. Can you convert the driver to use it? -- With Best Regards, Andy Shevchenko
Re: [PATCH v4 1/2] drm/bridge/analogix/anx78xx: Drop ID table
On Sat, Aug 26, 2023 at 08:19:00AM +0100, Biju Das wrote: > The driver has an ID table, but it uses the wrong API for retrieving match > data and that will lead to a crash, if it is instantiated by user space or > using ID. From this, there is no user for the ID table and let's drop it > from the driver as it saves some memory. Reviewed-by: Andy Shevchenko -- With Best Regards, Andy Shevchenko
Re: [PATCH v15 03/23] drm/gem: Change locked/unlocked postfix of drm_gem_v/unmap() function names
On Sun, 27 Aug 2023 20:54:29 +0300 Dmitry Osipenko wrote: > Make drm/gem API function names consistent by having locked function > use the _locked postfix in the name, while the unlocked variants don't > use the _unlocked postfix. Rename drm_gem_v/unmap() function names to > make them consistent with the rest of the API functions. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko Reviewed-by: Boris Brezillon > --- > drivers/gpu/drm/drm_client.c | 6 +++--- > drivers/gpu/drm/drm_gem.c| 20 ++-- > drivers/gpu/drm/drm_gem_framebuffer_helper.c | 6 +++--- > drivers/gpu/drm/drm_internal.h | 4 ++-- > drivers/gpu/drm/drm_prime.c | 4 ++-- > drivers/gpu/drm/lima/lima_sched.c| 4 ++-- > drivers/gpu/drm/panfrost/panfrost_dump.c | 4 ++-- > drivers/gpu/drm/panfrost/panfrost_perfcnt.c | 6 +++--- > include/drm/drm_gem.h| 4 ++-- > 9 files changed, 29 insertions(+), 29 deletions(-) > > diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c > index 037e36f2049c..29306657117a 100644 > --- a/drivers/gpu/drm/drm_client.c > +++ b/drivers/gpu/drm/drm_client.c > @@ -265,7 +265,7 @@ void drm_client_dev_restore(struct drm_device *dev) > static void drm_client_buffer_delete(struct drm_client_buffer *buffer) > { > if (buffer->gem) { > - drm_gem_vunmap_unlocked(buffer->gem, &buffer->map); > + drm_gem_vunmap(buffer->gem, &buffer->map); > drm_gem_object_put(buffer->gem); > } > > @@ -349,7 +349,7 @@ drm_client_buffer_vmap(struct drm_client_buffer *buffer, >* fd_install step out of the driver backend hooks, to make that >* final step optional for internal users. >*/ > - ret = drm_gem_vmap_unlocked(buffer->gem, map); > + ret = drm_gem_vmap(buffer->gem, map); > if (ret) > return ret; > > @@ -371,7 +371,7 @@ void drm_client_buffer_vunmap(struct drm_client_buffer > *buffer) > { > struct iosys_map *map = &buffer->map; > > - drm_gem_vunmap_unlocked(buffer->gem, map); > + drm_gem_vunmap(buffer->gem, map); > } > EXPORT_SYMBOL(drm_client_buffer_vunmap); > > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > index 6129b89bb366..fae5832bb0bd 100644 > --- a/drivers/gpu/drm/drm_gem.c > +++ b/drivers/gpu/drm/drm_gem.c > @@ -1173,7 +1173,7 @@ void drm_gem_unpin(struct drm_gem_object *obj) > obj->funcs->unpin(obj); > } > > -int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map) > +int drm_gem_vmap_locked(struct drm_gem_object *obj, struct iosys_map *map) > { > int ret; > > @@ -1190,9 +1190,9 @@ int drm_gem_vmap(struct drm_gem_object *obj, struct > iosys_map *map) > > return 0; > } > -EXPORT_SYMBOL(drm_gem_vmap); > +EXPORT_SYMBOL(drm_gem_vmap_locked); > > -void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) > +void drm_gem_vunmap_locked(struct drm_gem_object *obj, struct iosys_map *map) > { > dma_resv_assert_held(obj->resv); > > @@ -1205,27 +1205,27 @@ void drm_gem_vunmap(struct drm_gem_object *obj, > struct iosys_map *map) > /* Always set the mapping to NULL. Callers may rely on this. */ > iosys_map_clear(map); > } > -EXPORT_SYMBOL(drm_gem_vunmap); > +EXPORT_SYMBOL(drm_gem_vunmap_locked); > > -int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map) > +int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map) > { > int ret; > > dma_resv_lock(obj->resv, NULL); > - ret = drm_gem_vmap(obj, map); > + ret = drm_gem_vmap_locked(obj, map); > dma_resv_unlock(obj->resv); > > return ret; > } > -EXPORT_SYMBOL(drm_gem_vmap_unlocked); > +EXPORT_SYMBOL(drm_gem_vmap); > > -void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map > *map) > +void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) > { > dma_resv_lock(obj->resv, NULL); > - drm_gem_vunmap(obj, map); > + drm_gem_vunmap_locked(obj, map); > dma_resv_unlock(obj->resv); > } > -EXPORT_SYMBOL(drm_gem_vunmap_unlocked); > +EXPORT_SYMBOL(drm_gem_vunmap); > > /** > * drm_gem_lock_reservations - Sets up the ww context and acquires > diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c > b/drivers/gpu/drm/drm_gem_framebuffer_helper.c > index 3bdb6ba37ff4..3808f47310bf 100644 > --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c > +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c > @@ -362,7 +362,7 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb, struct > iosys_map *map, > ret = -EINVAL; > goto err_drm_gem_vunmap; > } > - ret = drm_gem_vmap_unlocked(obj, &map[i]); > + ret = drm_gem_vmap(obj, &map[i]); > if (ret) > goto err_drm_gem_vunmap; > } > @
Re: [PATCH v15 04/23] drm/gem: Add _locked postfix to functions that have unlocked counterpart
On Sun, 27 Aug 2023 20:54:30 +0300 Dmitry Osipenko wrote: > Add _locked postfix to drm_gem functions that have unlocked counterpart > functions to make GEM functions naming more consistent and intuitive in > regards to the locking requirements. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko Reviewed-by: Boris Brezillon > --- > drivers/gpu/drm/drm_gem.c | 6 +++--- > include/drm/drm_gem.h | 2 +- > 2 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > index fae5832bb0bd..8c0268944199 100644 > --- a/drivers/gpu/drm/drm_gem.c > +++ b/drivers/gpu/drm/drm_gem.c > @@ -1488,10 +1488,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, > EXPORT_SYMBOL(drm_gem_lru_scan); > > /** > - * drm_gem_evict - helper to evict backing pages for a GEM object > + * drm_gem_evict_locked - helper to evict backing pages for a GEM object > * @obj: obj in question > */ > -int drm_gem_evict(struct drm_gem_object *obj) > +int drm_gem_evict_locked(struct drm_gem_object *obj) > { > dma_resv_assert_held(obj->resv); > > @@ -1503,4 +1503,4 @@ int drm_gem_evict(struct drm_gem_object *obj) > > return 0; > } > -EXPORT_SYMBOL(drm_gem_evict); > +EXPORT_SYMBOL(drm_gem_evict_locked); > diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h > index f338f8cfacf7..e78e6d817451 100644 > --- a/include/drm/drm_gem.h > +++ b/include/drm/drm_gem.h > @@ -542,7 +542,7 @@ unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, > unsigned long *remaining, > bool (*shrink)(struct drm_gem_object *obj)); > > -int drm_gem_evict(struct drm_gem_object *obj); > +int drm_gem_evict_locked(struct drm_gem_object *obj); > > #ifdef CONFIG_LOCKDEP > /**
Re: [PATCH v4 2/2] drm/bridge: Drop conditionals around of_node pointers
Hi Biju, Thank you for the patch. On Sat, Aug 26, 2023 at 08:19:01AM +0100, Biju Das wrote: > Having conditional around the of_node pointers turns out to make driver > code use ugly #ifdef and #if blocks. So drop the conditionals. > > Suggested-by: Douglas Anderson > Signed-off-by: Biju Das > --- > v4: > * New patch > --- > drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 2 -- > include/drm/drm_bridge.h | 2 -- This should be split in two patches, one addressing drm_bridge.h (and likely referencing the commit that dropped the conditionals in struct device, as mentioned by Doug), and one for the drivers. > 2 files changed, 4 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > index 6169db73d2fe..ad8241758896 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > @@ -1231,9 +1231,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client) > > mutex_init(&anx78xx->lock); > > -#if IS_ENABLED(CONFIG_OF) > anx78xx->bridge.of_node = client->dev.of_node; > -#endif > > anx78xx->client = client; > i2c_set_clientdata(client, anx78xx); > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > index c339fc85fd07..d49d5c03df3e 100644 > --- a/include/drm/drm_bridge.h > +++ b/include/drm/drm_bridge.h > @@ -716,10 +716,8 @@ struct drm_bridge { > struct drm_encoder *encoder; > /** @chain_node: used to form a bridge chain */ > struct list_head chain_node; > -#ifdef CONFIG_OF > /** @of_node: device node pointer to the bridge */ > struct device_node *of_node; > -#endif > /** @list: to keep track of all added bridges */ > struct list_head list; > /** -- Regards, Laurent Pinchart
Re: [PATCH v15 08/23] drm/shmem-helper: Refactor locked/unlocked functions
On Sun, 27 Aug 2023 20:54:34 +0300 Dmitry Osipenko wrote: > Add locked and remove unlocked postfixes from drm-shmem function names, > making names consistent with the drm/gem core code. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko Reviewed-by: Boris Brezillon > --- > drivers/gpu/drm/drm_gem_shmem_helper.c| 64 +-- > drivers/gpu/drm/lima/lima_gem.c | 8 +-- > drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- > drivers/gpu/drm/panfrost/panfrost_gem.c | 6 +- > .../gpu/drm/panfrost/panfrost_gem_shrinker.c | 2 +- > drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- > drivers/gpu/drm/v3d/v3d_bo.c | 4 +- > drivers/gpu/drm/virtio/virtgpu_object.c | 4 +- > include/drm/drm_gem_shmem_helper.h| 36 +-- > 9 files changed, 64 insertions(+), 64 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index 575704f38808..f053dc511508 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -43,8 +43,8 @@ static const struct drm_gem_object_funcs > drm_gem_shmem_funcs = { > .pin = drm_gem_shmem_object_pin, > .unpin = drm_gem_shmem_object_unpin, > .get_sg_table = drm_gem_shmem_object_get_sg_table, > - .vmap = drm_gem_shmem_object_vmap, > - .vunmap = drm_gem_shmem_object_vunmap, > + .vmap = drm_gem_shmem_object_vmap_locked, > + .vunmap = drm_gem_shmem_object_vunmap_locked, > .mmap = drm_gem_shmem_object_mmap, > .vm_ops = &drm_gem_shmem_vm_ops, > }; > @@ -153,7 +153,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > kfree(shmem->sgt); > } > if (shmem->got_sgt) > - drm_gem_shmem_put_pages(shmem); > + drm_gem_shmem_put_pages_locked(shmem); > > drm_WARN_ON(obj->dev, shmem->pages_use_count); > > @@ -165,7 +165,7 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object > *shmem) > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_free); > > -static int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem) > +static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) > { > struct drm_gem_object *obj = &shmem->base; > struct page **pages; > @@ -199,12 +199,12 @@ static int drm_gem_shmem_get_pages(struct > drm_gem_shmem_object *shmem) > } > > /* > - * drm_gem_shmem_put_pages - Decrease use count on the backing pages for a > shmem GEM object > + * drm_gem_shmem_put_pages_locked - Decrease use count on the backing pages > for a shmem GEM object > * @shmem: shmem GEM object > * > * This function decreases the use count and puts the backing pages when use > drops to zero. > */ > -void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem) > +void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem) > { > struct drm_gem_object *obj = &shmem->base; > > @@ -226,7 +226,7 @@ void drm_gem_shmem_put_pages(struct drm_gem_shmem_object > *shmem) > shmem->pages_mark_accessed_on_put); > shmem->pages = NULL; > } > -EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages); > +EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages_locked); > > static int drm_gem_shmem_pin_locked(struct drm_gem_shmem_object *shmem) > { > @@ -234,7 +234,7 @@ static int drm_gem_shmem_pin_locked(struct > drm_gem_shmem_object *shmem) > > dma_resv_assert_held(shmem->base.resv); > > - ret = drm_gem_shmem_get_pages(shmem); > + ret = drm_gem_shmem_get_pages_locked(shmem); > > return ret; > } > @@ -243,7 +243,7 @@ static void drm_gem_shmem_unpin_locked(struct > drm_gem_shmem_object *shmem) > { > dma_resv_assert_held(shmem->base.resv); > > - drm_gem_shmem_put_pages(shmem); > + drm_gem_shmem_put_pages_locked(shmem); > } > > /** > @@ -293,7 +293,7 @@ void drm_gem_shmem_unpin(struct drm_gem_shmem_object > *shmem) > EXPORT_SYMBOL_GPL(drm_gem_shmem_unpin); > > /* > - * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object > + * drm_gem_shmem_vmap_locked - Create a virtual mapping for a shmem GEM > object > * @shmem: shmem GEM object > * @map: Returns the kernel virtual address of the SHMEM GEM object's backing > * store. > @@ -302,13 +302,13 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_unpin); > * exists for the buffer backing the shmem GEM object. It hides the > differences > * between dma-buf imported and natively allocated objects. > * > - * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap(). > + * Acquired mappings should be cleaned up by calling > drm_gem_shmem_vunmap_locked(). > * > * Returns: > * 0 on success or a negative error code on failure. > */ > -int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem, > -struct iosys_map *map) > +int drm_gem_shmem_vm
Re: [PATCH v4 2/2] drm/bridge: Drop conditionals around of_node pointers
On Mon, Aug 28, 2023 at 02:17:02PM +0300, Andy Shevchenko wrote: > On Sat, Aug 26, 2023 at 08:19:01AM +0100, Biju Das wrote: > > Having conditional around the of_node pointers turns out to make driver > > code use ugly #ifdef and #if blocks. So drop the conditionals. > > ... > > > -#ifdef CONFIG_OF > > /** @of_node: device node pointer to the bridge */ > > struct device_node *of_node; > > -#endif > > This simply has to be struct fwnode_handle to begin with. > Can you convert the driver to use it? While that's possibly a good idea, it will require touching all the bridge drivers that set this field, so I think it could be done separately. -- Regards, Laurent Pinchart
Re: [PATCH v15 09/23] drm/shmem-helper: Remove obsoleted is_iomem test
On Sun, 27 Aug 2023 20:54:35 +0300 Dmitry Osipenko wrote: > Everything that uses the mapped buffer should by agnostic to is_iomem. ^be > The only reason for the is_iomem test is that we're setting shmem->vaddr > to the returned map->vaddr. Now that the shmem->vaddr code is gone, remove > the obsoleted is_iomem test to clean up the code. > > Suggested-by: Thomas Zimmermann > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 6 -- > 1 file changed, 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index f053dc511508..d545d3d227d7 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -315,12 +315,6 @@ int drm_gem_shmem_vmap_locked(struct > drm_gem_shmem_object *shmem, > > if (obj->import_attach) { > ret = dma_buf_vmap(obj->import_attach->dmabuf, map); > - if (!ret) { > - if (drm_WARN_ON(obj->dev, map->is_iomem)) { > - dma_buf_vunmap(obj->import_attach->dmabuf, map); > - return -EIO; > - } > - } > } else { > pgprot_t prot = PAGE_KERNEL; >
Re: [PATCH v4 2/2] drm/bridge: Drop conditionals around of_node pointers
On Mon, Aug 28, 2023 at 02:29:21PM +0300, Laurent Pinchart wrote: > On Mon, Aug 28, 2023 at 02:17:02PM +0300, Andy Shevchenko wrote: > > On Sat, Aug 26, 2023 at 08:19:01AM +0100, Biju Das wrote: > > > Having conditional around the of_node pointers turns out to make driver > > > code use ugly #ifdef and #if blocks. So drop the conditionals. ... > > > -#ifdef CONFIG_OF > > > /** @of_node: device node pointer to the bridge */ > > > struct device_node *of_node; > > > -#endif > > > > This simply has to be struct fwnode_handle to begin with. > > Can you convert the driver to use it? > > While that's possibly a good idea, it will require touching all the > bridge drivers that set this field, so I think it could be done > separately. Okay. -- With Best Regards, Andy Shevchenko
Re: [PATCH v15 12/23] drm/shmem-helper: Add and use pages_pin_count
On Sun, 27 Aug 2023 20:54:38 +0300 Dmitry Osipenko wrote: > Add separate pages_pin_count for tracking of whether drm-shmem pages are > moveable or not. With the addition of memory shrinker support to drm-shmem, > the pages_use_count will no longer determine whether pages are hard-pinned > in memory, but whether pages exit and are soft-pinned (and could be swapped > out). The pages_pin_count > 1 will hard-pin pages in memory. > > Suggested-by: Boris Brezillon > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/drm_gem_shmem_helper.c | 22 +- > include/drm/drm_gem_shmem_helper.h | 10 ++ > 2 files changed, 27 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c > b/drivers/gpu/drm/drm_gem_shmem_helper.c > index d545d3d227d7..1a7e5c332fd8 100644 > --- a/drivers/gpu/drm/drm_gem_shmem_helper.c > +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c > @@ -234,14 +234,22 @@ static int drm_gem_shmem_pin_locked(struct > drm_gem_shmem_object *shmem) > > dma_resv_assert_held(shmem->base.resv); > > + if (kref_get_unless_zero(&shmem->pages_pin_count)) > + return 0; > + > ret = drm_gem_shmem_get_pages_locked(shmem); > + if (!ret) > + kref_init(&shmem->pages_pin_count); > > return ret; > } > > -static void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem) > +static void drm_gem_shmem_kref_unpin_pages(struct kref *kref) > { > - dma_resv_assert_held(shmem->base.resv); > + struct drm_gem_shmem_object *shmem; > + > + shmem = container_of(kref, struct drm_gem_shmem_object, > + pages_pin_count); > > drm_gem_shmem_put_pages_locked(shmem); > } > @@ -263,6 +271,9 @@ int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem) > > drm_WARN_ON(obj->dev, obj->import_attach); > > + if (kref_get_unless_zero(&shmem->pages_pin_count)) > + return 0; > + > ret = dma_resv_lock_interruptible(shmem->base.resv, NULL); > if (ret) > return ret; > @@ -286,9 +297,10 @@ void drm_gem_shmem_unpin(struct drm_gem_shmem_object > *shmem) > > drm_WARN_ON(obj->dev, obj->import_attach); > > - dma_resv_lock(shmem->base.resv, NULL); > - drm_gem_shmem_unpin_locked(shmem); > - dma_resv_unlock(shmem->base.resv); > + if (kref_put_dma_resv(&shmem->pages_pin_count, > + drm_gem_shmem_kref_unpin_pages, > + obj->resv, NULL)) > + dma_resv_unlock(obj->resv); > } > EXPORT_SYMBOL_GPL(drm_gem_shmem_unpin); > > diff --git a/include/drm/drm_gem_shmem_helper.h > b/include/drm/drm_gem_shmem_helper.h > index ec2d8b24e3cf..afb7cd671e2a 100644 > --- a/include/drm/drm_gem_shmem_helper.h > +++ b/include/drm/drm_gem_shmem_helper.h > @@ -39,6 +39,16 @@ struct drm_gem_shmem_object { >*/ > unsigned int pages_use_count; > > + /** > + * @pages_pin_count: > + * > + * Reference count on the pinned pages table. > + * The pages allowed to be evicted and purged by memory > + * shrinker only when the count is zero, otherwise pages > + * are hard-pinned in memory. > + */ > + struct kref pages_pin_count; I know it's tempting to use kref for the pages use/pin count, but I'm wondering if we wouldn't be better using a refcount_t, which provides overflow/underflow protection while still letting us control how we want to handle the locking for 0 <-> 1 transitions. By doing that, we avoid introducing core locking changes that might be more controversial/longer to get accepted. Besides, I suspect the resulting code (the one using a refcount_t) won't be more verbose/complicated (no release functions needed if you don't use kref_put(), which makes things closer to what we have right now). > + > /** >* @madv: State for madvise >*
Re: [PATCH v4 1/2] drm/bridge/analogix/anx78xx: Drop ID table
On Saturday, August 26, 2023 04:19 -03, Biju Das wrote: > The driver has an ID table, but it uses the wrong API for retrieving match > data and that will lead to a crash, if it is instantiated by user space or > using ID. From this, there is no user for the ID table and let's drop it > from the driver as it saves some memory. > > Signed-off-by: Biju Das > Reviewed-by: Douglas Anderson > Reviewed-by: Laurent Pinchart Reviewed-by: Helen Koike > --- > v3->v4: > * Added Rb tag from Laurent and Douglas Anderson. > v2->v3: > * Updated commit header. > v1->v2: > * Dropped ID table support. > --- > drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 7 --- > 1 file changed, 7 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > index 800555aef97f..6169db73d2fe 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > @@ -1367,12 +1367,6 @@ static void anx78xx_i2c_remove(struct i2c_client > *client) > kfree(anx78xx->edid); > } > > -static const struct i2c_device_id anx78xx_id[] = { > - { "anx7814", 0 }, > - { /* sentinel */ } > -}; > -MODULE_DEVICE_TABLE(i2c, anx78xx_id); > - > static const struct of_device_id anx78xx_match_table[] = { > { .compatible = "analogix,anx7808", .data = anx7808_i2c_addresses }, > { .compatible = "analogix,anx7812", .data = anx781x_i2c_addresses }, > @@ -1389,7 +1383,6 @@ static struct i2c_driver anx78xx_driver = { > }, > .probe = anx78xx_i2c_probe, > .remove = anx78xx_i2c_remove, > - .id_table = anx78xx_id, > }; > module_i2c_driver(anx78xx_driver); > > -- > 2.25.1 >
Re: [PATCH v2] fs: clean up usage of noop_dirty_folio
Looks good: Reviewed-by: Christoph Hellwig
Re: [PATCH v2] fs: clean up usage of noop_dirty_folio
On Mon, Aug 28, 2023 at 03:54:49PM +0800, Xueshi Hu wrote: > In folio_mark_dirty(), it can automatically fallback to > noop_dirty_folio() if a_ops->dirty_folio is not registered. > > As anon_aops, dev_dax_aops and fb_deferred_io_aops becames empty, remove > them too. > > Signed-off-by: Xueshi Hu Reviewed-by: Matthew Wilcox (Oracle)
[PATCH v3 0/7] GPU workload hints for better performance
AMDGPU SOCs supports dynamic workload based power profiles, which can provide fine-tuned performance for a particular type of workload. This patch series adds an interface to set/reset these power profiles based on the submitted job. The driver can dynamically switch the power profiles based on submitted job. This can optimize the power performance when the particular workload is on. v2: - Splitting workload_profile_set and workload_profile_put into two separate patches. - Addressed review comment. - Added new suspend function. - Added patch to switches the GPU workload mode for KFD. v3: - Addressed all review comment. - Changed the function name from *_set() to *_get(). - Now clearing all the profile in work handler. - Added *_clear_all function to clear all the power profile. Arvind Yadav (7): drm/amdgpu: Added init/fini functions for workload drm/amdgpu: Add new function to set GPU power profile drm/amdgpu: Add new function to put GPU power profile drm/amdgpu: Add suspend function to clear the GPU power profile. drm/amdgpu: Set/Reset GPU workload profile drm/amdgpu: switch workload context to/from compute Revert "drm/amd/amdgpu: switch on/off vcn power profile mode" drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c| 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 226 ++ drivers/gpu/drm/amd/include/amdgpu_workload.h | 61 + 8 files changed, 309 insertions(+), 16 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c create mode 100644 drivers/gpu/drm/amd/include/amdgpu_workload.h -- 2.34.1
[PATCH v3 1/7] drm/amdgpu: Added init/fini functions for workload
The'struct amdgpu_smu_workload' initialization/cleanup functions is added by this patch. v2: - Splitting big patch into separate patches. - Added new fini function. v3: - Addressed review comment to change 'power_profile_work' instead of 'smu_delayed_work'. Cc: Christian Koenig Cc: Alex Deucher Reviewed-by: Shashank Sharma Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 4 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 44 +++ drivers/gpu/drm/amd/include/amdgpu_workload.h | 53 +++ 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c create mode 100644 drivers/gpu/drm/amd/include/amdgpu_workload.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 415a7fa395c4..6a9e187d61e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -60,7 +60,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ - amdgpu_ring_mux.o + amdgpu_ring_mux.o amdgpu_workload.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 02b827785e39..1939fa1af8a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -107,6 +107,7 @@ #include "amdgpu_fdinfo.h" #include "amdgpu_mca.h" #include "amdgpu_ras.h" +#include "amdgpu_workload.h" #define MAX_GPU_INSTANCE 16 @@ -1050,6 +1051,8 @@ struct amdgpu_device { booljob_hang; booldc_enabled; + + struct amdgpu_smu_workload smu_workload; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5c7d40873ee2..cd3bf641b630 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2243,6 +2243,8 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) adev->cg_flags &= amdgpu_cg_mask; adev->pg_flags &= amdgpu_pg_mask; + amdgpu_workload_profile_init(adev); + return 0; } @@ -2890,6 +2892,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) { int i, r; + amdgpu_workload_profile_fini(adev); + if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done) amdgpu_virt_release_ras_err_handler_data(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c new file mode 100644 index ..32166f482f77 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "amdgpu.h" + +void amdgpu_workload_profile_init(struct amdgpu_device *adev) +{ + adev->smu_workload.adev = adev; + adev->smu_workload.submit_workload_status = 0; + adev->smu_workload.initialized = true; + + mutex_init(&adev->smu_workload.workload_lock); +} + +void amdgpu_workload_profile_fini(struct amdgpu_device *adev) +{ + if (!adev->smu_workload.initialized) + return; + + adev->smu_workload.submit_workload_status = 0; + adev->smu_workload.initialized = false; + mutex_destroy(&adev->smu_workload.workload_lock); +} diff --git a/drivers/gpu/drm/amd/include/amdgpu_workload.h b/drivers/gpu/drm/amd/inc
[PATCH v3 2/7] drm/amdgpu: Add new function to set GPU power profile
This patch adds a function which will change the GPU power profile based on a submitted job. This can optimize the power performance when the workload is on. v2: - Splitting workload_profile_set and workload_profile_put into two separate patches. - Addressed review comment. v3: - Adressed all the review comment. - Changing the function name from *_set() to *_get(). - Now setting a power profile when refcount is zero. Cc: Shashank Sharma Cc: Christian Koenig Cc: Alex Deucher Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 59 +++ drivers/gpu/drm/amd/include/amdgpu_workload.h | 3 + 2 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c index 32166f482f77..67eacaac6c9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c @@ -24,6 +24,65 @@ #include "amdgpu.h" +static enum PP_SMC_POWER_PROFILE +ring_to_power_profile(uint32_t ring_type) +{ + switch (ring_type) { + case AMDGPU_RING_TYPE_GFX: + return PP_SMC_POWER_PROFILE_FULLSCREEN3D; + case AMDGPU_RING_TYPE_COMPUTE: + return PP_SMC_POWER_PROFILE_COMPUTE; + case AMDGPU_RING_TYPE_UVD: + case AMDGPU_RING_TYPE_VCE: + case AMDGPU_RING_TYPE_UVD_ENC: + case AMDGPU_RING_TYPE_VCN_DEC: + case AMDGPU_RING_TYPE_VCN_ENC: + case AMDGPU_RING_TYPE_VCN_JPEG: + return PP_SMC_POWER_PROFILE_VIDEO; + default: + return PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + } +} + +static int +amdgpu_power_profile_set(struct amdgpu_device *adev, +enum PP_SMC_POWER_PROFILE profile) +{ + int ret = amdgpu_dpm_switch_power_profile(adev, profile, true); + + if (!ret) { + /* Set the bit for the submitted workload profile */ + set_bit(profile, &adev->smu_workload.submit_workload_status); + } + + return ret; +} + +void amdgpu_workload_profile_get(struct amdgpu_device *adev, +uint32_t ring_type) +{ + struct amdgpu_smu_workload *workload = &adev->smu_workload; + enum PP_SMC_POWER_PROFILE profile = ring_to_power_profile(ring_type); + int ret, refcount; + + if (profile == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT) + return; + + mutex_lock(&workload->workload_lock); + + refcount = atomic_read(&workload->power_profile_ref[profile]); + if (!refcount) { + ret = amdgpu_power_profile_set(adev, profile); + if (ret) { + DRM_WARN("Failed to set workload profile to %s, error = %d\n", +amdgpu_workload_mode_name[profile], ret); + } + } + + atomic_inc(&adev->smu_workload.power_profile_ref[profile]); + mutex_unlock(&workload->workload_lock); +} + void amdgpu_workload_profile_init(struct amdgpu_device *adev) { adev->smu_workload.adev = adev; diff --git a/drivers/gpu/drm/amd/include/amdgpu_workload.h b/drivers/gpu/drm/amd/include/amdgpu_workload.h index dc12448764a3..5fc0bc2a74a4 100644 --- a/drivers/gpu/drm/amd/include/amdgpu_workload.h +++ b/drivers/gpu/drm/amd/include/amdgpu_workload.h @@ -46,6 +46,9 @@ static const char * const amdgpu_workload_mode_name[] = { "Window3D" }; +void amdgpu_workload_profile_get(struct amdgpu_device *adev, +uint32_t ring_type); + void amdgpu_workload_profile_init(struct amdgpu_device *adev); void amdgpu_workload_profile_fini(struct amdgpu_device *adev); -- 2.34.1
[PATCH v3 3/7] drm/amdgpu: Add new function to put GPU power profile
This patch adds a function which will clear the GPU power profile after job finished. This is how it works: - schedular will set the GPU power profile based on ring_type. - Schedular will clear the GPU Power profile once job finished. - Here, the *_workload_profile_set function will set the GPU power profile and the *_workload_profile_put function will schedule the smu_delayed_work task after 100ms delay. This smu_delayed_work task will clear a GPU power profile if any new jobs are not scheduled within 100 ms. But if any new job comes within 100ms then the *_workload_profile_set function will cancel this work and set the GPU power profile based on preferences. v2: - Splitting workload_profile_set and workload_profile_put into two separate patches. - Addressed review comment. v3: - Adressed all the review comment. - Now clearing all the profile in work handler. - Added *_clear_all function to clear all the power profile. - scheduling delay work to clear the power profile when refcount becomes zero. Cc: Shashank Sharma Cc: Christian Koenig Cc: Alex Deucher Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 118 +- drivers/gpu/drm/amd/include/amdgpu_workload.h | 3 + 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c index 67eacaac6c9b..fbe86ee5b8bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c @@ -24,6 +24,9 @@ #include "amdgpu.h" +/* 100 millsecond timeout */ +#define SMU_IDLE_TIMEOUT msecs_to_jiffies(100) + static enum PP_SMC_POWER_PROFILE ring_to_power_profile(uint32_t ring_type) { @@ -58,16 +61,111 @@ amdgpu_power_profile_set(struct amdgpu_device *adev, return ret; } +static int +amdgpu_power_profile_clear(struct amdgpu_device *adev, + enum PP_SMC_POWER_PROFILE profile) +{ + int ret = amdgpu_dpm_switch_power_profile(adev, profile, false); + + if (!ret) { + /* Clear the bit for the submitted workload profile */ + clear_bit(profile, &adev->smu_workload.submit_workload_status); + } + + return ret; +} + +static void +amdgpu_power_profile_clear_all(struct amdgpu_device *adev, + struct amdgpu_smu_workload *workload) +{ + int ret; + int profile = PP_SMC_POWER_PROFILE_COMPUTE; + + cancel_delayed_work_sync(&workload->power_profile_work); + mutex_lock(&workload->workload_lock); + + /* Clear all the GPU power profile*/ + for (; profile > 0; profile--) { + atomic_set(&workload->power_profile_ref[profile], 0); + ret = amdgpu_power_profile_clear(adev, profile); + if (ret) { + DRM_WARN("Failed to clear workload %s,error = %d\n", +amdgpu_workload_mode_name[profile], ret); + } + } + + workload->submit_workload_status = 0; + mutex_unlock(&workload->workload_lock); +} + +static void +amdgpu_power_profile_idle_work_handler(struct work_struct *work) +{ + + struct amdgpu_smu_workload *workload = container_of(work, + struct amdgpu_smu_workload, + power_profile_work.work); + struct amdgpu_device *adev = workload->adev; + int ret; + int profile; + + mutex_lock(&workload->workload_lock); + + /* Clear all the GPU power profile*/ + for_each_set_bit(profile, &workload->submit_workload_status, +PP_SMC_POWER_PROFILE_CUSTOM) { + if (!atomic_read(&workload->power_profile_ref[profile])) { + ret = amdgpu_power_profile_clear(adev, profile); + if (ret) { + DRM_WARN("Failed to clear workload %s,error = %d\n", +amdgpu_workload_mode_name[profile], ret); + } + } + } + + mutex_unlock(&workload->workload_lock); +} + +void amdgpu_workload_profile_put(struct amdgpu_device *adev, +uint32_t ring_type) +{ + struct amdgpu_smu_workload *workload = &adev->smu_workload; + enum PP_SMC_POWER_PROFILE profile = ring_to_power_profile(ring_type); + int refcount; + + if (profile == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT) + return; + + mutex_lock(&workload->workload_lock); + + refcount = atomic_read(&workload->power_profile_ref[profile]); + if (!refcount) { + DRM_WARN("Power profile %s ref. count error\n", +amdgpu_workload_mode_name[profile]); + } else { + if (refcount == 1) + schedule_delayed_work(&workload->power_profile_work, +
[PATCH v3 4/7] drm/amdgpu: Add suspend function to clear the GPU power profile.
This patch adds a suspend function that will clear the GPU power profile before going into suspend state. v2: - Add the new suspend function based on review comment. v3: - Adressed the review comment. - Now clearing all the profile in work handler. Cc: Shashank Sharma Cc: Christian Koenig Cc: Alex Deucher Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 7 +++ drivers/gpu/drm/amd/include/amdgpu_workload.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index cd3bf641b630..3b70e657b439 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4212,6 +4212,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) amdgpu_ras_suspend(adev); + amdgpu_workload_profile_suspend(adev); + amdgpu_device_ip_suspend_phase1(adev); if (!adev->in_s0ix) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c index fbe86ee5b8bf..0bab274a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c @@ -197,6 +197,13 @@ void amdgpu_workload_profile_get(struct amdgpu_device *adev, mutex_unlock(&workload->workload_lock); } +void amdgpu_workload_profile_suspend(struct amdgpu_device *adev) +{ + struct amdgpu_smu_workload *workload = &adev->smu_workload; + + amdgpu_power_profile_clear_all(adev, workload); +} + void amdgpu_workload_profile_init(struct amdgpu_device *adev) { adev->smu_workload.adev = adev; diff --git a/drivers/gpu/drm/amd/include/amdgpu_workload.h b/drivers/gpu/drm/amd/include/amdgpu_workload.h index 596a962800e9..34b96a5e7b50 100644 --- a/drivers/gpu/drm/amd/include/amdgpu_workload.h +++ b/drivers/gpu/drm/amd/include/amdgpu_workload.h @@ -52,6 +52,8 @@ void amdgpu_workload_profile_put(struct amdgpu_device *adev, void amdgpu_workload_profile_get(struct amdgpu_device *adev, uint32_t ring_type); +void amdgpu_workload_profile_suspend(struct amdgpu_device *adev); + void amdgpu_workload_profile_init(struct amdgpu_device *adev); void amdgpu_workload_profile_fini(struct amdgpu_device *adev); -- 2.34.1
[PATCH v3 5/7] drm/amdgpu: Set/Reset GPU workload profile
This patch is to switch the GPU workload profile based on the submitted job. The workload profile is reset to default when the job is done. v3: - Addressed the review comment about changing the function name from *_set() to *_get(). Cc: Christian Koenig Cc: Alex Deucher Reviewed-by: Shashank Sharma Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index c3d9d75143f4..c5032762d497 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -176,6 +176,9 @@ void amdgpu_job_free_resources(struct amdgpu_job *job) static void amdgpu_job_free_cb(struct drm_sched_job *s_job) { struct amdgpu_job *job = to_amdgpu_job(s_job); + struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched); + + amdgpu_workload_profile_put(ring->adev, ring->funcs->type); drm_sched_job_cleanup(s_job); @@ -295,6 +298,8 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) DRM_ERROR("Error scheduling IBs (%d)\n", r); } + amdgpu_workload_profile_get(adev, ring->funcs->type); + job->job_run_counter++; amdgpu_job_free_resources(job); -- 2.34.1
[PATCH v3 6/7] drm/amdgpu: switch workload context to/from compute
This patch switches the GPU workload mode to/from compute mode, while submitting compute workload. v3: - Addressed the review comment about changing the function name from *_set() to *_get(). Cc: Christian Koenig Signed-off-by: Alex Deucher Reviewed-by: Shashank Sharma Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0385f7f69278..fa939ac17120 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -713,9 +713,11 @@ void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle) pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled"); amdgpu_gfx_off_ctrl(adev, idle); } - amdgpu_dpm_switch_power_profile(adev, - PP_SMC_POWER_PROFILE_COMPUTE, - !idle); + + if (idle) + amdgpu_workload_profile_put(adev, AMDGPU_RING_TYPE_COMPUTE); + else + amdgpu_workload_profile_get(adev, AMDGPU_RING_TYPE_COMPUTE); } bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) -- 2.34.1
[PATCH v3 7/7] Revert "drm/amd/amdgpu: switch on/off vcn power profile mode"
This reverts commit 5ce71f59bb9bd3d8a09b96afdbc92975cb6dc303. Reason for revert: New amdgpu_workload_profile* api is added to switch on/off profile mode. These new api will allow to change the GPU power profile based on a submitted job. Cc: Christian Koenig Cc: Alex Deucher Acked-by: Shashank Sharma Signed-off-by: Arvind Yadav --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 ++ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 2d94f1b63bd6..70777fcfa626 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -363,7 +363,6 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) container_of(work, struct amdgpu_device, vcn.idle_work.work); unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0}; unsigned int i, j; - int r = 0; for (j = 0; j < adev->vcn.num_vcn_inst; ++j) { if (adev->vcn.harvest_config & (1 << j)) @@ -392,10 +391,6 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) { amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, AMD_PG_STATE_GATE); - r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, - false); - if (r) - dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r); } else { schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT); } @@ -404,16 +399,11 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - int r = 0; atomic_inc(&adev->vcn.total_submission_cnt); - if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) { - r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, - true); - if (r) - dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r); - } + if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) + amdgpu_gfx_off_ctrl(adev, false); mutex_lock(&adev->vcn.vcn_pg_lock); amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, -- 2.34.1
[PATCH -next] drm/i915/gvt: Use list_for_each_entry() helper
Convert list_for_each() to list_for_each_entry() so that the pos list_head pointer and list_entry() call are no longer needed, which can reduce a few lines of code. No functional changed. Signed-off-by: Jinjie Ruan --- drivers/gpu/drm/i915/gvt/dmabuf.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 6834f9fe40cf..f136ce140a2b 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -340,13 +340,11 @@ static struct intel_vgpu_dmabuf_obj * pick_dmabuf_by_info(struct intel_vgpu *vgpu, struct intel_vgpu_fb_info *latest_info) { - struct list_head *pos; struct intel_vgpu_fb_info *fb_info; struct intel_vgpu_dmabuf_obj *dmabuf_obj = NULL; struct intel_vgpu_dmabuf_obj *ret = NULL; - list_for_each(pos, &vgpu->dmabuf_obj_list_head) { - dmabuf_obj = list_entry(pos, struct intel_vgpu_dmabuf_obj, list); + list_for_each_entry(dmabuf_obj, &vgpu->dmabuf_obj_list_head, list) { if (!dmabuf_obj->info) continue; @@ -369,12 +367,10 @@ pick_dmabuf_by_info(struct intel_vgpu *vgpu, static struct intel_vgpu_dmabuf_obj * pick_dmabuf_by_num(struct intel_vgpu *vgpu, u32 id) { - struct list_head *pos; struct intel_vgpu_dmabuf_obj *dmabuf_obj = NULL; struct intel_vgpu_dmabuf_obj *ret = NULL; - list_for_each(pos, &vgpu->dmabuf_obj_list_head) { - dmabuf_obj = list_entry(pos, struct intel_vgpu_dmabuf_obj, list); + list_for_each_entry(dmabuf_obj, &vgpu->dmabuf_obj_list_head, list) { if (dmabuf_obj->dmabuf_id == id) { ret = dmabuf_obj; break; -- 2.34.1
Re: [PATCH v4 2/2] drm/bridge: Drop conditionals around of_node pointers
Hello! Thanks for the patch. On Saturday, August 26, 2023 04:19 -03, Biju Das wrote: > Having conditional around the of_node pointers turns out to make driver > code use ugly #ifdef and #if blocks. So drop the conditionals. It would be nice to explain why those ifdev/if conditionals are not required anymore (besides the cosmetic part). Regards, Helen > > Suggested-by: Douglas Anderson > Signed-off-by: Biju Das > --- > v4: > * New patch > --- > drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 2 -- > include/drm/drm_bridge.h | 2 -- > 2 files changed, 4 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > index 6169db73d2fe..ad8241758896 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > @@ -1231,9 +1231,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client) > > mutex_init(&anx78xx->lock); > > -#if IS_ENABLED(CONFIG_OF) > anx78xx->bridge.of_node = client->dev.of_node; > -#endif > > anx78xx->client = client; > i2c_set_clientdata(client, anx78xx); > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > index c339fc85fd07..d49d5c03df3e 100644 > --- a/include/drm/drm_bridge.h > +++ b/include/drm/drm_bridge.h > @@ -716,10 +716,8 @@ struct drm_bridge { > struct drm_encoder *encoder; > /** @chain_node: used to form a bridge chain */ > struct list_head chain_node; > -#ifdef CONFIG_OF > /** @of_node: device node pointer to the bridge */ > struct device_node *of_node; > -#endif > /** @list: to keep track of all added bridges */ > struct list_head list; > /** > -- > 2.25.1 >
Re: [PATCH v5 5/7] drm/vkms: Support enabling ConfigFS devices
Hi Brandon, kernel test robot noticed the following build warnings: [auto build test WARNING on drm-misc/drm-misc-next] [also build test WARNING on next-20230828] [cannot apply to linus/master v6.5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Brandon-Pollack/drm-vkms-Back-VKMS-with-DRM-memory-management-instead-of-static-objects/20230828-162136 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20230828081929.3574228-6-brpol%40chromium.org patch subject: [PATCH v5 5/7] drm/vkms: Support enabling ConfigFS devices config: x86_64-randconfig-r015-20230828 (https://download.01.org/0day-ci/archive/20230828/202308282031.phgzz2py-...@intel.com/config) compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230828/202308282031.phgzz2py-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202308282031.phgzz2py-...@intel.com/ All warnings (new ones prefixed by >>): >> drivers/gpu/drm/vkms/vkms_output.c:180: warning: Function parameter or >> member 'vkmsdev' not described in >> 'validate_vkms_configfs_no_dangling_objects' vim +180 drivers/gpu/drm/vkms/vkms_output.c 166 167 /** 168 * validate_vkms_configfs_no_dangling_objects - warn on unused objects in vkms 169 * configfs. 170 * @vkmsdev vkms device 171 * 172 * This gives slightly more visible warning messaging to the user before the drm 173 * system finds the configuration invalid and prints it's debug information. In 174 * this case the user may have accidentally not included some links, or the user 175 * could be testing this faulty configuration. 176 * 177 */ 178 static void 179 validate_vkms_configfs_no_dangling_objects(struct vkms_device *vkmsdev) > 180 { 181 struct vkms_configfs *configfs = vkmsdev->configfs; 182 struct config_item *item; 183 184 // 1. Planes 185 list_for_each_entry(item, &configfs->planes_group.cg_children, 186 ci_entry) { 187 struct vkms_config_plane *config_plane = 188 item_to_config_plane(item); 189 if (config_plane->possible_crtcs.linked_object_bitmap == 0) 190 DRM_WARN( 191 "Vkms configfs created plane %s has no linked crtcs", 192 item->ci_name); 193 } 194 195 // 2. connectors 196 list_for_each_entry(item, &configfs->connectors_group.cg_children, 197 ci_entry) { 198 struct vkms_config_connector *config_connector = 199 item_to_config_connector(item); 200 if (config_connector->possible_encoders.linked_object_bitmap == 201 0) { 202 DRM_WARN( 203 "Vkms configfs created connector %s has no linked encoders", 204 item->ci_name); 205 } 206 } 207 208 // 3. encoders 209 list_for_each_entry(item, &configfs->encoders_group.cg_children, 210 ci_entry) { 211 struct vkms_config_encoder *config_encoder = 212 item_to_config_encoder(item); 213 if (config_encoder->possible_crtcs.linked_object_bitmap == 0) { 214 DRM_WARN( 215 "Vkms configfs created encoder %s has no linked crtcs", 216 item->ci_name); 217 } 218 } 219 220 // 4. crtcs only require a primary plane to function, this is checked during 221 // output initialization and returns an error. 222 } 223 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
[PATCH 1/8] fbdev/smscufx: Use fb_ops helpers for deferred I/O
Generate callback functions for struct fb_ops with the fbdev macro FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(). Initialize struct fb_ops to the generated functions with fbdev initializer macros. Signed-off-by: Thomas Zimmermann Cc: Steve Glendinning --- drivers/video/fbdev/smscufx.c | 85 +-- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c index 387d18706fec..90a77d19b236 100644 --- a/drivers/video/fbdev/smscufx.c +++ b/drivers/video/fbdev/smscufx.c @@ -894,64 +894,6 @@ static int ufx_handle_damage(struct ufx_data *dev, int x, int y, return 0; } -/* Path triggered by usermode clients who write to filesystem - * e.g. cat filename > /dev/fb1 - * Not used by X Windows or text-mode console. But useful for testing. - * Slow because of extra copy and we must assume all pixels dirty. */ -static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t result; - struct ufx_data *dev = info->par; - u32 offset = (u32) *ppos; - - result = fb_sys_write(info, buf, count, ppos); - - if (result > 0) { - int start = max((int)(offset / info->fix.line_length), 0); - int lines = min((u32)((result / info->fix.line_length) + 1), - (u32)info->var.yres); - - ufx_handle_damage(dev, 0, start, info->var.xres, lines); - } - - return result; -} - -static void ufx_ops_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - - struct ufx_data *dev = info->par; - - sys_copyarea(info, area); - - ufx_handle_damage(dev, area->dx, area->dy, - area->width, area->height); -} - -static void ufx_ops_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct ufx_data *dev = info->par; - - sys_imageblit(info, image); - - ufx_handle_damage(dev, image->dx, image->dy, - image->width, image->height); -} - -static void ufx_ops_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct ufx_data *dev = info->par; - - sys_fillrect(info, rect); - - ufx_handle_damage(dev, rect->dx, rect->dy, rect->width, - rect->height); -} - /* NOTE: fb_defio.c is holding info->fbdefio.mutex * Touching ANY framebuffer memory that triggers a page fault * in fb_defio will cause a deadlock, when it also tries to @@ -1279,14 +1221,31 @@ static int ufx_ops_blank(int blank_mode, struct fb_info *info) return 0; } +static void ufx_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct ufx_data *dev = info->par; + int start = max((int)(off / info->fix.line_length), 0); + int lines = min((u32)((len / info->fix.line_length) + 1), (u32)info->var.yres); + + ufx_handle_damage(dev, 0, start, info->var.xres, lines); +} + +static void ufx_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + struct ufx_data *dev = info->par; + + ufx_handle_damage(dev, x, y, width, height); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(ufx_ops, + ufx_ops_damage_range, + ufx_ops_damage_area) + static const struct fb_ops ufx_ops = { .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = ufx_ops_write, + __FB_DEFAULT_DEFERRED_OPS_RDWR(ufx_ops), .fb_setcolreg = ufx_ops_setcolreg, - .fb_fillrect = ufx_ops_fillrect, - .fb_copyarea = ufx_ops_copyarea, - .fb_imageblit = ufx_ops_imageblit, + __FB_DEFAULT_DEFERRED_OPS_DRAW(ufx_ops), .fb_mmap = ufx_ops_mmap, .fb_ioctl = ufx_ops_ioctl, .fb_open = ufx_ops_open, -- 2.41.0
[PATCH 2/8] fbdev/udlfb: Use fb_ops helpers for deferred I/O
Generate callback functions for struct fb_ops with the fbdev macro FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(). Initialize struct fb_ops to the generated functions with fbdev initializer macros. Signed-off-by: Thomas Zimmermann Cc: Bernie Thompson --- drivers/video/fbdev/udlfb.c | 89 + 1 file changed, 22 insertions(+), 67 deletions(-) diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index b70762ead13c..2460ff4ac86b 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -715,68 +715,6 @@ static void dlfb_offload_damage(struct dlfb_data *dlfb, int x, int y, int width, schedule_work(&dlfb->damage_work); } -/* - * Path triggered by usermode clients who write to filesystem - * e.g. cat filename > /dev/fb1 - * Not used by X Windows or text-mode console. But useful for testing. - * Slow because of extra copy and we must assume all pixels dirty. - */ -static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t result; - struct dlfb_data *dlfb = info->par; - u32 offset = (u32) *ppos; - - result = fb_sys_write(info, buf, count, ppos); - - if (result > 0) { - int start = max((int)(offset / info->fix.line_length), 0); - int lines = min((u32)((result / info->fix.line_length) + 1), - (u32)info->var.yres); - - dlfb_handle_damage(dlfb, 0, start, info->var.xres, - lines); - } - - return result; -} - -/* hardware has native COPY command (see libdlo), but not worth it for fbcon */ -static void dlfb_ops_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - - struct dlfb_data *dlfb = info->par; - - sys_copyarea(info, area); - - dlfb_offload_damage(dlfb, area->dx, area->dy, - area->width, area->height); -} - -static void dlfb_ops_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct dlfb_data *dlfb = info->par; - - sys_imageblit(info, image); - - dlfb_offload_damage(dlfb, image->dx, image->dy, - image->width, image->height); -} - -static void dlfb_ops_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct dlfb_data *dlfb = info->par; - - sys_fillrect(info, rect); - - dlfb_offload_damage(dlfb, rect->dx, rect->dy, rect->width, - rect->height); -} - /* * NOTE: fb_defio.c is holding info->fbdefio.mutex * Touching ANY framebuffer memory that triggers a page fault @@ -1186,14 +1124,31 @@ static int dlfb_ops_blank(int blank_mode, struct fb_info *info) return 0; } +static void dlfb_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct dlfb_data *dlfb = info->par; + int start = max((int)(off / info->fix.line_length), 0); + int lines = min((u32)((len / info->fix.line_length) + 1), (u32)info->var.yres); + + dlfb_handle_damage(dlfb, 0, start, info->var.xres, lines); +} + +static void dlfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + struct dlfb_data *dlfb = info->par; + + dlfb_offload_damage(dlfb, x, y, width, height); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(dlfb_ops, + dlfb_ops_damage_range, + dlfb_ops_damage_area) + static const struct fb_ops dlfb_ops = { .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = dlfb_ops_write, + __FB_DEFAULT_DEFERRED_OPS_RDWR(dlfb_ops), .fb_setcolreg = dlfb_ops_setcolreg, - .fb_fillrect = dlfb_ops_fillrect, - .fb_copyarea = dlfb_ops_copyarea, - .fb_imageblit = dlfb_ops_imageblit, + __FB_DEFAULT_DEFERRED_OPS_DRAW(dlfb_ops), .fb_mmap = dlfb_ops_mmap, .fb_ioctl = dlfb_ops_ioctl, .fb_open = dlfb_ops_open, -- 2.41.0
[PATCH 0/8] fbdev: Use helpers for deferred I/O
Here's another patchset for deferred-I/O helpers. Update a number of fbdev drivers with deferred I/O to use fbdev's helper macros and Kconfig tokens. Generating and initializing via helpers macros will later allow for a fine-grained setup, depending on Kconfig options. For example, it will be possible to leave out file I/O if FB_DEVICE has not been set. Each driver in special in its own way. The smscufx and udlfb drivers support file I/O without damage updates. (That probably doesn't work correctly.) So they provide their own mmap code. The hyperv_fb driver sometimes operates on memory in I/O address spaces and fails to do damage handling correctly for write operations. The picolcd and fbtft drivers are outside of fbdev. Thomas Zimmermann (8): fbdev/smscufx: Use fb_ops helpers for deferred I/O fbdev/udlfb: Use fb_ops helpers for deferred I/O fbdev: Add Kconfig macro FB_IOMEM_HELPERS_DEFERRED fbdev/hyperv_fb: Use fb_ops helpers for deferred I/O hid: Remove trailing whitespace hid/picolcd: Use fb_ops helpers for deferred I/O staging/fbtft: Initialize fb_op struct as static const staging/fbtft: Use fb_ops helpers for deferred I/O drivers/hid/Kconfig| 8 +-- drivers/hid/hid-picolcd_fb.c | 73 ++ drivers/staging/fbtft/Kconfig | 6 +- drivers/staging/fbtft/fbtft-core.c | 99 -- drivers/video/fbdev/Kconfig| 5 +- drivers/video/fbdev/core/Kconfig | 6 ++ drivers/video/fbdev/hyperv_fb.c| 48 +-- drivers/video/fbdev/smscufx.c | 85 +++-- drivers/video/fbdev/udlfb.c| 89 +++ 9 files changed, 114 insertions(+), 305 deletions(-) -- 2.41.0
[PATCH 4/8] fbdev/hyperv_fb: Use fb_ops helpers for deferred I/O
Generate callback functions for struct fb_ops with the fbdev macro FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(). Initialize struct fb_ops to the generated functions with fbdev initializer macros. The hyperv_fb driver is incomplete in its handling of deferred I/O and damage framebuffers. Write operations do no trigger damage handling. Fixing this is beyond the scope of this patch. Signed-off-by: Thomas Zimmermann Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Wei Liu Cc: Dexuan Cui --- drivers/video/fbdev/Kconfig | 5 +--- drivers/video/fbdev/hyperv_fb.c | 48 ++--- 2 files changed, 15 insertions(+), 38 deletions(-) diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 79b1e4e542e7..4455bfd57f0e 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1905,11 +1905,8 @@ config FB_BROADSHEET config FB_HYPERV tristate "Microsoft Hyper-V Synthetic Video support" depends on FB && HYPERV - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_DEFERRED_IO select DMA_CMA if HAVE_DMA_CONTIGUOUS && CMA + select FB_IOMEM_HELPERS_DEFERRED select VIDEO_NOMODESET help This framebuffer driver supports Microsoft Hyper-V Synthetic Video. diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index b9965cbdd764..2e27c6bd8044 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -848,58 +848,38 @@ static int hvfb_blank(int blank, struct fb_info *info) return 1; /* get fb_blank to set the colormap to all black */ } -static void hvfb_cfb_fillrect(struct fb_info *p, - const struct fb_fillrect *rect) +static void hvfb_ops_damage_range(struct fb_info *info, off_t off, size_t len) { - struct hvfb_par *par = p->par; - - cfb_fillrect(p, rect); - if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); - else - hvfb_ondemand_refresh_throttle(par, rect->dx, rect->dy, - rect->width, rect->height); + /* TODO: implement damage handling */ } -static void hvfb_cfb_copyarea(struct fb_info *p, - const struct fb_copyarea *area) +static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) { - struct hvfb_par *par = p->par; + struct hvfb_par *par = info->par; - cfb_copyarea(p, area); if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); + synthvid_update(info, 0, 0, INT_MAX, INT_MAX); else - hvfb_ondemand_refresh_throttle(par, area->dx, area->dy, - area->width, area->height); + hvfb_ondemand_refresh_throttle(par, x, y, width, height); } -static void hvfb_cfb_imageblit(struct fb_info *p, - const struct fb_image *image) -{ - struct hvfb_par *par = p->par; - - cfb_imageblit(p, image); - if (par->synchronous_fb) - synthvid_update(p, 0, 0, INT_MAX, INT_MAX); - else - hvfb_ondemand_refresh_throttle(par, image->dx, image->dy, - image->width, image->height); -} +/* + * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the + * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases. + */ +FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(hvfb_ops, + hvfb_ops_damage_range, + hvfb_ops_damage_area) static const struct fb_ops hvfb_ops = { .owner = THIS_MODULE, + FB_DEFAULT_DEFERRED_OPS(hvfb_ops), .fb_check_var = hvfb_check_var, .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, - .fb_fillrect = hvfb_cfb_fillrect, - .fb_copyarea = hvfb_cfb_copyarea, - .fb_imageblit = hvfb_cfb_imageblit, .fb_blank = hvfb_blank, - .fb_mmap = fb_deferred_io_mmap, }; - /* Get options from kernel paramenter "video=" */ static void hvfb_get_option(struct fb_info *info) { -- 2.41.0
[PATCH 5/8] hid: Remove trailing whitespace
Fix coding style in Kconfig. No functional changes. Signed-off-by: Thomas Zimmermann Cc: Jiri Kosina Cc: Benjamin Tissoires --- drivers/hid/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index e11c1c803676..b50054a41c10 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1037,7 +1037,7 @@ config HID_SONY * Guitar Hero PS3 and PC guitar dongles config SONY_FF - bool "Sony PS2/3/4 accessories force feedback support" + bool "Sony PS2/3/4 accessories force feedback support" depends on HID_SONY select INPUT_FF_MEMLESS help -- 2.41.0
[PATCH 7/8] staging/fbtft: Initialize fb_op struct as static const
Replace dynamic allocation of the fb_ops instance with static allocation. Initialize the fields at module-load time. The owner field changes to THIS_MODULE, as in all other fbdev drivers. Signed-off-by: Thomas Zimmermann --- drivers/staging/fbtft/fbtft-core.c | 30 +- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index eac1d570f437..e4a77a4e7be6 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -473,6 +473,18 @@ static int fbtft_fb_blank(int blank, struct fb_info *info) return ret; } +static const struct fb_ops fbtft_ops = { + .owner= THIS_MODULE; + .fb_read = fb_sys_read; + .fb_write = fbtft_fb_write; + .fb_fillrect = fbtft_fb_fillrect; + .fb_copyarea = fbtft_fb_copyarea; + .fb_imageblit = fbtft_fb_imageblit; + .fb_setcolreg = fbtft_fb_setcolreg; + .fb_blank = fbtft_fb_blank; + .fb_mmap = fb_deferred_io_mmap; +}; + static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) { if (src->write) @@ -521,7 +533,6 @@ static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) * Creates a new frame buffer info structure. * * Also creates and populates the following structures: - * info->fbops * info->fbdefio * info->pseudo_palette * par->fbtftops @@ -536,7 +547,6 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, { struct fb_info *info; struct fbtft_par *par; - struct fb_ops *fbops = NULL; struct fb_deferred_io *fbdefio = NULL; u8 *vmem = NULL; void *txbuf = NULL; @@ -611,10 +621,6 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, if (!vmem) goto alloc_fail; - fbops = devm_kzalloc(dev, sizeof(struct fb_ops), GFP_KERNEL); - if (!fbops) - goto alloc_fail; - fbdefio = devm_kzalloc(dev, sizeof(struct fb_deferred_io), GFP_KERNEL); if (!fbdefio) goto alloc_fail; @@ -638,19 +644,9 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, goto alloc_fail; info->screen_buffer = vmem; - info->fbops = fbops; + info->fbops = &fbtft_ops; info->fbdefio = fbdefio; - fbops->owner= dev->driver->owner; - fbops->fb_read = fb_sys_read; - fbops->fb_write = fbtft_fb_write; - fbops->fb_fillrect = fbtft_fb_fillrect; - fbops->fb_copyarea = fbtft_fb_copyarea; - fbops->fb_imageblit = fbtft_fb_imageblit; - fbops->fb_setcolreg = fbtft_fb_setcolreg; - fbops->fb_blank = fbtft_fb_blank; - fbops->fb_mmap = fb_deferred_io_mmap; - fbdefio->delay =HZ / fps; fbdefio->sort_pagereflist = true; fbdefio->deferred_io = fbtft_deferred_io; -- 2.41.0
[PATCH 8/8] staging/fbtft: Use fb_ops helpers for deferred I/O
Generate callback functions for struct fb_ops with the fbdev macro FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(). Initialize struct fb_ops to the generated functions with an fbdev initializer macro. Signed-off-by: Thomas Zimmermann --- drivers/staging/fbtft/Kconfig | 6 +-- drivers/staging/fbtft/fbtft-core.c | 87 -- 2 files changed, 24 insertions(+), 69 deletions(-) diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 5dda3c65a38e..77ab44362f16 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -4,12 +4,8 @@ menuconfig FB_TFT depends on FB && SPI depends on FB_DEVICE depends on GPIOLIB || COMPILE_TEST - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO select FB_BACKLIGHT + select FB_SYSMEM_HELPERS_DEFERRED config FB_TFT_AGM1264K_FL tristate "FB driver for the AGM1264K-FL LCD display" diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index e4a77a4e7be6..3626f429b002 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -357,61 +357,6 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis dirty_lines_start, dirty_lines_end); } -static void fbtft_fb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct fbtft_par *par = info->par; - - dev_dbg(info->dev, - "%s: dx=%d, dy=%d, width=%d, height=%d\n", - __func__, rect->dx, rect->dy, rect->width, rect->height); - sys_fillrect(info, rect); - - par->fbtftops.mkdirty(info, rect->dy, rect->height); -} - -static void fbtft_fb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct fbtft_par *par = info->par; - - dev_dbg(info->dev, - "%s: dx=%d, dy=%d, width=%d, height=%d\n", - __func__, area->dx, area->dy, area->width, area->height); - sys_copyarea(info, area); - - par->fbtftops.mkdirty(info, area->dy, area->height); -} - -static void fbtft_fb_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct fbtft_par *par = info->par; - - dev_dbg(info->dev, - "%s: dx=%d, dy=%d, width=%d, height=%d\n", - __func__, image->dx, image->dy, image->width, image->height); - sys_imageblit(info, image); - - par->fbtftops.mkdirty(info, image->dy, image->height); -} - -static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct fbtft_par *par = info->par; - ssize_t res; - - dev_dbg(info->dev, - "%s: count=%zd, ppos=%llu\n", __func__, count, *ppos); - res = fb_sys_write(info, buf, count, ppos); - - /* TODO: only mark changed area update all for now */ - par->fbtftops.mkdirty(info, -1, 0); - - return res; -} - /* from pxafb.c */ static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf) { @@ -473,16 +418,30 @@ static int fbtft_fb_blank(int blank, struct fb_info *info) return ret; } +static void fbtft_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + struct fbtft_par *par = info->par; + + /* TODO: only mark changed area update all for now */ + par->fbtftops.mkdirty(info, -1, 0); +} + +static void fbtft_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + struct fbtft_par *par = info->par; + + par->fbtftops.mkdirty(info, y, height); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(fbtft_ops, + fbtft_ops_damage_range, + fbtft_ops_damage_area) + static const struct fb_ops fbtft_ops = { - .owner= THIS_MODULE; - .fb_read = fb_sys_read; - .fb_write = fbtft_fb_write; - .fb_fillrect = fbtft_fb_fillrect; - .fb_copyarea = fbtft_fb_copyarea; - .fb_imageblit = fbtft_fb_imageblit; - .fb_setcolreg = fbtft_fb_setcolreg; - .fb_blank = fbtft_fb_blank; - .fb_mmap = fb_deferred_io_mmap; + .owner= THIS_MODULE, + FB_DEFAULT_DEFERRED_OPS(fbtft_ops), + .fb_setcolreg = fbtft_fb_setcolreg, + .fb_blank = fbtft_fb_blank, }; static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) -- 2.41.0
[PATCH 6/8] hid/picolcd: Use fb_ops helpers for deferred I/O
Generate callback functions for struct fb_ops with the fbdev macro FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(). Initialize struct fb_ops to the generated functions with an fbdev initializer macro. Signed-off-by: Thomas Zimmermann Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: "Bruno Prémont" --- drivers/hid/Kconfig | 6 +-- drivers/hid/hid-picolcd_fb.c | 73 ++-- 2 files changed, 20 insertions(+), 59 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index b50054a41c10..dbf632bb7e26 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -871,11 +871,7 @@ config HID_PICOLCD_FB default !EXPERT depends on HID_PICOLCD depends on HID_PICOLCD=FB || FB=y - select FB_DEFERRED_IO - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS + select FB_SYSMEM_HELPERS_DEFERRED help Provide access to PicoLCD's 256x64 monochrome display via a framebuffer device. diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c index d726aaafb146..a4dccdcda26f 100644 --- a/drivers/hid/hid-picolcd_fb.c +++ b/drivers/hid/hid-picolcd_fb.c @@ -283,54 +283,6 @@ static void picolcd_fb_update(struct fb_info *info) mutex_unlock(&info->lock); } -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - if (!info->par) - return; - sys_fillrect(info, rect); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - if (!info->par) - return; - sys_copyarea(info, area); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* Stub to call the system default and update the image on the picoLCD */ -static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image) -{ - if (!info->par) - return; - sys_imageblit(info, image); - - schedule_delayed_work(&info->deferred_work, 0); -} - -/* - * this is the slow path from userspace. they can seek and write to - * the fb. it's inefficient to do anything less than a full screen draw - */ -static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - if (!info->par) - return -ENODEV; - ret = fb_sys_write(info, buf, count, ppos); - if (ret >= 0) - schedule_delayed_work(&info->deferred_work, 0); - return ret; -} - static int picolcd_fb_blank(int blank, struct fb_info *info) { /* We let fb notification do this for us via lcd/backlight device */ @@ -417,18 +369,31 @@ static int picolcd_set_par(struct fb_info *info) return 0; } +static void picolcdfb_ops_damage_range(struct fb_info *info, off_t off, size_t len) +{ + if (!info->par) + return; + schedule_delayed_work(&info->deferred_work, 0); +} + +static void picolcdfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height) +{ + if (!info->par) + return; + schedule_delayed_work(&info->deferred_work, 0); +} + +FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(picolcdfb_ops, + picolcdfb_ops_damage_range, + picolcdfb_ops_damage_area) + static const struct fb_ops picolcdfb_ops = { .owner= THIS_MODULE, + FB_DEFAULT_DEFERRED_OPS(picolcdfb_ops), .fb_destroy = picolcd_fb_destroy, - .fb_read = fb_sys_read, - .fb_write = picolcd_fb_write, .fb_blank = picolcd_fb_blank, - .fb_fillrect = picolcd_fb_fillrect, - .fb_copyarea = picolcd_fb_copyarea, - .fb_imageblit = picolcd_fb_imageblit, .fb_check_var = picolcd_fb_check_var, .fb_set_par = picolcd_set_par, - .fb_mmap = fb_deferred_io_mmap, }; -- 2.41.0
[PATCH 3/8] fbdev: Add Kconfig macro FB_IOMEM_HELPERS_DEFERRED
The new Kconfig macro FB_IOMEM_HELPERS_DEFERRED selects fbdev's helpers for device I/O memory and deferred I/O. Drivers should use it if they perform damage updates on device I/O memory. Signed-off-by: Thomas Zimmermann --- drivers/video/fbdev/core/Kconfig | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig index baf7e852c75b..e80d6429f76a 100644 --- a/drivers/video/fbdev/core/Kconfig +++ b/drivers/video/fbdev/core/Kconfig @@ -151,6 +151,12 @@ config FB_IOMEM_HELPERS select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT +config FB_IOMEM_HELPERS_DEFERRED + bool + depends on FB_CORE + select FB_DEFERRED_IO + select FB_IOMEM_HELPERS + config FB_SYSMEM_HELPERS bool depends on FB_CORE -- 2.41.0
Re: [PATCH v2 19/34] drm/amd/display: decouple steps for mapping CRTC degamma to DC plane
On 08/28, Pekka Paalanen wrote: > On Mon, 28 Aug 2023 09:45:44 +0100 > Joshua Ashton wrote: > > > Degamma has always been on the plane on AMD. CRTC DEGAMMA_LUT has actually > > just been applying it to every plane pre-blend. > > I've never seen that documented anywhere. > > It has seemed obvious, that since we have KMS objects for planes and > CRTCs, stuff on the CRTC does not do plane stuff before blending. That > also has not been documented in the past, but it seemed the most > logical choice. > > Even today > https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#color-management-properties > make no mention of whether they apply before or after blending. It's mentioned in the next section: https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-manager.html#dc-color-capabilities-between-dcn-generations In hindsight, maybe it isn't the best place... > > > Degamma makes no sense after blending anyway. > > If the goal is to allow blending in optical or other space, you are > correct. However, APIs do not need to make sense to exist, like most of > the options of "Colorspace" connector property. > > I have always thought the CRTC DEGAMMA only exists to allow the CRTC > CTM to work in linear or other space. > > I have at times been puzzled by what the DEGAMMA and CTM are actually > good for. > > > The entire point is for it to happen before blending to blend in linear > > space. Otherwise DEGAMMA_LUT and REGAMMA_LUT are the exact same thing... > > The CRTC CTM is between CRTC DEGAMMA and CRTC GAMMA, meaning they are > not interchangeable. > > I have literally believed that DRM KMS UAPI simply does not support > blending in optical space, unless your framebuffers are in optical > which no-one does, until the color management properties are added to > KMS planes. This never even seemed weird, because non-linear blending > is so common. > > So I have been misunderstanding the CRTC DEGAMMA property forever. Am I > the only one? Do all drivers agree today at what point does CRTC > DEGAMMA apply, before blending on all planes or after blending? > I'd like to know current userspace cases on Linux of this CRTC DEGAMMA LUT. > Does anyone know of any doc about that? From what I retrieved about the introduction of CRTC color props[1], it seems the main concern at that point was getting a linear space for CTM[2] and CRTC degamma property seems to have followed intel requirements, but didn't find anything about the blending space. AFAIU, we have just interpreted that all CRTC color properties for DRM interface are after blending[3]. Can this be seen in another way? [1] https://patchwork.freedesktop.org/series/2720/ [2] https://codereview.chromium.org/1182063002 [3] https://dri.freedesktop.org/docs/drm/_images/dcn3_cm_drm_current.svg > > If drivers do not agree on the behaviour of a KMS property, then that > property is useless for generic userspace. > > > Thanks, > pq > > > > On Tuesday, 22 August 2023, Pekka Paalanen > > wrote: > > > On Thu, 10 Aug 2023 15:02:59 -0100 > > > Melissa Wen wrote: > > > > > >> The next patch adds pre-blending degamma to AMD color mgmt pipeline, but > > >> pre-blending degamma caps (DPP) is currently in use to provide DRM CRTC > > >> atomic degamma or implict degamma on legacy gamma. Detach degamma usage > > >> regarging CRTC color properties to manage plane and CRTC color > > >> correction combinations. > > >> > > >> Reviewed-by: Harry Wentland > > >> Signed-off-by: Melissa Wen > > >> --- > > >> .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 59 +-- > > >> 1 file changed, 41 insertions(+), 18 deletions(-) > > >> > > >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > >> index 68e9f2c62f2e..74eb02655d96 100644 > > >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c > > >> @@ -764,20 +764,9 @@ int amdgpu_dm_update_crtc_color_mgmt(struct > > dm_crtc_state *crtc) > > >> return 0; > > >> } > > >> > > >> -/** > > >> - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC > > plane. > > >> - * @crtc: amdgpu_dm crtc state > > >> - * @dc_plane_state: target DC surface > > >> - * > > >> - * Update the underlying dc_stream_state's input transfer function > > (ITF) in > > >> - * preparation for hardware commit. The transfer function used depends > > on > > >> - * the preparation done on the stream for color management. > > >> - * > > >> - * Returns: > > >> - * 0 on success. -ENOMEM if mem allocation fails. > > >> - */ > > >> -int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, > > >> - struct dc_plane_state > > *dc_plane_state) > > >> +static int > > >> +map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, > > >> + struct dc_plane_state *dc_plane_state) > > >> { > > >>
Re: [PATCH v5 2/7] drm/vkms: Support multiple DRM objects (crtcs, etc.) per VKMS device
Hi Brandon, See a bottom comment about writeback connectors creation/initalization. On Mon, Aug 28, 2023 at 08:17:04AM +, Brandon Pollack wrote: > From: Jim Shargo > > This change supports multiple CRTCs, encoders, connectors instead of one > of each per device. > > Since ConfigFS-based devices will support multiple crtcs, it's useful to > move all of the writeback/composition data from being per-"output" to > being per-CRTC. > > Since there's still only ever one CRTC, this should be a no-op refactor. > > Signed-off-by: Jim Shargo > Signed-off-by: Brandon Pollack > --- > drivers/gpu/drm/vkms/vkms_composer.c | 30 +++ > drivers/gpu/drm/vkms/vkms_crtc.c | 100 - > drivers/gpu/drm/vkms/vkms_drv.c | 12 +-- > drivers/gpu/drm/vkms/vkms_drv.h | 70 +-- > drivers/gpu/drm/vkms/vkms_output.c| 122 ++ > drivers/gpu/drm/vkms/vkms_plane.c | 38 ++-- > drivers/gpu/drm/vkms/vkms_writeback.c | 31 +++ > 7 files changed, 256 insertions(+), 147 deletions(-) > > diff --git a/drivers/gpu/drm/vkms/vkms_composer.c > b/drivers/gpu/drm/vkms/vkms_composer.c > index d5d4f642d367..a59eb75a21c4 100644 > --- a/drivers/gpu/drm/vkms/vkms_composer.c > +++ b/drivers/gpu/drm/vkms/vkms_composer.c > @@ -300,13 +300,13 @@ void vkms_composer_worker(struct work_struct *work) > composer_work); > struct drm_crtc *crtc = crtc_state->base.crtc; > struct vkms_writeback_job *active_wb = crtc_state->active_writeback; > - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); > + struct vkms_crtc *vkms_crtc = drm_crtc_to_vkms_crtc(crtc); > bool crc_pending, wb_pending; > u64 frame_start, frame_end; > u32 crc32 = 0; > int ret; > > - spin_lock_irq(&out->composer_lock); > + spin_lock_irq(&vkms_crtc->composer_lock); > frame_start = crtc_state->frame_start; > frame_end = crtc_state->frame_end; > crc_pending = crtc_state->crc_pending; > @@ -330,7 +330,7 @@ void vkms_composer_worker(struct work_struct *work) > crtc_state->gamma_lut.base = NULL; > } > > - spin_unlock_irq(&out->composer_lock); > + spin_unlock_irq(&vkms_crtc->composer_lock); > > /* >* We raced with the vblank hrtimer and previous work already computed > @@ -348,10 +348,10 @@ void vkms_composer_worker(struct work_struct *work) > return; > > if (wb_pending) { > - drm_writeback_signal_completion(&out->wb_connector, 0); > - spin_lock_irq(&out->composer_lock); > + drm_writeback_signal_completion(&vkms_crtc->wb_connector, 0); > + spin_lock_irq(&vkms_crtc->composer_lock); > crtc_state->wb_pending = false; > - spin_unlock_irq(&out->composer_lock); > + spin_unlock_irq(&vkms_crtc->composer_lock); > } > > /* > @@ -401,30 +401,30 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const > char *src_name, > return 0; > } > > -void vkms_set_composer(struct vkms_output *out, bool enabled) > +void vkms_set_composer(struct vkms_crtc *vkms_crtc, bool enabled) > { > bool old_enabled; > > if (enabled) > - drm_crtc_vblank_get(&out->crtc); > + drm_crtc_vblank_get(&vkms_crtc->base); > > - mutex_lock(&out->enabled_lock); > - old_enabled = out->composer_enabled; > - out->composer_enabled = enabled; > + mutex_lock(&vkms_crtc->enabled_lock); > + old_enabled = vkms_crtc->composer_enabled; > + vkms_crtc->composer_enabled = enabled; > > /* the composition wasn't enabled, so unlock the lock to make sure the > lock >* will be balanced even if we have a failed commit >*/ > - if (!out->composer_enabled) > - mutex_unlock(&out->enabled_lock); > + if (!vkms_crtc->composer_enabled) > + mutex_unlock(&vkms_crtc->enabled_lock); > > if (old_enabled) > - drm_crtc_vblank_put(&out->crtc); > + drm_crtc_vblank_put(&vkms_crtc->base); > } > > int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) > { > - struct vkms_output *out = drm_crtc_to_vkms_output(crtc); > + struct vkms_crtc *out = drm_crtc_to_vkms_crtc(crtc); > bool enabled = false; > int ret = 0; > > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c > b/drivers/gpu/drm/vkms/vkms_crtc.c > index 3c5ebf106b66..74bbd675464b 100644 > --- a/drivers/gpu/drm/vkms/vkms_crtc.c > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c > @@ -1,5 +1,6 @@ > // SPDX-License-Identifier: GPL-2.0+ > > +#include "linux/mutex.h" > #include > > #include > @@ -11,17 +12,16 @@ > > static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) > { > - struct vkms_output *output = container_of(timer, struct vkms_output, > - vblank_hrtimer); > - struct drm_c
Re: [PATCH v5 4/7] drm/vkms: Add ConfigFS scaffolding to VKMS
Hi Brandon, See some minor missing rmdirs for connector_other and encoder_other. On Mon, Aug 28, 2023 at 08:17:06AM +, Brandon Pollack wrote: > From: Jim Shargo > > This change adds the basic scaffolding for ConfigFS, including setting > up the default directories. It does not allow for the registration of > configfs-backed devices, which is complex and provided in a follow-up > commit. > > This CL includes docs about using ConfigFS with VKMS, but I'll summarize > in brief here as well (assuming ConfigFS is mounted at /config/): > > To create a new device, you can do so via `mkdir > /config/vkms/my-device`. > > This will create a number of directories and files automatically: > > /config > `-- vkms > `-- my-device > |-- connectors > |-- crtcs > |-- encoders > |-- planes > `-- enabled > > You can then configure objects by mkdir'ing in each of the directories. > > When you're satisfied, you can `echo 1 > /config/vkms/my-device/enabled`. > This will create a new device according to your configuration. > > For now, this will fail, but the next change will add support for it. > > Signed-off-by: Jim Shargo > Signed-off-by: Brandon Pollack > --- > Documentation/gpu/vkms.rst | 18 +- > drivers/gpu/drm/Kconfig | 1 + > drivers/gpu/drm/vkms/Makefile| 1 + > drivers/gpu/drm/vkms/vkms_configfs.c | 648 +++ > drivers/gpu/drm/vkms/vkms_drv.c | 56 ++- > drivers/gpu/drm/vkms/vkms_drv.h | 92 +++- > drivers/gpu/drm/vkms/vkms_output.c | 5 + > 7 files changed, 804 insertions(+), 17 deletions(-) > create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c > > diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst > index ba04ac7c2167..c3875bf66dba 100644 > --- a/Documentation/gpu/vkms.rst > +++ b/Documentation/gpu/vkms.rst > @@ -51,6 +51,12 @@ To disable the driver, use :: > >sudo modprobe -r vkms > > +Configuration With ConfigFS > +=== > + > +.. kernel-doc:: drivers/gpu/drm/vkms/vkms_configfs.c > + :doc: ConfigFS Support for VKMS > + > Testing With IGT > > > @@ -135,22 +141,16 @@ project. > Runtime Configuration > - > > -We want to be able to reconfigure vkms instance without having to reload the > -module. Use/Test-cases: > +We want to be able to manipulate vkms instances without having to reload the > +module. Such configuration can be added as extensions to vkms's ConfigFS > +support. Use-cases: > > - Hotplug/hotremove connectors on the fly (to be able to test DP MST handling >of compositors). > > -- Configure planes/crtcs/connectors (we'd need some code to have more than 1 > of > - them first). > - > - Change output configuration: Plug/unplug screens, change EDID, allow > changing >the refresh rate. > > -The currently proposed solution is to expose vkms configuration through > -configfs. All existing module options should be supported through configfs > -too. > - > Writeback support > - > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig > index ab9ef1c20349..e39ee0e8ca06 100644 > --- a/drivers/gpu/drm/Kconfig > +++ b/drivers/gpu/drm/Kconfig > @@ -284,6 +284,7 @@ config DRM_VKMS > depends on DRM && MMU > select DRM_KMS_HELPER > select DRM_GEM_SHMEM_HELPER > + select CONFIGFS_FS > select CRC32 > default n > help > diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile > index 1b28a6a32948..6b83907ad554 100644 > --- a/drivers/gpu/drm/vkms/Makefile > +++ b/drivers/gpu/drm/vkms/Makefile > @@ -1,5 +1,6 @@ > # SPDX-License-Identifier: GPL-2.0-only > vkms-y := \ > + vkms_configfs.o \ > vkms_drv.o \ > vkms_plane.o \ > vkms_output.o \ > diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c > b/drivers/gpu/drm/vkms/vkms_configfs.c > new file mode 100644 > index ..f2439629b37b > --- /dev/null > +++ b/drivers/gpu/drm/vkms/vkms_configfs.c > @@ -0,0 +1,648 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +#include > +#include > +#include > + > +#include > +#include > + > +#include "vkms_drv.h" > + > +/** > + * DOC: ConfigFS Support for VKMS > + * > + * VKMS is instrumented with support for configuration via :doc:`ConfigFS > + * <../filesystems/configfs>`. > + * > + * With VKMS installed, you can mount ConfigFS at ``/config/`` like so:: > + * > + * mkdir -p /config/ > + * sudo mount -t configfs none /config > + * > + * This allows you to configure multiple virtual devices. Note > + * that the default device which can be enabled in the module params with:: > + * > + * modprobe vkms default_device=1 > + * > + * is immutable because we cannot pre-populate ConfigFS directories with > normal > + * files. > + * > + * To set up a new device, create a new directory under the VKMS configfs > + * directory:: > + *
Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes
On 2023-08-28 at 10:25:01 +0200, Maxime Ripard wrote: > On Sat, Aug 26, 2023 at 11:12:16AM +0200, Frank Oltmanns wrote: >> >> On 2023-08-25 at 17:07:58 +0200, Frank Oltmanns wrote: >> > Thank you for your feedback, Maxime! >> > >> > On 2023-08-25 at 10:13:53 +0200, Maxime Ripard wrote: >> >> [[PGP Signed Part:Undecided]] >> >> Hi, >> >> >> >> On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote: >> >>> I would like to make the Allwinner A64's pll-mipi to keep its rate when >> >>> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is >> >>> required, to let the A64 drive both an LCD and HDMI display at the same >> >>> time, because both have pll-video0 as an ancestor. >> >>> >> >>> PATCH 1 adds this functionality as a feature into the clk framework (new >> >>> flag: CLK_KEEP_RATE). >> >>> >> >>> Cores that use this flag, store a rate as req_rate when it or one of its >> >>> descendants requests a new rate. >> >>> >> >>> That rate is then restored in the clk_change_rate recursion, which walks >> >>> through the tree. It will reach the flagged core (e.g. pll-mipi) after >> >>> the parent's rate (e.g. pll-video0) has already been set to the new >> >>> rate. It will then call determine_rate (which requests the parent's >> >>> current, i.e. new, rate) to determine a rate that is close to the >> >>> flagged core's previous rate. Afterward it will re-calculate the rates >> >>> for the flagged core's subtree. >> >> >> >> I don't think it's the right way forward. It makes the core logic more >> >> complicated, for something that is redundant with the notifiers >> >> mechanism that has been the go-to for that kind of things so far. >> > >> > Yeah, that was my initial idea as well. But I couldn't get it to work. >> > See details below. >> > >> > Do you have an example of a clock that restores its previous rate after >> > the parent rate has changed? I've looked left and right, but to me it >> > seems that notifiers are mainly used for setting clocks into some kind >> > of "safe mode" prior to the rate change. Examples: >> > >> > sunxi-ng: >> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273 >> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60 >> > >> > but also others: >> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248 >> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755 >> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546 >> > >> >> It's not really obvious to me why the notifiers don't work there. >> >> >> >>> This work is inspired by an out-of-tree patchset [1] [2] [3]. >> >>> Unfortunately, the patchset uses clk_set_rate() in a notifier callback, >> >>> which the following comment on clk_notifier_register() forbids: "The >> >>> callbacks associated with the notifier must not re-enter into the clk >> >>> framework by calling any top-level clk APIs." [4] Furthermore, that >> >>> out-of-tree patchset no longer works with the current linux-next, >> >>> because setting pll-mipi is now also resetting pll-video0 [5]. >> >> >> >> Is it because of the "The callbacks associated with the notifier must >> >> not re-enter into the clk framework by calling any top-level clk APIs." >> >> comment? >> > >> > I don't think that's the reason. I'm fairly certain that the problem is, >> > that pll-mipi tries to set the parent rate. Maybe it should check if the >> > parent is locked, before determining a rate that requires the parent >> > rate to change. 🤔 Currently, it only calls clk_hw_can_set_rate_parent() >> > which only checks the flag, but does not check if it is really possible >> > to change the parent's rate. >> > >> > Regardless, please don't prematurely dismiss my proposal. It has the >> > advantage that it is not specific for sunxi-ng, but could be used for >> > other drivers as well. Maybe there other instances of exclusive locks >> > today where the CLK_KEEP_RATE flag might work equally well. 🤷 >> > >> >> If so, I think the thing we should emphasize is that it's about *any >> >> top-level clk API*, as in clk_set_rate() or clk_set_parent(). >> >> >> >> The issue is that any consumer-facing API is taking the clk_prepare lock >> >> and thus we would have reentrancy. But we're a provider there, and none >> >> of the clk_hw_* functions are taking that lock. Neither do our own >> >> function. >> >> >> >> So we could call in that notifier our set_rate callback directly, or we >> >> could create a clk_hw_set_rate() function. >> >> >> >> The first one will create cache issue between the actual rate that the >> >> common clock framework is running and the one we actually enforced, but >> >> we could create a function to flush the CCF cache. >> >> >> >> The second one is probably simpler. >> > >> > I'm probably missing something, because I don't think this would work. >> > For reference, this is our tree: >> > >> > pll-vid
Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes
On 2023-08-28 at 10:04:51 +0200, Maxime Ripard wrote: > On Fri, Aug 25, 2023 at 05:07:58PM +0200, Frank Oltmanns wrote: >> Thank you for your feedback, Maxime! >> >> On 2023-08-25 at 10:13:53 +0200, Maxime Ripard wrote: >> > [[PGP Signed Part:Undecided]] >> > Hi, >> > >> > On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote: >> >> I would like to make the Allwinner A64's pll-mipi to keep its rate when >> >> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is >> >> required, to let the A64 drive both an LCD and HDMI display at the same >> >> time, because both have pll-video0 as an ancestor. >> >> >> >> PATCH 1 adds this functionality as a feature into the clk framework (new >> >> flag: CLK_KEEP_RATE). >> >> >> >> Cores that use this flag, store a rate as req_rate when it or one of its >> >> descendants requests a new rate. >> >> >> >> That rate is then restored in the clk_change_rate recursion, which walks >> >> through the tree. It will reach the flagged core (e.g. pll-mipi) after >> >> the parent's rate (e.g. pll-video0) has already been set to the new >> >> rate. It will then call determine_rate (which requests the parent's >> >> current, i.e. new, rate) to determine a rate that is close to the >> >> flagged core's previous rate. Afterward it will re-calculate the rates >> >> for the flagged core's subtree. >> > >> > I don't think it's the right way forward. It makes the core logic more >> > complicated, for something that is redundant with the notifiers >> > mechanism that has been the go-to for that kind of things so far. >> >> Yeah, that was my initial idea as well. But I couldn't get it to work. >> See details below. >> >> Do you have an example of a clock that restores its previous rate after >> the parent rate has changed? I've looked left and right, but to me it >> seems that notifiers are mainly used for setting clocks into some kind >> of "safe mode" prior to the rate change. Examples: >> >> sunxi-ng: >> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273 >> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60 >> >> but also others: >> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248 >> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755 >> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546 > > There's examples for phases and parents, but not for rates afaics. We > shouldn't behave any differently though. > >> > It's not really obvious to me why the notifiers don't work there. >> > >> >> This work is inspired by an out-of-tree patchset [1] [2] [3]. >> >> Unfortunately, the patchset uses clk_set_rate() in a notifier callback, >> >> which the following comment on clk_notifier_register() forbids: "The >> >> callbacks associated with the notifier must not re-enter into the clk >> >> framework by calling any top-level clk APIs." [4] Furthermore, that >> >> out-of-tree patchset no longer works with the current linux-next, >> >> because setting pll-mipi is now also resetting pll-video0 [5]. >> > >> > Is it because of the "The callbacks associated with the notifier must >> > not re-enter into the clk framework by calling any top-level clk APIs." >> > comment? >> >> I don't think that's the reason. > > I'm not sure I follow you there. How can we find a solution to a problem > you don't know about or can't know for sure? I was hoping that the discussion here would give me some clues (and it does). You have already explained, that the issue is the locks. I'm still confused why Icenowy's patches work. They use clk_set_rate() in a notifier callback and despite that they work (up until kernel 6.5). The only thing that has changed here (that I'm aware of), is that pll-mipi now sets the parent rate in clk-next. >> I'm fairly certain that the problem is, that pll-mipi tries to set the >> parent rate. Maybe it should check if the parent is locked, before >> determining a rate that requires the parent rate to change. 🤔 > > Why would the clock framework documentation mention an issue that only > arises with a single clock on a single SoC? No, sorry, that's not what I said or meant. I was wondering if ccu_nkm_determine_rate should check if the parent rate has no exclusive lock, before assuming it can change the parent rate, so that Icenowy's patches still work. > That comment in the clock framework you linked to clearly stated that > you can't use a top-level clock function in a notifier, and that's > because of the locking. Yes, it does. And that's why I thought that calling clk_set_rate() in the notifier callback was never the right choice. > If it's not what you're trying to fix, then I'd really like to know what > issue you're trying to fix *in the framework* (so, not on the pll-mipi > clock, or the A64). I'm not trying to "fix" anything in the framework in the sense that the framework has a bug. I propose to add a
Re: [PATCH v15 00/23] Add generic memory shrinker to VirtIO-GPU and Panfrost DRM drivers
On Sunday, August 27, 2023 14:54 -03, Dmitry Osipenko wrote: > This series: > > 1. Adds common drm-shmem memory shrinker > 2. Enables shrinker for VirtIO-GPU driver > 3. Switches Panfrost driver to the common shrinker Hi Dmitry, Would you mind testing with drm-ci? We virt-io tests there and it would be really great to get your feedback of it. https://cgit.freedesktop.org/drm/drm/log/?h=topic/drm-ci You need to merge your changes with the above tree. To configure it, you just need to have a tree on gitlab.freedesktop.org, go to the settings and change the CI/CD configuration file from .gitlab-ci.yml to drivers/gpu/drm/ci/gitlab-ci.yml, and you can start a pipeline on your branch. at the time of this writting, gitlab.freedesktop.org is under maintenance, but it should be back soon. Thank you! Helen > > Changelog: > > v15:- Moved drm-shmem reference counters to use kref that allows to > optimize unlocked functions, like was suggested by Boris Brezillon. > > - Changed drm/gem/shmem function names to use _locked postfix and > dropped the _unlocked, making the naming scheme consistent across > DRM code, like was suggested by Boris Brezillon. > > - Added patch that fixes UAF in drm-shmem for drivers that import > dma-buf and then release buffer in the import error code path. > > - Added patch that makes drm-shmem use new flag for SGT's get_pages() > refcounting, preventing unbalanced refcounting when GEM is freed. > > - Fixed guest blob pinning in virtio-gpu driver that was missed > previously in the shrinker patch. > > - Moved VC4 and virtio-gpu drivers to use drm_gem_put() in > GEM-creation error code paths, which is now required by drm-shmem > and was missed in a previous patch versions. > > - Virtio-GPU now attaches shmem pages to host on first use and not > when BO is created. In older patch versions there was a potential > race condition in the BO creation code path where both > get_sgt()+object_attach() should've been made under same resv lock, > otherwise pages could be evicted before attachment is invoked. > > - Virtio-GPU and drm-shmem shrinker patches are split into smaller > ones. > > v14:- All the prerequisite reservation locking patches landed upstream, > previously were a part of this series in v13 and older. > > > https://lore.kernel.org/dri-devel/20230529223935.2672495-1-dmitry.osipe...@collabora.com/ > > - Added patches to improve locked/unlocked function names, like was > suggested by Boris Brezillon for v13. > > - Made all exported drm-shmem symbols GPL, like was previously > discussed with Thomas Zimmermann on this series. > > - Improved virtio-gpu shrinker patch. Now it won't detach purged BO > when userspace closes GEM. Crosvm (and not qemu) checks res_id on > CMD_CTX_DETACH_RESOURCE and prints noisy error message if ID is > invalid, which wasn't noticed before. > > v13:- Updated virtio-gpu shrinker patch to use drm_gem_shmem_object_pin() > directly instead of drm_gem_pin() and dropped patch that exported > drm_gem_pin() functions, like was requested by Thomas Zimmermann in > v12. > > v12:- Fixed the "no previous prototype for function" warning reported by > kernel build bot for v11. > > - Fixed the missing reservation lock reported by Intel CI for VGEM > driver. Other drivers using drm-shmem were affected similarly to > VGEM. The problem was in the dma-buf attachment code path that led > to drm-shmem pinning function which assumed the held reservation lock > by drm_gem_pin(). In the past that code path was causing trouble for > i915 driver and we've changed the locking scheme for the attachment > code path in the dma-buf core to let exporters to handle the locking > themselves. After a closer investigation, I realized that my assumption > about testing of dma-buf export code path using Panfrost driver was > incorrect. Now I created additional local test to exrecise the Panfrost > export path. I also reproduced the issue reported by the Intel CI for > v10. It's all fixed now by making the drm_gem_shmem_pin() to take the > resv lock by itself. > > - Patches are based on top of drm-tip, CC'd intel-gfx CI for testing. > > v11:- Rebased on a recent linux-next. Added new patch as a result: > > drm/shmem-helper: Export drm_gem_shmem_get_pages_sgt_locked() > > It's needed by the virtio-gpu driver to swap-in/unevict shmem > object, previously get_pages_sgt() didn't use locking. > > - Separated the "Add memory shrinker" patch into smaller parts to ease > the reviewing, as was requested by Thomas Zimmermann: > > drm/shmem-helper: Factor out pages alloc/release from > drm_gem_shmem_get/put_pages() > drm/shmem-helper: Add pages_pin_count fie
Re: [PATCH v2] fs: clean up usage of noop_dirty_folio
On Mon, Aug 28, 2023 at 03:54:49PM +0800, Xueshi Hu wrote: > In folio_mark_dirty(), it can automatically fallback to > noop_dirty_folio() if a_ops->dirty_folio is not registered. > > As anon_aops, dev_dax_aops and fb_deferred_io_aops becames empty, remove > them too. I'd put the last sentence as 'In dev_dax_aops and fb_deferred_io_aops replacing .dirty_folio with NULL makes them identical to default (empty_aops) and since we never compare ->a_ops pointer with either of those, we can remove them completely'. There could've been places like #define is_fb_deferred(mapping) (mapping)->a_ops == fb_deferred_io_aops and those would've been broken by that. The fact that there's nothing of that sort in the tree ought to be mentioned in commit message. Note that we *do* have places where method table comparisons are used in predicates like that, so it's not a pure theory; sure, missing that would've probably ended up with broken build, but that can easily be dependent upon the config (and that, alas, is also not a pure theory - BTDT). In this case the change is correct, fortunately... Other than that part of commit message - Acked-by: Al Viro
Re: [PATCH 7/8] staging/fbtft: Initialize fb_op struct as static const
On Mon, Aug 28, 2023 at 03:14:23PM +0200, Thomas Zimmermann wrote: > Replace dynamic allocation of the fb_ops instance with static > allocation. Initialize the fields at module-load time. The owner > field changes to THIS_MODULE, as in all other fbdev drivers. > > Signed-off-by: Thomas Zimmermann > --- > drivers/staging/fbtft/fbtft-core.c | 30 +- > 1 file changed, 13 insertions(+), 17 deletions(-) > Acked-by: Greg Kroah-Hartman
Re: [PATCH 8/8] staging/fbtft: Use fb_ops helpers for deferred I/O
On Mon, Aug 28, 2023 at 03:14:24PM +0200, Thomas Zimmermann wrote: > Generate callback functions for struct fb_ops with the fbdev macro > FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(). Initialize struct fb_ops to > the generated functions with an fbdev initializer macro. > > Signed-off-by: Thomas Zimmermann Acked-by: Greg Kroah-Hartman
Re: [PATCH v2 6/6] drm/drm-file: Allow size unit selection in drm_show_memory_stats
On Wed, Aug 23, 2023 at 6:36 PM Adrián Larumbe wrote: > > The current implementation will try to pick the highest available > unit. This is rather unflexible, and allowing drivers to display BO size > statistics through fdinfo in units of their choice might be desirable. > > The new argument to drm_show_memory_stats is to be interpreted as the > integer multiplier of a 10-power of 2, so 1 would give us size in Kib and 2 > in Mib. If we want drm-file functions to pick the highest unit, then 0 > should be passed. > > Signed-off-by: Adrián Larumbe > --- > drivers/gpu/drm/drm_file.c | 22 +- > drivers/gpu/drm/msm/msm_drv.c | 2 +- > drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- > include/drm/drm_file.h | 5 +++-- > 4 files changed, 18 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c > index 762965e3d503..517e1fb8072a 100644 > --- a/drivers/gpu/drm/drm_file.c > +++ b/drivers/gpu/drm/drm_file.c > @@ -873,7 +873,7 @@ void drm_send_event(struct drm_device *dev, struct > drm_pending_event *e) > EXPORT_SYMBOL(drm_send_event); > > static void print_size(struct drm_printer *p, const char *stat, > - const char *region, u64 sz) > + const char *region, u64 sz, unsigned int unit) > { > const char *units[] = {"", " KiB", " MiB"}; > unsigned u; > @@ -881,6 +881,8 @@ static void print_size(struct drm_printer *p, const char > *stat, > for (u = 0; u < ARRAY_SIZE(units) - 1; u++) { > if (sz < SZ_1K) > break; > + if (unit > 0 && unit == u) > + break; > sz = div_u64(sz, SZ_1K); > } > > @@ -898,17 +900,18 @@ static void print_size(struct drm_printer *p, const > char *stat, > void drm_print_memory_stats(struct drm_printer *p, > const struct drm_memory_stats *stats, > enum drm_gem_object_status supported_status, > - const char *region) > + const char *region, > + unsigned int unit) I'm not really adverse to changing what units we use.. or perhaps changing the threshold to go to higher units to be 1x or 10x of the previous unit. But I'm less excited about having different drivers using different units. BR, -R > { > - print_size(p, "total", region, stats->private + stats->shared); > - print_size(p, "shared", region, stats->shared); > - print_size(p, "active", region, stats->active); > + print_size(p, "total", region, stats->private + stats->shared, unit); > + print_size(p, "shared", region, stats->shared, unit); > + print_size(p, "active", region, stats->active, unit); > > if (supported_status & DRM_GEM_OBJECT_RESIDENT) > - print_size(p, "resident", region, stats->resident); > + print_size(p, "resident", region, stats->resident, unit); > > if (supported_status & DRM_GEM_OBJECT_PURGEABLE) > - print_size(p, "purgeable", region, stats->purgeable); > + print_size(p, "purgeable", region, stats->purgeable, unit); > } > EXPORT_SYMBOL(drm_print_memory_stats); > > @@ -916,11 +919,12 @@ EXPORT_SYMBOL(drm_print_memory_stats); > * drm_show_memory_stats - Helper to collect and show standard fdinfo memory > stats > * @p: the printer to print output to > * @file: the DRM file > + * @unit: multipliyer of power of two exponent of desired unit > * > * Helper to iterate over GEM objects with a handle allocated in the > specified > * file. > */ > -void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file) > +void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file, > unsigned int unit) > { > struct drm_gem_object *obj; > struct drm_memory_stats status = {}; > @@ -967,7 +971,7 @@ void drm_show_memory_stats(struct drm_printer *p, struct > drm_file *file) > } > spin_unlock(&file->table_lock); > > - drm_print_memory_stats(p, &status, supported_status, "memory"); > + drm_print_memory_stats(p, &status, supported_status, "memory", unit); > } > EXPORT_SYMBOL(drm_show_memory_stats); > > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c > index 2a0e3529598b..cd1198151744 100644 > --- a/drivers/gpu/drm/msm/msm_drv.c > +++ b/drivers/gpu/drm/msm/msm_drv.c > @@ -1067,7 +1067,7 @@ static void msm_show_fdinfo(struct drm_printer *p, > struct drm_file *file) > > msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, p); > > - drm_show_memory_stats(p, file); > + drm_show_memory_stats(p, file, 0); > } > > static const struct file_operations fops = { > diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c > b/drivers/gpu/drm/panfrost/panfrost_drv.c > index 93d5f5538c0b..79c08cee3e9d 100644 > --- a
Re: [PATCH v3 0/7] GPU workload hints for better performance
[AMD Official Use Only - General] As mentioned with an older version of this series, this is an 'abuse' of power profile interface. This series is oversimplifying what PMFW algorithms are supposed to be doing. Whatever this series is doing, FW can do it better. To explain in simpler terms - it just tries to boost a profile based on ring type without even knowing how much of activity a job can trigger on a particular ring. A job scheduled to a GFX ring doesn't deserve a profile boost unless it can create a certain level of activity. In CPU terms, a job scheduled to a processor doesn't mean it deserves a frequency boost of that CPU. At minimum it depends on more details like whether that job is compute bound or memory bound or memory bound. While FW algorithms are designed to do that, this series tries to trivialise all such things. Unless you are able to show the tangible benefits in some terms like performance, power, or performance per watt, I don't think this should be the default behaviour where driver tries to override FW just based on job submissions to rings. Thanks, Lijo From: amd-gfx on behalf of Arvind Yadav Sent: Monday, August 28, 2023 5:56:07 PM To: Koenig, Christian ; Deucher, Alexander ; Sharma, Shashank ; Pan, Xinhui ; airl...@gmail.com ; dan...@ffwll.ch ; Kuehling, Felix ; amd-...@lists.freedesktop.org Cc: Yadav, Arvind ; linux-ker...@vger.kernel.org ; dri-devel@lists.freedesktop.org Subject: [PATCH v3 0/7] GPU workload hints for better performance AMDGPU SOCs supports dynamic workload based power profiles, which can provide fine-tuned performance for a particular type of workload. This patch series adds an interface to set/reset these power profiles based on the submitted job. The driver can dynamically switch the power profiles based on submitted job. This can optimize the power performance when the particular workload is on. v2: - Splitting workload_profile_set and workload_profile_put into two separate patches. - Addressed review comment. - Added new suspend function. - Added patch to switches the GPU workload mode for KFD. v3: - Addressed all review comment. - Changed the function name from *_set() to *_get(). - Now clearing all the profile in work handler. - Added *_clear_all function to clear all the power profile. Arvind Yadav (7): drm/amdgpu: Added init/fini functions for workload drm/amdgpu: Add new function to set GPU power profile drm/amdgpu: Add new function to put GPU power profile drm/amdgpu: Add suspend function to clear the GPU power profile. drm/amdgpu: Set/Reset GPU workload profile drm/amdgpu: switch workload context to/from compute Revert "drm/amd/amdgpu: switch on/off vcn power profile mode" drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c| 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 226 ++ drivers/gpu/drm/amd/include/amdgpu_workload.h | 61 + 8 files changed, 309 insertions(+), 16 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c create mode 100644 drivers/gpu/drm/amd/include/amdgpu_workload.h -- 2.34.1
Re: [PATCH v4 1/3] dt-bindings: display: panel: add common dual-link schema
On Fri, 25 Aug 2023 14:11:40 +0200, Krzysztof Kozlowski wrote: > Add schema with common properties shared among dual-link panel ICs. > > Signed-off-by: Krzysztof Kozlowski > > --- > > Changes since v3: > 1. Re-phrase description of binding and ports (Laurent) > v3: > https://lore.kernel.org/all/20230823081500.84005-1-krzysztof.kozlow...@linaro.org/ > > Changes since v2: > 1. New Patch > v2: > https://lore.kernel.org/all/20230502120036.47165-1-krzysztof.kozlow...@linaro.org/ > v1: > https://lore.kernel.org/all/20230416153929.356330-1-krzysztof.kozlow...@linaro.org/ > --- > .../display/panel/panel-common-dual.yaml | 47 +++ > 1 file changed, 47 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/panel-common-dual.yaml > Reviewed-by: Rob Herring
Re: [PATCH v15 00/23] Add generic memory shrinker to VirtIO-GPU and Panfrost DRM drivers
On Monday, August 28, 2023 11:37 -03, "Helen Mae Koike Fornazier" wrote: > On Sunday, August 27, 2023 14:54 -03, Dmitry Osipenko > wrote: > > > This series: > > > > 1. Adds common drm-shmem memory shrinker > > 2. Enables shrinker for VirtIO-GPU driver > > 3. Switches Panfrost driver to the common shrinker > > Hi Dmitry, > > Would you mind testing with drm-ci? We virt-io tests there and it would be > really great to get your feedback of it. > > https://cgit.freedesktop.org/drm/drm/log/?h=topic/drm-ci sorry, I forgot that you also need this patchset: https://lists.freedesktop.org/archives/dri-devel/2023-August/420063.html to enable virtio_gpu test job. Thanks again. Helen > > You need to merge your changes with the above tree. > To configure it, you just need to have a tree on gitlab.freedesktop.org, > go to the settings and change the CI/CD configuration file from .gitlab-ci.yml > to drivers/gpu/drm/ci/gitlab-ci.yml, and you can start a pipeline > on your branch. > > at the time of this writting, gitlab.freedesktop.org is under maintenance, > but it should be back soon. > > Thank you! > Helen > > > > > Changelog: > > > > v15:- Moved drm-shmem reference counters to use kref that allows to > > optimize unlocked functions, like was suggested by Boris Brezillon. > > > > - Changed drm/gem/shmem function names to use _locked postfix and > > dropped the _unlocked, making the naming scheme consistent across > > DRM code, like was suggested by Boris Brezillon. > > > > - Added patch that fixes UAF in drm-shmem for drivers that import > > dma-buf and then release buffer in the import error code path. > > > > - Added patch that makes drm-shmem use new flag for SGT's get_pages() > > refcounting, preventing unbalanced refcounting when GEM is freed. > > > > - Fixed guest blob pinning in virtio-gpu driver that was missed > > previously in the shrinker patch. > > > > - Moved VC4 and virtio-gpu drivers to use drm_gem_put() in > > GEM-creation error code paths, which is now required by drm-shmem > > and was missed in a previous patch versions. > > > > - Virtio-GPU now attaches shmem pages to host on first use and not > > when BO is created. In older patch versions there was a potential > > race condition in the BO creation code path where both > > get_sgt()+object_attach() should've been made under same resv lock, > > otherwise pages could be evicted before attachment is invoked. > > > > - Virtio-GPU and drm-shmem shrinker patches are split into smaller > > ones. > > > > v14:- All the prerequisite reservation locking patches landed upstream, > > previously were a part of this series in v13 and older. > > > > > > https://lore.kernel.org/dri-devel/20230529223935.2672495-1-dmitry.osipe...@collabora.com/ > > > > - Added patches to improve locked/unlocked function names, like was > > suggested by Boris Brezillon for v13. > > > > - Made all exported drm-shmem symbols GPL, like was previously > > discussed with Thomas Zimmermann on this series. > > > > - Improved virtio-gpu shrinker patch. Now it won't detach purged BO > > when userspace closes GEM. Crosvm (and not qemu) checks res_id on > > CMD_CTX_DETACH_RESOURCE and prints noisy error message if ID is > > invalid, which wasn't noticed before. > > > > v13:- Updated virtio-gpu shrinker patch to use drm_gem_shmem_object_pin() > > directly instead of drm_gem_pin() and dropped patch that exported > > drm_gem_pin() functions, like was requested by Thomas Zimmermann in > > v12. > > > > v12:- Fixed the "no previous prototype for function" warning reported by > > kernel build bot for v11. > > > > - Fixed the missing reservation lock reported by Intel CI for VGEM > > driver. Other drivers using drm-shmem were affected similarly to > > VGEM. The problem was in the dma-buf attachment code path that led > > to drm-shmem pinning function which assumed the held reservation lock > > by drm_gem_pin(). In the past that code path was causing trouble for > > i915 driver and we've changed the locking scheme for the attachment > > code path in the dma-buf core to let exporters to handle the locking > > themselves. After a closer investigation, I realized that my > > assumption > > about testing of dma-buf export code path using Panfrost driver was > > incorrect. Now I created additional local test to exrecise the > > Panfrost > > export path. I also reproduced the issue reported by the Intel CI for > > v10. It's all fixed now by making the drm_gem_shmem_pin() to take the > > resv lock by itself. > > > > - Patches are based on top of drm-tip, CC'd intel-gfx CI for testing. > > > > v11:- Rebased on a recent linux-next. Added new patch as a result: > > > > drm/shmem-helper: Export drm_
Re: [PATCH] spi: tegra: Fix missing IRQ check in tegra_slink_probe()
On Saturday, August 26, 2023 07:02 -03, Zhang Shurong wrote: > This func misses checking for platform_get_irq()'s call and may passes the > negative error codes to request_irq(), which takes unsigned IRQ #, > causing it to fail with -EINVAL, overriding an original error code. > > Fix this by stop calling request_irq() with invalid IRQ #s. > > Fixes: dc4dc3605639 ("spi: tegra: add spi driver for SLINK controller") > Signed-off-by: Zhang Shurong Reviewed-by: Helen Koike > --- > drivers/spi/spi-tegra20-slink.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c > index 4d6db6182c5e..f5cd365c913a 100644 > --- a/drivers/spi/spi-tegra20-slink.c > +++ b/drivers/spi/spi-tegra20-slink.c > @@ -1086,6 +1086,8 @@ static int tegra_slink_probe(struct platform_device > *pdev) > reset_control_deassert(tspi->rst); > > spi_irq = platform_get_irq(pdev, 0); > + if (spi_irq < 0) > + return spi_irq; > tspi->irq = spi_irq; > ret = request_threaded_irq(tspi->irq, tegra_slink_isr, > tegra_slink_isr_thread, IRQF_ONESHOT, > -- > 2.30.2 >
Re: [PATCH] drm: bridge: it66121: Fix invalid connector dereference
On Friday, August 25, 2023 08:02 -03, Jai Luthra wrote: > Fix the NULL pointer dereference when no monitor is connected, and the > sound card is opened from userspace. > > Instead return an error as EDID information cannot be provided to > the sound framework if there is no connector attached. > > Fixes: e0fd83dbe924 ("drm: bridge: it66121: Add audio support") > Reported-by: Nishanth Menon > Closes: https://lore.kernel.org/all/20230825105849.crhon42qndxqif4i@gondola/ > Signed-off-by: Jai Luthra Reviewed-by: Helen Koike > --- > drivers/gpu/drm/bridge/ite-it66121.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/gpu/drm/bridge/ite-it66121.c > b/drivers/gpu/drm/bridge/ite-it66121.c > index 466641c77fe9..d6fa00dea464 100644 > --- a/drivers/gpu/drm/bridge/ite-it66121.c > +++ b/drivers/gpu/drm/bridge/ite-it66121.c > @@ -1446,6 +1446,11 @@ static int it66121_audio_get_eld(struct device *dev, > void *data, > { > struct it66121_ctx *ctx = dev_get_drvdata(dev); > > + if (!ctx->connector) { > + dev_dbg(dev, "No connector present, cannot provide EDID data"); > + return -EINVAL; > + } > + > mutex_lock(&ctx->lock); > > memcpy(buf, ctx->connector->eld, > > --- > base-commit: 6269320850097903b30be8f07a5c61d9f7592393 > change-id: 20230825-it66121_edid-6ee98517808b > > Best regards, > -- > Jai Luthra >
Re: [PATCH] drm/prime: Support page array >= 4GB
On 2023-08-21 16:02, Philip Yang wrote: Without unsigned long typecast, the size is passed in as zero if page array size >= 4GB, nr_pages >= 0x10, then sg list converted will have the first and the last chunk lost. Signed-off-by: Philip Yang The patch looks reasonable to me. I don't have authority to approve it. But FWIW, Acked-by: Felix Kuehling Can anyone give a Reviewed-by? Thanks, Felix --- drivers/gpu/drm/drm_prime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index f924b8b4ab6b..2630ad2e504d 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -830,7 +830,7 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev, if (max_segment == 0) max_segment = UINT_MAX; err = sg_alloc_table_from_pages_segment(sg, pages, nr_pages, 0, - nr_pages << PAGE_SHIFT, + (unsigned long)nr_pages << PAGE_SHIFT, max_segment, GFP_KERNEL); if (err) { kfree(sg);
Re: [PATCH v3 0/7] GPU workload hints for better performance
On Monday, August 28, 2023 09:26 -03, Arvind Yadav wrote: > AMDGPU SOCs supports dynamic workload based power profiles, which can > provide fine-tuned performance for a particular type of workload. > This patch series adds an interface to set/reset these power profiles > based on the submitted job. The driver can dynamically switch > the power profiles based on submitted job. This can optimize the power > performance when the particular workload is on. Hi Arvind, Would you mind to test your patchset with drm-ci ? There is a amdgpu test there and I would love to get your feedback of the ci. You basically just need to apply the ci patch which is available on https://cgit.freedesktop.org/drm/drm/log/?h=topic/drm-ci There are instruction on the docs, but in short: to configure it, you push your branch to gitlab.freedesktop.org, go to the settings and change the CI/CD configuration file from .gitlab-ci.yml to drivers/gpu/drm/ci/gitlab-ci.yml, and you can trigger a pipeline on your branch to get tests running. (by the time of this writing, gitlab.fdo is under maintenance but should be up soonish). Thank you! Helen > > v2: > - Splitting workload_profile_set and workload_profile_put > into two separate patches. > - Addressed review comment. > - Added new suspend function. > - Added patch to switches the GPU workload mode for KFD. > > v3: > - Addressed all review comment. > - Changed the function name from *_set() to *_get(). > - Now clearing all the profile in work handler. > - Added *_clear_all function to clear all the power profile. > > > Arvind Yadav (7): > drm/amdgpu: Added init/fini functions for workload > drm/amdgpu: Add new function to set GPU power profile > drm/amdgpu: Add new function to put GPU power profile > drm/amdgpu: Add suspend function to clear the GPU power profile. > drm/amdgpu: Set/Reset GPU workload profile > drm/amdgpu: switch workload context to/from compute > Revert "drm/amd/amdgpu: switch on/off vcn power profile mode" > > drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- > drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + > drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c| 8 +- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 6 + > drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 5 + > drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 +- > drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c | 226 ++ > drivers/gpu/drm/amd/include/amdgpu_workload.h | 61 + > 8 files changed, 309 insertions(+), 16 deletions(-) > create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_workload.c > create mode 100644 drivers/gpu/drm/amd/include/amdgpu_workload.h > > -- > 2.34.1 >