[Patch] x86, ia64, efifb: Move boot_vga fixup from pci to vgaarb
With commit b4aa0163056b6c70029b6e8619ce07c274351f42 Matthew Garret introduced a efifb vga_default_device() so that EFI systems that do not load shadow VBIOS or setup VGA get proper value for boot_vga PCI sysfs attribute on the corresponding PCI device. Xorg is refusing to autodetect devices when boot_vga=0 which is the case on some EFI system (e.g. MacBookAir2,1). Xorg detects the GPU and finds the dri device but then bails out with "no devices detected". With introduction of sysfb/simplefb/simpledrm efifb is getting obsolete while having native drivers for the GPU also makes selecting sysfb/efifb optional. Remove the efifb implementation of vga_default_device() and initialize vgaarb's vga_default_device() with the PCI GPU that matches boot screen_info in pci_fixup_video() [x86 and ia64 pci_fixup_video merged into common function in vgaarb.c]. Other architectures with PCI GPU might need a similar fixup. Note: If CONFIG_VGA_ARB is unset vga_default_device() is only available as a stub that returns NULL, making this adjustment insufficient. In addition, with the merge of x86/ia64 fixup code, this would also result in disabled fixup. Unsetting CONFIG_VGA_ARB requires CONFIG_EXPERT=y though. Signed-off-by: Bruno Pr?mont --- This is ported to changes in pci/fixup.c that landed in 3.15-rcs. Is this fine to go in, if so who will take it? I got no feedback on my last respin (on top of 3.14 a couple of weeks ago, which added moving the ia64 pci boot_vga fixup). I've been running this revision for a week or so on 3.15-rc kernels here (mostly EFI-enabled system, the mentioned MBA as wells as non-Apple systems where the patch was not required). arch/ia64/pci/fixup.c | 56 ++--- arch/x86/include/asm/vga.h | 6 arch/x86/pci/fixup.c| 55 + drivers/gpu/vga/vgaarb.c| 75 + drivers/video/fbdev/efifb.c | 38 --- include/linux/vgaarb.h | 37 ++ 6 files changed, 116 insertions(+), 151 deletions(-) diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c index eee069a..5df22f9 100644 --- a/arch/ia64/pci/fixup.c +++ b/arch/ia64/pci/fixup.c @@ -9,64 +9,14 @@ #include -/* - * Fixup to mark boot BIOS video selected by BIOS before it changes - * - * From information provided by "Jon Smirl" - * - * The standard boot ROM sequence for an x86 machine uses the BIOS - * to select an initial video card for boot display. This boot video - * card will have it's BIOS copied to C in system RAM. - * IORESOURCE_ROM_SHADOW is used to associate the boot video - * card with this copy. On laptops this copy has to be used since - * the main ROM may be compressed or combined with another image. - * See pci_map_rom() for use of this flag. Before marking the device - * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set - * by either arch cde or vga-arbitration, if so only apply the fixup to this - * already determined primary video card. - */ - -static void pci_fixup_video(struct pci_dev *pdev) +static void pci_ia64_fixup_video(struct pci_dev *pdev) { - struct pci_dev *bridge; - struct pci_bus *bus; - u16 config; - if ((strcmp(ia64_platform_name, "dig") != 0) && (strcmp(ia64_platform_name, "hpzx1") != 0)) return; /* Maybe, this machine supports legacy memory map. */ - /* Is VGA routed to us? */ - bus = pdev->bus; - while (bus) { - bridge = bus->self; - - /* -* From information provided by -* "David Miller" -* The bridge control register is valid for PCI header -* type BRIDGE, or CARDBUS. Host to PCI controllers use -* PCI header type NORMAL. -*/ - if (bridge - &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) - ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, - ); - if (!(config & PCI_BRIDGE_CTL_VGA)) - return; - } - bus = bus->parent; - } - if (!vga_default_device() || pdev == vga_default_device()) { - pci_read_config_word(pdev, PCI_COMMAND, ); - if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; - dev_printk(KERN_DEBUG, >dev, "Boot video device\n"); - vga_set_default_device(pdev); - } - } + pci_fixup_video(pdev); } DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); +
[PATCH 11/12] drm/i915: Accurately initialize fifo underrun state on gmch platforms
On Wed, 2014-05-14 at 20:51 +0200, Daniel Vetter wrote: > We don't have hardware based disable bits on gmch platforms, so need > to block spurious underrun reports in software. Which means that we > _must_ start out with fifo underrun reporting disabled everywhere. > > This is in big contrast to ilk/hsw/cpt where there's only _one_ > disable bit for all platforms and hence we must allow underrun > reporting on disabled pipes. Otherwise nothing really works, > especially the CRC support since that's key'ed off the same irq > disable bit. > > This allows us to ditch the fifo underrun reporting hack from the vlv > runtime pm code and unexport the internal function from i915_irq.c > again. Yay! > > v2: Keep the display irq disabling, spotted by Imre. > > Cc: Imre Deak > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/i915/i915_irq.c | 4 ++-- > drivers/gpu/drm/i915/intel_display.c | 9 - > drivers/gpu/drm/i915/intel_drv.h | 2 -- > drivers/gpu/drm/i915/intel_pm.c | 6 -- > 4 files changed, 10 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index afa55199b829..a502faae0d0b 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -415,8 +415,8 @@ static void cpt_set_fifo_underrun_reporting(struct > drm_device *dev, > * > * Returns the previous state of underrun reporting. > */ > -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > - enum pipe pipe, bool enable) > +static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > + enum pipe pipe, bool enable) > { > struct drm_i915_private *dev_priv = dev->dev_private; > struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index d4abaa4bf2f4..e78003ac71a0 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -11510,11 +11510,18 @@ static void intel_sanitize_crtc(struct intel_crtc > *crtc) > encoder->base.crtc = NULL; > } > } > - if (crtc->active) { > + > + if (crtc->active || IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen < 5) { > /* >* We start out with underrun reporting disabled to avoid races. >* For correct bookkeeping mark this on active crtcs. >* > + * Also on gmch platforms we dont have any hardware bits to > + * disable the underrun reporting. Which means we need to start > + * out with underrun reporting disabled also on inactive pipes, > + * since otherwise we'll complain about the garbage we read when > + * e.g. coming up after runtime pm. > + * >* No protection against concurrent access is required - at >* worst a fifo underrun happens which also sets this to false. >*/ > diff --git a/drivers/gpu/drm/i915/intel_drv.h > b/drivers/gpu/drm/i915/intel_drv.h > index b885df150910..d3fa5e0a13bd 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -642,8 +642,6 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) > /* i915_irq.c */ > bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > enum pipe pipe, bool enable); > -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, > - enum pipe pipe, bool enable); > bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, > enum transcoder pch_transcoder, > bool enable); > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c > index 45fa43f16bb3..08d5d4c16fdf 100644 > --- a/drivers/gpu/drm/i915/intel_pm.c > +++ b/drivers/gpu/drm/i915/intel_pm.c > @@ -5605,15 +5605,9 @@ static void vlv_display_power_well_enable(struct > drm_i915_private *dev_priv, > static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, > struct i915_power_well *power_well) > { > - struct drm_device *dev = dev_priv->dev; > - enum pipe pipe; > - > WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D); > > spin_lock_irq(_priv->irq_lock); > - for_each_pipe(pipe) > - __intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); > - As we discussed on IRC, something like the following could be added to the commit log: Originally the purpose of disabling the reporting on vlv was to prevent spurious underflow reports when the power well is turned off and the pipestat register containing the underflow flag will read 0x.
[PATCH v3 1/3] phy: Add exynos-simple-phy driver
Hi Rahul, Tomasz, On 14.05.2014 21:17, Rahul Sharma wrote: > From: Tomasz Stanislawski > > Add exynos-simple-phy driver to support a single register > PHY interfaces present on Exynos4 SoC. > > Signed-off-by: Tomasz Stanislawski > Signed-off-by: Rahul Sharma > > --- > .../devicetree/bindings/phy/samsung-phy.txt| 56 ++ > drivers/phy/Kconfig|5 + > drivers/phy/Makefile |1 + > drivers/phy/exynos-simple-phy.c| 189 > > include/dt-bindings/phy/exynos-simple-phy.h| 27 +++ > 5 files changed, 278 insertions(+) > create mode 100644 drivers/phy/exynos-simple-phy.c > create mode 100644 include/dt-bindings/phy/exynos-simple-phy.h > > diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt > b/Documentation/devicetree/bindings/phy/samsung-phy.txt > index 2049261..12ad9cf 100644 > --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt > +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt > @@ -161,3 +161,59 @@ Example: > usbdrdphy0 = _phy0; > usbdrdphy1 = _phy1; > }; > + > +Samsung S5P/EXYNOS SoC series SIMPLE PHY > +- > + > +Required properties: > +- compatible : should be one of the listed compatibles: > + - "samsung,exynos4210-simple-phy" > + - "samsung,exynos4412-simple-phy" > + - "samsung,exynos5250-simple-phy" > + - "samsung,exynos5420-simple-phy" > +- samsung,pmureg-phandle - handle to syscon to control PMU registers > +- #phy-cells : from the generic phy bindings, must be 1; > + > +For "samsung,exynos4210-simple-phy" compatible PHYs the second cell in > +the PHY specifier identifies the PHY and the supported phys for exynos4210 > +are: > + HDMI_PHY, > + DAC_PHY, > + ADC_PHY, > + PCIE_PHY, > + SATA_PHY. > + > +For "samsung,exynos4412-simple-phy" compatible PHYs the second cell in > +the PHY specifier identifies the PHY and the supported phys for exynos4412 > +are: > + HDMI_PHY, > + ADC_PHY. > + > +For "samsung,exynos5250-simple-phy" compatible PHYs the second cell in > +the PHY specifier identifies the PHY and the supported phys for exynos5250 > +are: > + HDMI_PHY, > + ADC_PHY, > + SATA_PHY. > + > +For "samsung,exynos5420-simple-phy" compatible PHYs the second cell in > +the PHY specifier identifies the PHY and the supported phys for exynos5420 > +are: > + HDMI_PHY, > + ADC_PHY. > + > +Example: > +Simple PHY provider node: > + > + simplephys: simple-phys at 1004 { > + compatible = "samsung,exynos5250-simple-phy"; Missing reg property or unnecessary @unit-address suffix in node name. > + samsung,pmu-syscon = <_system_controller>; > + #phy-cells = <1>; > + }; In general, the idea is quite good, but I think this should rather bind to the main PMU node, since this is just a part of the PMU, not another device in the system. This also means that the PMU node itself should be the PHY provider. Otherwise looks good. Best regards, Tomasz
[Bug 73378] [drm:radeon_uvd_send_upll_ctlreq] *ERROR* Timeout setting UVD clocks!
https://bugs.freedesktop.org/show_bug.cgi?id=73378 --- Comment #7 from ?yvind Saether --- > Can you bisect? Not sure how to do that but if you want to point me to some instructions then please do. Basically suspend and resume works with 3.12 kernels but in later kernels I can suspend and then resume once but after that the system does not suspend anymore. -- 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/20140514/79b82f06/attachment.html>
[Bug 75992] Display freezes & corruption with an r7 260x on 3.14-rc6
https://bugs.freedesktop.org/show_bug.cgi?id=75992 --- Comment #59 from nicolas.laplante at gmail.com --- Well, same thing with _mc2.bin, except this line (size changed): radeon/BONAIRE_mc2.bin: 31792 bytes I still get the Direct firmware load error and calibrating clocksource TSC takes a long time too. Usually I get this slowdown when the drm firmware cannot be loaded correctly. -- 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/20140514/ccf1b98d/attachment.html>
[Bug 75992] Display freezes & corruption with an r7 260x on 3.14-rc6
https://bugs.freedesktop.org/show_bug.cgi?id=75992 --- Comment #58 from nicolas.laplante at gmail.com --- Just saw that I'm loading the wrong firmware (_mc, not _mc2). Sorry. I'll try this now. -- 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/20140514/61d9b455/attachment.html>
[Bug 75992] Display freezes & corruption with an r7 260x on 3.14-rc6
https://bugs.freedesktop.org/show_bug.cgi?id=75992 --- Comment #57 from nicolas.laplante at gmail.com --- Ok, tried 3.15_rc5 and I get no corruption. But, booting took a long time (calibrating clocksource TSC) and I got this message: radeon :01:00.0: Direct firmware load failed with error -2 Here's the dmesg | grep drm: [0.703606] [drm] Initialized drm 1.1.0 20060810 [0.703728] [drm] radeon kernel modesetting enabled. [0.704231] [drm] initializing kernel modesetting (BONAIRE 0x1002:0x6658 0x174B:0xE253). [0.704390] [drm] register mmio base: 0xFE9C [0.704477] [drm] register mmio size: 262144 [0.704565] [drm] doorbell mmio base: 0xCF80 [0.704649] [drm] doorbell mmio size: 8388608 [0.707062] [drm] Detected VRAM RAM=2048M, BAR=256M [0.707148] [drm] RAM width 128bits DDR [0.707658] [drm] radeon: 2048M of VRAM memory ready [0.707744] [drm] radeon: 1024M of GTT memory ready. [0.707846] [drm] Loading BONAIRE Microcode [ 60.691462] [drm] radeon/BONAIRE_mc.bin: 31464 bytes [ 60.691551] [drm] Internal thermal controller with fan control [ 60.691679] [drm] probing gen 2 caps for device 1002:5978 = 300d02/0 [ 60.699424] [drm] radeon: dpm initialized [ 120.799122] [drm] GART: num cpu pages 262144, num gpu pages 262144 [ 120.801322] [drm] probing gen 2 caps for device 1002:5978 = 300d02/0 [ 120.801413] [drm] PCIE gen 2 link speeds already enabled [ 120.810251] [drm] PCIE GART of 1024M enabled (table at 0x00277000). [ 120.811879] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). [ 120.811968] [drm] Driver supports precise vblank timestamp query. [ 120.812206] [drm] radeon: irq initialized. [ 120.814520] [drm] ring test on 0 succeeded in 3 usecs [ 120.814689] [drm] ring test on 1 succeeded in 3 usecs [ 120.814790] [drm] ring test on 2 succeeded in 3 usecs [ 120.815030] [drm] ring test on 3 succeeded in 2 usecs [ 120.815127] [drm] ring test on 4 succeeded in 2 usecs [ 120.871242] [drm] ring test on 5 succeeded in 2 usecs [ 120.891334] [drm] UVD initialized successfully. [ 120.891718] [drm] ib test on ring 0 succeeded in 0 usecs [ 120.891961] [drm] ib test on ring 1 succeeded in 0 usecs [ 120.892205] [drm] ib test on ring 2 succeeded in 0 usecs [ 120.892467] [drm] ib test on ring 3 succeeded in 0 usecs [ 120.892719] [drm] ib test on ring 4 succeeded in 0 usecs [ 120.913684] [drm] ib test on ring 5 succeeded [ 120.934151] [drm] Radeon Display Connectors [ 120.934232] [drm] Connector 0: [ 120.934318] [drm] DP-1 [ 120.934402] [drm] HPD2 [ 120.934488] [drm] DDC: 0x6530 0x6530 0x6534 0x6534 0x6538 0x6538 0x653c 0x653c [ 120.934615] [drm] Encoders: [ 120.934700] [drm] DFP1: INTERNAL_UNIPHY2 [ 120.934786] [drm] Connector 1: [ 120.934864] [drm] HDMI-A-1 [ 120.934948] [drm] HPD3 [ 120.935033] [drm] DDC: 0x6550 0x6550 0x6554 0x6554 0x6558 0x6558 0x655c 0x655c [ 120.935152] [drm] Encoders: [ 120.935230] [drm] DFP2: INTERNAL_UNIPHY2 [ 120.935315] [drm] Connector 2: [ 120.935394] [drm] DVI-D-1 [ 120.935479] [drm] HPD1 [ 120.935563] [drm] DDC: 0x6560 0x6560 0x6564 0x6564 0x6568 0x6568 0x656c 0x656c [ 120.935684] [drm] Encoders: [ 120.935763] [drm] DFP3: INTERNAL_UNIPHY1 [ 120.935850] [drm] Connector 3: [ 120.935928] [drm] DVI-I-1 [ 120.936006] [drm] HPD6 [ 120.936085] [drm] DDC: 0x6580 0x6580 0x6584 0x6584 0x6588 0x6588 0x658c 0x658c [ 120.936211] [drm] Encoders: [ 120.936295] [drm] DFP4: INTERNAL_UNIPHY [ 120.936381] [drm] CRT1: INTERNAL_KLDSCP_DAC1 [ 120.990787] [drm] fb mappable at 0xD047A000 [ 120.990873] [drm] vram apper at 0xD000 [ 120.990952] [drm] size 7299072 [ 120.991037] [drm] fb depth is 24 [ 120.991116] [drm]pitch is 6912 [ 120.991261] fbcon: radeondrmfb (fb0) is primary device [ 121.025398] radeon :01:00.0: fb0: radeondrmfb frame buffer device [ 121.026375] [drm] Initialized radeon 2.38.0 20080528 for :01:00.0 on minor -- 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/20140514/f76e608b/attachment-0001.html>
[Bug 76231] New: radeon: DCE2 & DCE3 HDMI setup should be updated/improved (to match fglrx)
https://bugzilla.kernel.org/show_bug.cgi?id=76231 Bug ID: 76231 Summary: radeon: DCE2 & DCE3 HDMI setup should be updated/improved (to match fglrx) Product: Drivers Version: 2.5 Kernel Version: torvalds/linux.git Hardware: All 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: zajec5 at gmail.com Regression: No Created attachment 136121 --> https://bugzilla.kernel.org/attachment.cgi?id=136121=edit Log of fglrx with DCE 2.0 and DCE 3.0 cards (HDMI setup) Current code isn't based on a perfect RE method, we were mostly observing registers, not tracing fglrx operations. It should be a good idea to trace fglrx operations and improve radeon's code to match it as much as possible. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH 04/12] drm: Add drm_vblank_on()
On Wed, May 14, 2014 at 08:51:06PM +0200, Daniel Vetter wrote: > From: Ville Syrj?l? > > drm_vblank_off() will turn off vblank interrupts, but as long as the > refcount is elevated drm_vblank_get() will not re-enable them. This > is a problem is someone is holding a vblank reference while a modeset is > happening, and the driver requires vblank interrupt to work during that > time. > > Add drm_vblank_on() as a counterpart to drm_vblank_off() which will > re-enabled vblank interrupts if the refcount is already elevated. This > will allow drivers to choose the specific places in the modeset sequence > at which vblank interrupts get disabled and enabled. > > Testcase: igt/kms_flip/*-vs-suspend Testcase: igt/kms_flip/*-vs-vblank-race > Signed-off-by: Ville Syrj?l? > [danvet: Add Testcase tag for the igt I've written.] > Signed-off-by: Daniel Vetter > --- > drivers/gpu/drm/drm_irq.c| 72 > ++-- > drivers/gpu/drm/i915/intel_display.c | 8 > include/drm/drmP.h | 1 + > 3 files changed, 62 insertions(+), 19 deletions(-) > > diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c > index 13d671ed3421..dd786d84daab 100644 > --- a/drivers/gpu/drm/drm_irq.c > +++ b/drivers/gpu/drm/drm_irq.c > @@ -840,6 +840,41 @@ static void drm_update_vblank_count(struct drm_device > *dev, int crtc) > } > > /** > + * drm_vblank_enable - enable the vblank interrupt on a CRTC > + * @dev: DRM device > + * @crtc: CRTC in question > + */ > +static int drm_vblank_enable(struct drm_device *dev, int crtc) > +{ > + int ret = 0; > + > + assert_spin_locked(>vbl_lock); > + > + spin_lock(>vblank_time_lock); > + > + if (!dev->vblank[crtc].enabled) { > + /* Enable vblank irqs under vblank_time_lock protection. > + * All vblank count & timestamp updates are held off > + * until we are done reinitializing master counter and > + * timestamps. Filtercode in drm_handle_vblank() will > + * prevent double-accounting of same vblank interval. > + */ > + ret = dev->driver->enable_vblank(dev, crtc); > + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); > + if (ret) > + atomic_dec(>vblank[crtc].refcount); > + else { > + dev->vblank[crtc].enabled = true; > + drm_update_vblank_count(dev, crtc); > + } > + } > + > + spin_unlock(>vblank_time_lock); > + > + return ret; > +} > + > +/** > * drm_vblank_get - get a reference count on vblank events > * @dev: DRM device > * @crtc: which CRTC to own > @@ -858,25 +893,7 @@ int drm_vblank_get(struct drm_device *dev, int crtc) > spin_lock_irqsave(>vbl_lock, irqflags); > /* Going from 0->1 means we have to enable interrupts again */ > if (atomic_add_return(1, >vblank[crtc].refcount) == 1) { > - spin_lock(>vblank_time_lock); > - if (!dev->vblank[crtc].enabled) { > - /* Enable vblank irqs under vblank_time_lock protection. > - * All vblank count & timestamp updates are held off > - * until we are done reinitializing master counter and > - * timestamps. Filtercode in drm_handle_vblank() will > - * prevent double-accounting of same vblank interval. > - */ > - ret = dev->driver->enable_vblank(dev, crtc); > - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", > - crtc, ret); > - if (ret) > - atomic_dec(>vblank[crtc].refcount); > - else { > - dev->vblank[crtc].enabled = true; > - drm_update_vblank_count(dev, crtc); > - } > - } > - spin_unlock(>vblank_time_lock); > + ret = drm_vblank_enable(dev, crtc); > } else { > if (!dev->vblank[crtc].enabled) { > atomic_dec(>vblank[crtc].refcount); > @@ -946,6 +963,23 @@ void drm_vblank_off(struct drm_device *dev, int crtc) > EXPORT_SYMBOL(drm_vblank_off); > > /** > + * drm_vblank_on - enable vblank events on a CRTC > + * @dev: DRM device > + * @crtc: CRTC in question > + */ > +void drm_vblank_on(struct drm_device *dev, int crtc) > +{ > + unsigned long irqflags; > + > + spin_lock_irqsave(>vbl_lock, irqflags); > + /* re-enable interrupts if there's are users left */ > + if (atomic_read(>vblank[crtc].refcount) != 0) > + WARN_ON(drm_vblank_enable(dev, crtc)); > + spin_unlock_irqrestore(>vbl_lock, irqflags); > +} > +EXPORT_SYMBOL(drm_vblank_on); > + > +/** > * drm_vblank_pre_modeset - account for vblanks across mode sets > * @dev: DRM device > * @crtc: CRTC in question > diff
[PATCH 12/12] [RFC] drm/crtc-helper: Enforce sane vblank counter semantics
It literally took us years in i915 to track down all the vblank bogosity, which means that userspace has now code to deal with random crap like stuck vblank waits, needless counter wraps and other hilarity. To make sure that all drivers are at least somewhat sane enforce minimal standards in the crtc helpers. Note that this is not perfect since for intermediate levels it's unclear whether the vblank will keep on running. Modern userspace is advised to just never use those. Totatlly untested. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index df281b54db01..64d8797cd172 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -167,6 +167,8 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev) else (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); crtc->primary->fb = NULL; + + drm_crtc_vblank_off(crtc->dev, crtc); } } } @@ -323,6 +325,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, crtc_funcs->prepare(crtc); + drm_crtc_vblank_off(dev, crtc); + /* Set up the DPLL and any encoders state that needs to adjust or depend * on the DPLL. */ @@ -349,6 +353,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, /* Now enable the clocks, plane, pipe, and connectors that we set up. */ crtc_funcs->commit(crtc); + drm_crtc_vblank_on(dev, crtc); + list_for_each_entry(encoder, >mode_config.encoder_list, head) { if (encoder->crtc != crtc) @@ -767,6 +773,9 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) if (crtc_funcs->dpms) (*crtc_funcs->dpms) (crtc, drm_helper_choose_crtc_dpms(crtc)); + + if (mode == DRM_MODE_DPMS_ON) + drm_crtc_vblank_on(crtc->dev, crtc); } if (encoder) drm_helper_encoder_dpms(encoder, encoder_dpms); @@ -781,6 +790,9 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) if (crtc_funcs->dpms) (*crtc_funcs->dpms) (crtc, drm_helper_choose_crtc_dpms(crtc)); + + if (mode == DRM_MODE_DPMS_OFF) + drm_crtc_vblank_off(crtc->dev, crtc); } } -- 1.8.3.1
[PATCH 11/12] [RFC] drm/irq: More robustness in drm_vblank_on|off
If we want to use this functionality in generic helpers to make sure that all drivers have somewhat sane vblank handling across modesets/dpms, we need to make it work for all drivers. But some don't support interrupts and hence also not vblank waits. Just return early on such drivers. Note that with pageflips drivers are free to implement them however they wish to. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 51ebe9086be9..03fba43ab6be 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1020,6 +1020,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc) unsigned long irqflags; unsigned int seq; + if (!dev->irq_enabled) + return; + spin_lock_irqsave(>vbl_lock, irqflags); vblank_disable_and_save(dev, crtc); wake_up(>vblank[crtc].queue); @@ -1080,6 +1083,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc) { unsigned long irqflags; + if (!dev->irq_enabled) + return; + spin_lock_irqsave(>vbl_lock, irqflags); /* re-enable interrupts if there's are users left */ if (atomic_read(>vblank[crtc].refcount) != 0) -- 1.8.3.1
[PATCH 11/12] drm/i915: Accurately initialize fifo underrun state on gmch platforms
We don't have hardware based disable bits on gmch platforms, so need to block spurious underrun reports in software. Which means that we _must_ start out with fifo underrun reporting disabled everywhere. This is in big contrast to ilk/hsw/cpt where there's only _one_ disable bit for all platforms and hence we must allow underrun reporting on disabled pipes. Otherwise nothing really works, especially the CRC support since that's key'ed off the same irq disable bit. This allows us to ditch the fifo underrun reporting hack from the vlv runtime pm code and unexport the internal function from i915_irq.c again. Yay! v2: Keep the display irq disabling, spotted by Imre. Cc: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 9 - drivers/gpu/drm/i915/intel_drv.h | 2 -- drivers/gpu/drm/i915/intel_pm.c | 6 -- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index afa55199b829..a502faae0d0b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -415,8 +415,8 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, * * Returns the previous state of underrun reporting. */ -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, -enum pipe pipe, bool enable) +static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, + enum pipe pipe, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d4abaa4bf2f4..e78003ac71a0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11510,11 +11510,18 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) encoder->base.crtc = NULL; } } - if (crtc->active) { + + if (crtc->active || IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen < 5) { /* * We start out with underrun reporting disabled to avoid races. * For correct bookkeeping mark this on active crtcs. * +* Also on gmch platforms we dont have any hardware bits to +* disable the underrun reporting. Which means we need to start +* out with underrun reporting disabled also on inactive pipes, +* since otherwise we'll complain about the garbage we read when +* e.g. coming up after runtime pm. +* * No protection against concurrent access is required - at * worst a fifo underrun happens which also sets this to false. */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b885df150910..d3fa5e0a13bd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -642,8 +642,6 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) /* i915_irq.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, enum pipe pipe, bool enable); -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, -enum pipe pipe, bool enable); bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, enum transcoder pch_transcoder, bool enable); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 45fa43f16bb3..08d5d4c16fdf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5605,15 +5605,9 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv, static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - struct drm_device *dev = dev_priv->dev; - enum pipe pipe; - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D); spin_lock_irq(_priv->irq_lock); - for_each_pipe(pipe) - __intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); - valleyview_disable_display_irqs(dev_priv); spin_unlock_irq(_priv->irq_lock); -- 1.8.3.1
[PATCH 10/12] drm/i915: rip our vblank reset hacks for runtime PM
Now that we unconditionally dtrt when disabling/enabling crtcs we don't need any hacks any longer to keep the vblank logic sane when all the registers go poof. So let's rip it all out. This essentially undoes commit 9dbd8febb4dbc9199fcf340b882eb930e36b65b6 Author: Paulo Zanoni Date: Tue Jul 23 10:48:11 2013 -0300 drm/i915: update last_vblank when disabling the power well Apparently igt/kms_flip is already powerful enough to exercise this properly, yay! See the reference regression report for details. References: https://bugs.freedesktop.org/show_bug.cgi?id=66808 Testcase: igt/kms_flip/*-vs-rpm Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 34 -- 1 file changed, 34 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 75c1c766b507..45fa43f16bb3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5423,33 +5423,6 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) } } -static void reset_vblank_counter(struct drm_device *dev, enum pipe pipe) -{ - assert_spin_locked(>vbl_lock); - - dev->vblank[pipe].last = 0; -} - -static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - enum pipe pipe; - unsigned long irqflags; - - /* -* After this, the registers on the pipes that are part of the power -* well will become zero, so we have to adjust our counters according to -* that. -* -* FIXME: Should we do this in general in drm_vblank_post_modeset? -*/ - spin_lock_irqsave(>vbl_lock, irqflags); - for_each_pipe(pipe) - if (pipe != PIPE_A) - reset_vblank_counter(dev, pipe); - spin_unlock_irqrestore(>vbl_lock, irqflags); -} - static void hsw_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { @@ -5478,8 +5451,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, I915_WRITE(HSW_PWR_WELL_DRIVER, 0); POSTING_READ(HSW_PWR_WELL_DRIVER); DRM_DEBUG_KMS("Requesting to disable the power well\n"); - - hsw_power_well_post_disable(dev_priv); } } } @@ -5646,11 +5617,6 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, valleyview_disable_display_irqs(dev_priv); spin_unlock_irq(_priv->irq_lock); - spin_lock_irq(>vbl_lock); - for_each_pipe(pipe) - reset_vblank_counter(dev, pipe); - spin_unlock_irq(>vbl_lock); - vlv_set_power_well(dev_priv, power_well, false); } -- 1.8.3.1
[PATCH 10/12] drm/i915: Accurately initialize fifo underrun state on gmch platforms
We don't have hardware based disable bits on gmch platforms, so need to block spurious underrun reports in software. Which means that we _must_ start out with fifo underrun reporting disabled everywhere. This is in big contrast to ilk/hsw/cpt where there's only _one_ disable bit for all platforms and hence we must allow underrun reporting on disabled pipes. Otherwise nothing really works, especially the CRC support since that's key'ed off the same irq disable bit. This allows us to ditch the fifo underrun reporting hack from the vlv runtime pm code and unexport the internal function from i915_irq.c again. Yay! v2: Keep the display irq disabling, spotted by Imre. Cc: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 9 - drivers/gpu/drm/i915/intel_drv.h | 2 -- drivers/gpu/drm/i915/intel_pm.c | 6 -- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index afa55199b829..a502faae0d0b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -415,8 +415,8 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, * * Returns the previous state of underrun reporting. */ -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, -enum pipe pipe, bool enable) +static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, + enum pipe pipe, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d4abaa4bf2f4..e78003ac71a0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11510,11 +11510,18 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) encoder->base.crtc = NULL; } } - if (crtc->active) { + + if (crtc->active || IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen < 5) { /* * We start out with underrun reporting disabled to avoid races. * For correct bookkeeping mark this on active crtcs. * +* Also on gmch platforms we dont have any hardware bits to +* disable the underrun reporting. Which means we need to start +* out with underrun reporting disabled also on inactive pipes, +* since otherwise we'll complain about the garbage we read when +* e.g. coming up after runtime pm. +* * No protection against concurrent access is required - at * worst a fifo underrun happens which also sets this to false. */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b885df150910..d3fa5e0a13bd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -642,8 +642,6 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) /* i915_irq.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, enum pipe pipe, bool enable); -bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, -enum pipe pipe, bool enable); bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, enum transcoder pch_transcoder, bool enable); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 45fa43f16bb3..08d5d4c16fdf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5605,15 +5605,9 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv, static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - struct drm_device *dev = dev_priv->dev; - enum pipe pipe; - WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D); spin_lock_irq(_priv->irq_lock); - for_each_pipe(pipe) - __intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); - valleyview_disable_display_irqs(dev_priv); spin_unlock_irq(_priv->irq_lock); -- 1.8.3.1
[PATCH 09/12] drm/irq: Lack of interrupt support in drm_vblank_on|off
If we want to use this functionality in generic helpers to make sure that all drivers have somewhat sane vblank handling across modesets/dpms, we need to make it work for all drivers. But some don't support interrupts and hence also not vblank waits. Just return early on such drivers. Note that with pageflips drivers are free to implement them however they wish to. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 51ebe9086be9..03fba43ab6be 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1020,6 +1020,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc) unsigned long irqflags; unsigned int seq; + if (!dev->irq_enabled) + return; + spin_lock_irqsave(>vbl_lock, irqflags); vblank_disable_and_save(dev, crtc); wake_up(>vblank[crtc].queue); @@ -1080,6 +1083,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc) { unsigned long irqflags; + if (!dev->irq_enabled) + return; + spin_lock_irqsave(>vbl_lock, irqflags); /* re-enable interrupts if there's are users left */ if (atomic_read(>vblank[crtc].refcount) != 0) -- 1.8.3.1
[PATCH 09/12] drm/i915: rip our vblank reset hacks for runtime PM
Now that we unconditionally dtrt when disabling/enabling crtcs we don't need any hacks any longer to keep the vblank logic sane when all the registers go poof. So let's rip it all out. This essentially undoes commit 9dbd8febb4dbc9199fcf340b882eb930e36b65b6 Author: Paulo Zanoni Date: Tue Jul 23 10:48:11 2013 -0300 drm/i915: update last_vblank when disabling the power well Apparently igt/kms_flip is already powerful enough to exercise this properly, yay! See the reference regression report for details. References: https://bugs.freedesktop.org/show_bug.cgi?id=66808 Testcase: igt/kms_flip/*-vs-rpm Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 34 -- 1 file changed, 34 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 75c1c766b507..45fa43f16bb3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5423,33 +5423,6 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) } } -static void reset_vblank_counter(struct drm_device *dev, enum pipe pipe) -{ - assert_spin_locked(>vbl_lock); - - dev->vblank[pipe].last = 0; -} - -static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - enum pipe pipe; - unsigned long irqflags; - - /* -* After this, the registers on the pipes that are part of the power -* well will become zero, so we have to adjust our counters according to -* that. -* -* FIXME: Should we do this in general in drm_vblank_post_modeset? -*/ - spin_lock_irqsave(>vbl_lock, irqflags); - for_each_pipe(pipe) - if (pipe != PIPE_A) - reset_vblank_counter(dev, pipe); - spin_unlock_irqrestore(>vbl_lock, irqflags); -} - static void hsw_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { @@ -5478,8 +5451,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, I915_WRITE(HSW_PWR_WELL_DRIVER, 0); POSTING_READ(HSW_PWR_WELL_DRIVER); DRM_DEBUG_KMS("Requesting to disable the power well\n"); - - hsw_power_well_post_disable(dev_priv); } } } @@ -5646,11 +5617,6 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, valleyview_disable_display_irqs(dev_priv); spin_unlock_irq(_priv->irq_lock); - spin_lock_irq(>vbl_lock); - for_each_pipe(pipe) - reset_vblank_counter(dev, pipe); - spin_unlock_irq(>vbl_lock); - vlv_set_power_well(dev_priv, power_well, false); } -- 1.8.3.1
[PATCH 08/12] drm/irq: Add kms-native crtc interface functions
We need to start somewhere ... With this the only places left in i915 where we use pipe integers is in the interrupt handling code. And there it actually makes some amount of sense. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c| 81 drivers/gpu/drm/i915/intel_display.c | 22 +- include/drm/drmP.h | 5 +++ 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 5ff986bd4de4..51ebe9086be9 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -916,6 +916,8 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc) * Acquire a reference count on vblank events to avoid having them disabled * while in use. * + * This is the legacy version of drm_crtc_vblank_get(). + * * Returns: * Zero on success, nonzero on failure. */ @@ -941,12 +943,33 @@ int drm_vblank_get(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_get); /** + * drm_crtc_vblank_get - get a reference count on vblank events + * @dev: drm device + * @crtc: which CRTC to own + * + * Acquire a reference count on vblank events to avoid having them disabled + * while in use. + * + * This is the native kms version of drm_vblank_off(). + * + * Returns: + * Zero on success, nonzero on failure. + */ +int drm_crtc_vblank_get(struct drm_device *dev, struct drm_crtc *crtc) +{ + return drm_vblank_get(dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_get); + +/** * drm_vblank_put - give up ownership of vblank events * @dev: drm device * @crtc: which counter to give up * * Release ownership of a given vblank counter, turning off interrupts * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. + * + * This is the legacy version of drm_crtc_vblank_put(). */ void drm_vblank_put(struct drm_device *dev, int crtc) { @@ -961,6 +984,22 @@ void drm_vblank_put(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_put); /** + * drm_crtc_vblank_put - give up ownership of vblank events + * @dev: drm device + * @crtc: which counter to give up + * + * Release ownership of a given vblank counter, turning off interrupts + * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. + * + * This is the native kms version of drm_vblank_put(). + */ +void drm_crtc_vblank_put(struct drm_device *dev, struct drm_crtc *crtc) +{ + drm_vblank_put(dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_put); + +/** * drm_vblank_off - disable vblank events on a CRTC * @dev: drm device * @crtc: CRTC in question @@ -971,6 +1010,8 @@ EXPORT_SYMBOL(drm_vblank_put); * * Drivers must use this function when the hardware vblank counter can get * reset, e.g. when suspending. + * + * This is the legacy version of drm_crtc_vblank_off(). */ void drm_vblank_off(struct drm_device *dev, int crtc) { @@ -1004,6 +1045,26 @@ void drm_vblank_off(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_off); /** + * drm_crtc_vblank_off - disable vblank events on a CRTC + * @dev: drm device + * @crtc: CRTC in question + * + * Drivers can use this function to shut down the vblank interrupt handling when + * disabling a crtc. This function ensures that the latest vblank frame count is + * stored so that drm_vblank_on can restore it again. + * + * Drivers must use this function when the hardware vblank counter can get + * reset, e.g. when suspending. + * + * This is the native kms version of drm_vblank_off(). + */ +void drm_crtc_vblank_off(struct drm_device *dev, struct drm_crtc *crtc) +{ + drm_vblank_off(dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_off); + +/** * drm_vblank_on - enable vblank events on a CRTC * @dev: drm device * @crtc: CRTC in question @@ -1012,6 +1073,8 @@ EXPORT_SYMBOL(drm_vblank_off); * drm_vblank_off() again. Note that calls to drm_vblank_on() and * drm_vblank_off() can be unbalanced and so can also be unconditionaly called * in driver load code to reflect the current hardware state of the crtc. + * + * This is the legacy version of drm_crtc_vblank_on(). */ void drm_vblank_on(struct drm_device *dev, int crtc) { @@ -1026,6 +1089,24 @@ void drm_vblank_on(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_on); /** + * drm_crtc_vblank_on - enable vblank events on a CRTC + * @dev: drm device + * @crtc: CRTC in question + * + * This functions restores the vblank interrupt state captured with + * drm_vblank_off() again. Note that calls to drm_vblank_on() and + * drm_vblank_off() can be unbalanced and so can also be unconditionaly called + * in driver load code to reflect the current hardware state of the crtc. + * + * This is the native kms version of drm_vblank_on(). + */ +void drm_crtc_vblank_on(struct drm_device *dev, struct drm_crtc *crtc) +{ + drm_vblank_on(dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_on); +
[PATCH 07/12] drm/irq: kerneldoc polish
- Integrate into the drm DocBook - Disable kerneldoc for functions not exported to drivers. - Properly document the new drm_vblank_on|off and add cautious comments explaining when drm_vblank_pre|post_modesets shouldn't be used. - General polish and OCD. Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 5 +- drivers/gpu/drm/drm_irq.c | 181 - 2 files changed, 129 insertions(+), 57 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index e37a77a72b8b..70ef87bcea04 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2519,6 +2519,10 @@ void (*disable_vblank) (struct drm_device *dev, int crtc); with a call to drm_vblank_cleanup in the driver unload operation handler. + + Vertical Blanking and Interrupt Handling Functions Reference +!Edrivers/gpu/drm/drm_irq.c + @@ -2870,7 +2874,6 @@ int num_ioctls; - diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index dd786d84daab..5ff986bd4de4 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1,6 +1,5 @@ -/** - * \file drm_irq.c - * IRQ support +/* + * drm_irq.c IRQ and vblank support * * \author Rickard E. (Rik) Faith * \author Gareth Hughes @@ -156,6 +155,12 @@ static void vblank_disable_fn(unsigned long arg) spin_unlock_irqrestore(>vbl_lock, irqflags); } +/** + * drm_vblank_cleanup - cleanup vblank support + * @dev: drm device + * + * This function cleans up any resources allocated in drm_vblank_init. + */ void drm_vblank_cleanup(struct drm_device *dev) { int crtc; @@ -175,6 +180,16 @@ void drm_vblank_cleanup(struct drm_device *dev) } EXPORT_SYMBOL(drm_vblank_cleanup); +/** + * drm_vblank_init - initialize vblank support + * @dev: drm_device + * @num_crtcs: number of crtcs supported by @dev + * + * This function initializes vblank support for @num_crtcs display pipelines. + * + * Returns: + * Zero on success or a negative error code on failure. + */ int drm_vblank_init(struct drm_device *dev, int num_crtcs) { int i, ret = -ENOMEM; @@ -238,13 +253,21 @@ static void drm_irq_vgaarb_nokms(void *cookie, bool state) } /** - * Install IRQ handler. - * - * \param dev DRM device. + * drm_irq_install - install IRQ handler + * @dev: drm device + * @irq: irq number to install the handler for * * Initializes the IRQ related data. Installs the handler, calling the driver - * \c irq_preinstall() and \c irq_postinstall() functions - * before and after the installation. + * irq_preinstall() and irq_postinstall() functions before and after the + * installation. + * + * This is the simplified helper interface provided for drivers with no special + * needs. Drivers which need to install interrupt handlers for multiple + * interrupts must instead set drm_device->irq_enabled to signal the drm core + * that vblank interrupts are available. + * + * Returns: + * Zero on success or a negative error code on failure. */ int drm_irq_install(struct drm_device *dev, int irq) { @@ -304,11 +327,20 @@ int drm_irq_install(struct drm_device *dev, int irq) EXPORT_SYMBOL(drm_irq_install); /** - * Uninstall the IRQ handler. + * drm_irq_uninstall - uninstall the IRQ handler + * @dev: drm device + * + * Calls the driver's irq_uninstall() function and unregisters the irq handler. + * This should only be called by drivers which used drm_irq_install() to set up + * their interrupt handler. Other drivers must only reset + * drm_device->irq_enabled to false. * - * \param dev DRM device. + * Note that for kernel modesetting drivers it is a bug if this function fails. + * The sanity checks are only to catch buggy user modesetting drivers which call + * the same function through an ioctl. * - * Calls the driver's \c irq_uninstall() function, and stops the irq. + * Returns: + * Zero on success or a negative error code on failure. */ int drm_irq_uninstall(struct drm_device *dev) { @@ -353,7 +385,7 @@ int drm_irq_uninstall(struct drm_device *dev) } EXPORT_SYMBOL(drm_irq_uninstall); -/** +/* * IRQ control ioctl. * * \param inode device inode. @@ -406,10 +438,9 @@ int drm_control(struct drm_device *dev, void *data, } /** - * drm_calc_timestamping_constants - Calculate vblank timestamp constants - * - * @crtc drm_crtc whose timestamp constants should be updated. - * @mode display mode containing the scanout timings + * drm_calc_timestamping_constants - calculate vblank timestamp constants + * @crtc: drm_crtc whose timestamp constants should be updated. + * @mode: display mode containing the scanout timings * * Calculate and store various constants which are later * needed by vblank and swap-completion timestamping, e.g, @@ -459,11 +490,22 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_calc_timestamping_constants); /** - *
[PATCH 06/12] drm/doc: Discourage usage of MODESET_CTL ioctl
Leftover from the old days of ums and should be used any longer. Since commit 29935554b384b1b3a7377d6f0b03b21d18a61683 Author: Laurent Pinchart Date: Wed May 30 00:58:09 2012 +0200 drm: Disallow DRM_IOCTL_MODESET_CTL for KMS drivers it is a complete no-Op for kms drivers. Cc: Laurent Pinchart Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 83dd0b043c28..e37a77a72b8b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2861,12 +2861,11 @@ int num_ioctls; DRM_IOCTL_MODESET_CTL -This should be called by application level drivers before and -after mode setting, since on many devices the vertical blank -counter is reset at that time. Internally, the DRM snapshots -the last vblank count when the ioctl is called with the -_DRM_PRE_MODESET command, so that the counter won't go backwards -(which is dealt with when _DRM_POST_MODESET is used). + This was only used for user-mode-settind drivers around + modesetting changes to allow the kernel to update the vblank + interrupt after mode setting, since on many devices the vertical + blank. Modern drivers should not call this any more since with + kernel mode setting it is a no-Op. -- 1.8.3.1
[PATCH 05/12] drm/i915: Remove drm_vblank_pre/post_modeset calls
Originally these functions have been for user modesetting drivers to ensure vblank processing doesn't fall over completely around modeset changes. This has been carried over ever since then. Now that Ville cleaned our vblank handling with an explicit drm_vblank_off/on braket when disabling/enabling crtcs. So this seems to be unnecessary now. The most important side effect was that due to the delayed vblank disabling we have been pretty much guaranteed to receive a vblank interrupt soonish after a crtc was enabled. Note that our vblank handling across modeset is still fairly decent fubar - we don't actually handle vblank counter all to well. drm_update_vblank_count will make sure that the frame counter always rolls forward, but userspace isn't really all to ready to cope with the big jumps this causes. This isn't a big mostly because the hardware retains the frame counter. But with runtime pm and also across suspend/resume we fall over. Fixing this is a lot more involved and also needs som i-g-ts. So material for another patch series. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 858c393b051f..d0eff53a8ad1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7207,15 +7207,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, struct intel_encoder *encoder; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_display_mode *mode = _crtc->config.requested_mode; - int pipe = intel_crtc->pipe; int ret; - drm_vblank_pre_modeset(dev, pipe); - ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb); - drm_vblank_post_modeset(dev, pipe); - if (ret != 0) return ret; -- 1.8.3.1
[PATCH 04/12] drm: Add drm_vblank_on()
From: Ville Syrj?l?drm_vblank_off() will turn off vblank interrupts, but as long as the refcount is elevated drm_vblank_get() will not re-enable them. This is a problem is someone is holding a vblank reference while a modeset is happening, and the driver requires vblank interrupt to work during that time. Add drm_vblank_on() as a counterpart to drm_vblank_off() which will re-enabled vblank interrupts if the refcount is already elevated. This will allow drivers to choose the specific places in the modeset sequence at which vblank interrupts get disabled and enabled. Testcase: igt/kms_flip/*-vs-suspend Signed-off-by: Ville Syrj?l? [danvet: Add Testcase tag for the igt I've written.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c| 72 ++-- drivers/gpu/drm/i915/intel_display.c | 8 include/drm/drmP.h | 1 + 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 13d671ed3421..dd786d84daab 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -840,6 +840,41 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) } /** + * drm_vblank_enable - enable the vblank interrupt on a CRTC + * @dev: DRM device + * @crtc: CRTC in question + */ +static int drm_vblank_enable(struct drm_device *dev, int crtc) +{ + int ret = 0; + + assert_spin_locked(>vbl_lock); + + spin_lock(>vblank_time_lock); + + if (!dev->vblank[crtc].enabled) { + /* Enable vblank irqs under vblank_time_lock protection. +* All vblank count & timestamp updates are held off +* until we are done reinitializing master counter and +* timestamps. Filtercode in drm_handle_vblank() will +* prevent double-accounting of same vblank interval. +*/ + ret = dev->driver->enable_vblank(dev, crtc); + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + if (ret) + atomic_dec(>vblank[crtc].refcount); + else { + dev->vblank[crtc].enabled = true; + drm_update_vblank_count(dev, crtc); + } + } + + spin_unlock(>vblank_time_lock); + + return ret; +} + +/** * drm_vblank_get - get a reference count on vblank events * @dev: DRM device * @crtc: which CRTC to own @@ -858,25 +893,7 @@ int drm_vblank_get(struct drm_device *dev, int crtc) spin_lock_irqsave(>vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ if (atomic_add_return(1, >vblank[crtc].refcount) == 1) { - spin_lock(>vblank_time_lock); - if (!dev->vblank[crtc].enabled) { - /* Enable vblank irqs under vblank_time_lock protection. -* All vblank count & timestamp updates are held off -* until we are done reinitializing master counter and -* timestamps. Filtercode in drm_handle_vblank() will -* prevent double-accounting of same vblank interval. -*/ - ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", - crtc, ret); - if (ret) - atomic_dec(>vblank[crtc].refcount); - else { - dev->vblank[crtc].enabled = true; - drm_update_vblank_count(dev, crtc); - } - } - spin_unlock(>vblank_time_lock); + ret = drm_vblank_enable(dev, crtc); } else { if (!dev->vblank[crtc].enabled) { atomic_dec(>vblank[crtc].refcount); @@ -946,6 +963,23 @@ void drm_vblank_off(struct drm_device *dev, int crtc) EXPORT_SYMBOL(drm_vblank_off); /** + * drm_vblank_on - enable vblank events on a CRTC + * @dev: DRM device + * @crtc: CRTC in question + */ +void drm_vblank_on(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + + spin_lock_irqsave(>vbl_lock, irqflags); + /* re-enable interrupts if there's are users left */ + if (atomic_read(>vblank[crtc].refcount) != 0) + WARN_ON(drm_vblank_enable(dev, crtc)); + spin_unlock_irqrestore(>vbl_lock, irqflags); +} +EXPORT_SYMBOL(drm_vblank_on); + +/** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device * @crtc: CRTC in question diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b39d0367dd68..858c393b051f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@
[PATCH 03/12] drm: Make blocking vblank wait return when the vblank interrupts get disabled
From: Ville Syrj?l?If there's a blocking vblank wait in progress while the vblank interrupt gets disabled, the current code will just let the vblank wait time out. Instead make it return immediately when vblank interrupts get disabled. Signed-off-by: Ville Syrj?l? Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 90c59a8c820f..13d671ed3421 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1189,6 +1189,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ, (((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) || +!dev->vblank[crtc].enabled || !dev->irq_enabled)); if (ret != -EINTR) { -- 1.8.3.1
[PATCH 02/12] drm: Make the vblank disable timer per-crtc
From: Ville Syrj?l?Currently there's one per-device vblank disable timer, and it gets reset wheneven the vblank refcount for any crtc drops to zero. That means that one crtc could accidentally be keeping the vblank interrupts for other crtcs enabled even if there are no users for them. Make the disable timer per-crtc to avoid this issue. Signed-off-by: Ville Syrj?l? Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 40 +--- include/drm/drmP.h| 4 +++- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index ea20c4aa1b6b..90c59a8c820f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -140,33 +140,34 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) static void vblank_disable_fn(unsigned long arg) { - struct drm_device *dev = (struct drm_device *)arg; + struct drm_vblank_crtc *vblank = (void *)arg; + struct drm_device *dev = vblank->dev; unsigned long irqflags; - int i; + int crtc = vblank->crtc; if (!dev->vblank_disable_allowed) return; - for (i = 0; i < dev->num_crtcs; i++) { - spin_lock_irqsave(>vbl_lock, irqflags); - if (atomic_read(>vblank[i].refcount) == 0 && - dev->vblank[i].enabled) { - DRM_DEBUG("disabling vblank on crtc %d\n", i); - vblank_disable_and_save(dev, i); - } - spin_unlock_irqrestore(>vbl_lock, irqflags); + spin_lock_irqsave(>vbl_lock, irqflags); + if (atomic_read(>refcount) == 0 && vblank->enabled) { + DRM_DEBUG("disabling vblank on crtc %d\n", crtc); + vblank_disable_and_save(dev, crtc); } + spin_unlock_irqrestore(>vbl_lock, irqflags); } void drm_vblank_cleanup(struct drm_device *dev) { + int crtc; + /* Bail if the driver didn't call drm_vblank_init() */ if (dev->num_crtcs == 0) return; - del_timer_sync(>vblank_disable_timer); - - vblank_disable_fn((unsigned long)dev); + for (crtc = 0; crtc < dev->num_crtcs; crtc++) { + del_timer_sync(>vblank[crtc].disable_timer); + vblank_disable_fn((unsigned long)>vblank[crtc]); + } kfree(dev->vblank); @@ -178,8 +179,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) { int i, ret = -ENOMEM; - setup_timer(>vblank_disable_timer, vblank_disable_fn, - (unsigned long)dev); spin_lock_init(>vbl_lock); spin_lock_init(>vblank_time_lock); @@ -189,8 +188,13 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) if (!dev->vblank) goto err; - for (i = 0; i < num_crtcs; i++) + for (i = 0; i < num_crtcs; i++) { + dev->vblank[i].dev = dev; + dev->vblank[i].crtc = i; init_waitqueue_head(>vblank[i].queue); + setup_timer(>vblank[i].disable_timer, vblank_disable_fn, + (unsigned long)>vblank[i]); + } DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); @@ -900,7 +904,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc) /* Last user schedules interrupt disable */ if (atomic_dec_and_test(>vblank[crtc].refcount) && (drm_vblank_offdelay > 0)) - mod_timer(>vblank_disable_timer, + mod_timer(>vblank[crtc].disable_timer, jiffies + ((drm_vblank_offdelay * HZ)/1000)); } EXPORT_SYMBOL(drm_vblank_put); @@ -909,8 +913,6 @@ EXPORT_SYMBOL(drm_vblank_put); * drm_vblank_off - disable vblank events on a CRTC * @dev: DRM device * @crtc: CRTC in question - * - * Caller must hold event lock. */ void drm_vblank_off(struct drm_device *dev, int crtc) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 12f10bc2395f..9d982d483f12 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1024,14 +1024,17 @@ struct drm_pending_vblank_event { }; struct drm_vblank_crtc { + struct drm_device *dev; /* pointer to the drm_device */ wait_queue_head_t queue;/**< VBLANK wait queue */ struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */ + struct timer_list disable_timer;/* delayed disable timer */ atomic_t count; /**< number of VBLANK interrupts */ atomic_t refcount; /* number of users of vblank interruptsper crtc */ u32 last; /* protected by dev->vbl_lock, used */ /* for wraparound handling */ u32 last_wait; /* Last vblank seqno waited per CRTC */ unsigned int inmodeset; /* Display
[PATCH 01/12] drm: Use correct spinlock flavor in drm_vblank_get()
From: Peter HurleyThe irq flags state is already established by the outer spin_lock_irqsave(); re-disabling irqs is redundant. Signed-off-by: Peter Hurley Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 7583767ec619..ea20c4aa1b6b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -848,13 +848,13 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) */ int drm_vblank_get(struct drm_device *dev, int crtc) { - unsigned long irqflags, irqflags2; + unsigned long irqflags; int ret = 0; spin_lock_irqsave(>vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ if (atomic_add_return(1, >vblank[crtc].refcount) == 1) { - spin_lock_irqsave(>vblank_time_lock, irqflags2); + spin_lock(>vblank_time_lock); if (!dev->vblank[crtc].enabled) { /* Enable vblank irqs under vblank_time_lock protection. * All vblank count & timestamp updates are held off @@ -872,7 +872,7 @@ int drm_vblank_get(struct drm_device *dev, int crtc) drm_update_vblank_count(dev, crtc); } } - spin_unlock_irqrestore(>vblank_time_lock, irqflags2); + spin_unlock(>vblank_time_lock); } else { if (!dev->vblank[crtc].enabled) { atomic_dec(>vblank[crtc].refcount); -- 1.8.3.1
[PATCH 00/12] irq vblank handling rework
Hi all, This is Ville's vblank rework series, slightly pimped. I've added kerneldoc, some polish and also some additional nasty igt testcases for these crtc on/off vs vblank issues. Seems all to hold together nicely. Now one thing I wanted to do is roll this out across all drm drivers, but that looks ugly: Many drivers don't support vblanks really, and I couldn't fully audit whether they'd e.g. blow up when userspace tries to use the vblank wait ioctl. But I think we want to have more sanity since otherwise userspace is doomed to carry countless ugly hacks around forever. The last two patches are my attempt at that. By doing the drm_vblank_on/off dance in the crtc helpers after we know that the crtc is on/off we should have at least a somewhat sane baseline behaviour. Note that since drm_vblank_on/off are idempotent drivers are free to call these functions in their callback at an earlier time, where it makes more sense. But at least it's guaranteed to happen. Otoh drivers still need to manually complete pageflips, so this doesn't solve all the issues. But until we have a solid cross-driver testsuite for these corner-cases (all the interesting stuff happens when you race vblank waits against concurrent modesets, dpms, or system/runtime suspend/resume) we're pretty much guaranteed to have some that works at best occasionally and is guaranteed to have different behaviour in corner cases. Note that the patches won't degrade behaviour for existing drivers, the drm core changes simply allow us to finally fix things up correctly. I guess in a way this is a more generic discussion for the drm subsystem at large. Coments and review highly welcome. Cheers, Daniel Daniel Vetter (8): drm/i915: Remove drm_vblank_pre/post_modeset calls drm/doc: Discourage usage of MODESET_CTL ioctl drm/irq: kerneldoc polish drm/irq: Add kms-native crtc interface functions drm/i915: rip our vblank reset hacks for runtime PM drm/i915: Accurately initialize fifo underrun state on gmch platforms [RFC] drm/irq: More robustness in drm_vblank_on|off [RFC] drm/crtc-helper: Enforce sane vblank counter semantics Peter Hurley (1): drm: Use correct spinlock flavor in drm_vblank_get() Ville Syrj?l? (3): drm: Make the vblank disable timer per-crtc drm: Make blocking vblank wait return when the vblank interrupts get disabled drm: Add drm_vblank_on() Documentation/DocBook/drm.tmpl | 16 +- drivers/gpu/drm/drm_crtc_helper.c| 12 ++ drivers/gpu/drm/drm_irq.c| 377 ++- drivers/gpu/drm/i915/i915_irq.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 36 ++-- drivers/gpu/drm/i915/intel_drv.h | 2 - drivers/gpu/drm/i915/intel_pm.c | 40 include/drm/drmP.h | 10 +- 8 files changed, 341 insertions(+), 156 deletions(-) -- 1.8.3.1
[RFC PATCH 0/8] component helper improvements
On Sun, Apr 27, 2014 at 12:00:25AM +0100, Russell King - ARM Linux wrote: > A while back, Laurent raised some comments about the component helper, > which this patch set starts to address. > > The first point it addresses is the repeated parsing inefficiency when > deferred probing occurs. When DT is used, the structure of the > component helper today means that masters end up parsing the device > tree for each attempt to re-bind the driver. > > We remove this inefficiency by creating an array of matching data and > functions, which the component helper can use internally to match up > components to their master. > > The second point was the inefficiency of destroying the list of > components each time we saw a failure. We did this to ensure that > we kept things correctly ordered: component bind order matters. > As we have an array instead, the array is already ordered, so we > use this array to store the component pointers instead of a list, > and remember which are duplicates (and thus should be avoided.) > Avoiding the right duplicates matters as we walk the array in the > opposite direction at tear down. I've been looking at converting the Tegra DRM driver to the component helpers for a while now and had to make some changes to make it work for that particular use-case. While updating the imx-drm and msm DRM drivers for those changes I noticed an oddity. Both of the existing drivers use the following pattern: static int driver_component_bind(struct device *dev, struct device *master, void *data) { allocate memory request resources ... hook up to subsystem ... enable hardware } static const struct component_ops driver_component_ops = { .bind = driver_component_bind, }; static int driver_probe(struct platform_device *pdev) { return component_add(>dev, _component_ops); } While converting Tegra DRM, what I intuitively did (I didn't actually look at the other drivers for inspiration) was something more along the lines of the following: static int driver_component_bind(struct device *dev, struct device *master, void *data) { hook up to subsystem ... enable hardware } static const struct component_ops driver_component_ops = { .bind = driver_component_bind, }; static int driver_probe(struct platform_device *pdev) { allocate memory request resources ... return component_add(>dev, _component_ops); } Since usually deferred probing is caused by resource allocations failing this has the side-effect of handling deferred probing before the master device is even bound (the component_add() happens as the very last step) and therefore there is less risk for component_bind_all() to fail. I've actually never seen it fail at all. Failure at that point is almost certainly irrecoverable anyway. It would seem to me that if other drivers followed the same pattern, the second point above is solved by moving deferred probe handling one level up and reduce the work of the component helpers to gluing together the components on a subsystem level. Another advantage to that pattern is that probe failure happens on a much more granular level. It's handled by each component device rather than all at once when the master is bound. By that time all components will be ready and the heavy work of building the subsystem device will usually not have to be undone as opposed to the former pattern where that process is bound to be interrupted possibly many times be deferred probing. But perhaps I'm missing something. Was there another reason for choosing this particular pattern? Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140514/2cd86462/attachment-0001.sig>
[PULL] topic/core-stuff
On Mon, May 5, 2014 at 11:19 AM, Daniel Vetter wrote: > Hi Dave, > > Update pull request with drm core patches. Mostly some polish for the > primary plane stuff and a pile of patches all over from Thierry. Has > survived a few days in drm-intel-nightly without causing ill. > > I've frobbed my scripts a bit to also tag my topic branches so that you > have something stable to pull - I've accidentally pushed a bunch more > patches onto this branch before you've taken the old pull request. Ping. -Daniel > > Cheers, Daniel > > > The following changes since commit a798c10faf62a505d24e5f6213fbaf904a39623f: > > Linux 3.15-rc2 (2014-04-20 11:08:50 -0700) > > are available in the git repository at: > > git://anongit.freedesktop.org/drm-intel tags/topic/core-stuff-2014-05-05 > > for you to fetch changes up to a74591d781a8e445e8d5aec8a8bb9ec43a31138b: > > drm: Make drm_crtc_helper_disable() return void (2014-04-29 12:34:33 +0200) > > > Andrzej Hajda (1): > drm: make mode_valid callback optional > > Daniel Vetter (4): > drm/plane_helper: don't disable plane in destroy function > drm/crtc-helper: gc usless connector loop in disable_unused_functions > drm: Simplify fb refcounting rules around ->update_plane > drm: Handle ->disable_plane failures correctly > > Ilija Hadzic (1): > drm: remove unused argument from drm_open_helper > > Matt Roper (1): > drm/plane-helper: Fix primary plane scaling check > > Thierry Reding (8): > drm: Try to acquire modeset lock on panic or sysrq > drm/edid: Drop revision argument for drm_mode_std() > drm/edid: Cleanup kerneldoc > drm/fb: Fix typos > drm: Fixup flip-work kerneldoc > drm/dp: Fix typo in comment > drm: Fix indentation of closing brace > drm: Make drm_crtc_helper_disable() return void > > Vandana Kannan (1): > drm/edid: Fill PAR in AVI infoframe based on CEA mode list > > Documentation/DocBook/drm.tmpl | 6 +- > drivers/gpu/drm/ast/ast_mode.c | 7 -- > drivers/gpu/drm/bridge/ptn3460.c | 7 -- > drivers/gpu/drm/cirrus/cirrus_mode.c | 8 -- > drivers/gpu/drm/drm_bufs.c | 2 +- > drivers/gpu/drm/drm_crtc.c | 27 +++-- > drivers/gpu/drm/drm_crtc_helper.c | 13 +-- > drivers/gpu/drm/drm_dp_helper.c| 2 +- > drivers/gpu/drm/drm_edid.c | 161 > +++-- > drivers/gpu/drm/drm_fb_helper.c| 17 ++- > drivers/gpu/drm/drm_fops.c | 9 +- > drivers/gpu/drm/drm_plane_helper.c | 13 +-- > drivers/gpu/drm/drm_probe_helper.c | 2 +- > drivers/gpu/drm/exynos/exynos_dp_core.c| 7 -- > drivers/gpu/drm/exynos/exynos_drm_dpi.c| 7 -- > drivers/gpu/drm/exynos/exynos_drm_vidi.c | 7 -- > drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 7 -- > drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 7 -- > drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 7 -- > drivers/staging/imx-drm/imx-drm-core.c | 7 -- > drivers/staging/imx-drm/imx-drm.h | 2 - > drivers/staging/imx-drm/imx-hdmi.c | 1 - > drivers/staging/imx-drm/imx-ldb.c | 1 - > drivers/staging/imx-drm/imx-tve.c | 4 - > drivers/staging/imx-drm/parallel-display.c | 1 - > include/drm/drm_crtc.h | 1 + > include/drm/drm_crtc_helper.h | 2 +- > include/drm/drm_flip_work.h| 1 + > 28 files changed, 153 insertions(+), 183 deletions(-) > > -- > 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
[RFC PATCH 0/2] drm: make drm_get_{connector, encoder}_name thread safe
On Wed, 14 May 2014, Chris Wilson wrote: > On Wed, May 14, 2014 at 04:58:18PM +0300, Jani Nikula wrote: >> Hi all - >> >> This series stores connector/encoder names in the relevant structs to >> make the name getters thread safe. >> >> What say you, is the wasted memory too high a price to pay for the >> thread safety and implementation simplicity of this approach? I think >> making drm_get_connector_name and drm_get_encoder_name return allocated >> buffers makes a lot of code really ugly and error prone. > > I thought we could use dev_set_name(connector->kdev, "foo"). Hmm, connector->kdev is created at drm_sysfs_connector_add(), and it uses a drm_get_connector_name() prefixed with "cardN-". So there's the naming difference and the lifetime difference, and additionally encoder doesn't have anything similar. Unless I'm missing something, what I'm suggesting is way simpler. BR, Jani. > -Chris > > -- > Chris Wilson, Intel Open Source Technology Centre -- Jani Nikula, Intel Open Source Technology Center
[PATCH] imx-drm: imx-hdmi: move memory and resource allocation into probe function
Philipp, On Wed, May 14, 2014 at 6:24 PM, Philipp Zabel wrote: > Move memory allocation and resource acquisition from the bind function into > the probe function. This calls the devres managed functions once instead of > possibly multiple times in the bind function and avoids leaking memory (as > long as the hdmi platform device stays bound). > > While at it, request the irq only after the interrupt handler mutes are > set up, to avoid spurious interrupts. > > Signed-off-by: Philipp Zabel This one does not apply against the latest version from linux-next.
[Intel-gfx] Design review request: DRM color manager
On Tue, May 13, 2014 at 09:18:45AM +0530, Sharma, Shashank wrote: > Daniel, > Please find my comments inline. > > Regards > Shashank > On 5/12/2014 8:58 PM, Daniel Vetter wrote: > >On Mon, May 12, 2014 at 05:35:13PM +0530, Sharma, Shashank wrote: > >>Thanks for your time and the comments David. > >>please find mine inline. > >> > >>Regards > >>Shashank > >>On 5/12/2014 5:20 PM, David Herrmann wrote: > >>>Hi > >>> > >>>On Mon, May 12, 2014 at 12:26 PM, Sharma, Shashank > >>> wrote: > >Gamma correction lut is already supported. For the other stuff we can use > >SET_BLOB (or fix it if it doesn't work). > > > Current gamma correction supports only 8 bit mode, which cant do a real > gamma correction. This is only to initialize the LUT. Actual gamma > correction needs 10 bit support. > > As discussed in design, the idea is same, ie to fix (implement) SET_BLOB. > But see some of the requirements on LUT size of VLV: > > 1. Gamma correction: 256 values > 2. CSC : 9 values in form of 6 register > 3. Hue : 1 value (Plane level) > 4. Saturation: 1 value (Plane level) > 5. Contrast: 1 value (Plane level) > 6. Brightness: 1 value (Plane level) > > For CHV, the requirement is again different. > There are different values, which vary from platform to platform and > property-by-property. > Now, one method of supporting these values is create a DRM property for > each, some blob, some single valued, set individual interface and set them > all at random. IMHO, this looks the non-systematic way of doing it. That's exactly what atomic modeset/pageflip is meant to address. You get the flexibility of individual properties and on top of that a way to apply them all atomically. > The same thing has to be done differently for different platfroms, with some > new color corrections added, some removed, and some no of coefficients > changed. I can clearly see a requirement here. Having them separated into individual properties will make it easy for userspace to determine at runtime which of them are available and which aren't. Also it seems to me that all of these properties should have a unified userspace interface. Drivers would then be free to implement the kernel side with the hardware-specific details. > >>AFAIK color management is not a part of atomic modeset, but once we create > >>such an interface, it would be really easy to club that in the atomic > >>modeset. > > > >See above, this is a reason to _not_ add a separate color manager. > >-Daniel > > > As I mentioned above, color manager is designed to be clubbed with atomic > modeset, and will not be any blockage there. I think the point here is that once we have atomic modesetting/pageflip then there's no longer a need to have an "atomic" color manager property since there will be a mechanism to atomically apply any number of properties. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140514/e728469c/attachment.sig>
[RFC PATCH v1 08/16] drm/radeon: use common fence implementation for fences
> + /* did fence get signaled after we enabled the sw irq? */ > + if (atomic64_read(>rdev->fence_drv[fence->ring].last_seq) >= > fence->seq) { > + radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring); > + return false; > + } > + > + fence->fence_wake.flags = 0; > + fence->fence_wake.private = NULL; > + fence->fence_wake.func = radeon_fence_check_signaled; > + __add_wait_queue(>rdev->fence_queue, >fence_wake); > + fence_get(f); That looks like a race condition to me. The fence needs to be added to the wait queue before the check, not after. Apart from that the whole approach looks like a really bad idea to me. How for example is lockup detection supposed to happen with this? Christian. Am 14.05.2014 16:58, schrieb Maarten Lankhorst: > Signed-off-by: Maarten Lankhorst > --- > drivers/gpu/drm/radeon/radeon.h| 15 +-- > drivers/gpu/drm/radeon/radeon_device.c |1 > drivers/gpu/drm/radeon/radeon_fence.c | 189 > +--- > 3 files changed, 153 insertions(+), 52 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h > index 68528619834a..a7d839a158ae 100644 > --- a/drivers/gpu/drm/radeon/radeon.h > +++ b/drivers/gpu/drm/radeon/radeon.h > @@ -64,6 +64,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -113,9 +114,6 @@ extern int radeon_hard_reset; > #define RADEONFB_CONN_LIMIT 4 > #define RADEON_BIOS_NUM_SCRATCH 8 > > -/* fence seq are set to this number when signaled */ > -#define RADEON_FENCE_SIGNALED_SEQ0LL > - > /* internal ring indices */ > /* r1xx+ has gfx CP ring */ > #define RADEON_RING_TYPE_GFX_INDEX 0 > @@ -347,12 +345,15 @@ struct radeon_fence_driver { > }; > > struct radeon_fence { > + struct fence base; > + > struct radeon_device*rdev; > - struct kref kref; > /* protected by radeon_fence.lock */ > uint64_tseq; > /* RB, DMA, etc. */ > unsignedring; > + > + wait_queue_t fence_wake; > }; > > int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); > @@ -2256,6 +2257,7 @@ struct radeon_device { > struct radeon_mman mman; > struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; > wait_queue_head_t fence_queue; > + unsignedfence_context; > struct mutexring_lock; > struct radeon_ring ring[RADEON_NUM_RINGS]; > boolib_pool_ready; > @@ -2346,11 +2348,6 @@ u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 > index); > void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v); > > /* > - * Cast helper > - */ > -#define to_radeon_fence(p) ((struct radeon_fence *)(p)) > - > -/* >* Registers read & write functions. >*/ > #define RREG8(reg) readb((rdev->rmmio) + (reg)) > diff --git a/drivers/gpu/drm/radeon/radeon_device.c > b/drivers/gpu/drm/radeon/radeon_device.c > index 0e770bbf7e29..501d0cf9eb8b 100644 > --- a/drivers/gpu/drm/radeon/radeon_device.c > +++ b/drivers/gpu/drm/radeon/radeon_device.c > @@ -1175,6 +1175,7 @@ int radeon_device_init(struct radeon_device *rdev, > for (i = 0; i < RADEON_NUM_RINGS; i++) { > rdev->ring[i].idx = i; > } > + rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS); > > DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X > 0x%04X:0x%04X).\n", > radeon_family_name[rdev->family], pdev->vendor, pdev->device, > diff --git a/drivers/gpu/drm/radeon/radeon_fence.c > b/drivers/gpu/drm/radeon/radeon_fence.c > index a77b1c13ea43..bc844f300d3f 100644 > --- a/drivers/gpu/drm/radeon/radeon_fence.c > +++ b/drivers/gpu/drm/radeon/radeon_fence.c > @@ -39,6 +39,15 @@ > #include "radeon.h" > #include "radeon_trace.h" > > +static const struct fence_ops radeon_fence_ops; > + > +#define to_radeon_fence(p) \ > + ({ \ > + struct radeon_fence *__f; \ > + __f = container_of((p), struct radeon_fence, base); \ > + __f->base.ops == _fence_ops ? __f : NULL;\ > + }) > + > /* >* Fences >* Fences mark an event in the GPUs pipeline and are used > @@ -111,30 +120,55 @@ int radeon_fence_emit(struct radeon_device *rdev, > struct radeon_fence **fence, > int ring) > { > + u64 seq = ++rdev->fence_drv[ring].sync_seq[ring]; > + > /* we are protected by the ring emission mutex */ > *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); > if ((*fence) == NULL) { > return -ENOMEM; > } > -
[PATCH v2 4/7] drivers/base: Add interface framework
On Wed, May 14, 2014 at 04:34:21PM +0200, Daniel Vetter wrote: > On Tue, May 13, 2014 at 11:31:07PM +0200, Thierry Reding wrote: > > A different solution, which seems to be fairly common for DRM drivers > > for SoCs, is to instantiate a dummy device so that the DRM driver can > > bind to it. This can happen in two forms: add the dummy device directly > > in device tree (which goes against pretty much everything that's been > > preached about device tree in the past) or the dummy device can be > > instantiated in code, which is what the current Tegra DRM/host1x driver > > does. > > Actually the dummy device seems to be an acceptable solution and iirc was > even acked by DT maintainers in the last KS. I'm not on top of things, but > iirc the thinking was that a dummy device which just pulls in all the > relevant real bits with phandles is justified in the board file since it > tells you how the board is intended to be used. The justification was that > on SoCs where assigning stuff between v4l and drm is really flexible (e.g. > on omap or so where you can assign the display pipes essentially freely) > the use-case of the board is what matters, and that's a somewhat physical > property of it (i.e. in what kind of device it's sitting.) I disagree. If there's a way to derive all that information within the driver (like we do for Tegra) then there should be no need to add redundant content to the device tree. Also note that Tegra DRM and its device tree binding predate the last KS, and prior to that the gospel was to *not* add this kind of data to the device tree. Hence I was forced to spend a *lot* of time working out a solution in the driver. Therefore I hope it's understandable that I don't take well to being told to just go use a bloody dummy device. > So in your case you'd have a fake display and a fake video device which > pulls everything the drm/v4l driver need together. So if the issue is how > to get at a master device I think that's simple to solve. But that's completely redundant. The driver is perfectly capable of determining what devices belong to a DRM device and which should be part of a V4L2 device. Fake devices are only workarounds for a problem that we currently have no better solution for in the kernel. And as a matter of fact we already do create a dummy device (albeit in the kernel rather than in device tree) on Tegra. But I consider that suboptimal, hence why I want to find a better way to do this. This interface framework is the result. If people don't see a need to fix this then I'll just stick with what I currently have, since it isn't any worse than what everybody else is doing. > If the issue otoh is how the various drivers can get at the bus-like > services host1x exposes, then I think a real bus driver makes a lot more > sense. And Greg seems to have ideas about that already. There aren't really any bus-like services exposed by host1x. It really just exposes resources such as DMA channels or syncpoints. But that's not even a problem because we know that host1x children are always, well, children of host1x and therefore we can simply get access to host1x via the parent device. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140514/2c2e9e59/attachment.sig>
[PATCH] drm/exynos: Make exynos_drm_init() call late during the bootup
exynos_drm_init() does probing of various drivers like dp_panel, hdmi, fimd, mixer, etc in an order and finally binds them together. Some of the drm devices (Eg: dp_panel) try to do regulator_get() and enable few supplies during their probe. Chances are that, these devices may get probed before the respective supply/PMIC is hooked. In such cases, dp_panel would continue with "dummy regulator". Which is not what the system wants. Lets give the core connectivity and regulators modules some time to hookup the supplies before Exynos DRM devices comes into picture. Signed-off-by: Naveen Krishna Chatradhi --- This change is proposed after 1. Discussing with I2C/SPI & DMA subsystem maintainers and Others @ https://lkml.org/lkml/2014/5/9/333 Trying to change the I2C, SPI and DMA drivers as subsys_initcall() Which was strictly opposed, as a flaw was found in DRM subsystem. 2. -EPROBE_DEFER won't work well with the current sequency of platform_driver_register()s in exynos_drm_init() 3. bridge_panel mechanism is under RFC and no conclusions were drawn yet. We should be able to probe each DRM device independently and let PROBE_DEFER take care of dependencies. But, this could cause lot of bootup time. late_initcall() of DRM works well and fixes all the above issues for now. Kindly suggest, if an alternative/better mechanism is out there. Thanks, drivers/gpu/drm/exynos/exynos_drm_drv.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 4cef88f..78c185a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -692,7 +692,7 @@ static void exynos_drm_exit(void) platform_driver_unregister(_drm_platform_driver); } -module_init(exynos_drm_init); +late_initcall(exynos_drm_init); module_exit(exynos_drm_exit); MODULE_AUTHOR("Inki Dae "); -- 1.7.9.5
[PATCH 4/5] drm/radeon: rework page flip handling
On 05.05.2014 18:27, Michel D?nzer wrote: > On 02.05.2014 22:29, Christian K?nig wrote: >> Am 02.05.2014 09:25, schrieb Michel D?nzer: >>> >>> and asynchronous flips (not synchronized to vertical blank). >> Actually that's one of the things I've implement in 3.15 by using the >> pflip interrupt. All you need to do is to set the appropriate bits in >> the hardware to sync the flip to VBLANK, HBLANK or not at all. For the >> pflip interrupt that doesn't matter it should just fire as soon as the >> new base address is used by the hardware. > > Sounds great. :) Then we just need to expose that to userspace somehow. Actually, looks like that should be quite simple: git grep -i async_page_flip -- Earthling Michel D?nzer| http://www.amd.com Libre software enthusiast |Mesa and X developer
[RFC PATCH v1 16/16] drm/ttm: use rcu in core ttm
Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/ttm/ttm_bo.c | 76 +++--- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 31c4a6dd722d..6fe1f4bf37ed 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -466,66 +466,6 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) ((HZ / 100) < 1) ? 1 : HZ / 100); } -static int ttm_bo_unreserve_and_wait(struct ttm_buffer_object *bo, -bool interruptible) -{ - struct ttm_bo_global *glob = bo->glob; - struct reservation_object_list *fobj; - struct fence *excl = NULL; - struct fence **shared = NULL; - u32 shared_count = 0, i; - int ret = 0; - - fobj = reservation_object_get_list(bo->resv); - if (fobj && fobj->shared_count) { - shared = kmalloc(sizeof(*shared) * fobj->shared_count, -GFP_KERNEL); - - if (!shared) { - ret = -ENOMEM; - __ttm_bo_unreserve(bo); - spin_unlock(>lru_lock); - return ret; - } - - for (i = 0; i < fobj->shared_count; ++i) { - if (!fence_is_signaled(fobj->shared[i])) { - fence_get(fobj->shared[i]); - shared[shared_count++] = fobj->shared[i]; - } - } - if (!shared_count) { - kfree(shared); - shared = NULL; - } - } - - excl = reservation_object_get_excl(bo->resv); - if (excl && !fence_is_signaled(excl)) - fence_get(excl); - else - excl = NULL; - - __ttm_bo_unreserve(bo); - spin_unlock(>lru_lock); - - if (excl) { - ret = fence_wait(excl, interruptible); - fence_put(excl); - } - - if (shared_count > 0) { - for (i = 0; i < shared_count; ++i) { - if (!ret) - ret = fence_wait(shared[i], interruptible); - fence_put(shared[i]); - } - kfree(shared); - } - - return ret; -} - /** * function ttm_bo_cleanup_refs_and_unlock * If bo idle, remove from delayed- and lru lists, and unref. @@ -549,9 +489,19 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, ret = ttm_bo_wait(bo, false, false, true); if (ret && !no_wait_gpu) { - ret = ttm_bo_unreserve_and_wait(bo, interruptible); - if (ret) - return ret; + long lret; + ww_mutex_unlock(>resv->lock); + spin_unlock(>lru_lock); + + lret = reservation_object_wait_timeout_rcu(bo->resv, + true, + interruptible, + 30 * HZ); + + if (lret < 0) + return lret; + else if (lret == 0) + return -EBUSY; spin_lock(>lru_lock); ret = __ttm_bo_reserve(bo, false, true, false, 0);
[RFC PATCH v1 15/16] drm/vmwgfx: use rcu in vmw_user_dmabuf_synccpu_grab
Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 20a1a866ceeb..79e950df3018 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -567,13 +567,16 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, int ret; if (flags & drm_vmw_synccpu_allow_cs) { - ret = ttm_bo_reserve(bo, true, !!(flags & drm_vmw_synccpu_dontblock), false, 0); - if (!ret) { - ret = ttm_bo_wait(bo, false, true, - !!(flags & drm_vmw_synccpu_dontblock)); - ttm_bo_unreserve(bo); - } - return ret; + long lret; + if (flags & drm_vmw_synccpu_dontblock) + return reservation_object_test_signaled_rcu(bo->resv, true) ? 0 : -EBUSY; + + lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, MAX_SCHEDULE_TIMEOUT); + if (!lret) + return -EBUSY; + else if (lret < 0) + return lret; + return 0; } ret = ttm_bo_synccpu_write_grab
[RFC PATCH v1 14/16] drm/radeon: use rcu waits in some ioctls
Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/radeon/radeon_gem.c | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index d09650c1d720..7ba883843668 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -107,9 +107,12 @@ static int radeon_gem_set_domain(struct drm_gem_object *gobj, } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ - r = radeon_bo_wait(robj, NULL, false); - if (r) { - printk(KERN_ERR "Failed to wait for object !\n"); + r = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ); + if (!r) + r = -EBUSY; + + if (r < 0 && r != -EINTR) { + printk(KERN_ERR "Failed to wait for object: %i\n", r); return r; } } @@ -357,14 +360,20 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_radeon_gem_wait_idle *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; - int r; + int r = 0; + long ret; gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { return -ENOENT; } robj = gem_to_radeon_bo(gobj); - r = radeon_bo_wait(robj, NULL, false); + ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ); + if (ret == 0) + r = -EBUSY; + else if (ret < 0) + r = ret; + /* callback hw specific functions if any */ if (rdev->asic->ioctl_wait_idle) robj->rdev->asic->ioctl_wait_idle(rdev, robj);
[RFC PATCH v1 13/16] drm/nouveau: use rcu in nouveau_gem_ioctl_cpu_prep
With the conversion to the reservation api this should be safe. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/nouveau/nouveau_gem.c | 28 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 4beaa897adad..c2ca894f6507 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -863,33 +863,29 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, struct drm_gem_object *gem; struct nouveau_bo *nvbo; bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); + bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE); int ret; - struct nouveau_fence *fence = NULL; gem = drm_gem_object_lookup(dev, file_priv, req->handle); if (!gem) return -ENOENT; nvbo = nouveau_gem_object(gem); - ret = ttm_bo_reserve(>bo, true, false, false, 0); - if (!ret) { - ret = ttm_bo_wait(>bo, true, true, true); - if (!no_wait && ret) { - struct fence *excl; - - excl = reservation_object_get_excl(nvbo->bo.resv); - fence = nouveau_fence_ref((struct nouveau_fence *)excl); - } + if (no_wait) + ret = reservation_object_test_signaled_rcu(nvbo->bo.resv, write) ? 0 : -EBUSY; + else { + long lret; - ttm_bo_unreserve(>bo); + lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, 30 * HZ); + if (!lret) + ret = -EBUSY; + else if (lret > 0) + ret = 0; + else + ret = lret; } drm_gem_object_unreference_unlocked(gem); - if (fence) { - ret = nouveau_fence_wait(fence, true, no_wait); - nouveau_fence_unref(); - } - return ret; }
[RFC PATCH v1 12/16] drm/ttm: flip the switch, and convert to dma_fence
--- drivers/gpu/drm/nouveau/nouveau_bo.c | 48 +--- drivers/gpu/drm/nouveau/nouveau_fence.c | 24 +--- drivers/gpu/drm/nouveau/nouveau_fence.h |2 drivers/gpu/drm/nouveau/nouveau_gem.c| 16 ++- drivers/gpu/drm/qxl/qxl_debugfs.c|6 + drivers/gpu/drm/qxl/qxl_drv.h|2 drivers/gpu/drm/qxl/qxl_kms.c|1 drivers/gpu/drm/qxl/qxl_object.h |4 - drivers/gpu/drm/qxl/qxl_release.c|3 - drivers/gpu/drm/qxl/qxl_ttm.c| 104 -- drivers/gpu/drm/radeon/radeon_cs.c | 10 +- drivers/gpu/drm/radeon/radeon_display.c | 18 +++ drivers/gpu/drm/radeon/radeon_object.c |4 - drivers/gpu/drm/radeon/radeon_ttm.c | 34 -- drivers/gpu/drm/radeon/radeon_uvd.c |8 + drivers/gpu/drm/radeon/radeon_vm.c |2 drivers/gpu/drm/ttm/ttm_bo.c | 171 +- drivers/gpu/drm/ttm/ttm_bo_util.c| 23 +--- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 10 -- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 40 --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14 +- include/drm/ttm/ttm_bo_api.h |2 include/drm/ttm/ttm_bo_driver.h | 26 - include/drm/ttm/ttm_execbuf_util.h | 10 +- 24 files changed, 197 insertions(+), 385 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 84aba3fa1bd0..5b8ccc39a282 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -92,13 +92,13 @@ nv10_bo_get_tile_region(struct drm_device *dev, int i) static void nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, - struct nouveau_fence *fence) + struct fence *fence) { struct nouveau_drm *drm = nouveau_drm(dev); if (tile) { spin_lock(>tile.lock); - tile->fence = nouveau_fence_ref(fence); + tile->fence = nouveau_fence_ref((struct nouveau_fence *)fence); tile->used = false; spin_unlock(>tile.lock); } @@ -965,7 +965,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, if (ret == 0) { ret = nouveau_fence_new(chan, false, ); if (ret == 0) { - ret = ttm_bo_move_accel_cleanup(bo, fence, + ret = ttm_bo_move_accel_cleanup(bo, + >base, evict, no_wait_gpu, new_mem); @@ -1151,8 +1152,9 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; + struct fence *fence = reservation_object_get_excl(bo->resv); - nv10_bo_put_tile_region(dev, *old_tile, bo->sync_obj); + nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; } @@ -1423,47 +1425,14 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) ttm_pool_unpopulate(ttm); } -static void -nouveau_bo_fence_unref(void **sync_obj) -{ - nouveau_fence_unref((struct nouveau_fence **)sync_obj); -} - void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) { struct reservation_object *resv = nvbo->bo.resv; - nouveau_bo_fence_unref(>bo.sync_obj); - nvbo->bo.sync_obj = nouveau_fence_ref(fence); - reservation_object_add_excl_fence(resv, >base); } -static void * -nouveau_bo_fence_ref(void *sync_obj) -{ - return nouveau_fence_ref(sync_obj); -} - -static bool -nouveau_bo_fence_signalled(void *sync_obj) -{ - return nouveau_fence_done(sync_obj); -} - -static int -nouveau_bo_fence_wait(void *sync_obj, bool lazy, bool intr) -{ - return nouveau_fence_wait(sync_obj, lazy, intr); -} - -static int -nouveau_bo_fence_flush(void *sync_obj) -{ - return 0; -} - struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = _ttm_tt_create, .ttm_tt_populate = _ttm_tt_populate, @@ -1474,11 +1443,6 @@ struct ttm_bo_driver nouveau_bo_driver = { .move_notify = nouveau_bo_move_ntfy, .move = nouveau_bo_move, .verify_access = nouveau_bo_verify_access, - .sync_obj_signaled = nouveau_bo_fence_signalled, - .sync_obj_wait = nouveau_bo_fence_wait, - .sync_obj_flush = nouveau_bo_fence_flush, - .sync_obj_unref = nouveau_bo_fence_unref, - .sync_obj_ref = nouveau_bo_fence_ref, .fault_reserve_notify = _ttm_fault_reserve_notify, .io_mem_reserve = _ttm_io_mem_reserve, .io_mem_free = _ttm_io_mem_free, diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c
[RFC PATCH v1 11/16] drm/vmwgfx: rework to new fence interface
Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |2 drivers/gpu/drm/vmwgfx/vmwgfx_fence.c| 299 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fence.h| 29 ++- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |9 - 4 files changed, 200 insertions(+), 139 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index db30b790ad24..f3f8caa09cc8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2360,7 +2360,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, BUG_ON(fence == NULL); fence_rep.handle = fence_handle; - fence_rep.seqno = fence->seqno; + fence_rep.seqno = fence->base.seqno; vmw_update_seqno(dev_priv, _priv->fifo); fence_rep.passed_seqno = dev_priv->last_read_seqno; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 05b9eea8e875..5d595ca5d82a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -46,6 +46,7 @@ struct vmw_fence_manager { bool goal_irq_on; /* Protected by @goal_irq_mutex */ bool seqno_valid; /* Protected by @lock, and may not be set to true without the @goal_irq_mutex held. */ + unsigned ctx; }; struct vmw_user_fence { @@ -80,6 +81,12 @@ struct vmw_event_fence_action { uint32_t *tv_usec; }; +static struct vmw_fence_manager * +fman_from_fence(struct vmw_fence_obj *fence) +{ + return container_of(fence->base.lock, struct vmw_fence_manager, lock); +} + /** * Note on fencing subsystem usage of irqs: * Typically the vmw_fences_update function is called @@ -102,25 +109,130 @@ struct vmw_event_fence_action { * objects with actions attached to them. */ -static void vmw_fence_obj_destroy_locked(struct kref *kref) +static void vmw_fence_obj_destroy(struct fence *f) { struct vmw_fence_obj *fence = - container_of(kref, struct vmw_fence_obj, kref); + container_of(f, struct vmw_fence_obj, base); - struct vmw_fence_manager *fman = fence->fman; - unsigned int num_fences; + struct vmw_fence_manager *fman = fman_from_fence(fence); + unsigned long irq_flags; + spin_lock_irqsave(>lock, irq_flags); list_del_init(>head); - num_fences = --fman->num_fence_objects; - spin_unlock_irq(>lock); - if (fence->destroy) - fence->destroy(fence); - else - kfree(fence); + --fman->num_fence_objects; + spin_unlock_irqrestore(>lock, irq_flags); + fence->destroy(fence); +} - spin_lock_irq(>lock); +static const char *vmw_fence_get_driver_name(struct fence *f) +{ + return "vmwgfx"; +} + +static const char *vmw_fence_get_timeline_name(struct fence *f) +{ + return "svga"; +} + +static bool vmw_fence_enable_signaling(struct fence *f) +{ + struct vmw_fence_obj *fence = + container_of(f, struct vmw_fence_obj, base); + + struct vmw_fence_manager *fman = fman_from_fence(fence); + + __le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt; + u32 seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); + if (seqno - fence->base.seqno < VMW_FENCE_WRAP) + return false; + + vmw_fifo_ping_host(fman->dev_priv, SVGA_SYNC_GENERIC); + + return true; +} + +struct vmwgfx_wait_cb { + struct fence_cb base; + struct task_struct *task; +}; + +static void +vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb) +{ + struct vmwgfx_wait_cb *wait = + container_of(cb, struct vmwgfx_wait_cb, base); + + wake_up_state(wait->task, TASK_NORMAL); } +static void __vmw_fences_update(struct vmw_fence_manager *fman); + +static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout) +{ + struct vmw_fence_obj *fence = + container_of(f, struct vmw_fence_obj, base); + + struct vmw_fence_manager *fman = fman_from_fence(fence); + struct vmw_private *dev_priv = fman->dev_priv; + struct vmwgfx_wait_cb cb; + long ret = timeout; + unsigned long irq_flags; + + if (likely(vmw_fence_obj_signaled(fence))) + return timeout; + + vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); + vmw_seqno_waiter_add(dev_priv); + + spin_lock_irqsave(f->lock, irq_flags); + + if (intr && signal_pending(current)) { + ret = -ERESTARTSYS; + goto out; + } + + cb.base.func = vmwgfx_wait_cb; + cb.task = current; + list_add(, >cb_list); + + while (ret > 0) { + __vmw_fences_update(fman); + if (test_bit(FENCE_FLAG_SIGNALED_BIT, >flags)) + break; + + if (intr) +
[RFC PATCH v1 10/16] drm/vmwgfx: get rid of different types of fence_flags entirely
Only one type was ever used. This is needed to simplify the fence support in the next commit. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c |5 +-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |1 - drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 14 ++--- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 50 --- drivers/gpu/drm/vmwgfx/vmwgfx_fence.h |8 + 5 files changed, 26 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 4a36bb1dc525..f15718cc631d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -792,15 +792,12 @@ static int vmw_sync_obj_flush(void *sync_obj) static bool vmw_sync_obj_signaled(void *sync_obj) { - return vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj, - DRM_VMW_FENCE_FLAG_EXEC); - + return vmw_fence_obj_signaled((struct vmw_fence_obj *) sync_obj); } static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible) { return vmw_fence_obj_wait((struct vmw_fence_obj *) sync_obj, - DRM_VMW_FENCE_FLAG_EXEC, lazy, interruptible, VMW_FENCE_WAIT_TIMEOUT); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 6b252a887ae2..f217e9723b9e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -332,7 +332,6 @@ struct vmw_sw_context{ uint32_t *cmd_bounce; uint32_t cmd_bounce_size; struct list_head resource_list; - uint32_t fence_flags; struct ttm_buffer_object *cur_query_bo; struct list_head res_relocations; uint32_t *buf_start; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index f8b25bc4e634..db30b790ad24 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -350,8 +350,6 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, vval_buf->validate_as_mob = validate_as_mob; } - sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC; - if (p_val_node) *p_val_node = val_node; @@ -2308,13 +2306,9 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, if (p_handle != NULL) ret = vmw_user_fence_create(file_priv, dev_priv->fman, - sequence, - DRM_VMW_FENCE_FLAG_EXEC, - p_fence, p_handle); + sequence, p_fence, p_handle); else - ret = vmw_fence_create(dev_priv->fman, sequence, - DRM_VMW_FENCE_FLAG_EXEC, - p_fence); + ret = vmw_fence_create(dev_priv->fman, sequence, p_fence); if (unlikely(ret != 0 && !synced)) { (void) vmw_fallback_wait(dev_priv, false, false, @@ -2387,8 +2381,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle, TTM_REF_USAGE); DRM_ERROR("Fence copy error. Syncing.\n"); - (void) vmw_fence_obj_wait(fence, fence->signal_mask, - false, false, + (void) vmw_fence_obj_wait(fence, false, false, VMW_FENCE_WAIT_TIMEOUT); } } @@ -2438,7 +2431,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, sw_context->fp = vmw_fpriv(file_priv); sw_context->cur_reloc = 0; sw_context->cur_val_buf = 0; - sw_context->fence_flags = 0; INIT_LIST_HEAD(_context->resource_list); sw_context->cur_query_bo = dev_priv->pinned_bo; sw_context->last_query_ctx = NULL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 436b013b4231..05b9eea8e875 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -207,9 +207,7 @@ void vmw_fence_manager_takedown(struct vmw_fence_manager *fman) } static int vmw_fence_obj_init(struct vmw_fence_manager *fman, - struct vmw_fence_obj *fence, - u32 seqno, - uint32_t mask, + struct vmw_fence_obj *fence, u32 seqno, void (*destroy) (struct vmw_fence_obj *fence)) { unsigned long irq_flags; @@ -220,7 +218,6 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, INIT_LIST_HEAD(>seq_passed_actions); fence->fman = fman;
[RFC PATCH 2/2] drm: store encoder name in encoder struct
This makes drm_get_encoder_name() thread safe. Reference: http://lkml.kernel.org/r/645ee6e22cad47d38a2b35c21c8d5fe3 at DC1-MBX-01\ .ptsecurity.ru Signed-off-by: Jani Nikula --- drivers/gpu/drm/drm_crtc.c | 31 +-- include/drm/drm_crtc.h | 2 ++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5781130b4126..1c4cb74ede77 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -257,21 +257,11 @@ void drm_connector_ida_destroy(void) /** * drm_get_encoder_name - return a string for encoder - * @encoder: encoder to compute name of - * - * Note that the buffer used by this function is globally shared and owned by - * the function itself. - * - * FIXME: This isn't really multithreading safe. + * @encoder: the encoder to get name for */ const char *drm_get_encoder_name(const struct drm_encoder *encoder) { - static char buf[32]; - - snprintf(buf, 32, "%s-%d", -drm_encoder_enum_list[encoder->encoder_type].name, -encoder->base.id); - return buf; + return encoder->name; } EXPORT_SYMBOL(drm_get_encoder_name); @@ -986,16 +976,27 @@ int drm_encoder_init(struct drm_device *dev, ret = drm_mode_object_get(dev, >base, DRM_MODE_OBJECT_ENCODER); if (ret) - goto out; + goto out_unlock; encoder->dev = dev; encoder->encoder_type = encoder_type; encoder->funcs = funcs; + encoder->name = kasprintf(GFP_KERNEL, "%s-%d", + drm_encoder_enum_list[encoder_type].name, + encoder->base.id); + if (!encoder->name) { + ret = -ENOMEM; + goto out_put; + } list_add_tail(>head, >mode_config.encoder_list); dev->mode_config.num_encoder++; - out: +out_put: + if (ret) + drm_mode_object_put(dev, >base); + +out_unlock: drm_modeset_unlock_all(dev); return ret; @@ -1013,6 +1014,8 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) struct drm_device *dev = encoder->dev; 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); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d4cd7e513280..219b533a2c15 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -400,6 +400,7 @@ struct drm_encoder_funcs { * @dev: parent DRM device * @head: list management * @base: base KMS object + * @name: encoder name * @encoder_type: one of the %DRM_MODE_ENCODER_ types in drm_mode.h * @possible_crtcs: bitmask of potential CRTC bindings * @possible_clones: bitmask of potential sibling encoders for cloning @@ -416,6 +417,7 @@ struct drm_encoder { struct list_head head; struct drm_mode_object base; + char *name; int encoder_type; uint32_t possible_crtcs; uint32_t possible_clones; -- 1.9.1
[RFC PATCH 1/2] drm: store connector name in connector struct
This makes drm_get_connector_name() thread safe. Reference: http://lkml.kernel.org/r/645ee6e22cad47d38a2b35c21c8d5fe3 at DC1-MBX-01.ptsecurity.ru Signed-off-by: Jani Nikula --- drivers/gpu/drm/drm_crtc.c | 36 include/drm/drm_crtc.h | 2 ++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 461d19bd14ee..5781130b4126 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -277,21 +277,11 @@ EXPORT_SYMBOL(drm_get_encoder_name); /** * drm_get_connector_name - return a string for connector - * @connector: connector to compute name of - * - * Note that the buffer used by this function is globally shared and owned by - * the function itself. - * - * FIXME: This isn't really multithreading safe. + * @connector: the connector to get name for */ const char *drm_get_connector_name(const struct drm_connector *connector) { - static char buf[32]; - - snprintf(buf, 32, "%s-%d", -drm_connector_enum_list[connector->connector_type].name, -connector->connector_type_id); - return buf; + return connector->name; } EXPORT_SYMBOL(drm_get_connector_name); @@ -824,7 +814,7 @@ int drm_connector_init(struct drm_device *dev, ret = drm_mode_object_get(dev, >base, DRM_MODE_OBJECT_CONNECTOR); if (ret) - goto out; + goto out_unlock; connector->base.properties = >properties; connector->dev = dev; @@ -834,9 +824,17 @@ int drm_connector_init(struct drm_device *dev, ida_simple_get(connector_ida, 1, 0, GFP_KERNEL); if (connector->connector_type_id < 0) { ret = connector->connector_type_id; - drm_mode_object_put(dev, >base); - goto out; + goto out_out; } + connector->name = + kasprintf(GFP_KERNEL, "%s-%d", + drm_connector_enum_list[connector_type].name, + connector->connector_type_id); + if (!connector->name) { + ret = -ENOMEM; + goto out_put; + } + INIT_LIST_HEAD(>probed_modes); INIT_LIST_HEAD(>modes); connector->edid_blob_ptr = NULL; @@ -853,7 +851,11 @@ int drm_connector_init(struct drm_device *dev, drm_object_attach_property(>base, dev->mode_config.dpms_property, 0); - out: +out_put: + if (ret) + drm_mode_object_put(dev, >base); + +out_unlock: drm_modeset_unlock_all(dev); return ret; @@ -881,6 +883,8 @@ void drm_connector_cleanup(struct drm_connector *connector) connector->connector_type_id); drm_mode_object_put(dev, >base); + kfree(connector->name); + connector->name = NULL; list_del(>head); dev->mode_config.num_connector--; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c061bb372199..d4cd7e513280 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -444,6 +444,7 @@ struct drm_encoder { * @attr: sysfs attributes * @head: list management * @base: base KMS object + * @name: connector name * @connector_type: one of the %DRM_MODE_CONNECTOR_ types from drm_mode.h * @connector_type_id: index into connector type enum * @interlace_allowed: can this connector handle interlaced modes? @@ -482,6 +483,7 @@ struct drm_connector { struct drm_mode_object base; + char *name; int connector_type; int connector_type_id; bool interlace_allowed; -- 1.9.1
[RFC PATCH 0/2] drm: make drm_get_{connector, encoder}_name thread safe
Hi all - This series stores connector/encoder names in the relevant structs to make the name getters thread safe. What say you, is the wasted memory too high a price to pay for the thread safety and implementation simplicity of this approach? I think making drm_get_connector_name and drm_get_encoder_name return allocated buffers makes a lot of code really ugly and error prone. I am assuming connector_type, connector_type_id, encoder_type, and encoder.base.id remain unchanged for the lifetime of the connector/encoder - is that a correct assumption? BR, Jani. N.B. I did not actually test this... Jani Nikula (2): drm: store connector name in connector struct drm: store encoder name in encoder struct drivers/gpu/drm/drm_crtc.c | 67 +- include/drm/drm_crtc.h | 4 +++ 2 files changed, 41 insertions(+), 30 deletions(-) -- 1.9.1
[RFC PATCH v1 09/16] drm/qxl: rework to new fence interface
Final driver! \o/ This is not a proper dma_fence because the hardware may never signal anything, so don't use dma-buf with qxl, ever. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/qxl/Makefile |2 drivers/gpu/drm/qxl/qxl_cmd.c |5 - drivers/gpu/drm/qxl/qxl_debugfs.c | 12 ++- drivers/gpu/drm/qxl/qxl_drv.h | 22 ++--- drivers/gpu/drm/qxl/qxl_fence.c | 87 --- drivers/gpu/drm/qxl/qxl_kms.c |2 drivers/gpu/drm/qxl/qxl_object.c |2 drivers/gpu/drm/qxl/qxl_release.c | 166 - drivers/gpu/drm/qxl/qxl_ttm.c | 97 -- 9 files changed, 220 insertions(+), 175 deletions(-) delete mode 100644 drivers/gpu/drm/qxl/qxl_fence.c diff --git a/drivers/gpu/drm/qxl/Makefile b/drivers/gpu/drm/qxl/Makefile index ea046ba691d2..ac0d74852e11 100644 --- a/drivers/gpu/drm/qxl/Makefile +++ b/drivers/gpu/drm/qxl/Makefile @@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm -qxl-y := qxl_drv.o qxl_kms.o qxl_display.o qxl_ttm.o qxl_fb.o qxl_object.o qxl_gem.o qxl_cmd.o qxl_image.o qxl_draw.o qxl_debugfs.o qxl_irq.o qxl_dumb.o qxl_ioctl.o qxl_fence.o qxl_release.o +qxl-y := qxl_drv.o qxl_kms.o qxl_display.o qxl_ttm.o qxl_fb.o qxl_object.o qxl_gem.o qxl_cmd.o qxl_image.o qxl_draw.o qxl_debugfs.o qxl_irq.o qxl_dumb.o qxl_ioctl.o qxl_release.o obj-$(CONFIG_DRM_QXL)+= qxl.o diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 45fad7b45486..97823644d347 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -620,11 +620,6 @@ static int qxl_reap_surf(struct qxl_device *qdev, struct qxl_bo *surf, bool stal if (ret == -EBUSY) return -EBUSY; - if (surf->fence.num_active_releases > 0 && stall == false) { - qxl_bo_unreserve(surf); - return -EBUSY; - } - if (stall) mutex_unlock(>surf_evict_mutex); diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index c3c2bbdc6674..0d144e0646d6 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -57,11 +57,21 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data) struct qxl_device *qdev = node->minor->dev->dev_private; struct qxl_bo *bo; + spin_lock(>release_lock); list_for_each_entry(bo, >gem.objects, list) { + struct reservation_object_list *fobj; + int rel; + + rcu_read_lock(); + fobj = rcu_dereference(bo->tbo.resv->fence); + rel = fobj ? fobj->shared_count : 0; + rcu_read_unlock(); + seq_printf(m, "size %ld, pc %d, sync obj %p, num releases %d\n", (unsigned long)bo->gem_base.size, bo->pin_count, - bo->tbo.sync_obj, bo->fence.num_active_releases); + bo->tbo.sync_obj, rel); } + spin_unlock(>release_lock); return 0; } diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 36ed40ba773f..d547cbdebeb4 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -31,6 +31,7 @@ * Definitions taken from spice-protocol, plus kernel driver specific bits. */ +#include #include #include #include @@ -95,13 +96,6 @@ enum { QXL_INTERRUPT_IO_CMD |\ QXL_INTERRUPT_CLIENT_MONITORS_CONFIG) -struct qxl_fence { - struct qxl_device *qdev; - uint32_t num_active_releases; - uint32_t *release_ids; - struct radix_tree_root tree; -}; - struct qxl_bo { /* Protected by gem.mutex */ struct list_headlist; @@ -113,13 +107,13 @@ struct qxl_bo { unsignedpin_count; void*kptr; int type; + /* Constant after initialization */ struct drm_gem_object gem_base; bool is_primary; /* is this now a primary surface */ bool hw_surf_alloc; struct qxl_surface surf; uint32_t surface_id; - struct qxl_fence fence; /* per bo fence - list of releases */ struct qxl_release *surf_create; }; #define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, gem_base) @@ -191,6 +185,8 @@ enum { * spice-protocol/qxl_dev.h */ #define QXL_MAX_RES 96 struct qxl_release { + struct fence base; + int id; int type; uint32_t release_offset; @@ -284,7 +280,11 @@ struct qxl_device { uint8_t slot_gen_bits; uint64_tva_slot_mask; + /* XXX: when rcu becomes available, release_lock can be killed */ + spinlock_t release_lock; + spinlock_t fence_lock; struct idr release_idr; + uint32_trelease_seqno; spinlock_t release_idr_lock; struct mutexasync_io_mutex;
[RFC PATCH v1 08/16] drm/radeon: use common fence implementation for fences
Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/radeon/radeon.h| 15 +-- drivers/gpu/drm/radeon/radeon_device.c |1 drivers/gpu/drm/radeon/radeon_fence.c | 189 +--- 3 files changed, 153 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 68528619834a..a7d839a158ae 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -113,9 +114,6 @@ extern int radeon_hard_reset; #define RADEONFB_CONN_LIMIT4 #define RADEON_BIOS_NUM_SCRATCH8 -/* fence seq are set to this number when signaled */ -#define RADEON_FENCE_SIGNALED_SEQ 0LL - /* internal ring indices */ /* r1xx+ has gfx CP ring */ #define RADEON_RING_TYPE_GFX_INDEX 0 @@ -347,12 +345,15 @@ struct radeon_fence_driver { }; struct radeon_fence { + struct fence base; + struct radeon_device*rdev; - struct kref kref; /* protected by radeon_fence.lock */ uint64_tseq; /* RB, DMA, etc. */ unsignedring; + + wait_queue_t fence_wake; }; int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); @@ -2256,6 +2257,7 @@ struct radeon_device { struct radeon_mman mman; struct radeon_fence_driver fence_drv[RADEON_NUM_RINGS]; wait_queue_head_t fence_queue; + unsignedfence_context; struct mutexring_lock; struct radeon_ring ring[RADEON_NUM_RINGS]; boolib_pool_ready; @@ -2346,11 +2348,6 @@ u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index); void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v); /* - * Cast helper - */ -#define to_radeon_fence(p) ((struct radeon_fence *)(p)) - -/* * Registers read & write functions. */ #define RREG8(reg) readb((rdev->rmmio) + (reg)) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0e770bbf7e29..501d0cf9eb8b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1175,6 +1175,7 @@ int radeon_device_init(struct radeon_device *rdev, for (i = 0; i < RADEON_NUM_RINGS; i++) { rdev->ring[i].idx = i; } + rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS); DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", radeon_family_name[rdev->family], pdev->vendor, pdev->device, diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index a77b1c13ea43..bc844f300d3f 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -39,6 +39,15 @@ #include "radeon.h" #include "radeon_trace.h" +static const struct fence_ops radeon_fence_ops; + +#define to_radeon_fence(p) \ + ({ \ + struct radeon_fence *__f; \ + __f = container_of((p), struct radeon_fence, base); \ + __f->base.ops == _fence_ops ? __f : NULL;\ + }) + /* * Fences * Fences mark an event in the GPUs pipeline and are used @@ -111,30 +120,55 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring) { + u64 seq = ++rdev->fence_drv[ring].sync_seq[ring]; + /* we are protected by the ring emission mutex */ *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); if ((*fence) == NULL) { return -ENOMEM; } - kref_init(&((*fence)->kref)); - (*fence)->rdev = rdev; - (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; (*fence)->ring = ring; + __fence_init(&(*fence)->base, _fence_ops, +>fence_queue.lock, rdev->fence_context + ring, seq); + (*fence)->rdev = rdev; + (*fence)->seq = seq; radeon_fence_ring_emit(rdev, ring, *fence); trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); return 0; } /** - * radeon_fence_process - process a fence + * radeon_fence_check_signaled - callback from fence_queue * - * @rdev: radeon_device pointer - * @ring: ring index the fence is associated with - * - * Checks the current fence value and wakes the fence queue - * if the sequence number has increased (all asics). + * this function is called with fence_queue lock held, which is also used + * for the fence locking itself, so unlocked variants are used for + * fence_signal, and remove_wait_queue. */ -void
[RFC PATCH v1 07/16] drm/nouveau: rework to new fence interface
From: Maarten LankhorstSigned-off-by: Maarten Lankhorst --- drivers/gpu/drm/nouveau/core/core/event.c |4 drivers/gpu/drm/nouveau/nouveau_bo.c |6 drivers/gpu/drm/nouveau/nouveau_display.c |4 drivers/gpu/drm/nouveau/nouveau_fence.c | 434 - drivers/gpu/drm/nouveau/nouveau_fence.h | 20 + drivers/gpu/drm/nouveau/nouveau_gem.c | 17 - drivers/gpu/drm/nouveau/nv04_fence.c |4 drivers/gpu/drm/nouveau/nv10_fence.c |4 drivers/gpu/drm/nouveau/nv17_fence.c |2 drivers/gpu/drm/nouveau/nv50_fence.c |2 drivers/gpu/drm/nouveau/nv84_fence.c | 11 - 11 files changed, 329 insertions(+), 179 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index 3f3c76581a9e..167408b72099 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c @@ -118,14 +118,14 @@ nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref) void nouveau_event_trigger(struct nouveau_event *event, int index) { - struct nouveau_eventh *handler; + struct nouveau_eventh *handler, *next; unsigned long flags; if (WARN_ON(index >= event->index_nr)) return; spin_lock_irqsave(>list_lock, flags); - list_for_each_entry(handler, >index[index].list, head) { + list_for_each_entry_safe(handler, next, >index[index].list, head) { if (test_bit(NVKM_EVENT_ENABLE, >flags) && handler->func(handler->priv, index) == NVKM_EVENT_DROP) nouveau_event_put(handler); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e98af2e9a1cb..84aba3fa1bd0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -959,7 +959,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, } mutex_lock_nested(>cli->mutex, SINGLE_DEPTH_NESTING); - ret = nouveau_fence_sync(bo->sync_obj, chan); + ret = nouveau_fence_sync(nouveau_bo(bo), chan); if (ret == 0) { ret = drm->ttm.move(chan, bo, >mem, new_mem); if (ret == 0) { @@ -1432,10 +1432,12 @@ nouveau_bo_fence_unref(void **sync_obj) void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) { - lockdep_assert_held(>bo.resv->lock.base); + struct reservation_object *resv = nvbo->bo.resv; nouveau_bo_fence_unref(>bo.sync_obj); nvbo->bo.sync_obj = nouveau_fence_ref(fence); + + reservation_object_add_excl_fence(resv, >base); } static void * diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 6a0ca004bd19..eeb8762feaf0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -660,7 +660,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, spin_unlock_irqrestore(>event_lock, flags); /* Synchronize with the old framebuffer */ - ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); + ret = nouveau_fence_sync(old_bo, chan); if (ret) goto fail; @@ -721,7 +721,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, goto fail_unpin; /* synchronise rendering channel with the kernel's channel */ - ret = nouveau_fence_sync(new_bo->bo.sync_obj, chan); + ret = nouveau_fence_sync(new_bo, chan); if (ret) { ttm_bo_unreserve(_bo->bo); goto fail_unpin; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 90074d620e31..9a9e04985826 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -32,91 +32,139 @@ #include "nouveau_drm.h" #include "nouveau_dma.h" #include "nouveau_fence.h" +#include #include -struct fence_work { - struct work_struct base; - struct list_head head; - void (*func)(void *); - void *data; -}; +static const struct fence_ops nouveau_fence_ops_uevent; +static const struct fence_ops nouveau_fence_ops_legacy; static void nouveau_fence_signal(struct nouveau_fence *fence) { - struct fence_work *work, *temp; + __fence_signal(>base); + list_del(>head); + + if (fence->base.ops == _fence_ops_uevent && + fence->event.head.next) { + struct nouveau_event *event; - list_for_each_entry_safe(work, temp, >work, head) { - schedule_work(>base); - list_del(>head); + list_del(>event.head); + fence->event.head.next = NULL; + + event = container_of(fence->base.lock, typeof(*event), list_lock); + nouveau_event_put(>event); } -
[RFC PATCH v1 06/16] drm/ttm: kill fence_lock
No users are left, kill it off! :D Conversion to the reservation api is next on the list, after that the functionality can be restored with rcu. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/nouveau/nouveau_bo.c | 25 +++--- drivers/gpu/drm/nouveau/nouveau_display.c |6 -- drivers/gpu/drm/nouveau/nouveau_gem.c | 16 +- drivers/gpu/drm/qxl/qxl_cmd.c |2 - drivers/gpu/drm/qxl/qxl_fence.c |4 -- drivers/gpu/drm/qxl/qxl_object.h |2 - drivers/gpu/drm/qxl/qxl_release.c |2 - drivers/gpu/drm/radeon/radeon_display.c |2 - drivers/gpu/drm/radeon/radeon_object.c|2 - drivers/gpu/drm/ttm/ttm_bo.c | 75 +++-- drivers/gpu/drm/ttm/ttm_bo_util.c |5 -- drivers/gpu/drm/ttm/ttm_bo_vm.c |3 - drivers/gpu/drm/ttm/ttm_execbuf_util.c|2 - drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c|4 -- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 17 ++- include/drm/ttm/ttm_bo_api.h |5 -- include/drm/ttm/ttm_bo_driver.h |3 - 17 files changed, 36 insertions(+), 139 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 33eb7164525a..e98af2e9a1cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1196,9 +1196,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, } /* Fallback to software copy. */ - spin_lock(>bdev->fence_lock); ret = ttm_bo_wait(bo, true, intr, no_wait_gpu); - spin_unlock(>bdev->fence_lock); if (ret == 0) ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); @@ -1425,26 +1423,19 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) ttm_pool_unpopulate(ttm); } +static void +nouveau_bo_fence_unref(void **sync_obj) +{ + nouveau_fence_unref((struct nouveau_fence **)sync_obj); +} + void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) { - struct nouveau_fence *new_fence = nouveau_fence_ref(fence); - struct nouveau_fence *old_fence = NULL; - lockdep_assert_held(>bo.resv->lock.base); - spin_lock(>bo.bdev->fence_lock); - old_fence = nvbo->bo.sync_obj; - nvbo->bo.sync_obj = new_fence; - spin_unlock(>bo.bdev->fence_lock); - - nouveau_fence_unref(_fence); -} - -static void -nouveau_bo_fence_unref(void **sync_obj) -{ - nouveau_fence_unref((struct nouveau_fence **)sync_obj); + nouveau_bo_fence_unref(>bo.sync_obj); + nvbo->bo.sync_obj = nouveau_fence_ref(fence); } static void * diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 61b8c3375135..6a0ca004bd19 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -721,11 +721,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, goto fail_unpin; /* synchronise rendering channel with the kernel's channel */ - spin_lock(_bo->bo.bdev->fence_lock); - fence = nouveau_fence_ref(new_bo->bo.sync_obj); - spin_unlock(_bo->bo.bdev->fence_lock); - ret = nouveau_fence_sync(fence, chan); - nouveau_fence_unref(); + ret = nouveau_fence_sync(new_bo->bo.sync_obj, chan); if (ret) { ttm_bo_unreserve(_bo->bo); goto fail_unpin; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 6e1c58a880fe..6cd5298cbb53 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -105,9 +105,7 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma) list_del(>head); if (mapped) { - spin_lock(>bo.bdev->fence_lock); fence = nouveau_fence_ref(nvbo->bo.sync_obj); - spin_unlock(>bo.bdev->fence_lock); } if (fence) { @@ -432,17 +430,11 @@ retry: static int validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo) { - struct nouveau_fence *fence = NULL; + struct nouveau_fence *fence = nvbo->bo.sync_obj; int ret = 0; - spin_lock(>bo.bdev->fence_lock); - fence = nouveau_fence_ref(nvbo->bo.sync_obj); - spin_unlock(>bo.bdev->fence_lock); - - if (fence) { + if (fence) ret = nouveau_fence_sync(fence, chan); - nouveau_fence_unref(); - } return ret; } @@ -661,9 +653,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, data |= r->vor; } - spin_lock(>bo.bdev->fence_lock); ret = ttm_bo_wait(>bo, false, false, false); - spin_unlock(>bo.bdev->fence_lock); if (ret) { NV_ERROR(cli, "reloc
[RFC PATCH v1 05/16] drm/ttm: call ttm_bo_wait while inside a reservation
This is the last remaining function that doesn't use the reservation lock completely to fence off access to a buffer. --- drivers/gpu/drm/ttm/ttm_bo.c | 25 - 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4ab9f7171c4f..d7d34336f108 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -502,17 +502,6 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, if (ret) return ret; - /* -* remove sync_obj with ttm_bo_wait, the wait should be -* finished, and no new wait object should have been added. -*/ - spin_lock(>fence_lock); - ret = ttm_bo_wait(bo, false, false, true); - WARN_ON(ret); - spin_unlock(>fence_lock); - if (ret) - return ret; - spin_lock(>lru_lock); ret = __ttm_bo_reserve(bo, false, true, false, 0); @@ -528,8 +517,16 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, spin_unlock(>lru_lock); return 0; } - } else - spin_unlock(>fence_lock); + + /* +* remove sync_obj with ttm_bo_wait, the wait should be +* finished, and no new wait object should have been added. +*/ + spin_lock(>fence_lock); + ret = ttm_bo_wait(bo, false, false, true); + WARN_ON(ret); + } + spin_unlock(>fence_lock); if (ret || unlikely(list_empty(>ddestroy))) { __ttm_bo_unreserve(bo); @@ -1539,6 +1536,8 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, void *sync_obj; int ret = 0; + lockdep_assert_held(>resv->lock.base); + if (likely(bo->sync_obj == NULL)) return 0;
[RFC PATCH v1 04/16] drm/nouveau: require reservations for nouveau_fence_sync and nouveau_bo_fence
This will ensure we always hold the required lock when calling those functions. --- drivers/gpu/drm/nouveau/nouveau_bo.c |2 ++ drivers/gpu/drm/nouveau/nouveau_display.c | 17 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index b6dc85c614be..33eb7164525a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1431,6 +1431,8 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) struct nouveau_fence *new_fence = nouveau_fence_ref(fence); struct nouveau_fence *old_fence = NULL; + lockdep_assert_held(>bo.resv->lock.base); + spin_lock(>bo.bdev->fence_lock); old_fence = nvbo->bo.sync_obj; nvbo->bo.sync_obj = new_fence; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index da764a4ed958..61b8c3375135 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -716,6 +716,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, } mutex_lock(>cli->mutex); + ret = ttm_bo_reserve(_bo->bo, true, false, false, NULL); + if (ret) + goto fail_unpin; /* synchronise rendering channel with the kernel's channel */ spin_lock(_bo->bo.bdev->fence_lock); @@ -723,12 +726,18 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, spin_unlock(_bo->bo.bdev->fence_lock); ret = nouveau_fence_sync(fence, chan); nouveau_fence_unref(); - if (ret) + if (ret) { + ttm_bo_unreserve(_bo->bo); goto fail_unpin; + } - ret = ttm_bo_reserve(_bo->bo, true, false, false, NULL); - if (ret) - goto fail_unpin; + if (new_bo != old_bo) { + ttm_bo_unreserve(_bo->bo); + + ret = ttm_bo_reserve(_bo->bo, true, false, false, NULL); + if (ret) + goto fail_unpin; + } /* Initialize a page flip struct */ *s = (struct nouveau_page_flip_state)
[RFC PATCH v1 03/16] drm/nouveau: add reservation to nouveau_gem_ioctl_cpu_prep
Apart from some code inside ttm itself and nouveau_bo_vma_del, this is the only place where ttm_bo_wait is used without a reservation. Fix this so we can remove the fence_lock later on. After the switch to rcu the reservation lock will be removed again. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/nouveau/nouveau_gem.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c90c0dc0afe8..6e1c58a880fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -886,17 +886,31 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, struct drm_gem_object *gem; struct nouveau_bo *nvbo; bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); - int ret = -EINVAL; + int ret; + struct nouveau_fence *fence = NULL; gem = drm_gem_object_lookup(dev, file_priv, req->handle); if (!gem) return -ENOENT; nvbo = nouveau_gem_object(gem); - spin_lock(>bo.bdev->fence_lock); - ret = ttm_bo_wait(>bo, true, true, no_wait); - spin_unlock(>bo.bdev->fence_lock); + ret = ttm_bo_reserve(>bo, true, false, false, 0); + if (!ret) { + spin_lock(>bo.bdev->fence_lock); + ret = ttm_bo_wait(>bo, true, true, true); + if (!no_wait && ret) + fence = nouveau_fence_ref(nvbo->bo.sync_obj); + spin_unlock(>bo.bdev->fence_lock); + + ttm_bo_unreserve(>bo); + } drm_gem_object_unreference_unlocked(gem); + + if (fence) { + ret = nouveau_fence_wait(fence, true, no_wait); + nouveau_fence_unref(); + } + return ret; }
[RFC PATCH v1 02/16] drm/ttm: kill off some members to ttm_validate_buffer
This reorders the list to keep track of what buffers are reserved, so previous members are always unreserved. This gets rid of some bookkeeping that's no longer needed, while simplifying the code some. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/qxl/qxl_release.c |1 drivers/gpu/drm/ttm/ttm_execbuf_util.c | 142 +++ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |1 include/drm/ttm/ttm_execbuf_util.h |3 - 4 files changed, 50 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 2b43e5deb051..e85c4d274dc0 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -350,7 +350,6 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release) ttm_bo_add_to_lru(bo); __ttm_bo_unreserve(bo); - entry->reserved = false; } spin_unlock(>fence_lock); spin_unlock(>lru_lock); diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index 39a11bbd2bac..6db47a72667e 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -32,20 +32,12 @@ #include #include -static void ttm_eu_backoff_reservation_locked(struct list_head *list) +static void ttm_eu_backoff_reservation_reverse(struct list_head *list, + struct ttm_validate_buffer *entry) { - struct ttm_validate_buffer *entry; - - list_for_each_entry(entry, list, head) { + list_for_each_entry_continue_reverse(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - if (!entry->reserved) - continue; - entry->reserved = false; - if (entry->removed) { - ttm_bo_add_to_lru(bo); - entry->removed = false; - } __ttm_bo_unreserve(bo); } } @@ -56,27 +48,9 @@ static void ttm_eu_del_from_lru_locked(struct list_head *list) list_for_each_entry(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - if (!entry->reserved) - continue; + unsigned put_count = ttm_bo_del_from_lru(bo); - if (!entry->removed) { - entry->put_count = ttm_bo_del_from_lru(bo); - entry->removed = true; - } - } -} - -static void ttm_eu_list_ref_sub(struct list_head *list) -{ - struct ttm_validate_buffer *entry; - - list_for_each_entry(entry, list, head) { - struct ttm_buffer_object *bo = entry->bo; - - if (entry->put_count) { - ttm_bo_list_ref_sub(bo, entry->put_count, true); - entry->put_count = 0; - } + ttm_bo_list_ref_sub(bo, put_count, true); } } @@ -91,11 +65,18 @@ void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, entry = list_first_entry(list, struct ttm_validate_buffer, head); glob = entry->bo->glob; + spin_lock(>lru_lock); - ttm_eu_backoff_reservation_locked(list); + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + + ttm_bo_add_to_lru(bo); + __ttm_bo_unreserve(bo); + } + spin_unlock(>lru_lock); + if (ticket) ww_acquire_fini(ticket); - spin_unlock(>lru_lock); } EXPORT_SYMBOL(ttm_eu_backoff_reservation); @@ -121,64 +102,55 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, if (list_empty(list)) return 0; - list_for_each_entry(entry, list, head) { - entry->reserved = false; - entry->put_count = 0; - entry->removed = false; - } - entry = list_first_entry(list, struct ttm_validate_buffer, head); glob = entry->bo->glob; if (ticket) ww_acquire_init(ticket, _ww_class); -retry: + list_for_each_entry(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - /* already slowpath reserved? */ - if (entry->reserved) - continue; - ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), true, ticket); + if (!ret && unlikely(atomic_read(>cpu_writers) > 0)) { + __ttm_bo_unreserve(bo); - if (ret == -EDEADLK) { - /* uh oh, we lost out, drop every reservation and try -* to only reserve this buffer, then start over if -* this succeeds. -*/ - BUG_ON(ticket == NULL); - spin_lock(>lru_lock); -
[RFC PATCH v1 01/16] drm/ttm: add interruptible parameter to ttm_eu_reserve_buffers
It seems some drivers really want this as a parameter, like vmwgfx. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/qxl/qxl_release.c|2 +- drivers/gpu/drm/radeon/radeon_object.c |2 +- drivers/gpu/drm/radeon/radeon_uvd.c |2 +- drivers/gpu/drm/radeon/radeon_vm.c |2 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 22 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |7 ++- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |2 +- include/drm/ttm/ttm_execbuf_util.h |9 + 8 files changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 14e776f1d14e..2b43e5deb051 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -159,7 +159,7 @@ int qxl_release_reserve_list(struct qxl_release *release, bool no_intr) if (list_is_singular(>bos)) return 0; - ret = ttm_eu_reserve_buffers(>ticket, >bos); + ret = ttm_eu_reserve_buffers(>ticket, >bos, !no_intr); if (ret) return ret; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 19bec0dbfa38..51bf80cdce5c 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -438,7 +438,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, u64 bytes_moved = 0, initial_bytes_moved; u64 bytes_moved_threshold = radeon_bo_get_threshold_for_moves(rdev); - r = ttm_eu_reserve_buffers(ticket, head); + r = ttm_eu_reserve_buffers(ticket, head, true); if (unlikely(r != 0)) { return r; } diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 1b65ae2433cd..2f93fef15aab 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -620,7 +620,7 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev, INIT_LIST_HEAD(); list_add(, ); - r = ttm_eu_reserve_buffers(, ); + r = ttm_eu_reserve_buffers(, , true); if (r) return r; diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 2aae6ce49d32..f4fd72477a71 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -364,7 +364,7 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev, INIT_LIST_HEAD(); list_add(, ); -r = ttm_eu_reserve_buffers(, ); +r = ttm_eu_reserve_buffers(, , true); if (r) return r; diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index e8dac8758528..39a11bbd2bac 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -112,7 +112,7 @@ EXPORT_SYMBOL(ttm_eu_backoff_reservation); */ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, - struct list_head *list) + struct list_head *list, bool intr) { struct ttm_bo_global *glob; struct ttm_validate_buffer *entry; @@ -140,7 +140,7 @@ retry: if (entry->reserved) continue; - ret = __ttm_bo_reserve(bo, true, (ticket == NULL), true, + ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), true, ticket); if (ret == -EDEADLK) { @@ -153,13 +153,17 @@ retry: ttm_eu_backoff_reservation_locked(list); spin_unlock(>lru_lock); ttm_eu_list_ref_sub(list); - ret = ww_mutex_lock_slow_interruptible(>resv->lock, - ticket); - if (unlikely(ret != 0)) { - if (ret == -EINTR) - ret = -ERESTARTSYS; - goto err_fini; - } + + if (intr) { + ret = ww_mutex_lock_slow_interruptible(>resv->lock, + ticket); + if (unlikely(ret != 0)) { + if (ret == -EINTR) + ret = -ERESTARTSYS; + goto err_fini; + } + } else + ww_mutex_lock_slow(>resv->lock, ticket); entry->reserved = true; if (unlikely(atomic_read(>cpu_writers) > 0)) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 87df0b3674fd..5d7d2e00296b 100644 ---
[RFC PATCH v1 00/16] Convert all ttm drivers to use the new reservation interface
This series depends on the previously posted reservation api patches. 2 of them are not yet in for-next-fences branch of git://git.linaro.org/people/sumit.semwal/linux-3.x.git The missing patches are still in my vmwgfx_wip branch at git://people.freedesktop.org/~mlankhorst/linux All ttm drivers are converted to the fence api, fence_lock is removed and rcu is used in its place. qxl is the first driver to use shared fence slots, but when these patches are applied it's easy to convert nouveau too. I've done it as part of the cross-device gpu synchronization patch series. --- Maarten Lankhorst (16): drm/ttm: add interruptible parameter to ttm_eu_reserve_buffers drm/ttm: kill off some members to ttm_validate_buffer drm/nouveau: add reservation to nouveau_gem_ioctl_cpu_prep drm/nouveau: require reservations for nouveau_fence_sync and nouveau_bo_fence drm/ttm: call ttm_bo_wait while inside a reservation drm/ttm: kill fence_lock drm/nouveau: rework to new fence interface drm/radeon: use common fence implementation for fences drm/qxl: rework to new fence interface drm/vmwgfx: get rid of different types of fence_flags entirely drm/vmwgfx: rework to new fence interface drm/ttm: flip the switch, and convert to dma_fence drm/nouveau: use rcu in nouveau_gem_ioctl_cpu_prep drm/radeon: use rcu waits in some ioctls drm/vmwgfx: use rcu in vmw_user_dmabuf_synccpu_grab drm/ttm: use rcu in core ttm drivers/gpu/drm/nouveau/core/core/event.c |4 drivers/gpu/drm/nouveau/nouveau_bo.c | 59 +--- drivers/gpu/drm/nouveau/nouveau_display.c | 25 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 430 +++-- drivers/gpu/drm/nouveau/nouveau_fence.h | 22 + drivers/gpu/drm/nouveau/nouveau_gem.c | 55 +--- drivers/gpu/drm/nouveau/nv04_fence.c |4 drivers/gpu/drm/nouveau/nv10_fence.c |4 drivers/gpu/drm/nouveau/nv17_fence.c |2 drivers/gpu/drm/nouveau/nv50_fence.c |2 drivers/gpu/drm/nouveau/nv84_fence.c | 11 - drivers/gpu/drm/qxl/Makefile |2 drivers/gpu/drm/qxl/qxl_cmd.c |7 drivers/gpu/drm/qxl/qxl_debugfs.c | 16 + drivers/gpu/drm/qxl/qxl_drv.h | 20 - drivers/gpu/drm/qxl/qxl_fence.c | 91 -- drivers/gpu/drm/qxl/qxl_kms.c |1 drivers/gpu/drm/qxl/qxl_object.c |2 drivers/gpu/drm/qxl/qxl_object.h |6 drivers/gpu/drm/qxl/qxl_release.c | 172 ++-- drivers/gpu/drm/qxl/qxl_ttm.c | 93 -- drivers/gpu/drm/radeon/radeon.h | 15 - drivers/gpu/drm/radeon/radeon_cs.c| 10 + drivers/gpu/drm/radeon/radeon_device.c|1 drivers/gpu/drm/radeon/radeon_display.c | 20 + drivers/gpu/drm/radeon/radeon_fence.c | 191 ++--- drivers/gpu/drm/radeon/radeon_gem.c | 19 + drivers/gpu/drm/radeon/radeon_object.c|8 - drivers/gpu/drm/radeon/radeon_ttm.c | 34 -- drivers/gpu/drm/radeon/radeon_uvd.c | 10 - drivers/gpu/drm/ttm/ttm_bo.c | 187 ++--- drivers/gpu/drm/ttm/ttm_bo_util.c | 28 -- drivers/gpu/drm/ttm/ttm_bo_vm.c |3 drivers/gpu/drm/ttm/ttm_execbuf_util.c| 146 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c| 47 --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h |1 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 24 -- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 329 -- drivers/gpu/drm/vmwgfx/vmwgfx_fence.h | 35 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 43 +-- include/drm/ttm/ttm_bo_api.h |7 include/drm/ttm/ttm_bo_driver.h | 29 -- include/drm/ttm/ttm_execbuf_util.h| 22 + 43 files changed, 1107 insertions(+), 1130 deletions(-) delete mode 100644 drivers/gpu/drm/qxl/qxl_fence.c -- Signature
[RFC V3 2/3] drm/bridge: add a dummy panel driver to support lvds bridges
ontrols inside > bridge! :( What makes you think that I would suddenly be any more convinced by this solution than by your prior proposal? I didn't say outright no to what you proposed earlier. What I said was that I didn't like it and that I thought we could come up with a better solution. Part of getting to a better solution is trying to understand the problems involved. You don't solve a problem by simply moving code into a different driver. Thierry -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20140514/6d0ed490/attachment.sig>
[PATCH v2 4/7] drivers/base: Add interface framework
On Tue, May 13, 2014 at 05:32:15PM -0700, Greg Kroah-Hartman wrote: > On Tue, May 13, 2014 at 07:57:13PM +0200, Daniel Vetter wrote: > > On Tue, May 13, 2014 at 05:30:47PM +0200, Thierry Reding wrote: > > > From: Thierry Reding > > > > > > Some drivers, such as graphics drivers in the DRM subsystem, do not have > > > a real device that they can bind to. They are often composed of several > > > devices, each having their own driver. The master/component framework > > > can be used in these situations to collect the devices pertaining to one > > > logical device, wait until all of them have registered and then bind > > > them all at once. > > > > > > For some situations this is only a partial solution. An implementation > > > of a master still needs to be registered with the system somehow. Many > > > drivers currently resort to creating a dummy device that a driver can > > > bind to and register the master against. This is problematic since it > > > requires (and presumes) knowledge about the system within drivers. > > > > > > Furthermore there are setups where a suitable device already exists, but > > > is already bound to a driver. For example, on Tegra the following device > > > tree extract (simplified) represents the host1x device along with child > > > devices: > > > > > > host1x { > > > display-controller { > > > ... > > > }; > > > > > > display-controller { > > > ... > > > }; > > > > > > hdmi { > > > ... > > > }; > > > > > > dsi { > > > ... > > > }; > > > > > > csi { > > > ... > > > }; > > > > > > video-input { > > > ... > > > }; > > > }; > > > > > > Each of the child devices is in turn a client of host1x, in that it can > > > request resources (command stream DMA channels and syncpoints) from it. > > > To implement the DMA channel and syncpoint infrastructure, host1x comes > > > with its own driver. Children are implemented in separate drivers. In > > > Linux this set of devices would be exposed by DRM and V4L2 drivers. > > > > > > However, neither the DRM nor the V4L2 drivers have a single device that > > > they can bind to. The DRM device is composed of the display controllers > > > and the various output devices, whereas the V4L2 device is composed of > > > one or more video input devices. > > > > > > This patch introduces the concept of an interface and drivers that can > > > bind to a given interface. An interface can be exposed by any device, > > > and interface drivers can bind to these interfaces. Multiple drivers can > > > bind against a single interface. When a device is removed, interfaces > > > exposed by it will be removed as well, thereby removing the drivers that > > > were bound to those interfaces. > > > > > > In the example above, the host1x device would expose the "tegra-host1x" > > > interface. DRM and V4L2 drivers can then bind to that interface and > > > instantiate the respective subsystem objects from there. > > > > > > Signed-off-by: Thierry Reding > > > --- > > > Note that I'd like to merge this through the Tegra DRM tree so that the > > > changes to the Tegra DRM driver later in this series can be merged at > > > the same time and are not delayed for another release cycle. > > > > > > In particular that means that I'm looking for an Acked-by from Greg. > > > > > > drivers/base/Makefile | 2 +- > > > drivers/base/interface.c | 186 > > > ++ > > > include/linux/interface.h | 40 ++ > > > 3 files changed, 227 insertions(+), 1 deletion(-) > > > create mode 100644 drivers/base/interface.c > > > create mode 100644 include/linux/interface.h > > > > Hm, this interface stuff smells like bus drivers light. Should we instead > > have a pile of helpers to make creating new buses with match methods more > > trivial? There's a fairly big pile of small use-cases where this might be > > useful. In your case here all the host1x children would sit on a host1x > > bus. Admittedly I didn't look into the details. > > I have no problem adding such "bus-light" functions, to make it easier > to create and implement a bus in the driver core, as I know it's really > heavy. That's been on my "todo" list for over a decade now... Hm, I've victimized^Wvolunteered a few internal people to look into a hdmi/dp sink bus type of thing so that we can move away from all those ad-hoc hacks currently used to coordinate between drm display drivers and the audio side of things. So I'm interested. Do you have some ideas somewhere already about how you think this should look like? Or is this more a "hey, this would be really cool, eventually" kind of thing? Thanks, Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH v2 4/7] drivers/base: Add interface framework
On Tue, May 13, 2014 at 11:31:07PM +0200, Thierry Reding wrote: > A different solution, which seems to be fairly common for DRM drivers > for SoCs, is to instantiate a dummy device so that the DRM driver can > bind to it. This can happen in two forms: add the dummy device directly > in device tree (which goes against pretty much everything that's been > preached about device tree in the past) or the dummy device can be > instantiated in code, which is what the current Tegra DRM/host1x driver > does. Actually the dummy device seems to be an acceptable solution and iirc was even acked by DT maintainers in the last KS. I'm not on top of things, but iirc the thinking was that a dummy device which just pulls in all the relevant real bits with phandles is justified in the board file since it tells you how the board is intended to be used. The justification was that on SoCs where assigning stuff between v4l and drm is really flexible (e.g. on omap or so where you can assign the display pipes essentially freely) the use-case of the board is what matters, and that's a somewhat physical property of it (i.e. in what kind of device it's sitting.) So in your case you'd have a fake display and a fake video device which pulls everything the drm/v4l driver need together. So if the issue is how to get at a master device I think that's simple to solve. If the issue otoh is how the various drivers can get at the bus-like services host1x exposes, then I think a real bus driver makes a lot more sense. And Greg seems to have ideas about that already. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH] drm/panel: Add support for EDT ETM0700G0DH6 panel
The EDT ETM0700G0DH6 is a 7" 800x480 panel, which can be supported by the simple panel driver. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/panel/panel-simple.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 309f29e..c10ebb5 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -328,6 +328,29 @@ static const struct panel_desc chunghwa_claa101wb01 = { }, }; +static const struct drm_display_mode edt_etm0700g0dh6_mode = { + .clock = 33260, + .hdisplay = 800, + .hsync_start = 800 + 40, + .hsync_end = 800 + 40 + 128, + .htotal = 800 + 40 + 128 + 88, + .vdisplay = 480, + .vsync_start = 480 + 10, + .vsync_end = 480 + 10 + 2, + .vtotal = 480 + 10 + 2 + 33, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +}; + +static const struct panel_desc edt_etm0700g0dh6 = { + .modes = _etm0700g0dh6_mode, + .num_modes = 1, + .size = { + .width = 152, + .height = 91, + }, +}; + static const struct drm_display_mode lg_lp129qe_mode = { .clock = 285250, .hdisplay = 2560, @@ -383,6 +406,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "chunghwa,claa101wb01", .data = _claa101wb01 }, { + .compatible = "edt,etm0700g0dh6", + .data = _etm0700g0dh6, + }, { .compatible = "lg,lp129qe", .data = _lp129qe, }, { -- 2.0.0.rc2
[Bug 78669] [r600g with -O3] layered-rendering/clear-color-all-types 3d single_level fails
https://bugs.freedesktop.org/show_bug.cgi?id=78669 --- Comment #5 from Marek Ol??k --- I always compile with -O2 and the test result is random pass/fail. -- 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/20140514/89ca5175/attachment.html>
[PATCH 18/18] ARM: dts: exynos5420: add dsi node
This patch adds common part of dsi node. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- arch/arm/boot/dts/exynos5420.dtsi | 14 ++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index 6fde5fd..43b6852 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -478,6 +478,20 @@ #phy-cells = <1>; }; + dsi at 1450 { + compatible = "samsung,exynos5420-mipi-dsi"; + reg = <0x1450 0x1>; + interrupts = <0 82 0>; + samsung,power-domain = <_pd>; + phys = <_phy 1>; + phy-names = "dsim"; + clocks = < CLK_DSIM1>, < CLK_SCLK_MIPI1>; + clock-names = "bus_clk", "pll_clk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + fimd at 1440 { samsung,power-domain = <_pd>; clocks = < CLK_SCLK_FIMD1>, < CLK_FIMD1>; -- 1.7.9.5
[PATCH 17/18] ARM: dts: exynos5420: add mipi-phy node
This patch adds mipi-phy node for MIPI-DSI device. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- arch/arm/boot/dts/exynos5420.dtsi |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c3a9a66..6fde5fd 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -472,6 +472,12 @@ phy-names = "dp"; }; + mipi_phy: video-phy at 10040714 { + compatible = "samsung,s5pv210-mipi-video-phy"; + reg = <0x10040714 12>; + #phy-cells = <1>; + }; + fimd at 1440 { samsung,power-domain = <_pd>; clocks = < CLK_SCLK_FIMD1>, < CLK_FIMD1>; -- 1.7.9.5
[PATCH 16/18] ARM: dts: exynos5: add system register support
This patch adds sysreg device node, and sysreg property to fimd device node which is required to use I80 interface. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- arch/arm/boot/dts/exynos5.dtsi |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi index 79d0608..95ee496 100644 --- a/arch/arm/boot/dts/exynos5.dtsi +++ b/arch/arm/boot/dts/exynos5.dtsi @@ -81,12 +81,18 @@ status = "disabled"; }; + sys_reg: syscon at 1005 { + compatible = "samsung,exynos5-sysreg", "syscon"; + reg = <0x1005 0x500>; + }; + fimd at 1440 { compatible = "samsung,exynos5250-fimd"; interrupt-parent = <>; reg = <0x1440 0x4>; interrupt-names = "fifo", "vsync", "lcd_sys"; interrupts = <18 4>, <18 5>, <18 6>; + samsung,sysreg = <_reg>; status = "disabled"; }; -- 1.7.9.5
[PATCH 15/18] ARM: dts: exynos4: add system register node
This patch adds sysreg property to fimd device node which is required to use I80 interface. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- arch/arm/boot/dts/exynos4.dtsi |1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 2f8bcd0..abfcbe2 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -534,6 +534,7 @@ clocks = < CLK_SCLK_FIMD0>, < CLK_FIMD0>; clock-names = "sclk_fimd", "fimd"; samsung,power-domain = <_lcd0>; + samsung,sysreg = <_reg>; status = "disabled"; }; }; -- 1.7.9.5
[PATCH 14/18] drm/panel: add S6E3FA0 driver
This patch adds MIPI-DSI command mode based S6E3FA0 AMOLED LCD Panel driver. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/panel/Kconfig |7 + drivers/gpu/drm/panel/Makefile|1 + drivers/gpu/drm/panel/panel-s6e3fa0.c | 570 + 3 files changed, 578 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-s6e3fa0.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 4ec874d..fa51237 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -30,4 +30,11 @@ config DRM_PANEL_S6E8AA0 select DRM_MIPI_DSI select VIDEOMODE_HELPERS +config DRM_PANEL_S6E3FA0 + tristate "S6E3FA0 DSI command mode panel" + depends on DRM && DRM_PANEL + depends on OF + select DRM_MIPI_DSI + select CMDMODE_HELPERS + endmenu diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 8b92921..85c6738 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o +obj-$(CONFIG_DRM_PANEL_S6E3FA0) += panel-s6e3fa0.o diff --git a/drivers/gpu/drm/panel/panel-s6e3fa0.c b/drivers/gpu/drm/panel/panel-s6e3fa0.c new file mode 100644 index 000..a3b2d7e --- /dev/null +++ b/drivers/gpu/drm/panel/panel-s6e3fa0.c @@ -0,0 +1,570 @@ +/* + * MIPI-DSI based s6e3fa0 AMOLED LCD 5.7 inch panel driver. + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * + * YoungJun Cho + * + * 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. +*/ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* Manufacturer Command Set */ +#define MCS_GLOBAL_PARAMETER 0xb0 +#define MCS_AID0xb2 +#define MCS_ELVSSOPT 0xb6 +#define MCS_TEMPERATURE_SET0xb8 +#define MCS_PENTILE_CTRL 0xc0 +#define MCS_GAMMA_MODE 0xca +#define MCS_VDDM 0xd7 +#define MCS_ALS0xe3 +#define MCS_ERR_FG 0xed +#define MCS_KEY_LEV1 0xf0 +#define MCS_PANEL_UPDATE 0xf7 +#define MCS_KEY_LEV2 0xfc +#define MCS_RE 0xfe +#define MCS_TOUT2_HSYNC0xff + +/* Content Adaptive Brightness Control */ +#define DCS_WRITE_CABC 0x55 + +#define MTP_ID_LEN 3 +#define GAMMA_LEVEL_NUM30 + +#define DEFAULT_VDDM_VAL 0x15 + +struct s6e3fa0 { + struct device *dev; + struct drm_panelpanel; + + struct regulator_bulk_data supplies[2]; + struct gpio_desc*reset_gpio; + struct gpio_desc*det_gpio; + struct gpio_desc*te_gpio; + struct cmdmode cm; + + unsigned intpower_on_delay; + unsigned intreset_delay; + unsigned intinit_delay; + unsigned intwidth_mm; + unsigned intheight_mm; + + unsigned char id; + unsigned char vddm; + unsigned intbrightness; +}; + +#define panel_to_s6e3fa0(p) container_of(p, struct s6e3fa0, panel) + +/* VDD Memory Lookup Table contains paires of {ReadValue, WriteValue} */ +static const unsigned char s6e3fa0_vddm_lut[][2] = { + {0x00, 0x0d}, {0x01, 0x0d}, {0x02, 0x0e}, {0x03, 0x0f}, {0x04, 0x10}, + {0x05, 0x11}, {0x06, 0x12}, {0x07, 0x13}, {0x08, 0x14}, {0x09, 0x15}, + {0x0a, 0x16}, {0x0b, 0x17}, {0x0c, 0x18}, {0x0d, 0x19}, {0x0e, 0x1a}, + {0x0f, 0x1b}, {0x10, 0x1c}, {0x11, 0x1d}, {0x12, 0x1e}, {0x13, 0x1f}, + {0x14, 0x20}, {0x15, 0x21}, {0x16, 0x22}, {0x17, 0x23}, {0x18, 0x24}, + {0x19, 0x25}, {0x1a, 0x26}, {0x1b, 0x27}, {0x1c, 0x28}, {0x1d, 0x29}, + {0x1e, 0x2a}, {0x1f, 0x2b}, {0x20, 0x2c}, {0x21, 0x2d}, {0x22, 0x2e}, + {0x23, 0x2f}, {0x24, 0x30}, {0x25, 0x31}, {0x26, 0x32}, {0x27, 0x33}, + {0x28, 0x34}, {0x29, 0x35}, {0x2a, 0x36}, {0x2b, 0x37}, {0x2c, 0x38}, + {0x2d, 0x39}, {0x2e, 0x3a}, {0x2f, 0x3b}, {0x30, 0x3c}, {0x31, 0x3d}, + {0x32, 0x3e}, {0x33, 0x3f}, {0x34, 0x3f}, {0x35, 0x3f}, {0x36, 0x3f}, + {0x37, 0x3f}, {0x38, 0x3f}, {0x39, 0x3f}, {0x3a, 0x3f}, {0x3b, 0x3f}, + {0x3c, 0x3f}, {0x3d, 0x3f}, {0x3e, 0x3f}, {0x3f, 0x3f}, {0x40, 0x0c}, + {0x41, 0x0b}, {0x42, 0x0a}, {0x43, 0x09}, {0x44, 0x08}, {0x45, 0x07}, + {0x46, 0x06}, {0x47, 0x05}, {0x48, 0x04}, {0x49, 0x03}, {0x4a,
[PATCH 13/18] ARM: dts: s6e3fa0: add DT bindings
This patch adds DT bindings for s6e3fa0 panel. The bindings describes panel resources, display timings and cpu mode timings. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- .../devicetree/bindings/panel/samsung,s6e3fa0.txt | 45 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/samsung,s6e3fa0.txt diff --git a/Documentation/devicetree/bindings/panel/samsung,s6e3fa0.txt b/Documentation/devicetree/bindings/panel/samsung,s6e3fa0.txt new file mode 100644 index 000..c9a3fbd --- /dev/null +++ b/Documentation/devicetree/bindings/panel/samsung,s6e3fa0.txt @@ -0,0 +1,45 @@ +Samsung S6E3FA0 AMOLED LCD 5.7 inch panel + +Required properties: + - compatible: "samsung,s6e3fa0" + - reg: the virtual channel number of a DSI peripheral + - vdd3-supply: core voltage supply + - vci-supply: voltage supply for analog circuits + - reset-gpios: a GPIO spec for the reset pin + - det-gpios: a GPIO spec for the OLED detection pin + - te-gpios: a GPIO spec for the TE pin + - cmdmode-display-timings: command mode interface timings for the connected + panel as described by [1] + +Optional properties: + +The device node can contain one 'port' child node with one child 'endpoint' +node, according to the bindings defined in [2]. This node should describe +panel's video bus. + +[1]: Documentation/devicetree/bindings/video/cmdmode-display-timing.txt +[2]: Documentation/devicetree/bindings/media/video-interfaces.txt + +Example: + + panel at 0 { + compatible = "samsung,s6e3fa0"; + reg = <0>; + vdd3-supply = <_reg>; + vci-supply = <_reg>; + reset-gpios = < 4 0>; + det-gpios = < 6 0>; + te-gpios = < 7 0>; + + cmdmode-display-timings { + timing-0 { + clock-frequency = <0>; + hactive = <1080>; + vactive = <1920>; + cs-setup = <0>; + wr-setup = <0>; + wr-active = <1>; + wr-hold = <0>; + }; + }; + }; -- 1.7.9.5
[PATCH 12/18] drm/exynos: dsi: add driver data to support Exynos5420
The offset of register DSIM_PLLTMR_REG in Exynos5420 is different from the one in Exynos4 SoC. In case of Exynos5420 SoC, there is no frequency band bit in DSIM_PLLCTRL_REG, and it uses DSIM_PHYCTRL_REG and DSIM_PHYTIMING*_REG instead. So this patch adds driver data to distinguish it. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 157 ++- 1 file changed, 135 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 783d7a5..35d636b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -55,9 +56,12 @@ /* FIFO memory AC characteristic register */ #define DSIM_PLLCTRL_REG 0x4c/* PLL control register */ -#define DSIM_PLLTMR_REG0x50/* PLL timer register */ #define DSIM_PHYACCHR_REG 0x54/* D-PHY AC characteristic register */ #define DSIM_PHYACCHR1_REG 0x58/* D-PHY AC characteristic register1 */ +#define DSIM_PHYCTRL_REG 0x5c +#define DSIM_PHYTIMING_REG 0x64 +#define DSIM_PHYTIMING1_REG0x68 +#define DSIM_PHYTIMING2_REG0x6c /* DSIM_STATUS */ #define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0) @@ -201,6 +205,24 @@ #define DSIM_PLL_M(x) ((x) << 4) #define DSIM_PLL_S(x) ((x) << 1) +/* DSIM_PHYCTRL */ +#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0) + +/* DSIM_PHYTIMING */ +#define DSIM_PHYTIMING_LPX(x) ((x) << 8) +#define DSIM_PHYTIMING_HS_EXIT(x) ((x) << 0) + +/* DSIM_PHYTIMING1 */ +#define DSIM_PHYTIMING1_CLK_PREPARE(x) ((x) << 24) +#define DSIM_PHYTIMING1_CLK_ZERO(x)((x) << 16) +#define DSIM_PHYTIMING1_CLK_POST(x)((x) << 8) +#define DSIM_PHYTIMING1_CLK_TRAIL(x) ((x) << 0) + +/* DSIM_PHYTIMING2 */ +#define DSIM_PHYTIMING2_HS_PREPARE(x) ((x) << 16) +#define DSIM_PHYTIMING2_HS_ZERO(x) ((x) << 8) +#define DSIM_PHYTIMING2_HS_TRAIL(x)((x) << 0) + #define DSI_MAX_BUS_WIDTH 4 #define DSI_NUM_VIRTUAL_CHANNELS 4 #define DSI_TX_FIFO_SIZE 2048 @@ -234,6 +256,12 @@ struct exynos_dsi_transfer { #define DSIM_STATE_INITIALIZED BIT(1) #define DSIM_STATE_CMD_LPM BIT(2) +struct exynos_dsi_driver_data { + unsigned int plltmr_reg; + + unsigned int has_freqband:1; +}; + struct exynos_dsi { struct mipi_dsi_host dsi_host; struct drm_connector connector; @@ -263,11 +291,39 @@ struct exynos_dsi { spinlock_t transfer_lock; /* protects transfer_list */ struct list_head transfer_list; + + struct exynos_dsi_driver_data *driver_data; }; #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) +static struct exynos_dsi_driver_data exynos4_dsi_driver_data = { + .plltmr_reg = 0x50, + .has_freqband = 1, +}; + +static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { + .plltmr_reg = 0x58, +}; + +static struct of_device_id exynos_dsi_of_match[] = { + { .compatible = "samsung,exynos4210-mipi-dsi", + .data = _dsi_driver_data }, + { .compatible = "samsung,exynos5420-mipi-dsi", + .data = _dsi_driver_data }, + { } +}; + +static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data( + struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(exynos_dsi_of_match, >dev); + + return (struct exynos_dsi_driver_data *)of_id->data; +} + static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) { if (wait_for_completion_timeout(>completed, msecs_to_jiffies(300))) @@ -341,14 +397,9 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, unsigned long freq) { - static const unsigned long freq_bands[] = { - 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ, - 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ, - 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ, - 770 * MHZ, 870 * MHZ, 950 * MHZ, - }; + struct exynos_dsi_driver_data *driver_data = dsi->driver_data; unsigned long fin, fout; - int timeout, band; + int timeout; u8 p, s; u16 m; u32 reg; @@ -369,18 +420,30 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, "failed to find PLL PMS for requested frequency\n"); return -EFAULT; } + dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s); - for (band = 0; band < ARRAY_SIZE(freq_bands);
[PATCH 11/18] ARM: dts: exynos_dsim: add exynos5420 compatible to DT bindings
This patch adds relevant to exynos5420 compatible for exynos5420 SoC support. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- .../devicetree/bindings/video/exynos_dsim.txt |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt b/Documentation/devicetree/bindings/video/exynos_dsim.txt index 33b5730..29bf3b2 100644 --- a/Documentation/devicetree/bindings/video/exynos_dsim.txt +++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt @@ -1,7 +1,9 @@ Exynos MIPI DSI Master Required properties: - - compatible: "samsung,exynos4210-mipi-dsi" + - compatible: value should be one of the following + "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */ + "samsung,exynos5420-mipi-dsi" /* for Exynos5420 SoCs */ - reg: physical base address and length of the registers set for the device - interrupts: should contain DSI interrupt - clocks: list of clock specifiers, must contain an entry for each required -- 1.7.9.5
[PATCH 10/18] drm/exynos: fimd: support I80 interface
To support MIPI DSI command mode interface, FIMD should do followings: - Sets LCD block configuration for I80 interface. - Uses "lcd_sys" as an IRQ resource and sets relevant IRQ configuration. - Implements trigger feature which transfers image date if there is page flip request, and implements TE handler to call trigger function. - Sets command mode timings configuration. - Sets ideal(pixel) clock is 2 times faster than the original one to generate frame done IRQ prior to the next TE signal. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/Kconfig |1 + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 277 +- include/video/samsung_fimd.h |3 +- 3 files changed, 237 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 5bf5bca..f4d34f0 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD bool "Exynos DRM FIMD" depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM select FB_MODE_HELPERS + select MFD_SYSCON help Choose this option if you want to use Exynos FIMD for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 173ee97..9d585f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -20,11 +20,14 @@ #include #include #include +#include +#include #include #include #include #include +#include #include "exynos_drm_drv.h" #include "exynos_drm_fbdev.h" @@ -60,6 +63,24 @@ /* color key value register for hardware window 1 ~ 4. */ #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) +/* i80 / RGB trigger control register */ +#define TRIGCON0x1A4 +#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0) +#define SWTRGCMD_I80_RGB_ENABLE(1 << 1) + +/* display mode change control register except exynos4 */ +#define VIDOUT_CON 0x000 +#define VIDOUT_CON_F_I80_LDI0 (0x2 << 8) + +/* i80 interface control for main LDI register */ +#define I80IFCONFAx(x) (0x1B0 + (x) * 4) +#define I80IFCONFBx(x) (0x1B8 + (x) * 4) +#define LCD_CS_SETUP(x)((x) << 16) +#define LCD_WR_SETUP(x)((x) << 12) +#define LCD_WR_ACT(x) ((x) << 8) +#define LCD_WR_HOLD(x) ((x) << 4) +#define I80IFEN_ENABLE (1 << 0) + /* FIMD has totally five hardware windows. */ #define WINDOWS_NR 5 @@ -67,10 +88,14 @@ struct fimd_driver_data { unsigned int timing_base; + unsigned int lcdblk_off; + unsigned int lcdblk_vt_shift; + unsigned int lcdblk_bypass_shift; unsigned int has_shadowcon:1; unsigned int has_clksel:1; unsigned int has_limited_fmt:1; + unsigned int has_vidoutcon:1; }; static struct fimd_driver_data s3c64xx_fimd_driver_data = { @@ -81,12 +106,19 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = { static struct fimd_driver_data exynos4_fimd_driver_data = { .timing_base = 0x0, + .lcdblk_off = 0x210, + .lcdblk_vt_shift = 10, + .lcdblk_bypass_shift = 1, .has_shadowcon = 1, }; static struct fimd_driver_data exynos5_fimd_driver_data = { .timing_base = 0x2, + .lcdblk_off = 0x214, + .lcdblk_vt_shift = 24, + .lcdblk_bypass_shift = 15, .has_shadowcon = 1, + .has_vidoutcon = 1, }; struct fimd_win_data { @@ -111,15 +143,23 @@ struct fimd_context { struct clk *bus_clk; struct clk *lcd_clk; void __iomem*regs; + struct regmap *sysreg; struct drm_display_mode mode; struct fimd_win_datawin_data[WINDOWS_NR]; unsigned intdefault_win; unsigned long irq_flags; + u32 vidcon0; u32 vidcon1; + u32 vidout_con; + u32 i80ifcon; + booli80_if; boolsuspended; int pipe; wait_queue_head_t wait_vsync_queue; atomic_twait_vsync_event; + atomic_twin_updated; + atomic_ttriggering; + spinlock_t win_updated_lock; struct exynos_drm_panel_info panel; struct fimd_driver_data *driver_data; @@ -242,6 +282,14 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx, unsigned long ideal_clk = mode->htotal *
[PATCH 09/18] drm/exynos: dsi: add TE handler to support command mode interface
To support command mode interface, the DSI host calls this handler to notify the panel tearing effect synchronization signal to the CRTC device manager to trigger to transfer video image. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 0a4e3ce..783d7a5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -24,6 +24,7 @@ #include #include +#include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" /* returns true iff both arguments logically differs */ @@ -1033,10 +1034,22 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host, return (ret < 0) ? ret : xfer.rx_done; } +static int exynos_dsi_host_te_handler(struct mipi_dsi_host *host) +{ + struct exynos_dsi *dsi = host_to_dsi(host); + struct drm_encoder *encoder = dsi->encoder; + + if (!(dsi->state & DSIM_STATE_ENABLED)) + return -EPERM; + + return exynos_drm_crtc_te_handler(encoder->crtc); +} + static const struct mipi_dsi_host_ops exynos_dsi_ops = { .attach = exynos_dsi_host_attach, .detach = exynos_dsi_host_detach, .transfer = exynos_dsi_host_transfer, + .te_handler = exynos_dsi_host_te_handler, }; static int exynos_dsi_poweron(struct exynos_dsi *dsi) -- 1.7.9.5
[PATCH 08/18] drm/exynos: add TE handler to support MIPI DSI command mode interface
To support MIPI DSI command mode interface, the panel should generates Tearing Effect synchronization signal between MCU and FB to display video images. And the display controller should trigger to transfer video image at this signal. So the panel receives the TE IRQ, then calls this handler chains to notify it to the display controller. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +++ drivers/gpu/drm/exynos/exynos_drm_crtc.h |7 +++ drivers/gpu/drm/exynos/exynos_drm_drv.h |3 +++ include/drm/drm_mipi_dsi.h |8 4 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 485fa26..2567ae0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -509,3 +509,14 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, return -EPERM; } + +int exynos_drm_crtc_te_handler(struct drm_crtc *crtc) +{ + struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; + int ret = 0; + + if (manager->ops->te_handler) + ret = manager->ops->te_handler(manager); + + return ret; +} diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 9f74b10..875d93d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, unsigned int out_type); +/* + * This function calls the crtc device(manager)'s te_handler() callback + * to trigger to transfer video image at the tearing effect synchronization + * signal. + */ +int exynos_drm_crtc_te_handler(struct drm_crtc *crtc); + #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index e82e620..54b08d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -181,6 +181,8 @@ struct exynos_drm_display { * @win_commit: apply hardware specific overlay data to registers. * @win_enable: enable hardware specific overlay. * @win_disable: disable hardware specific overlay. + * @te_handler: trigger to transfer video image at the tearing effect + * synchronization signal if there is a page flip request. */ struct exynos_drm_manager; struct exynos_drm_manager_ops { @@ -199,6 +201,7 @@ struct exynos_drm_manager_ops { void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); + int (*te_handler)(struct exynos_drm_manager *mgr); }; /* diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 7209df1..f6d4c85 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -49,6 +49,13 @@ struct mipi_dsi_msg { * @detach: detach DSI device from DSI host * @transfer: send and/or receive DSI packet, return number of received bytes, * or error + * @te_handler: call the crtc te_handler() callback from DSI host. + * The panel generates tearing effect synchronization signal + * between MCU and FB to display video images. + * And the display controller should trigger to transfer video + * image at this signal. + * So the panel receives the TE IRQ, then calls this handler + * to notify it to the display controller. */ struct mipi_dsi_host_ops { int (*attach)(struct mipi_dsi_host *host, @@ -57,6 +64,7 @@ struct mipi_dsi_host_ops { struct mipi_dsi_device *dsi); ssize_t (*transfer)(struct mipi_dsi_host *host, struct mipi_dsi_msg *msg); + int (*te_handler)(struct mipi_dsi_host *host); }; /** -- 1.7.9.5
[PATCH 07/18] ARM: dts: samsung-fimd: add I80 specific properties
In case of using MIPI command mode interface panel, the relevant registers should be set. So this patch adds relevant DT bindings. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- .../devicetree/bindings/video/samsung-fimd.txt |2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt index 2dad41b..6bf93e9 100644 --- a/Documentation/devicetree/bindings/video/samsung-fimd.txt +++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt @@ -44,6 +44,8 @@ Optional Properties: - display-timings: timing settings for FIMD, as described in document [1]. Can be used in case timings cannot be provided otherwise or to override timings provided by the panel. +- samsung,sysreg: handle to syscon used to control the system registers +- vidout-i80-ldi: boolean to support i80 interface instead of rgb one The device node can contain 'port' child nodes according to the bindings defined in [2]. The following are properties specific to those nodes: -- 1.7.9.5
[PATCH 06/18] ARM: dts: sysreg: add exynos5 compatible to DT bindings
This patch adds relevant to exynos5 compatible for exynos5 SoCs. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- .../devicetree/bindings/arm/samsung/sysreg.txt |1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/samsung/sysreg.txt b/Documentation/devicetree/bindings/arm/samsung/sysreg.txt index 0ab3251..fd71581 100644 --- a/Documentation/devicetree/bindings/arm/samsung/sysreg.txt +++ b/Documentation/devicetree/bindings/arm/samsung/sysreg.txt @@ -3,6 +3,7 @@ SAMSUNG S5P/Exynos SoC series System Registers (SYSREG) Properties: - compatible : should contain "samsung,-sysreg", "syscon"; For Exynos4 SoC series it should be "samsung,exynos4-sysreg", "syscon"; + For Exynos5 SoC series it should be "samsung,exynos5-sysreg", "syscon"; - reg : offset and length of the register set. Example: -- 1.7.9.5
[PATCH 05/18] drm_modes: add command mode helpers
This patch adds helper functions to convert cmdmode to drm_display_mode Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/drm_modes.c | 59 +++ include/drm/drm_modes.h | 12 + 2 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index bedf189..8977381 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include "drm_crtc_internal.h" @@ -651,6 +653,63 @@ EXPORT_SYMBOL_GPL(of_get_drm_display_mode); #endif /* CONFIG_OF */ #endif /* CONFIG_VIDEOMODE_HELPERS */ +#ifdef CONFIG_CMDMODE_HELPERS +int drm_display_mode_from_cmdmode(const struct cmdmode *cm, + struct drm_display_mode *dmode) +{ + dmode->hdisplay = cm->hactive; + dmode->htotal = dmode->hsync_end = dmode->hsync_start = dmode->hdisplay; + + dmode->vdisplay = cm->vactive; + dmode->vtotal = dmode->vsync_end = dmode->vsync_start = dmode->vdisplay; + + dmode->clock = cm->pixelclock / 1000; + + dmode->cs_setup = cm->cs_setup; + dmode->wr_setup = cm->wr_setup; + dmode->wr_active = cm->wr_active; + dmode->wr_hold = cm->wr_hold; + + dmode->flags = 0; + drm_mode_set_name(dmode); + + return 0; +} +EXPORT_SYMBOL_GPL(drm_display_mode_from_cmdmode); + +#ifdef CONFIG_OF +/** + * of_get_drm_cmdmode_display_mode - get a drm_display_mode from devicetree + * @np: device_node with the timing specification + * @dmode: will be set to the return value + * @index: index into the list of display timings in devicetree + * + * This function is expensive and should only be used, if only one mode is to be + * read from DT. To get multiple modes start with + * of_get_cmdmode_display_timings and work with that instead. + */ +int of_get_drm_cmdmode_display_mode(struct device_node *np, + struct drm_display_mode *dmode, int index) +{ + struct cmdmode cm; + int ret; + + ret = of_get_cmdmode(np, , index); + if (ret) + return ret; + + drm_display_mode_from_cmdmode(, dmode); + + pr_debug("%s: got %dx%d display mode from %s\n", + of_node_full_name(np), cm.hactive, cm.vactive, np->name); + drm_mode_debug_printmodeline(dmode); + + return 0; +} +EXPORT_SYMBOL_GPL(of_get_drm_cmdmode_display_mode); +#endif /* CONFIG_OF */ +#endif /* CONFIG_CMDMODE_HELPERS */ + /** * drm_mode_set_name - set the name on a mode * @mode: name will be set in this mode diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 91d0582..0d29754 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -144,6 +144,12 @@ struct drm_display_mode { int vrefresh; /* in Hz */ int hsync; /* in kHz */ enum hdmi_picture_aspect picture_aspect_ratio; + + /* Command mode info - refers to video/cmdmode.h */ + int cs_setup; + int wr_setup; + int wr_active; + int wr_hold; }; /* mode specified on the command line */ @@ -176,6 +182,7 @@ static inline bool drm_mode_is_stereo(const struct drm_display_mode *mode) struct drm_connector; struct drm_cmdline_mode; +struct cmdmode; struct drm_display_mode *drm_mode_create(struct drm_device *dev); void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); @@ -200,6 +207,11 @@ void drm_display_mode_from_videomode(const struct videomode *vm, int of_get_drm_display_mode(struct device_node *np, struct drm_display_mode *dmode, int index); +extern int drm_display_mode_from_cmdmode(const struct cmdmode *cm, + struct drm_display_mode *dmode); +extern int of_get_drm_cmdmode_display_mode(struct device_node *np, + struct drm_display_mode *dmode, + int index); void drm_mode_set_name(struct drm_display_mode *mode); int drm_mode_hsync(const struct drm_display_mode *mode); -- 1.7.9.5
[PATCH 04/18] video: add command mode and command mode display timing
This patch is based on videomode and display_timing relevant codes. To support command mode panel, it does not need to guide its timing information to the display controller like video mode panel, but it requires signal timings to transfer video data. So this patch adds cmdmode struct, cmdmode_display_timing struct and the according helper functions to convert cmdmode_display_timing to a generic cmdmode. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/video/Kconfig |3 + drivers/video/Makefile|2 + drivers/video/cmdmode.c | 42 ++ drivers/video/cmdmode_display_timing.c| 26 drivers/video/of_cmdmode.c| 55 drivers/video/of_cmdmode_display_timing.c | 212 + include/video/cmdmode.h | 67 + include/video/cmdmode_display_timing.h| 59 include/video/of_cmdmode.h| 19 +++ include/video/of_cmdmode_display_timing.h | 26 10 files changed, 511 insertions(+) create mode 100644 drivers/video/cmdmode.c create mode 100644 drivers/video/cmdmode_display_timing.c create mode 100644 drivers/video/of_cmdmode.c create mode 100644 drivers/video/of_cmdmode_display_timing.c create mode 100644 include/video/cmdmode.h create mode 100644 include/video/cmdmode_display_timing.h create mode 100644 include/video/of_cmdmode.h create mode 100644 include/video/of_cmdmode_display_timing.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index c7b4f0f..7090ee5 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -38,6 +38,9 @@ config VGASTATE config VIDEOMODE_HELPERS bool +config CMDMODE_HELPERS + bool + config HDMI bool diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9ad3c17..619dd99 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -8,6 +8,8 @@ obj-y += backlight/ obj-y+= fbdev/ obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o +obj-$(CONFIG_CMDMODE_HELPERS) += cmdmode_display_timing.o cmdmode.o ifeq ($(CONFIG_OF),y) obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o +obj-$(CONFIG_CMDMODE_HELPERS) += of_cmdmode_display_timing.o of_cmdmode.o endif diff --git a/drivers/video/cmdmode.c b/drivers/video/cmdmode.c new file mode 100644 index 000..3d3eeb8 --- /dev/null +++ b/drivers/video/cmdmode.c @@ -0,0 +1,42 @@ +/* + * generic cmdmode display timing functions + * + * Copyright (c) 2014 YoungJun Cho + * + * 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. + */ + +#include +#include +#include +#include + +void cmdmode_from_timing(const struct cmdmode_display_timing *cmdt, + struct cmdmode *cm) +{ + cm->pixelclock = cmdt->pixelclock; + cm->hactive = cmdt->hactive; + cm->vactive = cmdt->vactive; + cm->cs_setup = cmdt->cs_setup; + cm->wr_setup = cmdt->wr_setup; + cm->wr_active = cmdt->wr_active; + cm->wr_hold = cmdt->wr_hold; +} +EXPORT_SYMBOL_GPL(cmdmode_from_timing); + +int cmdmode_from_timings(const struct cmdmode_display_timings *cmdts, + struct cmdmode *cm, unsigned int index) +{ + struct cmdmode_display_timing *cmdt; + + cmdt = cmdmode_display_timings_get(cmdts, index); + if (!cmdt) + return -EINVAL; + + cmdmode_from_timing(cmdt, cm); + + return 0; +} +EXPORT_SYMBOL_GPL(cmdmode_from_timings); diff --git a/drivers/video/cmdmode_display_timing.c b/drivers/video/cmdmode_display_timing.c new file mode 100644 index 000..88bab08 --- /dev/null +++ b/drivers/video/cmdmode_display_timing.c @@ -0,0 +1,26 @@ +/* + * generic cmdmode display timing functions + * + * Copyright (c) 2014 YoungJun Cho + * + * 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. + */ + +#include +#include +#include + +void cmdmode_display_timings_release(struct cmdmode_display_timings *cmdts) +{ + if (cmdts->timings) { + unsigned int i; + + for (i = 0; i < cmdts->num_timings; i++) + kfree(cmdts->timings[i]); + kfree(cmdts->timings); + } + kfree(cmdts); +} +EXPORT_SYMBOL_GPL(cmdmode_display_timings_release); diff --git a/drivers/video/of_cmdmode.c b/drivers/video/of_cmdmode.c new file mode 100644 index 000..d63294e --- /dev/null +++ b/drivers/video/of_cmdmode.c @@ -0,0 +1,55 @@ +/* + * generic cmdmode helper + * + * Copyright (c) 2014 YoungJun Cho + * + * This program is free software; you can redistribute it and/or modify + * it under
[PATCH 03/18] ARM: dts: video: add command mode display timing DT bindings
This patch adds DT bindings for command mode display timing. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- .../bindings/video/cmdmode-display-timing.txt | 64 1 file changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/video/cmdmode-display-timing.txt diff --git a/Documentation/devicetree/bindings/video/cmdmode-display-timing.txt b/Documentation/devicetree/bindings/video/cmdmode-display-timing.txt new file mode 100644 index 000..7cedfe4 --- /dev/null +++ b/Documentation/devicetree/bindings/video/cmdmode-display-timing.txt @@ -0,0 +1,64 @@ +cmdmode-display-timing bindings +=== + +cmdmode-display-timings node + + +required properties: + - none + +optional properties: + - native-mode: The native mode for the display, in case multiple modes are + provided. When omitted, assume the first node is the native. + +timing subnode +-- + +required properties: + - clock-frequency: display clock in Hz + - hactive, vactive: display resolution + - cs-setup: clock cycles for the active period of address signal is enabled + until chip select is enabled. + - wr-setup: clock cycles for the active period of CS signal is enabled until + write signal is enabled. + - wr-active: clock cycles for the active period of CS is enabled. + - wr-hold: clock cycles for the active period of CS is disabled until write + signal is disabled. + +optional properties: + +There are different ways of describing the capabilities of a display. The +devicetree representation corresponds to the one commonly found in datasheets +for displays. If a display supports multiple signal timings, the native-mode +can be specified. + +The parameters are defined as: + + VCLK(internal) __|??|_|??|_|??|_|??|_|?? +::::: + Address Output --:|::: + Chip Select ???|::|?? + | WR-SETUP+1 || WR-HOLD+1 | + |<-->||<-->| + Write Enable||??? + | WR-ACTIVE+1| + |<-->| + Video Data -- + +Example: + + cmdmode-display-timings { + native-mode = <>; + timing0: 1080p24 { + /* 1920x1080p24 */ + clock-frequency = <5200>; + hactive = <1920>; + vactive = <1080>; + cs-setup = <0>; + wr-setup = <0>; + wr-active = <1>; + wr-hold = <0>; + }; + }; -- 1.7.9.5
[PATCH 02/18] drm/exynos: use wait_event_timeout() for safety usage
There could be the case that the page flip operation isn't finished correctly with some abnormal condition such as panel reset. So this patch replaces wait_event() with wait_event_timeout() to avoid waiting for page flip completion infinitely. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_crtc.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 95c9435..485fa26 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -69,8 +69,9 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) if (mode > DRM_MODE_DPMS_ON) { /* wait for the completion of page flip. */ - wait_event(exynos_crtc->pending_flip_queue, - atomic_read(_crtc->pending_flip) == 0); + wait_event_timeout(exynos_crtc->pending_flip_queue, + !atomic_read(_crtc->pending_flip), + HZ/20); drm_vblank_off(crtc->dev, exynos_crtc->pipe); } -- 1.7.9.5
[PATCH 01/18] drm/exynos: dsi: move the EoT packets configuration point
This configuration could be used in MIPI DSI command mode also. Signed-off-by: YoungJun Cho Acked-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_dsi.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 84661fe..0a4e3ce 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -473,8 +473,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH)) reg |= DSIM_MFLUSH_VS; - if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET)) - reg |= DSIM_EOT_DISABLE; if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) reg |= DSIM_SYNC_INFORM; if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) @@ -491,6 +489,9 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) reg |= DSIM_HSA_MODE; } + if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET)) + reg |= DSIM_EOT_DISABLE; + switch (dsi->format) { case MIPI_DSI_FMT_RGB888: reg |= DSIM_MAIN_PIX_FORMAT_RGB888; -- 1.7.9.5
[PATCH 00/18] drm/exynos: support MIPI DSI command mode display
Hi, This series is for the Exynos DRM driver to support MIPI DSI command mode display and based on exynos-drm-next branch. The previous patches, RFC: http://www.spinics.net/lists/dri-devel/msg58898.html Patches 1 and 2 fix trivial bugs. Patches 3 and 4 introduce command mode and command mode display timing. These are based on video mode and (video mode) display timing. The MIPI DSI command mode interface panel does not require (video mode) display timing, but it requires signal timings to distinguish command data and video data so command mode and command mode display timing are used for it. Patch 5 converts command mode to drm display mode. Patches 6, 7, 8, 9 and 10 implement FIMD(display controller) I80 interface. The MIPI DSI command mode interface panel generates Tearing Effect synchronization signal between MCU and FB to display video image, and FIMD should trigger to transfer video image at this signal. So the panel should receive the TE IRQ then calls TE handler chains to notify it to the FIMD. Patches 11 and 12 implement to use Exynos5420 SoC DSI driver which is different from previous Exynos4 SoCs for some registers control. Patches 13 and 14 introduce MIPI DSI command interface Samsung S6E3FA0 AMOLED 5.7" LCD panel driver. Patch 15 is device tree source file for Exynos4 SoCs to support MIPI DSI command mode. The others are device tree source files for Exynos5420 to support MIPI DSI (command mode) driver. I welcome any comments. Thank you. Best regards YJ YoungJun Cho (18): drm/exynos: dsi: move the EoT packets configuration point drm/exynos: use wait_event_timeout() for safety usage ARM: dts: video: add command mode display timing DT bindings video: add command mode and command mode display timing drm_modes: add command mode helpers ARM: dts: sysreg: add exynos5 compatible to DT bindings ARM: dts: samsung-fimd: add I80 specific properties drm/exynos: add TE handler to support MIPI DSI command mode interface drm/exynos: dsi: add TE handler to support command mode interface drm/exynos: fimd: support I80 interface ARM: dts: exynos_dsim: add exynos5420 compatible to DT bindings drm/exynos: dsi: add driver data to support Exynos5420 ARM: dts: s6e3fa0: add DT bindings drm/panel: add S6E3FA0 driver ARM: dts: exynos4: add system register node ARM: dts: exynos5: add system register support ARM: dts: exynos5420: add mipi-phy node ARM: dts: exynos5420: add dsi node .../devicetree/bindings/arm/samsung/sysreg.txt |1 + .../devicetree/bindings/panel/samsung,s6e3fa0.txt | 45 ++ .../bindings/video/cmdmode-display-timing.txt | 64 +++ .../devicetree/bindings/video/exynos_dsim.txt |4 +- .../devicetree/bindings/video/samsung-fimd.txt |2 + arch/arm/boot/dts/exynos4.dtsi |1 + arch/arm/boot/dts/exynos5.dtsi |6 + arch/arm/boot/dts/exynos5420.dtsi | 20 + drivers/gpu/drm/drm_modes.c| 59 ++ drivers/gpu/drm/exynos/Kconfig |1 + drivers/gpu/drm/exynos/exynos_drm_crtc.c | 16 +- drivers/gpu/drm/exynos/exynos_drm_crtc.h |7 + drivers/gpu/drm/exynos/exynos_drm_drv.h|3 + drivers/gpu/drm/exynos/exynos_drm_dsi.c| 175 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 277 -- drivers/gpu/drm/panel/Kconfig |7 + drivers/gpu/drm/panel/Makefile |1 + drivers/gpu/drm/panel/panel-s6e3fa0.c | 570 drivers/video/Kconfig |3 + drivers/video/Makefile |2 + drivers/video/cmdmode.c| 42 ++ drivers/video/cmdmode_display_timing.c | 26 + drivers/video/of_cmdmode.c | 55 ++ drivers/video/of_cmdmode_display_timing.c | 212 include/drm/drm_mipi_dsi.h |8 + include/drm/drm_modes.h| 12 + include/video/cmdmode.h| 67 +++ include/video/cmdmode_display_timing.h | 59 ++ include/video/of_cmdmode.h | 19 + include/video/of_cmdmode_display_timing.h | 26 + include/video/samsung_fimd.h |3 +- 31 files changed, 1722 insertions(+), 71 deletions(-) create mode 100644 Documentation/devicetree/bindings/panel/samsung,s6e3fa0.txt create mode 100644 Documentation/devicetree/bindings/video/cmdmode-display-timing.txt create mode 100644 drivers/gpu/drm/panel/panel-s6e3fa0.c create mode 100644 drivers/video/cmdmode.c create mode 100644 drivers/video/cmdmode_display_timing.c create mode 100644 drivers/video/of_cmdmode.c create mode 100644 drivers/video/of_cmdmode_display_timing.c create mode 100644 include/video/cmdmode.h create mode 100644 include/video/cmdmode_display_timing.h
[RFC PATCH 0/2] drm: make drm_get_{connector, encoder}_name thread safe
On Wed, May 14, 2014 at 04:58:18PM +0300, Jani Nikula wrote: > Hi all - > > This series stores connector/encoder names in the relevant structs to > make the name getters thread safe. > > What say you, is the wasted memory too high a price to pay for the > thread safety and implementation simplicity of this approach? I think > making drm_get_connector_name and drm_get_encoder_name return allocated > buffers makes a lot of code really ugly and error prone. I thought we could use dev_set_name(connector->kdev, "foo"). -Chris -- Chris Wilson, Intel Open Source Technology Centre
[Bug 78537] no anisotropic filtering in a native Half-Life 2
https://bugs.freedesktop.org/show_bug.cgi?id=78537 Michel D?nzer changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #6 from Michel D?nzer --- Commit: c5828b0599a5c00ebab488b795c63a21f1dc53cd URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=c5828b0599a5c00ebab488b795c63a21f1dc53cd Author: Michel D?nzer Date: Wed May 14 16:30:33 2014 +0900 radeonsi: Fix anisotropic filtering state setup -- 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/20140514/11dff6c2/attachment-0001.html>
CIK hangs with kernel 3.15, bisected
Crap, any chance you can narrow it down a bit more? I've just tried a piglit quick test on my Bonaire and it seems to work perfectly fine. What hw do you test on? Regards, Christian. Am 13.05.2014 23:21, schrieb Marek Ol??k: > Hi Christian, > > Even though some regressions are fixed by these patches: > > drm/radeon: fix page directory update size estimation > drm/radeon: fix buffer placement under memory pressure v2 > > and indeed, the texelFetch tests no longer hang, there is one more > hang which needs to be fixed. :( All I know is the exact same commit > causes it and it can only be reproduced by running whole piglit with > concurrency enabled. > > My kernel git log: > > * 2ba22c8 - drm/radeon: fix buffer placement under memory pressure v2 > (10 hours ago) > * 3af91e5 - drm/radeon: fix page directory update size estimation (21 > hours ago) > * 6d2f294 - drm/radeon: use normal BOs for the page tables v4 (2 > months ago) > * fa68834 - drm/radeon: further cleanup vm flushing & fencing (2 > months ago) > > fa68834 doesn't hang, but 2ba22c8 hangs, which means 6d2f294 or either > of the two fixes is the first bad commit. > > Marek > > On Fri, May 9, 2014 at 8:03 PM, Marek Ol??k wrote: >> Hi Christian, >> >> This commit which first appeared in 3.15-rc1 causes hangs on Bonaire: >> >> commit 6d2f2944e95e504a7d33385eeeb9bb7fcca72592 >> Author: Christian K?nig >> Date: Thu Feb 20 13:42:17 2014 +0100 >> >> drm/radeon: use normal BOs for the page tables v4 >> >> No need to make it more complicated than necessary, >> just allocate the page tables as normal BO and >> flush whenever the address change. >> >> v2: update comments and function name >> v3: squash bug fixes, page directory and tables patch >> v4: rebased on Mareks changes >> >> Signed-off-by: Christian K?nig >> >> >> Reverting the commit gives me a lot of merge conflicts. >> >> The simplest way to reproduce the hangs is to run piglit with these >> parameters: >> -t texelFetch.fs >> >> Some of the tests allocate a lot of MSAA textures and the tests also >> run in parallel, which creates a lot of memory pressure and probably >> causes buffer evictions. >> >> Any idea what is wrong with it? >> >> Thanks, >> >> Marek
[Bug 78669] [r600g with -O3] layered-rendering/clear-color-all-types 3d single_level fails
https://bugs.freedesktop.org/show_bug.cgi?id=78669 --- Comment #4 from David Heidelberger (okias) --- it's random with -O3 or just random? if you want some more testing on 6550D, let me know -- 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/20140514/a5d3d309/attachment.html>
[Bug 75992] Display freezes & corruption with an r7 260x on 3.14-rc6
https://bugs.freedesktop.org/show_bug.cgi?id=75992 --- Comment #56 from Alexander Tsoy --- (In reply to comment #55) Without commit [1] new microcode (BONAIRE_mc2.bin) is not loaded. This commit is currently included only in >=3.15-rc2 [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=277babc374f6ecab6af182554f5d9f35a7768755 -- 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/20140514/f6c83e47/attachment-0001.html>
[PATCH 2/2] drm/radeon: fix buffer placement under memory pressure v2
Am 13.05.2014 21:47, schrieb Marek Ol??k: > For the patch: > > Reviewed-by: Marek Ol??k > > It would be clearer if alt_domain was renamed to allowed_domains. Yeah, already had the same idea. Going to rename "domain" to "prefered_domains" and "alt_domain" to "allowed_domains" for 3.16. Thanks, Christian. > > Marek > > On Mon, May 12, 2014 at 3:30 PM, Christian K?nig > wrote: >> From: Christian K?nig >> >> Some buffers (UVD/VM page tables) must be placed in VRAM, >> but the byte restriction for moving buffers didn't took this >> into account. >> >> v2: keep closer to the original code >> >> Signed-off-by: Christian K?nig >> --- >> drivers/gpu/drm/radeon/radeon_object.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/radeon/radeon_object.c >> b/drivers/gpu/drm/radeon/radeon_object.c >> index 72705fb..4faa4d6 100644 >> --- a/drivers/gpu/drm/radeon/radeon_object.c >> +++ b/drivers/gpu/drm/radeon/radeon_object.c >> @@ -458,7 +458,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, >> * into account. We don't want to disallow buffer >> moves >> * completely. >> */ >> - if (current_domain != RADEON_GEM_DOMAIN_CPU && >> + if ((lobj->alt_domain & current_domain) != 0 && >> (domain & current_domain) == 0 && /* will be >> moved */ >> bytes_moved > bytes_moved_threshold) { >> /* don't move it */ >> -- >> 1.9.1 >> >> ___ >> dri-devel mailing list >> dri-devel at lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Intel-gfx] [PATCH] drm,drm/i915: Export cmdline mode parsing
On Tue, 13 May 2014, Chris Wilson wrote: > i915.ko has a custom fbdev initialisation routine that aims to preserve > the current mode set by the BIOS, unless overruled by the user. The > user's wishes are determined by what, if any, mode is specified on the > command line (via the video= parameter). However, that command line mode > is first parsed by drm_fb_helper_initial_config() which is called after > i915.ko's custom initial_config() as a fallback method. So in order for > us to honour it, we need to export the routine out of the helper and > call it first. Is this an answer to https://bugs.freedesktop.org/show_bug.cgi?id=73154? Jani. > > Signed-off-by: Chris Wilson > Cc: Jesse Barnes > Cc: Ville Syrj?l? > Cc: Daniel Vetter > --- > drivers/gpu/drm/drm_crtc.c | 58 > ++ > drivers/gpu/drm/drm_fb_helper.c| 47 +++--- > drivers/gpu/drm/i915/intel_fbdev.c | 2 ++ > include/drm/drm_crtc.h | 3 +- > 4 files changed, 66 insertions(+), 44 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 656788a9bf4b..853804277921 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -852,6 +852,64 @@ int drm_connector_init(struct drm_device *dev, > EXPORT_SYMBOL(drm_connector_init); > > /** > + * drm_connector_get_cmdline_mode - reads the user's cmdline mode > + * @connector: connector to quwery > + * @mode: returned mode > + * > + * The kernel supports per-connector configration of its consoles through > + * use of the video= parameter. This function parses that option and > + * extracts the user's specified mode (or enable/disable status) for a > + * particular connector. This is typically only used during the early fbdev > + * setup. > + */ > +void drm_connector_get_cmdline_mode(struct drm_connector *connector, > + struct drm_cmdline_mode *mode) > +{ > + char *option = NULL; > + > + if (mode->specified) > + return; > + > + if (fb_get_options(drm_get_connector_name(connector), )) > + return; > + > + if (!drm_mode_parse_command_line_for_connector(option, > +connector, > +mode)) > + return; > + > + if (mode->force) { > + const char *s; > + > + switch (mode->force) { > + case DRM_FORCE_OFF: > + s = "OFF"; > + break; > + case DRM_FORCE_ON_DIGITAL: > + s = "ON - dig"; > + break; > + default: > + case DRM_FORCE_ON: > + s = "ON"; > + break; > + } > + > + DRM_INFO("forcing %s connector %s\n", > + drm_get_connector_name(connector), s); > + connector->force = mode->force; > + } > + > + DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", > + drm_get_connector_name(connector), > + mode->xres, mode->yres, > + mode->refresh_specified ? mode->refresh : 60, > + mode->rb ? " reduced blanking" : "", > + mode->margins ? " with margins" : "", > + mode->interlace ? " interlaced" : ""); > +} > +EXPORT_SYMBOL(drm_connector_get_cmdline_mode); > + > +/** > * drm_connector_cleanup - cleans up an initialised connector > * @connector: connector to cleanup > * > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c > index e95ed5805f07..f61a6c02101c 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -107,55 +107,16 @@ EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); > > static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) > { > - struct drm_fb_helper_connector *fb_helper_conn; > int i; > > for (i = 0; i < fb_helper->connector_count; i++) { > - struct drm_cmdline_mode *mode; > - struct drm_connector *connector; > - char *option = NULL; > + struct drm_fb_helper_connector *fb_helper_conn; > > fb_helper_conn = fb_helper->connector_info[i]; > - connector = fb_helper_conn->connector; > - mode = _helper_conn->cmdline_mode; > - > - /* do something on return - turn off connector maybe */ > - if (fb_get_options(drm_get_connector_name(connector), )) > - continue; > - > - if (drm_mode_parse_command_line_for_connector(option, > - connector, > - mode)) { > - if (mode->force) { > - const char *s; > -
[Bug 75992] Display freezes & corruption with an r7 260x on 3.14-rc6
https://bugs.freedesktop.org/show_bug.cgi?id=75992 --- Comment #55 from nicolas.laplante at gmail.com --- Regression on 3.14.3. Screen corruption is back. Using Radeon microcode from 2014-04-30. dmesg is full of messages like this: [ 658.696174] radeon :01:00.0: GPU fault detected: 147 0x0ee20808 [ 658.696175] radeon :01:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x [ 658.696177] radeon :01:00.0: VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x [ 658.696178] VM fault (0x00, vmid 0) at page 0, read from '' (0x) (0) -- 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/20140514/31ca8d1c/attachment.html>
[Intel-gfx] [PATCH 09/10] i915: add DP 1.2 MST support (v0.3)
On Wed, May 14, 2014 at 08:05:11AM +0200, David Herrmann wrote: > Hi > > On Wed, May 14, 2014 at 2:03 AM, Dave Airlie wrote: > > Since any objects you get with find are only valid under mode_config.mutex, > > yes some drivers mess this up, but they should be fixed. > > Didn't know that we have such a rule. Then it's fine, of course. The > page-flip code is what worried me, but drivers ought to cancel that > when destroying connectors, anyway. i915 cancels/stalls for any pageflips when we switch off the crtc, so I think we should be fine. And the above rule is for all modeset objects except framebuffers, since those are separately protected with refcounting and you don't even need the big mode_config mutex to do the idr lookup. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
[PATCH v2 4/7] drivers/base: Add interface framework
On Wed, May 14, 2014 at 04:37:19PM +0200, Daniel Vetter wrote: > On Tue, May 13, 2014 at 05:32:15PM -0700, Greg Kroah-Hartman wrote: > > On Tue, May 13, 2014 at 07:57:13PM +0200, Daniel Vetter wrote: > > > On Tue, May 13, 2014 at 05:30:47PM +0200, Thierry Reding wrote: > > > > From: Thierry Reding > > > > > > > > Some drivers, such as graphics drivers in the DRM subsystem, do not have > > > > a real device that they can bind to. They are often composed of several > > > > devices, each having their own driver. The master/component framework > > > > can be used in these situations to collect the devices pertaining to one > > > > logical device, wait until all of them have registered and then bind > > > > them all at once. > > > > > > > > For some situations this is only a partial solution. An implementation > > > > of a master still needs to be registered with the system somehow. Many > > > > drivers currently resort to creating a dummy device that a driver can > > > > bind to and register the master against. This is problematic since it > > > > requires (and presumes) knowledge about the system within drivers. > > > > > > > > Furthermore there are setups where a suitable device already exists, but > > > > is already bound to a driver. For example, on Tegra the following device > > > > tree extract (simplified) represents the host1x device along with child > > > > devices: > > > > > > > > host1x { > > > > display-controller { > > > > ... > > > > }; > > > > > > > > display-controller { > > > > ... > > > > }; > > > > > > > > hdmi { > > > > ... > > > > }; > > > > > > > > dsi { > > > > ... > > > > }; > > > > > > > > csi { > > > > ... > > > > }; > > > > > > > > video-input { > > > > ... > > > > }; > > > > }; > > > > > > > > Each of the child devices is in turn a client of host1x, in that it can > > > > request resources (command stream DMA channels and syncpoints) from it. > > > > To implement the DMA channel and syncpoint infrastructure, host1x comes > > > > with its own driver. Children are implemented in separate drivers. In > > > > Linux this set of devices would be exposed by DRM and V4L2 drivers. > > > > > > > > However, neither the DRM nor the V4L2 drivers have a single device that > > > > they can bind to. The DRM device is composed of the display controllers > > > > and the various output devices, whereas the V4L2 device is composed of > > > > one or more video input devices. > > > > > > > > This patch introduces the concept of an interface and drivers that can > > > > bind to a given interface. An interface can be exposed by any device, > > > > and interface drivers can bind to these interfaces. Multiple drivers can > > > > bind against a single interface. When a device is removed, interfaces > > > > exposed by it will be removed as well, thereby removing the drivers that > > > > were bound to those interfaces. > > > > > > > > In the example above, the host1x device would expose the "tegra-host1x" > > > > interface. DRM and V4L2 drivers can then bind to that interface and > > > > instantiate the respective subsystem objects from there. > > > > > > > > Signed-off-by: Thierry Reding > > > > --- > > > > Note that I'd like to merge this through the Tegra DRM tree so that the > > > > changes to the Tegra DRM driver later in this series can be merged at > > > > the same time and are not delayed for another release cycle. > > > > > > > > In particular that means that I'm looking for an Acked-by from Greg. > > > > > > > > drivers/base/Makefile | 2 +- > > > > drivers/base/interface.c | 186 > > > > ++ > > > > include/linux/interface.h | 40 ++ > > > > 3 files changed, 227 insertions(+), 1 deletion(-) > > > > create mode 100644 drivers/base/interface.c > > > > create mode 100644 include/linux/interface.h > > > > > > Hm, this interface stuff smells like bus drivers light. Should we instead > > > have a pile of helpers to make creating new buses with match methods more > > > trivial? There's a fairly big pile of small use-cases where this might be > > > useful. In your case here all the host1x children would sit on a host1x > > > bus. Admittedly I didn't look into the details. > > > > I have no problem adding such "bus-light" functions, to make it easier > > to create and implement a bus in the driver core, as I know it's really > > heavy. That's been on my "todo" list for over a decade now... > > Hm, I've victimized^Wvolunteered a few internal people to look into a > hdmi/dp sink bus type of thing so that we can move away from all those > ad-hoc hacks currently used to coordinate
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 --- Comment #5 from Felix Homann --- OK, 3.14.x kernels will resume fine if I suspend before the screen freezes. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH 09/10] i915: add DP 1.2 MST support (v0.3)
> > So we leak all dynamically created objects? There's no > kfree(intel_connector) here and we cannot add it because > drm_mode_object_find() is not ref-counted. So we keep the connector in > the mode_group and wait until the final drm_mode_config_cleanup()? But > drm_connector_cleanup() already removes the connector from the > mode-group, so we eventually leak the object. > Seems like freeing it should be fine, it was just an oversight, Since any objects you get with find are only valid under mode_config.mutex, yes some drivers mess this up, but they should be fixed. Dave.
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 --- Comment #4 from Felix Homann --- I'll do (*). But bisecting will not be that easy as the R7 260x is mostly broken on 3.14.x anyway, see https://bugzilla.redhat.com/show_bug.cgi?id=1094153 and the corresponding report on freedesktop.org. The bisect result might get wrong due to the overall 3.14.x issues. (*) I probably won't find any time for a bisect session before May 26. -- You are receiving this mail because: You are watching the assignee of the bug.
[Intel-gfx] [PATCH] drm,drm/i915: Export cmdline mode parsing
On Wed, May 14, 2014 at 11:31:47AM +0300, Jani Nikula wrote: > On Tue, 13 May 2014, Chris Wilson wrote: > > i915.ko has a custom fbdev initialisation routine that aims to preserve > > the current mode set by the BIOS, unless overruled by the user. The > > user's wishes are determined by what, if any, mode is specified on the > > command line (via the video= parameter). However, that command line mode > > is first parsed by drm_fb_helper_initial_config() which is called after > > i915.ko's custom initial_config() as a fallback method. So in order for > > us to honour it, we need to export the routine out of the helper and > > call it first. > > Is this an answer to https://bugs.freedesktop.org/show_bug.cgi?id=73154? Yes. Not in this patch, but we can also use in that case as well. -Chris -- Chris Wilson, Intel Open Source Technology Centre
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 --- Comment #3 from Christian K?nig --- Then please bisect what commit broke it for you. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH] drm: Missed clflushopt in drm_clflush_virt_range
With this commit: 2a0788dc9bc4 x86: Use clflushopt in drm_clflush_virt_range If clflushopt is available on the system, we use it instead of clflush in drm_clflush_virt_range. There were two calls to clflush in this function, but only one was changed to clflushopt. This patch changes the other clflush call to clflushopt. Signed-off-by: Ross Zwisler Reported-by: Matthew Wilcox Cc: David Airlie Cc: dri-devel at lists.freedesktop.org Cc: H Peter Anvin Cc: Ingo Molnar Cc: Thomas Gleixner --- drivers/gpu/drm/drm_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 534cb89..041b73b 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -138,7 +138,7 @@ drm_clflush_virt_range(char *addr, unsigned long length) char *end = addr + length; mb(); for (; addr < end; addr += boot_cpu_data.x86_clflush_size) - clflush(addr); + clflushopt(addr); clflushopt(end - 1); mb(); return; -- 1.9.0
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 --- Comment #2 from Felix Homann --- The proposed patch https://bugzilla.kernel.org/attachment.cgi?id=135881 doesn't fix the issue on my machine. -- You are receiving this mail because: You are watching the assignee of the bug.
[PATCH] Documentation/dma-buf-sharing.txt: update API descriptions
Thank you for advice. I will send a fixed patch soon. > -Original Message- > From: Thierry Reding [mailto:thierry.reding at gmail.com] > Sent: Tuesday, May 13, 2014 5:45 PM > To: gioh.kim > Cc: Sumit Semwal; Randy Dunlap; linux-media at vger.kernel.org; dri-devel at > lists.freedesktop.org; linux- > doc at vger.kernel.org; linux-kernel at vger.kernel.org; gunho.lee at lge.com > Subject: Re: [PATCH] Documentation/dma-buf-sharing.txt: update API > descriptions > > On Mon, May 12, 2014 at 08:48:12PM +0900, gioh.kim wrote: > > From: "gioh.kim" > > It might be good to fix your setup to make this be the same as the name > and email used in the Signed-off-by line below. > > > update some descriptions for API arguments and descriptions. > > Nit: "Update" since it's the beginning of a sentence. > > > Signed-off-by: Gioh Kim > > --- > > Documentation/dma-buf-sharing.txt | 10 ++ > > 1 file changed, 6 insertions(+), 4 deletions(-) > > > > diff --git a/Documentation/dma-buf-sharing.txt > > b/Documentation/dma-buf-sharing.txt > > index 505e711..1ea89b8 100644 > > --- a/Documentation/dma-buf-sharing.txt > > +++ b/Documentation/dma-buf-sharing.txt > > @@ -56,7 +56,7 @@ The dma_buf buffer sharing API usage contains the > > following steps: > > size_t size, int flags, > > const char *exp_name) > > > > - If this succeeds, dma_buf_export allocates a dma_buf structure, and > > returns a > > + If this succeeds, dma_buf_export_named allocates a dma_buf structure, > > and returns a > > Perhaps reformat this so that the lines don't exceed 80 characters? > > > pointer to the same. It also associates an anonymous file with this > > buffer, > > so it can be exported. On failure to allocate the dma_buf object, it > > returns > > NULL. > > @@ -66,7 +66,7 @@ The dma_buf buffer sharing API usage contains the > > following steps: > > > > Exporting modules which do not wish to provide any specific name may > > use the > > helper define 'dma_buf_export()', with the same arguments as above, but > > - without the last argument; a __FILE__ pre-processor directive will be > > + without the last argument; a KBUILD_MODNAME pre-processor directive > > will be > > inserted in place of 'exp_name' instead. > > This was already fixed in commit 2e33def0339c (dma-buf: update exp_name > when using dma_buf_export()). Perhaps you should rebase this patch on > top of the latest linux-next. > > Otherwise looks good. > > Thierry
[PATCH] Documentation/dma-buf-sharing.txt: update API descriptions
Update some descriptions for API arguments and descriptions. Signed-off-by: Gioh Kim --- Documentation/dma-buf-sharing.txt | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index 505e711..aadd901 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt @@ -56,10 +56,10 @@ The dma_buf buffer sharing API usage contains the following steps: size_t size, int flags, const char *exp_name) - If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a - pointer to the same. It also associates an anonymous file with this buffer, - so it can be exported. On failure to allocate the dma_buf object, it returns - NULL. + If this succeeds, dma_buf_export_named allocates a dma_buf structure, and + returns a pointer to the same. It also associates an anonymous file with this + buffer, so it can be exported. On failure to allocate the dma_buf object, + it returns NULL. 'exp_name' is the name of exporter - to facilitate information while debugging. @@ -76,7 +76,7 @@ The dma_buf buffer sharing API usage contains the following steps: drivers and/or processes. Interface: - int dma_buf_fd(struct dma_buf *dmabuf) + int dma_buf_fd(struct dma_buf *dmabuf, int flags) This API installs an fd for the anonymous file associated with this buffer; returns either 'fd', or error. @@ -157,7 +157,9 @@ to request use of buffer for allocation. "dma_buf->ops->" indirection from the users of this interface. In struct dma_buf_ops, unmap_dma_buf is defined as - void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *); + void (*unmap_dma_buf)(struct dma_buf_attachment *, +struct sg_table *, +enum dma_data_direction); unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like map_dma_buf, this API also must be implemented by the exporter. -- 1.7.9.5
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 Christian K?nig changed: What|Removed |Added CC||deathsimple at vodafone.de --- Comment #1 from Christian K?nig --- Sounds like a duplicate of https://bugzilla.kernel.org/show_bug.cgi?id=75651 -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 76131] Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 Felix Homann changed: What|Removed |Added CC||linuxaudio at showlabor.de Regression|No |Yes -- You are receiving this mail because: You are watching the assignee of the bug.
[Bug 76131] New: Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi)
https://bugzilla.kernel.org/show_bug.cgi?id=76131 Bug ID: 76131 Summary: Regression: Wake up after suspend broken with Radeon R7 260x (BONAIRE, radeonsi) Product: Drivers Version: 2.5 Kernel Version: 3.15.0-rc5+ (commit 14186fea0cb06bc43181ce239efe0df6f1af260a) 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: linuxaudio at showlabor.de Regression: No My sytem won't wake up (properly) after suspend when using a Radeon R7 260x: The screen stays black and the system cannot be reached over ssh. Using the onboard Intel graphics adapter the system will wake up properly with the same kernel. This has not been a problem with 3.13.x kernels. I have not tested with 3.14 kernels. I am using the MESA driver, the BONAIRE_mc2.bin firmware is present. Overall performance of the driver is great. The kernel I'm using is commit 14186fea0cb06bc43181ce239efe0df6f1af260a from Linus' tree. Here's the output of ver_linux: Linux yerbouti.fritz.box 3.15.0-rc5+ #1 SMP Tue May 13 16:34:21 CEST 2014 x86_64 x86_64 x86_64 GNU/Linux Gnu C 4.8.2 Gnu make 3.82 binutils 2.23.2 util-linux 2.24.2 mount assert module-init-tools 15 e2fsprogs 1.42.8 jfsutils 1.1.15 reiserfsprogs 3.6.21 pcmciautils018 PPP2.4.5 Linux C Library2.18 Dynamic linker (ldd) 2.18 Procps 3.3.8 Net-tools 2.10-alpha Kbd1.15.5 oprofile 0.9.9 Sh-utils 8.21 wireless-tools 29 Modules Loaded rfcomm ipt_MASQUERADE fuse xt_CHECKSUM tun nf_conntrack_netbios_ns nf_conntrack_broadcast ip6t_rpfilter ip6t_REJECT xt_conntrack cfg80211 ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw bnep it87 hwmon_vid vfat fat btusb bluetooth 6lowpan_iphc rfkill iTCO_wdt iTCO_vendor_support uas usb_storage x86_pkg_temp_thermal coretemp kvm_intel kvm bcache crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel snd_hda_codec_via snd_hda_codec_generic microcode snd_hda_codec_hdmi serio_raw snd_hda_intel pcspkr snd_hda_controller i2c_i801 snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm mei_me tpm_infineon mei tpm_tis tpm video snd_timer snd lpc_ich mfd_core shpchp soundcore binfmt_misc radeon btrfs xor raid1 i2c_algo_bit drm_kms_helper ttm raid6_pq drm firewire_ohci alx firewire_core r8169 i2c_core mii crc_itu_t mdio -- You are receiving this mail because: You are watching the assignee of the bug.