Re: [PATCH v3 18/50] drm/omap: dss: Cleanup DSS ports on initialisation failure

2019-12-16 Thread Tomi Valkeinen

On 11/12/2019 00:57, Laurent Pinchart wrote:

When the DSS initialises its output DPI and SDI ports, failures don't
clean up previous successfully initialised ports. This can lead to
resource leak or memory corruption. Fix it.

Reported-by: Hans Verkuil 
Signed-off-by: Laurent Pinchart 
---
  drivers/gpu/drm/omapdrm/dss/dss.c | 43 +++
  1 file changed, 26 insertions(+), 17 deletions(-)


Reviewed-by: Tomi Valkeinen 

 Tomi

--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 1/1] drm/sun4i: hdmi: Check for null pointer before cleanup

2019-12-16 Thread Uwe Kleine-König
On Mon, Dec 16, 2019 at 04:43:48PM +0200, Stefan Mavrodiev wrote:
> It's possible hdmi->connector and hdmi->encoder divices to be NULL.

The wording is broken and s/divices/devices/. I'd write:

It's possible that the parent devices of the connector and/or
encoder are NULL. This makes drm_connector_cleanup and
drm_encoder_cleanup respectively trigger a NULL pointer
exeception:

<...log here...>

This is reproducible by

<...receipt here...>

So add a check for NULL before calling these functions.

Of course this doesn't address the reservations by Maxime.

Best regards
Uwe

-- 
Pengutronix e.K.   | Uwe Kleine-König|
Industrial Linux Solutions | https://www.pengutronix.de/ |
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v11 00/25] mm/gup: track dma-pinned pages: FOLL_PIN

2019-12-16 Thread Jan Kara
Hi!

On Mon 16-12-19 14:25:12, John Hubbard wrote:
> Hi,
> 
> This implements an API naming change (put_user_page*() -->
> unpin_user_page*()), and also implements tracking of FOLL_PIN pages. It
> extends that tracking to a few select subsystems. More subsystems will
> be added in follow up work.

Just a note for Andrew and others watching this series: At this point I'm fine
with the series so if someone still has some review feedback or wants to
check the series, now is the right time. Otherwise I think Andrew can push
the series to MM tree so that it will get wider testing exposure and is
prepared for the next merge window.

Honza
-- 
Jan Kara 
SUSE Labs, CR
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v11 23/25] mm/gup: track FOLL_PIN pages

2019-12-16 Thread Jan Kara
On Mon 16-12-19 14:18:59, John Hubbard wrote:
> On 12/16/19 4:53 AM, Jan Kara wrote:
> > With this fixed, the patch looks good to me so you can then add:
> > 
> > Reviewed-by: Jan Kara 
> > 
> > Honza
> > 
> 
> btw, thanks for the thorough review of this critical patch (and for your
> patience with my mistakes). I really appreciate it, and this patchset would
> not have made it this far without your detailed help and explanations.

You're welcome! I'd also like to thank you for persistently driving this
series :)

Honza
-- 
Jan Kara 
SUSE Labs, CR
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3 17/50] drm/omap: Fix possible object reference leak

2019-12-16 Thread Tomi Valkeinen

On 11/12/2019 00:57, Laurent Pinchart wrote:

From: Wen Yang 

The call to of_find_matching_node returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

Detected by coccinelle with the following warnings:
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c:212:2-8: ERROR: missing 
of_node_put; acquired a node pointer with refcount incremented on line 209, but 
without a corresponding object release within this function.
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c:237:1-7: ERROR: missing 
of_node_put; acquired a node pointer with refcount incremented on line 209, but 
without a corresponding object release within this function.

Signed-off-by: Wen Yang 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Mukesh Ojha 
Signed-off-by: Laurent Pinchart 
---
  drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

Reviewed-by: Tomi Valkeinen 

 Tomi

--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH RESEND 2/4] drm: bridge: anx7688: Add anx7688 bridge driver support.

2019-12-16 Thread Nicolas Boichat
Hi,

On Tue, Dec 17, 2019 at 8:52 AM Laurent Pinchart
 wrote:
>
> Hi Nicolas,
>
> On Tue, Dec 17, 2019 at 08:40:51AM +0800, Nicolas Boichat wrote:
> > (Brilliant, I managed to accidentally send the email below, and send
> > it as HTML, sorry about that... ASCII art in gmail is hard ,-(
>
> No worries. I have been told it's indeed painful.
>
> > Take 2:)
> >
> > Hi Laurent,
> >
> > > On Tue, Dec 17, 2019 at 12:39 AM Laurent Pinchart wrote:
> > > > On Mon, Dec 16, 2019 at 06:19:24PM +0800, Nicolas Boichat wrote:
> > > > > On Mon, Dec 16, 2019 at 4:46 PM Hsin-Yi Wang wrote:
> > > > > > On Sat, Dec 14, 2019 at 6:38 AM Laurent Pinchart wrote:
> > > > > > > On Wed, Dec 11, 2019 at 02:19:09PM +0800, Hsin-Yi Wang wrote:
> > > > > > > > From: Nicolas Boichat 
> > > > > > > >
> > > > > > > > ANX7688 is a HDMI to DP converter (as well as USB-C port 
> > > > > > > > controller),
> > > > > > > > that has an internal microcontroller.
> > > > > > > >
> > > > > > > > The only reason a Linux kernel driver is necessary is to reject
> > > > > > > > resolutions that require more bandwidth than what is available 
> > > > > > > > on
> > > > > > > > the DP side. DP bandwidth and lane count are reported by the 
> > > > > > > > bridge
> > > > > > > > via 2 registers on I2C.
> > > > > > >
> > > > > > > How about power, doesn't this chip have power supplies that 
> > > > > > > potentially
> > > > > > > need to be controlled ?
> > > > > > >
> > > > > > Ideally we should add power supplies as well, but the power is
> > > > > > supplied by ec in mt8173 oak board. And we only have this board can
> > > > > > test this driver. If we add power supplies in driver we can't test 
> > > > > > it.
> > > > >
> > > > > To clarify a bit more, this is because this chip is actually a
> > > > > TCPC+mux+HDMI=>DP converter
> > > > > (https://www.analogix.com/en/products/convertersbridges/anx7688). In
> > > > > Chromebook architecture, TCPC+mux is controlled by the EC (including
> > > > > power and other control pins), and the only reason we need a driver
> > > > > for the HDMI=>DP converter is to get the number of lanes on the DP
> > > > > side and filter out resolutions. Also, the converter is on a different
> > > > > I2C address and it could almost be considered as a separate device.
> > > > >
> > > > > (of course we could write a kernel driver for the TCPC+mux but we'll
> > > > > leave that to others if there's ever a board that is built with the
> > > > > TCPC part connected to the AP)
> > > >
> > > > Is the mux the one that is handled through a gpio-mux driver in this
> > > > series, or a different mux ?
> > >
> >
> > It's a different mux: it's the usual USB-C mux that takes in USB 3.0
> > and DP (internally converted from HDMI), and decides which 2 lanes to
> > use for each (4 lanes in total, but DP can only take 2 with this
> > converter), and flip if necessary. This is all controlled by the EC
> > (like on most other Chromebooks), so this is transparent to the kernel
> > on this hardware.
> >
> > > > It would really, really help if you could
> > > > show a block diagram of the related hardware (including the EC), as this
> > > > is quite confusing. With every e-mail exchanged there's a bit more
> > > > information that change my understanding of the issue, I can't really
> > > > provide guidance without a full overview.
> >
> > https://lkml.org/lkml/2019/12/9/548 that you drew is accurate for the
> > display part of the problem.
> >
> > You can just add a USB3 connection to the above (there's also I2C
> > interface to the EC of course to control the TCPC/mux aspect of it,
> > but that's on different I2C addresses). Something like this:
> >
> >   +---+
> >  +-+ +--+/--> | HDMI  |
> >  | MT8173  |  HDMI   |   -->| --/ | Connector |
> >  |  HDMI   | --> |--/   | +---+
> >  | Encoder | |->| --\ +---+  +---+
> >  +-+ +--+\--> | ANX7688   | ---> | USB-C |
> >   | Bridge|  | Connector |
> >   USB3--> | + mux |  |   |
> >   +---+  +---+
> >  ^ ^
> >(I2C) | | (I2C)
> >MT8173 (DP lane count/bw readback) -- + + -- EC (TCPC+mux control)
> >
> > Power is also fully controlled by the EC.
>
> Could I ask you to also explain how the HDMI mux is controlled,

Priority to HDMI. If the HDMI is connected (looking at its HPD
signal), then the HDMI signals are routed to HDMI connector. Else HDMI
is routed to ANX7688/USB-C.

> and
> where the HPD-related signals for the HDMI connector and USB-C connector
> are routed to ?

HPD is also muxed by the mux, between the 2 inputs.
(http://www.ti.com/lit/ds/symlink/ts3dv642.pdf, if you are curious,
9.2.3 is basically how things are 

Re: linux-next: Tree for Dec 16 (drm_panel & intel_panel)

2019-12-16 Thread Sam Ravnborg
Hi Randy.

On Mon, Dec 16, 2019 at 08:25:11AM -0800, Randy Dunlap wrote:
> On 12/15/19 9:22 PM, Stephen Rothwell wrote:
> > Hi all,
> > 
> > Changes since 20191213:
> > 
> 
> on x86_64:
> 
> ld: drivers/gpu/drm/drm_panel.o: in function `drm_panel_of_backlight':
> (.text+0x2ee): undefined reference to `devm_of_find_backlight'
> 
> ld: drivers/gpu/drm/i915/display/intel_panel.o: in function 
> `intel_backlight_device_register':
> intel_panel.c:(.text+0x593e): undefined reference to 
> `backlight_device_register'
> ld: drivers/gpu/drm/i915/display/intel_panel.o: in function 
> `intel_backlight_device_unregister':
> intel_panel.c:(.text+0x5a04): undefined reference to 
> `backlight_device_unregister'
> 
> CONFIG_DRM_PANEL=y
> CONFIG_BACKLIGHT_CLASS_DEVICE=m
> CONFIG_DRM_I915=y
> 
> Full randconfig file is attached.

Can you please verify if you have:
907aa265fde6589b8059dc51649c6d1f49ade2f3
("drm/drm_panel: fix EXPORT of drm_panel_of_backlight")

This commit is supposed to fix it.

Sam

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3] drm: Add getfb2 ioctl

2019-12-16 Thread Juston Li
From: Daniel Stone 

getfb2 allows us to pass multiple planes and modifiers, just like addfb2
over addfb.

Changes since v2:
 - add privilege checks from getfb1 since handles should only be
   returned to master/root

Changes since v1:
 - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID
 - update ioctl number

Signed-off-by: Daniel Stone 
Signed-off-by: Juston Li 
Acked-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_internal.h |   2 +
 drivers/gpu/drm/drm_framebuffer.c   | 122 
 drivers/gpu/drm/drm_ioctl.c |   1 +
 include/uapi/drm/drm.h  |   2 +
 4 files changed, 127 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc_internal.h 
b/drivers/gpu/drm/drm_crtc_internal.h
index c7d5e4c21423..16f2413403aa 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
 int drm_mode_getfb(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
 
diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 57564318ceea..57ac94ce9b9e 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -548,7 +549,128 @@ int drm_mode_getfb(struct drm_device *dev,
 
 out:
drm_framebuffer_put(fb);
+   return ret;
+}
+
+/**
+ * drm_mode_getfb2 - get extended FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+   struct drm_mode_fb_cmd2 *r = data;
+   struct drm_framebuffer *fb;
+   unsigned int i;
+   int ret;
+
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   return -EINVAL;
+
+   fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
+   if (!fb)
+   return -ENOENT;
+
+   /* For multi-plane framebuffers, we require the driver to place the
+* GEM objects directly in the drm_framebuffer. For single-plane
+* framebuffers, we can fall back to create_handle.
+*/
+   if (!fb->obj[0] &&
+   (fb->format->num_planes > 1 || !fb->funcs->create_handle)) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   r->height = fb->height;
+   r->width = fb->width;
+   r->pixel_format = fb->format->format;
+
+   r->flags = 0;
+   if (dev->mode_config.allow_fb_modifiers)
+   r->flags |= DRM_MODE_FB_MODIFIERS;
+
+   for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+   r->handles[i] = 0;
+   r->pitches[i] = 0;
+   r->offsets[i] = 0;
+   r->modifier[i] = 0;
+   }
+
+   for (i = 0; i < fb->format->num_planes; i++) {
+   r->pitches[i] = fb->pitches[i];
+   r->offsets[i] = fb->offsets[i];
+   if (dev->mode_config.allow_fb_modifiers)
+   r->modifier[i] = fb->modifier;
+   }
+
+   /* GET_FB2() is an unprivileged ioctl so we must not return a
+* buffer-handle to non master/root processes! To match GET_FB()
+* just return invalid handles (0) for non masters/root
+* rather than making GET_FB2() privileged.
+*/
+   if (!drm_is_current_master(file_priv) && !capable(CAP_SYS_ADMIN)) {
+   ret = 0;
+   goto out;
+   }
 
+   for (i = 0; i < fb->format->num_planes; i++) {
+   int j;
+
+   /* If we reuse the same object for multiple planes, also
+* return the same handle.
+*/
+   for (j = 0; j < i; j++) {
+   if (fb->obj[i] == fb->obj[j]) {
+   r->handles[i] = r->handles[j];
+   break;
+   }
+   }
+
+   if (r->handles[i])
+   continue;
+
+   if (fb->obj[i]) {
+   ret = drm_gem_handle_create(file_priv, fb->obj[i],
+   >handles[i]);
+   } else {
+   WARN_ON(i > 0);
+   ret = fb->funcs->create_handle(fb, file_priv,
+  >handles[i]);
+   }
+
+  

Re: [PATCH] drm/mediatek: reduce the hbp and hfp for phy timing

2019-12-16 Thread CK Hu
Hi,

On Mon, 2019-12-16 at 11:30 +0100, Enric Balletbo Serra wrote:
> Hi all,
> 
> Missatge de Hsin-Yi Wang  del dia dl., 16 de des.
> 2019 a les 3:42:
> >
> > On Fri, Dec 13, 2019 at 9:52 AM Jitao Shi  wrote:
> > >
> > > There are some extra data transfer in dsi.
> > > ex. LPX, hs_prepare, hs_zero, hs_exit and the sof/eof of dsi packet.
> > > This signal will enlarge the line time. So the real frame on dsi bus
> > > will be lower than calc by video timing.
> > >
> > > So dsi driver reduces the hbp and hfp to keep the line time.
> > >
> 
> This patch not only reduces the hbp and hfp for phy timing, it also
> fixes an actual issue for MT8173 boards (i.e. Acer Chromebook R 13)
> which is that the display is not working anymore (black screen) after
> 7a5bc4e22ecfd74dc3662342beaa909770a3b786 "drm/mediatek: change the dsi
> phytiming calculate method". So the patch is probably missing a:
> 
> Fixes: 7a5bc4e22ecf ("drm/mediatek: change the dsi phytiming calculate 
> method")
> 
> And would be nice to have this patch applied for 5.5
> 
> > > Signed-off-by: Jitao Shi 
> > Tested-by: Hsin-Yi Wang 
> 
> If it helps, you can also add my
> 
> Tested-by: Enric Balletbo i Serra 
> 
> Thanks,
>  Enric

Applied to mediatek-drm-fixes-5.5 [1], thank you all.

[1]
https://github.com/ckhu-mediatek/linux.git-tags/commits/mediatek-drm-fixes-5.5

Regards,
CK

> 
> > > ---
> >
> > Tested on mt8183 and mt8173
> >
> > ___
> > Linux-mediatek mailing list
> > linux-media...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 05/10] drm/mediatek: plane_state->fb iff plane_state->crtc

2019-12-16 Thread CK Hu
Hi, Daniel:

On Fri, 2019-12-13 at 18:26 +0100, Daniel Vetter wrote:
> Checking both is one too much, so wrap a WARN_ON around it to stope
> the copypasta.

Even though I don't know what is copypasta,

Acked-by: CK Hu 

> 
> Signed-off-by: Daniel Vetter 
> Cc: CK Hu 
> Cc: Philipp Zabel 
> Cc: Matthias Brugger 
> Cc: linux-arm-ker...@lists.infradead.org
> Cc: linux-media...@lists.infradead.org
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_plane.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c 
> b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> index 540ef2faa40a..f0b0325381e0 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> @@ -94,7 +94,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
>   if (!fb)
>   return 0;
>  
> - if (!state->crtc)
> + if (WARN_ON(!state->crtc))
>   return 0;
>  
>   ret = mtk_drm_crtc_plane_check(state->crtc, plane,

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 5/6] drm/mediatek: Convert to use CMA helpers

2019-12-16 Thread Laurent Pinchart
Hi Rob,

On Thu, Oct 24, 2019 at 03:02:57PM +0800, CK Hu wrote:
> On Wed, 2019-10-23 at 17:56 -0500, Rob Herring wrote:
> > On Wed, Oct 23, 2019 at 4:06 PM CK Hu wrote:
> > > On Wed, 2019-10-23 at 12:42 -0500, Rob Herring wrote:
> > > > On Tue, Oct 22, 2019 at 12:07 PM Matthias Brugger wrote:
> > > > > On 21/10/2019 23:45, Rob Herring wrote:
> > > > > > The only reason the Mediatek driver doesn't use the CMA helpers is 
> > > > > > it
> > > > > > sets DMA_ATTR_NO_KERNEL_MAPPING and does a vmap() on demand. Using
> > > > > > vmap() is not even guaranteed to work as DMA buffers may not have a
> > > > > > struct page. Now that the CMA helpers support setting
> > > > > > DMA_ATTR_NO_KERNEL_MAPPING as needed or not, convert Mediatek 
> > > > > > driver to
> > > > > > use CMA helpers.
> > > > > >
> > > > > > Cc: CK Hu 
> > > > > > Cc: Philipp Zabel 
> > > > > > Cc: David Airlie 
> > > > > > Cc: Daniel Vetter 
> > > > > > Cc: Matthias Brugger 
> > > > > > Cc: linux-arm-ker...@lists.infradead.org
> > > > > > Cc: linux-media...@lists.infradead.org
> > > > > > Signed-off-by: Rob Herring 
> > > > > > ---
> > > > >
> > > > > I tested this on my Chromebook with some patches on top of v5.4-rc1 
> > > > > [1], which
> > > > > work. If I add your patches on top of that, the system does not boot 
> > > > > up.
> > > > > Unfortunately I don't have a serial console, so I wasn't able to see 
> > > > > if there is
> > > > > any error message.
> > > >
> > > > Thanks for testing. I'm based on drm-misc-next, but don't see anything
> > > > obvious there that would matter. There are some mmap changes, but I
> > > > think they shouldn't matter.
> > > >
> > > > Did you have fbcon enabled? That may give more clues about where the 
> > > > problem is.
> > >
> > > There are priv->dma_dev for dma device, but it is not drm device. In
> > > mt8173.dtsi [1], there are mmsys device and ovl device, mmsys device is
> > > drm device and ovl device is mmsys's sub device which provide dma
> > > function, so ovl is the priv->dma_dev. I think your patch directly use
> > > drm device for dma operation and this would cause dma function fail.
> > > Please use priv->dma_dev for dma operation.
> > 
> > Right, thanks for catching that. Either we'll need to make CMA GEM
> > object have a struct device ptr or adjust the drm_device.dev to have
> > the necessary DMA setup.
> > 
> > One question though, why do you use CMA when you have an IOMMU? That's
> > not optimal as CMA size may be limited. Or you don't always have an
> > IOMMU?

Please note that the DRM GEM CMA helpers are misnamed, they use the DMA
coherent allocation API, and thus don't use CMA if the device is backed
by an IOMMU. They should really have been named DRM GEM DMA helpers.

> For all upstreamed mediatek SoC, all has IOMMU, so it does not need CMA.
> I think we use CMA just because we refer to other drm driver to
> implement mediatek drm driver and we misused CMA helper function but it
> works. I think we should change to more accurate implementation. If you
> want, you could modify it in this series.
> 

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/nouveau: Add correct turing page kinds

2019-12-16 Thread James Jones
Turing introduced a new simplified page kind
scheme, reducing the number of possible page
kinds from 256 to 16.  It also is the first
NVIDIA GPU in which the highest possible page
kind value is not reserved as an "invalid" page
kind.

To address this, the invalid page kind is made
an explicit property of the MMU HAL, and a new
table of page kinds is added to the tu102 MMU
HAL.

One hardware change not addressed here is that
0x00 is technically no longer a supported page
kind, and pitch surfaces are instead intended to
share the block-linear generic page kind 0x06.
However, because that will be a rather invasive
change to nouveau and 0x00 still works fine in
practice on Turing hardware, addressing this new
behavior is deferred.

Signed-off-by: James Jones 
---
 drivers/gpu/drm/nouveau/include/nvif/if0008.h|  2 +-
 drivers/gpu/drm/nouveau/include/nvif/mmu.h   |  4 ++--
 drivers/gpu/drm/nouveau/nvif/mmu.c   |  1 +
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c  |  3 ++-
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c  |  3 ++-
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c   |  3 ++-
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h   |  8 
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c  | 16 +++-
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c   |  7 +--
 .../gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c   |  6 +++---
 .../gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c   |  6 +++---
 .../gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c|  6 +++---
 12 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0008.h 
b/drivers/gpu/drm/nouveau/include/nvif/if0008.h
index 8450127420f5..c21d09f04f1d 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0008.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0008.h
@@ -35,7 +35,7 @@ struct nvif_mmu_type_v0 {
 
 struct nvif_mmu_kind_v0 {
__u8  version;
-   __u8  pad01[1];
+   __u8  kind_inv;
__u16 count;
__u8  data[];
 };
diff --git a/drivers/gpu/drm/nouveau/include/nvif/mmu.h 
b/drivers/gpu/drm/nouveau/include/nvif/mmu.h
index 747ecf67e403..cec1e88a0a05 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/mmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/mmu.h
@@ -7,6 +7,7 @@ struct nvif_mmu {
u8  dmabits;
u8  heap_nr;
u8  type_nr;
+   u8  kind_inv;
u16 kind_nr;
s32 mem;
 
@@ -36,9 +37,8 @@ void nvif_mmu_fini(struct nvif_mmu *);
 static inline bool
 nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind)
 {
-   const u8 invalid = mmu->kind_nr - 1;
if (kind) {
-   if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid)
+   if (kind >= mmu->kind_nr || mmu->kind[kind] == mmu->kind_inv)
return false;
}
return true;
diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c 
b/drivers/gpu/drm/nouveau/nvif/mmu.c
index 5641bda2046d..47efc408efa6 100644
--- a/drivers/gpu/drm/nouveau/nvif/mmu.c
+++ b/drivers/gpu/drm/nouveau/nvif/mmu.c
@@ -121,6 +121,7 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, 
struct nvif_mmu *mmu)
   kind, argc);
if (ret == 0)
memcpy(mmu->kind, kind->data, kind->count);
+   mmu->kind_inv = kind->kind_inv;
kfree(kind);
}
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
index 2d075246dc46..2cd5ec81c0d0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
@@ -30,7 +30,7 @@
  * The value 0xff represents an invalid storage type.
  */
 const u8 *
-gf100_mmu_kind(struct nvkm_mmu *mmu, int *count)
+gf100_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
 {
static const u8
kind[256] = {
@@ -69,6 +69,7 @@ gf100_mmu_kind(struct nvkm_mmu *mmu, int *count)
};
 
*count = ARRAY_SIZE(kind);
+   *invalid = 0xff;
return kind;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
index dbf644ebac97..83990c83f9f8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
@@ -27,7 +27,7 @@
 #include 
 
 const u8 *
-gm200_mmu_kind(struct nvkm_mmu *mmu, int *count)
+gm200_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
 {
static const u8
kind[256] = {
@@ -65,6 +65,7 @@ gm200_mmu_kind(struct nvkm_mmu *mmu, int *count)
0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
};
*count = ARRAY_SIZE(kind);
+   *invalid = 0xff;
return kind;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
index db3dfbbb2aa0..c0083ddda65a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
@@ -27,7 

[PATCH] drm/nouveau: Fix ttm move init with multiple GPUs

2019-12-16 Thread James Jones
The pointer used to walk the table of move ops
and pick the right one for the current GPU was
declared static, meaning its state was carried
over between invocations of the function, and also
made the function non-rentrant and thread-unsafe.
Since the table is ordered such that newer GPU
methods are listed first, the result of this was
that initializing newer GPUs after older GPUs
would result in no suitable ttm move acceleration
operations being found, and ttm would fall back
to CPU blits on the older GPUs.

This change declares the walking pointer
separately from the table and makes it non-static
to fix the logic.

Signed-off-by: James Jones 
---
 drivers/gpu/drm/nouveau/nouveau_bo.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index f8015e0318d7..1b62ccc57aef 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1162,7 +1162,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int 
evict, bool intr,
 void
 nouveau_bo_move_init(struct nouveau_drm *drm)
 {
-   static const struct {
+   static const struct _method_table {
const char *name;
int engine;
s32 oclass;
@@ -1192,7 +1192,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
{  "M2MF", 0, 0x0039, nv04_bo_move_m2mf, nv04_bo_move_init },
{},
{ "CRYPT", 0, 0x88b4, nv98_bo_move_exec, nv50_bo_move_init },
-   }, *mthd = _methods;
+   };
+   const struct _method_table *mthd = _methods;
const char *name = "CPU";
int ret;
 
-- 
2.17.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH RESEND 2/4] drm: bridge: anx7688: Add anx7688 bridge driver support.

2019-12-16 Thread Laurent Pinchart
Hi Nicolas,

On Tue, Dec 17, 2019 at 08:40:51AM +0800, Nicolas Boichat wrote:
> (Brilliant, I managed to accidentally send the email below, and send
> it as HTML, sorry about that... ASCII art in gmail is hard ,-(

No worries. I have been told it's indeed painful.

> Take 2:)
> 
> Hi Laurent,
> 
> > On Tue, Dec 17, 2019 at 12:39 AM Laurent Pinchart wrote:
> > > On Mon, Dec 16, 2019 at 06:19:24PM +0800, Nicolas Boichat wrote:
> > > > On Mon, Dec 16, 2019 at 4:46 PM Hsin-Yi Wang wrote:
> > > > > On Sat, Dec 14, 2019 at 6:38 AM Laurent Pinchart wrote:
> > > > > > On Wed, Dec 11, 2019 at 02:19:09PM +0800, Hsin-Yi Wang wrote:
> > > > > > > From: Nicolas Boichat 
> > > > > > >
> > > > > > > ANX7688 is a HDMI to DP converter (as well as USB-C port 
> > > > > > > controller),
> > > > > > > that has an internal microcontroller.
> > > > > > >
> > > > > > > The only reason a Linux kernel driver is necessary is to reject
> > > > > > > resolutions that require more bandwidth than what is available on
> > > > > > > the DP side. DP bandwidth and lane count are reported by the 
> > > > > > > bridge
> > > > > > > via 2 registers on I2C.
> > > > > >
> > > > > > How about power, doesn't this chip have power supplies that 
> > > > > > potentially
> > > > > > need to be controlled ?
> > > > > >
> > > > > Ideally we should add power supplies as well, but the power is
> > > > > supplied by ec in mt8173 oak board. And we only have this board can
> > > > > test this driver. If we add power supplies in driver we can't test it.
> > > >
> > > > To clarify a bit more, this is because this chip is actually a
> > > > TCPC+mux+HDMI=>DP converter
> > > > (https://www.analogix.com/en/products/convertersbridges/anx7688). In
> > > > Chromebook architecture, TCPC+mux is controlled by the EC (including
> > > > power and other control pins), and the only reason we need a driver
> > > > for the HDMI=>DP converter is to get the number of lanes on the DP
> > > > side and filter out resolutions. Also, the converter is on a different
> > > > I2C address and it could almost be considered as a separate device.
> > > >
> > > > (of course we could write a kernel driver for the TCPC+mux but we'll
> > > > leave that to others if there's ever a board that is built with the
> > > > TCPC part connected to the AP)
> > >
> > > Is the mux the one that is handled through a gpio-mux driver in this
> > > series, or a different mux ?
> >
> 
> It's a different mux: it's the usual USB-C mux that takes in USB 3.0
> and DP (internally converted from HDMI), and decides which 2 lanes to
> use for each (4 lanes in total, but DP can only take 2 with this
> converter), and flip if necessary. This is all controlled by the EC
> (like on most other Chromebooks), so this is transparent to the kernel
> on this hardware.
> 
> > > It would really, really help if you could
> > > show a block diagram of the related hardware (including the EC), as this
> > > is quite confusing. With every e-mail exchanged there's a bit more
> > > information that change my understanding of the issue, I can't really
> > > provide guidance without a full overview.
> 
> https://lkml.org/lkml/2019/12/9/548 that you drew is accurate for the
> display part of the problem.
> 
> You can just add a USB3 connection to the above (there's also I2C
> interface to the EC of course to control the TCPC/mux aspect of it,
> but that's on different I2C addresses). Something like this:
> 
>   +---+
>  +-+ +--+/--> | HDMI  |
>  | MT8173  |  HDMI   |   -->| --/ | Connector |
>  |  HDMI   | --> |--/   | +---+
>  | Encoder | |->| --\ +---+  +---+
>  +-+ +--+\--> | ANX7688   | ---> | USB-C |
>   | Bridge|  | Connector |
>   USB3--> | + mux |  |   |
>   +---+  +---+
>  ^ ^
>(I2C) | | (I2C)
>MT8173 (DP lane count/bw readback) -- + + -- EC (TCPC+mux control)
> 
> Power is also fully controlled by the EC.

Could I ask you to also explain how the HDMI mux is controlled, and
where the HPD-related signals for the HDMI connector and USB-C connector
are routed to ?

> (the product brief has a good diagram of the internals of the ANX7688:
> https://www.analogix.com/en/system/files/AA-002281-PB-6-ANX7688_Product_Brief.pdf)
> 
> The ANX7688 bridge could _almost_ work driverless (and it does
> already), the _only_ thing that the driver is doing is filtering out
> impossible resolution based on DP (over USB-C) number of lanes and
> bandwidth. This is required to support, for example, old monitors that
> may only do RBR over DP (so we can't drive the full resolution over 2
> DP lanes, we'd need 4 lanes, and we need to filter out the higher
> 

[PATCH] drm/tegra: Use more descriptive format modifiers

2019-12-16 Thread James Jones
Advertise and accept both the existing
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK()-based format
modifiers and the more descriptive
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D()-based
format modifiers, preserving backwards
compatibility with existing userspace drivers, but
providing forwards compatibility with future
userspace drivers that also make use of the more
descriptive modifiers to enable differentiation
between desktop and tegra, as well as compressed
and non-compressed surfaces.

This patch depends on the "[PATCH v3] drm: Generalized NV Block Linear DRM
format mod" patch submitted to dri-devel.

Signed-off-by: James Jones 
---
 drivers/gpu/drm/tegra/dc.c  | 10 ++
 drivers/gpu/drm/tegra/fb.c  | 14 +++---
 drivers/gpu/drm/tegra/hub.c | 10 ++
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index fbf57bc3cdab..a2cc687dc2d8 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -588,6 +588,16 @@ static const u32 tegra124_primary_formats[] = {
 
 static const u64 tegra124_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 0),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 1),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 2),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 3),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 4),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 5),
+   /*
+* For backwards compatibility with older userspace that may have
+* baked in usage of the less-descriptive modifiers
+*/
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index e34325c83d28..d04e0b1c61ea 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -44,7 +44,7 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
 {
uint64_t modifier = framebuffer->modifier;
 
-   switch (modifier) {
+   switch (drm_fourcc_canonicalize_nvidia_format_mod(modifier)) {
case DRM_FORMAT_MOD_LINEAR:
tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
tiling->value = 0;
@@ -55,32 +55,32 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
tiling->value = 0;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 0):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 0;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 1):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 1;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 2):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 2;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 3):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 3;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 4):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 4;
break;
 
-   case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5):
+   case DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 5):
tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
tiling->value = 5;
break;
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index 839b49c40e51..03c97b10b122 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -49,6 +49,16 @@ static const u32 tegra_shared_plane_formats[] = {
 
 static const u64 tegra_shared_plane_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 0),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 1),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 2),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 3),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 4),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0xfe, 5),
+   /*
+* For backwards compatibility with older userspace that may have
+* baked in usage of the less-descriptive modifiers
+*/
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
-- 
2.17.1


Re: [Nouveau] [PATCH 3/3] drm/nouveau: Support NVIDIA format modifiers

2019-12-16 Thread James Jones

On 12/12/19 6:51 PM, James Jones wrote:

On 12/11/19 1:13 PM, Ilia Mirkin wrote:

On Wed, Dec 11, 2019 at 4:04 PM James Jones  wrote:


