[Bug 85421] radeon stalled, GPU lockup, reset and failed on resume; crashed by firefox.
https://bugzilla.kernel.org/show_bug.cgi?id=85421 --- Comment #18 from Hin-Tak Leung --- (In reply to Alex Deucher from comment #14) > Please make sure your version of mesa has this patch: > http://cgit.freedesktop.org/mesa/mesa/commit/ > ?id=ae4536b4f71cbe76230ea7edc7eb4d6041e651b4 This seems no good /insufficient. I just had a lock-up with 10.3.5, which includes it. With kernel 3.17.6-200.fc20.x86_64, if that means anything. Also it looks like I upgraded firefox to v34 (from v33) 5 days ago. I was merely opening a few more tabs on firefox when it happened. Though 20 minutes before then my computer came out of a suspend, and before the suspend, I was using kvm and virtualbox a bit. Switching VT was still possible so I was able to reboot cleanly. The failure message seems slightly different, so just in case it means anything, ... [71241.232157] radeon :00:01.0: ring 0 stalled for more than 10002msec [71241.232173] radeon :00:01.0: GPU lockup (waiting for 0x0052e910 last fence id 0x00 52e90d on ring 0) [71241.232337] radeon :00:01.0: failed to get a new IB (-35) [71241.232347] [drm:radeon_cs_ib_fill] *ERROR* Failed to get ib ! [71241.279772] radeon :00:01.0: Saved 15657 dwords of commands on ring 0. ... [71252.356774] [drm:cik_ring_test] *ERROR* radeon: ring 1 test failed (scratch(0x3010C)=0xCAFEDEA D) [71252.718837] [drm:cik_ring_test] *ERROR* radeon: ring 2 test failed (scratch(0x3010C)=0xCAFEDEA D) [71252.836977] [drm:cik_sdma_ring_test] *ERROR* radeon: ring 3 test failed (0xCAFEDEAD) [71252.836992] [drm:cik_resume] *ERROR* cik startup failed on resume [71252.837260] [drm] ib test on ring 0 succeeded in 0 usecs [71252.837790] [drm] ib test on ring 6 succeeded [71252.838167] [drm] ib test on ring 7 succeeded [71254.210168] [drm:radeon_dp_link_train_cr] *ERROR* displayport link status failed [71254.210182] [drm:radeon_dp_link_train_cr] *ERROR* clock recovery failed [71257.654395] radeon :00:01.0: still active bo inside vm [71257.765448] radeon :00:01.0: still active bo inside vm [71258.526881] radeon :00:01.0: still active bo inside vm [71265.473102] radeon :00:01.0: couldn't schedule ib ... I cam supply the dmesg if needed. Seeing as the patch does not work/insufficient, and my best experience so far is 10.2.9 (lasted 3 weeks, without the patch), my worst experience is 10.3.3 (less than a day), and 10.3.4/10.3.5 (patch included) lasted a week, I am going back to 10.2.9, and adding the patch to it. If the patch improves 10.2.9 the way it did from 10.3.3 -> 10.3.4/10.3.5, i.e. make 10.2.9 lasts a few months, I'd be happy enough. -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 86011] [drm] "Memory manager not clean during takedown" after vga-switcheroo turn off nvidia card
https://bugzilla.kernel.org/show_bug.cgi?id=86011 Bjorn Helgaas changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |CODE_FIX --- Comment #6 from Bjorn Helgaas --- This should be fixed by https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/gpu/drm/nouveau/nouveau_drm.c?id=8b62c8c6df08ca567c78afa51aa7bbc554cede06, which appeared in v3.18. -- You are receiving this mail because: You are watching someone on the CC list of the bug.
[PATCH] drm: fb helper should avoid sleeping in panic context
On Tue, Dec 09, 2014 at 08:05:21PM -0500, Rob Clark wrote: > oh, whoops.. gmail hiding quoted text.. > > yeah, that looks sane, > > Reviewed-by: Rob Clark > > On Tue, Dec 9, 2014 at 7:55 PM, rui wang wrote: > > Hi Rob, > > Yes it's exactly what I'm doing. Please scroll down and review my patch. > > > > Thanks > > Rui > > > > On 12/10/14, Rob Clark wrote: > >> perhaps fb helpers could use __drm_modeset_lock_all() w/ trylock=true > >> in panic context? > >> > >> BR, > >> -R > >> > >> On Tue, Dec 9, 2014 at 7:09 PM, rui wang wrote: > >>> Hi All, > >>> > >>> Any comment ? Or any better idea how this should be fixed? > >>> > >>> Regards, > >>> Rui > >>> Dear gmail-ers, A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail? Please stop the top-posting or use a mail client which doesn't facilitate the idiocy. Thanks. -- Regards/Gruss, Boris. Sent from a fat crate under my desk. Formatting is fine. --
Long radeon stalls on recent kernels
On Wed, Dec 10, 2014 at 8:24 PM, Michel Dänzer wrote: > On 11.12.2014 05:28, Andy Lutomirski wrote: >> On Wed, Dec 10, 2014 at 1:44 AM, Michel Dänzer >> wrote: >>> On 10.12.2014 06:39, Andy Lutomirski wrote: On Tue, Dec 9, 2014 at 8:06 AM, Andy Lutomirski wrote: > On Tue, Dec 9, 2014 at 1:18 AM, Michel Dänzer > wrote: >> On 09.12.2014 09:24, Andy Lutomirski wrote: >>> >>> The relevant line from latencytop seems to be: >>> >>> 154 20441402 489139 radeon_fence_default_wait [radeon] >>> fence_wait_timeout ttm_bo_wait [ttm] ttm_bo_move_accel_cleanup [ttm] >>> radeon_move_blit.isra.12 [radeon] radeon_bo_move [radeon] >>> ttm_bo_handle_move_mem [ttm] ttm_bo_evict [ttm] ttm_mem_evict_first >>> [ttm] ttm_bo_mem_space [ttm] ttm_bo_validate [ttm] >>> radeon_bo_fault_reserve_notify [radeon] >> >> Which process is this? > > Xorg > >> >> Looks like CPU access to a BO in VRAM, but the BO is located outside of >> the CPU visible area of VRAM, so it has to be moved into the CPU visible >> area first. > > [...] > But I'm still waiting for the day that buggy userspace *can't* cause kernel graphics stalls. >>> >>> Actually, this looks more like buggy userspace stalling itself. :) >> >> I thought the stall was the kernel evicting things from vram. Why >> does it need to wait for userspace for that? Is it that userspace is >> actively using whatever's being evicted? > > As I explained above, the stall happens because userspace does CPU > access to a BO which resides in the CPU-inaccessible part of VRAM. The > kernel has to move the BO into the CPU accessible part of VRAM before it > can let userspace proceed. Sure, but why does that take nearly 500ms? Even if the object in question is the entire framebuffer, that still seems extraordinarily slow. --Andy > > Current Mesa (10.4 or newer I think) sets a hint for BOs which will > likely be accessed by the CPU, so recent kernels can prioritize putting > those into the CPU accessible part of VRAM in the first place. > > Or, if you're using EXA, the problem could be in the xf86-video-ati EXA > code. > > > -- > Earthling Michel Dänzer | http://www.amd.com > Libre software enthusiast | Mesa and X developer -- Andy Lutomirski AMA Capital Management, LLC
[RESEND PATCH] drm/doc: Document drm_add_modes_noedid() usage
From: Laurent PinchartAnd fix a spelling mistake. Signed-off-by: Laurent Pinchart --- Documentation/DocBook/drm.tmpl | 24 +++- 1 file changed, 19 insertions(+), 5 deletions(-) I've had this patch in my tree for way too long, it's time to get it to mainline or drop it. I of course vote for the former as I wouldn't submit it otherwise. diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 60c1063d4178..a5024f6aaf53 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -1947,10 +1947,16 @@ void intel_crt_init(struct drm_device *dev) and then retrieves a list of modes by calling the connector get_modes helper operation. + +If the helper operation returns no mode, and if the connector status +is connector_status_connected, standard VESA DMT modes up to +1024x768 are automatically added to the modes list by a call to +drm_add_modes_noedid. + -The function filters out modes larger than +The function then filters out modes larger than max_width and max_height -if specified. It then calls the optional connector +if specified. It finally calls the optional connector mode_valid helper operation for each mode in the probed list to check whether the mode is valid for the connector. @@ -2090,12 +2096,20 @@ void intel_crt_init(struct drm_device *dev) int (*get_modes)(struct drm_connector *connector); Fill the connector's probed_modes list -by parsing EDID data with drm_add_edid_modes or -calling drm_mode_probed_add directly for every +by parsing EDID data with drm_add_edid_modes, +adding standard VESA DMT modes with drm_add_modes_noedid, +or calling drm_mode_probed_add directly for every supported mode and return the number of modes it has detected. This operation is mandatory. +Note that the caller function will automatically add standard VESA +DMT modes up to 1024x768 if the get_modes +helper operation returns no mode and if the connector status is +connector_status_connected. There is no need to call +drm_add_edid_modes manually in that case. + + When adding modes manually the driver creates each mode with a call to drm_mode_create and must fill the following fields. @@ -2292,7 +2306,7 @@ void intel_crt_init(struct drm_device *dev) drm_helper_probe_single_connector_modes. -When parsing EDID data, drm_add_edid_modes fill the +When parsing EDID data, drm_add_edid_modes fills the connector display_info width_mm and height_mm fields. When creating modes -- Regards, Laurent Pinchart
[PATCH v18 12/12] drm: bridge/dw_hdmi: add rockchip rk3288 support
Hi Andy, This driver adds HDMI to rockchip/drm. The fact that rockchip's hdmi uses dw_hdmi is an implementation detail. I do not think that the names used for rk3288-hdmi should include "dw" in them. See inline for what I mean... On Thu, Dec 4, 2014 at 10:34 PM, Andy Yan wrote: > Rockchip RK3288 hdmi is compatible with dw_hdmi > > this patch is depend on patch by Mark Yao > drm: rockchip: Add basic drm driver > see https://lkml.org/lkml/2014/12/2/161 > > Signed-off-by: Andy Yan > > --- > > Changes in v18: None > Changes in v17: > - parse resource and irq in platform driver > > Changes in v16: None > Changes in v15: > - remove THIS_MODULE in platform driver > > Changes in v14: None > Changes in v13: None > Changes in v12: > - add comment for the depend on patch > > Changes in v11: None > Changes in v10: > - add more display mode support mpll configuration for rk3288 > > Changes in v9: > - move some phy configuration to platform driver > > Changes in v8: None > Changes in v7: None > Changes in v6: None > Changes in v5: None > Changes in v4: None > Changes in v3: None > > drivers/gpu/drm/bridge/dw_hdmi.c| 3 + > drivers/gpu/drm/rockchip/Kconfig| 10 + > drivers/gpu/drm/rockchip/Makefile | 2 + > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 341 > > include/drm/bridge/dw_hdmi.h| 1 + > 5 files changed, 357 insertions(+) > create mode 100644 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > > diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c > b/drivers/gpu/drm/bridge/dw_hdmi.c > index cecc46a..01c95a8 100644 > --- a/drivers/gpu/drm/bridge/dw_hdmi.c > +++ b/drivers/gpu/drm/bridge/dw_hdmi.c > @@ -852,6 +852,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, > unsigned char prep, > dw_hdmi_phy_gen2_txpwron(hdmi, 1); > dw_hdmi_phy_gen2_pddq(hdmi, 0); > > + if (hdmi->dev_type == RK3288_HDMI) > + dw_hdmi_phy_enable_spare(hdmi, 1); > + > /*Wait for PHY PLL lock */ > msec = 5; > do { > diff --git a/drivers/gpu/drm/rockchip/Kconfig > b/drivers/gpu/drm/rockchip/Kconfig > index ca9f085..6ebebe8 100644 > --- a/drivers/gpu/drm/rockchip/Kconfig > +++ b/drivers/gpu/drm/rockchip/Kconfig > @@ -15,3 +15,13 @@ config DRM_ROCKCHIP > management to userspace. This driver does not provide > 2D or 3D acceleration; acceleration is performed by other > IP found on the SoC. > + > +config ROCKCHIP_DW_HDMI I would rather call this ROCKCHIP_HDMI, since this driver implements the HDMI for Rockchip. The fact that it uses dw_hdmi is an implementation detail. > +bool "Rockchip specific extensions for Synopsys DW HDMI" > +depends on DRM_ROCKCHIP > +select DRM_DW_HDMI > +help > + This selects support for Rockchip SoC specific extensions > + for the Synopsys DesignWare HDMI driver. If you want to > + enable HDMI on RK3288 based SoC, you should selet this > + option. This could become simply: Select this option to enable HDMI support for Rockchip SoCs. > diff --git a/drivers/gpu/drm/rockchip/Makefile > b/drivers/gpu/drm/rockchip/Makefile > index 2cb0672..beed7df 100644 > --- a/drivers/gpu/drm/rockchip/Makefile > +++ b/drivers/gpu/drm/rockchip/Makefile > @@ -5,4 +5,6 @@ > rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ > rockchip_drm_gem.o > > +rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o > + > obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > new file mode 100644 > index 000..11d54b0 > --- /dev/null > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c Similarly, I'd rather this file be called drm_rockchip_hdmi.c to be consistent with the rest of the files in drm/rockchip. > @@ -0,0 +1,341 @@ > +/* > + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rockchip_drm_drv.h" > +#include "rockchip_drm_vop.h" > + > +#define GRF_SOC_CON60x025c > +#define HDMI_SEL_VOP_LIT(1 << 4) > + > +struct rockchip_hdmi { > + struct device *dev; > + struct regmap *regmap; > + struct drm_encoder encoder; > +}; > + > +#define to_rockchip_hdmi(x)container_of(x, struct rockchip_hdmi, x) > + > +static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { Let's stick to mpll_config. Not much value to abbreviate an abbreviation. > +
[PATCH 0/4] removal of extra abstraction layers
Hi, On 8 December 2014 at 17:03, Gustavo Padovan wrote: > 2014-12-06 Dave Airlie : > > On 2 December 2014 at 22:38, Gustavo Padovan > wrote: > > > Can you please review this? I also have sent other two patch sets that > sits on > > > top of this one. Thanks. > > > > Inki, any plans on when you can get to looking at this? > > > > I think cleaning up exynos so we can get atomic using it is something > > that will benefit it heavily. > > Besides these patches I have other two clean up patchsets[0][1] that are > very > important for atomic support, can you review these two too? > It'd be fantastic to get the START == START_S fix merged too: http://www.spinics.net/lists/linux-samsung-soc/msg40128.html Cheers, Daniel -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/86a0dff3/attachment.html>
[RFC 1/4] dma-buf: Add constraints sharing information
Hi Daniel, Thanks a bunch for your review comments! A few comments, post our discussion at LPC; On 12 October 2014 at 00:25, Daniel Vetter wrote: > On Sat, Oct 11, 2014 at 01:37:55AM +0530, Sumit Semwal wrote: >> At present, struct device lacks a mechanism of exposing memory >> access constraints for the device. >> >> Consequently, there is also no mechanism to share these constraints >> while sharing buffers using dma-buf. >> >> If we add support for sharing such constraints, we could use that >> to try to collect requirements of different buffer-sharing devices >> to allocate buffers from a pool that satisfies requirements of all >> such devices. >> >> This is an attempt to add this support; at the moment, only a bitmask >> is added, but if post discussion, we realise we need more information, >> we could always extend the definition of constraint. >> >> A new dma-buf op is also added, to allow exporters to interpret or decide >> on constraint-masks on their own. A default implementation is provided to >> just AND (&) all the constraint-masks. >> >> What constitutes a constraint-mask could be left for interpretation on a >> per-platform basis, while defining some common masks. >> >> Signed-off-by: Sumit Semwal >> Cc: linux-kernel at vger.kernel.org >> Cc: Greg Kroah-Hartman >> Cc: linux-media at vger.kernel.org >> Cc: dri-devel at lists.freedesktop.org >> Cc: linaro-mm-sig at lists.linaro.org > > Just a few high-level comments, I'm between conference travel but > hopefully I can discuss this a bit at plumbers next week. > > - I agree that for the insane specific cases we need something opaque like > the access constraints mask you propose here. But for the normal case I > think the existing dma constraints in dma_params would go a long way, > and I think we should look at Rob's RFC from aeons ago to solve those: > > https://lkml.org/lkml/2012/7/19/285 > > With this we should be able to cover the allocation constraints of 90% > of all cases hopefully. > > - I'm not sure whether an opaque bitmask is good enough really, I suspect > that we also need various priorities between different allocators. With > the option that some allocators are flat-out incompatible. Your/Rob's idea to figure out the constraints wrt max number of segments in the sg_list can provide, like you said, maybe 80-90% of the allocation constraints hopefully. The opaque mask should help for the remaining 'crazy' cases, so I'll be glad to merge Rob's and my approach on defining the constraints. I should think a little bit more about the priority idea that you propose here (and in another patch), but atm I am unable to see how that could help solve the finding-out-constraints problem. > > - The big bummer imo with ION is that it fully side-steps, but this > proposal here also seems to add entirely new allocators. My rough idea This proposal does borrow this bit from ION, but once we have the required changes done in the dma api itself, the allocators can just become shims to the dma api allocators (eg dma_alloc_coherent etc) for cases where they can be used directly, while leaving provision for any crazy platform-specific allocators, without the userspace having to worry about it. > was that at allocate/attach time we iterate over all attached devices > like in Rob's patch and compute the most constrained allocation > requirements. Then we pick the underlying dma api allocator for these > constraints. That probably means that we need to open up the dma api a > bit. But I guess for a start we could simply try to allocate from the > most constrained device. Together with the opaque bits you propose here > we could even map additional crazy requirements like that an allocation > must come from a specific memory bank (provided by a special-purpose CMA > region). That might also mean that requirements are exclusive and no > allocation is possible. > My idea was a little variation on what you said here - rather than do compute the most constraint allocation 'after' devices have attached (and right now, we don't really have a way to know that - but that's another point), I'd proposed to do the compute on each attach request, so the requesting drivers can know immediately if the attachment will not work for the other currently attached devices. > - I'm not sure we should allow drivers to override the access constraint > checks really - the dma_buf interfaces already provide this possibility > through the ->attach callback. In there exporters are allowed to reject > the attachment for any reason whatsover. > This override the access constraint check is again meant only as a helper, but I could sure drop it. > - I think we should at least provide a helper implementation to allocate > dma-buffers for multiple devices using the dma constraints logic we > implement here. I think we should even go as far as providing a default > implementation for dma-bufs which uses dma_alloc_coherent and
Long radeon stalls on recent kernels
On 10.12.2014 06:39, Andy Lutomirski wrote: > On Tue, Dec 9, 2014 at 8:06 AM, Andy Lutomirski > wrote: >> On Tue, Dec 9, 2014 at 1:18 AM, Michel Dänzer wrote: >>> On 09.12.2014 09:24, Andy Lutomirski wrote: The relevant line from latencytop seems to be: 154 20441402 489139 radeon_fence_default_wait [radeon] fence_wait_timeout ttm_bo_wait [ttm] ttm_bo_move_accel_cleanup [ttm] radeon_move_blit.isra.12 [radeon] radeon_bo_move [radeon] ttm_bo_handle_move_mem [ttm] ttm_bo_evict [ttm] ttm_mem_evict_first [ttm] ttm_bo_mem_space [ttm] ttm_bo_validate [ttm] radeon_bo_fault_reserve_notify [radeon] >>> >>> Which process is this? >> >> Xorg >> >>> >>> Looks like CPU access to a BO in VRAM, but the BO is located outside of >>> the CPU visible area of VRAM, so it has to be moved into the CPU visible >>> area first. >>> >>> Which version of Mesa are you using? >>> >> >> mesa-dri-drivers-10.3.3-1.20141110.fc20.x86_64 >> >> I'm planning on upgrading to Fedora 21 fairly soon. > > Upgrading to mesa-dri-drivers-10.3.3-1.20141110.fc21.x86_64 seems to > have helped enough that my usual test (open a couple of Firefox tabs > with graphics in them) doesn't hang anymore. Hmm, since that looks like the exact same upstream version, maybe it was actually upgrading something else that made the difference? > This card still isn't *fast*. I'm afraid it wasn't exactly a high-end card even when it was new. What kind of operations are slow? > Is there some way I can check that I'm actually using all 16 PCIe lanes? > In my tinkering w/ power management settings, I got some odd logs > suggesting that only one lane was in use. You can try forcing off ASPM with radeon.aspm=0, other than that I'm not sure. > But I'm still waiting for the day that buggy userspace *can't* cause > kernel graphics stalls. Actually, this looks more like buggy userspace stalling itself. :) -- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Mesa and X developer
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 --- Comment #5 from Sylvain BERTRAND --- Ok, I dive in. The thing: for each kernel commit I should test I need to play hours to see if the mini freezes happen... this will probably take a while. The only significant change in my dota2 configuration from the configuration, which seemed to work flawlessly, is that I play now in a 1920x1080 borderless window with openbox window manager, instead of 2560x1600 fullscreen with mutter window manager. I'll try to locate a "good" commit from 26045b53c96f23b75a48544349c3d936e8402418 -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/f774090a/attachment.html>
[RFC] drm: add support for tiled/compressed/etc modifier in addfb2
On Wed, Dec 10, 2014 at 12:17:51PM -0500, Rob Clark wrote: > In DRM/KMS we are lacking a good way to deal with tiled/compressed > formats. Especially in the case of dmabuf/prime buffer sharing, where > we cannot always rely on under-the-hood flags passed to driver specific > gem-create ioctl to pass around these extra flags. > > The proposal is to add a per-plane format modifier. This allows to, if > necessary, use different tiling patters for sub-sampled planes, etc. > The format modifiers are added at the end of the ioctl struct, so for > legacy userspace it will be zero padded. > > TODO how best to deal with assignment of modifier token values? The > rough idea was to namespace things with an 8bit vendor-id, and then > beyond that it is treated as an opaque value. But that was a relatively > arbitrary choice. There are cases where same tiling pattern and/or > compression is supported by various different vendors. So we should > standardize to use the vendor-id and value of the first one who > documents the format? 8bits should be enough, will take a while until we have more than 250 gpu drivers in the linux kernel ;-) I'm leaning a bit towards using 64bits though to make sure that there's enough space in the bitfiel to encode substrides and stuff like that, in case anyone needs it. For vendor ids I'd just go with first come and starting at 1 (i.e. rename yours). That way we make it clear that until a patch is merged upstream the id isn't reserved yet. drm-next should be sufficient as registry imo. > TODO move definition of tokens to drm_fourcc.h? Seems orthogonal imo. Another todo is to add checking to all drivers to reject it if it's not 0 with -EINVAL. Otherwise we have yet another case of an ioctl with fields that can't actually be used everywhere. But yeah I like this and in i915 we definitely need this. skl adds a bunch of framebuffer layouts where we need to spec tiling in more detail. Overall I like. > Signed-off-by: Rob Clark > --- > include/uapi/drm/drm_mode.h | 30 ++ > 1 file changed, 30 insertions(+) > > diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h > index aae71cb..c43648c 100644 > --- a/include/uapi/drm/drm_mode.h > +++ b/include/uapi/drm/drm_mode.h > @@ -330,6 +330,28 @@ struct drm_mode_fb_cmd { > > #define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ > > +/* > + * Format Modifiers: > + * > + * Format modifiers describe, typically, a re-ordering or modification > + * of the data in a plane of an FB. This can be used to express tiled/ > + * swizzled formats, or compression, or a combination of the two. > + * > + * The upper 8 bits of the format modifier are a vendor-id as assigned > + * below. The lower 24 bits are assigned as vendor sees fit. > + */ > + > +/* Vendor Ids: */ > +#define DRM_FOURCC_MOD_VENDOR_SAMSUNG 0x03 > +/* ... more */ > + > +#define DRM_FOURCC_MOD(vendor, name) (((DRM_FOURCC_MOD_VENDOR_## vendor) << > 24) | val) Maybe a mask for the lower 24 bits? -Daniel > + > +/* Modifier values: */ > +/* 64x32 macroblock, ie NV12MT: */ > +#define DRM_FOURCC_MOD_SAMSUNG_64_32_TILE DRM_FOURCC_MOD(SAMSUNG, 123) > +/* ... more */ > + > struct drm_mode_fb_cmd2 { > __u32 fb_id; > __u32 width, height; > @@ -349,10 +371,18 @@ struct drm_mode_fb_cmd2 { >* So it would consist of Y as offsets[0] and UV as >* offsets[1]. Note that offsets[0] will generally >* be 0 (but this is not required). > + * > + * To accommodate tiled, compressed, etc formats, a per-plane > + * modifier can be specified. The default value of zero > + * indicates "native" format as specified by the fourcc. > + * Vendor specific modifier token. This allows, for example, > + * different tiling/swizzling pattern on different planes. > + * See discussion above of DRM_FOURCC_MOD_xxx. >*/ > __u32 handles[4]; > __u32 pitches[4]; /* pitch for each plane */ > __u32 offsets[4]; /* offset of each plane */ > + __u32 modifier[4]; /* ie, tiling, compressed (per plane) */ > }; > > #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 > -- > 2.1.0 > -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[RFC 00/15] Resource tracking/allocation framework
10 gru 2014 17:16 "Russell King - ARM Linux" napisaÅ(a): > > On Wed, Dec 10, 2014 at 04:48:18PM +0100, Andrzej Hajda wrote: > > 3. There are drivers which can work without specific resource, but if > > the resource becomes available/unavailable it can do some additional stuff. > > An example of such driver is DRM driver (more precisely drm_connector) - > > it can start without attached drm_panel, but if the panel becomes available it > > can react by generating HPD event and start using it. > > Bad example, and actually incorrect. DRM connectors are referenced in > userspace by an IDR number, which can be re-used in the case of a > connector appearing, disappearing, and then a different connector > re-appearing. But it is not about reappearing of drm_connector, it is about reappearing of drm_panel which is fortunately not a part of drm driver. Connector here is only consumer of drm_panel which should have possibility to receive notifications on panel (dis-)appearance. Regards Andrzej > > DRM really is *not* safe to hotplug like this: DRM is more a card-level > thing, which is why we have the component helpers - which allow us to > merge several devices into one logical card-like device in a generic > manner. > > DRM needs a stable picture of the CRTCs, encoders and connectors, which > should _never_ change during the lifetime of the DRM device. Devices > attached to connectors can be hotplugged, but that's about the limit of > hot-plugging in DRM. > > -- > FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up > according to speedtest.net. > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/608d5942/attachment.html>
[Bug 86891] AMD/ATI Tahiti XT 7970 - long lags/stutters in games
https://bugzilla.kernel.org/show_bug.cgi?id=86891 Alan changed: What|Removed |Added Status|NEW |RESOLVED CC||alan at lxorguk.ukuu.org.uk Resolution|--- |CODE_FIX -- You are receiving this mail because: You are watching the assignee of the bug.
[RFC 00/15] Resource tracking/allocation framework
On Wed, Dec 10, 2014 at 06:23:49PM +0100, A H wrote: > 10 gru 2014 17:16 "Russell King - ARM Linux" > napisaÅ(a): > > > > On Wed, Dec 10, 2014 at 04:48:18PM +0100, Andrzej Hajda wrote: > > > 3. There are drivers which can work without specific resource, but if > > > the resource becomes available/unavailable it can do some additional > stuff. > > > An example of such driver is DRM driver (more precisely > drm_connector) - > > > it can start without attached drm_panel, but if the panel becomes > available it > > > can react by generating HPD event and start using it. > > > > Bad example, and actually incorrect. DRM connectors are referenced in > > userspace by an IDR number, which can be re-used in the case of a > > connector appearing, disappearing, and then a different connector > > re-appearing. > > But it is not about reappearing of drm_connector, it is about reappearing > of drm_panel which is fortunately not a part of drm driver. Connector here > is only consumer of drm_panel which should have possibility to receive > notifications on panel (dis-)appearance. Okay, so that's exactly like a panel being "hotplugged" to the connector, which should be fine. -- FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up according to speedtest.net.
[PATCH] drm/cache: Implement drm_clflush_*() for ARM
From: Thierry RedingAdd implementations for drm_clflush_*() on ARM by borrowing code from the DMA mapping API implementation. Unfortunately ARM doesn't export an API to flush caches on a page by page basis, so this replicates most of the code. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_cache.c | 45 + 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index a6b690626a6b..fca0b8994c77 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -72,6 +72,41 @@ drm_clflush_ipi_handler(void *null) } #endif +#if defined(CONFIG_ARM) + +#include +#include +#include +#include + +static void drm_clflush_page(struct page *page) +{ + enum dma_data_direction dir = DMA_TO_DEVICE; + phys_addr_t phys = page_to_phys(page); + size_t size = PAGE_SIZE; + void *virt; + + if (PageHighMem(page)) { + if (cache_is_vipt_nonaliasing()) { + virt = kmap_atomic(page); + dmac_map_area(virt, size, dir); + kunmap_atomic(virt); + } else { + virt = kmap_high_get(page); + if (virt) { + dmac_map_area(virt, size, dir); + kunmap_high(page); + } + } + } else { + virt = page_address(page); + dmac_map_area(virt, size, dir); + } + + outer_flush_range(phys, phys + PAGE_SIZE); +} +#endif + void drm_clflush_pages(struct page *pages[], unsigned long num_pages) { @@ -99,6 +134,11 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) (unsigned long)page_virtual + PAGE_SIZE); kunmap_atomic(page_virtual); } +#elif defined(CONFIG_ARM) + unsigned long i; + + for (i = 0; i < num_pages; i++) + drm_clflush_page(pages[i]); #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); @@ -123,6 +163,11 @@ drm_clflush_sg(struct sg_table *st) if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) printk(KERN_ERR "Timed out waiting for cache flush.\n"); +#elif defined(CONFIG_ARM) + struct sg_page_iter sg_iter; + + for_each_sg_page(st->sgl, _iter, st->nents, 0) + drm_clflush_page(sg_page_iter_page(_iter)); #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); WARN_ON_ONCE(1); -- 2.1.3
[Bug 89521] New: Radeon driver fails to set dpm power state after resume from S3
https://bugzilla.kernel.org/show_bug.cgi?id=89521 Bug ID: 89521 Summary: Radeon driver fails to set dpm power state after resume from S3 Product: Drivers Version: 2.5 Kernel Version: 3.18.0 Hardware: x86-64 OS: Linux Tree: Mainline Status: NEW Severity: normal Priority: P1 Component: Video(DRI - non Intel) Assignee: drivers_video-dri at kernel-bugs.osdl.org Reporter: anhermann at gmx.net Regression: No Created attachment 160341 --> https://bugzilla.kernel.org/attachment.cgi?id=160341=edit dmesg output from 3 resume cycles Using a Radeon R9 270X and kernel 3.18.0 I get the following error message only after resume from S3 state: [drm:si_dpm_set_power_state] *ERROR* si_set_sw_state failed I would like to notice that this also happened with older kernel versions (3.17 and 3.16 with radeon.dpm=1) and other cards. My other PC has a HD 5450 with the same problem (slightly other ERROR string as its not SI). Besides the error message, I cannot see any strange behaviour, performance is good, no freezes etc. . But it sounds like performance level switching is not working correctly? I added the dmesg output showing three resume cycles with the mentioned error message as attachment. Thanks -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 87761] nouveau: renaming aux.c would make life easier for those remote editing via git/windows
https://bugzilla.kernel.org/show_bug.cgi?id=87761 Alan changed: What|Removed |Added CC||alan at lxorguk.ukuu.org.uk Component|I2C |Video(DRI - non Intel) Assignee|drivers-i2c at kernel-bugs.osd |drivers_video-dri at kernel-bu |l.org |gs.osdl.org Summary|File Name "aux" not allowed |nouveau: renaming aux.c |on windows |would make life easier for ||those remote editing via ||git/windows --- Comment #1 from Alan --- This would be graphics. We've traditionally not cared, but with git now being a workable and not unusual environment for edit on windows, commit and build on the servers it's a good point Reassigning to the right category -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH 2/3] drm/radeon: Add implementation of get_fw_version
On Wed, Dec 10, 2014 at 8:13 AM, Oded Gabbay wrote: > From: Alexey Skidanov > > This patch implements a new interface that was added to the kfd-->kgd > interface. > The new interface function retrieves the firmware version that is currently > in use by the MEC engine. The firmware was uploaded to the MEC engine by the > radeon driver. > > Signed-off-by: Alexey Skidanov > Reviewed-by: Oded Gabbay > --- > drivers/gpu/drm/radeon/radeon_kfd.c | 23 +++ > 1 file changed, 23 insertions(+) > > diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c > b/drivers/gpu/drm/radeon/radeon_kfd.c > index 065d020..223c831 100644 > --- a/drivers/gpu/drm/radeon/radeon_kfd.c > +++ b/drivers/gpu/drm/radeon/radeon_kfd.c > @@ -28,6 +28,8 @@ > #include "cikd.h" > #include "cik_reg.h" > #include "radeon_kfd.h" > +#include "radeon_ucode.h" > +#include > > #define CIK_PIPE_PER_MEC (4) > > @@ -49,6 +51,7 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd); > static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); > > static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); > +static uint16_t get_fw_version(struct kgd_dev *kgd); > > /* > * Register access functions > @@ -91,6 +94,7 @@ static const struct kfd2kgd_calls kfd2kgd = { > .hqd_load = kgd_hqd_load, > .hqd_is_occupies = kgd_hqd_is_occupies, > .hqd_destroy = kgd_hqd_destroy, > + .get_fw_version = get_fw_version > }; > > static const struct kgd2kfd_calls *kgd2kfd; > @@ -561,3 +565,22 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t > reset_type, > release_queue(kgd); > return 0; > } > + > +static uint16_t get_fw_version(struct kgd_dev *kgd) I think it would be better to call the is get_mec_fw_version or add an engine and/or instance parameter if it need to query other engines (e.g., MEC2 or GFX). > +{ > + struct radeon_device *rdev; > + const struct gfx_firmware_header_v1_0 *hdr; > + > + BUG_ON(kgd == NULL); > + > + rdev = (struct radeon_device *) kgd; > + > + BUG_ON(rdev->mec_fw == NULL); > + > + hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data; > + Do you care about the fw version of MEC2? Alex
[RFC 15/15] drm/panel/ld9040: convert to restrack API
Convert ld9040 panel driver to use restrack API. As a result driver have following advantages: - correctly handles removal of resources, - do not need to defer probing, so as a result the panel becomes available as soon as possible, in case of deferred probing it was late_initcall, - simplified initialization. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/panel/panel-ld9040.c | 41 ++-- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ld9040.c b/drivers/gpu/drm/panel/panel-ld9040.c index 3337f30..619610e 100644 --- a/drivers/gpu/drm/panel/panel-ld9040.c +++ b/drivers/gpu/drm/panel/panel-ld9040.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -310,9 +311,22 @@ static int ld9040_parse_dt(struct ld9040 *ctx) return 0; } +void ld9040_restrack_cb(struct device *dev, int ret) +{ + struct ld9040 *ctx = dev_get_drvdata(dev); + + if (ret == 0) + drm_panel_add(>panel); + else if (ret == -EPROBE_DEFER) + drm_panel_remove(>panel); + else + dev_err(dev, "restrack error %d\n", ret); +} + static int ld9040_probe(struct spi_device *spi) { struct device *dev = >dev; + struct restrack_ctx *rtrack; struct ld9040 *ctx; int ret; @@ -331,17 +345,6 @@ static int ld9040_probe(struct spi_device *spi) ctx->supplies[0].supply = "vdd3"; ctx->supplies[1].supply = "vci"; - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), - ctx->supplies); - if (ret < 0) - return ret; - - ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(ctx->reset_gpio)) { - dev_err(dev, "cannot get reset-gpios %ld\n", - PTR_ERR(ctx->reset_gpio)); - return PTR_ERR(ctx->reset_gpio); - } spi->bits_per_word = 9; ret = spi_setup(spi); @@ -354,16 +357,13 @@ static int ld9040_probe(struct spi_device *spi) ctx->panel.dev = dev; ctx->panel.funcs = _drm_funcs; - return drm_panel_add(>panel); -} - -static int ld9040_remove(struct spi_device *spi) -{ - struct ld9040 *ctx = spi_get_drvdata(spi); - - drm_panel_remove(>panel); + rtrack = devm_restrack_register(ctx->dev, ld9040_restrack_cb, + regulator_bulk_restrack_desc(>supplies[0]), + regulator_bulk_restrack_desc(>supplies[1]), + gpiod_restrack_desc(>reset_gpio, "reset", GPIOD_OUT_HIGH), + ); - return 0; + return PTR_ERR_OR_ZERO(rtrack); } static struct of_device_id ld9040_of_match[] = { @@ -374,7 +374,6 @@ MODULE_DEVICE_TABLE(of, ld9040_of_match); static struct spi_driver ld9040_driver = { .probe = ld9040_probe, - .remove = ld9040_remove, .driver = { .name = "ld9040", .owner = THIS_MODULE, -- 1.9.1
[RFC 14/15] drm/panel/ld9040: do not power off panel on removal
Panel is powered off already by connector during drm_panel_remove call. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/panel/panel-ld9040.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-ld9040.c b/drivers/gpu/drm/panel/panel-ld9040.c index 08cf2c5..3337f30 100644 --- a/drivers/gpu/drm/panel/panel-ld9040.c +++ b/drivers/gpu/drm/panel/panel-ld9040.c @@ -361,7 +361,6 @@ static int ld9040_remove(struct spi_device *spi) { struct ld9040 *ctx = spi_get_drvdata(spi); - ld9040_power_off(ctx); drm_panel_remove(>panel); return 0; -- 1.9.1
[RFC 13/15] drm/exynos/dpi: convert to restrack API
exynos_dpi implements drm encoder and connector. Currently its probe was defered if the associated panel was not yet present. It is inefficient behavior - it could start normally with connector status set to disconnected and notify drm about status change when panel appears/disapeears. Unfortunately drm_panel API does not provide such notifications. restrack solves the issue above. After converting to restrack driver have following advantages: - correctly handles removal of resources, - do not need to defer probing, so as a result the whole drm system initialization will not be postponed to late initcall, unless other components delays it, - it starts/stops tracking panel presence only when necessary. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 80 +++- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 7 +++ 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 91a29e1..75ee578 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -13,9 +13,9 @@ #include #include #include - #include #include +#include #include #include @@ -34,7 +34,6 @@ enum { struct exynos_dpi { struct exynos_drm_display display; struct device *dev; - struct device_node *panel_node; struct drm_panel *panel; struct drm_connector connector; @@ -42,10 +41,13 @@ struct exynos_dpi { struct videomode *vm; int dpms_mode; + struct restrack_ctx *rtrack; }; #define connector_to_dpi(c) container_of(c, struct exynos_dpi, connector) +struct exynos_drm_display *fimd_dev_to_display(struct device *dev); + static inline struct exynos_dpi *display_to_dpi(struct exynos_drm_display *d) { return container_of(d, struct exynos_dpi, display); @@ -56,14 +58,18 @@ exynos_dpi_detect(struct drm_connector *connector, bool force) { struct exynos_dpi *ctx = connector_to_dpi(connector); - if (ctx->panel && !ctx->panel->connector) - drm_panel_attach(ctx->panel, >connector); + if (!ctx->vm && IS_ERR(ctx->panel)) + return connector_status_disconnected; return connector_status_connected; } static void exynos_dpi_connector_destroy(struct drm_connector *connector) { + struct exynos_dpi *ctx = connector_to_dpi(connector); + + if (!IS_ERR(ctx->rtrack)) + restrack_unregister(ctx->rtrack); drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -94,7 +100,7 @@ static int exynos_dpi_get_modes(struct drm_connector *connector) return 1; } - if (ctx->panel) + if (!IS_ERR(ctx->panel)) return ctx->panel->funcs->get_modes(ctx->panel); return 0; @@ -113,6 +119,38 @@ static struct drm_connector_helper_funcs exynos_dpi_connector_helper_funcs = { .best_encoder = exynos_dpi_best_encoder, }; +static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode); + +void exynos_dpi_notifier(struct device *dev, int ret) +{ + struct exynos_drm_display *display = fimd_dev_to_display(dev); + struct exynos_dpi *ctx = display_to_dpi(display); + struct drm_connector *connector = >connector; + struct drm_device *drm_dev = connector->dev; + bool poll_enabled = drm_dev->mode_config.poll_enabled; + + mutex_lock(_dev->mode_config.mutex); + + if (ret == 0) { + drm_panel_attach(ctx->panel, connector); + } else if (ret == -EPROBE_DEFER) { + exynos_dpi_dpms(>display, DRM_MODE_DPMS_OFF); + drm_panel_detach(ctx->panel); + ctx->panel = ERR_PTR(-EPROBE_DEFER); + } else { + dev_err(dev, "restrack error %d\n", ret); + poll_enabled = false; + } + + if (poll_enabled) + connector->status = exynos_dpi_detect(connector, true); + + mutex_unlock(_dev->mode_config.mutex); + + if (poll_enabled) + drm_kms_helper_hotplug_event(drm_dev); +} + static int exynos_dpi_create_connector(struct exynos_drm_display *display, struct drm_encoder *encoder) { @@ -136,12 +174,23 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display, drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); + if (ctx->vm) + return 0; + + ctx->rtrack = restrack_register(ctx->dev, exynos_dpi_notifier, + drm_panel_restrack_desc(>panel, NULL, FIMD_PORT_RGB) + ); + + if (IS_ERR(ctx->rtrack)) + DRM_ERROR("error installing panel tracker: %ld\n", + PTR_ERR(ctx->rtrack)); + return 0; } static void exynos_dpi_poweron(struct exynos_dpi *ctx) { - if (ctx->panel) { +
[RFC 12/15] drm/exynos/dpi: use common of_graph functions
The patch removes private of_graph functions and uses common ones. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 117 +++- 1 file changed, 24 insertions(+), 93 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 37678cf..91a29e1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -21,6 +22,15 @@ #include "exynos_drm_drv.h" +/* possible of_graph port nodes used by device */ +enum { + FIMD_PORT_IN0, + FIMD_PORT_IN1, + FIMD_PORT_IN2, + FIMD_PORT_RGB, + FIMD_PORT_WRB, +}; + struct exynos_dpi { struct exynos_drm_display display; struct device *dev; @@ -171,102 +181,12 @@ static struct exynos_drm_display_ops exynos_dpi_display_ops = { .dpms = exynos_dpi_dpms }; -/* of_* functions will be removed after merge of of_graph patches */ -static struct device_node * -of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg) -{ - struct device_node *np; - - for_each_child_of_node(parent, np) { - u32 r; - - if (!np->name || of_node_cmp(np->name, name)) - continue; - - if (of_property_read_u32(np, "reg", ) < 0) - r = 0; - - if (reg == r) - break; - } - - return np; -} - -static struct device_node *of_graph_get_port_by_reg(struct device_node *parent, - u32 reg) -{ - struct device_node *ports, *port; - - ports = of_get_child_by_name(parent, "ports"); - if (ports) - parent = ports; - - port = of_get_child_by_name_reg(parent, "port", reg); - - of_node_put(ports); - - return port; -} - -static struct device_node * -of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg) -{ - return of_get_child_by_name_reg(port, "endpoint", reg); -} - -static struct device_node * -of_graph_get_remote_port_parent(const struct device_node *node) -{ - struct device_node *np; - unsigned int depth; - - np = of_parse_phandle(node, "remote-endpoint", 0); - - /* Walk 3 levels up only if there is 'ports' node. */ - for (depth = 3; depth && np; depth--) { - np = of_get_next_parent(np); - if (depth == 2 && of_node_cmp(np->name, "ports")) - break; - } - return np; -} - -enum { - FIMD_PORT_IN0, - FIMD_PORT_IN1, - FIMD_PORT_IN2, - FIMD_PORT_RGB, - FIMD_PORT_WRB, -}; - -static struct device_node *exynos_dpi_of_find_panel_node(struct device *dev) -{ - struct device_node *np, *ep; - - np = of_graph_get_port_by_reg(dev->of_node, FIMD_PORT_RGB); - if (!np) - return NULL; - - ep = of_graph_get_endpoint_by_reg(np, 0); - of_node_put(np); - if (!ep) - return NULL; - - np = of_graph_get_remote_port_parent(ep); - of_node_put(ep); - - return np; -} - static int exynos_dpi_parse_dt(struct exynos_dpi *ctx) { struct device *dev = ctx->dev; struct device_node *dn = dev->of_node; struct device_node *np; - ctx->panel_node = exynos_dpi_of_find_panel_node(dev); - np = of_get_child_by_name(dn, "display-timings"); if (np) { struct videomode *vm; @@ -289,10 +209,21 @@ static int exynos_dpi_parse_dt(struct exynos_dpi *ctx) return 0; } - if (!ctx->panel_node) - return -EINVAL; + np = NULL; + while ((np = of_graph_get_next_endpoint(dev->of_node, np))) { + struct of_endpoint ep; - return 0; + of_graph_parse_endpoint(np, ); + if (ep.port != FIMD_PORT_RGB) + continue; + + ctx->panel_node = of_graph_get_remote_port_parent(np); + of_node_put(np); + + return ctx->panel_node ? 0 : -EINVAL; + } + + return -EINVAL; } struct exynos_drm_display *exynos_dpi_probe(struct device *dev) -- 1.9.1
[RFC 11/15] drm/exynos/dsi: convert to restrack API
Convert exynos_dsi driver to use restrack API. As a result driver have following advantages: - correctly handles removal of resources, - do not need to defer probing, so as a result the whole drm system initialization will not be postponed to late initcall, unless other components delays it, - simplified initialization. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 52 + 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 8201d79..53ac467 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -23,7 +23,7 @@ #include #include #include - +#include #include #include @@ -1690,9 +1690,18 @@ static const struct component_ops exynos_dsi_component_ops = { .unbind = exynos_dsi_unbind, }; +void exynos_dsi_restrack_cb(struct device *dev, int ret) +{ + if (ret) + component_del(dev, _dsi_component_ops); + else + component_add(dev, _dsi_component_ops); +} + static int exynos_dsi_probe(struct platform_device *pdev) { struct device *dev = >dev; + struct restrack_ctx *rtrack; struct resource *res; struct exynos_dsi *dsi; int ret; @@ -1728,26 +1737,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->supplies[0].supply = "vddcore"; dsi->supplies[1].supply = "vddio"; - ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies), - dsi->supplies); - if (ret) { - dev_info(dev, "failed to get regulators: %d\n", ret); - return -EPROBE_DEFER; - } - - dsi->pll_clk = devm_clk_get(dev, "pll_clk"); - if (IS_ERR(dsi->pll_clk)) { - dev_info(dev, "failed to get dsi pll input clock\n"); - ret = PTR_ERR(dsi->pll_clk); - goto err_del_component; - } - - dsi->bus_clk = devm_clk_get(dev, "bus_clk"); - if (IS_ERR(dsi->bus_clk)) { - dev_info(dev, "failed to get dsi bus clock\n"); - ret = PTR_ERR(dsi->bus_clk); - goto err_del_component; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dsi->reg_base = devm_ioremap_resource(dev, res); @@ -1757,13 +1746,6 @@ static int exynos_dsi_probe(struct platform_device *pdev) goto err_del_component; } - dsi->phy = devm_phy_get(dev, "dsim"); - if (IS_ERR(dsi->phy)) { - dev_info(dev, "failed to get dsim phy\n"); - ret = PTR_ERR(dsi->phy); - goto err_del_component; - } - dsi->irq = platform_get_irq(pdev, 0); if (dsi->irq < 0) { dev_err(dev, "failed to request dsi irq resource\n"); @@ -1782,11 +1764,20 @@ static int exynos_dsi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, >display); - ret = component_add(dev, _dsi_component_ops); + rtrack = devm_restrack_register(dsi->dev, exynos_dsi_restrack_cb, + regulator_bulk_restrack_desc(>supplies[0]), + regulator_bulk_restrack_desc(>supplies[1]), + clk_restrack_desc(>pll_clk, "pll_clk"), + clk_restrack_desc(>bus_clk, "bus_clk"), + phy_restrack_desc(>phy, "dsim"), + ); + + ret = PTR_ERR_OR_ZERO(rtrack); + if (ret) goto err_del_component; - return ret; + return 0; err_del_component: exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR); @@ -1795,7 +1786,6 @@ err_del_component: static int exynos_dsi_remove(struct platform_device *pdev) { - component_del(>dev, _dsi_component_ops); exynos_drm_component_del(>dev, EXYNOS_DEVICE_TYPE_CONNECTOR); return 0; -- 1.9.1
[RFC 10/15] drm/exynos/dsi: simplify hotplug code
Exynos DSI driver uses DSI bus attach/detach callbacks to implement panel hotplug mechanism. The patch moves panel attachment code from .detect callback to DSI bus callbacks. It makes the code simpler and more straightforward. The patch removes also redundant and lock unprotected dpms_off call from unbind code. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 61 - 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 05fe93d..8201d79 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -271,7 +271,6 @@ struct exynos_dsi { struct exynos_drm_display display; struct mipi_dsi_host dsi_host; struct drm_connector connector; - struct device_node *panel_node; struct drm_panel *panel; struct device *dev; @@ -1154,10 +1153,11 @@ static int exynos_dsi_init(struct exynos_dsi *dsi) static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi) { + struct device_node *panel_node = dsi->panel->dev->of_node; int ret; int te_gpio_irq; - dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0); + dsi->te_gpio = of_get_named_gpio(panel_node, "te-gpios", 0); if (!gpio_is_valid(dsi->te_gpio)) { dev_err(dsi->dev, "no te-gpios specified\n"); ret = dsi->te_gpio; @@ -1198,11 +1198,25 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host); + struct drm_device *drm_dev = dsi->connector.dev; + bool changed = false; dsi->lanes = device->lanes; dsi->format = device->format; dsi->mode_flags = device->mode_flags; - dsi->panel_node = device->dev.of_node; + + mutex_lock(_dev->mode_config.mutex); + + dsi->panel = of_drm_find_panel(device->dev.of_node); + if (dsi->panel) { + drm_panel_attach(dsi->panel, >connector); + if (drm_dev->mode_config.poll_enabled) { + dsi->connector.status = connector_status_connected; + changed = true; + } + } + + mutex_unlock(_dev->mode_config.mutex); /* * This is a temporary solution and should be made by more generic way. @@ -1217,8 +1231,8 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, return ret; } - if (dsi->connector.dev) - drm_helper_hpd_irq_event(dsi->connector.dev); + if (changed) + drm_kms_helper_hotplug_event(drm_dev); return 0; } @@ -1227,13 +1241,29 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host); + struct drm_device *drm_dev = dsi->connector.dev; + struct exynos_drm_display *display = dev_get_drvdata(dsi->dev); + bool changed = false; exynos_dsi_unregister_te_irq(dsi); - dsi->panel_node = NULL; + mutex_lock(_dev->mode_config.mutex); + + display->ops->dpms(display, DRM_MODE_DPMS_OFF); + + if (dsi->panel) { + drm_panel_detach(dsi->panel); + dsi->panel = NULL; + if (drm_dev->mode_config.poll_enabled) { + dsi->connector.status = connector_status_disconnected; + changed = true; + } + } + + mutex_unlock(_dev->mode_config.mutex); - if (dsi->connector.dev) - drm_helper_hpd_irq_event(dsi->connector.dev); + if (changed) + drm_kms_helper_hotplug_event(drm_dev); return 0; } @@ -1430,19 +1460,6 @@ exynos_dsi_detect(struct drm_connector *connector, bool force) { struct exynos_dsi *dsi = connector_to_dsi(connector); - if (!dsi->panel) { - dsi->panel = of_drm_find_panel(dsi->panel_node); - if (dsi->panel) - drm_panel_attach(dsi->panel, >connector); - } else if (!dsi->panel_node) { - struct exynos_drm_display *display; - - display = platform_get_drvdata(to_platform_device(dsi->dev)); - exynos_dsi_dpms(display, DRM_MODE_DPMS_OFF); - drm_panel_detach(dsi->panel); - dsi->panel = NULL; - } - if (dsi->panel) return connector_status_connected; @@ -1665,8 +1682,6 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, struct exynos_drm_display *display = dev_get_drvdata(dev); struct exynos_dsi *dsi = display_to_dsi(display); - exynos_dsi_dpms(display, DRM_MODE_DPMS_OFF); - mipi_dsi_host_unregister(>dsi_host); } --
[RFC 09/15] phy: add restrack support
PHYs supports different methods of lookup. The patch adds restrack support only to DT based PHYs. Signed-off-by: Andrzej Hajda --- drivers/phy/phy-core.c | 90 include/linux/phy/phy.h | 3 ++ include/linux/restrack.h | 1 + 3 files changed, 94 insertions(+) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index ff5eec5..449ec4e 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -22,6 +22,7 @@ #include #include #include +#include static struct class *phy_class; static DEFINE_MUTEX(phy_provider_mutex); @@ -754,6 +755,8 @@ struct phy_provider *__of_phy_provider_register(struct device *dev, list_add_tail(_provider->list, _provider_list); mutex_unlock(_provider_mutex); + restrack_up(RESTRACK_TYPE_PHY, dev->of_node, phy_provider); + return phy_provider; } EXPORT_SYMBOL_GPL(__of_phy_provider_register); @@ -804,6 +807,9 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider) if (IS_ERR(phy_provider)) return; + restrack_down(RESTRACK_TYPE_PHY, phy_provider->dev->of_node, + phy_provider); + mutex_lock(_provider_mutex); list_del(_provider->list); kfree(phy_provider); @@ -828,6 +834,90 @@ void devm_of_phy_provider_unregister(struct device *dev, } EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister); +int of_get_phy_spec(struct device *dev, const char *name, + struct of_phandle_args *spec) +{ + struct device_node *np = dev->of_node; + int idx; + + idx = of_property_match_string(np, "phy-names", name); + + return of_parse_phandle_with_args(np, "phys", "#phy-cells", idx, spec); +} + +struct phy_restrack_desc { + struct phy **ptr; + const char *name; + struct of_phandle_args spec; + struct restrack_desc desc; +}; + +static int phy_restrack_init(struct device *dev, + struct restrack_desc *desc) +{ + struct phy_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + int ret; + + ret = of_get_phy_spec(dev, rd->name, >spec); + if (!ret) + desc->if_id = rd->spec.np; + return ret; +} + +static void phy_restrack_destroy(struct device *dev, + struct restrack_desc *desc) +{ + struct phy_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + of_node_put(desc->if_id); + kfree(rd); +} + +static int phy_restrack_ifup(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct phy_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + struct phy_provider *phy_provider = data; + + *rd->ptr = phy_provider->of_xlate(phy_provider->dev, >spec); + return PTR_ERR_OR_ZERO(*rd->ptr); +} + +static void phy_restrack_ifdown(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct phy_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = ERR_PTR(-EPROBE_DEFER); +} + +static const struct restrack_ops phy_restrack_ops = { + .if_type = RESTRACK_TYPE_PHY, + .init = phy_restrack_init, + .destroy = phy_restrack_destroy, + .if_up = phy_restrack_ifup, + .if_down = phy_restrack_ifdown, +}; + +/** + * phy_restrack_desc - phy resource descriptor allocator + * @phy: pointer to variable which will be set to phy handle + * @name: name of phy + * + * The function creates resource description for phy, which shall be used + * by *restrack_register functions. + */ +struct restrack_desc *phy_restrack_desc(struct phy **phy, const char *name) +{ + struct phy_restrack_desc *rd; + + RESTRACK_DESC_ALLOC(rd, phy_restrack_ops, phy, name); + + return rd ? >desc : ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(phy_restrack_desc); + + /** * phy_release() - release the phy * @dev: the dev member within phy diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 8cb6f81..14d176c 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -174,6 +174,9 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev, void of_phy_provider_unregister(struct phy_provider *phy_provider); void devm_of_phy_provider_unregister(struct device *dev, struct phy_provider *phy_provider); + +struct restrack_desc; +struct restrack_desc *phy_restrack_desc(struct phy **phy, const char *name); #else static inline int phy_pm_runtime_get(struct phy *phy) { diff --git a/include/linux/restrack.h b/include/linux/restrack.h index 6707dce..411d791 100644 --- a/include/linux/restrack.h +++ b/include/linux/restrack.h @@ -7,6 +7,7 @@ #define RESTRACK_TYPE_REGULATOR 2 #define RESTRACK_TYPE_GPIO 3 #define RESTRACK_TYPE_CLOCK 4 +#define RESTRACK_TYPE_PHY 5 struct device; struct restrack_ctx; -- 1.9.1
[RFC 08/15] clk: add restrack support
Clocks supports different methods of lookup. The patch adds restrack support only to DT based clocks. Signed-off-by: Andrzej Hajda --- drivers/clk/clk.c| 6 drivers/clk/clkdev.c | 74 include/linux/clk.h | 3 ++ include/linux/restrack.h | 1 + 4 files changed, 84 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4896ae9..2c50204 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -2476,6 +2477,9 @@ int of_clk_add_provider(struct device_node *np, ret = of_clk_set_defaults(np, true); if (ret < 0) of_clk_del_provider(np); + else + restrack_up(RESTRACK_TYPE_CLOCK, cp->node, cp); + return ret; } @@ -2489,6 +2493,8 @@ void of_clk_del_provider(struct device_node *np) { struct of_clk_provider *cp; + restrack_down(RESTRACK_TYPE_CLOCK, np, NULL); + mutex_lock(_clk_mutex); list_for_each_entry(cp, _clk_providers, link) { if (cp->node == np) { diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index bd22750..2532ea1 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "clk.h" @@ -143,6 +144,79 @@ static int of_get_clock_spec(struct device *dev, const char *name, return -ENOENT; } + +struct clk_restrack_desc { + struct clk **ptr; + const char *name; + struct of_phandle_args spec; + struct restrack_desc desc; +}; + +static int clk_restrack_init(struct device *dev, + struct restrack_desc *desc) +{ + struct clk_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + int ret; + + ret = of_get_clock_spec(dev, rd->name, >spec); + if (!ret) + desc->if_id = rd->spec.np; + return ret; +} + +static void clk_restrack_destroy(struct device *dev, + struct restrack_desc *desc) +{ + struct clk_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + of_node_put(desc->if_id); + kfree(rd); +} + +static int clk_restrack_ifup(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct clk_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = of_clk_get_by_clkspec(>spec); + return PTR_ERR_OR_ZERO(*rd->ptr); +} + +static void clk_restrack_ifdown(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct clk_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + clk_put(*rd->ptr); + *rd->ptr = ERR_PTR(-EPROBE_DEFER); +} + +static const struct restrack_ops clk_restrack_ops = { + .if_type = RESTRACK_TYPE_CLOCK, + .init = clk_restrack_init, + .destroy = clk_restrack_destroy, + .if_up = clk_restrack_ifup, + .if_down = clk_restrack_ifdown, +}; + +/** + * clk_restrack_desc - clock resource descriptor allocator + * @clk: pointer to variable which will be set to clock handle + * @name: name of clock + * + * The function creates resource description for clock, which shall be used + * by *restrack_register functions. + */ +struct restrack_desc *clk_restrack_desc(struct clk **clock, const char *name) +{ + struct clk_restrack_desc *rd; + + RESTRACK_DESC_ALLOC(rd, clk_restrack_ops, clock, name); + + return rd ? >desc : ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(clk_restrack_desc); + #endif /* diff --git a/include/linux/clk.h b/include/linux/clk.h index c7f258a..28bad95 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -428,6 +428,9 @@ struct of_phandle_args; struct clk *of_clk_get(struct device_node *np, int index); struct clk *of_clk_get_by_name(struct device_node *np, const char *name); struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec); + +struct restrack_desc; +struct restrack_desc *clk_restrack_desc(struct clk **clock, const char *name); #else static inline struct clk *of_clk_get(struct device_node *np, int index) { diff --git a/include/linux/restrack.h b/include/linux/restrack.h index e1aded0..6707dce 100644 --- a/include/linux/restrack.h +++ b/include/linux/restrack.h @@ -6,6 +6,7 @@ #define RESTRACK_TYPE_DRM_PANEL 1 #define RESTRACK_TYPE_REGULATOR 2 #define RESTRACK_TYPE_GPIO 3 +#define RESTRACK_TYPE_CLOCK 4 struct device; struct restrack_ctx; -- 1.9.1
[RFC 07/15] clk: add DT parsing function
The patch adds function for parsing Device Tree to get clock specifier. The function could be ultimately used by clock core. Signed-off-by: Andrzej Hajda --- drivers/clk/clkdev.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index da4bda8..bd22750 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -120,6 +120,29 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) return clk; } EXPORT_SYMBOL(of_clk_get_by_name); + +static int of_get_clock_spec(struct device *dev, const char *name, + struct of_phandle_args *spec) +{ + struct device_node *np = dev->of_node; + + while (np) { + int idx = 0; + + if (name) + idx = of_property_match_string(np, "clock-names", name); + + if (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", + idx, spec)) + return 0; + + np = np->parent; + if (np && !of_get_property(np, "clock-ranges", NULL)) + break; + } + + return -ENOENT; +} #endif /* -- 1.9.1
[RFC 06/15] gpio: add restrack support
GPIO supports different methods of lookup. The patch adds restrack support only to DT based GPIOs. Signed-off-by: Andrzej Hajda --- drivers/gpio/gpiolib.c| 81 +++ include/linux/gpio/consumer.h | 4 +++ include/linux/restrack.h | 1 + 3 files changed, 86 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 78fcec9..5d85e20 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "gpiolib.h" @@ -278,6 +279,8 @@ int gpiochip_add(struct gpio_chip *chip) if (status) goto fail; + restrack_up(RESTRACK_TYPE_GPIO, chip->of_node, chip); + status = gpiochip_export(chip); if (status) goto fail; @@ -313,6 +316,7 @@ void gpiochip_remove(struct gpio_chip *chip) unsigned long flags; unsignedid; + restrack_down(RESTRACK_TYPE_GPIO, chip->of_node, chip); acpi_gpiochip_remove(chip); spin_lock_irqsave(_lock, flags); @@ -1770,6 +1774,83 @@ void gpiod_put(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_put); +struct gpiod_restrack_desc { + struct gpio_desc **ptr; + const char *name; + enum gpiod_flags flags; + struct of_phandle_args spec; + struct restrack_desc desc; +}; + +static int gpiod_restrack_init(struct device *dev, struct restrack_desc *desc) +{ + struct gpiod_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + int ret; + + ret = of_get_gpiod_spec(dev, rd->name, 0, >spec); + if (!ret) + desc->if_id = rd->spec.np; + return ret; +} + +static void gpiod_restrack_destroy(struct device *dev, + struct restrack_desc *desc) +{ + struct gpiod_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + of_node_put(desc->if_id); + kfree(rd); +} + +static int gpiod_restrack_ifup(struct device *dev, struct restrack_desc *desc, + void *data) +{ + struct gpiod_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = gpiod_get(dev, rd->name, rd->flags); + return PTR_ERR_OR_ZERO(*rd->ptr); +} + +static void gpiod_restrack_ifdown(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct gpiod_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + gpiod_put(*rd->ptr); + *rd->ptr = ERR_PTR(-EPROBE_DEFER); +} + +static const struct restrack_ops gpiod_restrack_ops = { + .if_type = RESTRACK_TYPE_GPIO, + .init = gpiod_restrack_init, + .destroy = gpiod_restrack_destroy, + .if_up = gpiod_restrack_ifup, + .if_down = gpiod_restrack_ifdown, +}; + +/** + * gpiod_restrack_desc - gpio resource descriptor allocator + * @gpiod: pointer to variable which will be set to gpiod handle + * @name: name of gpio + * @flags: gpiod flags + * + * The function creates resource description for gpio, which shall be used + * by *restrack_register functions. + */ +struct restrack_desc *gpiod_restrack_desc(struct gpio_desc **gpiod, + const char *con_id, enum gpiod_flags flags) +{ + struct gpiod_restrack_desc *rd; + + RESTRACK_DESC_ALLOC(rd, gpiod_restrack_ops, gpiod, con_id); + if (!rd) + return ERR_PTR(-ENOMEM); + + rd->flags = flags; + return >desc; +} +EXPORT_SYMBOL_GPL(gpiod_restrack_desc); + #ifdef CONFIG_DEBUG_FS static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 12f146f..55f2e4e 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -94,6 +94,10 @@ int gpiod_to_irq(const struct gpio_desc *desc); struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); +struct restrack_desc; +struct restrack_desc *gpiod_restrack_desc(struct gpio_desc **gpiod, + const char *con_id, enum gpiod_flags flags); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, diff --git a/include/linux/restrack.h b/include/linux/restrack.h index 4e4eec6..e1aded0 100644 --- a/include/linux/restrack.h +++ b/include/linux/restrack.h @@ -5,6 +5,7 @@ #define RESTRACK_TYPE_DRM_PANEL 1 #define RESTRACK_TYPE_REGULATOR 2 +#define RESTRACK_TYPE_GPIO 3 struct device; struct restrack_ctx; -- 1.9.1
[RFC 05/15] gpio: move DT parsing code to separate functions
The patch moves Device Tree parsing logic to separate function. Signed-off-by: Andrzej Hajda --- drivers/gpio/gpiolib-of.c | 59 +-- drivers/gpio/gpiolib.c| 33 +++--- drivers/gpio/gpiolib.h| 4 ++-- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 604dbe6..4707727 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -28,7 +28,7 @@ /* Private data structure for of_gpiochip_find_and_xlate */ struct gg_data { enum of_gpio_flags *flags; - struct of_phandle_args gpiospec; + struct of_phandle_args *gpiospec; struct gpio_desc *out_gpio; }; @@ -39,12 +39,12 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) struct gg_data *gg_data = data; int ret; - if ((gc->of_node != gg_data->gpiospec.np) || - (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) || + if ((gc->of_node != gg_data->gpiospec->np) || + (gc->of_gpio_n_cells != gg_data->gpiospec->args_count) || (!gc->of_xlate)) return false; - ret = gc->of_xlate(gc, _data->gpiospec, gg_data->flags); + ret = gc->of_xlate(gc, gg_data->gpiospec, gg_data->flags); if (ret < 0) return false; @@ -52,61 +52,54 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) return true; } -/** - * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API - * @np:device node to get GPIO from - * @propname: property name containing gpio specifier(s) - * @index: index of the GPIO - * @flags: a flags pointer to fill in - * - * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno - * value on the error condition. If @flags is not NULL the function also fills - * in flags for the GPIO. - */ -struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, -const char *propname, int index, enum of_gpio_flags *flags) +struct gpio_desc *of_get_gpiod_by_spec(struct of_phandle_args *spec, + enum of_gpio_flags *flags) { /* Return -EPROBE_DEFER to support probe() functions to be called * later when the GPIO actually becomes available */ struct gg_data gg_data = { .flags = flags, - .out_gpio = ERR_PTR(-EPROBE_DEFER) + .out_gpio = ERR_PTR(-EPROBE_DEFER), + .gpiospec = spec }; - int ret; /* .of_xlate might decide to not fill in the flags, so clear it. */ if (flags) *flags = 0; - ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, -_data.gpiospec); - if (ret) { - pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n", - __func__, propname, np->full_name, index); - return ERR_PTR(ret); - } - gpiochip_find(_data, of_gpiochip_find_and_xlate); - of_node_put(gg_data.gpiospec.np); - pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n", -__func__, propname, np->full_name, index, + pr_debug("%s: parsed property of node '%s[%d]' - status (%d)\n", +__func__, spec->np->full_name, spec->args[0], PTR_ERR_OR_ZERO(gg_data.out_gpio)); + return gg_data.out_gpio; } int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags) { + struct of_phandle_args spec; struct gpio_desc *desc; + int ret; + + ret = of_parse_phandle_with_args(np, list_name, "#gpio-cells", index, +); + if (ret) { + pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n", + __func__, list_name, np->full_name, index); + return ret; + } - desc = of_get_named_gpiod_flags(np, list_name, index, flags); + desc = of_get_gpiod_by_spec(, flags); if (IS_ERR(desc)) return PTR_ERR(desc); - else - return desc_to_gpio(desc); + + of_node_put(spec.np); + + return desc_to_gpio(desc); } EXPORT_SYMBOL(of_get_named_gpio_flags); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8e98ca..78fcec9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1470,15 +1470,13 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(_lookup_lock); } -static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) +static int of_get_gpiod_spec(struct
[RFC 04/15] regulator: add restrack support
Regulators supports various methods of lookup. The patch adds restrack support only to DT based regulators. Signed-off-by: Andrzej Hajda --- drivers/regulator/core.c | 77 ++ include/linux/regulator/consumer.h | 10 + include/linux/restrack.h | 1 + 3 files changed, 88 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index cd87c0c..5641e85 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -32,6 +32,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -3733,6 +3734,10 @@ add_dev: rdev_init_debugfs(rdev); out: mutex_unlock(_list_mutex); + + if (rdev->dev.of_node) + restrack_up(RESTRACK_TYPE_REGULATOR, rdev->dev.of_node, rdev); + return rdev; unset_supplies: @@ -3767,6 +3772,9 @@ void regulator_unregister(struct regulator_dev *rdev) if (rdev == NULL) return; + if (rdev->dev.of_node) + restrack_down(RESTRACK_TYPE_REGULATOR, rdev->dev.of_node, rdev); + if (rdev->supply) { while (rdev->use_count--) regulator_disable(rdev->supply); @@ -3971,6 +3979,75 @@ static const struct file_operations supply_map_fops = { #endif }; +struct regulator_restrack_desc { + struct regulator **ptr; + const char *name; + struct restrack_desc desc; +}; + +static int regulator_restrack_init(struct device *dev, + struct restrack_desc *desc) +{ + struct regulator_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + desc->if_id = of_get_regulator(dev, rd->name); + return PTR_ERR_OR_ZERO(desc->if_id); +} + +static void regulator_restrack_destroy(struct device *dev, + struct restrack_desc *desc) +{ + struct regulator_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + of_node_put(desc->if_id); + kfree(rd); +} + +static int regulator_restrack_ifup(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct regulator_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = regulator_get(dev, rd->name); + return PTR_ERR_OR_ZERO(*rd->ptr); +} + +static void regulator_restrack_ifdown(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct regulator_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + regulator_put(*rd->ptr); + *rd->ptr = ERR_PTR(-EPROBE_DEFER); +} + +static const struct restrack_ops regulator_restrack_ops = { + .if_type = RESTRACK_TYPE_REGULATOR, + .init = regulator_restrack_init, + .destroy = regulator_restrack_destroy, + .if_up = regulator_restrack_ifup, + .if_down = regulator_restrack_ifdown, +}; + +/** + * regulator_restrack_desc - regulator resource descriptor allocator + * @regulator: pointer to variable which will be set to regulator handle + * @name: name of regulator + * + * The function creates resource description for regulator, which shall be used + * by *restrack_register functions. + */ +struct restrack_desc *regulator_restrack_desc(struct regulator **regulator, + const char *name) +{ + struct regulator_restrack_desc *rd; + + RESTRACK_DESC_ALLOC(rd, regulator_restrack_ops, regulator, name); + + return rd ? >desc : ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(regulator_restrack_desc); + static int __init regulator_init(void) { int ret; diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index f540b14..69e71ebb 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -551,4 +551,14 @@ static inline int regulator_is_supported_voltage_tol(struct regulator *regulator target_uV + tol_uV); } +struct restrack_desc; +struct restrack_desc *regulator_restrack_desc(struct regulator **regulator, + const char *supply); + +static inline struct restrack_desc * +regulator_bulk_restrack_desc(struct regulator_bulk_data *data) +{ + return regulator_restrack_desc(>consumer, data->supply); +} + #endif diff --git a/include/linux/restrack.h b/include/linux/restrack.h index af5b617..4e4eec6 100644 --- a/include/linux/restrack.h +++ b/include/linux/restrack.h @@ -4,6 +4,7 @@ #include #define RESTRACK_TYPE_DRM_PANEL 1 +#define RESTRACK_TYPE_REGULATOR 2 struct device; struct restrack_ctx; -- 1.9.1
[RFC 03/15] drm/panel: add restrack support
The patch adds Device Tree restrack support to drm/panel framework. As panels supports only Device Tree based lookup all panels can be converted to restrack. Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/drm_panel.c | 97 + include/drm/drm_panel.h | 4 ++ include/linux/restrack.h| 2 + 3 files changed, 103 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 2ef988e..db04696 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -22,7 +22,9 @@ */ #include +#include #include +#include #include #include @@ -41,6 +43,7 @@ int drm_panel_add(struct drm_panel *panel) mutex_lock(_lock); list_add_tail(>list, _list); mutex_unlock(_lock); + restrack_up(RESTRACK_TYPE_DRM_PANEL, panel->dev->of_node, panel); return 0; } @@ -48,6 +51,7 @@ EXPORT_SYMBOL(drm_panel_add); void drm_panel_remove(struct drm_panel *panel) { + restrack_down(RESTRACK_TYPE_DRM_PANEL, panel->dev->of_node, panel); mutex_lock(_lock); list_del_init(>list); mutex_unlock(_lock); @@ -93,6 +97,99 @@ struct drm_panel *of_drm_find_panel(struct device_node *np) return NULL; } EXPORT_SYMBOL(of_drm_find_panel); + +struct drm_panel_restrack_desc { + struct drm_panel **ptr; + const char *name; + int port; + struct restrack_desc desc; +}; + +static int drm_panel_restrack_init(struct device *dev, + struct restrack_desc *desc) +{ + struct drm_panel_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + struct device_node *np; + + if (rd->name) { + desc->if_id = of_parse_phandle(dev->of_node, rd->name, 0); + goto end; + } + + np = NULL; + while ((np = of_graph_get_next_endpoint(dev->of_node, np))) { + struct of_endpoint ep; + + of_graph_parse_endpoint(np, ); + if (ep.port != rd->port) + continue; + desc->if_id = of_graph_get_remote_port_parent(np); + of_node_put(np); + break; + } + +end: + return desc->if_id ? 0 : -EINVAL; +} + +static void drm_panel_restrack_destroy(struct device *dev, + struct restrack_desc *desc) +{ + struct drm_panel_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + of_node_put(desc->if_id); + kfree(rd); +} + +static int drm_panel_restrack_ifup(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct drm_panel_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = data; + return PTR_ERR_OR_ZERO(*rd->ptr); +} + +static void drm_panel_restrack_ifdown(struct device *dev, + struct restrack_desc *desc, void *data) +{ + struct drm_panel_restrack_desc *rd = restrack_desc_to_rd(rd, desc); + + *rd->ptr = ERR_PTR(-EPROBE_DEFER); +} + +static const struct restrack_ops drm_panel_restrack_ops = { + .if_type = RESTRACK_TYPE_DRM_PANEL, + .init = drm_panel_restrack_init, + .destroy = drm_panel_restrack_destroy, + .if_up = drm_panel_restrack_ifup, + .if_down = drm_panel_restrack_ifdown, +}; + +/** + * drm_panel_restrack_desc - drm_panel resource descriptor allocator + * @panel: pointer to variable which will be set to drm_panel handle + * @prop_name: property name containing phandle to the panel node, it can be + *NULL if driver uses only of_graph + * @port: of_graph port number in case of_graph is used + * + * The function creates resource description for panel, which shall be used by + * *restrack_register functions. + */ +struct restrack_desc *drm_panel_restrack_desc(struct drm_panel **panel, + const char *prop_name, int port) +{ + struct drm_panel_restrack_desc *rd; + + RESTRACK_DESC_ALLOC(rd, drm_panel_restrack_ops, panel, prop_name); + if (!rd) + return ERR_PTR(-ENOMEM); + + rd->port = port; + return >desc; +} +EXPORT_SYMBOL_GPL(drm_panel_restrack_desc); + #endif MODULE_AUTHOR("Thierry Reding "); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 1fbcc96..46eb88e 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -130,6 +130,10 @@ int drm_panel_detach(struct drm_panel *panel); #ifdef CONFIG_OF struct drm_panel *of_drm_find_panel(struct device_node *np); + +struct restrack_desc; +struct restrack_desc *drm_panel_restrack_desc(struct drm_panel **panel, + const char *prop_name, int port); #else static inline struct drm_panel *of_drm_find_panel(struct device_node *np) { diff --git a/include/linux/restrack.h b/include/linux/restrack.h index 6cf8144f..af5b617 100644 --- a/include/linux/restrack.h +++ b/include/linux/restrack.h @@ -3,6 +3,8 @@ #include +#define RESTRACK_TYPE_DRM_PANEL 1 + struct device; struct restrack_ctx; struct restrack_desc; --
[RFC 02/15] drivers/base: add restrack framework
restrack framework allows tracking presence of resources with dynamic life time. Typical example of such resources are all resources provided by device drivers, for example clocks, phys, regulators. Since drivers can be bound and unbound dynamically and unconditionally, resources provided by such drivers can appear and disappear at any time. To use restrack in consumer user should call one of *restrack_register functions. In the function arguments consumer should provide callback and description of resources which should be tracked. Each resource description should contain pointer to variable where restrack should store address of allocated resource and parameters describing specific resource, for example in case of clock it should be clock name and in case of gpio it should be gpio name and flags. The callback should have two arguments: - dev - device for which callback have been registered, - ret - return code. If callback is called with ret == 0 it means all tracked resources are present, allocated and provided resource pointers are set accordingly. In case ret == -EPROBE_DEFER it means all resources are present but at least one of the resources are to be removed after return form the callback. Simplified example of framework usage on LCD panel driver. static int lcd_probe(...) { struct restrack *rtrack; (...initialization w/o resource allocation ...) rtrack = devm_restrack_register(dev, lcd_callback, regulator_bulk_restrack_desc(>supplies[0]), regulator_bulk_restrack_desc(>supplies[1]), clk_restrack_desc(>pll_clk, "pll_clk"), clk_restrack_desc(>bus_clk, "bus_clk"), phy_restrack_desc(>phy, "dsim"), ); return PTR_ERR_OR_NULL(rtrack); } void lcd_callback(struct device *dev, int ret) { struct lcd_ctx *ctx = dev_get_drvdata(dev); if (ret == 0) drm_panel_add(>panel); else if (ret == -EPROBE_DEFER) drm_panel_remove(>panel); else dev_err(dev, "restrack error %d\n", ret); } Please note few things: 1. drm_panel_add calls restrack_up and drm_panel_remove calls restrack_down. It is OK to call restrack framework from the callback. 2. In lcd_callback if ret is 0 or -EDEFER_PROBE all resources are valid, ie driver for example can call clk_prepare_enable(ctx->pll_clk). 3. No mutexes are needed to protect lcd_ctx in lcd_callback call. 4. All resources are freed by restrack_unregister, which in this case is called by devres framework. To add restrack support to specific framework following things should be defined: - structure describing resource with embedded restrack_desc structure, - at least one exported allocator of such structure, - few simple operations according to description of struct restrack_ops, - notifications about adding/removal of the resource. For details please look at implementations. Signed-off-by: Andrzej Hajda --- drivers/base/Makefile| 2 +- drivers/base/restrack.c | 344 +++ include/linux/restrack.h | 137 +++ 3 files changed, 482 insertions(+), 1 deletion(-) create mode 100644 drivers/base/restrack.c create mode 100644 include/linux/restrack.h diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 4edff7d..cf9a21e 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -4,7 +4,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ - topology.o container.o track.o + topology.o container.o track.o restrack.o obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-$(CONFIG_DMA_CMA) += dma-contiguous.o obj-y += power/ diff --git a/drivers/base/restrack.c b/drivers/base/restrack.c new file mode 100644 index 000..e16d8ed --- /dev/null +++ b/drivers/base/restrack.c @@ -0,0 +1,344 @@ +/* + * Resource tracking framework + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * Andrzej Hajda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * restrack framework allows to track presence of resources with dynamic life + * time. Typical example of such resources are all resources provided by device + * drivers, for example clocks, phys, regulators. Since drivers can be bound and + * unbound dynamically and unconditionally, resources provided by such drivers + * can appear and disappear at any time. + * + * To use restrack in consumer user should call one of *restrack_register + * functions. In the function arguments consumer should provide callback and + * description of resources
[RFC 01/15] drivers/base: add track framework
track is a generic framework for safe tracking presence of any kernel objects having an id. There are no special requirements about type of object or its id. Id shall be unique. Typical usage of the framework by consumer looks as follow: 1. Consumer registers notifier callback for objects with given id. 2. If the object is present consumer is notified immediately, otherwise it will be notified immediately after object creation. 3. If the object is about to be removed notification is sent to the consumer just before removal. 4. When consumer do not need the object anymore it unregisters its notifier callback. If the object is present during notifier unregistration notification about removal of the object is sent to the consumer. All notification callbacks are serialized so the consumer do not need use additional mechanisms to prevent callback races. Consumer should assume that object is valid only between up and down notification callbacks inclusive. Framework usage by object provider is simple: 1. When object becomes available it notifies framework about it. 2. When object becomes unavailable it notifies framework about it. Provider should take care of calling notifications synchronously in proper order. The framework does not uses locks during notification calls, so it is safe to call framework functions from the callbacks. This feature allows to model complex object dependencies without deadlock risk. Some framework functions can sleep so the framework should be used in process context. Signed-off-by: Andrzej Hajda --- drivers/base/Makefile | 2 +- drivers/base/track.c | 241 ++ include/linux/track.h | 148 +++ 3 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 drivers/base/track.c create mode 100644 include/linux/track.h diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 6922cd6..4edff7d 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -4,7 +4,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ - topology.o container.o + topology.o container.o track.o obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-$(CONFIG_DMA_CMA) += dma-contiguous.o obj-y += power/ diff --git a/drivers/base/track.c b/drivers/base/track.c new file mode 100644 index 000..8cf0492 --- /dev/null +++ b/drivers/base/track.c @@ -0,0 +1,241 @@ +/* + * Generic framework for tracking named object + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * Andrzej Hajda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * track is a generic framework for safe tracking presence of any kernel objects + * having an id. There are no special requirements about type of object or its + * id. Id shall be unique. + * Typical usage of the framework by consumer looks as follow: + * 1. Consumer registers notifier callback for objects with given id. + * 2. If the object is present consumer is notified immediately, otherwise it + *will be notified immediately after object creation. + * 3. If the object is about to be removed notification is sent to the consumer + *just before removal. + * 4. When consumer do not need the object anymore it unregisters its notifier + *callback. If the object is present during notifier unregistration + *notification about removal of the object is sent to the consumer. + * + * All notification callbacks are serialized so the consumer do not need use + * additional mechanisms to prevent callback races. Consumer should assume that + * object is valid only between up and down notification callbacks inclusive. + * + * Framework usage by object provider is simple: + * 1. When object becomes available it notifies framework about it. + * 2. When object becomes unavailable it notifies framework about it. + * + * Provider should take care of calling notifications synchronously in proper + * order. + * + * The framework does not uses locks during notification calls, so it is safe + * to call framework functions from the callbacks. This feature allows to model + * complex object dependencies without deadlock risk. + * + * Some framework functions can sleep so the framework should be used in process + * context. + * + */ +#include +#include +#include + +struct track_task { + struct list_head list; + enum track_task_id task_id; + + unsigned long type; + const void *id; + union { + void *data; + struct track_block *itb; + }; +}; + +struct track_node { + struct list_head list; +
[RFC 00/15] Resource tracking/allocation framework
Hi, Many kernel frameworks that uses provider/consumer schema suffer from few issues: 1. They have broken driver unbinding handling. When device driver of the provider is unbound from the device, its consumers stay with reference to non-existing objects, as a result we can observe oopses, crashes, hangs. Frameworks tries to handle it by using: - module refcounting (try_module_get/module_put) - as the name says it protects only from module unloading, not driver unbinding. Additionally it can cause circular dependencies of modules and inability to unload them. - ghost providers - when driver is unbound provider is replaced with phony one, which returns errors on every access. It also does not solve the issue - consumer device can hang if the hardware represented by the provider is off. 2. Consumer does not know when required resource becomes available. Currently it is solved by deferred probing. The main problem with this solution is that it delays deferred device probe to late_initcall, for some devices it is unacceptable/undesirable. 3. There are drivers which can work without specific resource, but if the resource becomes available/unavailable it can do some additional stuff. An example of such driver is DRM driver (more precisely drm_connector) - it can start without attached drm_panel, but if the panel becomes available it can react by generating HPD event and start using it. Delaying drm initialization due to lack of panel should be avoided - drm can still be usable without it, for example it can still use HDMI monitor. Currently it can be handled by periodic polling drm_panel framework for the panel, but it is rather an workaround, not a real solution. The main problem with the 1st issue is that drivers cannot be protected from unbinding. So there is no way to prevent removal of resources they provide. The only solution I see is to provide notifications to consumers about incoming removal of resources they are using, so they can react appropriately. Symmetrically we can add notifications about appearance of specific resources, this way the 2nd issue can be solved. And finally with both notifications we can solve the 3rd issue. In the 1st patch I propose generic framework providing such notifications, named track - propositions for better name are welcome. Its main feature is that callbacks are serialized but are not called under lock, it allows two important things: - avoid additional locks in the consumers to protect data access from different callbacks, - call the framework from within the callback, so complex dependencies can be modelled this way, without worries about deadlocks due to framework. The 2nd patch contains restrack framework which uses internally track framework to track and automatically allocate different resources. In short it can replace all resource allocations with single call + callback. Of course it is just a bonus. The most important thing is that it solves all described issues: - it can properly handle provider unbind/re-bind, - it avoids late init due to deferred probing, - it allows to track optional resources. Simple example taken from restrack commit message: static int lcd_probe(...) { struct restrack *rtrack; (...initialization w/o resource allocation ...) rtrack = devm_restrack_register(dev, lcd_callback, regulator_bulk_restrack_desc(>supplies[0]), regulator_bulk_restrack_desc(>supplies[1]), clk_restrack_desc(>pll_clk, "pll_clk"), clk_restrack_desc(>bus_clk, "bus_clk"), phy_restrack_desc(>phy, "dsim"), ); return PTR_ERR_OR_NULL(rtrack); } void lcd_callback(struct device *dev, int ret) { struct lcd_ctx *ctx = dev_get_drvdata(dev); if (ret == 0) drm_panel_add(>panel); else if (ret == -EPROBE_DEFER) drm_panel_remove(>panel); else dev_err(dev, "restrack error %d\n", ret); } For other examples look at patches 11, 13, 15. Patches 3,4,6,8,9 adds restrack support to various frameworks. Restrack support is added only to resources exposed via Device Tree. Adding support for non-DT resources should be also possible, but I guess it can be more complicated as resource lookup mechanism is more fuzzy. Anyway I can work on it if necessary. Moreover these patches in some cases adds redundant code for DT lookup, this redundancy can be removed in final version of the patchset. Also another frameworks may need similar patches. Patch 11 converts exynos-dsi driver to restrack API. It solves issues of provider unbind (1st issue) and late init due to deferred probing (2nd issue). Patch 13 shows how to deal with optional resources (3rd issue). Patch 15 is a simple example how to deal with resources depending on other resources. In this particular case ld9040 lcd panel driver requires presence of regulators
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 --- Comment #4 from Alex Deucher --- (In reply to Sylvain BERTRAND from comment #3) > It seems, those mini freezes started to happen after the my last pull from > drm-next-3.19 (see bug #86832) Can you bisect? -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/13b7d097/attachment.html>
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 --- Comment #3 from Sylvain BERTRAND --- It seems, those mini freezes started to happen after the my last pull from drm-next-3.19 (see bug #86832) -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/f1fa1709/attachment.html>
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 --- Comment #2 from Sylvain BERTRAND --- Created attachment 110682 --> https://bugs.freedesktop.org/attachment.cgi?id=110682=edit xorg.log -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/9bfe912b/attachment.html>
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 --- Comment #1 from Sylvain BERTRAND --- Created attachment 110681 --> https://bugs.freedesktop.org/attachment.cgi?id=110681=edit dmesg -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/77a014b6/attachment.html>
[PATCH RFC 15/15] ARM: imx_v6_v7_defconfig: Add support for Himax HX8369A panel
This patch adds support for Himax HX8369A panel. The new imx_v6_v7_defconfig is generated in this way: * make ARCH=arm imx_v6_v7_defconfig * make ARCH=arm menuconfig and manually choose to build in the Himax HX8369A panel driver * make ARCH=arm savedefconfig * cp defconfig arch/arm/configs/imx_v6_v7_defconfig Signed-off-by: Liu Ying --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 3e0e589..01b2b89 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -192,6 +192,7 @@ CONFIG_SOC_CAMERA_OV2640=y CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_PANEL_HX8369A=y CONFIG_DRM_IMX=y CONFIG_DRM_IMX_FB_HELPER=y CONFIG_DRM_IMX_PARALLEL_DISPLAY=y -- 2.1.0
[PATCH RFC 14/15] ARM: imx_v6_v7_defconfig: Add support for MIPI DSI host controller
This patch adds support for MIPI DSI host controller. The new imx_v6_v7_defconfig is generated in this way: * make ARCH=arm imx_v6_v7_defconfig * make ARCH=arm menuconfig and manually choose to build in the MIPI DSI host controller driver * make ARCH=arm savedefconfig * cp defconfig arch/arm/configs/imx_v6_v7_defconfig Signed-off-by: Liu Ying --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 0dbd0c3..3e0e589 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -199,6 +199,7 @@ CONFIG_DRM_IMX_TVE=y CONFIG_DRM_IMX_LDB=y CONFIG_DRM_IMX_IPUV3=y CONFIG_DRM_IMX_HDMI=y +CONFIG_DRM_IMX_MIPI_DSI=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y CONFIG_LCD_PLATFORM=y -- 2.1.0
[PATCH RFC 13/15] ARM: imx_v6_v7_defconfig: Cleanup for imx drm being moved out of staging
The new imx_v6_v7_defconfig is generated in this way: * make ARCH=arm imx_v6_v7_defconfig * make ARCH=arm savedefconfig * cp defconfig arch/arm/configs/imx_v6_v7_defconfig Signed-off-by: Liu Ying --- arch/arm/configs/imx_v6_v7_defconfig | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 6790f1b..0dbd0c3 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -192,7 +192,13 @@ CONFIG_SOC_CAMERA_OV2640=y CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_FB_HELPER=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_TVE=y +CONFIG_DRM_IMX_LDB=y +CONFIG_DRM_IMX_IPUV3=y +CONFIG_DRM_IMX_HDMI=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y CONFIG_LCD_PLATFORM=y @@ -249,13 +255,6 @@ CONFIG_IMX_SDMA=y CONFIG_MXS_DMA=y CONFIG_FSL_EDMA=y CONFIG_STAGING=y -CONFIG_DRM_IMX=y -CONFIG_DRM_IMX_FB_HELPER=y -CONFIG_DRM_IMX_PARALLEL_DISPLAY=y -CONFIG_DRM_IMX_TVE=y -CONFIG_DRM_IMX_LDB=y -CONFIG_DRM_IMX_IPUV3=y -CONFIG_DRM_IMX_HDMI=y # CONFIG_IOMMU_SUPPORT is not set CONFIG_PWM=y CONFIG_PWM_IMX=y -- 2.1.0
[PATCH RFC 12/15] ARM: dts: imx6qdl-sabresd: Add support for TRULY TFT480800-16-E MIPI DSI panel
The TRULY TFT480800-16-E panel is driven by the Himax HX8369A driver IC. The driver IC supports several display/control interface modes, including the MIPI DSI video mode and command mode. Signed-off-by: Liu Ying --- arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 41 ++ 1 file changed, 41 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index baf2f00..483aa5f 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -482,6 +482,13 @@ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 >; }; + + pinctrl_mipi_panel: mipipanelgrp { + fsl,pins = < + MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x1b0b0 + MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x1b0b0 + >; + }; }; gpio_leds { @@ -518,6 +525,40 @@ }; }; +_dsi { + status = "okay"; + + panel at 0 { + compatible = "himax,hx8369a-dsi"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_mipi_panel>; + reset-gpios = < 11 GPIO_ACTIVE_LOW>; + reset-delay = <120>; + bs2-gpios = < 14 GPIO_ACTIVE_HIGH>; + data-lanes = <2>; + panel-width-mm = <45>; + panel-height-mm = <76>; + bs = <10>; + status = "okay"; + + display-timings { + native-mode = <>; + timing1: truly-tft480800-16-e { + clock-frequency = <2640>; + hactive = <480>; + vactive = <800>; + hfront-porch = <8>; + hback-porch = <8>; + hsync-len = <8>; + vfront-porch = <6>; + vback-porch = <6>; + vsync-len = <6>; + }; + }; + }; +}; + { pinctrl-names = "default"; pinctrl-0 = <_pcie>; -- 2.1.0
[PATCH RFC 11/15] ARM: dtsi: imx6qdl: Add support for MIPI DSI host controller
This patch adds support for MIPI DSI host controller. Signed-off-by: Liu Ying --- arch/arm/boot/dts/imx6qdl.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 5d92ad7..4769767 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -1006,7 +1006,14 @@ mipi_dsi: mipi at 021e { #address-cells = <1>; #size-cells = <0>; + compatible = "fsl,imx6q-mipi-dsi"; reg = <0x021e 0x4000>; + interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>; + gpr = <>; + clocks = < IMX6QDL_CLK_VIDEO_27M>, +< IMX6QDL_CLK_HSI_TX>, +< IMX6QDL_CLK_HSI_TX>; + clock-names = "pllref", "pllref_gate", "core_cfg"; status = "disabled"; port at 0 { -- 2.1.0
[PATCH RFC 10/15] drm: panel: Add support for Himax HX8369A MIPI DSI panel
This patch adds support for Himax HX8369A MIPI DSI panel. Signed-off-by: Liu Ying --- .../devicetree/bindings/panel/himax,hx8369a.txt| 86 +++ drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-hx8369a.c | 627 + 4 files changed, 720 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/himax,hx8369a.txt create mode 100644 drivers/gpu/drm/panel/panel-hx8369a.c diff --git a/Documentation/devicetree/bindings/panel/himax,hx8369a.txt b/Documentation/devicetree/bindings/panel/himax,hx8369a.txt new file mode 100644 index 000..6fe251e --- /dev/null +++ b/Documentation/devicetree/bindings/panel/himax,hx8369a.txt @@ -0,0 +1,86 @@ +Himax HX8369A WVGA 16.7M color TFT single chip driver with internal GRAM + +Himax HX8369A is a WVGA resolution driving controller. +It is designed to provide a single chip solution that combines a source +driver and power supply circuits to drive a TFT dot matrix LCD with +480RGBx864 dots at the maximum. + +The HX8369A supports several interface modes, including MPU MIPI DBI Type +A/B mode, MIPI DPI/DBI Type C mode, MIPI DSI video mode, MIPI DSI command +mode and MDDI mode. The interface mode is selected by the external hardware +pins BS[3:0]. + +Currently, only the MIPI DSI video mode is supported. + +Required properties: + - compatible: "himax,hx8369a-dsi" + - reg: the virtual channel number of a DSI peripheral + - reset-gpios: a GPIO spec for the reset pin + - data-lanes: the data lane number of a DSI peripheral + - display-timings: timings for the connected panel as described by [1] + - bs: the interface mode number described by the following table +-- + | DBI_TYPE_A_8BIT | 0 | + | DBI_TYPE_A_9BIT | 1 | + | DBI_TYPE_A_16BIT| 2 | + | DBI_TYPE_A_18BIT| 3 | + | DBI_TYPE_B_8BIT | 4 | + | DBI_TYPE_B_9BIT | 5 | + | DBI_TYPE_B_16BIT| 6 | + | DBI_TYPE_B_18BIT| 7 | + | DSI_CMD_MODE| 8 | + | DBI_TYPE_B_24BIT| 9 | + | DSI_VIDEO_MODE | 10 | + | MDDI| 11 | + | DPI_DBI_TYPE_C_OPT1 | 12 | + | DPI_DBI_TYPE_C_OPT2 | 13 | + | DPI_DBI_TYPE_C_OPT3 | 14 | +-- + +Optional properties: + - power-on-delay: delay after turning regulators on [ms] + - reset-delay: delay after reset sequence [ms] + - vdd1-supply: I/O and interface power supply + - vdd2-supply: analog power supply + - vdd3-supply: logic power supply + - dsi-vcc-supply: DSI and MDDI power supply + - vpp-supply: OTP programming voltage + - bs0-gpios: a GPIO spec for the pin BS0 + - bs1-gpios: a GPIO spec for the pin BS1 + - bs2-gpios: a GPIO spec for the pin BS2 + - bs3-gpios: a GPIO spec for the pin BS3 + - panel-width-mm: physical panel width [mm] + - panel-height-mm: physical panel height [mm] + +[1]: Documentation/devicetree/bindings/video/display-timing.txt + +Example: + panel at 0 { + compatible = "himax,hx8369a-dsi"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <_mipi_panel>; + reset-gpios = < 11 GPIO_ACTIVE_LOW>; + reset-delay = <120>; + bs2-gpios = < 14 GPIO_ACTIVE_HIGH>; + data-lanes = <2>; + panel-width-mm = <45>; + panel-height-mm = <76>; + bs = <10>; + status = "okay"; + + display-timings { + native-mode = <>; + timing1: truly-tft480800-16-e { + clock-frequency = <2640>; + hactive = <480>; + vactive = <800>; + hfront-porch = <8>; + hback-porch = <8>; + hsync-len = <8>; + vfront-porch = <6>; + vback-porch = <6>; + vsync-len = <6>; + }; + }; +}; diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 024e98e..f1a5b58 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -40,4 +40,10 @@ config DRM_PANEL_SHARP_LQ101R1SX01 To compile this driver as a module, choose M here: the module will be called panel-sharp-lq101r1sx01. +config DRM_PANEL_HX8369A + tristate "HX8369A panel" + depends on OF + select DRM_MIPI_DSI + select VIDEOMODE_HELPERS + endmenu diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 4b2a043..d6768ca 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o obj-$(CONFIG_DRM_PANEL_S6E8AA0) +=
[PATCH RFC 09/15] drm: imx: Add MIPI DSI host controller driver
This patch adds i.MX MIPI DSI host controller driver support. Currently, the driver supports the burst with sync pulses mode only. Signed-off-by: Liu Ying --- .../devicetree/bindings/drm/imx/mipi_dsi.txt | 81 ++ drivers/gpu/drm/imx/Kconfig|6 + drivers/gpu/drm/imx/Makefile |1 + drivers/gpu/drm/imx/imx-mipi-dsi.c | 1017 4 files changed, 1105 insertions(+) create mode 100644 Documentation/devicetree/bindings/drm/imx/mipi_dsi.txt create mode 100644 drivers/gpu/drm/imx/imx-mipi-dsi.c diff --git a/Documentation/devicetree/bindings/drm/imx/mipi_dsi.txt b/Documentation/devicetree/bindings/drm/imx/mipi_dsi.txt new file mode 100644 index 000..3d07fd7 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/imx/mipi_dsi.txt @@ -0,0 +1,81 @@ +Device-Tree bindings for MIPI DSI host controller + +MIPI DSI host controller + + +The MIPI DSI host controller is a Synopsys DesignWare IP. +It is a digital core that implements all protocol functions defined +in the MIPI DSI specification, providing an interface between the +system and the MIPI DPHY, and allowing communication with a MIPI DSI +compliant display. + +Required properties: + - #address-cells : Should be <1>. + - #size-cells : Should be <0>. + - compatible : Should be "fsl,imx6q-mipi-dsi" for i.MX6q/sdl SoCs. + - reg : Physical base address of the controller and length of memory + mapped region. + - interrupts : The controller's interrupt number to the CPU(s). + - gpr : Should be <>. + The phandle points to the iomuxc-gpr region containing the + multiplexer control register for the controller. + - clocks, clock-names : Phandles to the controller pllref, pllref_gate + and core_cfg clocks, as described in [1] and [2]. + - panel at 0 : A panel node which contains a display-timings child node as + defined in [3]. + - port@[0-4] : Up to four port nodes with endpoint definitions as defined + in [4], corresponding to the four inputs to the controller multiplexer. + Note that each port node should contain the input-port property to + distinguish it from the panel node, as described in [5]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt +[2] Documentation/devicetree/bindings/clock/imx6q-clock.txt +[3] Documentation/devicetree/bindings/video/display-timing.txt +[4] Documentation/devicetree/bindings/media/video-interfaces.txt +[5] Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt + +example: + gpr: iomuxc-gpr at 020e { + /* ... */ + }; + + mipi_dsi: mipi at 021e { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx6q-mipi-dsi"; + reg = <0x021e 0x4000>; + interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>; + gpr = <>; + clocks = < IMX6QDL_CLK_VIDEO_27M>, +< IMX6QDL_CLK_HSI_TX>, +< IMX6QDL_CLK_HSI_TX>; + clock-names = "pllref", "pllref_gate", "core_cfg"; + + port at 0 { + reg = <0>; + input-port; + + mipi_mux_0: endpoint { + remote-endpoint = <_di0_mipi>; + }; + }; + + port at 1 { + reg = <1>; + input-port; + + mipi_mux_1: endpoint { + remote-endpoint = <_di1_mipi>; + }; + }; + + panel at 0 { + compatible = "himax,hx8369a-dsi"; + reg = <0>; + /* ... */ + + display-timings { + /* ... */ + }; + }; + }; diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index 82fb758..03f04fb 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -51,3 +51,9 @@ config DRM_IMX_HDMI depends on DRM_IMX help Choose this if you want to use HDMI on i.MX6. + +config DRM_IMX_MIPI_DSI + tristate "Freescale i.MX DRM MIPI DSI" + depends on DRM_IMX && MFD_SYSCON + help + Choose this if you want to use MIPI DSI on i.MX6. diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile index 582c438..4571d52 100644 --- a/drivers/gpu/drm/imx/Makefile +++ b/drivers/gpu/drm/imx/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o obj-$(CONFIG_DRM_IMX_IPUV3)+= imx-ipuv3-crtc.o obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o +obj-$(CONFIG_DRM_IMX_MIPI_DSI) += imx-mipi-dsi.o diff --git a/drivers/gpu/drm/imx/imx-mipi-dsi.c b/drivers/gpu/drm/imx/imx-mipi-dsi.c new file mode
[PATCH RFC 08/15] ARM: imx6q: clk: Add the video_27m clock
This patch supports the video_27m clock which is a fixed factor clock of the pll3_pfd1_540m clock. Signed-off-by: Liu Ying --- arch/arm/mach-imx/clk-imx6q.c | 1 + include/dt-bindings/clock/imx6qdl-clock.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 4e79da7..9470df3 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -246,6 +246,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); clk[IMX6QDL_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); clk[IMX6QDL_CLK_GPT_3M]= imx_clk_fixed_factor("gpt_3m","osc", 1, 8); + clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20); if (cpu_is_imx6dl()) { clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1); clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1); diff --git a/include/dt-bindings/clock/imx6qdl-clock.h b/include/dt-bindings/clock/imx6qdl-clock.h index b690cdb..25625bf 100644 --- a/include/dt-bindings/clock/imx6qdl-clock.h +++ b/include/dt-bindings/clock/imx6qdl-clock.h @@ -248,6 +248,7 @@ #define IMX6QDL_PLL6_BYPASS235 #define IMX6QDL_PLL7_BYPASS236 #define IMX6QDL_CLK_GPT_3M 237 -#define IMX6QDL_CLK_END238 +#define IMX6QDL_CLK_VIDEO_27M 238 +#define IMX6QDL_CLK_END239 #endif /* __DT_BINDINGS_CLOCK_IMX6QDL_H */ -- 2.1.0
[PATCH RFC 07/15] ARM: imx6q: Add GPR3 MIPI muxing control register field shift bits definition
This patch adds a macro to define the GPR3 MIPI muxing control register field shift bits. Signed-off-by: Liu Ying --- include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h index ff44374..3b0bed4 100644 --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h @@ -207,6 +207,7 @@ #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1 (0x1 << 6) #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0 (0x2 << 6) #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1 (0x3 << 6) +#define IMX6Q_GPR3_MIPI_MUX_CTL_SHIFT 4 #define IMX6Q_GPR3_MIPI_MUX_CTL_MASK (0x3 << 4) #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI0 (0x0 << 4) #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1 (0x1 << 4) -- 2.1.0
[PATCH RFC 06/15] ARM: dts: imx6q: Add MIPI DSI remote end points for IPU2 DI0/1 end points
This patch adds MIPI DSI remote end points for IPU2 DI0/1 end points. Signed-off-by: Liu Ying --- arch/arm/boot/dts/imx6q.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index e6a6d90..82507e7 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -185,6 +185,7 @@ }; ipu2_di0_mipi: endpoint at 2 { + remote-endpoint = <_mux_2>; }; ipu2_di0_lvds0: endpoint at 3 { @@ -206,6 +207,7 @@ }; ipu2_di1_mipi: endpoint at 2 { + remote-endpoint = <_mux_3>; }; ipu2_di1_lvds0: endpoint at 3 { -- 2.1.0
[PATCH RFC 05/15] ARM: dts: imx6qdl: Add input-port property to MIPI DSI node's CTRC child nodes
To phase out the MIPI DSI's child nodes which present DRM CRTCs from the child nodes which represent MIPI DSI peripherals, we need to add input-port property to the child nodes to be phased out. Signed-off-by: Liu Ying --- arch/arm/boot/dts/imx6q.dtsi | 2 ++ arch/arm/boot/dts/imx6qdl.dtsi | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index e9f3646..e6a6d90 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -294,6 +294,7 @@ _dsi { port at 2 { reg = <2>; + input-port; mipi_mux_2: endpoint { remote-endpoint = <_di0_mipi>; @@ -302,6 +303,7 @@ port at 3 { reg = <3>; + input-port; mipi_mux_3: endpoint { remote-endpoint = <_di1_mipi>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 9596ed5..5d92ad7 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -1011,6 +1011,7 @@ port at 0 { reg = <0>; + input-port; mipi_mux_0: endpoint { remote-endpoint = <_di0_mipi>; @@ -1019,6 +1020,7 @@ port at 1 { reg = <1>; + input-port; mipi_mux_1: endpoint { remote-endpoint = <_di1_mipi>; -- 2.1.0
[PATCH RFC 04/15] drm/dsi: Do not add DSI devices for the child nodes with input-port property
The MIPI DSI bus driver would try to add a DSI device for a host's every child node which contains the reg property. Unfortunately, the existing i.MX6Q/SDL MIPI DSI host device tree node's child nodes contain the reg property, but the child nodes are ports pointing to dedicated CRTCs. So, this patch phases out the child nodes with input-port property before adding DSI devices for them and updates the MIPI DSI bus OF binding documentation. Signed-off-by: Liu Ying --- Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt | 4 drivers/gpu/drm/drm_mipi_dsi.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt b/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt index 973c272..1a1d3c1 100644 --- a/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt +++ b/Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt @@ -36,6 +36,10 @@ Peripherals are represented as child nodes of the DSI host's node. Properties described here apply to all DSI peripherals, but individual bindings may want to define additional, device-specific properties. +Please, do not add the input-port property to the child nodes which represent +peripherals. Otherwise, the peripherals would be omitted by the MIPI DSI bus +driver. + Required properties: - reg: The virtual channel number of a DSI peripheral. Must be in the range from 0 to 3. diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index c0644bb..9adacfe 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -176,8 +176,9 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) struct device_node *node; for_each_available_child_of_node(host->dev->of_node, node) { - /* skip nodes without reg property */ - if (!of_find_property(node, "reg", NULL)) + /* skip nodes without reg property or with input-port property */ + if (!of_find_property(node, "reg", NULL) || +of_find_property(node, "input-port", NULL)) continue; of_mipi_dsi_device_add(host, node); } -- 2.1.0
[PATCH RFC 03/15] of: Add vendor prefix for Truly Semiconductors Limited
Signed-off-by: Liu Ying --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 3cee528..8257f3a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -158,6 +158,7 @@ tlm Trusted Logic Mobility toradexToradex AG toshibaToshiba Corporation toumaz Toumaz +truly Truly Semiconductors Limited usiUniversal Scientific Industrial Co., Ltd. v3 V3 Semiconductor variscite Variscite Ltd. -- 2.1.0
[PATCH RFC 02/15] of: Add vendor prefix for Himax Technologies Inc.
Signed-off-by: Liu Ying --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 78efebb..3cee528 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -69,6 +69,7 @@ hannstar HannStar Display Corporation haoyu Haoyu Microelectronic Co. Ltd. hisilicon Hisilicon Limited. hitHitachi Ltd. +himax Himax Technologies, Inc. honeywell Honeywell hp Hewlett Packard i2se I2SE GmbH -- 2.1.0
[PATCH RFC 01/15] clk: divider: Correct parent clk round rate if no bestdiv is normally found
If no best divider is normally found, we will try to use the maximum divider. We should not set the parent clock rate to be 1Hz by force for being rounded. Instead, we should take the maximum divider as a base and calculate a correct parent clock rate for being rounded. Signed-off-by: Liu Ying --- drivers/clk/clk-divider.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c0a842b..f641d4b 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -311,7 +311,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!bestdiv) { bestdiv = _get_maxdiv(divider); - *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); + *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), + MULT_ROUND_UP(rate, bestdiv)); } return bestdiv; -- 2.1.0
[Bug 87196] [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel
https://bugs.freedesktop.org/show_bug.cgi?id=87196 Bug ID: 87196 Summary: [radeonsi][dota2] small freezes happens while playing with a drm-next-3.19 linux kernel Product: DRI Version: DRI git Hardware: x86-64 (AMD64) OS: Linux (All) Status: NEW Severity: normal Priority: medium Component: DRM/Radeon Assignee: dri-devel at lists.freedesktop.org Reporter: sylvain.bertrand at gmail.com Up-to-date fedora rawhide, with up-to-date drm-next-3.19 linux kernel and mesa version 10.5.0 release 0.devel.3.29c7cf2.fc22 (bare openbox window manager). While playing, small freezes happens while playing. Usually, it "blocks" for less that half a second, randomly. It's not really disrupting the gameplay as it's short enough, but it's quite ugly and surprising. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/5403c60f/attachment.html>
[PATCH RFC 00/15] Add support for i.MX MIPI DSI DRM driver
Hi, This series adds support for i.MX MIPI DSI DRM driver. Currently, the MIPI DSI driver only supports the burst with sync pulse mode. This series also includes a DRM panel driver for the Truly TFT480800-16-E panel which is driven by the Himax HX8369A driver IC. The driver IC data sheet could be found at [1]. As mentioned by the data sheet, the driver IC supports several interface modes. Currently, the DRM panel driver only supports the MIPI DSI video mode. New interface modes could be added later(perhaps, just like the way the DRM simple panel driver supports both MIPI DSI interface panels and simple(parallel) interface panels). The MIPI DSI feature is tested on i.MX6Q SabreSD board and i.MX6DL SabreSD board. The MIPI DSI display could be enabled directly on i.MX6Q SabreSD board after applying this series, because the 26.4MHz pixel clock the panel requires could be derived from the IPU HSP clock(264MHz) with an integer divider. On i.MX6DL SabreSD board, we need to manually disable the LVDS and HDMI displays in the device tree blob, since the i.MX6DL IPU HSP clock is 198MHz at present, which makes the pixel clock share the PLL5 video clock source with the LVDS and HDMI, thus, the panel cannot get the pixel clock rate it wants. Patch 01/15 is needed to get a precise pixel clock rate(26.4MHz) from the PLL5 video clock. If we don't have this patch, the pixel clock rate is about 20MHz, which causes a horitonal shift on the display image. This series can be applied on the drm-next branch. [1] http://www.allshore.com/pdf/Himax_HX8369-A.pdf Liu Ying (15): clk: divider: Correct parent clk round rate if no bestdiv is normally found of: Add vendor prefix for Himax Technologies Inc. of: Add vendor prefix for Truly Semiconductors Limited drm/dsi: Do not add DSI devices for the child nodes with input-port property ARM: dts: imx6qdl: Add input-port property to MIPI DSI node's CTRC child nodes ARM: dts: imx6q: Add MIPI DSI remote end points for IPU2 DI0/1 end points ARM: imx6q: Add GPR3 MIPI muxing control register field shift bits definition ARM: imx6q: clk: Add the video_27m clock drm: imx: Add MIPI DSI host controller driver drm: panel: Add support for Himax HX8369A MIPI DSI panel ARM: dtsi: imx6qdl: Add support for MIPI DSI host controller ARM: dts: imx6qdl-sabresd: Add support for TRULY TFT480800-16-E MIPI DSI panel ARM: imx_v6_v7_defconfig: Cleanup for imx drm being moved out of staging ARM: imx_v6_v7_defconfig: Add support for MIPI DSI host controller ARM: imx_v6_v7_defconfig: Add support for Himax HX8369A panel .../devicetree/bindings/drm/imx/mipi_dsi.txt | 81 ++ .../devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt |4 + .../devicetree/bindings/panel/himax,hx8369a.txt| 86 ++ .../devicetree/bindings/vendor-prefixes.txt|2 + arch/arm/boot/dts/imx6q.dtsi |4 + arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 41 + arch/arm/boot/dts/imx6qdl.dtsi |9 + arch/arm/configs/imx_v6_v7_defconfig | 17 +- arch/arm/mach-imx/clk-imx6q.c |1 + drivers/clk/clk-divider.c |3 +- drivers/gpu/drm/drm_mipi_dsi.c |5 +- drivers/gpu/drm/imx/Kconfig|6 + drivers/gpu/drm/imx/Makefile |1 + drivers/gpu/drm/imx/imx-mipi-dsi.c | 1017 drivers/gpu/drm/panel/Kconfig |6 + drivers/gpu/drm/panel/Makefile |1 + drivers/gpu/drm/panel/panel-hx8369a.c | 627 include/dt-bindings/clock/imx6qdl-clock.h |3 +- include/linux/mfd/syscon/imx6q-iomuxc-gpr.h|1 + 19 files changed, 1903 insertions(+), 12 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/imx/mipi_dsi.txt create mode 100644 Documentation/devicetree/bindings/panel/himax,hx8369a.txt create mode 100644 drivers/gpu/drm/imx/imx-mipi-dsi.c create mode 100644 drivers/gpu/drm/panel/panel-hx8369a.c -- 2.1.0
[RFC 00/15] Resource tracking/allocation framework
On Wed, Dec 10, 2014 at 04:48:18PM +0100, Andrzej Hajda wrote: > 3. There are drivers which can work without specific resource, but if > the resource becomes available/unavailable it can do some additional stuff. > An example of such driver is DRM driver (more precisely drm_connector) - > it can start without attached drm_panel, but if the panel becomes available > it > can react by generating HPD event and start using it. Bad example, and actually incorrect. DRM connectors are referenced in userspace by an IDR number, which can be re-used in the case of a connector appearing, disappearing, and then a different connector re-appearing. DRM really is *not* safe to hotplug like this: DRM is more a card-level thing, which is why we have the component helpers - which allow us to merge several devices into one logical card-like device in a generic manner. DRM needs a stable picture of the CRTCs, encoders and connectors, which should _never_ change during the lifetime of the DRM device. Devices attached to connectors can be hotplugged, but that's about the limit of hot-plugging in DRM. -- FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up according to speedtest.net.
[RESEND PATCH] drm/doc: Document drm_add_modes_noedid() usage
On Wed, Dec 10, 2014 at 2:11 PM, Laurent Pinchartwrote: > From: Laurent Pinchart > > And fix a spelling mistake. > > Signed-off-by: Laurent Pinchart Reviewed-by: Alex Deucher > --- > Documentation/DocBook/drm.tmpl | 24 +++- > 1 file changed, 19 insertions(+), 5 deletions(-) > > I've had this patch in my tree for way too long, it's time to get it to > mainline or drop it. I of course vote for the former as I wouldn't submit it > otherwise. > > diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl > index 60c1063d4178..a5024f6aaf53 100644 > --- a/Documentation/DocBook/drm.tmpl > +++ b/Documentation/DocBook/drm.tmpl > @@ -1947,10 +1947,16 @@ void intel_crt_init(struct drm_device *dev) > and then retrieves a list of modes by calling the connector > get_modes helper operation. > > + > +If the helper operation returns no mode, and if the connector > status > +is connector_status_connected, standard VESA DMT modes up to > +1024x768 are automatically added to the modes list by a call to > +drm_add_modes_noedid. > + > > -The function filters out modes larger than > +The function then filters out modes larger than > max_width and > max_height > -if specified. It then calls the optional connector > +if specified. It finally calls the optional connector > mode_valid helper operation for each > mode in > the probed list to check whether the mode is valid for the > connector. > > @@ -2090,12 +2096,20 @@ void intel_crt_init(struct drm_device *dev) >int (*get_modes)(struct drm_connector > *connector); > > Fill the connector's probed_modes list > -by parsing EDID data with > drm_add_edid_modes or > -calling drm_mode_probed_add directly for > every > +by parsing EDID data with > drm_add_edid_modes, > +adding standard VESA DMT modes with > drm_add_modes_noedid, > +or calling drm_mode_probed_add directly for > every > supported mode and return the number of modes it has detected. > This > operation is mandatory. > > > +Note that the caller function will automatically add standard > VESA > +DMT modes up to 1024x768 if the > get_modes > +helper operation returns no mode and if the connector status is > +connector_status_connected. There is no need to call > +drm_add_edid_modes manually in that case. > + > + > When adding modes manually the driver creates each mode with a > call to > drm_mode_create and must fill the following > fields. > > @@ -2292,7 +2306,7 @@ void intel_crt_init(struct drm_device *dev) > drm_helper_probe_single_connector_modes. > > > -When parsing EDID data, drm_add_edid_modes > fill the > +When parsing EDID data, drm_add_edid_modes > fills the > connector display_info > width_mm and > height_mm fields. When creating modes > -- > Regards, > > Laurent Pinchart > > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 04/15] regulator: add restrack support
On Wed, Dec 10, 2014 at 04:48:22PM +0100, Andrzej Hajda wrote: > Regulators supports various methods of lookup. > The patch adds restrack support only to DT based regulators. Why, what does this mean and how might one use it? I've not looked at the code since I don't know what it's supposed to accomplish... One very high level thing is that anything that only works for DT only seems to be a non-starter, the API should be hiding details of the firmware interface. -- next part -- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: Digital signature URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/2edabc3e/attachment-0001.sig>
[drm-intel:topic/core-stuff 32/37] drivers/gpu/drm/drm_crtc.c:4472 drm_mode_crtc_set_gamma_size() warn: double check that we're allocating correct size: 2 vs 6
Forgotten to add mailing lists. -Daniel On Wed, Dec 10, 2014 at 3:53 PM, Daniel Vetter wrote: > On Wed, Dec 10, 2014 at 3:03 PM, Dan Carpenter > wrote: >> From a style prespective this should be: >> >> crtc->gamma_store = kcalloc(gamma_size * 3, sizeof(uint16_t), >> GFP_KERNEL); >> >> Because the elements are sizeof(uint16_t), we are allocating 3 >> arrays of gamma_size elements. But I guess it's nice to move all the >> constants to one side of the equation so that it tests for integer >> overflows... Whatever you decided is fine, this is a one time email >> that is auto-genenerated. > > Imo the point of kcalloc and kmalloc_array is to get the overflow > checks correct. Putting the *3 to the gamma_size (which can be fairly > big and migth come from dubios places) means we still have to deal > with overflow headaches. sizeof(uint16_t)*3 is trivial to see that > it's not overflowing. > > I think your style guide here is exactly _not_ what we should do as > best practice for safe code. > -Daniel > -- > Daniel Vetter > Software Engineer, Intel Corporation > +41 (0) 79 365 57 48 - http://blog.ffwll.ch -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH 3/3] amdkfd: Display MEC fw version in topology node
From: Alexey SkidanovThis patch displays the firmware version of the microcode that is currently running in the MEC. This is needed for the HSA RT, so it could differentiate its behavior based on fw version. e.g. workarounds for bugs in fw Signed-off-by: Alexey Skidanov Reviewed-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5733e28..8dd0e1b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -700,8 +700,6 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, dev->node_props.simd_per_cu); sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", dev->node_props.max_slots_scratch_cu); - sysfs_show_32bit_prop(buffer, "engine_id", - dev->node_props.engine_id); sysfs_show_32bit_prop(buffer, "vendor_id", dev->node_props.vendor_id); sysfs_show_32bit_prop(buffer, "device_id", @@ -715,6 +713,10 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, dev->gpu->kgd)); sysfs_show_64bit_prop(buffer, "local_mem_size", kfd2kgd->get_vmem_size(dev->gpu->kgd)); + + sysfs_show_32bit_prop(buffer, "fw_version", + kfd2kgd->get_fw_version(dev->gpu->kgd)); + } ret = sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", -- 1.9.1
[PATCH 2/3] drm/radeon: Add implementation of get_fw_version
From: Alexey SkidanovThis patch implements a new interface that was added to the kfd-->kgd interface. The new interface function retrieves the firmware version that is currently in use by the MEC engine. The firmware was uploaded to the MEC engine by the radeon driver. Signed-off-by: Alexey Skidanov Reviewed-by: Oded Gabbay --- drivers/gpu/drm/radeon/radeon_kfd.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 065d020..223c831 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c @@ -28,6 +28,8 @@ #include "cikd.h" #include "cik_reg.h" #include "radeon_kfd.h" +#include "radeon_ucode.h" +#include #define CIK_PIPE_PER_MEC (4) @@ -49,6 +51,7 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd); static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); +static uint16_t get_fw_version(struct kgd_dev *kgd); /* * Register access functions @@ -91,6 +94,7 @@ static const struct kfd2kgd_calls kfd2kgd = { .hqd_load = kgd_hqd_load, .hqd_is_occupies = kgd_hqd_is_occupies, .hqd_destroy = kgd_hqd_destroy, + .get_fw_version = get_fw_version }; static const struct kgd2kfd_calls *kgd2kfd; @@ -561,3 +565,22 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, release_queue(kgd); return 0; } + +static uint16_t get_fw_version(struct kgd_dev *kgd) +{ + struct radeon_device *rdev; + const struct gfx_firmware_header_v1_0 *hdr; + + BUG_ON(kgd == NULL); + + rdev = (struct radeon_device *) kgd; + + BUG_ON(rdev->mec_fw == NULL); + + hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data; + + BUG_ON(hdr == NULL); + + /* Only 12 bit in use*/ + return hdr->header.ucode_version; +} -- 1.9.1
[PATCH 1/3] drm/amd: Add get_fw_version to kfd-->kgd interface
From: Alexey SkidanovThis patch adds a new interface to the kfd-->kgd interface. The new interface function retrieves the firmware version that is currently in use by the MEC engine. The firmware was uploaded to the MEC engine by the kgd (radeon). Signed-off-by: Alexey Skidanov Reviewed-by: Oded Gabbay --- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 9c729dd..07f694b 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -137,6 +137,8 @@ struct kgd2kfd_calls { * * @hqd_destroy: Destructs and preempts the queue assigned to that hqd slot. * + * @get_fw_version: Returns FW versions from the header + * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -176,6 +178,7 @@ struct kfd2kgd_calls { int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, unsigned int timeout, uint32_t pipe_id, uint32_t queue_id); + uint16_t (*get_fw_version)(struct kgd_dev *kgd); }; bool kgd2kfd_init(unsigned interface_version, -- 1.9.1
[PATCH RFC 12/15] ARM: dts: imx6qdl-sabresd: Add support for TRULY TFT480800-16-E MIPI DSI panel
On Wed, Dec 10, 2014 at 04:37:25PM +0800, Liu Ying wrote: [...] > diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi > b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi [...] > +_dsi { > + status = "okay"; > + > + panel at 0 { > + compatible = "himax,hx8369a-dsi"; > + reg = <0>; > + pinctrl-names = "default"; > + pinctrl-0 = <_mipi_panel>; > + reset-gpios = < 11 GPIO_ACTIVE_LOW>; > + reset-delay = <120>; > + bs2-gpios = < 14 GPIO_ACTIVE_HIGH>; > + data-lanes = <2>; > + panel-width-mm = <45>; > + panel-height-mm = <76>; > + bs = <10>; > + status = "okay"; > + > + display-timings { > + native-mode = <>; > + timing1: truly-tft480800-16-e { This is the only place where Truly is mentioned. The panel vendor is either Truly or it is Himax, it can't be a mix. From this example and your patch description it seems like Truly is the manufacturer of the panel, hence the panel compatible should really be: compatible = "truly,tft480800-16-e"; That it uses an HX8369A chip internally is really secondary, at least regarding the binding. If we ever get need to support multiple panels with the same driver IC the proper solution would be to abstract that code out into a helper library that is used from the various panel drivers. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/ee9b2376/attachment.sig>
[PATCH] amdkfd: Fix accounting of device queues
This patch fixes a device QCM bug, where the number of queues were not counted correctly for the operation of update queue. The count was incorrect as there was no regard to the previous state of the queue. Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 924e90c..f44d673 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -320,6 +320,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) { int retval; struct mqd_manager *mqd; + bool prev_active = false; BUG_ON(!dqm || !q || !q->mqd); @@ -330,10 +331,18 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) return -ENOMEM; } - retval = mqd->update_mqd(mqd, q->mqd, >properties); if (q->properties.is_active == true) + prev_active = true; + + /* +* +* check active state vs. the previous state +* and modify counter accordingly +*/ + retval = mqd->update_mqd(mqd, q->mqd, >properties); + if ((q->properties.is_active == true) && (prev_active == false)) dqm->queue_count++; - else + else if ((q->properties.is_active == false) && (prev_active == true)) dqm->queue_count--; if (sched_policy != KFD_SCHED_POLICY_NO_HWS) -- 1.9.1
[PATCH RFC 10/15] drm: panel: Add support for Himax HX8369A MIPI DSI panel
nsion_command(ctx); > + hx8369a_dsi_set_maximum_return_packet_size(ctx, 4); > + hx8369a_dsi_panel_init(ctx); > + > + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); > + if (ret < 0) { > + dev_err(ctx->dev, "failed to exit sleep mode: %d\n", ret); > + return ret; > + } > + > + ret = mipi_dsi_dcs_set_display_on(dsi); > + if (ret < 0) { > + dev_err(ctx->dev, "failed to set display on: %d\n", ret); > + return ret; > + } > + > + return 0; > +} > + > +static int hx8369a_dsi_disable(struct drm_panel *panel) > +{ > + return 0; > +} [...] > +static int hx8369a_dsi_enable(struct drm_panel *panel) > +{ > + return 0; > +} Doesn't this usually come with a backlight attached that you want to control here? > +static int hx8369a_get_modes(struct drm_panel *panel) > +{ > + struct drm_connector *connector = panel->connector; > + struct hx8369a *ctx = panel_to_hx8369a(panel); > + struct drm_display_mode *mode; > + > + mode = drm_mode_create(connector->dev); > + if (!mode) { > + DRM_ERROR("failed to create a new display mode\n"); > + return 0; > + } > + > + drm_display_mode_from_videomode(>vm, mode); Like I've said before, the driver should hardcode the mode because it is implied by the compatible value. > + mode->width_mm = ctx->width_mm; > + mode->height_mm = ctx->height_mm; > + connector->display_info.width_mm = mode->width_mm; > + connector->display_info.height_mm = mode->height_mm; > + > + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; > + drm_mode_probed_add(connector, mode); > + > + return 1; > +} > + > +static const struct drm_panel_funcs hx8369a_dsi_drm_funcs = { > + .disable = hx8369a_dsi_disable, > + .unprepare = hx8369a_dsi_unprepare, > + .prepare = hx8369a_dsi_prepare, > + .enable = hx8369a_dsi_enable, > + .get_modes = hx8369a_get_modes, > +}; > +static int hx8369a_dsi_probe(struct mipi_dsi_device *dsi) > +{ > + struct device *dev = >dev; > + struct hx8369a *ctx; > + int ret, i; > + char bs[4]; > + > + ctx = devm_kzalloc(dev, sizeof(struct hx8369a), GFP_KERNEL); I'd prefer sizeof(*ctx). > + ctx->reset_gpio = devm_gpiod_get(dev, "reset"); > + if (IS_ERR(ctx->reset_gpio)) { > + dev_err(dev, "cannot get reset-gpios %ld\n", > + PTR_ERR(ctx->reset_gpio)); > + return PTR_ERR(ctx->reset_gpio); > + } > + ret = gpiod_direction_output(ctx->reset_gpio, 0); > + if (ret < 0) { > + dev_err(dev, "cannot configure reset-gpios %d\n", ret); > + return ret; > + } I think you're supposed to combine this into something like: ret = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); nowadays. > + > + for (i = 0; i < 4; i++) { > + snprintf(bs, sizeof(bs), "bs%d", i); > + ctx->bs_gpio[i] = devm_gpiod_get(dev, bs); > + if (IS_ERR(ctx->bs_gpio[i])) > + continue; > + > + ret = gpiod_direction_output(ctx->bs_gpio[i], 1); > + if (ret < 0) { > + dev_err(dev, "cannot configure bs%d-gpio %d\n", i, ret); > + return ret; > + } Similarly to the above: ret = devm_gpiod_get(dev, bs, GPIOD_OUT_HIGH); > +static int __init hx8369a_init(void) > +{ > + int err; > + > + err = mipi_dsi_driver_register(_dsi_driver); > + if (err < 0) > + return err; > + > + return 0; > +} > +module_init(hx8369a_init); > + > +static void __exit hx8369a_exit(void) > +{ > + mipi_dsi_driver_unregister(_dsi_driver); > +} > +module_exit(hx8369a_exit); Why can't this be module_mipi_dsi_driver(_dsi_driver)? > + > +MODULE_DESCRIPTION("Himax HX8369A panel driver"); > +MODULE_LICENSE("GPL v2"); Missing MODULE_AUTHOR()? Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/9aaf3496/attachment-0001.sig>
[PATCH] amdkfd/process: init aperture once per process
From: Alexey SkidanovSince the user space may call open() more that once from the same process, the aperture initialization should be moved from kfd_open() Signed-off-by: Alexey Skidanov Reviewed-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | 6 ++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 9 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 4f7b275..7d4974b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -121,13 +121,9 @@ static int kfd_open(struct inode *inode, struct file *filep) if (IS_ERR(process)) return PTR_ERR(process); - process->is_32bit_user_mode = is_32bit_user_mode; - dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", process->pasid, process->is_32bit_user_mode); - kfd_init_apertures(process); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index 66df4da..e64aa99 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c @@ -299,13 +299,13 @@ int kfd_init_apertures(struct kfd_process *process) struct kfd_dev *dev; struct kfd_process_device *pdd; - mutex_lock(>mutex); - /*Iterating over all devices*/ while ((dev = kfd_topology_enum_kfd_devices(id)) != NULL && id < NUM_OF_SUPPORTED_GPUS) { pdd = kfd_get_process_device_data(dev, process, 1); + if (!pdd) + return -1; /* * For 64 bit process aperture will be statically reserved in @@ -348,8 +348,6 @@ int kfd_init_apertures(struct kfd_process *process) id++; } - mutex_unlock(>mutex); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index b85eb0b..3c76ef0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -26,6 +26,8 @@ #include #include #include +#include + struct mm_struct; #include "kfd_priv.h" @@ -285,8 +287,15 @@ static struct kfd_process *create_process(const struct task_struct *thread) if (err != 0) goto err_process_pqm_init; + /* init process apertures*/ + process->is_32bit_user_mode = is_compat_task(); + if (kfd_init_apertures(process) != 0) + goto err_init_apretures; + return process; +err_init_apretures: + pqm_uninit(>pqm); err_process_pqm_init: hash_del_rcu(>kfd_processes); synchronize_rcu(); -- 1.9.1
[PATCH v2] drm/exynos/fimd: only finish pageflip if START == START_S
From: Daniel KurtzA framebuffer gets committed to FIMD's default window like this: exynos_drm_crtc_update() exynos_plane_commit() fimd_win_commit() fimd_win_commit() programs BUF_START[0]. At each vblank, FIMD hardware copies the value from BUF_START to BUF_START_S (BUF_START's shadow register), starts scanning out from BUF_START_S, and asserts its irq. This irq is handled by fimd_irq_handler(), which calls exynos_drm_crtc_finish_pageflip() to free the old buffer that FIMD just finished scanning out, and potentially commit the next pending flip. There is a race, however, if fimd_win_commit() programs BUF_START(0) between the actual vblank irq, and its corresponding fimd_irq_handler(). => FIMD vblank: BUF_START_S[0] := BUF_START[0], and irq asserted | => fimd_win_commit(0) writes new BUF_START[0] |exynos_drm_crtc_try_do_flip() marks exynos_fb as prepared => fimd_irq_handler() exynos_drm_crtc_finish_pageflip() sees prepared exynos_fb, and unmaps "old" fb ==> but, since BUF_START_S[0] still points to that "old" fb... ==> FIMD iommu fault This patch ensures that fimd_irq_handler() only calls exynos_drm_crtc_finish_pageflip() if any previously scheduled flip has really completed. This works because exynos_drm_crtc's flip fifo ensures that fimd_win_commit() is never called more than once per exynos_drm_crtc_finish_pageflip(). Signed-off-by: Daniel Kurtz Reviewed-by: Sean Paul Signed-off-by: Gustavo Padovan --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 31 --- include/video/samsung_fimd.h | 1 + 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index e5810d1..95bac27 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -55,6 +55,7 @@ #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) +#define VIDWx_BUF_START_S(win, buf) (VIDW_BUF_START_S(buf) + (win) * 8) #define VIDWx_BUF_END(win, buf)(VIDW_BUF_END(buf) + (win) * 8) #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) @@ -1039,6 +1040,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) { struct fimd_context *ctx = (struct fimd_context *)dev_id; u32 val, clear_bit; + u32 start, start_s; val = readl(ctx->regs + VIDINTCON1); @@ -1051,19 +1053,34 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) goto out; if (ctx->i80_if) { - exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); - /* Exits triggering mode */ atomic_set(>triggering, 0); } else { drm_handle_vblank(ctx->drm_dev, ctx->pipe); + } + + /* +* Ensure finish_pageflip is called iff a pending flip has completed. +* This works around a race between a page_flip request and the latency +* between vblank interrupt and this irq_handler: +* => FIMD vblank: BUF_START_S[0] := BUF_START[0], and asserts irq +* | => fimd_win_commit(0) writes new BUF_START[0] +* |exynos_drm_crtc_try_do_flip() marks exynos_fb as prepared +* => fimd_irq_handler() +* exynos_drm_crtc_finish_pageflip() sees prepared exynos_fb, +* and unmaps "old" fb +* ==> but, since BUF_START_S[0] still points to that "old" fb... +* ==> FIMD iommu fault +*/ + start = readl(ctx->regs + VIDWx_BUF_START(0, 0)); + start_s = readl(ctx->regs + VIDWx_BUF_START_S(0, 0)); + if (start == start_s) exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); - /* set wait vsync event to zero and wake up queue. */ - if (atomic_read(>wait_vsync_event)) { - atomic_set(>wait_vsync_event, 0); - wake_up(>wait_vsync_queue); - } + /* set wait vsync event to zero and wake up queue. */ + if (atomic_read(>wait_vsync_event)) { + atomic_set(>wait_vsync_event, 0); + wake_up(>wait_vsync_queue); } out: diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h index a20e4a3..f81d081 100644 --- a/include/video/samsung_fimd.h +++ b/include/video/samsung_fimd.h @@ -291,6 +291,7 @@ /* Video buffer addresses */ #define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) +#define VIDW_BUF_START_S(_buff) (0x40A0 + ((_buff) * 8)) #define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) #define VIDW_BUF_END(_buff)(0xD0 + ((_buff) * 8)) #define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) -- 1.9.3
[Bug 87172] UHD 4K (DisplayPort 1.2) monitor autodetects at 60Hz on Radeon 5870, which fails as this card doesn't support DP1.2
https://bugs.freedesktop.org/show_bug.cgi?id=87172 --- Comment #1 from Alex Deucher --- Created attachment 110680 --> https://bugs.freedesktop.org/attachment.cgi?id=110680=edit possible fix This patch should fix it. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/b70fc857/attachment.html>
[RFC 1/4] dma-buf: Add constraints sharing information
On Wed, Dec 10, 2014 at 07:01:16PM +0530, Sumit Semwal wrote: > Hi Daniel, > > Thanks a bunch for your review comments! A few comments, post our > discussion at LPC; > > On 12 October 2014 at 00:25, Daniel Vetter wrote: > > On Sat, Oct 11, 2014 at 01:37:55AM +0530, Sumit Semwal wrote: > >> At present, struct device lacks a mechanism of exposing memory > >> access constraints for the device. > >> > >> Consequently, there is also no mechanism to share these constraints > >> while sharing buffers using dma-buf. > >> > >> If we add support for sharing such constraints, we could use that > >> to try to collect requirements of different buffer-sharing devices > >> to allocate buffers from a pool that satisfies requirements of all > >> such devices. > >> > >> This is an attempt to add this support; at the moment, only a bitmask > >> is added, but if post discussion, we realise we need more information, > >> we could always extend the definition of constraint. > >> > >> A new dma-buf op is also added, to allow exporters to interpret or decide > >> on constraint-masks on their own. A default implementation is provided to > >> just AND (&) all the constraint-masks. > >> > >> What constitutes a constraint-mask could be left for interpretation on a > >> per-platform basis, while defining some common masks. > >> > >> Signed-off-by: Sumit Semwal > >> Cc: linux-kernel at vger.kernel.org > >> Cc: Greg Kroah-Hartman > >> Cc: linux-media at vger.kernel.org > >> Cc: dri-devel at lists.freedesktop.org > >> Cc: linaro-mm-sig at lists.linaro.org > > > > Just a few high-level comments, I'm between conference travel but > > hopefully I can discuss this a bit at plumbers next week. > > > > - I agree that for the insane specific cases we need something opaque like > > the access constraints mask you propose here. But for the normal case I > > think the existing dma constraints in dma_params would go a long way, > > and I think we should look at Rob's RFC from aeons ago to solve those: > > > > https://lkml.org/lkml/2012/7/19/285 > > > > With this we should be able to cover the allocation constraints of 90% > > of all cases hopefully. > > > > - I'm not sure whether an opaque bitmask is good enough really, I suspect > > that we also need various priorities between different allocators. With > > the option that some allocators are flat-out incompatible. > > Your/Rob's idea to figure out the constraints wrt max number of > segments in the sg_list can provide, like you said, maybe 80-90% of > the allocation constraints hopefully. The opaque mask should help for > the remaining 'crazy' cases, so I'll be glad to merge Rob's and my > approach on defining the constraints. > > I should think a little bit more about the priority idea that you > propose here (and in another patch), but atm I am unable to see how > that could help solve the finding-out-constraints problem. > > > > - The big bummer imo with ION is that it fully side-steps, but this > > proposal here also seems to add entirely new allocators. My rough idea > > This proposal does borrow this bit from ION, but once we have the > required changes done in the dma api itself, the allocators can just > become shims to the dma api allocators (eg dma_alloc_coherent etc) for > cases where they can be used directly, while leaving provision for any > crazy platform-specific allocators, without the userspace having to > worry about it. > > > was that at allocate/attach time we iterate over all attached devices > > like in Rob's patch and compute the most constrained allocation > > requirements. Then we pick the underlying dma api allocator for these > > constraints. That probably means that we need to open up the dma api a > > bit. But I guess for a start we could simply try to allocate from the > > most constrained device. Together with the opaque bits you propose here > > we could even map additional crazy requirements like that an allocation > > must come from a specific memory bank (provided by a special-purpose CMA > > region). That might also mean that requirements are exclusive and no > > allocation is possible. > > > My idea was a little variation on what you said here - rather than do > compute the most constraint allocation 'after' devices have attached > (and right now, we don't really have a way to know that - but that's > another point), I'd proposed to do the compute on each attach request, > so the requesting drivers can know immediately if the attachment will > not work for the other currently attached devices. Well I said allocate/attach ;-) But yeah if we check at attach and reject anything that doesn't work then there's no need to check again when allocating, it /should/ work. But perhaps good to be paranoid and check again. > > - I'm not sure we should allow drivers to override the access constraint > > checks really - the dma_buf interfaces already provide this possibility > > through the ->attach callback. In there
[PATCH RFC 09/15] drm: imx: Add MIPI DSI host controller driver
ipi_dsi_gen_pkt_hdr_write(dsi, val); > +} > + > +static ssize_t imx_mipi_dsi_host_transfer(struct mipi_dsi_host *host, > + const struct mipi_dsi_msg *msg) > +{ > + struct imx_mipi_dsi *dsi = host_to_dsi(host); > + int ret; > + > + switch (msg->type) { > + case MIPI_DSI_DCS_SHORT_WRITE: > + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: > + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: > + ret = imx_mipi_dsi_dcs_short_write(dsi, msg); > + break; > + case MIPI_DSI_DCS_LONG_WRITE: > + ret = imx_mipi_dsi_dcs_long_write(dsi, msg); > + break; > + default: > + dev_err(dsi->dev, "unsupported message type\n"); > + ret = -EFAULT; EFAULT really isn't appropriate here. > + } > + > + return ret; > +} > + > +static const struct mipi_dsi_host_ops imx_mipi_dsi_host_ops = { > + .attach = imx_mipi_dsi_host_attach, > + .detach = imx_mipi_dsi_host_detach, > + .transfer = imx_mipi_dsi_host_transfer, > +}; > + > +static enum drm_connector_status > +imx_mipi_dsi_detect(struct drm_connector *connector, bool force) > +{ > + struct imx_mipi_dsi *dsi = con_to_dsi(connector); > + > + if (!dsi->panel) { > + dsi->panel = of_drm_find_panel(dsi->panel_node); > + if (dsi->panel) > + drm_panel_attach(dsi->panel, >connector); > + } > + > + if (dsi->panel) > + return connector_status_connected; > + > + return connector_status_disconnected; > + > +} You really shouldn't be doing that here. of_drm_find_panel() returning NULL should be considered cause for deferring probe. I suspect that the driver doesn't really handle that very well at all, though, since if it did you would've run into the same issue that Benjamin ran into this morning. > +static void imx_mipi_dsi_encoder_prepare(struct drm_encoder *encoder) > +{ > + struct imx_mipi_dsi *dsi = enc_to_dsi(encoder); > + u32 interface_pix_fmt; > + > + switch (dsi->format) { > + case MIPI_DSI_FMT_RGB888: > + interface_pix_fmt = V4L2_PIX_FMT_RGB24; > + break; > + case MIPI_DSI_FMT_RGB565: > + interface_pix_fmt = V4L2_PIX_FMT_RGB565; > + break; > + default: > + dev_err(dsi->dev, "unsupported DSI pixel format\n"); > + return; Why even try doing this if you know upfront that it can't be done. You know much earlier than this that you can't drive the pixel format, why not abort then? People are much more likely to notice that the panel isn't supported if the DSI output doesn't even show up (or doesn't expose any modes) rather than if they have to find this error message in dmesg. > +static void imx_mipi_dsi_video_mode_config(struct imx_mipi_dsi *dsi) > +{ > + u32 val; > + > + val = VID_MODE_TYPE_BURST_SYNC_PULSES | ENABLE_LOW_POWER; > + > + dsi_write(dsi, DSI_VID_MODE_CFG, val); > +} You probably want to parameterize based on the DSI peripheral's flags. I see that you do reject devices with any other modes, so this may not be necessary now. Out of curiosity, the hardware supports other modes, right? [...] > +MODULE_LICENSE("GPL v2"); Sigh... according to your header comment this needs to be "GPL". Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/10d152b5/attachment-0001.sig>
[PATCH 1/7] drm: Miscellaneous checkpatch whitespace cleanups
On Wed, Dec 10, 2014 at 01:03:34PM +0100, Thierry Reding wrote: > From: Thierry Reding > > A couple of whitespace changes required to silent various errors and > warnings flagged by checkpatch. > > checkpatch requires that the opening brace be on the same line as a > variable declaration. Furthermore an empty line is required after a > block of variable declarations. Trailing whitespace as well as using > spaces before tabs is considered an error or warning, respectively. > Finally, the closing parenthesis of an if condition and the opening > brace of the conditional block should be separated by a space. > > Signed-off-by: Thierry Reding Also merged to drm misc. Imo patches 5&6 are a bit too close to a pure bikeshed so might drop them again if anyone else objects too. -Daniel > --- > drivers/gpu/drm/drm_crtc.c | 42 -- > drivers/gpu/drm/drm_irq.c | 3 ++- > 2 files changed, 22 insertions(+), 23 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 4e35d2f74e0f..6d36c959beb1 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -61,8 +61,8 @@ static struct drm_framebuffer > *add_framebuffer_internal(struct drm_device *dev, > /* > * Global properties > */ > -static const struct drm_prop_enum_list drm_dpms_enum_list[] = > -{{ DRM_MODE_DPMS_ON, "On" }, > +static const struct drm_prop_enum_list drm_dpms_enum_list[] = { > + { DRM_MODE_DPMS_ON, "On" }, > { DRM_MODE_DPMS_STANDBY, "Standby" }, > { DRM_MODE_DPMS_SUSPEND, "Suspend" }, > { DRM_MODE_DPMS_OFF, "Off" } > @@ -70,8 +70,7 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] > = > > DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) > > -static const struct drm_prop_enum_list drm_plane_type_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { > { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, > { DRM_PLANE_TYPE_PRIMARY, "Primary" }, > { DRM_PLANE_TYPE_CURSOR, "Cursor" }, > @@ -80,8 +79,7 @@ static const struct drm_prop_enum_list > drm_plane_type_enum_list[] = > /* > * Optional properties > */ > -static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { > { DRM_MODE_SCALE_NONE, "None" }, > { DRM_MODE_SCALE_FULLSCREEN, "Full" }, > { DRM_MODE_SCALE_CENTER, "Center" }, > @@ -97,8 +95,7 @@ static const struct drm_prop_enum_list > drm_aspect_ratio_enum_list[] = { > /* > * Non-global properties, but "required" for certain connectors. > */ > -static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { > { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ > { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ > { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ > @@ -106,8 +103,7 @@ static const struct drm_prop_enum_list > drm_dvi_i_select_enum_list[] = > > DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) > > -static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { > { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ > { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ > { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ > @@ -116,8 +112,7 @@ static const struct drm_prop_enum_list > drm_dvi_i_subconnector_enum_list[] = > DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, >drm_dvi_i_subconnector_enum_list) > > -static const struct drm_prop_enum_list drm_tv_select_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { > { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ > { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ > { DRM_MODE_SUBCONNECTOR_SVIDEO,"SVIDEO"}, /* TV-out */ > @@ -127,8 +122,7 @@ static const struct drm_prop_enum_list > drm_tv_select_enum_list[] = > > DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) > > -static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = > -{ > +static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { > { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ > { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ > { DRM_MODE_SUBCONNECTOR_SVIDEO,"SVIDEO"}, /* TV-out */ > @@ -154,8 +148,8 @@ struct drm_conn_prop_enum_list { > /* > * Connector and encoder types. > */ > -static struct drm_conn_prop_enum_list drm_connector_enum_list[] = > -{{ DRM_MODE_CONNECTOR_Unknown, "Unknown" }, > +static struct drm_conn_prop_enum_list
[PATCH 0/20] fix misspelling of current function in string
Hi Julia, On Mon, Dec 8, 2014 at 5:43 PM, Julia Lawall wrote: > On Mon, 8 Dec 2014, Julian Calaby wrote: > >> Hi Julia, >> >> On Mon, Dec 8, 2014 at 6:20 AM, Julia Lawall wrote: >> > These patches replace what appears to be a reference to the name of the >> > current function but is misspelled in some way by either the name of the >> > function itself, or by %s and then __func__ in an argument list. >> >> Would there be any value in doing this for _all_ cases where the >> function name is written in a format string? > > Probably. But there are a lot of them. Even for the misspellings, I have > only don about 1/3 of the cases. > > On the other hand, the misspelling have to be checked carefully, because a > misspelling of one thing could be the correct spelling of the thing thst > was actually intended. > > Joe, however, points out that a lot of these prints are just for function > tracing, and could be removed. I worked on another semantic patch that > tries to do that. It might be better to remove those prints completely, > rather than sending one patch to transform them and then one patch to > remove them after that. That is why for this series I did only the ones > where there was actually a problem. Ok, that makes sense. Either way though, this is a really interesting application of the semantic patching. Nice work! Thanks, -- Julian Calaby Email: julian.calaby at gmail.com Profile: http://www.google.com/profiles/julian.calaby/
[PATCH 5/5] drm/tegra: Remove dummy ->load_lut() implementation
On Wed, Dec 10, 2014 at 12:30:02PM +0100, Thierry Reding wrote: > From: Thierry Reding > > The ->load_lut() callback is optional, therefore a dummy implementation > is not needed. > > Signed-off-by: Thierry Reding All patches merged to drm-misc with the small conflict here resolved, thanks. Aside: We should rework the fbdev helper to use the main gamma table entry point and ditch this special-purpose gamma table save/restore logic here. But that's a lot more work. -Daniel > --- > drivers/gpu/drm/tegra/dc.c | 5 - > 1 file changed, 5 deletions(-) > > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c > index 80beebdc2566..faa2f5b4c7ac 100644 > --- a/drivers/gpu/drm/tegra/dc.c > +++ b/drivers/gpu/drm/tegra/dc.c > @@ -1169,10 +1169,6 @@ static void tegra_crtc_commit(struct drm_crtc *crtc) > drm_crtc_vblank_on(crtc); > } > > -static void tegra_crtc_load_lut(struct drm_crtc *crtc) > -{ > -} > - > static int tegra_crtc_atomic_check(struct drm_crtc *crtc, > struct drm_crtc_state *state) > { > @@ -1213,7 +1209,6 @@ static const struct drm_crtc_helper_funcs > tegra_crtc_helper_funcs = { > .mode_set_base = drm_helper_crtc_mode_set_base, > .prepare = tegra_crtc_prepare, > .commit = tegra_crtc_commit, > - .load_lut = tegra_crtc_load_lut, > .atomic_check = tegra_crtc_atomic_check, > .atomic_begin = tegra_crtc_atomic_begin, > .atomic_flush = tegra_crtc_atomic_flush, > -- > 2.1.3 > > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PULL] topic/core-stuff
Hi Dave, Decided to send a pull request for my misc drm branch because of teh memset patch from Thierry for drm_*_cleanup functions (fixes drivers using deferred probe) and the patch from Takashi. Everything else fairly trivial. Cheers, Daniel The following changes since commit e5b5341c28c66a122982d3d8822a4f9a0938f923: drm/atomic: clear plane's CRTC and FB when shutting down (2014-11-27 15:39:11 +0100) are available in the git repository at: git://anongit.freedesktop.org/drm-intel tags/topic/core-stuff-2014-12-10 for you to fetch changes up to a18c0af171bfb875012da26f23df051004726973: drm: Zero out DRM object memory upon cleanup (2014-12-10 12:05:56 +0100) Martin Peres (2): drm: fix a word repetition in a comment drm: fix a typo in a comment Sean Paul (1): drm/Documentation: Fix rowspan value in drm-kms-properties Stefan Brüns (3): drm/edid: move drm_edid_is_zero to top, make edid argument const drm/edid: shorten log output in case of all zeroes edid block drm/edid: new drm_edid_block_checksum helper function V3 Takashi Iwai (1): drm: Fix memory leak at error path of drm_read() Thierry Reding (2): drm/edid: Restore kerneldoc consistency drm: Zero out DRM object memory upon cleanup Documentation/DocBook/drm.tmpl | 2 +- drivers/gpu/drm/drm_crtc.c | 13 +++-- drivers/gpu/drm/drm_edid.c | 42 +++--- drivers/gpu/drm/drm_fops.c | 1 + drivers/gpu/drm/drm_irq.c | 2 +- 5 files changed, 41 insertions(+), 19 deletions(-) -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH RFC 04/15] drm/dsi: Do not add DSI devices for the child nodes with input-port property
On Wed, Dec 10, 2014 at 04:37:17PM +0800, Liu Ying wrote: > The MIPI DSI bus driver would try to add a DSI device for a host's every > child node which contains the reg property. Unfortunately, the existing > i.MX6Q/SDL MIPI DSI host device tree node's child nodes contain the reg There aren't any existing nodes for the DSI host on i.MX. This patch series adds support for them. > property, but the child nodes are ports pointing to dedicated CRTCs. > So, this patch phases out the child nodes with input-port property before > adding DSI devices for them and updates the MIPI DSI bus OF binding > documentation. > > Signed-off-by: Liu Ying > --- > Documentation/devicetree/bindings/mipi/dsi/mipi-dsi-bus.txt | 4 > drivers/gpu/drm/drm_mipi_dsi.c | 5 +++-- > 2 files changed, 7 insertions(+), 2 deletions(-) Sorry, but NAK. There's no need for this special-case. I'll go into more detail in response to patch 09/15. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/6e6f1051/attachment.sig>
[PATCH] drm: Zero out DRM object memory upon cleanup
I have test this patch on my side, plane properties are no more duplicated so you can add my ack. Thanks Benjamin 2014-12-10 12:06 GMT+01:00 Daniel Vetter : > On Wed, Dec 10, 2014 at 11:38:49AM +0100, Thierry Reding wrote: > > From: Thierry Reding > > > > Drivers where the DRM objects have a lifetime that extends beyond that > > of the DRM device need to zero out the DRM object memory to void stale > > data such as properties. The DRM core code expects to operate on newly > > allocated and zeroed out objects and will behave unexpectedly, such as > > add duplicate properties, otherwise. > > > > Signed-off-by: Thierry Reding > > Yeah, makes sense imo to do in the core. Reviewed-by: Daniel Vetter < > daniel.vetter at ffwll.ch> > > Also stuffed into drm-misc and I think I'll throw that at Dave today or > tomorrow. > -Daniel > > > --- > > drivers/gpu/drm/drm_crtc.c | 11 ++- > > 1 file changed, 10 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > > index 4c9aaf8e6176..4e35d2f74e0f 100644 > > --- a/drivers/gpu/drm/drm_crtc.c > > +++ b/drivers/gpu/drm/drm_crtc.c > > @@ -725,6 +725,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) > > WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); > > if (crtc->state && crtc->funcs->atomic_destroy_state) > > crtc->funcs->atomic_destroy_state(crtc, crtc->state); > > + > > + memset(crtc, 0, sizeof(*crtc)); > > } > > EXPORT_SYMBOL(drm_crtc_cleanup); > > > > @@ -927,6 +929,8 @@ void drm_connector_cleanup(struct drm_connector > *connector) > > if (connector->state && connector->funcs->atomic_destroy_state) > > connector->funcs->atomic_destroy_state(connector, > > connector->state); > > + > > + memset(connector, 0, sizeof(*connector)); > > } > > EXPORT_SYMBOL(drm_connector_cleanup); > > > > @@ -1068,6 +1072,8 @@ void drm_bridge_cleanup(struct drm_bridge *bridge) > > list_del(>head); > > dev->mode_config.num_bridge--; > > drm_modeset_unlock_all(dev); > > + > > + memset(bridge, 0, sizeof(*bridge)); > > } > > EXPORT_SYMBOL(drm_bridge_cleanup); > > > > @@ -1134,10 +1140,11 @@ void drm_encoder_cleanup(struct drm_encoder > *encoder) > > drm_modeset_lock_all(dev); > > drm_mode_object_put(dev, >base); > > kfree(encoder->name); > > - encoder->name = NULL; > > list_del(>head); > > dev->mode_config.num_encoder--; > > drm_modeset_unlock_all(dev); > > + > > + memset(encoder, 0, sizeof(*encoder)); > > } > > EXPORT_SYMBOL(drm_encoder_cleanup); > > > > @@ -1257,6 +1264,8 @@ void drm_plane_cleanup(struct drm_plane *plane) > > WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); > > if (plane->state && plane->funcs->atomic_destroy_state) > > plane->funcs->atomic_destroy_state(plane, plane->state); > > + > > + memset(plane, 0, sizeof(*plane)); > > } > > EXPORT_SYMBOL(drm_plane_cleanup); > > > > -- > > 2.1.3 > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > +41 (0) 79 365 57 48 - http://blog.ffwll.ch > -- Benjamin Gaignard Graphic Working Group Linaro.org <http://www.linaro.org/> *â *Open source software for ARM SoCs Follow *Linaro: *Facebook <http://www.facebook.com/pages/Linaro> | Twitter <http://twitter.com/#!/linaroorg> | Blog <http://www.linaro.org/linaro-blog/> -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/840a9d44/attachment-0001.html>
[PATCH 7/7] drm: Prefer sizeof(type) over sizeof type
From: Thierry Redingsizeof(type) is the variant used most commonly and required by checkpatch. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 12 ++-- drivers/gpu/drm/drm_irq.c | 8 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6888e1c7b936..242ab37e2738 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4684,23 +4684,23 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { ret = -ENOMEM; spin_lock_irqsave(>event_lock, flags); - if (file_priv->event_space < sizeof e->event) { + if (file_priv->event_space < sizeof(e->event)) { spin_unlock_irqrestore(>event_lock, flags); goto out; } - file_priv->event_space -= sizeof e->event; + file_priv->event_space -= sizeof(e->event); spin_unlock_irqrestore(>event_lock, flags); - e = kzalloc(sizeof *e, GFP_KERNEL); + e = kzalloc(sizeof(*e), GFP_KERNEL); if (e == NULL) { spin_lock_irqsave(>event_lock, flags); - file_priv->event_space += sizeof e->event; + file_priv->event_space += sizeof(e->event); spin_unlock_irqrestore(>event_lock, flags); goto out; } e->event.base.type = DRM_EVENT_FLIP_COMPLETE; - e->event.base.length = sizeof e->event; + e->event.base.length = sizeof(e->event); e->event.user_data = page_flip->user_data; e->base.event = >event.base; e->base.file_priv = file_priv; @@ -4713,7 +4713,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (ret) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { spin_lock_irqsave(>event_lock, flags); - file_priv->event_space += sizeof e->event; + file_priv->event_space += sizeof(e->event); spin_unlock_irqrestore(>event_lock, flags); kfree(e); } diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 63d7051dd75b..ddc6ac28c13e 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1383,7 +1383,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, unsigned int seq; int ret; - e = kzalloc(sizeof *e, GFP_KERNEL); + e = kzalloc(sizeof(*e), GFP_KERNEL); if (e == NULL) { ret = -ENOMEM; goto err_put; @@ -1392,7 +1392,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, e->pipe = pipe; e->base.pid = current->pid; e->event.base.type = DRM_EVENT_VBLANK; - e->event.base.length = sizeof e->event; + e->event.base.length = sizeof(e->event); e->event.user_data = vblwait->request.signal; e->base.event = >event.base; e->base.file_priv = file_priv; @@ -1412,12 +1412,12 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, goto err_unlock; } - if (file_priv->event_space < sizeof e->event) { + if (file_priv->event_space < sizeof(e->event)) { ret = -EBUSY; goto err_unlock; } - file_priv->event_space -= sizeof e->event; + file_priv->event_space -= sizeof(e->event); seq = drm_vblank_count_and_time(dev, pipe, ); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && -- 2.1.3
[PATCH 6/7] drm: Remove useless else block
From: Thierry RedingAll prior conditional blocks return from the function, so the else block can be at the top level of the function. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 654b1ae36f55..6888e1c7b936 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4135,6 +4135,8 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property); static bool drm_property_change_is_valid(struct drm_property *property, uint64_t value) { + int i; + if (property->flags & DRM_MODE_PROP_IMMUTABLE) return false; @@ -4150,7 +4152,6 @@ static bool drm_property_change_is_valid(struct drm_property *property, return false; return true; } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { - int i; uint64_t valid_mask = 0; for (i = 0; i < property->num_values; i++) @@ -4174,13 +4175,12 @@ static bool drm_property_change_is_valid(struct drm_property *property, */ obj = _object_find(property->dev, value, property->values[0]); return obj != NULL; - } else { - int i; - for (i = 0; i < property->num_values; i++) - if (property->values[i] == value) - return true; - return false; } + + for (i = 0; i < property->num_values; i++) + if (property->values[i] == value) + return true; + return false; } /** -- 2.1.3
[PATCH 5/7] drm: Remove unneeded braces for single statement blocks
From: Thierry RedingSingle statement blocks don't need to be enclosed in a pair of braces. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index faadd87477b5..654b1ae36f55 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2030,11 +2030,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, props_count = connector->properties.count; - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - if (connector->encoder_ids[i] != 0) { + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) + if (connector->encoder_ids[i] != 0) encoders_count++; - } - } if (out_resp->count_modes == 0) { connector->funcs->fill_modes(connector, -- 2.1.3
[PATCH 4/7] drm: Do not assign in if condition
From: Thierry Redingcheckpatch requires the assignment and the check to be separate statements. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2ce5629a53c1..faadd87477b5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1613,7 +1613,8 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_bridge *bridge; int ret; - if ((ret = drm_mode_group_init(dev, group))) + ret = drm_mode_group_init(dev, group); + if (ret) return ret; list_for_each_entry(crtc, >mode_config.crtc_list, head) -- 2.1.3
[PATCH 3/7] drm: Prefer kmalloc_array() over kmalloc() with multiply
From: Thierry RedingFixes a couple of checkpatch warnings regarding the use of kmalloc() with a multiplication. kmalloc_array() is the preferred API. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7228c70de281..2ce5629a53c1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1174,8 +1174,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->base.properties = >properties; plane->dev = dev; plane->funcs = funcs; - plane->format_types = kmalloc(sizeof(uint32_t) * format_count, - GFP_KERNEL); + plane->format_types = kmalloc_array(format_count, sizeof(uint32_t), + GFP_KERNEL); if (!plane->format_types) { DRM_DEBUG_KMS("out of memory when allocating plane\n"); drm_mode_object_put(dev, >base); @@ -2705,9 +2705,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - connector_set = kmalloc(crtc_req->count_connectors * - sizeof(struct drm_connector *), - GFP_KERNEL); + connector_set = kmalloc_array(crtc_req->count_connectors, + sizeof(struct drm_connector *), + GFP_KERNEL); if (!connector_set) { ret = -ENOMEM; goto out; -- 2.1.3
[PATCH 2/7] drm: Prefer kcalloc() over kzalloc() with multiply
From: Thierry RedingFixes a couple of checkpatch warnings regarding the use of kzalloc() with a multiplication. kcalloc() is the preferred API. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6d36c959beb1..7228c70de281 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1583,7 +1583,7 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr total_objects += dev->mode_config.num_encoder; total_objects += dev->mode_config.num_bridge; - group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); + group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); if (!group->id_list) return -ENOMEM; @@ -3400,7 +3400,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, ret = -EINVAL; goto out_err1; } - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); + clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); if (!clips) { ret = -ENOMEM; goto out_err1; @@ -3501,7 +3501,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, property->dev = dev; if (num_values) { - property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); + property->values = kcalloc(num_values, sizeof(uint64_t), + GFP_KERNEL); if (!property->values) goto fail; } @@ -4468,7 +4469,8 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, { crtc->gamma_size = gamma_size; - crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); + crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, + GFP_KERNEL); if (!crtc->gamma_store) { crtc->gamma_size = 0; return -ENOMEM; -- 2.1.3
[PATCH 1/7] drm: Miscellaneous checkpatch whitespace cleanups
From: Thierry RedingA couple of whitespace changes required to silent various errors and warnings flagged by checkpatch. checkpatch requires that the opening brace be on the same line as a variable declaration. Furthermore an empty line is required after a block of variable declarations. Trailing whitespace as well as using spaces before tabs is considered an error or warning, respectively. Finally, the closing parenthesis of an if condition and the opening brace of the conditional block should be separated by a space. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 42 -- drivers/gpu/drm/drm_irq.c | 3 ++- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4e35d2f74e0f..6d36c959beb1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -61,8 +61,8 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, /* * Global properties */ -static const struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DRM_MODE_DPMS_ON, "On" }, +static const struct drm_prop_enum_list drm_dpms_enum_list[] = { + { DRM_MODE_DPMS_ON, "On" }, { DRM_MODE_DPMS_STANDBY, "Standby" }, { DRM_MODE_DPMS_SUSPEND, "Suspend" }, { DRM_MODE_DPMS_OFF, "Off" } @@ -70,8 +70,7 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) -static const struct drm_prop_enum_list drm_plane_type_enum_list[] = -{ +static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, { DRM_PLANE_TYPE_PRIMARY, "Primary" }, { DRM_PLANE_TYPE_CURSOR, "Cursor" }, @@ -80,8 +79,7 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = /* * Optional properties */ -static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = -{ +static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { { DRM_MODE_SCALE_NONE, "None" }, { DRM_MODE_SCALE_FULLSCREEN, "Full" }, { DRM_MODE_SCALE_CENTER, "Center" }, @@ -97,8 +95,7 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { /* * Non-global properties, but "required" for certain connectors. */ -static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = -{ +static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ @@ -106,8 +103,7 @@ static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) -static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = -{ +static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ @@ -116,8 +112,7 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, drm_dvi_i_subconnector_enum_list) -static const struct drm_prop_enum_list drm_tv_select_enum_list[] = -{ +static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO,"SVIDEO"}, /* TV-out */ @@ -127,8 +122,7 @@ static const struct drm_prop_enum_list drm_tv_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) -static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = -{ +static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO,"SVIDEO"}, /* TV-out */ @@ -154,8 +148,8 @@ struct drm_conn_prop_enum_list { /* * Connector and encoder types. */ -static struct drm_conn_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, +static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { + { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, { DRM_MODE_CONNECTOR_VGA, "VGA" }, { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, @@ -174,8 +168,8 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_DSI, "DSI" }, }; -static
linux-next: manual merge of the drm-misc tree with the tree
Hi all, Today's linux-next merge of the drm-misc tree got a conflict in drivers/gpu/drm/drm_edid.c between commit 40d9b043a89e ("drm/connector: store tile information from displayid (v3)") from the drm tree and commit d6885d659037 ("drm/edid: move drm_edid_is_zero to top, make edid argument const") and c465bbc87ce3 ("drm/edid: new drm_edid_block_checksum helper function V3") from the drm-misc tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwellsfr at canb.auug.org.au diff --cc drivers/gpu/drm/drm_edid.c index 72fd8820e186,21cc45cf3367.. --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@@ -1015,8 -1014,24 +1015,27 @@@ module_param_named(edid_fixup, edid_fix MODULE_PARM_DESC(edid_fixup, "Minimum number of valid EDID header bytes (0-8, default 6)"); +static void drm_get_displayid(struct drm_connector *connector, +struct edid *edid); ++ + static int drm_edid_block_checksum(const u8 *raw_edid) + { + int i; + u8 csum = 0; + for (i = 0; i < EDID_LENGTH; i++) + csum += raw_edid[i]; + + return csum; + } + + static bool drm_edid_is_zero(const u8 *in_edid, int length) + { + if (memchr_inv(in_edid, 0, length)) + return false; + + return true; + } + /** * drm_edid_block_valid - Sanity check the EDID block (base or extension) * @raw_edid: pointer to raw EDID block @@@ -1179,34 -1196,8 +1200,26 @@@ drm_do_probe_ddc_edid(void *data, u8 *b return ret == xfers ? 0 : -1; } - static bool drm_edid_is_zero(u8 *in_edid, int length) - { - if (memchr_inv(in_edid, 0, length)) - return false; - - return true; - } - -static u8 * -drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) +/** + * drm_do_get_edid - get EDID data using a custom EDID block read function + * @connector: connector we're probing + * @get_edid_block: EDID block read function + * @data: private data passed to the block read function + * + * When the I2C adapter connected to the DDC bus is hidden behind a device that + * exposes a different interface to read EDID blocks this function can be used + * to get EDID data using a custom block read function. + * + * As in the general case the DDC bus is accessible by the kernel at the I2C + * level, drivers must make all reasonable efforts to expose it as an I2C + * adapter and use drm_get_edid() instead of abusing this function. + * + * Return: Pointer to valid EDID or NULL if we couldn't find any. + */ +struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *data, u8 *buf, unsigned int block, +size_t len), + void *data) { int i, j = 0, valid_extensions = 0; u8 *block, *new; -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/6c888fad/attachment.sig>
linux-next: manual merge of the drm-misc tree with the drm tree
Hi all, Today's linux-next merge of the drm-misc tree got a conflict in Documentation/DocBook/drm.tmpl between commit 6f134d7bb434 ("drm/tile: expose the tile property to userspace (v3)") from the drm tree and commit e2beb6cd5d0f ("drm/Documentation: Fix rowspan value in drm-kms-properties") from the drm-misc tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwellsfr at canb.auug.org.au diff --cc Documentation/DocBook/drm.tmpl index 60c1063d4178,b344bc3b0d77.. --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@@ -2550,8 -2546,8 +2550,8 @@@ void intel_crt_init(struct drm_device * Description/Restrictions - DRM + DRM - Generic + Generic âEDIDâ BLOB | IMMUTABLE 0 -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20141210/a4874d74/attachment.sig>
[PATCH] drm/cache: Implement drm_clflush_*() for ARM
On Wed, Dec 10, 2014 at 11:38 AM, Thierry Reding wrote: > From: Thierry Reding > > Add implementations for drm_clflush_*() on ARM by borrowing code from > the DMA mapping API implementation. Unfortunately ARM doesn't export an > API to flush caches on a page by page basis, so this replicates most of > the code. > Makes for a nice little simplification in msm_gem, now that I can use clflush helper. And if ARM does gain a better API it would be nice to just update the helper, rather than each driver. Reviewed: Rob Clark > Signed-off-by: Thierry Reding > --- > drivers/gpu/drm/drm_cache.c | 45 > + > 1 file changed, 45 insertions(+) > > diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c > index a6b690626a6b..fca0b8994c77 100644 > --- a/drivers/gpu/drm/drm_cache.c > +++ b/drivers/gpu/drm/drm_cache.c > @@ -72,6 +72,41 @@ drm_clflush_ipi_handler(void *null) > } > #endif > > +#if defined(CONFIG_ARM) > + > +#include > +#include > +#include > +#include > + > +static void drm_clflush_page(struct page *page) > +{ > + enum dma_data_direction dir = DMA_TO_DEVICE; > + phys_addr_t phys = page_to_phys(page); > + size_t size = PAGE_SIZE; > + void *virt; > + > + if (PageHighMem(page)) { > + if (cache_is_vipt_nonaliasing()) { > + virt = kmap_atomic(page); > + dmac_map_area(virt, size, dir); > + kunmap_atomic(virt); > + } else { > + virt = kmap_high_get(page); > + if (virt) { > + dmac_map_area(virt, size, dir); > + kunmap_high(page); > + } > + } > + } else { > + virt = page_address(page); > + dmac_map_area(virt, size, dir); > + } > + > + outer_flush_range(phys, phys + PAGE_SIZE); > +} > +#endif > + > void > drm_clflush_pages(struct page *pages[], unsigned long num_pages) > { > @@ -99,6 +134,11 @@ drm_clflush_pages(struct page *pages[], unsigned long > num_pages) >(unsigned long)page_virtual + PAGE_SIZE); > kunmap_atomic(page_virtual); > } > +#elif defined(CONFIG_ARM) > + unsigned long i; > + > + for (i = 0; i < num_pages; i++) > + drm_clflush_page(pages[i]); > #else > printk(KERN_ERR "Architecture has no drm_cache.c support\n"); > WARN_ON_ONCE(1); > @@ -123,6 +163,11 @@ drm_clflush_sg(struct sg_table *st) > > if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) > printk(KERN_ERR "Timed out waiting for cache flush.\n"); > +#elif defined(CONFIG_ARM) > + struct sg_page_iter sg_iter; > + > + for_each_sg_page(st->sgl, _iter, st->nents, 0) > + drm_clflush_page(sg_page_iter_page(_iter)); > #else > printk(KERN_ERR "Architecture has no drm_cache.c support\n"); > WARN_ON_ONCE(1); > -- > 2.1.3 >
[PATCH 5/5] drm/tegra: Remove dummy ->load_lut() implementation
From: Thierry RedingThe ->load_lut() callback is optional, therefore a dummy implementation is not needed. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 80beebdc2566..faa2f5b4c7ac 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1169,10 +1169,6 @@ static void tegra_crtc_commit(struct drm_crtc *crtc) drm_crtc_vblank_on(crtc); } -static void tegra_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static int tegra_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -1213,7 +1209,6 @@ static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { .mode_set_base = drm_helper_crtc_mode_set_base, .prepare = tegra_crtc_prepare, .commit = tegra_crtc_commit, - .load_lut = tegra_crtc_load_lut, .atomic_check = tegra_crtc_atomic_check, .atomic_begin = tegra_crtc_atomic_begin, .atomic_flush = tegra_crtc_atomic_flush, -- 2.1.3
[PATCH 4/5] drm/sti: Remove dummy ->load_lut() implementation
From: Thierry RedingThe ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Benjamin Gaignard Signed-off-by: Thierry Reding --- drivers/gpu/drm/sti/sti_drm_crtc.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 36a1ad3c4823..70e6e97a850e 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -184,11 +184,6 @@ out: return ret; } -static void sti_drm_crtc_load_lut(struct drm_crtc *crtc) -{ - /* do nothing */ -} - static void sti_drm_crtc_disable(struct drm_crtc *crtc) { struct sti_mixer *mixer = to_sti_mixer(crtc); @@ -243,7 +238,6 @@ static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { .mode_fixup = sti_drm_crtc_mode_fixup, .mode_set = sti_drm_crtc_mode_set, .mode_set_base = sti_drm_crtc_mode_set_base, - .load_lut = sti_drm_crtc_load_lut, .disable = sti_drm_crtc_disable, }; -- 2.1.3
[PATCH 3/5] drm/msm: Remove dummy ->load_lut() implementation
From: Thierry RedingThe ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Rob Clark Signed-off-by: Thierry Reding --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 5 - drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 5 - 2 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index a7672e100d8b..ac2a6ebce674 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -323,10 +323,6 @@ static void mdp4_crtc_commit(struct drm_crtc *crtc) drm_crtc_vblank_put(crtc); } -static void mdp4_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -524,7 +520,6 @@ static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { .mode_set_base = drm_helper_crtc_mode_set_base, .prepare = mdp4_crtc_prepare, .commit = mdp4_crtc_commit, - .load_lut = mdp4_crtc_load_lut, .atomic_check = mdp4_crtc_atomic_check, .atomic_begin = mdp4_crtc_atomic_begin, .atomic_flush = mdp4_crtc_atomic_flush, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 0e9a2e3a82d7..92d52a56b3b8 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -275,10 +275,6 @@ static void mdp5_crtc_commit(struct drm_crtc *crtc) mdp5_disable(get_kms(crtc)); } -static void mdp5_crtc_load_lut(struct drm_crtc *crtc) -{ -} - struct plane_state { struct drm_plane *plane; struct mdp5_plane_state *state; @@ -407,7 +403,6 @@ static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_base = drm_helper_crtc_mode_set_base, .prepare = mdp5_crtc_prepare, .commit = mdp5_crtc_commit, - .load_lut = mdp5_crtc_load_lut, .atomic_check = mdp5_crtc_atomic_check, .atomic_begin = mdp5_crtc_atomic_begin, .atomic_flush = mdp5_crtc_atomic_flush, -- 2.1.3
[PATCH 2/5] drm/bochs: Remove dummy ->load_lut() implementation
From: Thierry RedingThe ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Gerd Hoffmann Signed-off-by: Thierry Reding --- drivers/gpu/drm/bochs/bochs_kms.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 85f0f8cf1fb8..26bcd03a8cb6 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -18,10 +18,6 @@ MODULE_PARM_DESC(defy, "default y resolution"); /* -- */ -static void bochs_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode) { switch (mode) { @@ -144,7 +140,6 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = { .mode_set_base = bochs_crtc_mode_set_base, .prepare = bochs_crtc_prepare, .commit = bochs_crtc_commit, - .load_lut = bochs_crtc_load_lut, }; static void bochs_crtc_init(struct drm_device *dev) -- 2.1.3
[PATCH 1/5] drm/armada: Remove dummy ->load_lut() implementation
From: Thierry RedingThe ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Russell King Signed-off-by: Thierry Reding --- drivers/gpu/drm/armada/armada_crtc.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index e3a7a5078e5c..42d2ffa08716 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -653,10 +653,6 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return 0; } -static void armada_drm_crtc_load_lut(struct drm_crtc *crtc) -{ -} - /* The mode_config.mutex will be held for this call */ static void armada_drm_crtc_disable(struct drm_crtc *crtc) { @@ -678,7 +674,6 @@ static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { .mode_fixup = armada_drm_crtc_mode_fixup, .mode_set = armada_drm_crtc_mode_set, .mode_set_base = armada_drm_crtc_mode_set_base, - .load_lut = armada_drm_crtc_load_lut, .disable= armada_drm_crtc_disable, }; -- 2.1.3
Long radeon stalls on recent kernels
On Wed, Dec 10, 2014 at 1:44 AM, Michel Dänzer wrote: > On 10.12.2014 06:39, Andy Lutomirski wrote: >> On Tue, Dec 9, 2014 at 8:06 AM, Andy Lutomirski >> wrote: >>> On Tue, Dec 9, 2014 at 1:18 AM, Michel Dänzer >>> wrote: On 09.12.2014 09:24, Andy Lutomirski wrote: > > The relevant line from latencytop seems to be: > > 154 20441402 489139 radeon_fence_default_wait [radeon] > fence_wait_timeout ttm_bo_wait [ttm] ttm_bo_move_accel_cleanup [ttm] > radeon_move_blit.isra.12 [radeon] radeon_bo_move [radeon] > ttm_bo_handle_move_mem [ttm] ttm_bo_evict [ttm] ttm_mem_evict_first > [ttm] ttm_bo_mem_space [ttm] ttm_bo_validate [ttm] > radeon_bo_fault_reserve_notify [radeon] Which process is this? >>> >>> Xorg >>> Looks like CPU access to a BO in VRAM, but the BO is located outside of the CPU visible area of VRAM, so it has to be moved into the CPU visible area first. Which version of Mesa are you using? >>> >>> mesa-dri-drivers-10.3.3-1.20141110.fc20.x86_64 >>> >>> I'm planning on upgrading to Fedora 21 fairly soon. >> >> Upgrading to mesa-dri-drivers-10.3.3-1.20141110.fc21.x86_64 seems to >> have helped enough that my usual test (open a couple of Firefox tabs >> with graphics in them) doesn't hang anymore. > > Hmm, since that looks like the exact same upstream version, maybe it was > actually upgrading something else that made the difference? > Maybe mutter? > >> This card still isn't *fast*. > > I'm afraid it wasn't exactly a high-end card even when it was new. What > kind of operations are slow? Things like scrolling in Google Maps. It's not *that* bad, but older Intel IGPs still seem considerably smoother. > > >> Is there some way I can check that I'm actually using all 16 PCIe lanes? >> In my tinkering w/ power management settings, I got some odd logs >> suggesting that only one lane was in use. > > You can try forcing off ASPM with radeon.aspm=0, other than that I'm not > sure. > > >> But I'm still waiting for the day that buggy userspace *can't* cause >> kernel graphics stalls. > > Actually, this looks more like buggy userspace stalling itself. :) I thought the stall was the kernel evicting things from vram. Why does it need to wait for userspace for that? Is it that userspace is actively using whatever's being evicted? --Andy > > > -- > Earthling Michel Dänzer | http://www.amd.com > Libre software enthusiast | Mesa and X developer -- Andy Lutomirski AMA Capital Management, LLC
[RFC] drm: add support for tiled/compressed/etc modifier in addfb2
In DRM/KMS we are lacking a good way to deal with tiled/compressed formats. Especially in the case of dmabuf/prime buffer sharing, where we cannot always rely on under-the-hood flags passed to driver specific gem-create ioctl to pass around these extra flags. The proposal is to add a per-plane format modifier. This allows to, if necessary, use different tiling patters for sub-sampled planes, etc. The format modifiers are added at the end of the ioctl struct, so for legacy userspace it will be zero padded. TODO how best to deal with assignment of modifier token values? The rough idea was to namespace things with an 8bit vendor-id, and then beyond that it is treated as an opaque value. But that was a relatively arbitrary choice. There are cases where same tiling pattern and/or compression is supported by various different vendors. So we should standardize to use the vendor-id and value of the first one who documents the format? TODO move definition of tokens to drm_fourcc.h? Signed-off-by: Rob Clark --- include/uapi/drm/drm_mode.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index aae71cb..c43648c 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -330,6 +330,28 @@ struct drm_mode_fb_cmd { #define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ +/* + * Format Modifiers: + * + * Format modifiers describe, typically, a re-ordering or modification + * of the data in a plane of an FB. This can be used to express tiled/ + * swizzled formats, or compression, or a combination of the two. + * + * The upper 8 bits of the format modifier are a vendor-id as assigned + * below. The lower 24 bits are assigned as vendor sees fit. + */ + +/* Vendor Ids: */ +#define DRM_FOURCC_MOD_VENDOR_SAMSUNG 0x03 +/* ... more */ + +#define DRM_FOURCC_MOD(vendor, name) (((DRM_FOURCC_MOD_VENDOR_## vendor) << 24) | val) + +/* Modifier values: */ +/* 64x32 macroblock, ie NV12MT: */ +#define DRM_FOURCC_MOD_SAMSUNG_64_32_TILE DRM_FOURCC_MOD(SAMSUNG, 123) +/* ... more */ + struct drm_mode_fb_cmd2 { __u32 fb_id; __u32 width, height; @@ -349,10 +371,18 @@ struct drm_mode_fb_cmd2 { * So it would consist of Y as offsets[0] and UV as * offsets[1]. Note that offsets[0] will generally * be 0 (but this is not required). +* +* To accommodate tiled, compressed, etc formats, a per-plane +* modifier can be specified. The default value of zero +* indicates "native" format as specified by the fourcc. +* Vendor specific modifier token. This allows, for example, +* different tiling/swizzling pattern on different planes. +* See discussion above of DRM_FOURCC_MOD_xxx. */ __u32 handles[4]; __u32 pitches[4]; /* pitch for each plane */ __u32 offsets[4]; /* offset of each plane */ + __u32 modifier[4]; /* ie, tiling, compressed (per plane) */ }; #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 -- 2.1.0
[PATCH] drm: bit of spell-check / editorializing.
Signed-off-by: Rob Clark --- include/uapi/drm/drm_mode.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 86574b0..aae71cb 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -338,7 +338,7 @@ struct drm_mode_fb_cmd2 { /* * In case of planar formats, this ioctl allows up to 4 -* buffer objects with offets and pitches per plane. +* buffer objects with offsets and pitches per plane. * The pitch and offset order is dictated by the fourcc, * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: * @@ -346,9 +346,9 @@ struct drm_mode_fb_cmd2 { * followed by an interleaved U/V plane containing * 8 bit 2x2 subsampled colour difference samples. * -* So it would consist of Y as offset[0] and UV as -* offeset[1]. Note that offset[0] will generally -* be 0. +* So it would consist of Y as offsets[0] and UV as +* offsets[1]. Note that offsets[0] will generally +* be 0 (but this is not required). */ __u32 handles[4]; __u32 pitches[4]; /* pitch for each plane */ -- 2.1.0
[PATCH] drm: Zero out DRM object memory upon cleanup
On Wed, Dec 10, 2014 at 11:38:49AM +0100, Thierry Reding wrote: > From: Thierry Reding > > Drivers where the DRM objects have a lifetime that extends beyond that > of the DRM device need to zero out the DRM object memory to void stale > data such as properties. The DRM core code expects to operate on newly > allocated and zeroed out objects and will behave unexpectedly, such as > add duplicate properties, otherwise. > > Signed-off-by: Thierry Reding Yeah, makes sense imo to do in the core. Reviewed-by: Daniel Vetter Also stuffed into drm-misc and I think I'll throw that at Dave today or tomorrow. -Daniel > --- > drivers/gpu/drm/drm_crtc.c | 11 ++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 4c9aaf8e6176..4e35d2f74e0f 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -725,6 +725,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) > WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); > if (crtc->state && crtc->funcs->atomic_destroy_state) > crtc->funcs->atomic_destroy_state(crtc, crtc->state); > + > + memset(crtc, 0, sizeof(*crtc)); > } > EXPORT_SYMBOL(drm_crtc_cleanup); > > @@ -927,6 +929,8 @@ void drm_connector_cleanup(struct drm_connector > *connector) > if (connector->state && connector->funcs->atomic_destroy_state) > connector->funcs->atomic_destroy_state(connector, > connector->state); > + > + memset(connector, 0, sizeof(*connector)); > } > EXPORT_SYMBOL(drm_connector_cleanup); > > @@ -1068,6 +1072,8 @@ void drm_bridge_cleanup(struct drm_bridge *bridge) > list_del(>head); > dev->mode_config.num_bridge--; > drm_modeset_unlock_all(dev); > + > + memset(bridge, 0, sizeof(*bridge)); > } > EXPORT_SYMBOL(drm_bridge_cleanup); > > @@ -1134,10 +1140,11 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) > drm_modeset_lock_all(dev); > drm_mode_object_put(dev, >base); > kfree(encoder->name); > - encoder->name = NULL; > list_del(>head); > dev->mode_config.num_encoder--; > drm_modeset_unlock_all(dev); > + > + memset(encoder, 0, sizeof(*encoder)); > } > EXPORT_SYMBOL(drm_encoder_cleanup); > > @@ -1257,6 +1264,8 @@ void drm_plane_cleanup(struct drm_plane *plane) > WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); > if (plane->state && plane->funcs->atomic_destroy_state) > plane->funcs->atomic_destroy_state(plane, plane->state); > + > + memset(plane, 0, sizeof(*plane)); > } > EXPORT_SYMBOL(drm_plane_cleanup); > > -- > 2.1.3 > -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH] drm: Zero out DRM object memory upon cleanup
From: Thierry RedingDrivers where the DRM objects have a lifetime that extends beyond that of the DRM device need to zero out the DRM object memory to void stale data such as properties. The DRM core code expects to operate on newly allocated and zeroed out objects and will behave unexpectedly, such as add duplicate properties, otherwise. Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_crtc.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4c9aaf8e6176..4e35d2f74e0f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -725,6 +725,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); if (crtc->state && crtc->funcs->atomic_destroy_state) crtc->funcs->atomic_destroy_state(crtc, crtc->state); + + memset(crtc, 0, sizeof(*crtc)); } EXPORT_SYMBOL(drm_crtc_cleanup); @@ -927,6 +929,8 @@ void drm_connector_cleanup(struct drm_connector *connector) if (connector->state && connector->funcs->atomic_destroy_state) connector->funcs->atomic_destroy_state(connector, connector->state); + + memset(connector, 0, sizeof(*connector)); } EXPORT_SYMBOL(drm_connector_cleanup); @@ -1068,6 +1072,8 @@ void drm_bridge_cleanup(struct drm_bridge *bridge) list_del(>head); dev->mode_config.num_bridge--; drm_modeset_unlock_all(dev); + + memset(bridge, 0, sizeof(*bridge)); } EXPORT_SYMBOL(drm_bridge_cleanup); @@ -1134,10 +1140,11 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) drm_modeset_lock_all(dev); drm_mode_object_put(dev, >base); kfree(encoder->name); - encoder->name = NULL; list_del(>head); dev->mode_config.num_encoder--; drm_modeset_unlock_all(dev); + + memset(encoder, 0, sizeof(*encoder)); } EXPORT_SYMBOL(drm_encoder_cleanup); @@ -1257,6 +1264,8 @@ void drm_plane_cleanup(struct drm_plane *plane) WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); if (plane->state && plane->funcs->atomic_destroy_state) plane->funcs->atomic_destroy_state(plane, plane->state); + + memset(plane, 0, sizeof(*plane)); } EXPORT_SYMBOL(drm_plane_cleanup); -- 2.1.3
[PATCH] drm/tegra: dsi: Add suspend/resume support
On 12/10/2014 03:29 AM, Sean Paul wrote: > On Sun, Dec 7, 2014 at 10:40 PM, Mark Zhang wrote: >> This patch adds the suspend/resume support for Tegra drm >> driver by calling the corresponding DPMS functions. [...] >> + if (dsi->slave) { >> + err = tegra_dsi_pad_calibrate(dsi->slave); >> + if (err < 0) { >> + dev_err(dsi->slave->dev, >> + "MIPI calibration failed: %d\n", err); >> + return err; >> + } >> + } > > Move this duplicate call into tegra_dsi_pad_calibrate() to be > consistent with the other functions in this file (eg: > tegra_dsi_set_timeout). > Yeah, will do. >> + >> err = tegra_dsi_get_muldiv(dsi->format, , ); >> if (err < 0) >> return err; >> @@ -833,6 +850,13 @@ static int tegra_output_dsi_setup_clock(struct >> tegra_output *output, >> dev_err(dsi->dev, "failed to set parent clock: %d\n", err); >> return err; >> } >> + if (dsi->slave) { >> + err = tegra_dsi_ganged_setup(dsi); >> + if (err < 0) { >> + dev_err(dsi->dev, "DSI ganged setup failed: %d\n", >> err); >> + return err; >> + } >> + } > > I think this belongs in ->enable() instead of here. > Actually "tegra_dsi_ganged_setup" is not needed any more. This function ensures that DSIA & DSIB use the same PLL in ganged mode. But if you read the Tegra124/Tegra132 TRM, you'll find there is no way to select the clock source for DSIB. I.E, DSIB always uses the same clock source with DSIA. Besides, PLLD is the only clock source for DSIA. I.E, "clk_get_parent"/"clk_set_parent" doesn't make sense for dsia & dsib clock now. I've posted a patch(in tegra clock driver) to fix this: http://article.gmane.org/gmane.linux.ports.tegra/20313 And the corresponding changes in dsi driver will arrive soon. >> >> err = clk_set_rate(dsi->clk_parent, plld); >> if (err < 0) { [...] >> + >> + drm_modeset_lock_all(tegra->drm); >> + list_for_each_entry(connector, >> >drm->mode_config.connector_list, >> + head) { >> + if (connector->funcs->dpms) >> + connector->funcs->dpms(connector, connector->dpms); >> + } >> + drm_modeset_unlock_all(tegra->drm); >> + >> + drm_helper_resume_force_mode(tegra->drm); >> + >> + return 0; >> +} >> +#endif > > So this is the tricky chunk, it definitely does not belong here. I > think it makes most sense for this to live in drm.c, however > host1x_driver doesn't have suspend/resume hooks. > Agree. drm.c is the best place for putting this. > I suspect the correct thing to do here is to add them to > host1x_driver, but I'm not sure how much effort is involved in doing > that. > I thought about this before. If we do it in host1x driver, IIUC, it means that when host1x starts suspending, it will suspend all host1x client devices, right? Honestly I feel this is not a good thing despite I can't tell what's the problem in this right now... Mark > Sean > >> + >> + >> static const struct of_device_id tegra_dsi_of_match[] = { >> { .compatible = "nvidia,tegra114-dsi", }, >> { }, >> @@ -1557,4 +1636,9 @@ struct platform_driver tegra_dsi_driver = { >> }, >> .probe = tegra_dsi_probe, >> .remove = tegra_dsi_remove, >> +#ifdef CONFIG_PM >> + .suspend = tegra_dsi_suspend, >> + .resume = tegra_dsi_resume, >> +#endif >> + >> }; >> -- >> 1.8.1.5 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in >> the body of a message to majordomo at vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> Please read the FAQ at http://www.tux.org/lkml/
Long radeon stalls on recent kernels
On Tue, Dec 9, 2014 at 4:39 PM, Andy Lutomirski wrote: > On Tue, Dec 9, 2014 at 8:06 AM, Andy Lutomirski > wrote: >> On Tue, Dec 9, 2014 at 1:18 AM, Michel Dänzer wrote: >>> On 09.12.2014 09:24, Andy Lutomirski wrote: The relevant line from latencytop seems to be: 154 20441402 489139 radeon_fence_default_wait [radeon] fence_wait_timeout ttm_bo_wait [ttm] ttm_bo_move_accel_cleanup [ttm] radeon_move_blit.isra.12 [radeon] radeon_bo_move [radeon] ttm_bo_handle_move_mem [ttm] ttm_bo_evict [ttm] ttm_mem_evict_first [ttm] ttm_bo_mem_space [ttm] ttm_bo_validate [ttm] radeon_bo_fault_reserve_notify [radeon] >>> >>> Which process is this? >> >> Xorg >> >>> >>> Looks like CPU access to a BO in VRAM, but the BO is located outside of >>> the CPU visible area of VRAM, so it has to be moved into the CPU visible >>> area first. >>> >>> Which version of Mesa are you using? >>> >> >> mesa-dri-drivers-10.3.3-1.20141110.fc20.x86_64 >> >> I'm planning on upgrading to Fedora 21 fairly soon. > > Upgrading to mesa-dri-drivers-10.3.3-1.20141110.fc21.x86_64 seems to > have helped enough that my usual test (open a couple of Firefox tabs > with graphics in them) doesn't hang anymore. > > This card still isn't *fast*. Is there some way I can check that I'm > actually using all 16 PCIe lanes? In my tinkering w/ power management > settings, I got some odd logs suggesting that only one lane was in > use. > You should be using all the lanes available. The main issue with that card is vram memory bandwidth. Those chips have a single channel memory interface and most OEMs populate them with DDR3 memory rather than GDDR5. from your log: [3.079577] [drm] RAM width 64bits DDR ... [3.082589] [drm] enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0 Alex
[PATCH] drm/radeon: properly filter DP1.2 4k modes on non-DP1.2 hw
The check was already in place in the dp mode_valid check, but radeon_dp_get_dp_link_clock() never returned the high clock mode_valid was checking for because that function clipped the clock based on the hw capabilities. Add an explicit check in the mode_valid function. bug: https://bugs.freedesktop.org/show_bug.cgi?id=87172 Signed-off-by: Alex Deucher Cc:stable at vge.kernel.org --- drivers/gpu/drm/radeon/atombios_dp.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 11ba9d2..db42a67 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -492,6 +492,10 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct radeon_connector_atom_dig *dig_connector; int dp_clock; + if ((mode->clock > 34) && + (!radeon_connector_is_dp12_capable(connector))) + return MODE_CLOCK_HIGH; + if (!radeon_connector->con_priv) return MODE_CLOCK_HIGH; dig_connector = radeon_connector->con_priv; -- 1.8.3.1
[PATCH] drm: fb helper should avoid sleeping in panic context
Hi Rob, Yes it's exactly what I'm doing. Please scroll down and review my patch. Thanks Rui On 12/10/14, Rob Clark wrote: > perhaps fb helpers could use __drm_modeset_lock_all() w/ trylock=true > in panic context? > > BR, > -R > > On Tue, Dec 9, 2014 at 7:09 PM, rui wang wrote: >> Hi All, >> >> Any comment ? Or any better idea how this should be fixed? >> >> Regards, >> Rui >> >> -- Forwarded message -- >> From: ruiv.wang at gmail.com >> Date: Thu, 4 Dec 2014 22:11:35 +0800 >> Subject: [PATCH] drm: fb helper should avoid sleeping in panic context >> To: airlied at redhat.com, daniel.vetter at ffwll.ch, tony.luck at intel.com, >> bp at alien8.de, aris at redhat.com, rui.y.wang at intel.com >> Cc: linux-kernel at vger.kernel.org >> >> From: Rui Wang >> >> There are still some places in the fb helper that need to avoid >> sleeping in panic context. Here's an example: >> >> [ 65.615496] bad: scheduling from the idle thread! >> [ 65.620747] CPU: 92 PID: 0 Comm: swapper/92 Tainted: G ME >> 3.18.0-rc4-7-default+ #20 >> >> [ 65.630364] Hardware name: Intel Corporation BRICKLAND/BRICKLAND, >> BIOS BRHSXSD1.86B.0056.R01.1409242327 09/24/2014 >> [ 65.641923] 88087f693d80 88087f689878 81566db9 >> >> [ 65.650226] 88087f693d80 88087f689898 810871ff >> 88046eb3e0d0 >> [ 65.658527] 88087f693d80 88087f6898c8 8107c1fa >> 00017f6898b8 >> [ 65.666830] Call Trace: >> [ 65.669557] <#MC> [] dump_stack+0x46/0x58 >> [ 65.675994] [] dequeue_task_idle+0x2f/0x40 >> [ 65.682412] [] dequeue_task+0x5a/0x80 >> [ 65.688345] [] deactivate_task+0x23/0x30 >> [ 65.694569] [] __schedule+0x580/0x7f0 >> [ 65.700502] [] schedule_preempt_disabled+0x29/0x70 >> [ 65.707696] [] __ww_mutex_lock_slowpath+0xb8/0x162 >> [ 65.714891] [] __ww_mutex_lock+0x53/0x85 >> [ 65.721125] [] drm_modeset_lock+0x3d/0x110 [drm] >> [ 65.728132] [] __drm_modeset_lock_all+0x8a/0x120 >> [drm] >> [ 65.735721] [] drm_modeset_lock_all+0x10/0x30 [drm] >> [ 65.743015] [] >> drm_fb_helper_pan_display+0x2f/0xf0 [drm_kms_helper] >> [ 65.751857] [] fb_pan_display+0xd1/0x1a0 >> [ 65.758081] [] bit_update_start+0x20/0x50 >> [ 65.764400] [] fbcon_switch+0x3a2/0x550 >> [ 65.770528] [] redraw_screen+0x189/0x240 >> [ 65.776750] [] fbcon_blank+0x20a/0x2d0 >> [ 65.782778] [] ? erst_writer+0x209/0x330 >> [ 65.789002] [] ? internal_add_timer+0x63/0x80 >> [ 65.795710] [] ? mod_timer+0x127/0x1e0 >> [ 65.801740] [] do_unblank_screen+0xa8/0x1d0 >> [ 65.808255] [] unblank_screen+0x10/0x20 >> [ 65.814381] [] bust_spinlocks+0x19/0x40 >> [ 65.820508] [] panic+0x106/0x1f5 >> [ 65.825955] [] mce_panic+0x2ac/0x2e0 >> [ 65.831789] [] ? delay_tsc+0x4a/0x80 >> [ 65.837625] [] do_machine_check+0xbaf/0xbf0 >> [ 65.844138] [] ? intel_idle+0xc7/0x150 >> [ 65.850166] [] machine_check+0x1f/0x30 >> [ 65.856195] [] ? intel_idle+0xc7/0x150 >> [ 65.86] <> [] >> cpuidle_enter_state+0x55/0x170 >> [ 65.869823] [] cpuidle_enter+0x17/0x20 >> [ 65.875852] [] cpu_startup_entry+0x2d8/0x370 >> [ 65.882467] [] start_secondary+0x159/0x180 >> >> There's __drm_modeset_lock_all() which Daniel Vetter introduced for this >> purpose. We can leverage that without reinventing anything. This patch >> works with the latest kernel. >> >> Signed-off-by: Rui Wang >> --- >> drivers/gpu/drm/drm_fb_helper.c |8 ++-- >> 1 files changed, 6 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_fb_helper.c >> b/drivers/gpu/drm/drm_fb_helper.c >> index 0c0c39b..70dd2f4 100644 >> --- a/drivers/gpu/drm/drm_fb_helper.c >> +++ b/drivers/gpu/drm/drm_fb_helper.c >> @@ -732,7 +732,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, >> struct fb_info *info) >> int i, j, rc = 0; >> int start; >> >> - drm_modeset_lock_all(dev); >> + if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { >> + return -EBUSY; >> + } >> if (!drm_fb_helper_is_bound(fb_helper)) { >> drm_modeset_unlock_all(dev); >> return -EBUSY; >> @@ -910,7 +912,9 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo >> *var, >> int ret = 0; >> int i; >> >> - drm_modeset_lock_all(dev); >> + if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { >> + return -EBUSY; >> + } >> if (!drm_fb_helper_is_bound(fb_helper)) { >> drm_modeset_unlock_all(dev); >> return -EBUSY; >> -- >> 1.7.5.4 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-kernel" >> in >> the body of a message to majordomo at vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> Please read the FAQ at http://www.tux.org/lkml/ >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-kernel" >> in >> the body of a message to