Allow setting the block layout of a nouveau FB
object using DRM format modifiers.  When
specified, the format modifier block layout and
kind overrides the GEM buffer's implicit layout
and kind.  The specified format modifier is
validated against he list of modifiers supported
by the target display hardware.

Signed-off-by: James Jones 
---
  drivers/gpu/drm/nouveau/dispnv50/wndw.c   |  8 +--
  drivers/gpu/drm/nouveau/nouveau_display.c | 65 ++-
  drivers/gpu/drm/nouveau/nouveau_display.h |  2 +
  3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c 
b/drivers/gpu/drm/nouveau/dispnv50/wndw.c

index 70ad64cb2d34..06c1b18479c1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -43,7 +43,7 @@ nv50_wndw_ctxdma_new(struct nv50_wndw *wndw, struct 
nouveau_framebuffer *fb)

  {
 struct nouveau_drm *drm = nouveau_drm(fb->base.dev);
 struct nv50_wndw_ctxdma *ctxdma;
-   const u8    kind = fb->nvbo->kind;
+   const u8    kind = fb->kind;
 const u32 handle = 0xfb00 | kind;
 struct {
 struct nv_dma_v0 base;
@@ -243,7 +243,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw 
*wndw, bool modeset,
 if (asyw->state.fb != armw->state.fb || !armw->visible || 
modeset) {

 asyw->image.w = fb->base.width;
 asyw->image.h = fb->base.height;
-   asyw->image.kind = fb->nvbo->kind;
+   asyw->image.kind = fb->kind;

 ret = nv50_wndw_atomic_check_acquire_rgb(asyw);
 if (ret) {
@@ -255,9 +255,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw 
*wndw, bool modeset,

 if (asyw->image.kind) {
 asyw->image.layout = 0;
 if (drm->client.device.info.chipset >= 0xc0)
-   asyw->image.blockh = fb->nvbo->mode 
>> 4;

+   asyw->image.blockh = fb->tile_mode >> 4;
 else
-   asyw->image.blockh = fb->nvbo->mode;
+   asyw->image.blockh = fb->tile_mode;
 asyw->image.blocks[0] = fb->base.pitches[0] 
/ 64;

 asyw->image.pitch[0] = 0;
 } else {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c

index f1509392d7b7..351b58410e1a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -224,6 +224,50 @@ static const struct drm_framebuffer_funcs 
nouveau_framebuffer_funcs = {

 .create_handle = nouveau_user_framebuffer_create_handle,
  };

+static int
+nouveau_decode_mod(struct nouveau_drm *drm,
+  uint64_t modifier,
+  uint32_t *tile_mode,
+  uint8_t *kind)
+{
+   struct nouveau_display *disp = nouveau_display(drm->dev);
+   int mod;
+
+   BUG_ON(!tile_mode || !kind);
+
+   if (drm->client.device.info.chipset < 0x50) {


Not a full review, but you want to go off the family (chip_class iirc?
something like that, should be obvious). Sadly 0x67/0x68 are higher
than 0x50 numerically, but are logically part of the nv4x generation.


Good catch.  I'll get this fixed and send out an updated patchset.


I fixed this one instance in the v2 series, and I didn't see any other 
potentially dangerous uses of chipset, so I left the others as-is, as 
they seemed to better match surrounding code or existing checks used for 
a given bit of functionality.



Thanks,
-James


+   return -EINVAL;
+   }
+
+   BUG_ON(!disp->format_modifiers);
+
+   for (mod = 0;
+    (disp->format_modifiers[mod] != DRM_FORMAT_MOD_INVALID) &&
+    (disp->format_modifiers[mod] != modifier);
+    mod++);
+
+   if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
+   return -EINVAL;
+
+   if (modifier == DRM_FORMAT_MOD_LINEAR) {
+   /* tile_mode will not be used in this case */
+   *tile_mode = 0;
+   *kind = 0;
+   } else {
+   /*
+    * Extract the block height and kind from the 
corresponding

+    * modifier fields.  See drm_fourcc.h for details.
+    */
+   *tile_mode = (uint32_t)(modifier & 0xF);
+   *kind = (uint8_t)((modifier >> 12) & 0xFF);
+
+   if (drm->client.device.info.chipset >= 0xc0)
+   *tile_mode <<= 4;
+   }
+
+   return 0;
+}
+
  static inline uint32_t
  nouveau_get_width_in_blocks(uint32_t stride)
  {
@@ -300,6 +344,8 @@ nouveau_framebuffer_new(struct drm_device *dev,
 struct nouveau_framebuffer *fb;
 

[PATCH v2 2/3] drm/nouveau: Check framebuffer size against bo

2019-12-16 Thread James Jones
Make sure framebuffer dimensions and tiling
parameters will not result in accesses beyond the
end of the GEM buffer they are bound to.

Signed-off-by: James Jones 
---
 drivers/gpu/drm/nouveau/nouveau_display.c | 93 +++
 1 file changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 6f038511a03a..f1509392d7b7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -224,6 +224,72 @@ static const struct drm_framebuffer_funcs 
nouveau_framebuffer_funcs = {
.create_handle = nouveau_user_framebuffer_create_handle,
 };
 
+static inline uint32_t
+nouveau_get_width_in_blocks(uint32_t stride)
+{
+   /* GOBs per block in the x direction is always one, and GOBs are
+* 64 bytes wide
+*/
+   static const uint32_t log_block_width = 6;
+
+   return (stride + (1 << log_block_width) - 1) >> log_block_width;
+}
+
+static inline uint32_t
+nouveau_get_height_in_blocks(struct nouveau_drm *drm,
+uint32_t height,
+uint32_t log_block_height_in_gobs)
+{
+   uint32_t log_gob_height;
+   uint32_t log_block_height;
+
+   BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
+
+   if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
+   log_gob_height = 2;
+   else
+   log_gob_height = 3;
+
+   log_block_height = log_block_height_in_gobs + log_gob_height;
+
+   return (height + (1 << log_block_height) - 1) >> log_block_height;
+}
+
+static int
+nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
+ uint32_t offset, uint32_t stride, uint32_t h,
+ uint32_t tile_mode)
+{
+   uint32_t gob_size, bw, bh;
+   uint64_t bl_size;
+
+   BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA);
+
+   if (drm->client.device.info.chipset >= 0xc0)
+   tile_mode >>= 4;
+
+   BUG_ON(tile_mode & 0xFFF0);
+
+   if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI)
+   gob_size = 256;
+   else
+   gob_size = 512;
+
+   bw = nouveau_get_width_in_blocks(stride);
+   bh = nouveau_get_height_in_blocks(drm, h, tile_mode);
+
+   bl_size = bw * bh * (1 << tile_mode) * gob_size;
+
+   DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u 
gob_size=%u bl_size=%llu size=%lu\n",
+ offset, stride, h, tile_mode, bw, bh, gob_size, bl_size,
+ nvbo->bo.mem.size);
+
+   if (bl_size + offset > nvbo->bo.mem.size)
+   return -ERANGE;
+
+   return 0;
+}
+
 int
 nouveau_framebuffer_new(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
@@ -232,6 +298,8 @@ nouveau_framebuffer_new(struct drm_device *dev,
 {
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_framebuffer *fb;
+   const struct drm_format_info *info;
+   unsigned int width, height, i;
int ret;
 
 /* YUV overlays have special requirements pre-NV50 */
@@ -254,6 +322,31 @@ nouveau_framebuffer_new(struct drm_device *dev,
return -EINVAL;
}
 
+   info = drm_get_format_info(dev, mode_cmd);
+
+   for (i = 0; i < info->num_planes; i++) {
+   width = drm_format_info_plane_width(info,
+   mode_cmd->width,
+   i);
+   height = drm_format_info_plane_height(info,
+ mode_cmd->height,
+ i);
+
+   if (nvbo->kind) {
+   ret = nouveau_check_bl_size(drm, nvbo,
+   mode_cmd->offsets[i],
+   mode_cmd->pitches[i],
+   height, nvbo->mode);
+   if (ret)
+   return ret;
+   } else {
+   uint32_t size = mode_cmd->pitches[i] * height;
+
+   if (size + mode_cmd->offsets[i] > nvbo->bo.mem.size)
+   return -ERANGE;
+   }
+   }
+
if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
return -ENOMEM;
 
-- 
2.17.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 0/3] drm/nouveau: Support NVIDIA format modifiers

2019-12-16 Thread James Jones
This series modifies the NV5x+ nouveau display backends to advertise
appropriate format modifiers on their display planes in atomic mode
setting blobs.

Corresponding modifications to Mesa/userspace are available here:

https://gitlab.freedesktop.org/cubanismo/mesa/tree/nouveau_work

But those need a bit of cleanup before they're ready to submit.

I've tested this on Tesla, Kepler, Pascal, and Turing-class hardware
using various formats and all the exposed format modifiers, plus some
negative testing with invalid ones.

NOTE: this series depends on the "[PATCH v3] drm: Generalized NV Block
Linear DRM format mod" patch submitted to dri-devel.

v2: Used Tesla family instead of NV50 chipset compare to avoid treating
oddly numbered NV4x-class chipsets as NV50+ GPUs.  Other instances
of compares with chipset number in the series were audited, deemed
safe, and left as-is for consistency with existing code.

James Jones (3):
  drm/nouveau: Add format mod prop to base/ovly/nvdisp
  drm/nouveau: Check framebuffer size against bo
  drm/nouveau: Support NVIDIA format modifiers

 drivers/gpu/drm/nouveau/dispnv50/base507c.c |   7 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c |  59 
 drivers/gpu/drm/nouveau/dispnv50/disp.h |   4 +
 drivers/gpu/drm/nouveau/dispnv50/wndw.c |  35 -
 drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c |  17 +++
 drivers/gpu/drm/nouveau/nouveau_display.c   | 154 
 drivers/gpu/drm/nouveau/nouveau_display.h   |   4 +
 7 files changed, 272 insertions(+), 8 deletions(-)

-- 
2.17.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 3/3] drm/nouveau: Support NVIDIA format modifiers

2019-12-16 Thread James Jones
Allow setting the block layout of a nouveau FB
object using DRM format modifiers.  When
specified, the format modifier block layout and
kind overrides the GEM buffer's implicit layout
and kind.  The specified format modifier is
validated against he list of modifiers supported
by the target display hardware.

v2: Used Tesla family instead of NV50 chipset compare

Signed-off-by: James Jones 
---
 drivers/gpu/drm/nouveau/dispnv50/wndw.c   |  8 +--
 drivers/gpu/drm/nouveau/nouveau_display.c | 65 ++-
 drivers/gpu/drm/nouveau/nouveau_display.h |  2 +
 3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c 
b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 70ad64cb2d34..06c1b18479c1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -43,7 +43,7 @@ nv50_wndw_ctxdma_new(struct nv50_wndw *wndw, struct 
nouveau_framebuffer *fb)
 {
struct nouveau_drm *drm = nouveau_drm(fb->base.dev);
struct nv50_wndw_ctxdma *ctxdma;
-   const u8kind = fb->nvbo->kind;
+   const u8kind = fb->kind;
const u32 handle = 0xfb00 | kind;
struct {
struct nv_dma_v0 base;
@@ -243,7 +243,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool 
modeset,
if (asyw->state.fb != armw->state.fb || !armw->visible || modeset) {
asyw->image.w = fb->base.width;
asyw->image.h = fb->base.height;
-   asyw->image.kind = fb->nvbo->kind;
+   asyw->image.kind = fb->kind;
 
ret = nv50_wndw_atomic_check_acquire_rgb(asyw);
if (ret) {
@@ -255,9 +255,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool 
modeset,
if (asyw->image.kind) {
asyw->image.layout = 0;
if (drm->client.device.info.chipset >= 0xc0)
-   asyw->image.blockh = fb->nvbo->mode >> 4;
+   asyw->image.blockh = fb->tile_mode >> 4;
else
-   asyw->image.blockh = fb->nvbo->mode;
+   asyw->image.blockh = fb->tile_mode;
asyw->image.blocks[0] = fb->base.pitches[0] / 64;
asyw->image.pitch[0] = 0;
} else {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index f1509392d7b7..50e055adebd4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -224,6 +224,50 @@ static const struct drm_framebuffer_funcs 
nouveau_framebuffer_funcs = {
.create_handle = nouveau_user_framebuffer_create_handle,
 };
 
+static int
+nouveau_decode_mod(struct nouveau_drm *drm,
+  uint64_t modifier,
+  uint32_t *tile_mode,
+  uint8_t *kind)
+{
+   struct nouveau_display *disp = nouveau_display(drm->dev);
+   int mod;
+
+   BUG_ON(!tile_mode || !kind);
+
+   if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
+   return -EINVAL;
+   }
+
+   BUG_ON(!disp->format_modifiers);
+
+   for (mod = 0;
+(disp->format_modifiers[mod] != DRM_FORMAT_MOD_INVALID) &&
+(disp->format_modifiers[mod] != modifier);
+mod++);
+
+   if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
+   return -EINVAL;
+
+   if (modifier == DRM_FORMAT_MOD_LINEAR) {
+   /* tile_mode will not be used in this case */
+   *tile_mode = 0;
+   *kind = 0;
+   } else {
+   /*
+* Extract the block height and kind from the corresponding
+* modifier fields.  See drm_fourcc.h for details.
+*/
+   *tile_mode = (uint32_t)(modifier & 0xF);
+   *kind = (uint8_t)((modifier >> 12) & 0xFF);
+
+   if (drm->client.device.info.chipset >= 0xc0)
+   *tile_mode <<= 4;
+   }
+
+   return 0;
+}
+
 static inline uint32_t
 nouveau_get_width_in_blocks(uint32_t stride)
 {
@@ -300,6 +344,8 @@ nouveau_framebuffer_new(struct drm_device *dev,
struct nouveau_framebuffer *fb;
const struct drm_format_info *info;
unsigned int width, height, i;
+   uint32_t tile_mode;
+   uint8_t kind;
int ret;
 
 /* YUV overlays have special requirements pre-NV50 */
@@ -322,6 +368,18 @@ nouveau_framebuffer_new(struct drm_device *dev,
return -EINVAL;
}
 
+   if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
+   if (nouveau_decode_mod(drm, mode_cmd->modifier[0], _mode,
+  )) {
+   DRM_DEBUG_KMS("Unsupported modifier: 0x%llx\n",
+ mode_cmd->modifier[0]);
+   return 

[PATCH v2 1/3] drm/nouveau: Add format mod prop to base/ovly/nvdisp

2019-12-16 Thread James Jones
Advertise support for the full list of format
modifiers supported by each class of NVIDIA
desktop GPU display hardware.  Stash the array
of modifiers in the nouveau_display struct for
use when validating userspace framebuffer
creation requests, which will be supportd in
a subsequent change.

Signed-off-by: James Jones 
---
 drivers/gpu/drm/nouveau/dispnv50/base507c.c |  7 +--
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 59 +
 drivers/gpu/drm/nouveau/dispnv50/disp.h |  4 ++
 drivers/gpu/drm/nouveau/dispnv50/wndw.c | 27 +-
 drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c | 17 ++
 drivers/gpu/drm/nouveau/nouveau_display.h   |  2 +
 6 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c 
b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
index 00a85f1e1a4a..025b8f996a0a 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
@@ -262,7 +262,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 
*format,
struct nv50_disp_base_channel_dma_v0 args = {
.head = head,
};
-   struct nv50_disp *disp = nv50_disp(drm->dev);
+   struct nouveau_display *disp = nouveau_display(drm->dev);
+   struct nv50_disp *disp50 = nv50_disp(drm->dev);
struct nv50_wndw *wndw;
int ret;
 
@@ -272,9 +273,9 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 
*format,
if (*pwndw = wndw, ret)
return ret;
 
-   ret = nv50_dmac_create(>client.device, >disp->object,
+   ret = nv50_dmac_create(>client.device, >disp.object,
   , head, , sizeof(args),
-  disp->sync->bo.offset, >wndw);
+  disp50->sync->bo.offset, >wndw);
if (ret) {
NV_ERROR(drm, "base%04x allocation failed: %d\n", oclass, ret);
return ret;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 064a69d161e3..0956367d27a2 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2337,6 +2337,15 @@ nv50_display_create(struct drm_device *dev)
if (ret)
goto out;
 
+   /* Assign the correct format modifiers */
+   if (disp->disp->object.oclass >= TU102_DISP)
+   nouveau_display(dev)->format_modifiers = wndwc57e_modifiers;
+   else
+   if (disp->disp->object.oclass >= GF110_DISP)
+   nouveau_display(dev)->format_modifiers = disp90xx_modifiers;
+   else
+   nouveau_display(dev)->format_modifiers = disp50xx_modifiers;
+
/* create crtc objects to represent the hw heads */
if (disp->disp->object.oclass >= GV100_DISP)
crtcs = nvif_rd32(>object, 0x610060) & 0xff;
@@ -2404,3 +2413,53 @@ nv50_display_create(struct drm_device *dev)
nv50_display_destroy(dev);
return ret;
 }
+
+/**
+ * Format modifiers
+ */
+
+/
+ *Log2(block height) +  *
+ *Page Kind --+  |  *
+ *Gob Height/Page Kind Generation --+ |  |  *
+ *  Sector layout ---+  | |  |  *
+ *  Compression --+  |  | |  |  */
+const u64 disp50xx_modifiers[] = { /* |  |  | |  |  */
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 0),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 1),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 2),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 3),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 4),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x7a, 5),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 0),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 1),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 2),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 3),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 4),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x78, 5),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 0),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 1),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 2),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 3),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 4),
+   DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 1, 0x70, 5),
+   DRM_FORMAT_MOD_LINEAR,
+   DRM_FORMAT_MOD_INVALID
+};
+
+/
+ *   

Re: [PATCH RESEND 2/4] drm: bridge: anx7688: Add anx7688 bridge driver support.

2019-12-16 Thread Nicolas Boichat
(Brilliant, I managed to accidentally send the email below, and send
it as HTML, sorry about that... ASCII art in gmail is hard ,-(

Take 2:)

Hi Laurent,

> On Tue, Dec 17, 2019 at 12:39 AM Laurent Pinchart 
>  wrote:
> >
> > Hello Nicolas and Hsin-Yi,
> >
> > On Mon, Dec 16, 2019 at 06:19:24PM +0800, Nicolas Boichat wrote:
> > > On Mon, Dec 16, 2019 at 4:46 PM Hsin-Yi Wang wrote:
> > > > On Sat, Dec 14, 2019 at 6:38 AM Laurent Pinchart wrote:
> > > > > On Wed, Dec 11, 2019 at 02:19:09PM +0800, Hsin-Yi Wang wrote:
> > > > > > From: Nicolas Boichat 
> > > > > >
> > > > > > ANX7688 is a HDMI to DP converter (as well as USB-C port 
> > > > > > controller),
> > > > > > that has an internal microcontroller.
> > > > > >
> > > > > > The only reason a Linux kernel driver is necessary is to reject
> > > > > > resolutions that require more bandwidth than what is available on
> > > > > > the DP side. DP bandwidth and lane count are reported by the bridge
> > > > > > via 2 registers on I2C.
> > > > >
> > > > > How about power, doesn't this chip have power supplies that 
> > > > > potentially
> > > > > need to be controlled ?
> > > > >
> > > > Ideally we should add power supplies as well, but the power is
> > > > supplied by ec in mt8173 oak board. And we only have this board can
> > > > test this driver. If we add power supplies in driver we can't test it.
> > >
> > > To clarify a bit more, this is because this chip is actually a
> > > TCPC+mux+HDMI=>DP converter
> > > (https://www.analogix.com/en/products/convertersbridges/anx7688). In
> > > Chromebook architecture, TCPC+mux is controlled by the EC (including
> > > power and other control pins), and the only reason we need a driver
> > > for the HDMI=>DP converter is to get the number of lanes on the DP
> > > side and filter out resolutions. Also, the converter is on a different
> > > I2C address and it could almost be considered as a separate device.
> > >
> > > (of course we could write a kernel driver for the TCPC+mux but we'll
> > > leave that to others if there's ever a board that is built with the
> > > TCPC part connected to the AP)
> >
> > Is the mux the one that is handled through a gpio-mux driver in this
> > series, or a different mux ?
>

It's a different mux: it's the usual USB-C mux that takes in USB 3.0
and DP (internally converted from HDMI), and decides which 2 lanes to
use for each (4 lanes in total, but DP can only take 2 with this
converter), and flip if necessary. This is all controlled by the EC
(like on most other Chromebooks), so this is transparent to the kernel
on this hardware.

> > It would really, really help if you could
> > show a block diagram of the related hardware (including the EC), as this
> > is quite confusing. With every e-mail exchanged there's a bit more
> > information that change my understanding of the issue, I can't really
> > provide guidance without a full overview.

https://lkml.org/lkml/2019/12/9/548 that you drew is accurate for the
display part of the problem.

You can just add a USB3 connection to the above (there's also I2C
interface to the EC of course to control the TCPC/mux aspect of it,
but that's on different I2C addresses). Something like this:

  +---+
 +-+ +--+/--> | HDMI  |
 | MT8173  |  HDMI   |   -->| --/ | Connector |
 |  HDMI   | --> |--/   | +---+
 | Encoder | |->| --\ +---+  +---+
 +-+ +--+\--> | ANX7688   | ---> | USB-C |
  | Bridge|  | Connector |
  USB3--> | + mux |  |   |
  +---+  +---+
 ^ ^
   (I2C) | | (I2C)
   MT8173 (DP lane count/bw readback) -- + + -- EC (TCPC+mux control)

Power is also fully controlled by the EC.

(the product brief has a good diagram of the internals of the ANX7688:
https://www.analogix.com/en/system/files/AA-002281-PB-6-ANX7688_Product_Brief.pdf)

The ANX7688 bridge could _almost_ work driverless (and it does
already), the _only_ thing that the driver is doing is filtering out
impossible resolution based on DP (over USB-C) number of lanes and
bandwidth. This is required to support, for example, old monitors that
may only do RBR over DP (so we can't drive the full resolution over 2
DP lanes, we'd need 4 lanes, and we need to filter out the higher
resolution modes).

> > > > > > Signed-off-by: Nicolas Boichat 
> > > > > > Signed-off-by: Hsin-Yi Wang 
> > > > > > ---
> > > > > >  drivers/gpu/drm/bridge/Kconfig|   9 +
> > > > > >  drivers/gpu/drm/bridge/Makefile   |   1 +
> > > > > >  drivers/gpu/drm/bridge/analogix-anx7688.c | 202 
> > > > > > ++
> > > > > >  3 files changed, 212 insertions(+)
> > > > > >  create mode 100644 

Re: [PATCH 9/9] drm/bridge: ti-sn65dsi86: Skip non-standard DP rates

2019-12-16 Thread Doug Anderson
Hi,

On Sun, Dec 15, 2019 at 5:19 PM Jeffrey Hugo  wrote:
>
> On Fri, Dec 13, 2019 at 5:49 PM Doug Anderson  wrote:
> >
> > Hi,
> >
> > On Fri, Dec 13, 2019 at 4:07 PM Daniel Vetter  wrote:
> > >
> > > On Fri, Dec 13, 2019 at 03:45:30PM -0800, Douglas Anderson wrote:
> > > > The bridge chip supports these DP rates according to TI's spec:
> > > > * 1.62 Gbps (RBR)
> > > > * 2.16 Gbps
> > > > * 2.43 Gbps
> > > > * 2.7 Gbps (HBR)
> > > > * 3.24 Gbps
> > > > * 4.32 Gbps
> > > > * 5.4 Gbps (HBR2)
> > > >
> > > > As far as I can tell, only RBR, HBR, and HBR2 are part of the DP spec.
> > > > If other rates work then I believe it's because the sink has allowed
> > > > bending the spec a little bit.
> > >
> > > I think you need to look at the eDP spec. And filter this stuff correctly
> > > (there's more fields there for these somewhat irky edp timings). Simply
> > > not using them works, but it's defeating the point of having these
> > > intermediate clocks for edp panels.
> >
> > Ah, I see my problem.  I had earlier only found the eDP 1.3 spec which
> > doesn't mention these rates.  The eDP 1.4 spec does, however.  ...and
> > the change log for 1.4 specifically mentions that it added 4 new link
> > rates and also adds the "SUPPORTED_LINK_RATES" register.
>
> Yeah, you need the eDP spec.  I previously posted
> https://patchwork.kernel.org/patch/11205201/ and was hoping Bjorn
> would find time to test it.  Maybe it would fit well with your series?
>  I'm coming back from tracel, and hope to review everything you have,
> but this caught my eye.

Ah, interesting.  It looks like Rob has already posted a Fixup on my patch:

https://lore.kernel.org/r/20191215200632.1019065-1-robdcl...@gmail.com

...that should also read the supported rates.  I need to go and review
/ test his new patch (I lost access to the hardware but should get it
back tomorrow or the next day), but would you be OK with going that
route?  I think my series is a superset of yours.  Specifically it has
these extra features atop yours:

* If link training fails and the panel supports faster rates, it will
try a faster rate in case it works.

* It adds support for using 6bpp when that's all that's needed,
reducing bandwidth to the panel (and link rate)

* It breaks things into smaller functions (assuming you agree this is
a good thing).

-Doug
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH RESEND 2/4] drm: bridge: anx7688: Add anx7688 bridge driver support.

2019-12-16 Thread Nicolas Boichat
Hi Laurent,

On Tue, Dec 17, 2019 at 12:39 AM Laurent Pinchart <
laurent.pinch...@ideasonboard.com> wrote:
>
> Hello Nicolas and Hsin-Yi,
>
> On Mon, Dec 16, 2019 at 06:19:24PM +0800, Nicolas Boichat wrote:
> > On Mon, Dec 16, 2019 at 4:46 PM Hsin-Yi Wang wrote:
> > > On Sat, Dec 14, 2019 at 6:38 AM Laurent Pinchart wrote:
> > > > On Wed, Dec 11, 2019 at 02:19:09PM +0800, Hsin-Yi Wang wrote:
> > > > > From: Nicolas Boichat 
> > > > >
> > > > > ANX7688 is a HDMI to DP converter (as well as USB-C port
controller),
> > > > > that has an internal microcontroller.
> > > > >
> > > > > The only reason a Linux kernel driver is necessary is to reject
> > > > > resolutions that require more bandwidth than what is available on
> > > > > the DP side. DP bandwidth and lane count are reported by the
bridge
> > > > > via 2 registers on I2C.
> > > >
> > > > How about power, doesn't this chip have power supplies that
potentially
> > > > need to be controlled ?
> > > >
> > > Ideally we should add power supplies as well, but the power is
> > > supplied by ec in mt8173 oak board. And we only have this board can
> > > test this driver. If we add power supplies in driver we can't test it.
> >
> > To clarify a bit more, this is because this chip is actually a
> > TCPC+mux+HDMI=>DP converter
> > (https://www.analogix.com/en/products/convertersbridges/anx7688). In
> > Chromebook architecture, TCPC+mux is controlled by the EC (including
> > power and other control pins), and the only reason we need a driver
> > for the HDMI=>DP converter is to get the number of lanes on the DP
> > side and filter out resolutions. Also, the converter is on a different
> > I2C address and it could almost be considered as a separate device.
> >
> > (of course we could write a kernel driver for the TCPC+mux but we'll
> > leave that to others if there's ever a board that is built with the
> > TCPC part connected to the AP)
>
> Is the mux the one that is handled through a gpio-mux driver in this
> series, or a different mux ?

It's a different mux: it's the usual USB-C mux that takes in USB 3.0 and DP
(internally converted from HDMI), and decides which 2 lanes to use for
each, and flip if necessary. This is all controlled by the EC (like on most
other Chromebook), so this is transparent to the kernel, at least on
Chromebooks.

> It would really, really help if you could
> show a block diagram of the related hardware (including the EC), as this
> is quite confusing. With every e-mail exchanged there's a bit more
> information that change my understanding of the issue, I can't really
> provide guidance without a full overview.

https://lkml.org/lkml/2019/12/9/548 that you drew is accurate for the
display part of the problem.

You can just add a USB3 connection to the above (there's also I2C interface
to the EC of course to control the TCPC/mux aspect of it, but that's on
different I2C addresses).

 +---+
+-+ +--+/--> | HDMI  |
| MT8173  |  HDMI   |   -->| --/ | Connector |
|  HDMI   | --> |--/   | +---+
| Encoder | |->| --\ +---+  +---+
+-+ +--+\--> | ANX7688   | ---> | USB-C |
 | Bridge|  | Connector |
 USB3--> | + mux |  |   |
 +---+  +---+
 ^

The ANX7688 brige could _almost_ work driverless (and it does already), the
_only_ thing that the driver is doing is filtering out impossible
resolution based on DP (over USB-C) number of lanes and bandwidth.

> > > > > Signed-off-by: Nicolas Boichat 
> > > > > Signed-off-by: Hsin-Yi Wang 
> > > > > ---
> > > > >  drivers/gpu/drm/bridge/Kconfig|   9 +
> > > > >  drivers/gpu/drm/bridge/Makefile   |   1 +
> > > > >  drivers/gpu/drm/bridge/analogix-anx7688.c | 202
++
> > > > >  3 files changed, 212 insertions(+)
> > > > >  create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
> > > > >
> > > > > diff --git a/drivers/gpu/drm/bridge/Kconfig
b/drivers/gpu/drm/bridge/Kconfig
> > > > > index 34362976cd6f..1f3fc6bec842 100644
> > > > > --- a/drivers/gpu/drm/bridge/Kconfig
> > > > > +++ b/drivers/gpu/drm/bridge/Kconfig
> > > > > @@ -16,6 +16,15 @@ config DRM_PANEL_BRIDGE
> > > > >  menu "Display Interface Bridges"
> > > > >   depends on DRM && DRM_BRIDGE
> > > > >
> > > > > +config DRM_ANALOGIX_ANX7688
> > > > > + tristate "Analogix ANX7688 bridge"
> > > > > + select DRM_KMS_HELPER
> > > > > + select REGMAP_I2C
> > > > > + ---help---
> > > > > +   ANX7688 is a transmitter to support DisplayPort over
USB-C for
> > > > > +   smartphone and tablets.
> > > > > +   This driver only supports the HDMI to DP component of the
chip.
> > > > > +
> > > > >  config DRM_ANALOGIX_ANX78XX
> > > > >   tristate "Analogix 

[Bug 200695] Blank screen on RX 580 with amdgpu.dc=1 enabled (no displays detected)

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=200695

Claude Heiland-Allen (cla...@mathr.co.uk) changed:

   What|Removed |Added

 Kernel Version|4.17.19, 4.18.5 -- 4.18.20, |4.17.19, 4.18.5 -- 4.18.20,
   |4.19-rc1 -- 4.19.32,|4.19-rc1 -- 4.19.89,
   |4.20-rc1 -- 4.20.17,|4.20-rc1 -- 4.20.17,
   |5.0-rc1 -- 5.0.5, 5.1-rc3   |5.0-rc1 -- 5.0.5, 5.1-rc3,
   ||5.3.9, 5.3.16, 5.4.3,
   ||5.5-rc2

--- Comment #35 from Claude Heiland-Allen (cla...@mathr.co.uk) ---
Still getting this issue: with monitor connected via DVI, screen goes blank and
monitor turns off a few seconds into boot (is fine before that, in motherboard
power on display and grub and start of boot process).  With same monitor
connected via HDMI and HDMI/DVI adaptor there are no issues.

Kernel versions tested today, with behaviour as above:
- 4.19.89
- 5.3.16
- 5.4.3 (partial test, forgot to test with DVI; HDMI works fine)
- 5.5-rc2

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 204609] amdgpu: powerplay failed send message

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=204609

Błażej Szczygieł (spa...@wp.pl) changed:

   What|Removed |Added

 CC||spa...@wp.pl

--- Comment #5 from Błażej Szczygieł (spa...@wp.pl) ---
Created attachment 286329
  --> https://bugzilla.kernel.org/attachment.cgi?id=286329=edit
kernel5.4 powerplay add mutex

Also the same as: https://gitlab.freedesktop.org/drm/amd/issues/900

In kernel 5.4.3 run a few times `watch -n 0.1 cat
/sys/class/drm/card0/device/hwmon/hwmon*/fan1_input` in parallel and you'll
have a lot of warning and finally system freeze.

In kernel 5.5-rc2 powerplay warnings and finally system freeze can happen when
sensors are read and screen mode is changed (like screen resolution change,
etc).

In my opinion a lot of powerplay issues are caused by missing mutexes between
kernel and user space. I prepared a very simple kernel 5.4 patch which allows
me to use fan monitor, but probably there are still some missing mutexes there.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 205879] amdgpu: blank screen on RX 460

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205879

Bjoern Franke (b...@nord-west.org) changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |INVALID

--- Comment #4 from Bjoern Franke (b...@nord-west.org) ---
Issue was caused by a loose connection. Reinserted the HDMI cable and all is
fine again.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3] drm: rcar-du: lvds: Get mode from state

2019-12-16 Thread Laurent Pinchart
The R-Car LVDS encoder driver implements the bridge .mode_set()
operation for the sole purpose of storing the mode in the LVDS private
data, to be used later when enabling the encoder.

Switch to the bridge .atomic_enable() and .atomic_disable() operations
in order to access the global atomic state, and get the mode from the
state instead. Remove both the unneeded .mode_set() operation and the
display_mode and mode fields storing state data from the rcar_lvds
private structure.

As a side effect we get the CRTC from the state, replace the CRTC
pointer retrieved through the bridge's encoder that shouldn't be used by
atomic drivers.

While at it, clarify a few error messages in rcar_lvds_get_lvds_mode()
and turn them into warnings as they are not fatal.

Signed-off-by: Laurent Pinchart 
---
Changes since v2:

- Turn a few dev_err() into dev_warn()
- Split rcar_lvds_atomic_enable() to avoid setting the companion's
  bridge encoder pointer manually
- Call .atomic_disable() on the companion

Changes since v1:

- Call .atomic_enable() on the companion
- Set companion->encoder in .attach()
---
 drivers/gpu/drm/rcar-du/rcar_lvds.c | 140 +++-
 1 file changed, 74 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 8c6c172bbf2e..284f10d0307f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -65,9 +65,6 @@ struct rcar_lvds {
struct clk *dotclkin[2];/* External DU clocks */
} clocks;
 
-   struct drm_display_mode display_mode;
-   enum rcar_lvds_mode mode;
-
struct drm_bridge *companion;
bool dual_link;
 };
@@ -402,10 +399,53 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
  * Bridge
  */
 
-static void rcar_lvds_enable(struct drm_bridge *bridge)
+static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
+   const struct drm_connector *connector)
+{
+   const struct drm_display_info *info;
+   enum rcar_lvds_mode mode;
+
+   /*
+* There is no API yet to retrieve LVDS mode from a bridge, only panels
+* are supported.
+*/
+   if (!lvds->panel)
+   return RCAR_LVDS_MODE_JEIDA;
+
+   info = >display_info;
+   if (!info->num_bus_formats || !info->bus_formats) {
+   dev_warn(lvds->dev,
+"no LVDS bus format reported, using JEIDA\n");
+   return RCAR_LVDS_MODE_JEIDA;
+   }
+
+   switch (info->bus_formats[0]) {
+   case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+   case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+   mode = RCAR_LVDS_MODE_JEIDA;
+   break;
+   case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+   mode = RCAR_LVDS_MODE_VESA;
+   break;
+   default:
+   dev_warn(lvds->dev,
+"unsupported LVDS bus format 0x%04x, using JEIDA\n",
+info->bus_formats[0]);
+   return RCAR_LVDS_MODE_JEIDA;
+   }
+
+   if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
+   mode |= RCAR_LVDS_MODE_MIRROR;
+
+   return mode;
+}
+
+static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state,
+ struct drm_crtc *crtc,
+ struct drm_connector *connector)
 {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
-   const struct drm_display_mode *mode = >display_mode;
u32 lvdhcr;
u32 lvdcr0;
int ret;
@@ -416,7 +456,8 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 
/* Enable the companion LVDS encoder in dual-link mode. */
if (lvds->dual_link && lvds->companion)
-   lvds->companion->funcs->enable(lvds->companion);
+   __rcar_lvds_atomic_enable(lvds->companion, state, crtc,
+ connector);
 
/*
 * Hardcode the channels and control signals routing for now.
@@ -452,18 +493,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 * PLL clock configuration on all instances but the companion in
 * dual-link mode.
 */
-   if (!lvds->dual_link || lvds->companion)
+   if (!lvds->dual_link || lvds->companion) {
+   const struct drm_crtc_state *crtc_state =
+   drm_atomic_get_new_crtc_state(state, crtc);
+   const struct drm_display_mode *mode =
+   _state->adjusted_mode;
+
lvds->info->pll_setup(lvds, mode->clock * 1000);
+   }
 
/* Set the LVDS mode and select the input. */
-   lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
+   lvdcr0 = rcar_lvds_get_lvds_mode(lvds, connector) << LVDCR0_LVMD_SHIFT;
 
if (lvds->bridge.encoder) {
-   /*
- 

[PATCH v11 10/25] mm/gup: introduce pin_user_pages*() and FOLL_PIN

2019-12-16 Thread John Hubbard
Introduce pin_user_pages*() variations of get_user_pages*() calls,
and also pin_longterm_pages*() variations.

For now, these are placeholder calls, until the various call sites
are converted to use the correct get_user_pages*() or
pin_user_pages*() API.

These variants will eventually all set FOLL_PIN, which is also
introduced, and thoroughly documented.

pin_user_pages()
pin_user_pages_remote()
pin_user_pages_fast()

All pages that are pinned via the above calls, must be unpinned via
put_user_page().

The underlying rules are:

* FOLL_PIN is a gup-internal flag, so the call sites should not directly
set it. That behavior is enforced with assertions.

* Call sites that want to indicate that they are going to do DirectIO
  ("DIO") or something with similar characteristics, should call a
  get_user_pages()-like wrapper call that sets FOLL_PIN. These wrappers
  will:
* Start with "pin_user_pages" instead of "get_user_pages". That
  makes it easy to find and audit the call sites.
* Set FOLL_PIN

* For pages that are received via FOLL_PIN, those pages must be returned
  via put_user_page().

Thanks to Jan Kara and Vlastimil Babka for explaining the 4 cases
in this documentation. (I've reworded it and expanded upon it.)

Reviewed-by: Jan Kara 
Reviewed-by: Mike Rapoport   # Documentation
Reviewed-by: Jérôme Glisse 
Cc: Jonathan Corbet 
Cc: Ira Weiny 
Signed-off-by: John Hubbard 
---
 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/pin_user_pages.rst | 232 ++
 include/linux/mm.h|  63 --
 mm/gup.c  | 161 +--
 4 files changed, 423 insertions(+), 34 deletions(-)
 create mode 100644 Documentation/core-api/pin_user_pages.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index ab0eae1c153a..413f7d7c8642 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -31,6 +31,7 @@ Core utilities
generic-radix-tree
memory-allocation
mm-api
+   pin_user_pages
gfp_mask-from-fs-io
timekeeping
boot-time-mm
diff --git a/Documentation/core-api/pin_user_pages.rst 
b/Documentation/core-api/pin_user_pages.rst
new file mode 100644
index ..71849830cd48
--- /dev/null
+++ b/Documentation/core-api/pin_user_pages.rst
@@ -0,0 +1,232 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+
+pin_user_pages() and related calls
+
+
+.. contents:: :local:
+
+Overview
+
+
+This document describes the following functions::
+
+ pin_user_pages()
+ pin_user_pages_fast()
+ pin_user_pages_remote()
+
+Basic description of FOLL_PIN
+=
+
+FOLL_PIN and FOLL_LONGTERM are flags that can be passed to the 
get_user_pages*()
+("gup") family of functions. FOLL_PIN has significant interactions and
+interdependencies with FOLL_LONGTERM, so both are covered here.
+
+FOLL_PIN is internal to gup, meaning that it should not appear at the gup call
+sites. This allows the associated wrapper functions  (pin_user_pages*() and
+others) to set the correct combination of these flags, and to check for 
problems
+as well.
+
+FOLL_LONGTERM, on the other hand, *is* allowed to be set at the gup call sites.
+This is in order to avoid creating a large number of wrapper functions to cover
+all combinations of get*(), pin*(), FOLL_LONGTERM, and more. Also, the
+pin_user_pages*() APIs are clearly distinct from the get_user_pages*() APIs, so
+that's a natural dividing line, and a good point to make separate wrapper 
calls.
+In other words, use pin_user_pages*() for DMA-pinned pages, and
+get_user_pages*() for other cases. There are four cases described later on in
+this document, to further clarify that concept.
+
+FOLL_PIN and FOLL_GET are mutually exclusive for a given gup call. However,
+multiple threads and call sites are free to pin the same struct pages, via both
+FOLL_PIN and FOLL_GET. It's just the call site that needs to choose one or the
+other, not the struct page(s).
+
+The FOLL_PIN implementation is nearly the same as FOLL_GET, except that 
FOLL_PIN
+uses a different reference counting technique.
+
+FOLL_PIN is a prerequisite to FOLL_LONGTERM. Another way of saying that is,
+FOLL_LONGTERM is a specific case, more restrictive case of FOLL_PIN.
+
+Which flags are set by each wrapper
+===
+
+For these pin_user_pages*() functions, FOLL_PIN is OR'd in with whatever gup
+flags the caller provides. The caller is required to pass in a non-null struct
+pages* array, and the function then pin pages by incrementing each by a special
+value. For now, that value is +1, just like get_user_pages*().::
+
+ Function
+ 
+ pin_user_pages  FOLL_PIN is always set internally by this function.
+ pin_user_pages_fast FOLL_PIN is always set internally by this function.
+ 

[PATCH v11 14/25] drm/via: set FOLL_PIN via pin_user_pages_fast()

2019-12-16 Thread John Hubbard
Convert drm/via to use the new pin_user_pages_fast() call, which sets
FOLL_PIN. Setting FOLL_PIN is now required for code that requires
tracking of pinned pages, and therefore for any code that calls
put_user_page().

In partial anticipation of this work, the drm/via driver was already
calling put_user_page() instead of put_page(). Therefore, in order to
convert from the get_user_pages()/put_page() model, to the
pin_user_pages()/put_user_page() model, the only change required
is to change get_user_pages() to pin_user_pages().

Acked-by: Daniel Vetter 
Reviewed-by: Jérôme Glisse 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 drivers/gpu/drm/via/via_dmablit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/via/via_dmablit.c 
b/drivers/gpu/drm/via/via_dmablit.c
index 3db000aacd26..37c5e572993a 100644
--- a/drivers/gpu/drm/via/via_dmablit.c
+++ b/drivers/gpu/drm/via/via_dmablit.c
@@ -239,7 +239,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  
drm_via_dmablit_t *xfer)
vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages));
if (NULL == vsg->pages)
return -ENOMEM;
-   ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
+   ret = pin_user_pages_fast((unsigned long)xfer->mem_addr,
vsg->num_pages,
vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
vsg->pages);
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 15/25] fs/io_uring: set FOLL_PIN via pin_user_pages()

2019-12-16 Thread John Hubbard
Convert fs/io_uring to use the new pin_user_pages() call, which sets
FOLL_PIN. Setting FOLL_PIN is now required for code that requires
tracking of pinned pages, and therefore for any code that calls
put_user_page().

In partial anticipation of this work, the io_uring code was already
calling put_user_page() instead of put_page(). Therefore, in order to
convert from the get_user_pages()/put_page() model, to the
pin_user_pages()/put_user_page() model, the only change required
here is to change get_user_pages() to pin_user_pages().

Reviewed-by: Jens Axboe 
Reviewed-by: Jan Kara 
Signed-off-by: John Hubbard 
---
 fs/io_uring.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 9b1833fedc5c..c6ff9cc7fe71 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -4539,7 +4539,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx 
*ctx, void __user *arg,
 
ret = 0;
down_read(>mm->mmap_sem);
-   pret = get_user_pages(ubuf, nr_pages,
+   pret = pin_user_pages(ubuf, nr_pages,
  FOLL_WRITE | FOLL_LONGTERM,
  pages, vmas);
if (pret == nr_pages) {
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 19/25] vfio, mm: pin_user_pages (FOLL_PIN) and put_user_page() conversion

2019-12-16 Thread John Hubbard
1. Change vfio from get_user_pages_remote(), to
pin_user_pages_remote().

2. Because all FOLL_PIN-acquired pages must be released via
put_user_page(), also convert the put_page() call over to
put_user_pages_dirty_lock().

Note that this effectively changes the code's behavior in
vfio_iommu_type1.c: put_pfn(): it now ultimately calls
set_page_dirty_lock(), instead of set_page_dirty(). This is
probably more accurate.

As Christoph Hellwig put it, "set_page_dirty() is only safe if we are
dealing with a file backed page where we have reference on the inode it
hangs off." [1]

[1] https://lore.kernel.org/r/20190723153640.gb...@lst.de

Tested-by: Alex Williamson 
Acked-by: Alex Williamson 
Signed-off-by: John Hubbard 
---
 drivers/vfio/vfio_iommu_type1.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index b800fc9a0251..18bfc2fc8e6d 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -309,9 +309,8 @@ static int put_pfn(unsigned long pfn, int prot)
 {
if (!is_invalid_reserved_pfn(pfn)) {
struct page *page = pfn_to_page(pfn);
-   if (prot & IOMMU_WRITE)
-   SetPageDirty(page);
-   put_page(page);
+
+   put_user_pages_dirty_lock(, 1, prot & IOMMU_WRITE);
return 1;
}
return 0;
@@ -329,7 +328,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned 
long vaddr,
flags |= FOLL_WRITE;
 
down_read(>mmap_sem);
-   ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags | FOLL_LONGTERM,
+   ret = pin_user_pages_remote(NULL, mm, vaddr, 1, flags | FOLL_LONGTERM,
page, NULL, NULL);
if (ret == 1) {
*pfn = page_to_pfn(page[0]);
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 22/25] mm, tree-wide: rename put_user_page*() to unpin_user_page*()

2019-12-16 Thread John Hubbard
In order to provide a clearer, more symmetric API for pinning
and unpinning DMA pages. This way, pin_user_pages*() calls
match up with unpin_user_pages*() calls, and the API is a lot
closer to being self-explanatory.

Reviewed-by: Jan Kara 
Signed-off-by: John Hubbard 
---
 Documentation/core-api/pin_user_pages.rst   |  2 +-
 arch/powerpc/mm/book3s64/iommu_api.c|  4 +--
 drivers/gpu/drm/via/via_dmablit.c   |  4 +--
 drivers/infiniband/core/umem.c  |  2 +-
 drivers/infiniband/hw/hfi1/user_pages.c |  2 +-
 drivers/infiniband/hw/mthca/mthca_memfree.c |  6 ++--
 drivers/infiniband/hw/qib/qib_user_pages.c  |  2 +-
 drivers/infiniband/hw/qib/qib_user_sdma.c   |  6 ++--
 drivers/infiniband/hw/usnic/usnic_uiom.c|  2 +-
 drivers/infiniband/sw/siw/siw_mem.c |  2 +-
 drivers/media/v4l2-core/videobuf-dma-sg.c   |  4 +--
 drivers/platform/goldfish/goldfish_pipe.c   |  4 +--
 drivers/vfio/vfio_iommu_type1.c |  2 +-
 fs/io_uring.c   |  4 +--
 include/linux/mm.h  | 26 -
 mm/gup.c| 32 ++---
 mm/process_vm_access.c  |  4 +--
 net/xdp/xdp_umem.c  |  2 +-
 18 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/Documentation/core-api/pin_user_pages.rst 
b/Documentation/core-api/pin_user_pages.rst
index 71849830cd48..1d490155ecd7 100644
--- a/Documentation/core-api/pin_user_pages.rst
+++ b/Documentation/core-api/pin_user_pages.rst
@@ -219,7 +219,7 @@ since the system was booted, via two new /proc/vmstat 
entries: ::
 /proc/vmstat/nr_foll_pin_requested
 
 Those are both going to show zero, unless CONFIG_DEBUG_VM is set. This is
-because there is a noticeable performance drop in put_user_page(), when they
+because there is a noticeable performance drop in unpin_user_page(), when they
 are activated.
 
 References
diff --git a/arch/powerpc/mm/book3s64/iommu_api.c 
b/arch/powerpc/mm/book3s64/iommu_api.c
index a86547822034..eba73ebd8ae5 100644
--- a/arch/powerpc/mm/book3s64/iommu_api.c
+++ b/arch/powerpc/mm/book3s64/iommu_api.c
@@ -168,7 +168,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, 
unsigned long ua,
 
 free_exit:
/* free the references taken */
-   put_user_pages(mem->hpages, pinned);
+   unpin_user_pages(mem->hpages, pinned);
 
vfree(mem->hpas);
kfree(mem);
@@ -214,7 +214,7 @@ static void mm_iommu_unpin(struct 
mm_iommu_table_group_mem_t *mem)
if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY)
SetPageDirty(page);
 
-   put_user_page(page);
+   unpin_user_page(page);
 
mem->hpas[i] = 0;
}
diff --git a/drivers/gpu/drm/via/via_dmablit.c 
b/drivers/gpu/drm/via/via_dmablit.c
index 37c5e572993a..719d036c9384 100644
--- a/drivers/gpu/drm/via/via_dmablit.c
+++ b/drivers/gpu/drm/via/via_dmablit.c
@@ -188,8 +188,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t 
*vsg)
kfree(vsg->desc_pages);
/* fall through */
case dr_via_pages_locked:
-   put_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
- (vsg->direction == DMA_FROM_DEVICE));
+   unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
+  (vsg->direction == DMA_FROM_DEVICE));
/* fall through */
case dr_via_pages_alloc:
vfree(vsg->pages);
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 55daefaa9b88..a6094766b6f5 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -54,7 +54,7 @@ static void __ib_umem_release(struct ib_device *dev, struct 
ib_umem *umem, int d
 
for_each_sg_page(umem->sg_head.sgl, _iter, umem->sg_nents, 0) {
page = sg_page_iter_page(_iter);
-   put_user_pages_dirty_lock(, 1, umem->writable && dirty);
+   unpin_user_pages_dirty_lock(, 1, umem->writable && dirty);
}
 
sg_free_table(>sg_head);
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c 
b/drivers/infiniband/hw/hfi1/user_pages.c
index 9a94761765c0..3b505006c0a6 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -118,7 +118,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned 
long vaddr, size_t np
 void hfi1_release_user_pages(struct mm_struct *mm, struct page **p,
 size_t npages, bool dirty)
 {
-   put_user_pages_dirty_lock(p, npages, dirty);
+   unpin_user_pages_dirty_lock(p, npages, dirty);
 
if (mm) { /* during close after signal, mm can be NULL */
atomic64_sub(npages, >pinned_vm);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c 
b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 

[PATCH v11 07/25] vfio: fix FOLL_LONGTERM use, simplify get_user_pages_remote() call

2019-12-16 Thread John Hubbard
Update VFIO to take advantage of the recently loosened restriction on
FOLL_LONGTERM with get_user_pages_remote(). Also, now it is possible to
fix a bug: the VFIO caller is logically a FOLL_LONGTERM user, but it
wasn't setting FOLL_LONGTERM.

Also, remove an unnessary pair of calls that were releasing and
reacquiring the mmap_sem. There is no need to avoid holding mmap_sem
just in order to call page_to_pfn().

Also, now that the the DAX check ("if a VMA is DAX, don't allow long
term pinning") is in the internals of get_user_pages_remote() and
__gup_longterm_locked(), there's no need for it at the VFIO call site.
So remove it.

Tested-by: Alex Williamson 
Acked-by: Alex Williamson 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Ira Weiny 
Suggested-by: Jason Gunthorpe 
Cc: Dan Williams 
Cc: Jerome Glisse 
Signed-off-by: John Hubbard 
---
 drivers/vfio/vfio_iommu_type1.c | 30 +-
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 2ada8e6cdb88..b800fc9a0251 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -322,7 +322,6 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned 
long vaddr,
 {
struct page *page[1];
struct vm_area_struct *vma;
-   struct vm_area_struct *vmas[1];
unsigned int flags = 0;
int ret;
 
@@ -330,33 +329,14 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned 
long vaddr,
flags |= FOLL_WRITE;
 
down_read(>mmap_sem);
-   if (mm == current->mm) {
-   ret = get_user_pages(vaddr, 1, flags | FOLL_LONGTERM, page,
-vmas);
-   } else {
-   ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page,
-   vmas, NULL);
-   /*
-* The lifetime of a vaddr_get_pfn() page pin is
-* userspace-controlled. In the fs-dax case this could
-* lead to indefinite stalls in filesystem operations.
-* Disallow attempts to pin fs-dax pages via this
-* interface.
-*/
-   if (ret > 0 && vma_is_fsdax(vmas[0])) {
-   ret = -EOPNOTSUPP;
-   put_page(page[0]);
-   }
-   }
-   up_read(>mmap_sem);
-
+   ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags | FOLL_LONGTERM,
+   page, NULL, NULL);
if (ret == 1) {
*pfn = page_to_pfn(page[0]);
-   return 0;
+   ret = 0;
+   goto done;
}
 
-   down_read(>mmap_sem);
-
vaddr = untagged_addr(vaddr);
 
vma = find_vma_intersection(mm, vaddr, vaddr + 1);
@@ -366,7 +346,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned 
long vaddr,
if (is_invalid_reserved_pfn(*pfn))
ret = 0;
}
-
+done:
up_read(>mmap_sem);
return ret;
 }
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 20/25] powerpc: book3s64: convert to pin_user_pages() and put_user_page()

2019-12-16 Thread John Hubbard
1. Convert from get_user_pages() to pin_user_pages().

2. As required by pin_user_pages(), release these pages via
put_user_page().

Reviewed-by: Jan Kara 
Signed-off-by: John Hubbard 
---
 arch/powerpc/mm/book3s64/iommu_api.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/iommu_api.c 
b/arch/powerpc/mm/book3s64/iommu_api.c
index 56cc84520577..a86547822034 100644
--- a/arch/powerpc/mm/book3s64/iommu_api.c
+++ b/arch/powerpc/mm/book3s64/iommu_api.c
@@ -103,7 +103,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, 
unsigned long ua,
for (entry = 0; entry < entries; entry += chunk) {
unsigned long n = min(entries - entry, chunk);
 
-   ret = get_user_pages(ua + (entry << PAGE_SHIFT), n,
+   ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n,
FOLL_WRITE | FOLL_LONGTERM,
mem->hpages + entry, NULL);
if (ret == n) {
@@ -167,9 +167,8 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, 
unsigned long ua,
return 0;
 
 free_exit:
-   /* free the reference taken */
-   for (i = 0; i < pinned; i++)
-   put_page(mem->hpages[i]);
+   /* free the references taken */
+   put_user_pages(mem->hpages, pinned);
 
vfree(mem->hpas);
kfree(mem);
@@ -215,7 +214,8 @@ static void mm_iommu_unpin(struct 
mm_iommu_table_group_mem_t *mem)
if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY)
SetPageDirty(page);
 
-   put_page(page);
+   put_user_page(page);
+
mem->hpas[i] = 0;
}
 }
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 12/25] IB/{core, hw, umem}: set FOLL_PIN via pin_user_pages*(), fix up ODP

2019-12-16 Thread John Hubbard
Convert infiniband to use the new pin_user_pages*() calls.

Also, revert earlier changes to Infiniband ODP that had it using
put_user_page(). ODP is "Case 3" in
Documentation/core-api/pin_user_pages.rst, which is to say, normal
get_user_pages() and put_page() is the API to use there.

The new pin_user_pages*() calls replace corresponding get_user_pages*()
calls, and set the FOLL_PIN flag. The FOLL_PIN flag requires that the
caller must return the pages via put_user_page*() calls, but infiniband
was already doing that as part of an earlier commit.

Reviewed-by: Jason Gunthorpe 
Signed-off-by: John Hubbard 
---
 drivers/infiniband/core/umem.c  |  2 +-
 drivers/infiniband/core/umem_odp.c  | 13 ++---
 drivers/infiniband/hw/hfi1/user_pages.c |  2 +-
 drivers/infiniband/hw/mthca/mthca_memfree.c |  2 +-
 drivers/infiniband/hw/qib/qib_user_pages.c  |  2 +-
 drivers/infiniband/hw/qib/qib_user_sdma.c   |  2 +-
 drivers/infiniband/hw/usnic/usnic_uiom.c|  2 +-
 drivers/infiniband/sw/siw/siw_mem.c |  2 +-
 8 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 214e87aa609d..55daefaa9b88 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -266,7 +266,7 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, 
unsigned long addr,
sg = umem->sg_head.sgl;
 
while (npages) {
-   ret = get_user_pages_fast(cur_base,
+   ret = pin_user_pages_fast(cur_base,
  min_t(unsigned long, npages,
PAGE_SIZE /
sizeof(struct page *)),
diff --git a/drivers/infiniband/core/umem_odp.c 
b/drivers/infiniband/core/umem_odp.c
index e42d44e501fd..abc3bb6578cc 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -308,9 +308,8 @@ EXPORT_SYMBOL(ib_umem_odp_release);
  * The function returns -EFAULT if the DMA mapping operation fails. It returns
  * -EAGAIN if a concurrent invalidation prevents us from updating the page.
  *
- * The page is released via put_user_page even if the operation failed. For
- * on-demand pinning, the page is released whenever it isn't stored in the
- * umem.
+ * The page is released via put_page even if the operation failed. For 
on-demand
+ * pinning, the page is released whenever it isn't stored in the umem.
  */
 static int ib_umem_odp_map_dma_single_page(
struct ib_umem_odp *umem_odp,
@@ -363,7 +362,7 @@ static int ib_umem_odp_map_dma_single_page(
}
 
 out:
-   put_user_page(page);
+   put_page(page);
return ret;
 }
 
@@ -473,7 +472,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, 
u64 user_virt,
ret = -EFAULT;
break;
}
-   put_user_page(local_page_list[j]);
+   put_page(local_page_list[j]);
continue;
}
 
@@ -500,8 +499,8 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, 
u64 user_virt,
 * ib_umem_odp_map_dma_single_page().
 */
if (npages - (j + 1) > 0)
-   put_user_pages(_page_list[j+1],
-  npages - (j + 1));
+   release_pages(_page_list[j+1],
+ npages - (j + 1));
break;
}
}
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c 
b/drivers/infiniband/hw/hfi1/user_pages.c
index 469acb961fbd..9a94761765c0 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -106,7 +106,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned 
long vaddr, size_t np
int ret;
unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0);
 
-   ret = get_user_pages_fast(vaddr, npages, gup_flags, pages);
+   ret = pin_user_pages_fast(vaddr, npages, gup_flags, pages);
if (ret < 0)
return ret;
 
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c 
b/drivers/infiniband/hw/mthca/mthca_memfree.c
index edccfd6e178f..8269ab040c21 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -472,7 +472,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct 
mthca_uar *uar,
goto out;
}
 
-   ret = get_user_pages_fast(uaddr & PAGE_MASK, 1,
+   ret = pin_user_pages_fast(uaddr & PAGE_MASK, 1,
  FOLL_WRITE | FOLL_LONGTERM, pages);
if (ret < 0)
goto out;
diff --git 

[PATCH v11 25/25] selftests/vm: run_vmtests: invoke gup_benchmark with basic FOLL_PIN coverage

2019-12-16 Thread John Hubbard
It's good to have basic unit test coverage of the new FOLL_PIN
behavior. Fortunately, the gup_benchmark unit test is extremely
fast (a few milliseconds), so adding it the the run_vmtests suite
is going to cause no noticeable change in running time.

So, add two new invocations to run_vmtests:

1) Run gup_benchmark with normal get_user_pages().

2) Run gup_benchmark with pin_user_pages(). This is much like
the first call, except that it sets FOLL_PIN.

Running these two in quick succession also provide a visual
comparison of the running times, which is convenient.

The new invocations are fairly early in the run_vmtests script,
because with test suites, it's usually preferable to put the
shorter, faster tests first, all other things being equal.

Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 tools/testing/selftests/vm/run_vmtests | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/tools/testing/selftests/vm/run_vmtests 
b/tools/testing/selftests/vm/run_vmtests
index a692ea828317..df6a6bf3f238 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -112,6 +112,28 @@ echo "NOTE: The above hugetlb tests provide minimal 
coverage.  Use"
 echo "  https://github.com/libhugetlbfs/libhugetlbfs.git for"
 echo "  hugetlb regression testing."
 
+echo ""
+echo "running 'gup_benchmark -U' (normal/slow gup)"
+echo ""
+./gup_benchmark -U
+if [ $? -ne 0 ]; then
+   echo "[FAIL]"
+   exitcode=1
+else
+   echo "[PASS]"
+fi
+
+echo "--"
+echo "running gup_benchmark -b (pin_user_pages)"
+echo "--"
+./gup_benchmark -b
+if [ $? -ne 0 ]; then
+   echo "[FAIL]"
+   exitcode=1
+else
+   echo "[PASS]"
+fi
+
 echo "---"
 echo "running userfaultfd"
 echo "---"
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 23/25] mm/gup: track FOLL_PIN pages

2019-12-16 Thread John Hubbard
Add tracking of pages that were pinned via FOLL_PIN.

As mentioned in the FOLL_PIN documentation, callers who effectively set
FOLL_PIN are required to ultimately free such pages via unpin_user_page().
The effect is similar to FOLL_GET, and may be thought of as "FOLL_GET
for DIO and/or RDMA use".

Pages that have been pinned via FOLL_PIN are identifiable via a
new function call:

   bool page_dma_pinned(struct page *page);

What to do in response to encountering such a page, is left to later
patchsets. There is discussion about this in [1], [2], and [3].

This also changes a BUG_ON(), to a WARN_ON(), in follow_page_mask().

[1] Some slow progress on get_user_pages() (Apr 2, 2019):
https://lwn.net/Articles/784574/
[2] DMA and get_user_pages() (LPC: Dec 12, 2018):
https://lwn.net/Articles/774411/
[3] The trouble with get_user_pages() (Apr 30, 2018):
https://lwn.net/Articles/753027/

Reviewed-by: Jan Kara 
Suggested-by: Jan Kara 
Suggested-by: Jérôme Glisse 
Cc: Kirill A. Shutemov 
Signed-off-by: John Hubbard 
---
 Documentation/core-api/pin_user_pages.rst |   2 +-
 include/linux/mm.h|  83 -
 include/linux/mmzone.h|   2 +
 include/linux/page_ref.h  |  10 +
 mm/gup.c  | 409 +-
 mm/huge_memory.c  |  29 +-
 mm/hugetlb.c  |  38 +-
 mm/vmstat.c   |   2 +
 8 files changed, 439 insertions(+), 136 deletions(-)

diff --git a/Documentation/core-api/pin_user_pages.rst 
b/Documentation/core-api/pin_user_pages.rst
index 1d490155ecd7..2db14df1f2d7 100644
--- a/Documentation/core-api/pin_user_pages.rst
+++ b/Documentation/core-api/pin_user_pages.rst
@@ -53,7 +53,7 @@ Which flags are set by each wrapper
 For these pin_user_pages*() functions, FOLL_PIN is OR'd in with whatever gup
 flags the caller provides. The caller is required to pass in a non-null struct
 pages* array, and the function then pin pages by incrementing each by a special
-value. For now, that value is +1, just like get_user_pages*().::
+value: GUP_PIN_COUNTING_BIAS.::
 
  Function
  
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6a1a357e7d86..bb44c4d2ada7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1016,6 +1016,8 @@ static inline void get_page(struct page *page)
page_ref_inc(page);
 }
 
+bool __must_check try_grab_page(struct page *page, unsigned int flags);
+
 static inline __must_check bool try_get_page(struct page *page)
 {
page = compound_head(page);
@@ -1044,29 +1046,80 @@ static inline void put_page(struct page *page)
__put_page(page);
 }
 
-/**
- * unpin_user_page() - release a gup-pinned page
- * @page:pointer to page to be released
+/*
+ * GUP_PIN_COUNTING_BIAS, and the associated functions that use it, overload
+ * the page's refcount so that two separate items are tracked: the original 
page
+ * reference count, and also a new count of how many pin_user_pages() calls 
were
+ * made against the page. ("gup-pinned" is another term for the latter).
+ *
+ * With this scheme, pin_user_pages() becomes special: such pages are marked as
+ * distinct from normal pages. As such, the unpin_user_page() call (and its
+ * variants) must be used in order to release gup-pinned pages.
+ *
+ * Choice of value:
+ *
+ * By making GUP_PIN_COUNTING_BIAS a power of two, debugging of page reference
+ * counts with respect to pin_user_pages() and unpin_user_page() becomes
+ * simpler, due to the fact that adding an even power of two to the page
+ * refcount has the effect of using only the upper N bits, for the code that
+ * counts up using the bias value. This means that the lower bits are left for
+ * the exclusive use of the original code that increments and decrements by one
+ * (or at least, by much smaller values than the bias value).
  *
- * Pages that were pinned via pin_user_pages*() must be released via either
- * unpin_user_page(), or one of the unpin_user_pages*() routines. This is so
- * that eventually such pages can be separately tracked and uniquely handled. 
In
- * particular, interactions with RDMA and filesystems need special handling.
+ * Of course, once the lower bits overflow into the upper bits (and this is
+ * OK, because subtraction recovers the original values), then visual 
inspection
+ * no longer suffices to directly view the separate counts. However, for normal
+ * applications that don't have huge page reference counts, this won't be an
+ * issue.
  *
- * unpin_user_page() and put_page() are not interchangeable, despite this early
- * implementation that makes them look the same. unpin_user_page() calls must
- * be perfectly matched up with pin*() calls.
+ * Locking: the lockless algorithm described in page_cache_get_speculative()
+ * and page_cache_gup_pin_speculative() provides safe operation for
+ * get_user_pages and page_mkclean and other calls that 

[PATCH v11 17/25] media/v4l2-core: set pages dirty upon releasing DMA buffers

2019-12-16 Thread John Hubbard
After DMA is complete, and the device and CPU caches are synchronized,
it's still required to mark the CPU pages as dirty, if the data was
coming from the device. However, this driver was just issuing a
bare put_page() call, without any set_page_dirty*() call.

Fix the problem, by calling set_page_dirty_lock() if the CPU pages
were potentially receiving data from the device.

Reviewed-by: Christoph Hellwig 
Acked-by: Hans Verkuil 
Cc: Mauro Carvalho Chehab 
Cc: 
Signed-off-by: John Hubbard 
---
 drivers/media/v4l2-core/videobuf-dma-sg.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c 
b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 66a6c6c236a7..28262190c3ab 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -349,8 +349,11 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
BUG_ON(dma->sglen);
 
if (dma->pages) {
-   for (i = 0; i < dma->nr_pages; i++)
+   for (i = 0; i < dma->nr_pages; i++) {
+   if (dma->direction == DMA_FROM_DEVICE)
+   set_page_dirty_lock(dma->pages[i]);
put_page(dma->pages[i]);
+   }
kfree(dma->pages);
dma->pages = NULL;
}
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 08/25] mm/gup: allow FOLL_FORCE for get_user_pages_fast()

2019-12-16 Thread John Hubbard
Commit 817be129e6f2 ("mm: validate get_user_pages_fast flags") allowed
only FOLL_WRITE and FOLL_LONGTERM to be passed to get_user_pages_fast().
This, combined with the fact that get_user_pages_fast() falls back to
"slow gup", which *does* accept FOLL_FORCE, leads to an odd situation:
if you need FOLL_FORCE, you cannot call get_user_pages_fast().

There does not appear to be any reason for filtering out FOLL_FORCE.
There is nothing in the _fast() implementation that requires that we
avoid writing to the pages. So it appears to have been an oversight.

Fix by allowing FOLL_FORCE to be set for get_user_pages_fast().

Fixes: 817be129e6f2 ("mm: validate get_user_pages_fast flags")
Cc: Christoph Hellwig 
Reviewed-by: Leon Romanovsky 
Reviewed-by: Jan Kara 
Signed-off-by: John Hubbard 
---
 mm/gup.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/gup.c b/mm/gup.c
index c0c56888e7cc..958ab0757389 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2414,7 +2414,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages,
unsigned long addr, len, end;
int nr = 0, ret = 0;
 
-   if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM)))
+   if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM |
+  FOLL_FORCE)))
return -EINVAL;
 
start = untagged_addr(start) & PAGE_MASK;
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 18/25] media/v4l2-core: pin_user_pages (FOLL_PIN) and put_user_page() conversion

2019-12-16 Thread John Hubbard
1. Change v4l2 from get_user_pages() to pin_user_pages().

2. Because all FOLL_PIN-acquired pages must be released via
put_user_page(), also convert the put_page() call over to
put_user_pages_dirty_lock().

Acked-by: Hans Verkuil 
Cc: Ira Weiny 
Signed-off-by: John Hubbard 
---
 drivers/media/v4l2-core/videobuf-dma-sg.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c 
b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 28262190c3ab..162a2633b1e3 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -183,12 +183,12 @@ static int videobuf_dma_init_user_locked(struct 
videobuf_dmabuf *dma,
dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
data, size, dma->nr_pages);
 
-   err = get_user_pages(data & PAGE_MASK, dma->nr_pages,
+   err = pin_user_pages(data & PAGE_MASK, dma->nr_pages,
 flags | FOLL_LONGTERM, dma->pages, NULL);
 
if (err != dma->nr_pages) {
dma->nr_pages = (err >= 0) ? err : 0;
-   dprintk(1, "get_user_pages: err=%d [%d]\n", err,
+   dprintk(1, "pin_user_pages: err=%d [%d]\n", err,
dma->nr_pages);
return err < 0 ? err : -EINVAL;
}
@@ -349,11 +349,8 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
BUG_ON(dma->sglen);
 
if (dma->pages) {
-   for (i = 0; i < dma->nr_pages; i++) {
-   if (dma->direction == DMA_FROM_DEVICE)
-   set_page_dirty_lock(dma->pages[i]);
-   put_page(dma->pages[i]);
-   }
+   put_user_pages_dirty_lock(dma->pages, dma->nr_pages,
+ dma->direction == DMA_FROM_DEVICE);
kfree(dma->pages);
dma->pages = NULL;
}
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 03/25] mm: Cleanup __put_devmap_managed_page() vs ->page_free()

2019-12-16 Thread John Hubbard
From: Dan Williams 

After the removal of the device-public infrastructure there are only 2
->page_free() call backs in the kernel. One of those is a device-private
callback in the nouveau driver, the other is a generic wakeup needed in
the DAX case. In the hopes that all ->page_free() callbacks can be
migrated to common core kernel functionality, move the device-private
specific actions in __put_devmap_managed_page() under the
is_device_private_page() conditional, including the ->page_free()
callback. For the other page types just open-code the generic wakeup.

Yes, the wakeup is only needed in the MEMORY_DEVICE_FSDAX case, but it
does no harm in the MEMORY_DEVICE_DEVDAX and MEMORY_DEVICE_PCI_P2PDMA
case.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Jérôme Glisse 
Cc: Jan Kara 
Cc: Ira Weiny 
Signed-off-by: Dan Williams 
Signed-off-by: John Hubbard 
---
 drivers/nvdimm/pmem.c |  6 
 mm/memremap.c | 80 ---
 2 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index ad8e4df1282b..4eae441f86c9 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -337,13 +337,7 @@ static void pmem_release_disk(void *__pmem)
put_disk(pmem->disk);
 }
 
-static void pmem_pagemap_page_free(struct page *page)
-{
-   wake_up_var(>_refcount);
-}
-
 static const struct dev_pagemap_ops fsdax_pagemap_ops = {
-   .page_free  = pmem_pagemap_page_free,
.kill   = pmem_pagemap_kill,
.cleanup= pmem_pagemap_cleanup,
 };
diff --git a/mm/memremap.c b/mm/memremap.c
index 03ccbdfeb697..e899fa876a62 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -27,7 +27,8 @@ static void devmap_managed_enable_put(void)
 
 static int devmap_managed_enable_get(struct dev_pagemap *pgmap)
 {
-   if (!pgmap->ops || !pgmap->ops->page_free) {
+   if (pgmap->type == MEMORY_DEVICE_PRIVATE &&
+   (!pgmap->ops || !pgmap->ops->page_free)) {
WARN(1, "Missing page_free method\n");
return -EINVAL;
}
@@ -414,44 +415,51 @@ void __put_devmap_managed_page(struct page *page)
 {
int count = page_ref_dec_return(page);
 
-   /*
-* If refcount is 1 then page is freed and refcount is stable as nobody
-* holds a reference on the page.
-*/
-   if (count == 1) {
-   /* Clear Active bit in case of parallel mark_page_accessed */
-   __ClearPageActive(page);
-   __ClearPageWaiters(page);
+   /* still busy */
+   if (count > 1)
+   return;
 
-   mem_cgroup_uncharge(page);
+   /* only triggered by the dev_pagemap shutdown path */
+   if (count == 0) {
+   __put_page(page);
+   return;
+   }
 
-   /*
-* When a device_private page is freed, the page->mapping field
-* may still contain a (stale) mapping value. For example, the
-* lower bits of page->mapping may still identify the page as
-* an anonymous page. Ultimately, this entire field is just
-* stale and wrong, and it will cause errors if not cleared.
-* One example is:
-*
-*  migrate_vma_pages()
-*migrate_vma_insert_page()
-*  page_add_new_anon_rmap()
-*__page_set_anon_rmap()
-*  ...checks page->mapping, via PageAnon(page) call,
-*and incorrectly concludes that the page is an
-*anonymous page. Therefore, it incorrectly,
-*silently fails to set up the new anon rmap.
-*
-* For other types of ZONE_DEVICE pages, migration is either
-* handled differently or not done at all, so there is no need
-* to clear page->mapping.
-*/
-   if (is_device_private_page(page))
-   page->mapping = NULL;
+   /* notify page idle for dax */
+   if (!is_device_private_page(page)) {
+   wake_up_var(>_refcount);
+   return;
+   }
 
-   page->pgmap->ops->page_free(page);
-   } else if (!count)
-   __put_page(page);
+   /* Clear Active bit in case of parallel mark_page_accessed */
+   __ClearPageActive(page);
+   __ClearPageWaiters(page);
+
+   mem_cgroup_uncharge(page);
+
+   /*
+* When a device_private page is freed, the page->mapping field
+* may still contain a (stale) mapping value. For example, the
+* lower bits of page->mapping may still identify the page as an
+* anonymous page. Ultimately, this entire field is just stale
+* and wrong, and it will cause errors if not cleared.  One
+* example is:
+*
+*  

[PATCH v11 21/25] mm/gup_benchmark: use proper FOLL_WRITE flags instead of hard-coding "1"

2019-12-16 Thread John Hubbard
Fix the gup benchmark flags to use the symbolic FOLL_WRITE,
instead of a hard-coded "1" value.

Also, clean up the filtering of gup flags a little, by just doing
it once before issuing any of the get_user_pages*() calls. This
makes it harder to overlook, instead of having little "gup_flags & 1"
phrases in the function calls.

Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 mm/gup_benchmark.c | 9 ++---
 tools/testing/selftests/vm/gup_benchmark.c | 6 +-
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/mm/gup_benchmark.c b/mm/gup_benchmark.c
index 7dd602d7f8db..7fc44d25eca7 100644
--- a/mm/gup_benchmark.c
+++ b/mm/gup_benchmark.c
@@ -48,18 +48,21 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
nr = (next - addr) / PAGE_SIZE;
}
 
+   /* Filter out most gup flags: only allow a tiny subset here: */
+   gup->flags &= FOLL_WRITE;
+
switch (cmd) {
case GUP_FAST_BENCHMARK:
-   nr = get_user_pages_fast(addr, nr, gup->flags & 1,
+   nr = get_user_pages_fast(addr, nr, gup->flags,
 pages + i);
break;
case GUP_LONGTERM_BENCHMARK:
nr = get_user_pages(addr, nr,
-   (gup->flags & 1) | FOLL_LONGTERM,
+   gup->flags | FOLL_LONGTERM,
pages + i, NULL);
break;
case GUP_BENCHMARK:
-   nr = get_user_pages(addr, nr, gup->flags & 1, pages + i,
+   nr = get_user_pages(addr, nr, gup->flags, pages + i,
NULL);
break;
default:
diff --git a/tools/testing/selftests/vm/gup_benchmark.c 
b/tools/testing/selftests/vm/gup_benchmark.c
index 485cf06ef013..389327e9b30a 100644
--- a/tools/testing/selftests/vm/gup_benchmark.c
+++ b/tools/testing/selftests/vm/gup_benchmark.c
@@ -18,6 +18,9 @@
 #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark)
 #define GUP_BENCHMARK  _IOWR('g', 3, struct gup_benchmark)
 
+/* Just the flags we need, copied from mm.h: */
+#define FOLL_WRITE 0x01/* check pte is writable */
+
 struct gup_benchmark {
__u64 get_delta_usec;
__u64 put_delta_usec;
@@ -85,7 +88,8 @@ int main(int argc, char **argv)
}
 
gup.nr_pages_per_call = nr_pages;
-   gup.flags = write;
+   if (write)
+   gup.flags |= FOLL_WRITE;
 
fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR);
if (fd == -1)
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 24/25] mm/gup_benchmark: support pin_user_pages() and related calls

2019-12-16 Thread John Hubbard
Up until now, gup_benchmark supported testing of the
following kernel functions:

* get_user_pages(): via the '-U' command line option
* get_user_pages_longterm(): via the '-L' command line option
* get_user_pages_fast(): as the default (no options required)

Add test coverage for the new corresponding pin_*() functions:

* pin_user_pages_fast(): via the '-a' command line option
* pin_user_pages():  via the '-b' command line option

Also, add an option for clarity: '-u' for what is now (still) the
default choice: get_user_pages_fast().

Also, for the commands that set FOLL_PIN, verify that the pages
really are dma-pinned, via the new is_dma_pinned() routine.
Those commands are:

PIN_FAST_BENCHMARK : calls pin_user_pages_fast()
PIN_BENCHMARK  : calls pin_user_pages()

In between the calls to pin_*() and unpin_user_pages(),
check each page: if page_dma_pinned() returns false, then
WARN and return.

Do this outside of the benchmark timestamps, so that it doesn't
affect reported times.

Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 mm/gup_benchmark.c | 65 --
 tools/testing/selftests/vm/gup_benchmark.c | 15 -
 2 files changed, 74 insertions(+), 6 deletions(-)

diff --git a/mm/gup_benchmark.c b/mm/gup_benchmark.c
index 7fc44d25eca7..76d32db48af8 100644
--- a/mm/gup_benchmark.c
+++ b/mm/gup_benchmark.c
@@ -8,6 +8,8 @@
 #define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark)
 #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark)
 #define GUP_BENCHMARK  _IOWR('g', 3, struct gup_benchmark)
+#define PIN_FAST_BENCHMARK _IOWR('g', 4, struct gup_benchmark)
+#define PIN_BENCHMARK  _IOWR('g', 5, struct gup_benchmark)
 
 struct gup_benchmark {
__u64 get_delta_usec;
@@ -19,6 +21,42 @@ struct gup_benchmark {
__u64 expansion[10];/* For future use */
 };
 
+static void put_back_pages(int cmd, struct page **pages, unsigned long 
nr_pages)
+{
+   int i;
+
+   switch (cmd) {
+   case GUP_FAST_BENCHMARK:
+   case GUP_LONGTERM_BENCHMARK:
+   case GUP_BENCHMARK:
+   for (i = 0; i < nr_pages; i++)
+   put_page(pages[i]);
+   break;
+
+   case PIN_FAST_BENCHMARK:
+   case PIN_BENCHMARK:
+   unpin_user_pages(pages, nr_pages);
+   break;
+   }
+}
+
+static void verify_dma_pinned(int cmd, struct page **pages,
+ unsigned long nr_pages)
+{
+   int i;
+
+   switch (cmd) {
+   case PIN_FAST_BENCHMARK:
+   case PIN_BENCHMARK:
+   for (i = 0; i < nr_pages; i++) {
+   if (WARN(!page_dma_pinned(pages[i]),
+"pages[%d] is NOT dma-pinned\n", i))
+   break;
+   }
+   break;
+   }
+}
+
 static int __gup_benchmark_ioctl(unsigned int cmd,
struct gup_benchmark *gup)
 {
@@ -65,6 +103,14 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
nr = get_user_pages(addr, nr, gup->flags, pages + i,
NULL);
break;
+   case PIN_FAST_BENCHMARK:
+   nr = pin_user_pages_fast(addr, nr, gup->flags,
+pages + i);
+   break;
+   case PIN_BENCHMARK:
+   nr = pin_user_pages(addr, nr, gup->flags, pages + i,
+   NULL);
+   break;
default:
return -1;
}
@@ -75,15 +121,22 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
}
end_time = ktime_get();
 
+   /* Shifting the meaning of nr_pages: now it is actual number pinned: */
+   nr_pages = i;
+
gup->get_delta_usec = ktime_us_delta(end_time, start_time);
gup->size = addr - gup->addr;
 
+   /*
+* Take an un-benchmark-timed moment to verify DMA pinned
+* state: print a warning if any non-dma-pinned pages are found:
+*/
+   verify_dma_pinned(cmd, pages, nr_pages);
+
start_time = ktime_get();
-   for (i = 0; i < nr_pages; i++) {
-   if (!pages[i])
-   break;
-   put_page(pages[i]);
-   }
+
+   put_back_pages(cmd, pages, nr_pages);
+
end_time = ktime_get();
gup->put_delta_usec = ktime_us_delta(end_time, start_time);
 
@@ -101,6 +154,8 @@ static long gup_benchmark_ioctl(struct file *filep, 
unsigned int cmd,
case GUP_FAST_BENCHMARK:
case GUP_LONGTERM_BENCHMARK:
case GUP_BENCHMARK:
+   case PIN_FAST_BENCHMARK:
+   case PIN_BENCHMARK:
break;
default:
return -EINVAL;
diff --git a/tools/testing/selftests/vm/gup_benchmark.c 

[PATCH v11 13/25] mm/process_vm_access: set FOLL_PIN via pin_user_pages_remote()

2019-12-16 Thread John Hubbard
Convert process_vm_access to use the new pin_user_pages_remote()
call, which sets FOLL_PIN. Setting FOLL_PIN is now required for
code that requires tracking of pinned pages.

Also, release the pages via put_user_page*().

Also, rename "pages" to "pinned_pages", as this makes for
easier reading of process_vm_rw_single_vec().

Reviewed-by: Jan Kara 
Reviewed-by: Jérôme Glisse 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 mm/process_vm_access.c | 28 +++-
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index 357aa7bef6c0..fd20ab675b85 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -42,12 +42,11 @@ static int process_vm_rw_pages(struct page **pages,
if (copy > len)
copy = len;
 
-   if (vm_write) {
+   if (vm_write)
copied = copy_page_from_iter(page, offset, copy, iter);
-   set_page_dirty_lock(page);
-   } else {
+   else
copied = copy_page_to_iter(page, offset, copy, iter);
-   }
+
len -= copied;
if (copied < copy && iov_iter_count(iter))
return -EFAULT;
@@ -96,7 +95,7 @@ static int process_vm_rw_single_vec(unsigned long addr,
flags |= FOLL_WRITE;
 
while (!rc && nr_pages && iov_iter_count(iter)) {
-   int pages = min(nr_pages, max_pages_per_loop);
+   int pinned_pages = min(nr_pages, max_pages_per_loop);
int locked = 1;
size_t bytes;
 
@@ -106,14 +105,15 @@ static int process_vm_rw_single_vec(unsigned long addr,
 * current/current->mm
 */
down_read(>mmap_sem);
-   pages = get_user_pages_remote(task, mm, pa, pages, flags,
- process_pages, NULL, );
+   pinned_pages = pin_user_pages_remote(task, mm, pa, pinned_pages,
+flags, process_pages,
+NULL, );
if (locked)
up_read(>mmap_sem);
-   if (pages <= 0)
+   if (pinned_pages <= 0)
return -EFAULT;
 
-   bytes = pages * PAGE_SIZE - start_offset;
+   bytes = pinned_pages * PAGE_SIZE - start_offset;
if (bytes > len)
bytes = len;
 
@@ -122,10 +122,12 @@ static int process_vm_rw_single_vec(unsigned long addr,
 vm_write);
len -= bytes;
start_offset = 0;
-   nr_pages -= pages;
-   pa += pages * PAGE_SIZE;
-   while (pages)
-   put_page(process_pages[--pages]);
+   nr_pages -= pinned_pages;
+   pa += pinned_pages * PAGE_SIZE;
+
+   /* If vm_write is set, the pages need to be made dirty: */
+   put_user_pages_dirty_lock(process_pages, pinned_pages,
+ vm_write);
}
 
return rc;
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 16/25] net/xdp: set FOLL_PIN via pin_user_pages()

2019-12-16 Thread John Hubbard
Convert net/xdp to use the new pin_longterm_pages() call, which sets
FOLL_PIN. Setting FOLL_PIN is now required for code that requires
tracking of pinned pages.

In partial anticipation of this work, the net/xdp code was already
calling put_user_page() instead of put_page(). Therefore, in order to
convert from the get_user_pages()/put_page() model, to the
pin_user_pages()/put_user_page() model, the only change required
here is to change get_user_pages() to pin_user_pages().

Acked-by: Björn Töpel 
Signed-off-by: John Hubbard 
---
 net/xdp/xdp_umem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 3049af269fbf..d071003b5e76 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c
@@ -291,7 +291,7 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem)
return -ENOMEM;
 
down_read(>mm->mmap_sem);
-   npgs = get_user_pages(umem->address, umem->npgs,
+   npgs = pin_user_pages(umem->address, umem->npgs,
  gup_flags | FOLL_LONGTERM, >pgs[0], NULL);
up_read(>mm->mmap_sem);
 
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 09/25] IB/umem: use get_user_pages_fast() to pin DMA pages

2019-12-16 Thread John Hubbard
And get rid of the mmap_sem calls, as part of that. Note
that get_user_pages_fast() will, if necessary, fall back to
__gup_longterm_unlocked(), which takes the mmap_sem as needed.

Reviewed-by: Leon Romanovsky 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Jan Kara 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 drivers/infiniband/core/umem.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 7a3b99597ead..214e87aa609d 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -266,16 +266,13 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, 
unsigned long addr,
sg = umem->sg_head.sgl;
 
while (npages) {
-   down_read(>mmap_sem);
-   ret = get_user_pages(cur_base,
-min_t(unsigned long, npages,
-  PAGE_SIZE / sizeof (struct page *)),
-gup_flags | FOLL_LONGTERM,
-page_list, NULL);
-   if (ret < 0) {
-   up_read(>mmap_sem);
+   ret = get_user_pages_fast(cur_base,
+ min_t(unsigned long, npages,
+   PAGE_SIZE /
+   sizeof(struct page *)),
+ gup_flags | FOLL_LONGTERM, page_list);
+   if (ret < 0)
goto umem_release;
-   }
 
cur_base += ret * PAGE_SIZE;
npages   -= ret;
@@ -283,8 +280,6 @@ struct ib_umem *ib_umem_get(struct ib_udata *udata, 
unsigned long addr,
sg = ib_umem_add_sg_table(sg, page_list, ret,
dma_get_max_seg_size(context->device->dma_device),
>sg_nents);
-
-   up_read(>mmap_sem);
}
 
sg_mark_end(sg);
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 02/25] mm/gup: move try_get_compound_head() to top, fix minor issues

2019-12-16 Thread John Hubbard
An upcoming patch uses try_get_compound_head() more widely,
so move it to the top of gup.c.

Also fix a tiny spelling error and a checkpatch.pl warning.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Jan Kara 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 mm/gup.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index f764432914c4..3ecce297a47f 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -29,6 +29,21 @@ struct follow_page_context {
unsigned int page_mask;
 };
 
+/*
+ * Return the compound head page with ref appropriately incremented,
+ * or NULL if that failed.
+ */
+static inline struct page *try_get_compound_head(struct page *page, int refs)
+{
+   struct page *head = compound_head(page);
+
+   if (WARN_ON_ONCE(page_ref_count(head) < 0))
+   return NULL;
+   if (unlikely(!page_cache_add_speculative(head, refs)))
+   return NULL;
+   return head;
+}
+
 /**
  * put_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages
  * @pages:  array of pages to be maybe marked dirty, and definitely released.
@@ -1807,20 +1822,6 @@ static void __maybe_unused undo_dev_pagemap(int *nr, int 
nr_start,
}
 }
 
-/*
- * Return the compund head page with ref appropriately incremented,
- * or NULL if that failed.
- */
-static inline struct page *try_get_compound_head(struct page *page, int refs)
-{
-   struct page *head = compound_head(page);
-   if (WARN_ON_ONCE(page_ref_count(head) < 0))
-   return NULL;
-   if (unlikely(!page_cache_add_speculative(head, refs)))
-   return NULL;
-   return head;
-}
-
 #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
 static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
 unsigned int flags, struct page **pages, int *nr)
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 04/25] mm: devmap: refactor 1-based refcounting for ZONE_DEVICE pages

2019-12-16 Thread John Hubbard
An upcoming patch changes and complicates the refcounting and
especially the "put page" aspects of it. In order to keep
everything clean, refactor the devmap page release routines:

* Rename put_devmap_managed_page() to page_is_devmap_managed(),
  and limit the functionality to "read only": return a bool,
  with no side effects.

* Add a new routine, put_devmap_managed_page(), to handle checking
  what kind of page it is, and what kind of refcount handling it
  requires.

* Rename __put_devmap_managed_page() to free_devmap_managed_page(),
  and limit the functionality to unconditionally freeing a devmap
  page.

This is originally based on a separate patch by Ira Weiny, which
applied to an early version of the put_user_page() experiments.
Since then, Jérôme Glisse suggested the refactoring described above.

Cc: Christoph Hellwig 
Suggested-by: Jérôme Glisse 
Reviewed-by: Dan Williams 
Reviewed-by: Jan Kara 
Signed-off-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 include/linux/mm.h | 17 +
 mm/memremap.c  | 16 ++--
 mm/swap.c  | 24 
 3 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index c97ea3b694e6..77a4df06c8a7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -952,9 +952,10 @@ static inline bool is_zone_device_page(const struct page 
*page)
 #endif
 
 #ifdef CONFIG_DEV_PAGEMAP_OPS
-void __put_devmap_managed_page(struct page *page);
+void free_devmap_managed_page(struct page *page);
 DECLARE_STATIC_KEY_FALSE(devmap_managed_key);
-static inline bool put_devmap_managed_page(struct page *page)
+
+static inline bool page_is_devmap_managed(struct page *page)
 {
if (!static_branch_unlikely(_managed_key))
return false;
@@ -963,7 +964,6 @@ static inline bool put_devmap_managed_page(struct page 
*page)
switch (page->pgmap->type) {
case MEMORY_DEVICE_PRIVATE:
case MEMORY_DEVICE_FS_DAX:
-   __put_devmap_managed_page(page);
return true;
default:
break;
@@ -971,7 +971,14 @@ static inline bool put_devmap_managed_page(struct page 
*page)
return false;
 }
 
+bool put_devmap_managed_page(struct page *page);
+
 #else /* CONFIG_DEV_PAGEMAP_OPS */
+static inline bool page_is_devmap_managed(struct page *page)
+{
+   return false;
+}
+
 static inline bool put_devmap_managed_page(struct page *page)
 {
return false;
@@ -1028,8 +1035,10 @@ static inline void put_page(struct page *page)
 * need to inform the device driver through callback. See
 * include/linux/memremap.h and HMM for details.
 */
-   if (put_devmap_managed_page(page))
+   if (page_is_devmap_managed(page)) {
+   put_devmap_managed_page(page);
return;
+   }
 
if (put_page_testzero(page))
__put_page(page);
diff --git a/mm/memremap.c b/mm/memremap.c
index e899fa876a62..2ba773859031 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -411,20 +411,8 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
 EXPORT_SYMBOL_GPL(get_dev_pagemap);
 
 #ifdef CONFIG_DEV_PAGEMAP_OPS
-void __put_devmap_managed_page(struct page *page)
+void free_devmap_managed_page(struct page *page)
 {
-   int count = page_ref_dec_return(page);
-
-   /* still busy */
-   if (count > 1)
-   return;
-
-   /* only triggered by the dev_pagemap shutdown path */
-   if (count == 0) {
-   __put_page(page);
-   return;
-   }
-
/* notify page idle for dax */
if (!is_device_private_page(page)) {
wake_up_var(>_refcount);
@@ -461,5 +449,5 @@ void __put_devmap_managed_page(struct page *page)
page->mapping = NULL;
page->pgmap->ops->page_free(page);
 }
-EXPORT_SYMBOL(__put_devmap_managed_page);
+EXPORT_SYMBOL(free_devmap_managed_page);
 #endif /* CONFIG_DEV_PAGEMAP_OPS */
diff --git a/mm/swap.c b/mm/swap.c
index 5341ae93861f..49f7c2eea0ba 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -1102,3 +1102,27 @@ void __init swap_setup(void)
 * _really_ don't want to cluster much more
 */
 }
+
+#ifdef CONFIG_DEV_PAGEMAP_OPS
+bool put_devmap_managed_page(struct page *page)
+{
+   bool is_devmap = page_is_devmap_managed(page);
+
+   if (is_devmap) {
+   int count = page_ref_dec_return(page);
+
+   /*
+* devmap page refcounts are 1-based, rather than 0-based: if
+* refcount is 1, then the page is free and the refcount is
+* stable because nobody holds a reference on the page.
+*/
+   if (count == 1)
+   free_devmap_managed_page(page);
+   else if (!count)
+   __put_page(page);
+   }
+
+   return is_devmap;
+}
+EXPORT_SYMBOL(put_devmap_managed_page);
+#endif
-- 
2.24.1


[PATCH v11 05/25] goldish_pipe: rename local pin_user_pages() routine

2019-12-16 Thread John Hubbard
1. Avoid naming conflicts: rename local static function from
"pin_user_pages()" to "goldfish_pin_pages()".

An upcoming patch will introduce a global pin_user_pages()
function.

Reviewed-by: Jan Kara 
Reviewed-by: Jérôme Glisse 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 drivers/platform/goldfish/goldfish_pipe.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/goldfish/goldfish_pipe.c 
b/drivers/platform/goldfish/goldfish_pipe.c
index cef0133aa47a..ef50c264db71 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -257,12 +257,12 @@ static int goldfish_pipe_error_convert(int status)
}
 }
 
-static int pin_user_pages(unsigned long first_page,
- unsigned long last_page,
- unsigned int last_page_size,
- int is_write,
- struct page *pages[MAX_BUFFERS_PER_COMMAND],
- unsigned int *iter_last_page_size)
+static int goldfish_pin_pages(unsigned long first_page,
+ unsigned long last_page,
+ unsigned int last_page_size,
+ int is_write,
+ struct page *pages[MAX_BUFFERS_PER_COMMAND],
+ unsigned int *iter_last_page_size)
 {
int ret;
int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1;
@@ -354,9 +354,9 @@ static int transfer_max_buffers(struct goldfish_pipe *pipe,
if (mutex_lock_interruptible(>lock))
return -ERESTARTSYS;
 
-   pages_count = pin_user_pages(first_page, last_page,
-last_page_size, is_write,
-pipe->pages, _last_page_size);
+   pages_count = goldfish_pin_pages(first_page, last_page,
+last_page_size, is_write,
+pipe->pages, _last_page_size);
if (pages_count < 0) {
mutex_unlock(>lock);
return pages_count;
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 06/25] mm: fix get_user_pages_remote()'s handling of FOLL_LONGTERM

2019-12-16 Thread John Hubbard
As it says in the updated comment in gup.c: current FOLL_LONGTERM
behavior is incompatible with FAULT_FLAG_ALLOW_RETRY because of the
FS DAX check requirement on vmas.

However, the corresponding restriction in get_user_pages_remote() was
slightly stricter than is actually required: it forbade all
FOLL_LONGTERM callers, but we can actually allow FOLL_LONGTERM callers
that do not set the "locked" arg.

Update the code and comments to loosen the restriction, allowing
FOLL_LONGTERM in some cases.

Also, copy the DAX check ("if a VMA is DAX, don't allow long term
pinning") from the VFIO call site, all the way into the internals
of get_user_pages_remote() and __gup_longterm_locked(). That is:
get_user_pages_remote() calls __gup_longterm_locked(), which in turn
calls check_dax_vmas(). This check will then be removed from the VFIO
call site in a subsequent patch.

Thanks to Jason Gunthorpe for pointing out a clean way to fix this,
and to Dan Williams for helping clarify the DAX refactoring.

Tested-by: Alex Williamson 
Acked-by: Alex Williamson 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Ira Weiny 
Suggested-by: Jason Gunthorpe 
Cc: Dan Williams 
Cc: Jerome Glisse 
Signed-off-by: John Hubbard 
---
 mm/gup.c | 27 ++-
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index 3ecce297a47f..c0c56888e7cc 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -29,6 +29,13 @@ struct follow_page_context {
unsigned int page_mask;
 };
 
+static __always_inline long __gup_longterm_locked(struct task_struct *tsk,
+ struct mm_struct *mm,
+ unsigned long start,
+ unsigned long nr_pages,
+ struct page **pages,
+ struct vm_area_struct **vmas,
+ unsigned int flags);
 /*
  * Return the compound head page with ref appropriately incremented,
  * or NULL if that failed.
@@ -1179,13 +1186,23 @@ long get_user_pages_remote(struct task_struct *tsk, 
struct mm_struct *mm,
struct vm_area_struct **vmas, int *locked)
 {
/*
-* FIXME: Current FOLL_LONGTERM behavior is incompatible with
+* Parts of FOLL_LONGTERM behavior are incompatible with
 * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on
-* vmas.  As there are no users of this flag in this call we simply
-* disallow this option for now.
+* vmas. However, this only comes up if locked is set, and there are
+* callers that do request FOLL_LONGTERM, but do not set locked. So,
+* allow what we can.
 */
-   if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM))
-   return -EINVAL;
+   if (gup_flags & FOLL_LONGTERM) {
+   if (WARN_ON_ONCE(locked))
+   return -EINVAL;
+   /*
+* This will check the vmas (even if our vmas arg is NULL)
+* and return -ENOTSUPP if DAX isn't allowed in this case:
+*/
+   return __gup_longterm_locked(tsk, mm, start, nr_pages, pages,
+vmas, gup_flags | FOLL_TOUCH |
+FOLL_REMOTE);
+   }
 
return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
   locked,
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v11 00/25] mm/gup: track dma-pinned pages: FOLL_PIN

2019-12-16 Thread John Hubbard
Hi,

This implements an API naming change (put_user_page*() -->
unpin_user_page*()), and also implements tracking of FOLL_PIN pages. It
extends that tracking to a few select subsystems. More subsystems will
be added in follow up work.

Christoph Hellwig, a point of interest:

a) I've moved the bulk of the code out of the inline functions, as
   requested, for the devmap changes (patch 4: "mm: devmap: refactor
   1-based refcounting for ZONE_DEVICE pages").

Changes since v10: Remaining fixes resulting from Jan Kara's reviews:

* Shifted to using the sign bit in page_dma_pinned() to allow accurate
  results even in the overflow case. See the comments in that routine
  for details. This allowed getting rid of the new
  page_ref_zero_or_close_to_bias_overflow(), in favor of a simple
  sign check via "page_ref_count() <= 0").

* Simplified some of the huge_memory.c changes, and simplified a gup.c
  WARN invocation.

* Now using a standard -ENOMEM for most try_grab_page() failures.

* Got rid of tabs in the comment headers (I had thought they were
  required there, but it's actually the reverse: they are not
  allowed there).

* Rebased against 5.5-rc2 and retested.

* Added Jan Kara's reviewed-by tag for patch 23 (the main patch of the
  series).

Changes since v9: Fixes resulting from Jan Kara's and Jonathan Corbet's
reviews:

* Removed reviewed-by tags from the "mm/gup: track FOLL_PIN pages" (those
  were improperly inherited from the much smaller refactoring patch that
  was merged into it).

* Made try_grab_compound_head() and try_grab_page() behavior similar in
  their behavior with flags, in order to avoid "gotchas" later.

* follow_trans_huge_pmd(): moved the try_grab_page() to earlier in the
  routine, in order to avoid having to undo mlock_vma_page().

* follow_hugetlb_page(): removed a refcount overflow check that is now
  extraneous (and weaker than what try_grab_page() provides a few lines
  further down).

* Fixed up two Documentation flaws, pointed out by Jonathan Corbet's
  review.

Changes since v8:

* Merged the "mm/gup: pass flags arg to __gup_device_* functions" patch
  into the "mm/gup: track FOLL_PIN pages" patch, as requested by
  Christoph and Jan.

* Changed void grab_page() to bool try_grab_page(), and handled errors
  at the call sites. (From Jan's review comments.) try_grab_page()
  attempts to avoid page refcount overflows, even when counting up with
  GUP_PIN_COUNTING_BIAS increments.

* Fixed a bug that I'd introduced, when changing a BUG() to a WARN().

* Added Jan's reviewed-by tag to the " mm/gup: allow FOLL_FORCE for
  get_user_pages_fast()" patch.

* Documentation: pin_user_pages.rst: fixed an incorrect gup_benchmark
  invocation, left over from the pin_longterm days, spotted while preparing
  this version.

* Rebased onto today's linux.git (-rc1), and re-tested.

Changes since v7:

* Rebased onto Linux 5.5-rc1

* Reworked the grab_page() and try_grab_compound_head(), for API
  consistency and less diffs (thanks to Jan Kara's reviews).

* Added Leon Romanovsky's reviewed-by tags for two of the IB-related
  patches.

* patch 4 refactoring changes, as mentioned above.

There is a git repo and branch, for convenience:

g...@github.com:johnhubbard/linux.git pin_user_pages_tracking_v8

For the remaining list of "changes since version N", those are all in
v7, which is here:

  https://lore.kernel.org/r/20191121071354.456618-1-jhubb...@nvidia.com


Overview:

This is a prerequisite to solving the problem of proper interactions
between file-backed pages, and [R]DMA activities, as discussed in [1],
[2], [3], and in a remarkable number of email threads since about
2017. :)

A new internal gup flag, FOLL_PIN is introduced, and thoroughly
documented in the last patch's Documentation/vm/pin_user_pages.rst.

I believe that this will provide a good starting point for doing the
layout lease work that Ira Weiny has been working on. That's because
these new wrapper functions provide a clean, constrained, systematically
named set of functionality that, again, is required in order to even
know if a page is "dma-pinned".

In contrast to earlier approaches, the page tracking can be
incrementally applied to the kernel call sites that, until now, have
been simply calling get_user_pages() ("gup"). In other words, opt-in by
changing from this:

get_user_pages() (sets FOLL_GET)
put_page()

to this:
pin_user_pages() (sets FOLL_PIN)
unpin_user_page()


Testing:

* I've done some overall kernel testing (LTP, and a few other goodies),
  and some directed testing to exercise some of the changes. And as you
  can see, gup_benchmark is enhanced to exercise this. Basically, I've
  been able to runtime test the core get_user_pages() and
  pin_user_pages() and related routines, but not so much on several of
  the call sites--but those are generally just a couple of lines
  

[PATCH v11 01/25] mm/gup: factor out duplicate code from four routines

2019-12-16 Thread John Hubbard
There are four locations in gup.c that have a fair amount of code
duplication. This means that changing one requires making the same
changes in four places, not to mention reading the same code four
times, and wondering if there are subtle differences.

Factor out the common code into static functions, thus reducing the
overall line count and the code's complexity.

Also, take the opportunity to slightly improve the efficiency of the
error cases, by doing a mass subtraction of the refcount, surrounded
by get_page()/put_page().

Also, further simplify (slightly), by waiting until the the successful
end of each routine, to increment *nr.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Jérôme Glisse 
Reviewed-by: Jan Kara 
Cc: Ira Weiny 
Cc: Christoph Hellwig 
Cc: Aneesh Kumar K.V 
Signed-off-by: John Hubbard 
---
 mm/gup.c | 91 ++--
 1 file changed, 36 insertions(+), 55 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index 7646bf993b25..f764432914c4 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1978,6 +1978,25 @@ static int __gup_device_huge_pud(pud_t pud, pud_t *pudp, 
unsigned long addr,
 }
 #endif
 
+static int record_subpages(struct page *page, unsigned long addr,
+  unsigned long end, struct page **pages)
+{
+   int nr;
+
+   for (nr = 0; addr != end; addr += PAGE_SIZE)
+   pages[nr++] = page++;
+
+   return nr;
+}
+
+static void put_compound_head(struct page *page, int refs)
+{
+   /* Do a get_page() first, in case refs == page->_refcount */
+   get_page(page);
+   page_ref_sub(page, refs);
+   put_page(page);
+}
+
 #ifdef CONFIG_ARCH_HAS_HUGEPD
 static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end,
  unsigned long sz)
@@ -2007,32 +2026,20 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, 
unsigned long addr,
/* hugepages are never "special" */
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 
-   refs = 0;
head = pte_page(pte);
-
page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
-   do {
-   VM_BUG_ON(compound_head(page) != head);
-   pages[*nr] = page;
-   (*nr)++;
-   page++;
-   refs++;
-   } while (addr += PAGE_SIZE, addr != end);
+   refs = record_subpages(page, addr, end, pages + *nr);
 
head = try_get_compound_head(head, refs);
-   if (!head) {
-   *nr -= refs;
+   if (!head)
return 0;
-   }
 
if (unlikely(pte_val(pte) != pte_val(*ptep))) {
-   /* Could be optimized better */
-   *nr -= refs;
-   while (refs--)
-   put_page(head);
+   put_compound_head(head, refs);
return 0;
}
 
+   *nr += refs;
SetPageReferenced(head);
return 1;
 }
@@ -2079,28 +2086,19 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, 
unsigned long addr,
return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr);
}
 
-   refs = 0;
page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
-   do {
-   pages[*nr] = page;
-   (*nr)++;
-   page++;
-   refs++;
-   } while (addr += PAGE_SIZE, addr != end);
+   refs = record_subpages(page, addr, end, pages + *nr);
 
head = try_get_compound_head(pmd_page(orig), refs);
-   if (!head) {
-   *nr -= refs;
+   if (!head)
return 0;
-   }
 
if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) {
-   *nr -= refs;
-   while (refs--)
-   put_page(head);
+   put_compound_head(head, refs);
return 0;
}
 
+   *nr += refs;
SetPageReferenced(head);
return 1;
 }
@@ -2120,28 +2118,19 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, 
unsigned long addr,
return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr);
}
 
-   refs = 0;
page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
-   do {
-   pages[*nr] = page;
-   (*nr)++;
-   page++;
-   refs++;
-   } while (addr += PAGE_SIZE, addr != end);
+   refs = record_subpages(page, addr, end, pages + *nr);
 
head = try_get_compound_head(pud_page(orig), refs);
-   if (!head) {
-   *nr -= refs;
+   if (!head)
return 0;
-   }
 
if (unlikely(pud_val(orig) != pud_val(*pudp))) {
-   *nr -= refs;
-   while (refs--)
-   put_page(head);
+   put_compound_head(head, refs);
return 0;
}
 
+   *nr += refs;
SetPageReferenced(head);
return 1;
 }
@@ -2157,28 +2146,20 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, 
unsigned long 

[PATCH v11 11/25] goldish_pipe: convert to pin_user_pages() and put_user_page()

2019-12-16 Thread John Hubbard
1. Call the new global pin_user_pages_fast(), from pin_goldfish_pages().

2. As required by pin_user_pages(), release these pages via
put_user_page(). In this case, do so via put_user_pages_dirty_lock().

That has the side effect of calling set_page_dirty_lock(), instead
of set_page_dirty(). This is probably more accurate.

As Christoph Hellwig put it, "set_page_dirty() is only safe if we are
dealing with a file backed page where we have reference on the inode it
hangs off." [1]

Another side effect is that the release code is simplified because
the page[] loop is now in gup.c instead of here, so just delete the
local release_user_pages() entirely, and call
put_user_pages_dirty_lock() directly, instead.

[1] https://lore.kernel.org/r/20190723153640.gb...@lst.de

Reviewed-by: Jan Kara 
Reviewed-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 drivers/platform/goldfish/goldfish_pipe.c | 17 +++--
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/drivers/platform/goldfish/goldfish_pipe.c 
b/drivers/platform/goldfish/goldfish_pipe.c
index ef50c264db71..2a5901efecde 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -274,7 +274,7 @@ static int goldfish_pin_pages(unsigned long first_page,
*iter_last_page_size = last_page_size;
}
 
-   ret = get_user_pages_fast(first_page, requested_pages,
+   ret = pin_user_pages_fast(first_page, requested_pages,
  !is_write ? FOLL_WRITE : 0,
  pages);
if (ret <= 0)
@@ -285,18 +285,6 @@ static int goldfish_pin_pages(unsigned long first_page,
return ret;
 }
 
-static void release_user_pages(struct page **pages, int pages_count,
-  int is_write, s32 consumed_size)
-{
-   int i;
-
-   for (i = 0; i < pages_count; i++) {
-   if (!is_write && consumed_size > 0)
-   set_page_dirty(pages[i]);
-   put_page(pages[i]);
-   }
-}
-
 /* Populate the call parameters, merging adjacent pages together */
 static void populate_rw_params(struct page **pages,
   int pages_count,
@@ -372,7 +360,8 @@ static int transfer_max_buffers(struct goldfish_pipe *pipe,
 
*consumed_size = pipe->command_buffer->rw_params.consumed_size;
 
-   release_user_pages(pipe->pages, pages_count, is_write, *consumed_size);
+   put_user_pages_dirty_lock(pipe->pages, pages_count,
+ !is_write && *consumed_size > 0);
 
mutex_unlock(>lock);
return 0;
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v11 23/25] mm/gup: track FOLL_PIN pages

2019-12-16 Thread John Hubbard

On 12/16/19 4:53 AM, Jan Kara wrote:
...


I'd move this still a bit higher - just after VM_BUG_ON_PAGE() and before
if (flags & FOLL_TOUCH) test. Because touch_pmd() can update page tables
and we don't won't that if we're going to fail the fault.



Done. I'll post a full v11 series shortly.


With this fixed, the patch looks good to me so you can then add:

Reviewed-by: Jan Kara 

Honza



btw, thanks for the thorough review of this critical patch (and for your
patience with my mistakes). I really appreciate it, and this patchset would
not have made it this far without your detailed help and explanations.


thanks,
--
John Hubbard
NVIDIA
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2] drm: rcar-du: lvds: Get mode from state

2019-12-16 Thread Laurent Pinchart
Hi Fabrizio,

On Mon, Dec 16, 2019 at 05:39:55PM +, Fabrizio Castro wrote:
> > From: linux-renesas-soc-ow...@vger.kernel.org 
> >  On Behalf Of Laurent Pinchart
> > Sent: 13 December 2019 18:28
> > Subject: [PATCH v2] drm: rcar-du: lvds: Get mode from state
> > 
> > The R-Car LVDS encoder driver implements the bridge .mode_set()
> > operation for the sole purpose of storing the mode in the LVDS private
> > data, to be used later when enabling the encoder.
> > 
> > Switch to the bridge .atomic_enable() and .atomic_disable() operations
> > in order to access the global atomic state, and get the mode from the
> > state instead. Remove both the unneeded .mode_set() operation and the
> > display_mode and mode fields storing state data from the rcar_lvds
> > private structure.
> > 
> > As a side effect we get the CRTC from the state, replace the CRTC
> > pointer retrieved through the bridge's encoder that shouldn't be used by
> > atomic drivers.
> > 
> > Signed-off-by: Laurent Pinchart 
> > ---
> > Changes since v1:
> > 
> > - Call .atomic_enable() on the companion
> > - Set companion->encoder in .attach()
> > 
> > The patch has been tested on the Draak board with the HDMI output in
> > LVDS dual-link mode, and on the Salvator-XS board with the HDMI, VGA and
> > LVDS outputs in single-link mode.
> > 
> > ---
> >  drivers/gpu/drm/rcar-du/rcar_lvds.c | 158 +++-
> >  1 file changed, 85 insertions(+), 73 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> > b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > index 8c6c172bbf2e..c550bfd59e71 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > @@ -65,9 +65,6 @@ struct rcar_lvds {
> > struct clk *dotclkin[2];/* External DU clocks */
> > } clocks;
> > 
> > -   struct drm_display_mode display_mode;
> > -   enum rcar_lvds_mode mode;
> > -
> > struct drm_bridge *companion;
> > bool dual_link;
> >  };
> > @@ -402,10 +399,51 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
> >   * Bridge
> >   */
> > 
> > -static void rcar_lvds_enable(struct drm_bridge *bridge)
> > +static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
> > +   const struct drm_connector *connector)
> > +{
> > +   const struct drm_display_info *info;
> > +   enum rcar_lvds_mode mode;
> > +
> > +   /*
> > +* There is no API yet to retrieve LVDS mode from a bridge, only panels
> > +* are supported.
> > +*/
> > +   if (!lvds->panel)
> > +   return RCAR_LVDS_MODE_JEIDA;
> > +
> > +   info = >display_info;
> > +   if (!info->num_bus_formats || !info->bus_formats) {
> > +   dev_err(lvds->dev, "no LVDS bus format reported\n");
> 
> dev_warn perhaps?
> 
> Also, how about:
> s/no LVDS bus format reported/no LVDS bus format reported, using JEIDA/
> or something along those lines?

Ack.

> > +   return RCAR_LVDS_MODE_JEIDA;
> > +   }
> > +
> > +   switch (info->bus_formats[0]) {
> > +   case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> 
> Shall we take the below into account here?
> https://lwn.net/Articles/794944/

Sure, but I think it's not required when multiple cases are grouped
together with no line in-between.

> > +   case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> > +   mode = RCAR_LVDS_MODE_JEIDA;
> > +   break;
> > +   case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> > +   mode = RCAR_LVDS_MODE_VESA;
> > +   break;
> > +   default:
> > +   dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
> > +   info->bus_formats[0]);
> 
> dev_warn perhaps?
> 
> Also, how about:
> s/unsupported LVDS bus format 0x%04x/unsupported LVDS bus format 0x%04x, 
> using JEIDA/
> or something along those lines?

Ack.

> > +   return RCAR_LVDS_MODE_JEIDA;
> > +   }
> > +
> > +   if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
> > +   mode |= RCAR_LVDS_MODE_MIRROR;
> > +
> > +   return mode;
> > +}
> > +
> > +static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
> > +   struct drm_atomic_state *state)
> >  {
> > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> > -   const struct drm_display_mode *mode = >display_mode;
> > +   struct drm_connector *connector;
> > +   struct drm_crtc *crtc;
> > u32 lvdhcr;
> > u32 lvdcr0;
> > int ret;
> > @@ -414,9 +452,14 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
> > if (ret < 0)
> > return;
> > 
> > +   /* Retrieve the connector and CRTC through the atomic state. */
> > +   connector = drm_atomic_get_new_connector_for_encoder(state,
> > +bridge->encoder);
> > +   crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
> > +
> > /* Enable the companion LVDS encoder in dual-link mode. */
> > if (lvds->dual_link && lvds->companion)
> > -   

[Bug 200695] Blank screen on RX 580 with amdgpu.dc=1 enabled (no displays detected)

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=200695

--- Comment #34 from Bjoern Franke (b...@nord-west.org) ---
I'm getting this issue with only one monitor via HDMI connected. It was gone
some kernel versions before and came back with 5.4.x it seems.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 205879] amdgpu: blank screen on RX 460

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205879

--- Comment #3 from Bjoern Franke (b...@nord-west.org) ---
Created attachment 286321
  --> https://bugzilla.kernel.org/attachment.cgi?id=286321=edit
dmesg with amdgpu.dc_log=1

Enabling dc_log=1 shows similarities to #200695, but only with one monitor
connected via HDMI.

[   19.548801] [drm:drm_client_modeset_probe [drm]] No connectors reported
connected with modes
[   19.548809] [drm:drm_client_modeset_probe [drm]] connector 56 enabled? no
[   19.548816] [drm:drm_client_modeset_probe [drm]] connector 60 enabled? no
[   19.548823] [drm:drm_client_modeset_probe [drm]] connector 64 enabled? no
[   19.548831] [drm:drm_client_modeset_probe [drm]] Not using firmware
configuration
[   19.548838] [drm:drm_client_modeset_probe [drm]] picking CRTCs for
16384x16384 config
[   19.548841] [drm] Cannot find any crtc or sizes

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 4/6] drm: rcar-du: lvds: Allow for even and odd pixels swap

2019-12-16 Thread Laurent Pinchart
Hi Fabrizio,

Thank you for the patch.

On Mon, Dec 16, 2019 at 08:12:32PM +, Fabrizio Castro wrote:
> DT properties dual-lvds-even-pixels and dual-lvds-odd-pixels
> can be used to work out if the driver needs to swap even
> and odd pixels around.
> 
> This patch makes use of the return value from function
> drm_of_lvds_get_dual_link_pixel_order to determine if we
> need to swap odd and even pixels around for things to work
> properly.
> 
> Signed-off-by: Fabrizio Castro 
> 
> ---
> v4->v5:
> * Addressed comments from Laurent's review
> 
> v3->v4:
> * New patch extracted from patch:
>   "drm: rcar-du: lvds: Add dual-LVDS panels support"
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 67 
> +
>  1 file changed, 53 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index 3eb208e..c6a38c3 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -37,6 +37,12 @@ enum rcar_lvds_mode {
>   RCAR_LVDS_MODE_VESA = 4,
>  };
>  
> +enum rcar_lvds_link_type {
> + RCAR_LVDS_SINGLE_LINK = 0,
> + RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 1,
> + RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 2,
> +};
> +
>  #define RCAR_LVDS_QUIRK_LANESBIT(0)  /* LVDS lanes 1 and 3 
> inverted */
>  #define RCAR_LVDS_QUIRK_GEN3_LVENBIT(1)  /* LVEN bit needs to be set on 
> R8A77970/R8A7799x */
>  #define RCAR_LVDS_QUIRK_PWD  BIT(2)  /* PWD bit available (all of 
> Gen3 but E3) */
> @@ -67,7 +73,7 @@ struct rcar_lvds {
>   } clocks;
>  
>   struct drm_bridge *companion;
> - bool dual_link;
> + enum rcar_lvds_link_type dual_link;

Do you think we should rename this to link_type (and test for
lvds->link_type != RCAR_LVDS_SINGLE_LINK) instead of lvds->dual_link) ?
Apart from that,

Reviewed-by: Laurent Pinchart 

>  };
>  
>  #define bridge_to_rcar_lvds(b) \
> @@ -484,12 +490,31 @@ static void rcar_lvds_atomic_enable(struct drm_bridge 
> *bridge,
>   rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
>  
>   if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
> - /*
> -  * Configure vertical stripe based on the mode of operation of
> -  * the connected device.
> -  */
> - rcar_lvds_write(lvds, LVDSTRIPE,
> - lvds->dual_link ? LVDSTRIPE_ST_ON : 0);
> + u32 lvdstripe = 0;
> +
> + if (lvds->dual_link) {
> + /*
> +  * By default we generate even pixels from the primary
> +  * encoder and odd pixels from the companion encoder.
> +  * Swap pixels around if the sink requires odd pixels
> +  * from the primary encoder and even pixels from the
> +  * companion encoder.
> +  */
> + bool swap_pixels = lvds->dual_link ==
> + RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> +
> + /*
> +  * Configure vertical stripe since we are dealing with
> +  * an LVDS dual-link connection.
> +  *
> +  * ST_SWAP is reserved for the companion encoder, only
> +  * set it in the primary encoder.
> +  */
> + lvdstripe = LVDSTRIPE_ST_ON
> +   | (lvds->companion && swap_pixels ?
> +  LVDSTRIPE_ST_SWAP : 0);
> + }
> + rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe);
>   }
>  
>   /*
> @@ -716,15 +741,26 @@ static int rcar_lvds_parse_dt_companion(struct 
> rcar_lvds *lvds)
>   of_node_put(port0);
>   of_node_put(port1);
>  
> - if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS)
> - lvds->dual_link = true;
> - else if (lvds->next_bridge && lvds->next_bridge->timings)
> + switch (dual_link) {
> + case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
> + lvds->dual_link = RCAR_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> + break;
> + case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
> + lvds->dual_link = RCAR_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
> + break;
> + default:
>   /*
>* Early dual-link bridge specific implementations populate the
> -  * timings field of drm_bridge, read the dual_link flag off the
> -  * bridge directly for backward compatibility.
> +  * timings field of drm_bridge. If the flag is set, we assume
> +  * that we are expected to generate even pixels from the primary
> +  * encoder, and odd pixels from the companion encoder.
>*/
> - lvds->dual_link = lvds->next_bridge->timings->dual_link;
> + if (lvds->next_bridge && lvds->next_bridge->timings &&
> + 

Re: [PATCH v5 2/6] drm: rcar-du: lvds: Improve identification of panels

2019-12-16 Thread Laurent Pinchart
Hi Fabrizio,

Thank you for the patch.

On Mon, Dec 16, 2019 at 08:12:30PM +, Fabrizio Castro wrote:
> Dual-LVDS panels are mistakenly identified as bridges, this
> commit replaces the current logic with a call to
> drm_of_find_panel_or_bridge to sort that out.
> 
> Signed-off-by: Fabrizio Castro 

Reviewed-by: Laurent Pinchart 

> ---
> v4->v5:
> * Addressed comments from Laurent's review
> 
> v3->v4:
> * New patch extracted from patch:
>   "drm: rcar-du: lvds: Add dual-LVDS panels support"
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 75 
> +
>  1 file changed, 10 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index b03b7cd..4d038bd 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -21,6 +21,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  
> @@ -716,79 +717,23 @@ static int rcar_lvds_parse_dt_companion(struct 
> rcar_lvds *lvds)
>  
>  static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
>  {
> - struct device_node *local_output = NULL;
> - struct device_node *remote_input = NULL;
> - struct device_node *remote = NULL;
> - struct device_node *node;
> - bool is_bridge = false;
> - int ret = 0;
> -
> - local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
> - if (!local_output) {
> - dev_dbg(lvds->dev, "unconnected port@1\n");
> - ret = -ENODEV;
> - goto done;
> - }
> -
> - /*
> -  * Locate the connected entity and infer its type from the number of
> -  * endpoints.
> -  */
> - remote = of_graph_get_remote_port_parent(local_output);
> - if (!remote) {
> - dev_dbg(lvds->dev, "unconnected endpoint %pOF\n", local_output);
> - ret = -ENODEV;
> - goto done;
> - }
> + int ret;
>  
> - if (!of_device_is_available(remote)) {
> - dev_dbg(lvds->dev, "connected entity %pOF is disabled\n",
> - remote);
> - ret = -ENODEV;
> + ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0,
> +   >panel, >next_bridge);
> + if (ret)
>   goto done;
> - }
>  
> - remote_input = of_graph_get_remote_endpoint(local_output);
> -
> - for_each_endpoint_of_node(remote, node) {
> - if (node != remote_input) {
> - /*
> -  * We've found one endpoint other than the input, this
> -  * must be a bridge.
> -  */
> - is_bridge = true;
> - of_node_put(node);
> - break;
> - }
> - }
> -
> - if (is_bridge) {
> - lvds->next_bridge = of_drm_find_bridge(remote);
> - if (!lvds->next_bridge) {
> - ret = -EPROBE_DEFER;
> - goto done;
> - }
> -
> - if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
> - lvds->dual_link = lvds->next_bridge->timings
> - ? lvds->next_bridge->timings->dual_link
> - : false;
> - } else {
> - lvds->panel = of_drm_find_panel(remote);
> - if (IS_ERR(lvds->panel)) {
> - ret = PTR_ERR(lvds->panel);
> - goto done;
> - }
> - }
> + if ((lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) &&
> + lvds->next_bridge)
> + lvds->dual_link = lvds->next_bridge->timings
> + ? lvds->next_bridge->timings->dual_link
> + : false;
>  
>   if (lvds->dual_link)
>   ret = rcar_lvds_parse_dt_companion(lvds);
>  
>  done:
> - of_node_put(local_output);
> - of_node_put(remote_input);
> - of_node_put(remote);
> -
>   /*
>* On D3/E3 the LVDS encoder provides a clock to the DU, which can be
>* used for the DPAD output even when the LVDS output is not connected.

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v4 06/13] drm/bridge: lvds-codec: Add "lvds-decoder" support

2019-12-16 Thread Laurent Pinchart
Hi Fabrizio,

Ping ?

On Fri, Dec 13, 2019 at 07:10:38PM +0200, Laurent Pinchart wrote:
> On Wed, Nov 13, 2019 at 03:51:25PM +, Fabrizio Castro wrote:
> > Add support for transparent LVDS decoders by adding a new
> > compatible string ("lvds-decoder") to the driver.
> > This patch also adds member connector_type to struct lvds_codec,
> > and that's because LVDS decoders have a different connector type
> > from LVDS encoders. We fill this new member up with the data
> > matching the compatible string.
> > 
> > Signed-off-by: Fabrizio Castro 
> > 
> > ---
> > v3->v4:
> > * New patch
> > ---
> >  drivers/gpu/drm/bridge/lvds-codec.c | 19 ---
> >  1 file changed, 16 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/lvds-codec.c 
> > b/drivers/gpu/drm/bridge/lvds-codec.c
> > index b5801a2..c32e125 100644
> > --- a/drivers/gpu/drm/bridge/lvds-codec.c
> > +++ b/drivers/gpu/drm/bridge/lvds-codec.c
> > @@ -7,6 +7,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  
> > @@ -17,6 +18,7 @@ struct lvds_codec {
> > struct drm_bridge bridge;
> > struct drm_bridge *panel_bridge;
> > struct gpio_desc *powerdown_gpio;
> > +   u32 connector_type;
> >  };
> >  
> >  static int lvds_codec_attach(struct drm_bridge *bridge)
> > @@ -65,6 +67,7 @@ static int lvds_codec_probe(struct platform_device *pdev)
> > if (!lvds_codec)
> > return -ENOMEM;
> >  
> > +   lvds_codec->connector_type = (u32)of_device_get_match_data(>dev);
> 
> I'm now getting a compilation failure here:
> 
> drivers/gpu/drm/bridge/lvds-codec.c: In function ‘lvds_codec_probe’:
> drivers/gpu/drm/bridge/lvds-codec.c:68:31: error: cast from pointer to 
> integer of different size [-Werror=pointer-to-int-cast]
>   lvds_codec->connector_type = (u32)of_device_get_match_data(>dev);
>^
> 
> The fix should be simple:
> 
>   lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev);
> 
> I'm bothered by the fact that I've compiled this before without any
> issue, so this really puzzles me. Do you get the same warning ?
> 
> > lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
> >  GPIOD_OUT_HIGH);
> > if (IS_ERR(lvds_codec->powerdown_gpio)) {
> > @@ -105,7 +108,7 @@ static int lvds_codec_probe(struct platform_device 
> > *pdev)
> >  
> > lvds_codec->panel_bridge =
> > devm_drm_panel_bridge_add_typed(dev, panel,
> > -   DRM_MODE_CONNECTOR_LVDS);
> > +   lvds_codec->connector_type);
> > if (IS_ERR(lvds_codec->panel_bridge))
> > return PTR_ERR(lvds_codec->panel_bridge);
> >  
> > @@ -133,8 +136,18 @@ static int lvds_codec_remove(struct platform_device 
> > *pdev)
> >  }
> >  
> >  static const struct of_device_id lvds_codec_match[] = {
> > -   { .compatible = "lvds-encoder" },
> > -   { .compatible = "thine,thc63lvdm83d" },
> > +   {
> > +   .compatible = "lvds-decoder",
> > +   .data = (void *)DRM_MODE_CONNECTOR_DPI,
> > +   },
> > +   {
> > +   .compatible = "lvds-encoder",
> > +   .data = (void *)DRM_MODE_CONNECTOR_LVDS,
> > +   },
> > +   {
> > +   .compatible = "thine,thc63lvdm83d",
> > +   .data = (void *)DRM_MODE_CONNECTOR_LVDS,
> > +   },
> > {},
> >  };
> >  MODULE_DEVICE_TABLE(of, lvds_codec_match);

-- 
Regards,

Laurent Pinchart
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 205879] amdgpu: blank screen on RX 460

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205879

--- Comment #2 from Bjoern Franke (b...@nord-west.org) ---
Created attachment 286319
  --> https://bugzilla.kernel.org/attachment.cgi?id=286319=edit
xorg log

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 205879] amdgpu: blank screen on RX 460

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205879

--- Comment #1 from Bjoern Franke (b...@nord-west.org) ---
Xorg logs:

21.247] (WW) AMDGPU(0): No outputs definitely connected, trying again...
[21.247] (II) AMDGPU(0): Output DisplayPort-0 disconnected
[21.247] (II) AMDGPU(0): Output HDMI-A-0 disconnected
[21.247] (II) AMDGPU(0): Output DVI-D-0 disconnected
[21.247] (WW) AMDGPU(0): Unable to find connected outputs - setting
1024x768 initial framebuffer```

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3] drm/mcde: Some fixes to handling video mode

2019-12-16 Thread Linus Walleij
Hi Stephan,

I fixed up the patch according to your comments, this remains:

On Mon, Dec 16, 2019 at 6:55 PM Stephan Gerhold  wrote:

> In general I was wondering if we could benefit from using something like
> the regmap_update_bits() helper to avoid having to write this manually
> all the time. However, this does not have anything to do with this patch
> - just an idea that could be discussed separately.

Yeah I can take a stab at simply converting the whole thing to
regmap-mmio, I thinkt it'd be pretty quick and we can see how
it looks. Maybe easier to debug as well.

Yours,
Linus Walleij
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 2/2] dma-buf: heaps: Remove redundant heap identifier from system heap name

2019-12-16 Thread John Stultz
On Mon, Dec 16, 2019 at 5:34 AM Andrew F. Davis  wrote:
>
> The heaps are already in a directory of heaps, adding _heap to a heap
> name is redundant. This patch is only a name change, no logic is changed.
>
> Signed-off-by: Andrew F. Davis 

Again, do wish we had caught/made this tweak earlier, but this seems sane to me.
Acked-by: John Stultz 

I've also reworked my userland changes to use this name, and will
update them here shortly (assuming there's no objection to this).

Sumit: Mind queuing for drm-misc-next?

thanks
-john
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 205879] New: amdgpu: blank screen on RX 460

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=205879

Bug ID: 205879
   Summary: amdgpu: blank screen on RX 460
   Product: Drivers
   Version: 2.5
Kernel Version: 5.4.3
  Hardware: x86-64
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-...@kernel-bugs.osdl.org
  Reporter: b...@nord-west.org
Regression: No

Created attachment 286317
  --> https://bugzilla.kernel.org/attachment.cgi?id=286317=edit
dmesg 5.4.3

With a recent upgrade on Arch Linux, a bug came back which existed also several
versions before. Starting lightdm just results in a blank screen and switching
to a terminal also fails then. Booting with dc=0 works.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 1/2] dma-buf: heaps: Use _IOCTL_ for userspace IOCTL identifier

2019-12-16 Thread John Stultz
On Mon, Dec 16, 2019 at 5:34 AM Andrew F. Davis  wrote:
>
> This is more consistent with the DMA and DRM frameworks convention. This
> patch is only a name change, no logic is changed.
>
> Signed-off-by: Andrew F. Davis 

Do wish we had caught/made this tweak earlier, but I do agree its a
more consistent name.
Acked-by: John Stultz 

I've also reworked my userland changes to use this name, and will
update them here shortly (assuming there's no objection to this).

Sumit: Mind queuing for drm-misc-next?

thanks
-john
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH][next] dma-buf: fix resource leak on -ENOTTY error return path

2019-12-16 Thread John Stultz
On Mon, Dec 16, 2019 at 8:11 AM Colin King  wrote:
>
> From: Colin Ian King 
>
> The -ENOTTY error return path does not free the allocated
> kdata as it returns directly. Fix this by returning via the
> error handling label err.
>
> Addresses-Coverity: ("Resource leak")
> Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework")
> Signed-off-by: Colin Ian King 

Acked-by: John Stultz 

Thanks so much for submitting this!

Sumit, do you mind queueing this up for drm-misc-next?

thanks
-john
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5] drm/mcde: Some fixes to handling video mode

2019-12-16 Thread Linus Walleij
The video DSI mode had not really been tested. These fixes makes
it more likely to work on real hardware:
- Put the active width (x width) in the right bits and the VSA
  (vertical sync active) in the right bits (those were swapped).
- Calculate the packet sizes in bytes as in the vendor driver,
  rather than in bits. Test the calculations agains a
  spreadsheet and confirmed by debug prints to be reasonable.
- Also verified the register values with relative confidence
  to register dumps from the Samsung GT-I8190 boot loader
  graphics. We are not identical but not off by far either.
- Error out if the current mode and refresh frequency doesn't
  work out. (In the future we may simply want to scale down
  the vrefresh.)
- Handle negative result in front/back/sync packages and fall
  back to zero like in the vendor driver.
- Put in lots of clarifying comments and references to the
  documentation where the code is hard to understand.
- Set the DSI_VID_VCA_SETTING2 field
  DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT to blkline_pck - 6 as in
  the vendor driver and mask the field properly.

Cc: Stephan Gerhold 
Fixes: 5fc537bfd000 ("drm/mcde: Add new driver for ST-Ericsson MCDE")
Signed-off-by: Linus Walleij 
---
ChangeLog v4->v5:
- Restore log order, last verstion of the changelog inadvertedly
  merged v3 and v4 into v3 since I thought I didn't send out v3...
- Parens in blkeol_pck = bpl - (mode->htotal * cpp) - 6 for
  explicit priority.
- Use mask-and-set for DSI_VID_PCK_TIME and DSI_VID_VCA_SETTING1
- Restore DSI_VID_VCA_SETTING2 field
  DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT to blkline_pck - 6 as in
  the vendor driver and mask the field properly.
ChangeLog v3->v4:
- Calculate toward actual HS rate of the clock rather than the
  idealized rate provided by the panel resolution, this is what
  the vendor driver does.
- Add much comments and elaborate with references to the manual
  so the code can be understood as far as possible.
- Compared register dumps to that on the Samsung GT-I8190 (Golden)
  boot loader settings. We are now reasonably close to these,
  it may be that the boot loader driver is using slightly different
  settings for porches and syncs etc. But all figures makes sense.
- Duplicated the vendor code in a spread sheet and compared to
  what this code gives and we have an identical match with one
  small exception that the vendor code adds a small padding of 2
  lines to the vertical blanking area. This looks weird and might
  be some hackishly specified porch.
ChangeLog v2->v3:
- Rename the "bpp" variable to "cpp" since it is "chars per pixel"
  this was confusingly named in the vendor driver and it got
  carried over.
- Assign the SETTING2_EXACT_BURST_LIMIT by first shifting
  then masking.
- Also mask with the inverse of DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK
  before writing blkeol into DSI_VID_BLKSIZE1, so we make sure
  to zero these bits first.
- Also mask with DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK
  when writing event package length.
- Comb through the code and compare it to vendor code and try
  to get closer to doing what the vendor driver is doing.
ChangeLog v1->v2:
- Fix some more comments so we understand what is going on.
- Set up the maximum line limit size in the right register
  instead of setting it in the burst size register portion.
- Set some default wakeup time other than zero (still need
  fixing more).
---
 drivers/gpu/drm/mcde/mcde_dsi.c  | 238 +--
 drivers/gpu/drm/mcde/mcde_dsi_regs.h |   1 +
 2 files changed, 191 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index 21cee4d9d2fd..948841fc67df 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -379,13 +379,14 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
 static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
  const struct drm_display_mode *mode)
 {
-   u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format);
+   /* cpp, characters per pixel, number of bytes per pixel */
+   u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8;
+   u64 pclk;
u64 bpl;
-   u32 hfp;
-   u32 hbp;
-   u32 hsa;
+   int hfp;
+   int hbp;
+   int hsa;
u32 blkline_pck, line_duration;
-   u32 blkeol_pck, blkeol_duration;
u32 val;
 
val = 0;
@@ -422,11 +423,21 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
return;
}
 
-   /* TODO: TVG could be enabled here */
+   /* TODO: TVG (test video generator) could be enabled here */
 
-   /* Send blanking packet */
+   /*
+* During vertical blanking: go to LP mode
+* Like with the EOL setting, if this is not set, the EOL area will be
+* filled with NULL or blanking packets in the vblank area.
+* FIXME: some Samsung phones and display panels such as s6e63m0 use
+* 

[PATCH v2 0/5] drm/i915/dsi: Control panel and backlight enable GPIOs from VBT

2019-12-16 Thread Hans de Goede
Hi All,

Here is v2 of my patch-series to make the
i915 code control the SoC panel- and backlight-enable GPIOs on Bay Trail
devices when the VBT indicates that the SoC should be used for backlight
control. This fixes the panel not lighting up on various devices when
booted with a HDMI monitor connected, in which case the firmware skips
initializing the panel as it inits the HDMI instead.

This series has been tested on; and fixes this issue on; the following models:

Peaq C1010
Point of View MOBII TAB-P800W
Point of View MOBII TAB-P1005W
Terra Pad 1061
Thundersoft TST178
Yours Y8W81

Linus the main change in v2 is the discussed fixing of the patch to
export pinctrl_unregister_mappings. Can you please provide a new
immutable branch with the new version (assuming the new version is ok)?

Another change on the version is the use of intel_dsi_get_hw_state() to
check if the panel is on instead of relying on the current_mode pointer
in "[PATCH v2 3/5] drm/i915/dsi: Init panel-enable GPIO to low when the
LCD is initially off (v2)".

Other then that there are some small style tweaks addressing comments
from Andy and Ville.

Lee, I know you don't like this, but unfortunately this series introcudes
some (other) changes to drivers/mfd/intel_soc_pmic_core.c. The GPIO subsys
allows only one mapping-table per consumer, so in hindsight adding the code
which adds the mapping for the PMIC panel-enable pin to the PMIC mfd driver
was a mistake, as the PMIC code is a provider where as mapping-tables are
per consumer. The 4th patch fixes this by moving the mapping-table to the
i915 code, so that we can also add mappings for some of the pins on the SoC
itself. Since this whole series makes change to the i915 code I plan to
merge this mfd change to the drm-intel tree.

Regards,

Hans

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/5] pinctrl: Allow modules to use pinctrl_[un]register_mappings

2019-12-16 Thread Hans de Goede
Currently only the drivers/pinctrl/devicetree.c code allows registering
pinctrl-mappings which may later be unregistered, all other mappings
are assumed to be permanent.

Non-dt platforms may also want to register pinctrl mappings from code which
is build as a module, which requires being able to unregister the mapping
when the module is unloaded to avoid dangling pointers.

To allow unregistering the mappings the devicetree code uses 2 internal
functions: pinctrl_register_map and pinctrl_unregister_map.

pinctrl_register_map allows the devicetree code to tell the core to
not memdup the mappings as it retains ownership of them and
pinctrl_unregister_map does the unregistering, note this only works
when the mappings where not memdupped.

The only code relying on the memdup/shallow-copy done by
pinctrl_register_mappings is arch/arm/mach-u300/core.c this commit
replaces the __initdata with const, so that the shallow-copy is no
longer necessary.

After that we can get rid of the internal pinctrl_unregister_map function
and just use pinctrl_register_mappings directly everywhere.

This commit also renames pinctrl_unregister_map to
pinctrl_unregister_mappings so that its naming matches its
pinctrl_register_mappings counter-part and exports it.

Together these 2 changes will allow non-dt platform code to
register pinctrl-mappings from modules without breaking things on
module unload (as they can now unregister the mapping on unload).

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Drop __initdata from arch/arm/mach-u300/core.c pinctrl-map, so
 that we can drop the dup behavior for non device-tree callers
-Stop memdupping the pinctrl-maps in some cases, remove all code for
 dealing with dupped maps, including the extra coded added for this in v1
 of this patch
-Drop the private (non-dupping) pinctrl_register_map function, now that
 our public pinctrl_register_mappings does not dup we can simply use it
 everywhere
---
 arch/arm/mach-u300/core.c   |  2 +-
 drivers/pinctrl/core.c  | 41 +
 drivers/pinctrl/core.h  |  4 
 drivers/pinctrl/devicetree.c|  4 ++--
 include/linux/pinctrl/machine.h |  5 
 5 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index a79fa3b0c8ed..a1694d977ec9 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -201,7 +201,7 @@ static unsigned long pin_highz_conf[] = {
 };
 
 /* Pin control settings */
-static struct pinctrl_map __initdata u300_pinmux_map[] = {
+static const struct pinctrl_map u300_pinmux_map[] = {
/* anonymous maps for chip power and EMIFs */
PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "power"),
PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif0"),
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2bbd8ee93507..b0eea728455d 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1376,8 +1376,15 @@ void devm_pinctrl_put(struct pinctrl *p)
 }
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
-int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps,
-bool dup)
+/**
+ * pinctrl_register_mappings() - register a set of pin controller mappings
+ * @maps: the pincontrol mappings table to register. Note the pinctrl-core
+ * keeps a reference to the passed in maps, so they should _not_ be
+ * marked with __initdata.
+ * @num_maps: the number of maps in the mapping table
+ */
+int pinctrl_register_mappings(const struct pinctrl_map *maps,
+ unsigned num_maps)
 {
int i, ret;
struct pinctrl_maps *maps_node;
@@ -1430,17 +1437,8 @@ int pinctrl_register_map(const struct pinctrl_map *maps, 
unsigned num_maps,
if (!maps_node)
return -ENOMEM;
 
+   maps_node->maps = maps;
maps_node->num_maps = num_maps;
-   if (dup) {
-   maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
- GFP_KERNEL);
-   if (!maps_node->maps) {
-   kfree(maps_node);
-   return -ENOMEM;
-   }
-   } else {
-   maps_node->maps = maps;
-   }
 
mutex_lock(_maps_mutex);
list_add_tail(_node->node, _maps);
@@ -1448,22 +1446,14 @@ int pinctrl_register_map(const struct pinctrl_map 
*maps, unsigned num_maps,
 
return 0;
 }
+EXPORT_SYMBOL_GPL(pinctrl_register_mappings);
 
 /**
- * pinctrl_register_mappings() - register a set of pin controller mappings
- * @maps: the pincontrol mappings table to register. This should probably be
- * marked with __initdata so it can be discarded after boot. This
- * function will perform a shallow copy for the mapping entries.
- * @num_maps: the number of maps in the mapping table
+ * pinctrl_unregister_mappings() - unregister a set of pin controller mappings
+ * @maps: the pincontrol mappings 

[PATCH v2 4/5] drm/i915/dsi: Move Crystal Cove PMIC panel GPIO lookup from mfd to the i915 driver

2019-12-16 Thread Hans de Goede
Move the Crystal Cove PMIC panel GPIO lookup-table from
drivers/mfd/intel_soc_pmic_core.c to the i915 driver.

The moved looked-up table is adding a GPIO lookup to the i915 PCI
device and the GPIO subsys allows only one lookup table per device,

The intel_soc_pmic_core.c code only adds lookup-table entries for the
PMIC panel GPIO (as it deals only with the PMIC), but we also need to be
able to access some GPIOs on the SoC itself, which requires entries for
these GPIOs in the lookup-table.

Since the lookup-table is attached to the i915 PCI device it really
should be part of the i915 driver, this will also allow us to extend
it with GPIOs from other sources when necessary.

Acked-by: Linus Walleij 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Ville Syrjälä 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 23 +++-
 drivers/mfd/intel_soc_pmic_core.c| 19 
 2 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c 
b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 4210f449553e..89558ccf79c8 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -25,6 +25,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 
@@ -686,8 +687,18 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 
panel_id)
 
 /*
  * On some BYT/CHT devs some sequences are incomplete and we need to manually
- * control some GPIOs.
+ * control some GPIOs. We need to add a GPIO lookup table before we get these.
  */
+static struct gpiod_lookup_table pmic_panel_gpio_table = {
+   /* Intel GFX is consumer */
+   .dev_id = ":00:02.0",
+   .table = {
+   /* Panel EN/DISABLE */
+   GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
+   { }
+   },
+};
+
 void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on)
 {
struct drm_device *dev = intel_dsi->base.base.dev;
@@ -697,6 +708,8 @@ void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, 
bool panel_is_on)
 
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
mipi_config->pwm_blc == PPS_BLC_PMIC) {
+   gpiod_add_lookup_table(_panel_gpio_table);
+
intel_dsi->gpio_panel = gpiod_get(dev->dev, "panel", flags);
if (IS_ERR(intel_dsi->gpio_panel)) {
DRM_ERROR("Failed to own gpio for panel control\n");
@@ -707,8 +720,16 @@ void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, 
bool panel_is_on)
 
 void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi)
 {
+   struct drm_device *dev = intel_dsi->base.base.dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
+
if (intel_dsi->gpio_panel) {
gpiod_put(intel_dsi->gpio_panel);
intel_dsi->gpio_panel = NULL;
}
+
+   if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+   mipi_config->pwm_blc == PPS_BLC_PMIC)
+   gpiod_remove_lookup_table(_panel_gpio_table);
 }
diff --git a/drivers/mfd/intel_soc_pmic_core.c 
b/drivers/mfd/intel_soc_pmic_core.c
index 47188df3080d..ddd64f9e3341 100644
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -9,8 +9,6 @@
  */
 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -25,17 +23,6 @@
 #define BYT_CRC_HRV2
 #define CHT_CRC_HRV3
 
-/* Lookup table for the Panel Enable/Disable line as GPIO signals */
-static struct gpiod_lookup_table panel_gpio_table = {
-   /* Intel GFX is consumer */
-   .dev_id = ":00:02.0",
-   .table = {
-   /* Panel EN/DISABLE */
-   GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
-   { },
-   },
-};
-
 /* PWM consumed by the Intel GFX */
 static struct pwm_lookup crc_pwm_lookup[] = {
PWM_LOOKUP("crystal_cove_pwm", 0, ":00:02.0", "pwm_pmic_backlight", 
0, PWM_POLARITY_NORMAL),
@@ -96,9 +83,6 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
if (ret)
dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
 
-   /* Add lookup table binding for Panel Control to the GPIO Chip */
-   gpiod_add_lookup_table(_gpio_table);
-
/* Add lookup table for crc-pwm */
pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
 
@@ -121,9 +105,6 @@ static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
 
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
 
-   /* Remove lookup table for Panel Control from the GPIO Chip */
-   gpiod_remove_lookup_table(_gpio_table);
-
/* remove crc-pwm lookup table */
pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
 
-- 
2.23.0

___

[PATCH v2 3/5] drm/i915/dsi: Init panel-enable GPIO to low when the LCD is initially off (v2)

2019-12-16 Thread Hans de Goede
When the LCD has not been turned on by the firmware/GOP, because e.g. the
device was booted with an external monitor connected over HDMI, we should
not turn on the panel-enable GPIO when we request it.

Turning on the panel-enable GPIO when we request it, means we turn it on
too early in the init-sequence, which causes some panels to not correctly
light up.

This commits adds a panel_is_on parameter to intel_dsi_vbt_gpio_init()
and makes intel_dsi_vbt_gpio_init() set the initial GPIO value accordingly.

This fixes the panel not lighting up on a Thundersoft TST168 tablet when
booted with an external monitor connected over HDMI.

Changes in v2:
- Call intel_dsi_get_hw_state() to check if the panel is on instead of
  relying on the current_mode pointer

Reviewed-by: Linus Walleij 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_dsi.h | 2 +-
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 7 +++
 drivers/gpu/drm/i915/display/vlv_dsi.c   | 4 +++-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h 
b/drivers/gpu/drm/i915/display/intel_dsi.h
index de7e51cd3460..675771ea91aa 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -203,7 +203,7 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, 
enum port port);
 
 /* intel_dsi_vbt.c */
 bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
-void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi);
+void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on);
 void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi);
 void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
 enum mipi_seq seq_id);
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c 
b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 8be7d6c507aa..4210f449553e 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -688,17 +688,16 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 
panel_id)
  * On some BYT/CHT devs some sequences are incomplete and we need to manually
  * control some GPIOs.
  */
-void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi)
+void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on)
 {
struct drm_device *dev = intel_dsi->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
+   enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
 
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
mipi_config->pwm_blc == PPS_BLC_PMIC) {
-   intel_dsi->gpio_panel =
-   gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH);
-
+   intel_dsi->gpio_panel = gpiod_get(dev->dev, "panel", flags);
if (IS_ERR(intel_dsi->gpio_panel)) {
DRM_ERROR("Failed to own gpio for panel control\n");
intel_dsi->gpio_panel = NULL;
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c 
b/drivers/gpu/drm/i915/display/vlv_dsi.c
index c1edd8857af0..d0efee09c593 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1759,6 +1759,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
struct drm_connector *connector;
struct drm_display_mode *current_mode, *fixed_mode;
enum port port;
+   enum pipe pipe;
 
DRM_DEBUG_KMS("\n");
 
@@ -1857,7 +1858,8 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 
vlv_dphy_param_init(intel_dsi);
 
-   intel_dsi_vbt_gpio_init(intel_dsi);
+   intel_dsi_vbt_gpio_init(intel_dsi,
+   intel_dsi_get_hw_state(intel_encoder, ));
 
drm_connector_init(dev, connector, _dsi_connector_funcs,
   DRM_MODE_CONNECTOR_DSI);
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 5/5] drm/i915/dsi: Control panel and backlight enable GPIOs on BYT

2019-12-16 Thread Hans de Goede
On Bay Trail devices the MIPI power on/off sequences for DSI LCD panels
do not control the LCD panel- and backlight-enable GPIOs. So far, when
the VBT indicates we should use the SoC for backlight control, we have
been relying on these GPIOs being configured as output and driven high by
the Video BIOS (GOP) when it initializes the panel.

This does not work when the device is booted with a HDMI monitor connected
as then the GOP will initialize the HDMI instead of the panel, leaving the
panel black, even though the i915 driver tries to output an image to it.

Likewise on some device-models when the GOP does not initialize the DSI
panel it also leaves the mux of the PWM0 pin in generic GPIO mode instead
of muxing it to the PWM controller.

This commit makes the DSI code control the SoC GPIOs for panel- and
backlight-enable on BYT, when the VBT indicates the SoC should be used

for backlight control. It also ensures that the PWM0 pin is muxed to the
PWM controller in this case.

This fixes the LCD panel not lighting up on various devices when booted
with a HDMI monitor connected. This has been tested to fix this on the
following devices:

Peaq C1010
Point of View MOBII TAB-P800W
Point of View MOBII TAB-P1005W
Terra Pad 1061
Yours Y8W81

Reviewed-by: Linus Walleij 
Reviewed-by: Ville Syrjälä 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_dsi.h |  3 +-
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 64 
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h 
b/drivers/gpu/drm/i915/display/intel_dsi.h
index 675771ea91aa..7481a5aa3084 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -45,8 +45,9 @@ struct intel_dsi {
struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
intel_wakeref_t io_wakeref[I915_MAX_PORTS];
 
-   /* GPIO Desc for CRC based Panel control */
+   /* GPIO Desc for panel and backlight control */
struct gpio_desc *gpio_panel;
+   struct gpio_desc *gpio_backlight;
 
struct intel_connector *attached_connector;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c 
b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 89558ccf79c8..0032161e0f76 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -27,6 +27,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 #include 
@@ -525,11 +527,15 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi 
*intel_dsi,
 {
if (seq_id == MIPI_SEQ_POWER_ON && intel_dsi->gpio_panel)
gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
+   if (seq_id == MIPI_SEQ_BACKLIGHT_ON && intel_dsi->gpio_backlight)
+   gpiod_set_value_cansleep(intel_dsi->gpio_backlight, 1);
 
intel_dsi_vbt_exec(intel_dsi, seq_id);
 
if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel)
gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
+   if (seq_id == MIPI_SEQ_BACKLIGHT_OFF && intel_dsi->gpio_backlight)
+   gpiod_set_value_cansleep(intel_dsi->gpio_backlight, 0);
 }
 
 void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
@@ -688,6 +694,8 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 
panel_id)
 /*
  * On some BYT/CHT devs some sequences are incomplete and we need to manually
  * control some GPIOs. We need to add a GPIO lookup table before we get these.
+ * If the GOP did not initialize the panel (HDMI inserted) we may need to also
+ * change the pinmux for the SoC's PWM0 pin from GPIO to PWM.
  */
 static struct gpiod_lookup_table pmic_panel_gpio_table = {
/* Intel GFX is consumer */
@@ -699,23 +707,69 @@ static struct gpiod_lookup_table pmic_panel_gpio_table = {
},
 };
 
+static struct gpiod_lookup_table soc_panel_gpio_table = {
+   .dev_id = ":00:02.0",
+   .table = {
+   GPIO_LOOKUP("INT33FC:01", 10, "backlight", GPIO_ACTIVE_HIGH),
+   GPIO_LOOKUP("INT33FC:01", 11, "panel", GPIO_ACTIVE_HIGH),
+   { }
+   },
+};
+
+static const struct pinctrl_map soc_pwm_pinctrl_map[] = {
+   PIN_MAP_MUX_GROUP(":00:02.0", "soc_pwm0", "INT33FC:00",
+ "pwm0_grp", "pwm"),
+};
+
 void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on)
 {
struct drm_device *dev = intel_dsi->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
+   bool want_backlight_gpio = false;
+   bool want_panel_gpio = false;
+   struct pinctrl *pinctrl;
+   int ret;
 
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
mipi_config->pwm_blc == PPS_BLC_PMIC) {
gpiod_add_lookup_table(_panel_gpio_table);
+   

[PATCH v2 2/5] drm/i915/dsi: Move poking of panel-enable GPIO to intel_dsi_vbt.c

2019-12-16 Thread Hans de Goede
On some older devices (BYT, CHT) which may use v2 VBT MIPI-sequences,
we need to manually control the panel enable GPIO as v2 sequences do
not do this.

So far we have been carrying the code to do this on BYT/CHT devices
with a Crystal Cove PMIC in vlv_dsi.c, but as this really is a shortcoming
of the VBT MIPI-sequences, intel_dsi_vbt.c is a better place for this,
so move it there.

This is a preparation patch for adding panel-enable and backlight-enable
GPIO support for BYT devices where instead of the PMIC the SoC is used
for backlight control.

Reviewed-by: Linus Walleij 
Reviewed-by: Ville Syrjälä 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_dsi.h |  2 +
 drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 46 +++-
 drivers/gpu/drm/i915/display/vlv_dsi.c   | 27 +---
 3 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsi.h 
b/drivers/gpu/drm/i915/display/intel_dsi.h
index b15be5814599..de7e51cd3460 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi.h
+++ b/drivers/gpu/drm/i915/display/intel_dsi.h
@@ -203,6 +203,8 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, 
enum port port);
 
 /* intel_dsi_vbt.c */
 bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
+void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi);
+void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi);
 void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
 enum mipi_seq seq_id);
 void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec);
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c 
b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index f90946c912ee..8be7d6c507aa 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -453,8 +453,8 @@ static const char *sequence_name(enum mipi_seq seq_id)
return "(unknown)";
 }
 
-void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
-enum mipi_seq seq_id)
+static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
+  enum mipi_seq seq_id)
 {
struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
const u8 *data;
@@ -519,6 +519,18 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi 
*intel_dsi,
}
 }
 
+void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
+enum mipi_seq seq_id)
+{
+   if (seq_id == MIPI_SEQ_POWER_ON && intel_dsi->gpio_panel)
+   gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
+
+   intel_dsi_vbt_exec(intel_dsi, seq_id);
+
+   if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel)
+   gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
+}
+
 void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
 {
struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
@@ -671,3 +683,33 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 
panel_id)
 
return true;
 }
+
+/*
+ * On some BYT/CHT devs some sequences are incomplete and we need to manually
+ * control some GPIOs.
+ */
+void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi)
+{
+   struct drm_device *dev = intel_dsi->base.base.dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
+
+   if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+   mipi_config->pwm_blc == PPS_BLC_PMIC) {
+   intel_dsi->gpio_panel =
+   gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH);
+
+   if (IS_ERR(intel_dsi->gpio_panel)) {
+   DRM_ERROR("Failed to own gpio for panel control\n");
+   intel_dsi->gpio_panel = NULL;
+   }
+   }
+}
+
+void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi)
+{
+   if (intel_dsi->gpio_panel) {
+   gpiod_put(intel_dsi->gpio_panel);
+   intel_dsi->gpio_panel = NULL;
+   }
+}
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c 
b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 403fb09fcb63..c1edd8857af0 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -23,7 +23,6 @@
  * Author: Jani Nikula 
  */
 
-#include 
 #include 
 
 #include 
@@ -797,9 +796,6 @@ static void intel_dsi_pre_enable(struct intel_encoder 
*encoder,
if (!IS_GEMINILAKE(dev_priv))
intel_dsi_prepare(encoder, pipe_config);
 
-   /* Power on, try both CRC pmic gpio and VBT */
-   if (intel_dsi->gpio_panel)
-   gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
 
@@ -943,11 +939,8 @@ static void intel_dsi_post_disable(struct 

Re: [PATCHv4 03/36] drm/gem-fb-helper: Allow drivers to allocate struct drm_framebuffer on their own

2019-12-16 Thread Andrzej Pietrasiewicz

Hi Liviu,

My way of thinking is explained below. Do you still find it problematic?

W dniu 16.12.2019 o 18:08, Liviu Dudau pisze:

Hi Andrzej,






+struct drm_framebuffer *
+drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
+const struct drm_mode_fb_cmd2 *mode_cmd,
+const struct drm_framebuffer_funcs *funcs)
+{
+   struct drm_gem_object *objs[4];
+   struct drm_framebuffer *fb;
+   int ret, num_planes;
+
+   ret = drm_gem_fb_lookup(dev, file, mode_cmd, objs);
+   if (ret < 0)
+   return ERR_PTR(ret);


here objs is guaranteed to have been filled...


+   num_planes = ret;
+
+   ret = drm_gem_fb_size_check(dev, mode_cmd, objs);


if drm_gem_fb_size_check() returns an error, then ...


+   if (ret)
+   fb = ERR_PTR(ret);
+   else
+   fb = drm_gem_fb_alloc(dev, mode_cmd, objs, num_planes, funcs);


 the else part is not taken, but ...


... nonetheless objs have already been looked up...



  
-	return ERR_PTR(ret);

+   if (IS_ERR(fb))
+   for (num_planes--; num_planes >= 0; num_planes--)
+   drm_gem_object_put_unlocked(objs[num_planes]);


... here you'll attempt to dereference the objs. I don't think that is correct.


... so it is safe to dereference objs here

Regards,

Andrzej
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[CI 1/3] ACPI / LPSS: Rename pwm_backlight pwm-lookup to pwm_soc_backlight

2019-12-16 Thread Hans de Goede
At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2
different PWM controllers for controlling the LCD's backlight brightness.
Either the one integrated into the PMIC or the one integrated into the
SoC (the 1st LPSS PWM controller).

So far in the LPSS code on BYT we have skipped registering the LPSS PWM
controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is
present, assuming that in this case the PMIC PWM controller will be used.

On CHT we have been relying on only 1 of the 2 PWM controllers being
enabled in the DSDT at the same time; and always registered the lookup.

So far this has been working, but the correct way to determine which PWM
controller needs to be used is by checking a bit in the VBT table and
recently I've learned about 2 different BYT devices:
Point of View MOBII TAB-P800W
Acer Switch 10 SW5-012

Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS
PWM controller (and the VBT correctly indicates this), so here our old
heuristics fail.

Since only the i915 driver has access to the VBT, this commit renames
the "pwm_backlight" lookup entries for the 1st BYT/CHT LPSS PWM controller
to "pwm_soc_backlight" so that the i915 driver can do a pwm_get() for
the right controller depending on the VBT bit, instead of the i915 driver
relying on a "pwm_backlight" lookup getting registered which magically
points to the right controller.

Acked-by: Jani Nikula 
Reviewed-by: Andy Shevchenko 
Acked-by: Rafael J. Wysocki 
Signed-off-by: Hans de Goede 
---
 drivers/acpi/acpi_lpss.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 70f740b09684..db18df6cb330 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -69,10 +69,6 @@ ACPI_MODULE_NAME("acpi_lpss");
 #define LPSS_SAVE_CTX  BIT(4)
 #define LPSS_NO_D3_DELAY   BIT(5)
 
-/* Crystal Cove PMIC shares same ACPI ID between different platforms */
-#define BYT_CRC_HRV2
-#define CHT_CRC_HRV3
-
 struct lpss_private_data;
 
 struct lpss_device_desc {
@@ -158,7 +154,7 @@ static void lpss_deassert_reset(struct lpss_private_data 
*pdata)
  */
 static struct pwm_lookup byt_pwm_lookup[] = {
PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, ":00:02.0",
-  "pwm_backlight", 0, PWM_POLARITY_NORMAL,
+  "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL,
   "pwm-lpss-platform"),
 };
 
@@ -170,8 +166,7 @@ static void byt_pwm_setup(struct lpss_private_data *pdata)
if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1"))
return;
 
-   if (!acpi_dev_present("INT33FD", NULL, BYT_CRC_HRV))
-   pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
+   pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
 }
 
 #define LPSS_I2C_ENABLE0x6c
@@ -204,7 +199,7 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
 /* BSW PWM used for backlight control by the i915 driver */
 static struct pwm_lookup bsw_pwm_lookup[] = {
PWM_LOOKUP_WITH_MODULE("80862288:00", 0, ":00:02.0",
-  "pwm_backlight", 0, PWM_POLARITY_NORMAL,
+  "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL,
   "pwm-lpss-platform"),
 };
 
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[CI 2/3] mfd: intel_soc_pmic: Rename pwm_backlight pwm-lookup to pwm_pmic_backlight

2019-12-16 Thread Hans de Goede
At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2
different PWM controllers for controlling the LCD's backlight brightness.

Either the one integrated into the PMIC or the one integrated into the
SoC (the 1st LPSS PWM controller).

So far in the LPSS code on BYT we have skipped registering the LPSS PWM
controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is
present, assuming that in this case the PMIC PWM controller will be used.

On CHT we have been relying on only 1 of the 2 PWM controllers being
enabled in the DSDT at the same time; and always registered the lookup.

So far this has been working, but the correct way to determine which PWM
controller needs to be used is by checking a bit in the VBT table and
recently I've learned about 2 different BYT devices:
Point of View MOBII TAB-P800W
Acer Switch 10 SW5-012

Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS
PWM controller (and the VBT correctly indicates this), so here our old
heuristics fail.

Since only the i915 driver has access to the VBT, this commit renames
the "pwm_backlight" lookup entries for the Crystal Cove PMIC's PWM
controller to "pwm_pmic_backlight" so that the i915 driver can do a
pwm_get() for the right controller depending on the VBT bit, instead of
the i915 driver relying on a "pwm_backlight" lookup getting registered
which magically points to the right controller.

Acked-by: Jani Nikula 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Hans de Goede 
---
 drivers/mfd/intel_soc_pmic_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mfd/intel_soc_pmic_core.c 
b/drivers/mfd/intel_soc_pmic_core.c
index c9f35378d391..47188df3080d 100644
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -38,7 +38,7 @@ static struct gpiod_lookup_table panel_gpio_table = {
 
 /* PWM consumed by the Intel GFX */
 static struct pwm_lookup crc_pwm_lookup[] = {
-   PWM_LOOKUP("crystal_cove_pwm", 0, ":00:02.0", "pwm_backlight", 0, 
PWM_POLARITY_NORMAL),
+   PWM_LOOKUP("crystal_cove_pwm", 0, ":00:02.0", "pwm_pmic_backlight", 
0, PWM_POLARITY_NORMAL),
 };
 
 static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[CI 0/3] drm/i915 / LPSS / mfd: Select correct PWM controller to use based on VBT

2019-12-16 Thread Hans de Goede
Hi All,

Somehow the CI system did not pick up this series the first time, there
are no test results recorded for it:
https://patchwork.freedesktop.org/series/69685

So this is a resend for CI to do its thing. As soon as CI is happy with
this I will push this to drm-intel-next-queued.

Regards,

Hans

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[CI 3/3] drm/i915: DSI: select correct PWM controller to use based on the VBT

2019-12-16 Thread Hans de Goede
At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2
different PWM controllers for controlling the LCD's backlight brightness.
Either the one integrated into the PMIC or the one integrated into the
SoC (the 1st LPSS PWM controller).

So far in the LPSS code on BYT we have skipped registering the LPSS PWM
controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is
present, assuming that in this case the PMIC PWM controller will be used.

On CHT we have been relying on only 1 of the 2 PWM controllers being
enabled in the DSDT at the same time; and always registered the lookup.

So far this has been working, but the correct way to determine which PWM
controller needs to be used is by checking a bit in the VBT table and
recently I've learned about 2 different BYT devices:
Point of View MOBII TAB-P800W
Acer Switch 10 SW5-012

Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS
PWM controller (and the VBT correctly indicates this), so here our old
heuristics fail.

This commit fixes using the wrong PWM controller on these devices by
calling pwm_get() for the right PWM controller based on the
VBT dsi.config.pwm_blc bit.

Note this is part of a series which contains 2 other patches which renames
the PWM lookup for the 1st SoC/LPSS PWM from "pwm_backlight" to
"pwm_pmic_backlight" and the PWM lookup for the Crystal Cove PMIC PWM
from "pwm_backlight" to "pwm_pmic_backlight".

Acked-by: Jani Nikula 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Hans de Goede 
---
 drivers/gpu/drm/i915/display/intel_panel.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_panel.c 
b/drivers/gpu/drm/i915/display/intel_panel.c
index bc14e9c0285a..ddcf311d1114 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -1840,13 +1840,22 @@ static int pwm_setup_backlight(struct intel_connector 
*connector,
   enum pipe pipe)
 {
struct drm_device *dev = connector->base.dev;
+   struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_panel *panel = >panel;
+   const char *desc;
int retval;
 
-   /* Get the PWM chip for backlight control */
-   panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight");
+   /* Get the right PWM chip for DSI backlight according to VBT */
+   if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) {
+   panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight");
+   desc = "PMIC";
+   } else {
+   panel->backlight.pwm = pwm_get(dev->dev, "pwm_soc_backlight");
+   desc = "SoC";
+   }
+
if (IS_ERR(panel->backlight.pwm)) {
-   DRM_ERROR("Failed to own the pwm chip\n");
+   DRM_ERROR("Failed to get the %s PWM chip\n", desc);
panel->backlight.pwm = NULL;
return -ENODEV;
}
@@ -1873,6 +1882,7 @@ static int pwm_setup_backlight(struct intel_connector 
*connector,
 CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.enabled = panel->backlight.level != 0;
 
+   DRM_INFO("Using %s PWM for LCD backlight control\n", desc);
return 0;
 }
 
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 201497] [amdgpu]: '*ERROR* No EDID read' is back in 4.19

2019-12-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=201497

--- Comment #12 from Sebastien Bernard (sbern...@nerim.net) ---
I wonder if it's not a bad EDID from the monitor.
Anyway, that's a regression from 4.18.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 2/2] drm/i915/dp: Use BDB_GENERAL_FEATURES VBT block info for builtin panel-orientation

2019-12-16 Thread Hans de Goede

Hi,

On 16-12-2019 14:39, Ville Syrjälä wrote:

On Sun, Dec 15, 2019 at 10:33:07PM +0100, Hans de Goede wrote:

Some devices with a builtin panel have the panel mounted upside down,
this is indicated by the rotate_180 bit in the BDB_GENERAL_FEATURES VBT
block.

We store this info in dev_priv->vbt.orientation, use this to set the
connector's orientation property so that fbcon and userspace will show
the image the right way up on devices with an upside-down mounted panel.

This fixes the image being upside-down on a Teclast X89 tablet.

Signed-off-by: Hans de Goede 
---
  drivers/gpu/drm/i915/display/intel_dp.c | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index b05b2191b919..d31c04a22976 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -7350,9 +7350,12 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
intel_connector->panel.backlight.power = intel_edp_backlight_power;
intel_panel_setup_backlight(connector, pipe);
  
-	if (fixed_mode)

+   if (fixed_mode) {
+   connector->display_info.panel_orientation =
+   dev_priv->vbt.orientation;


Do we want to set this to UNKNOWN when the VBT didn't supply the
information? IIRC the DSI code sets it to NORMAL in that case.


It is true that the DSI code sets it to normal where-as the
code filling dev_priv->vbt.orientation will set it to unknown if the
info is missing from the VBT.

Note that drm_connector_init_panel_orientation_property() will simply
omit the property if the value is unknown (and userspace treats
the property no being there as "normal").

Omitting the property when we do not know is what we have been doing
sofar for eDP panels and that does feel like the right thing to do,
I would prefer to continue doing that, as that seems the most correct
behavior, if we do not know, do not advertise any specific orientation.

Regards,

Hans






drm_connector_init_panel_orientation_property(
connector, fixed_mode->hdisplay, fixed_mode->vdisplay);
+   }
  
  	return true;
  
--

2.23.0




___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv4 05/36] drm/gem-fb-helper: Add generic afbc size checks

2019-12-16 Thread Andrzej Pietrasiewicz

Hi Liviu,

W dniu 16.12.2019 o 18:19, Liviu Dudau pisze:

Hi Andrzej,

On Fri, Dec 13, 2019 at 04:58:36PM +0100, Andrzej Pietrasiewicz wrote:

Extend the size-checking special function to handle afbc.

Signed-off-by: Andrzej Pietrasiewicz 
---
  drivers/gpu/drm/drm_fourcc.c | 10 +++-
  drivers/gpu/drm/drm_framebuffer.c|  3 +
  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 60 ++--
  include/drm/drm_gem_framebuffer_helper.h | 16 ++
  4 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index d14dd7c86020..9ac2175c5bee 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -323,8 +323,14 @@ drm_get_format_info(struct drm_device *dev,
  {
const struct drm_format_info *info = NULL;
  
-	if (dev->mode_config.funcs->get_format_info)

-   info = dev->mode_config.funcs->get_format_info(mode_cmd);
+   /* bypass driver callback if afbc */
+   if (!drm_is_afbc(mode_cmd->modifier[0]))
+   if (dev->mode_config.funcs->get_format_info) {
+   const struct drm_mode_config_funcs *funcs;
+
+   funcs = dev->mode_config.funcs;
+   info = funcs->get_format_info(mode_cmd);
+   }


What has this change to do with the rest of the patch? Also, I think this goes
against the idea that an AFBC-aware driver might return better data about the 
format
info than the drm_format_info() code.



The reason is the conclusion of my talk with danvet on irc:

https://people.freedesktop.org/~cbrill/dri-log/?channel=dri-devel_names==2019-11-13_html=true

I followed his advice - if I understood him correctly, that is.


As a bikeshed, I know it is useful for debugging to turn the oneliner into 3, 
but it
feels like not necessary here.


80 chars per line. If kept in one line, the limit is exceeded
with an additional indentation level present.

Regards,

Andrzej
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v12 1/7] dt-bindings: sun6i-dsi: Document A64 MIPI-DSI controller

2019-12-16 Thread Maxime Ripard
On Mon, Dec 16, 2019 at 10:29:08PM +0530, Jagan Teki wrote:
> On Mon, Dec 16, 2019 at 4:50 PM Maxime Ripard  wrote:
> >
> > On Mon, Dec 16, 2019 at 04:37:20PM +0530, Jagan Teki wrote:
> > > On Wed, Dec 4, 2019 at 7:06 PM Maxime Ripard  wrote:
> > > >
> > > > On Tue, Dec 03, 2019 at 07:18:10PM +0530, Jagan Teki wrote:
> > > > > The MIPI DSI controller in Allwinner A64 is similar to A33.
> > > > >
> > > > > But unlike A33, A64 doesn't have DSI_SCLK gating so it is valid
> > > > > to have separate compatible for A64 on the same driver.
> > > > >
> > > > > DSI_SCLK uses mod clock-names on dt-bindings, so the same
> > > > > is not required for A64.
> > > > >
> > > > > On that note
> > > > > - A64 require minimum of 1 clock like the bus clock
> > > > > - A33 require minimum of 2 clocks like both bus, mod clocks
> > > > >
> > > > > So, update dt-bindings so-that it can document both A33,
> > > > > A64 bindings requirements.
> > > > >
> > > > > Reviewed-by: Rob Herring 
> > > > > Signed-off-by: Jagan Teki 
> > > > > ---
> > > > > Changes for v12:
> > > > > - Use 'enum' instead of oneOf+const
> > > > >
> > > > >  .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 20 
> > > > > +--
> > > > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git 
> > > > > a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > >  
> > > > > b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > > index dafc0980c4fa..b91446475f35 100644
> > > > > --- 
> > > > > a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > > +++ 
> > > > > b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > > @@ -15,7 +15,9 @@ properties:
> > > > >"#size-cells": true
> > > > >
> > > > >compatible:
> > > > > -const: allwinner,sun6i-a31-mipi-dsi
> > > > > +enum:
> > > > > +  - allwinner,sun6i-a31-mipi-dsi
> > > > > +  - allwinner,sun50i-a64-mipi-dsi
> > > > >
> > > > >reg:
> > > > >  maxItems: 1
> > > > > @@ -24,6 +26,8 @@ properties:
> > > > >  maxItems: 1
> > > > >
> > > > >clocks:
> > > > > +minItems: 1
> > > > > +maxItems: 2
> > > > >  items:
> > > > >- description: Bus Clock
> > > > >- description: Module Clock
> > > > > @@ -63,13 +67,25 @@ required:
> > > > >- reg
> > > > >- interrupts
> > > > >- clocks
> > > > > -  - clock-names
> > > > >- phys
> > > > >- phy-names
> > > > >- resets
> > > > >- vcc-dsi-supply
> > > > >- port
> > > > >
> > > > > +allOf:
> > > > > +  - if:
> > > > > +  properties:
> > > > > + compatible:
> > > > > +   contains:
> > > > > + const: allwinner,sun6i-a31-mipi-dsi
> > > > > +  then:
> > > > > +properties:
> > > > > +  clocks:
> > > > > +minItems: 2
> > > > > +required:
> > > > > +  - clock-names
> > > > > +
> > > >
> > > > Your else condition should check that the number of clocks items is 1
> > > > on the A64
> > >
> > > But the minItems mentioned as 1 in clocks, which is unchanged number
> > > by default. doesn't it sufficient?
> >
> > In the main schema, it's said that the clocks property can have one or
> > two elements (to cover the A31 case that has one, and the A64 case
> > that has 2).
> >
> > This is fine.
> >
> > Later on, you enforce that the A64 has two elements, and this is fine
> > too.
>
> Actually A31 case has 2 and A64 case has 1.
>
> >
> > However, you never check that on the A31 you only have one clock, and
> > you could very well have two and no one would notice.
>
> I did check A31 case for 2 but not in A64. this is what you mean? so
> adding A64 check like below would fine?
>
> allOf:
>   - if:
>   properties:
>  compatible:
>contains:
>  const: allwinner,sun6i-a31-mipi-dsi

You need a new line here

>   then:

This is the wrong level of indentation, it needs to be at the same level than if

> properties:
>   clocks:
> minItems: 2

Newline

> required:
>   - clock-names

Newline

>   - if:
>   properties:
>  compatible:
>contains:
>  const: allwinner,sun50i-a64-mipi-dsi
>   then:
> properties:
>   clocks:
> minItems: 1

(and same thing here).

But yeah, otherwise that's what I meant

Maxime


signature.asc
Description: PGP signature
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2] drm/modes: Apply video parameters with only reflect option

2019-12-16 Thread Stephan Gerhold
On Mon, Dec 16, 2019 at 07:27:25PM +0200, Ville Syrjälä wrote:
> On Mon, Dec 16, 2019 at 06:10:17PM +0100, Stephan Gerhold wrote:
> > At the moment, video mode parameters like video=540x960,reflect_x,
> > (without rotation set) are not taken into account when applying the
> > mode in drm_client_modeset.c.
> 
> A rotation value without exactly one rotation angle is illegal.
> IMO the code should not generate a value like that in the first
> place.
> 

You're right. I was thinking about this when creating this patch.
But then I was not sure if "mode->rotation_reflection" is supposed to be
a valid rotation value.The zero value is currently used to check
if any rotation/reflection was specified at all:

[...]
> > diff --git a/drivers/gpu/drm/drm_client_modeset.c 
> > b/drivers/gpu/drm/drm_client_modeset.c
> > index 895b73f23079..cfebce4f19a5 100644
> > --- a/drivers/gpu/drm/drm_client_modeset.c
> > +++ b/drivers/gpu/drm/drm_client_modeset.c
> > @@ -859,19 +859,23 @@ bool drm_client_rotation(struct drm_mode_set 
> > *modeset, unsigned int *rotation)
> >  */
> > cmdline = >cmdline_mode;
> > if (cmdline->specified && cmdline->rotation_reflection) {

I can try to make your suggested change in the cmdline parsing code,
but since this sounds like a larger change I would appreciate
some other opinions first.

Thanks,
Stephan

> > 
> > -   unsigned int cmdline_rest, panel_rest;
> > -   unsigned int cmdline_rot, panel_rot;
> > -   unsigned int sum_rot, sum_rest;
> > +   if (cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK) {
> > +   unsigned int cmdline_rest, panel_rest;
> > +   unsigned int cmdline_rot, panel_rot;
> > +   unsigned int sum_rot, sum_rest;
> >  
> > -   panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
> > -   cmdline_rot = ilog2(cmdline->rotation_reflection & 
> > DRM_MODE_ROTATE_MASK);
> > -   sum_rot = (panel_rot + cmdline_rot) % 4;
> > +   panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
> > +   cmdline_rot = ilog2(cmdline->rotation_reflection & 
> > DRM_MODE_ROTATE_MASK);
> > +   sum_rot = (panel_rot + cmdline_rot) % 4;
> >  
> > -   panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
> > -   cmdline_rest = cmdline->rotation_reflection & 
> > ~DRM_MODE_ROTATE_MASK;
> > -   sum_rest = panel_rest ^ cmdline_rest;
> > +   panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
> > +   cmdline_rest = cmdline->rotation_reflection & 
> > ~DRM_MODE_ROTATE_MASK;
> > +   sum_rest = panel_rest ^ cmdline_rest;
> >  
> > -   *rotation = (1 << sum_rot) | sum_rest;
> > +   *rotation = (1 << sum_rot) | sum_rest;
> > +   } else {
> > +   *rotation ^= cmdline->rotation_reflection;
> > +   }
> > }
> >  
> > /*
> > @@ -879,7 +883,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, 
> > unsigned int *rotation)
> >  * depending on the hardware this may require the framebuffer
> >  * to be in a specific tiling format.
> >  */
> > -   if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
> > +   if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
> > +(*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
> > !plane->rotation_property)
> > return false;
> >  
> > -- 
> > 2.24.1
> > 
> > ___
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> -- 
> Ville Syrjälä
> Intel
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


powernv build issue

2019-12-16 Thread David Hildenbrand
Hi,

the patch "drm/drm_panel: fix EXPORT of drm_panel_of_backlight" in
linux-next breaks the powernv build:

desktop: ~/git/linux-ppc memtrace $ ./compile.sh
  CALLscripts/atomic/check-atomics.sh
  CALLscripts/checksyscalls.sh
  CHK include/generated/compile.h
  GEN .version
  CHK include/generated/compile.h
  UPD include/generated/compile.h
  CC  init/version.o
  AR  init/built-in.a
  LD  vmlinux.o
  MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0x2fc8): Section mismatch in reference from the
variable start_here_common to the function .init.text:start_kernel()
The function start_here_common() references
the function __init start_kernel().
This is often because start_here_common lacks a __init
annotation or the annotation of start_kernel is wrong.

  MODINFO modules.builtin.modinfo
  LD  .tmp_vmlinux1
ppc64-linux-gnu-ld: drivers/gpu/drm/drm_panel.o: in function
`drm_panel_of_backlight':
(.text+0x434): undefined reference to `devm_of_find_backlight'
make: *** [Makefile:1079: vmlinux] Fehler 1

Reverting it makes it compile again. (not exploring the root issue, I
just need a powernv built and reverting that commit did the trick )

-- 
Thanks,

David / dhildenb

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v3] drm/mcde: Some fixes to handling video mode

2019-12-16 Thread Stephan Gerhold
Hi Linus,

Thanks for keeping this patch updated!
I think it is about time that we get this patch applied
- it gets increasingly larger and more complex and therefore difficult
to review.

Most of it looks fine to me, I just have a few notes below:

On Tue, Dec 10, 2019 at 11:48:57PM +0100, Linus Walleij wrote:
> The video DSI mode had not really been tested. These fixes makes
> it more likely to work on real hardware:
> - Put the active width (x width) in the right bits and the VSA
>   (vertical sync active) in the right bits (those were swapped).
> - Calculate the packet sizes in bytes as in the vendor driver,
>   rather than in bits. Test the calculations agains a
>   spreadsheet and confirmed by debug prints to be reasonable.
> - Also verified the register values with relative confidence
>   to register dumps from the Samsung GT-I8190 boot loader
>   graphics. We are not identical but not off by far either.
> - Error out if the current mode and refresh frequency doesn't
>   work out. (In the future we may simply want to scale down
>   the vrefresh.)
> - Handle negative result in front/back/sync packages and fall
>   back to zero like in the vendor driver.
> - Put in lots of clarifying comments and references to the
>   documentation where the code is hard to understand.
> 
> Cc: Stephan Gerhold 
> Fixes: 5fc537bfd000 ("drm/mcde: Add new driver for ST-Ericsson MCDE")
> Signed-off-by: Linus Walleij 
> ---
> ChangeLog v2->v3:
> - Calculate toward actual HS rate of the clock rather than the
>   idealized rate provided by the panel resolution, this is what
>   the vendor driver does.
> - Add much comments and elaborate with references to the manual
>   so the code can be understood as far as possible.
> - Compared register dumps to that on the Samsung GT-I8190 (Golden)
>   boot loader settings. We are now reasonably close to these,
>   it may be that the boot loader driver is using slightly different
>   settings for porches and syncs etc. But all figures makes sense.
> - Duplicated the vendor code in a spread sheet and compared to
>   what this code gives and we have an identical match with one
>   small exception that the vendor code adds a small padding of 2
>   lines to the vertical blanking area. This looks weird and might
>   be some hackishly specified porch.
> - Rename the "bpp" variable to "cpp" since it is "chars per pixel"
>   this was confusingly named in the vendor driver and it got
>   carried over.
> - Assign the SETTING2_EXACT_BURST_LIMIT by first shifting
>   then masking.
> - Also mask with the inverse of DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK
>   before writing blkeol into DSI_VID_BLKSIZE1, so we make sure
>   to zero these bits first.
> - Also mask with DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK
>   when writing event package length.
> - Comb through the code and compare it to vendor code and try
>   to get closer to doing what the vendor driver is doing.
> ChangeLog v1->v2:
> - Fix some more comments so we understand what is going on.
> - Set up the maximum line limit size in the right register
>   instead of setting it in the burst size register portion.
> - Set some default wakeup time other than zero (still need
>   fixing more).
> ---
>  drivers/gpu/drm/mcde/mcde_dsi.c | 221 +---
>  1 file changed, 178 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
> index 21cee4d9d2fd..e9713953c4ac 100644
> --- a/drivers/gpu/drm/mcde/mcde_dsi.c
> +++ b/drivers/gpu/drm/mcde/mcde_dsi.c
> @@ -379,13 +379,14 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
>  static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
> const struct drm_display_mode *mode)
>  {
> - u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format);
> + /* cpp, characters per pixel, number of bytes per pixel */
> + u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8;
> + u64 pclk;
>   u64 bpl;
> - u32 hfp;
> - u32 hbp;
> - u32 hsa;
> + int hfp;
> + int hbp;
> + int hsa;
>   u32 blkline_pck, line_duration;
> - u32 blkeol_pck, blkeol_duration;
>   u32 val;
>  
>   val = 0;
> @@ -422,11 +423,21 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi 
> *d,
>   return;
>   }
>  
> - /* TODO: TVG could be enabled here */
> + /* TODO: TVG (test video generator) could be enabled here */
>  
> - /* Send blanking packet */
> + /*
> +  * During vertical blanking: go to LP mode
> +  * Like with the EOL setting, if this is not set, the EOL area will be
> +  * filled with NULL or blanking packets in the vblank area.
> +  * FIXME: some Samsung phones and display panels such as s6e63m0 use
> +  * DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING here instead,
> +  * figure out how to properly configure that from the panel.
> +  */
>   val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0;
> - /* 

Re: [PATCH v3 5/5] drm/msm/a6xx: Support split pagetables

2019-12-16 Thread Rob Clark
On Mon, Dec 16, 2019 at 8:38 AM Jordan Crouse  wrote:
>
> Attempt to enable split pagetables if the arm-smmu driver supports it.
> This will move the default address space from the default region to
> the address range assigned to TTBR1. The behavior should be transparent
> to the driver for now but it gets the default buffers out of the way
> when we want to start swapping TTBR0 for context-specific pagetables.
>
> Signed-off-by: Jordan Crouse 

Reviewed-by: Rob Clark 

(my previous r-b's on the other patches from v2 carries over to v3)

> ---
>
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 52 
> ++-
>  1 file changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 5dc0b2c..1c6da93 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -811,6 +811,56 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
> return (unsigned long)busy_time;
>  }
>
> +static struct msm_gem_address_space *
> +a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
> +{
> +   struct iommu_domain *iommu = iommu_domain_alloc(_bus_type);
> +   struct msm_gem_address_space *aspace;
> +   struct msm_mmu *mmu;
> +   u64 start, size;
> +   u32 val = 1;
> +   int ret;
> +
> +   if (!iommu)
> +   return ERR_PTR(-ENOMEM);
> +
> +   /*
> +* Try to request split pagetables - the request has to be made before
> +* the domian is attached
> +*/
> +   iommu_domain_set_attr(iommu, DOMAIN_ATTR_SPLIT_TABLES, );
> +
> +   mmu = msm_iommu_new(>dev, iommu);
> +   if (IS_ERR(mmu)) {
> +   iommu_domain_free(iommu);
> +   return ERR_CAST(mmu);
> +   }
> +
> +   /*
> +* After the domain is attached, see if the split tables were actually
> +* successful.
> +*/
> +   ret = iommu_domain_get_attr(iommu, DOMAIN_ATTR_SPLIT_TABLES, );
> +   if (!ret && val) {
> +   /*
> +* The aperture start will be at the beginning of the TTBR1
> +* space so use that as a base
> +*/
> +   start = iommu->geometry.aperture_start;
> +   size = 0x;
> +   } else {
> +   /* Otherwise use the legacy 32 bit region */
> +   start = SZ_16M;
> +   size = 0x - SZ_16M;
> +   }
> +
> +   aspace = msm_gem_address_space_create(mmu, "gpu", start, size);
> +   if (IS_ERR(aspace))
> +   iommu_domain_free(iommu);
> +
> +   return aspace;
> +}
> +
>  static const struct adreno_gpu_funcs funcs = {
> .base = {
> .get_param = adreno_get_param,
> @@ -832,7 +882,7 @@ static const struct adreno_gpu_funcs funcs = {
>  #if defined(CONFIG_DRM_MSM_GPU_STATE)
> .gpu_state_get = a6xx_gpu_state_get,
> .gpu_state_put = a6xx_gpu_state_put,
> -   .create_address_space = adreno_iommu_create_address_space,
> +   .create_address_space = a6xx_create_address_space,
>  #endif
> },
> .get_timestamp = a6xx_get_timestamp,
> --
> 2.7.4
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2] backlight: pwm_bl: Switch to full GPIO descriptor

2019-12-16 Thread Krzysztof Kozlowski
On Fri, 13 Dec 2019 at 11:23, Linus Walleij  wrote:
>
> The PWM backlight still supports passing a enable GPIO line as
> platform data using the legacy  API.
>
> It turns out that ever board using this mechanism except one
> is pass .enable_gpio = -1. So we drop all these cargo-culted -1's
> from all instances of this platform data in the kernel.
>
> The remaning board, Palm TC, is converted to pass a machine
> descriptior table with the "enable" GPIO instead, and delete the
> platform data entry for enable_gpio and the code handling it
> and things should work smoothly with the new API.
>
> Cc: Krzysztof Kozlowski 
> Cc: Robert Jarzmik 
> Cc: Guan Xuetao 
> Reviewed-by: Bartosz Golaszewski 
> Signed-off-by: Linus Walleij 
> ---
> ChangeLog v1->v2:
> - Located a missing removal of .enable_gpio in the Palm TC
>   board file, pointed out by Daniel.
> - Grepped to ascertain there is not a single instance of
>   the string "enable_gpio" in the affected board files.
> ---
>  arch/arm/mach-pxa/cm-x300.c   |  1 -
>  arch/arm/mach-pxa/colibri-pxa270-income.c |  1 -
>  arch/arm/mach-pxa/ezx.c   |  1 -
>  arch/arm/mach-pxa/hx4700.c|  1 -
>  arch/arm/mach-pxa/lpd270.c|  1 -
>  arch/arm/mach-pxa/magician.c  |  1 -
>  arch/arm/mach-pxa/mainstone.c |  1 -
>  arch/arm/mach-pxa/mioa701.c   |  1 -
>  arch/arm/mach-pxa/palm27x.c   |  1 -
>  arch/arm/mach-pxa/palmtc.c| 11 ++-
>  arch/arm/mach-pxa/palmte2.c   |  1 -
>  arch/arm/mach-pxa/pcm990-baseboard.c  |  1 -
>  arch/arm/mach-pxa/tavorevb.c  |  2 --
>  arch/arm/mach-pxa/viper.c |  1 -
>  arch/arm/mach-pxa/z2.c|  2 --
>  arch/arm/mach-pxa/zylonite.c  |  1 -
>  arch/arm/mach-s3c24xx/mach-h1940.c|  1 -
>  arch/arm/mach-s3c24xx/mach-rx1950.c   |  1 -
>  arch/arm/mach-s3c64xx/dev-backlight.c |  3 ---
>  arch/arm/mach-s3c64xx/mach-crag6410.c |  1 -
>  arch/arm/mach-s3c64xx/mach-hmt.c  |  1 -
>  arch/arm/mach-s3c64xx/mach-smartq.c   |  1 -
>  arch/arm/mach-s3c64xx/mach-smdk6410.c |  2 +-

For s3c:
Acked-by: Krzysztof Kozlowski 

Best regards,
Krzysztof
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 0/3] drm/amdgpu: Remove unneeded semicolon

2019-12-16 Thread Alex Deucher
Applied the series.  Thanks!

Alex

On Sat, Dec 14, 2019 at 9:44 AM zhengbin  wrote:
>
> zhengbin (3):
>   drm/amdgpu: Remove unneeded semicolon in amdgpu_pmu.c
>   drm/amdgpu: Remove unneeded semicolon in gfx_v10_0.c
>   drm/amdgpu: Remove unneeded semicolon in amdgpu_ras.c
>
>  drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c | 8 
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
>  drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c  | 2 +-
>  3 files changed, 6 insertions(+), 6 deletions(-)
>
> --
> 2.7.4
>
> ___
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2] drm/modes: Apply video parameters with only reflect option

2019-12-16 Thread Ville Syrjälä
On Mon, Dec 16, 2019 at 06:10:17PM +0100, Stephan Gerhold wrote:
> At the moment, video mode parameters like video=540x960,reflect_x,
> (without rotation set) are not taken into account when applying the
> mode in drm_client_modeset.c.

A rotation value without exactly one rotation angle is illegal.
IMO the code should not generate a value like that in the first
place.

> 
> One of the reasons for this is that the calculation that
> combines the panel_orientation with cmdline->rotation_reflection
> does not handle the case when cmdline->rotation_reflection does
> not have any rotation set.
> (i.e. cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK == 0)
> 
> Example:
>   *rotation = DRM_MODE_ROTATE_0 (no panel_orientation)
>   cmdline->rotation_reflection = DRM_MODE_REFLECT_X (video=MODE,reflect_x)
> 
> The current code does:
>   panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
>   cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
>   sum_rot = (panel_rot + cmdline_rot) % 4;
> 
> and therefore:
>   panel_rot = ilog2(DRM_MODE_ROTATE_0) = ilog2(1) = 0
>   cmdline_rot = ilog2(0) = -1
>   sum_rot = (0 + -1) % 4 = -1 % 4 = 3
>...
>   *rotation = DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X
> 
> So we incorrectly generate DRM_MODE_ROTATE_270 in this case.
> To prevent cmdline_rot from becoming -1, we need to treat
> the rotation as DRM_MODE_ROTATE_0.
> 
> On the other hand, there is no need to go through that calculation
> at all if no rotation is set in rotation_reflection.
> A simple XOR is enough to combine the reflections.
> 
> Finally, also allow DRM_MODE_ROTATE_0 in the if statement below.
> DRM_MODE_ROTATE_0 means "no rotation" and should therefore not
> require any special handling (e.g. specific tiling format).
> 
> This makes video parameters with only reflect option work correctly.
> 
> Signed-off-by: Stephan Gerhold 
> ---
> v1: https://lists.freedesktop.org/archives/dri-devel/2019-December/248145.html
> 
> Changes in v2:
>   - Clarified commit message - parameters are parsed correctly,
> but not taken into account when applying the mode.
> ---
>  drivers/gpu/drm/drm_client_modeset.c | 27 ---
>  1 file changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_client_modeset.c 
> b/drivers/gpu/drm/drm_client_modeset.c
> index 895b73f23079..cfebce4f19a5 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -859,19 +859,23 @@ bool drm_client_rotation(struct drm_mode_set *modeset, 
> unsigned int *rotation)
>*/
>   cmdline = >cmdline_mode;
>   if (cmdline->specified && cmdline->rotation_reflection) {
> - unsigned int cmdline_rest, panel_rest;
> - unsigned int cmdline_rot, panel_rot;
> - unsigned int sum_rot, sum_rest;
> + if (cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK) {
> + unsigned int cmdline_rest, panel_rest;
> + unsigned int cmdline_rot, panel_rot;
> + unsigned int sum_rot, sum_rest;
>  
> - panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
> - cmdline_rot = ilog2(cmdline->rotation_reflection & 
> DRM_MODE_ROTATE_MASK);
> - sum_rot = (panel_rot + cmdline_rot) % 4;
> + panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
> + cmdline_rot = ilog2(cmdline->rotation_reflection & 
> DRM_MODE_ROTATE_MASK);
> + sum_rot = (panel_rot + cmdline_rot) % 4;
>  
> - panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
> - cmdline_rest = cmdline->rotation_reflection & 
> ~DRM_MODE_ROTATE_MASK;
> - sum_rest = panel_rest ^ cmdline_rest;
> + panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
> + cmdline_rest = cmdline->rotation_reflection & 
> ~DRM_MODE_ROTATE_MASK;
> + sum_rest = panel_rest ^ cmdline_rest;
>  
> - *rotation = (1 << sum_rot) | sum_rest;
> + *rotation = (1 << sum_rot) | sum_rest;
> + } else {
> + *rotation ^= cmdline->rotation_reflection;
> + }
>   }
>  
>   /*
> @@ -879,7 +883,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, 
> unsigned int *rotation)
>* depending on the hardware this may require the framebuffer
>* to be in a specific tiling format.
>*/
> - if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
> + if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
> +  (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
>   !plane->rotation_property)
>   return false;
>  
> -- 
> 2.24.1
> 
> ___
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä

Re: [PATCH] drm/amd/display: Remove unneeded semicolon

2019-12-16 Thread Alex Deucher
On Mon, Dec 16, 2019 at 9:32 AM Harry Wentland  wrote:
>
> On 2019-12-14 4:12 a.m., zhengbin wrote:
> > Fixes coccicheck warning:
> >
> > drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c:412:90-91: 
> > Unneeded semicolon
> >
> > Reported-by: Hulk Robot 
> > Signed-off-by: zhengbin 
>
> Reviewed-by: Harry Wentland 
>

Applied.  Thanks!

Alex

> Harry
>
> > ---
> >  drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c 
> > b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> > index de51ef1..a1b7e76 100644
> > --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> > +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> > @@ -409,7 +409,7 @@ void build_watermark_ranges(struct clk_bw_params 
> > *bw_params, struct pp_smu_wm_ra
> >   continue;
> >
> >   ranges->reader_wm_sets[num_valid_sets].wm_inst = 
> > bw_params->wm_table.entries[i].wm_inst;
> > - ranges->reader_wm_sets[num_valid_sets].wm_type = 
> > bw_params->wm_table.entries[i].wm_type;;
> > + ranges->reader_wm_sets[num_valid_sets].wm_type = 
> > bw_params->wm_table.entries[i].wm_type;
> >   /* We will not select WM based on dcfclk, so leave it as 
> > unconstrained */
> >   ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = 
> > PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
> >   ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = 
> > PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
> > --
> > 2.7.4
> >
> ___
> amd-gfx mailing list
> amd-...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv4 05/36] drm/gem-fb-helper: Add generic afbc size checks

2019-12-16 Thread Liviu Dudau
Hi Andrzej,

On Fri, Dec 13, 2019 at 04:58:36PM +0100, Andrzej Pietrasiewicz wrote:
> Extend the size-checking special function to handle afbc.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  drivers/gpu/drm/drm_fourcc.c | 10 +++-
>  drivers/gpu/drm/drm_framebuffer.c|  3 +
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 60 ++--
>  include/drm/drm_gem_framebuffer_helper.h | 16 ++
>  4 files changed, 82 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
> index d14dd7c86020..9ac2175c5bee 100644
> --- a/drivers/gpu/drm/drm_fourcc.c
> +++ b/drivers/gpu/drm/drm_fourcc.c
> @@ -323,8 +323,14 @@ drm_get_format_info(struct drm_device *dev,
>  {
>   const struct drm_format_info *info = NULL;
>  
> - if (dev->mode_config.funcs->get_format_info)
> - info = dev->mode_config.funcs->get_format_info(mode_cmd);
> + /* bypass driver callback if afbc */
> + if (!drm_is_afbc(mode_cmd->modifier[0]))
> + if (dev->mode_config.funcs->get_format_info) {
> + const struct drm_mode_config_funcs *funcs;
> +
> + funcs = dev->mode_config.funcs;
> + info = funcs->get_format_info(mode_cmd);
> + }

What has this change to do with the rest of the patch? Also, I think this goes
against the idea that an AFBC-aware driver might return better data about the 
format
info than the drm_format_info() code.

As a bikeshed, I know it is useful for debugging to turn the oneliner into 3, 
but it
feels like not necessary here.

Best regards,
Liviu

>  
>   if (!info)
>   info = drm_format_info(mode_cmd->pixel_format);
> diff --git a/drivers/gpu/drm/drm_framebuffer.c 
> b/drivers/gpu/drm/drm_framebuffer.c
> index 57564318ceea..33b741cc73e8 100644
> --- a/drivers/gpu/drm/drm_framebuffer.c
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -204,6 +204,9 @@ static int framebuffer_check(struct drm_device *dev,
>   unsigned int block_size = info->char_per_block[i];
>   u64 min_pitch = drm_format_info_min_pitch(info, i, width);
>  
> + if (drm_is_afbc(r->modifier[i]))
> + block_size = 0;
> +
>   if (!block_size && (r->modifier[i] == DRM_FORMAT_MOD_LINEAR)) {
>   DRM_DEBUG_KMS("Format requires non-linear modifier for 
> plane %d\n", i);
>   return -EINVAL;
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
> b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> index 4201dc1f32a5..e20f4d00b0a5 100644
> --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -21,6 +21,11 @@
>  #include 
>  #include 
>  
> +#define AFBC_HEADER_SIZE 16
> +#define AFBC_TH_LAYOUT_ALIGNMENT 8
> +#define AFBC_SUPERBLOCK_PIXELS   256
> +#define AFBC_SUPERBLOCK_ALIGNMENT128
> +
>  /**
>   * DOC: overview
>   *
> @@ -200,6 +205,40 @@ int drm_gem_fb_lookup(struct drm_device *dev,
>  }
>  EXPORT_SYMBOL_GPL(drm_gem_fb_lookup);
>  
> +static int drm_gem_afbc_min_size(struct drm_device *dev,
> +  const struct drm_mode_fb_cmd2 *mode_cmd,
> +  struct drm_afbc *afbc)
> +{
> + u32 n_blocks;
> +
> + if (!drm_afbc_get_superblock_wh(mode_cmd->modifier[0],
> + >block_width,
> + >block_height)) {
> + return -EINVAL;
> + }
> +
> + /* tiled header afbc */
> + if (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_TILED) {
> + afbc->block_width *= AFBC_TH_LAYOUT_ALIGNMENT;
> + afbc->block_height *= AFBC_TH_LAYOUT_ALIGNMENT;
> + }
> +
> + afbc->aligned_width = ALIGN(mode_cmd->width, afbc->block_width);
> + afbc->aligned_height = ALIGN(mode_cmd->height, afbc->block_height);
> + afbc->offset = mode_cmd->offsets[0];
> +
> + n_blocks = (afbc->aligned_width * afbc->aligned_height)
> +  / AFBC_SUPERBLOCK_PIXELS;
> + afbc->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE,
> +  afbc->alignment_header);
> +
> + afbc->afbc_size = afbc->offset_payload + n_blocks *
> +   ALIGN(afbc->bpp * AFBC_SUPERBLOCK_PIXELS / 8,
> + AFBC_SUPERBLOCK_ALIGNMENT);
> +
> + return 0;
> +}
> +
>  /**
>   * drm_gem_fb_size_check_special() - Helper function for use in
>   *_mode_config_funcs.fb_create
> @@ -218,6 +257,7 @@ int drm_gem_fb_size_check_special(struct drm_device *dev,
> const struct drm_size_check *check,
> struct drm_gem_object **objs)
>  {
> +#define CHECK_HAS(field) (check && check->field)
>   const struct drm_format_info *info;
>   int i;
>  
> @@ -231,24 +271,34 @@ int 

Re: [PATCHv4 04/36] drm/gem-fb-helper: Add special version of drm_gem_fb_size_check

2019-12-16 Thread Liviu Dudau
On Fri, Dec 13, 2019 at 04:58:35PM +0100, Andrzej Pietrasiewicz wrote:
> The new version accepts a struct describing deviations from standard way of
> doing the size checks. The caller must provide the respective values.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 47 
>  include/drm/drm_gem_framebuffer_helper.h | 16 +++
>  2 files changed, 55 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
> b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> index 787edb9a916b..4201dc1f32a5 100644
> --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -201,8 +201,9 @@ int drm_gem_fb_lookup(struct drm_device *dev,
>  EXPORT_SYMBOL_GPL(drm_gem_fb_lookup);
>  
>  /**
> - * drm_gem_fb_size_check() - Helper function for use in
> - *_mode_config_funcs.fb_create implementations
> + * drm_gem_fb_size_check_special() - Helper function for use in
> + *_mode_config_funcs.fb_create
> + *implementations
>   * @dev: DRM device
>   * @mode_cmd: Metadata from the userspace framebuffer creation request
>   *
> @@ -212,9 +213,10 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_lookup);
>   * Returns:
>   * Zero on success or a negative error code on failure.
>   */
> -int drm_gem_fb_size_check(struct drm_device *dev,
> -   const struct drm_mode_fb_cmd2 *mode_cmd,
> -   struct drm_gem_object **objs)
> +int drm_gem_fb_size_check_special(struct drm_device *dev,
> +   const struct drm_mode_fb_cmd2 *mode_cmd,
> +   const struct drm_size_check *check,
> +   struct drm_gem_object **objs)
>  {
>   const struct drm_format_info *info;
>   int i;
> @@ -227,10 +229,19 @@ int drm_gem_fb_size_check(struct drm_device *dev,
>   unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
>   unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
>   unsigned int min_size;
> + u32 pitch = mode_cmd->pitches[i];
> +
> + if (check && check->use_pitch_multiplier)
> + if ((pitch * check->pitch_multiplier[i]) %
> + check->pitch_modulo)
> + return -EINVAL;
>  
> - min_size = (height - 1) * mode_cmd->pitches[i]
> -  + drm_format_info_min_pitch(info, i, width)
> -  + mode_cmd->offsets[i];
> + if (check && check->use_min_size)
> + min_size = check->min_size[i];
> + else
> + min_size = (height - 1) * pitch
> +  + drm_format_info_min_pitch(info, i, width)
> +  + mode_cmd->offsets[i];
>  
>   if (objs[i]->size < min_size)
>   return -EINVAL;
> @@ -239,6 +250,26 @@ int drm_gem_fb_size_check(struct drm_device *dev,
>   return 0;
>  
>  }
> +EXPORT_SYMBOL_GPL(drm_gem_fb_size_check_special);

Hmm, not a big fan of exporting something called foo_special. What about 
following
the tradition of calling it drm_gem_fb_size_check2() ?

Best regards,
Liviu

> +
> +/**
> + * drm_gem_fb_size_check() - Helper function for use in
> + *_mode_config_funcs.fb_create implementations
> + * @dev: DRM device
> + * @mode_cmd: Metadata from the userspace framebuffer creation request
> + *
> + * This function can be used to verify buffer sizes for all planes.
> + * It is caller's responsibility to put the objects on failure.
> + *
> + * Returns:
> + * Zero on success or a negative error code on failure.
> + */
> +int drm_gem_fb_size_check(struct drm_device *dev,
> +   const struct drm_mode_fb_cmd2 *mode_cmd,
> +   struct drm_gem_object **objs)
> +{
> + return drm_gem_fb_size_check_special(dev, mode_cmd, NULL, objs);
> +}
>  EXPORT_SYMBOL_GPL(drm_gem_fb_size_check);
>  
>  /**
> diff --git a/include/drm/drm_gem_framebuffer_helper.h 
> b/include/drm/drm_gem_framebuffer_helper.h
> index c85d4b152e91..74304a268694 100644
> --- a/include/drm/drm_gem_framebuffer_helper.h
> +++ b/include/drm/drm_gem_framebuffer_helper.h
> @@ -11,6 +11,18 @@ struct drm_mode_fb_cmd2;
>  struct drm_plane;
>  struct drm_plane_state;
>  struct drm_simple_display_pipe;
> +struct drm_size_check;
> +
> +/**
> + * struct drm_size_check - Description of special requirements for size 
> checks.
> + */
> +struct drm_size_check {
> + unsigned int min_size[4];
> + bool use_min_size;
> + u32 pitch_multiplier[4];
> + u32 pitch_modulo;
> + bool use_pitch_multiplier;
> +};
>  
>  struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
> unsigned int plane);
> @@ -32,6 +44,10 

[PATCH v2] drm/modes: Apply video parameters with only reflect option

2019-12-16 Thread Stephan Gerhold
At the moment, video mode parameters like video=540x960,reflect_x,
(without rotation set) are not taken into account when applying the
mode in drm_client_modeset.c.

One of the reasons for this is that the calculation that
combines the panel_orientation with cmdline->rotation_reflection
does not handle the case when cmdline->rotation_reflection does
not have any rotation set.
(i.e. cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK == 0)

Example:
  *rotation = DRM_MODE_ROTATE_0 (no panel_orientation)
  cmdline->rotation_reflection = DRM_MODE_REFLECT_X (video=MODE,reflect_x)

The current code does:
  panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
  cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
  sum_rot = (panel_rot + cmdline_rot) % 4;

and therefore:
  panel_rot = ilog2(DRM_MODE_ROTATE_0) = ilog2(1) = 0
  cmdline_rot = ilog2(0) = -1
  sum_rot = (0 + -1) % 4 = -1 % 4 = 3
   ...
  *rotation = DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X

So we incorrectly generate DRM_MODE_ROTATE_270 in this case.
To prevent cmdline_rot from becoming -1, we need to treat
the rotation as DRM_MODE_ROTATE_0.

On the other hand, there is no need to go through that calculation
at all if no rotation is set in rotation_reflection.
A simple XOR is enough to combine the reflections.

Finally, also allow DRM_MODE_ROTATE_0 in the if statement below.
DRM_MODE_ROTATE_0 means "no rotation" and should therefore not
require any special handling (e.g. specific tiling format).

This makes video parameters with only reflect option work correctly.

Signed-off-by: Stephan Gerhold 
---
v1: https://lists.freedesktop.org/archives/dri-devel/2019-December/248145.html

Changes in v2:
  - Clarified commit message - parameters are parsed correctly,
but not taken into account when applying the mode.
---
 drivers/gpu/drm/drm_client_modeset.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c 
b/drivers/gpu/drm/drm_client_modeset.c
index 895b73f23079..cfebce4f19a5 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -859,19 +859,23 @@ bool drm_client_rotation(struct drm_mode_set *modeset, 
unsigned int *rotation)
 */
cmdline = >cmdline_mode;
if (cmdline->specified && cmdline->rotation_reflection) {
-   unsigned int cmdline_rest, panel_rest;
-   unsigned int cmdline_rot, panel_rot;
-   unsigned int sum_rot, sum_rest;
+   if (cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK) {
+   unsigned int cmdline_rest, panel_rest;
+   unsigned int cmdline_rot, panel_rot;
+   unsigned int sum_rot, sum_rest;
 
-   panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
-   cmdline_rot = ilog2(cmdline->rotation_reflection & 
DRM_MODE_ROTATE_MASK);
-   sum_rot = (panel_rot + cmdline_rot) % 4;
+   panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
+   cmdline_rot = ilog2(cmdline->rotation_reflection & 
DRM_MODE_ROTATE_MASK);
+   sum_rot = (panel_rot + cmdline_rot) % 4;
 
-   panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
-   cmdline_rest = cmdline->rotation_reflection & 
~DRM_MODE_ROTATE_MASK;
-   sum_rest = panel_rest ^ cmdline_rest;
+   panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
+   cmdline_rest = cmdline->rotation_reflection & 
~DRM_MODE_ROTATE_MASK;
+   sum_rest = panel_rest ^ cmdline_rest;
 
-   *rotation = (1 << sum_rot) | sum_rest;
+   *rotation = (1 << sum_rot) | sum_rest;
+   } else {
+   *rotation ^= cmdline->rotation_reflection;
+   }
}
 
/*
@@ -879,7 +883,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, 
unsigned int *rotation)
 * depending on the hardware this may require the framebuffer
 * to be in a specific tiling format.
 */
-   if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
+   if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
+(*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
!plane->rotation_property)
return false;
 
-- 
2.24.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCHv4 03/36] drm/gem-fb-helper: Allow drivers to allocate struct drm_framebuffer on their own

2019-12-16 Thread Liviu Dudau
Hi Andrzej,

On Fri, Dec 13, 2019 at 04:58:34PM +0100, Andrzej Pietrasiewicz wrote:
> Prepare tools for drivers which need to allocate a struct drm_framebuffer
> (or a container of struct drm_framebuffer) explicitly, before calling
> helpers. In such a case we need new helpers which omit allocating the
> struct drm_framebuffer and this patch provides them. Consequently, they
> are used also inside the helpers themselves.
> 
> The interested drivers will likely need to be able to perform object
> lookups and size checks in separate invocations and this patch provides
> that as well. Helpers themselves are updated, too.
> 
> Signed-off-by: Andrzej Pietrasiewicz 
> ---
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c | 184 ++-
>  include/drm/drm_gem_framebuffer_helper.h |  17 ++
>  2 files changed, 153 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c 
> b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> index b9bcd310ca2d..787edb9a916b 100644
> --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -54,6 +54,44 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct 
> drm_framebuffer *fb,
>  }
>  EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
>  
> +int drm_gem_fb_init_with_funcs(struct drm_framebuffer *fb,
> +struct drm_device *dev,
> +const struct drm_mode_fb_cmd2 *mode_cmd,
> +struct drm_gem_object **obj,
> +unsigned int num_planes,
> +const struct drm_framebuffer_funcs *funcs)
> +{
> + int ret, i;
> +
> + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
> +
> + for (i = 0; i < num_planes; i++)
> + fb->obj[i] = obj[i];
> +
> + ret = drm_framebuffer_init(dev, fb, funcs);
> + if (ret)
> + DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
> +   ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs);
> +
> +static const struct drm_framebuffer_funcs drm_gem_fb_funcs = {
> + .destroy= drm_gem_fb_destroy,
> + .create_handle  = drm_gem_fb_create_handle,
> +};
> +
> +int drm_gem_fb_init(struct drm_framebuffer *fb,
> + struct drm_device *dev,
> + const struct drm_mode_fb_cmd2 *mode_cmd,
> + struct drm_gem_object **obj, unsigned int num_planes)
> +{
> + return drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes,
> +   _gem_fb_funcs);
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_fb_init);

If you export these two function they should better have documentation 
associated with them.

> +
>  static struct drm_framebuffer *
>  drm_gem_fb_alloc(struct drm_device *dev,
>const struct drm_mode_fb_cmd2 *mode_cmd,
> @@ -61,21 +99,15 @@ drm_gem_fb_alloc(struct drm_device *dev,
>const struct drm_framebuffer_funcs *funcs)
>  {
>   struct drm_framebuffer *fb;
> - int ret, i;
> + int ret;
>  
>   fb = kzalloc(sizeof(*fb), GFP_KERNEL);
>   if (!fb)
>   return ERR_PTR(-ENOMEM);
>  
> - drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
> -
> - for (i = 0; i < num_planes; i++)
> - fb->obj[i] = obj[i];
> -
> - ret = drm_framebuffer_init(dev, fb, funcs);
> + ret = drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes,
> +  funcs);
>   if (ret) {
> - DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
> -   ret);
>   kfree(fb);
>   return ERR_PTR(ret);
>   }
> @@ -124,79 +156,135 @@ int drm_gem_fb_create_handle(struct drm_framebuffer 
> *fb, struct drm_file *file,
>  EXPORT_SYMBOL(drm_gem_fb_create_handle);
>  
>  /**
> - * drm_gem_fb_create_with_funcs() - Helper function for the
> - *  _mode_config_funcs.fb_create
> - *  callback
> + * drm_gem_fb_lookup() - Helper function for use in
> + *_mode_config_funcs.fb_create implementations
>   * @dev: DRM device
>   * @file: DRM file that holds the GEM handle(s) backing the framebuffer
>   * @mode_cmd: Metadata from the userspace framebuffer creation request
> - * @funcs: vtable to be used for the new framebuffer object
>   *
> - * This function can be used to set _framebuffer_funcs for drivers that 
> need
> - * custom framebuffer callbacks. Use drm_gem_fb_create() if you don't need to
> - * change _framebuffer_funcs. The function does buffer size validation.
> + * This function can be used to look up the objects for all planes.
> + * In case an error is returned all the objects are put by the
> + * function before returning.
>   *
>   * Returns:
> - * Pointer to a _framebuffer on success or an error pointer on failure.
> + * Number of planes on success 

Re: [PATCH v21 2/2] drm/bridge: Add I2C based driver for ps8640 bridge

2019-12-16 Thread Ezequiel Garcia
On Mon, 2019-12-16 at 14:58 +0100, Enric Balletbo i Serra wrote:
> From: Jitao Shi 
> 
> This patch adds drm_bridge driver for parade DSI to eDP bridge chip.
> 
> Signed-off-by: Jitao Shi 
> Reviewed-by: Daniel Kurtz 
> Reviewed-by: Enric Balletbo i Serra 
> [uli: followed API changes, removed FW update feature]
> Signed-off-by: Ulrich Hecht 
> Signed-off-by: Enric Balletbo i Serra 
> ---
> 
> Changes in v21:
>  - Use devm_i2c_new_dummy_device and fix build issue using deprecated 
> i2c_new_dummy
>  - Fix build issue due missing drm_bridge.h
>  - Do not remove in ps8640_remove device managed resources
> 
> Changes in v19:
>  - fixed return value of ps8640_probe() when no panel is found
> 
> Changes in v18:
>  - followed DRM API changes
>  - use DEVICE_ATTR_RO()
>  - remove firmware update code
>  - add SPDX identifier
> 
> Changes in v17:
>  - remove some unused head files.
>  - add macros for ps8640 pages.
>  - remove ddc_i2c client
>  - add mipi_dsi_device_register_full
>  - remove the manufacturer from the name and i2c_device_id
> 
> Changes in v16:
>  - Disable ps8640 DSI MCS Function.
>  - Rename gpios name more clearly.
>  - Tune the ps8640 power on sequence.
> 
> Changes in v15:
>  - Drop drm_connector_(un)register calls from parade ps8640.
>The main DRM driver mtk_drm_drv now calls
>drm_connector_register_all() after drm_dev_register() in the
>mtk_drm_bind() function. That function should iterate over all
>connectors and call drm_connector_register() for each of them.
>So, remove drm_connector_(un)register calls from parade ps8640.
> 
> Changes in v14:
>  - update copyright info.
>  - change bridge_to_ps8640 and connector_to_ps8640 to inline function.
>  - fix some coding style.
>  - use sizeof as array counter.
>  - use drm_get_edid when read edid.
>  - add mutex when firmware updating.
> 
> Changes in v13:
>  - add const on data, ps8640_write_bytes(struct i2c_client *client, const u8 
> *data, u16 data_len)
>  - fix PAGE2_SW_REST tyro.
>  - move the buf[3] init to entrance of the function.
> 
> Changes in v12:
>  - fix hw_chip_id build warning
> 
> Changes in v11:
>  - Remove depends on I2C, add DRM depends
>  - Reuse ps8640_write_bytes() in ps8640_write_byte()
>  - Use timer check for polling like the routines in 
>  - Fix no drm_connector_unregister/drm_connector_cleanup when 
> ps8640_bridge_attach fail
>  - Check the ps8640 hardware id in ps8640_validate_firmware
>  - Remove fw_version check
>  - Move ps8640_validate_firmware before ps8640_enter_bl
>  - Add ddc_i2c unregister when probe fail and ps8640_remove
> 
>  drivers/gpu/drm/bridge/Kconfig |  11 +
>  drivers/gpu/drm/bridge/Makefile|   1 +
>  drivers/gpu/drm/bridge/parade-ps8640.c | 655 +
>  3 files changed, 667 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 4734f6993858..3e0a63011723 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -101,6 +101,17 @@ config DRM_PARADE_PS8622
>   ---help---
> Parade eDP-LVDS bridge chip driver.
>  
> +config DRM_PARADE_PS8640
> + tristate "Parade PS8640 MIPI DSI to eDP Converter"
> + depends on OF
> + select DRM_KMS_HELPER
> + select DRM_MIPI_DSI
> + select DRM_PANEL
> + help
> +   Choose this option if you have PS8640 for display
> +   The PS8640 is a high-performance and low-power
> +   MIPI DSI to eDP converter
> +
>  config DRM_SIL_SII8620
>   tristate "Silicon Image SII8620 HDMI/MHL bridge"
>   depends on OF
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 1c0c92667ac4..91490c595b38 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
>  obj-$(CONFIG_DRM_MEGACHIPS_STDP_GE_B850V3_FW) += 
> megachips-stdp-ge-b850v3-fw.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
>  obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
> +obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
>  obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
>  obj-$(CONFIG_DRM_SII902X) += sii902x.o
>  obj-$(CONFIG_DRM_SII9234) += sii9234.o
> diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c 
> b/drivers/gpu/drm/bridge/parade-ps8640.c
> new file mode 100644
> index ..ab896ceb1a42
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/parade-ps8640.c
> @@ -0,0 +1,655 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + */
> +
> +#include 
> +#include 
> +//#include 

Commented stuff should gone.

> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +//#include 

Ditto.

> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define PAGE1_VSTART 0x6b
> +#define PAGE2_SPI_CFG3   0x82
> 

Re: [PATCH v12 1/7] dt-bindings: sun6i-dsi: Document A64 MIPI-DSI controller

2019-12-16 Thread Jagan Teki
On Mon, Dec 16, 2019 at 4:50 PM Maxime Ripard  wrote:
>
> On Mon, Dec 16, 2019 at 04:37:20PM +0530, Jagan Teki wrote:
> > On Wed, Dec 4, 2019 at 7:06 PM Maxime Ripard  wrote:
> > >
> > > On Tue, Dec 03, 2019 at 07:18:10PM +0530, Jagan Teki wrote:
> > > > The MIPI DSI controller in Allwinner A64 is similar to A33.
> > > >
> > > > But unlike A33, A64 doesn't have DSI_SCLK gating so it is valid
> > > > to have separate compatible for A64 on the same driver.
> > > >
> > > > DSI_SCLK uses mod clock-names on dt-bindings, so the same
> > > > is not required for A64.
> > > >
> > > > On that note
> > > > - A64 require minimum of 1 clock like the bus clock
> > > > - A33 require minimum of 2 clocks like both bus, mod clocks
> > > >
> > > > So, update dt-bindings so-that it can document both A33,
> > > > A64 bindings requirements.
> > > >
> > > > Reviewed-by: Rob Herring 
> > > > Signed-off-by: Jagan Teki 
> > > > ---
> > > > Changes for v12:
> > > > - Use 'enum' instead of oneOf+const
> > > >
> > > >  .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 20 +--
> > > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git 
> > > > a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > >  
> > > > b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > index dafc0980c4fa..b91446475f35 100644
> > > > --- 
> > > > a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > +++ 
> > > > b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
> > > > @@ -15,7 +15,9 @@ properties:
> > > >"#size-cells": true
> > > >
> > > >compatible:
> > > > -const: allwinner,sun6i-a31-mipi-dsi
> > > > +enum:
> > > > +  - allwinner,sun6i-a31-mipi-dsi
> > > > +  - allwinner,sun50i-a64-mipi-dsi
> > > >
> > > >reg:
> > > >  maxItems: 1
> > > > @@ -24,6 +26,8 @@ properties:
> > > >  maxItems: 1
> > > >
> > > >clocks:
> > > > +minItems: 1
> > > > +maxItems: 2
> > > >  items:
> > > >- description: Bus Clock
> > > >- description: Module Clock
> > > > @@ -63,13 +67,25 @@ required:
> > > >- reg
> > > >- interrupts
> > > >- clocks
> > > > -  - clock-names
> > > >- phys
> > > >- phy-names
> > > >- resets
> > > >- vcc-dsi-supply
> > > >- port
> > > >
> > > > +allOf:
> > > > +  - if:
> > > > +  properties:
> > > > + compatible:
> > > > +   contains:
> > > > + const: allwinner,sun6i-a31-mipi-dsi
> > > > +  then:
> > > > +properties:
> > > > +  clocks:
> > > > +minItems: 2
> > > > +required:
> > > > +  - clock-names
> > > > +
> > >
> > > Your else condition should check that the number of clocks items is 1
> > > on the A64
> >
> > But the minItems mentioned as 1 in clocks, which is unchanged number
> > by default. doesn't it sufficient?
>
> In the main schema, it's said that the clocks property can have one or
> two elements (to cover the A31 case that has one, and the A64 case
> that has 2).
>
> This is fine.
>
> Later on, you enforce that the A64 has two elements, and this is fine
> too.

Actually A31 case has 2 and A64 case has 1.

>
> However, you never check that on the A31 you only have one clock, and
> you could very well have two and no one would notice.

I did check A31 case for 2 but not in A64. this is what you mean? so
adding A64 check like below would fine?

allOf:
  - if:
  properties:
 compatible:
   contains:
 const: allwinner,sun6i-a31-mipi-dsi
  then:
properties:
  clocks:
minItems: 2
required:
  - clock-names
  - if:
  properties:
 compatible:
   contains:
 const: allwinner,sun50i-a64-mipi-dsi
  then:
properties:
  clocks:
minItems: 1
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH libdrm] intel: sync i915_pciids.h with kernel

2019-12-16 Thread Souza, Jose
On Thu, 2019-12-12 at 09:17 -0800, Matt Roper wrote:
> On Tue, Dec 10, 2019 at 12:06:11PM -0800, José Roberto de Souza
> wrote:
> > It is missing the new EHL/JSL PCI ids added in commit
> > 651cc835d5f6 ("drm/i915: Add new EHL/JSL PCI ids")
> > 
> > Cc: James Ausmus 
> > Cc: Matt Roper 
> > Signed-off-by: José Roberto de Souza 
> 
> Matches the kernel and the bspec.
> 
> Reviewed-by: Matt Roper 

Thanks for the review.

I just requested libdrm commit access in the mean time could someone
push this?

Thanks

> 
> > ---
> >  intel/i915_pciids.h | 7 +--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > diff --git a/intel/i915_pciids.h b/intel/i915_pciids.h
> > index b1f66b11..3e26a917 100644
> > --- a/intel/i915_pciids.h
> > +++ b/intel/i915_pciids.h
> > @@ -579,12 +579,15 @@
> > INTEL_VGA_DEVICE(0x8A51, info), \
> > INTEL_VGA_DEVICE(0x8A5D, info)
> >  
> > -/* EHL */
> > +/* EHL/JSL */
> >  #define INTEL_EHL_IDS(info) \
> > INTEL_VGA_DEVICE(0x4500, info), \
> > INTEL_VGA_DEVICE(0x4571, info), \
> > INTEL_VGA_DEVICE(0x4551, info), \
> > -   INTEL_VGA_DEVICE(0x4541, info)
> > +   INTEL_VGA_DEVICE(0x4541, info), \
> > +   INTEL_VGA_DEVICE(0x4E71, info), \
> > +   INTEL_VGA_DEVICE(0x4E61, info), \
> > +   INTEL_VGA_DEVICE(0x4E51, info)
> >  
> >  /* TGL */
> >  #define INTEL_TGL_12_IDS(info) \
> > -- 
> > 2.24.0
> > 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Requesting commit access to libdrm

2019-12-16 Thread Souza, Jose
Hello

I have being contributing to i915 for the past 2 years and part of my
work is update the PCI ids of Intel devices in libdrm.
Being able to push my reviewed patches would be really helpful, please
consider this request.

Thanks
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v2 1/5] drm/amdgpu: reverts commit b01245ff54db66073b104ac9d9fbefb7b264b36d.

2019-12-16 Thread Andrey Grodzovsky

Ping on unreviewed  V2s...

Andrey

On 12/13/19 11:54 AM, Andrey Grodzovsky wrote:

In preparation for doing XGMI reset synchronization using task barrier.

Signed-off-by: Andrey Grodzovsky 
Reviewed-by: Le Ma 
---
  drivers/gpu/drm/amd/amdgpu/amdgpu.h|  2 -
  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 76 +-
  2 files changed, 12 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index a78a363..50bab33 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1001,8 +1001,6 @@ struct amdgpu_device {
  
  	boolpm_sysfs_en;

boolucode_sysfs_en;
-
-   boolin_baco;
  };
  
  static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 7324a5f..1d19edfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -2667,7 +2667,7 @@ static void amdgpu_device_xgmi_reset_func(struct 
work_struct *__work)
if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)
adev->asic_reset_res = (adev->in_baco == false) ?
amdgpu_device_baco_enter(adev->ddev) :
-   amdgpu_device_baco_exit(adev->ddev);
+   qamdgpu_device_baco_exit(adev->ddev);
else
adev->asic_reset_res = amdgpu_asic_reset(adev);
  
@@ -3796,18 +3796,13 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,

return r;
  }
  
-static int amdgpu_do_asic_reset(struct amdgpu_device *adev,

-  struct amdgpu_hive_info *hive,
+static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
   struct list_head *device_list_handle,
   bool *need_full_reset_arg)
  {
struct amdgpu_device *tmp_adev = NULL;
bool need_full_reset = *need_full_reset_arg, vram_lost = false;
int r = 0;
-   int cpu = smp_processor_id();
-   bool use_baco =
-   (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) ?
-   true : false;
  
  	/*

 * ASIC reset has to be done on all HGMI hive nodes ASAP
@@ -3815,62 +3810,22 @@ static int amdgpu_do_asic_reset(struct amdgpu_device 
*adev,
 */
if (need_full_reset) {
list_for_each_entry(tmp_adev, device_list_handle, 
gmc.xgmi.head) {
-   /*
-* For XGMI run all resets in parallel to speed up the
-* process by scheduling the highpri wq on different
-* cpus. For XGMI with baco reset, all nodes must enter
-* baco within close proximity before anyone exit.
-*/
+   /* For XGMI run all resets in parallel to speed up the 
process */
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
-   if (!queue_work_on(cpu, system_highpri_wq,
-  _adev->xgmi_reset_work))
+   if (!queue_work(system_highpri_wq, 
_adev->xgmi_reset_work))
r = -EALREADY;
-   cpu = cpumask_next(cpu, cpu_online_mask);
} else
r = amdgpu_asic_reset(tmp_adev);
-   if (r)
-   break;
-   }
-
-   /* For XGMI wait for all work to complete before proceed */
-   if (!r) {
-   list_for_each_entry(tmp_adev, device_list_handle,
-   gmc.xgmi.head) {
-   if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
-   flush_work(_adev->xgmi_reset_work);
-   r = tmp_adev->asic_reset_res;
-   if (r)
-   break;
-   if (use_baco)
-   tmp_adev->in_baco = true;
-   }
-   }
-   }
  
-		/*

-* For XGMI with baco reset, need exit baco phase by scheduling
-* xgmi_reset_work one more time. PSP reset and sGPU skips this
-* phase. Not assume the situation that PSP reset and baco reset
-* coexist within an XGMI hive.
-*/
-
-   if (!r && use_baco) {
-   cpu = smp_processor_id();
-   

  1   2   3   >