[PATCH v6] backlight: lms283gf05: Convert to GPIO descriptors

2020-08-25 Thread Linus Walleij
This converts the lms283gf05 backlight driver to use GPIO
descriptors and switches the single PXA Palm Z2 device
over to defining these.

Since the platform data was only used to convey GPIO
information we can delete the platform data header.

Notice that we define the proper active low semantics in
the board file GPIO descriptor table (active low) and
assert the reset line by bringing it to "1" (asserted).

Cc: Marek Vasut 
Cc: Daniel Mack 
Cc: Haojian Zhuang 
Cc: Robert Jarzmik 
Reviewed-by: Daniel Thompson 
Signed-off-by: Linus Walleij 
---
ChangeLog v5->v6:
- Rebase onto v5.9-rc1
ChangeLog v4->v5:
- Rebase on v5.8-rc1
- Collected Daniel's Reviewed-by tag.
ChangeLog v3->v4:
- Check IS_ERR() on the returned GPIO descriptor.
- Unconditionally set consumer name since the API tolerates NULL.
ChangeLog v2->v3:
- Fix a use-before-allocated bug discovered by compile tests.
- Remove unused ret variable as autobuilders complained.
ChangeLog v1->v2:
- Bring up the GPIO de-asserted in probe()

Marek: I saw this was written by you, are you regularly
testing the Z2 device?
---
 arch/arm/mach-pxa/z2.c   | 12 +---
 drivers/video/backlight/lms283gf05.c | 43 +++-
 include/linux/spi/lms283gf05.h   | 16 ---
 3 files changed, 25 insertions(+), 46 deletions(-)
 delete mode 100644 include/linux/spi/lms283gf05.h

diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 21fd76bb09cd..89eb5243c85f 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -20,7 +20,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -578,8 +577,13 @@ static struct pxa2xx_spi_chip lms283_chip_info = {
.gpio_cs= GPIO88_ZIPITZ2_LCD_CS,
 };
 
-static const struct lms283gf05_pdata lms283_pdata = {
-   .reset_gpio = GPIO19_ZIPITZ2_LCD_RESET,
+static struct gpiod_lookup_table lms283_gpio_table = {
+   .dev_id = "spi2.0", /* SPI bus 2 chip select 0 */
+   .table = {
+   GPIO_LOOKUP("gpio-pxa", GPIO19_ZIPITZ2_LCD_RESET,
+   "reset", GPIO_ACTIVE_LOW),
+   { },
+   },
 };
 
 static struct spi_board_info spi_board_info[] __initdata = {
@@ -595,7 +599,6 @@ static struct spi_board_info spi_board_info[] __initdata = {
 {
.modalias   = "lms283gf05",
.controller_data= &lms283_chip_info,
-   .platform_data  = &lms283_pdata,
.max_speed_hz   = 40,
.bus_num= 2,
.chip_select= 0,
@@ -615,6 +618,7 @@ static void __init z2_spi_init(void)
 {
pxa2xx_set_spi_info(1, &pxa_ssp1_master_info);
pxa2xx_set_spi_info(2, &pxa_ssp2_master_info);
+   gpiod_add_lookup_table(&lms283_gpio_table);
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 #else
diff --git a/drivers/video/backlight/lms283gf05.c 
b/drivers/video/backlight/lms283gf05.c
index 0e45685bcc1c..36856962ed83 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -9,16 +9,16 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 #include 
-#include 
 #include 
 
 struct lms283gf05_state {
struct spi_device   *spi;
struct lcd_device   *ld;
+   struct gpio_desc*reset;
 };
 
 struct lms283gf05_seq {
@@ -90,13 +90,13 @@ static const struct lms283gf05_seq disp_pdwnseq[] = {
 };
 
 
-static void lms283gf05_reset(unsigned long gpio, bool inverted)
+static void lms283gf05_reset(struct gpio_desc *gpiod)
 {
-   gpio_set_value(gpio, !inverted);
+   gpiod_set_value(gpiod, 0); /* De-asserted */
mdelay(100);
-   gpio_set_value(gpio, inverted);
+   gpiod_set_value(gpiod, 1); /* Asserted */
mdelay(20);
-   gpio_set_value(gpio, !inverted);
+   gpiod_set_value(gpiod, 0); /* De-asserted */
mdelay(20);
 }
 
@@ -125,18 +125,15 @@ static int lms283gf05_power_set(struct lcd_device *ld, 
int power)
 {
struct lms283gf05_state *st = lcd_get_data(ld);
struct spi_device *spi = st->spi;
-   struct lms283gf05_pdata *pdata = dev_get_platdata(&spi->dev);
 
if (power <= FB_BLANK_NORMAL) {
-   if (pdata)
-   lms283gf05_reset(pdata->reset_gpio,
-   pdata->reset_inverted);
+   if (st->reset)
+   lms283gf05_reset(st->reset);
lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq));
} else {
lms283gf05_toggle(spi, disp_pdwnseq, ARRAY_SIZE(disp_pdwnseq));
-   if (pdata)
-   gpio_set_value(pdata->reset_gpio,
-   pdata->reset_inverted);
+   if (st->reset)
+   gpiod_set_value(st->reset, 1); /* Asserted */
}
 
return 0;
@@ -150,24 +147,18 @@ static struct lcd_ops lms_ops = {
 static int lms283gf05

Re: [RFC v4 09/20] drm/i915/dp: Extract drm_dp_has_mst()

2020-08-25 Thread Jani Nikula
On Tue, 25 Aug 2020, Lyude Paul  wrote:
> Just a tiny drive-by cleanup, we can consolidate i915's code for
> checking for MST support into a helper to be shared across drivers.
>
> Signed-off-by: Lyude Paul 
> Reviewed-by: Sean Paul 
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 18 ++
>  include/drm/drm_dp_mst_helper.h | 22 ++
>  2 files changed, 24 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 79c27f91f42c0..1e29d3a012856 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4699,20 +4699,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
>   return true;
>  }
>  
> -static bool
> -intel_dp_sink_can_mst(struct intel_dp *intel_dp)
> -{
> - u8 mstm_cap;
> -
> - if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
> - return false;
> -
> - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_MSTM_CAP, &mstm_cap) != 1)
> - return false;
> -
> - return mstm_cap & DP_MST_CAP;
> -}
> -
>  static bool
>  intel_dp_can_mst(struct intel_dp *intel_dp)
>  {
> @@ -4720,7 +4706,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp)
>  
>   return i915->params.enable_dp_mst &&
>   intel_dp->can_mst &&
> - intel_dp_sink_can_mst(intel_dp);
> + drm_dp_has_mst(&intel_dp->aux, intel_dp->dpcd);
>  }
>  
>  static void
> @@ -4729,7 +4715,7 @@ intel_dp_configure_mst(struct intel_dp *intel_dp)
>   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>   struct intel_encoder *encoder =
>   &dp_to_dig_port(intel_dp)->base;
> - bool sink_can_mst = intel_dp_sink_can_mst(intel_dp);
> + bool sink_can_mst = drm_dp_has_mst(&intel_dp->aux, intel_dp->dpcd);
>  
>   drm_dbg_kms(&i915->drm,
>   "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: 
> %s\n",
> diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
> index 8b9eb4db3381c..2d8983a713e8c 100644
> --- a/include/drm/drm_dp_mst_helper.h
> +++ b/include/drm/drm_dp_mst_helper.h
> @@ -911,4 +911,26 @@ __drm_dp_mst_state_iter_get(struct drm_atomic_state 
> *state,
>   for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
>   for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), 
> NULL, &(new_state), (__i)))
>  
> +/**
> + * drm_dp_has_mst() - check whether or not a sink supports MST
> + * @aux: The DP AUX channel to use
> + * @dpcd: A cached copy of the DPCD capabilities for this sink
> + *
> + * Returns: %True if the sink supports MST, %false otherwise
> + */
> +static inline bool

I've become more and more critical of accumulating a lot of inlines in
headers. Do we really want this in the header?

> +drm_dp_has_mst(struct drm_dp_aux *aux,
> +const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> +{
> + u8 mstm_cap;
> +
> + if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12)
> + return false;
> +
> + if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1)
> + return false;
> +
> + return !!(mstm_cap & DP_MST_CAP);

The !! is superfluous.

BR,
Jani.

> +}
> +
>  #endif

-- 
Jani Nikula, Intel Open Source Graphics Center
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[v3] drm/nouveau: utilize subconnector property for DP

2020-08-25 Thread Jeevan B
From: Oleg Vasilev 

Since DP-specific information is stored in driver's structures, every
driver needs to implement subconnector property by itself.

v2: rebase

v3: renamed a function call

Cc: Ben Skeggs 
Cc: nouv...@lists.freedesktop.org
Signed-off-by: Jeevan B 
Signed-off-by: Oleg Vasilev 
Reviewed-by: Emil Velikov 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 13 +
 drivers/gpu/drm/nouveau/nouveau_dp.c|  9 +
 drivers/gpu/drm/nouveau/nouveau_encoder.h   |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 7674025..955afed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -654,6 +654,17 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
 
+   if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+   connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+   enum drm_mode_subconnector subconnector = 
DRM_MODE_SUBCONNECTOR_Unknown;
+
+   if (conn_status == connector_status_connected && nv_encoder)
+   subconnector = nv_encoder->dp.subconnector;
+   drm_object_property_set_value(&connector->base,
+   connector->dev->mode_config.dp_subconnector_property,
+   subconnector);
+   }
+
return conn_status;
 }
 
@@ -1390,6 +1401,8 @@ nouveau_connector_create(struct drm_device *dev,
kfree(nv_connector);
return ERR_PTR(ret);
}
+
+   drm_connector_attach_dp_subconnector_property(connector);
funcs = &nouveau_connector_funcs;
break;
default:
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 8a0f799..3eff884 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -62,6 +62,7 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nvkm_i2c_aux *aux;
u8 dpcd[8];
+   u8 port_cap[DP_MAX_DOWNSTREAM_PORTS] = {};
int ret;
 
aux = nv_encoder->aux;
@@ -72,6 +73,14 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
if (ret)
return ret;
 
+   if (dpcd[DP_DPCD_REV] > 0x10) {
+   ret = nvkm_rdaux(aux, DP_DOWNSTREAM_PORT_0,
+port_cap, DP_MAX_DOWNSTREAM_PORTS);
+   if (ret)
+   memset(port_cap, 0, DP_MAX_DOWNSTREAM_PORTS);
+   }
+   nv_encoder->dp.subconnector = drm_dp_subconnector_type(dpcd, port_cap);
+
nv_encoder->dp.link_bw = 27000 * dpcd[1];
nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index a72c412..49b5c10 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -64,6 +64,7 @@ struct nouveau_encoder {
struct nv50_mstm *mstm;
int link_nr;
int link_bw;
+   enum drm_mode_subconnector subconnector;
} dp;
};
 
-- 
2.7.4

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


[PATCH v9 31/32] media: pci: fix common ALSA DMA-mapping related codes

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that dma_map_sg returns the
numer of the created entries in the DMA address space. However the
subsequent calls to dma_sync_sg_for_{device,cpu} and dma_unmap_sg must be
called with the original number of entries passed to dma_map_sg. The
sg_table->nents in turn holds the result of the dma_map_sg call as stated
in include/linux/scatterlist.h. Adapt the code to obey those rules.

Signed-off-by: Marek Szyprowski 
---
 drivers/media/pci/cx23885/cx23885-alsa.c | 2 +-
 drivers/media/pci/cx25821/cx25821-alsa.c | 2 +-
 drivers/media/pci/cx88/cx88-alsa.c   | 2 +-
 drivers/media/pci/saa7134/saa7134-alsa.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c 
b/drivers/media/pci/cx23885/cx23885-alsa.c
index df44ed7393a0..3f366e4e4685 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -129,7 +129,7 @@ static int cx23885_alsa_dma_unmap(struct cx23885_audio_dev 
*dev)
if (!buf->sglen)
return 0;
 
-   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, 
PCI_DMA_FROMDEVICE);
+   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->nr_pages, 
PCI_DMA_FROMDEVICE);
buf->sglen = 0;
return 0;
 }
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c 
b/drivers/media/pci/cx25821/cx25821-alsa.c
index 301616426d8a..c40304d33776 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -193,7 +193,7 @@ static int cx25821_alsa_dma_unmap(struct cx25821_audio_dev 
*dev)
if (!buf->sglen)
return 0;
 
-   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, 
PCI_DMA_FROMDEVICE);
+   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->nr_pages, 
PCI_DMA_FROMDEVICE);
buf->sglen = 0;
return 0;
 }
diff --git a/drivers/media/pci/cx88/cx88-alsa.c 
b/drivers/media/pci/cx88/cx88-alsa.c
index 7d7aceecc985..3c6fe6ceb0b7 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -332,7 +332,7 @@ static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev)
if (!buf->sglen)
return 0;
 
-   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen,
+   dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->nr_pages,
 PCI_DMA_FROMDEVICE);
buf->sglen = 0;
return 0;
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c 
b/drivers/media/pci/saa7134/saa7134-alsa.c
index 544ca57eee75..398c47ff473d 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -313,7 +313,7 @@ static int saa7134_alsa_dma_unmap(struct saa7134_dev *dev)
if (!dma->sglen)
return 0;
 
-   dma_unmap_sg(&dev->pci->dev, dma->sglist, dma->sglen, 
PCI_DMA_FROMDEVICE);
+   dma_unmap_sg(&dev->pci->dev, dma->sglist, dma->nr_pages, 
PCI_DMA_FROMDEVICE);
dma->sglen = 0;
return 0;
 }
-- 
2.17.1

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


[PATCH v9 32/32] videobuf2: use sgtable-based scatterlist wrappers

2020-08-25 Thread Marek Szyprowski
Use recently introduced common wrappers operating directly on the struct
sg_table objects and scatterlist page iterators to make the code a bit
more compact, robust, easier to follow and copy/paste safe.

No functional change, because the code already properly did all the
scaterlist related calls.

Signed-off-by: Marek Szyprowski 
---
 .../common/videobuf2/videobuf2-dma-contig.c   | 34 ---
 .../media/common/videobuf2/videobuf2-dma-sg.c | 32 +++--
 .../common/videobuf2/videobuf2-vmalloc.c  | 12 +++
 3 files changed, 31 insertions(+), 47 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c 
b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index ec3446cc45b8..1b242d844dde 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -58,10 +58,10 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
unsigned int i;
unsigned long size = 0;
 
-   for_each_sg(sgt->sgl, s, sgt->nents, i) {
+   for_each_sgtable_dma_sg(sgt, s, i) {
if (sg_dma_address(s) != expected)
break;
-   expected = sg_dma_address(s) + sg_dma_len(s);
+   expected += sg_dma_len(s);
size += sg_dma_len(s);
}
return size;
@@ -103,8 +103,7 @@ static void vb2_dc_prepare(void *buf_priv)
if (!sgt)
return;
 
-   dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
-  buf->dma_dir);
+   dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir);
 }
 
 static void vb2_dc_finish(void *buf_priv)
@@ -115,7 +114,7 @@ static void vb2_dc_finish(void *buf_priv)
if (!sgt)
return;
 
-   dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+   dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir);
 }
 
 /*/
@@ -275,8 +274,8 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
 * memory locations do not require any explicit cache
 * maintenance prior or after being used by the device.
 */
-   dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
-  attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
kfree(attach);
db_attach->priv = NULL;
@@ -301,8 +300,8 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
 
/* release any previous cache */
if (attach->dma_dir != DMA_NONE) {
-   dma_unmap_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
-  attach->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
attach->dma_dir = DMA_NONE;
}
 
@@ -310,9 +309,8 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
 * mapping to the client with new direction, no cache sync
 * required see comment in vb2_dc_dmabuf_ops_detach()
 */
-   sgt->nents = dma_map_sg_attrs(db_attach->dev, sgt->sgl, sgt->orig_nents,
- dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
-   if (!sgt->nents) {
+   if (dma_map_sgtable(db_attach->dev, sgt, dma_dir,
+   DMA_ATTR_SKIP_CPU_SYNC)) {
pr_err("failed to map scatterlist\n");
mutex_unlock(lock);
return ERR_PTR(-EIO);
@@ -455,8 +453,8 @@ static void vb2_dc_put_userptr(void *buf_priv)
 * No need to sync to CPU, it's already synced to the CPU
 * since the finish() memop will have been called before this.
 */
-   dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
-  buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(buf->dev, sgt, buf->dma_dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
pages = frame_vector_pages(buf->vec);
/* sgt should exist only if vector contains pages... */
BUG_ON(IS_ERR(pages));
@@ -553,9 +551,8 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
 * No need to sync to the device, this will happen later when the
 * prepare() memop is called.
 */
-   sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
-   if (sgt->nents <= 0) {
+   if (dma_map_sgtable(buf->dev, sgt, buf->dma_dir,
+   DMA_ATTR_SKIP_CPU_SYNC)) {
pr_err("failed to map scatterlist\n");

[PATCH v9 24/32] drm: host1x: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/host1x/job.c | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 89b6c14b7392..82d0a60ba3f7 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -170,11 +170,9 @@ static unsigned int pin_job(struct host1x *host, struct 
host1x_job *job)
goto unpin;
}
 
-   err = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
-   if (!err) {
-   err = -ENOMEM;
+   err = dma_map_sgtable(dev, sgt, dir, 0);
+   if (err)
goto unpin;
-   }
 
job->unpins[job->num_unpins].dev = dev;
job->unpins[job->num_unpins].dir = dir;
@@ -228,7 +226,7 @@ static unsigned int pin_job(struct host1x *host, struct 
host1x_job *job)
}
 
if (host->domain) {
-   for_each_sg(sgt->sgl, sg, sgt->nents, j)
+   for_each_sgtable_sg(sgt, sg, j)
gather_size += sg->length;
gather_size = iova_align(&host->iova, gather_size);
 
@@ -240,9 +238,9 @@ static unsigned int pin_job(struct host1x *host, struct 
host1x_job *job)
goto put;
}
 
-   err = iommu_map_sg(host->domain,
+   err = iommu_map_sgtable(host->domain,
iova_dma_addr(&host->iova, alloc),
-   sgt->sgl, sgt->nents, IOMMU_READ);
+   sgt, IOMMU_READ);
if (err == 0) {
__free_iova(&host->iova, alloc);
err = -EINVAL;
@@ -252,12 +250,9 @@ static unsigned int pin_job(struct host1x *host, struct 
host1x_job *job)
job->unpins[job->num_unpins].size = gather_size;
phys_addr = iova_dma_addr(&host->iova, alloc);
} else if (sgt) {
-   err = dma_map_sg(host->dev, sgt->sgl, sgt->nents,
-DMA_TO_DEVICE);
-   if (!err) {
-   err = -ENOMEM;
+   err = dma_map_sgtable(host->dev, sgt, DMA_TO_DEVICE, 0);
+   if (err)
goto put;
-   }
 
job->unpins[job->num_unpins].dir = DMA_TO_DEVICE;
job->unpins[job->num_unpins].dev = host->dev;
@@ -660,8 +655,7 @@ void host1x_job_unpin(struct host1x_job *job)
}
 
if (unpin->dev && sgt)
-   dma_unmap_sg(unpin->dev, sgt->sgl, sgt->nents,
-unpin->dir);
+   dma_unmap_sgtable(unpin->dev, sgt, unpin->dir, 0);
 
host1x_bo_unpin(dev, unpin->bo, sgt);
host1x_bo_put(unpin->bo);
-- 
2.17.1

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


[PATCH v9 15/32] drm: panfrost: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Steven Price 
Reviewed-by: Rob Herring 
---
 drivers/gpu/drm/panfrost/panfrost_gem.c | 4 ++--
 drivers/gpu/drm/panfrost/panfrost_mmu.c | 7 +++
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c 
b/drivers/gpu/drm/panfrost/panfrost_gem.c
index 33355dd302f1..1a6cea0e0bd7 100644
--- a/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ b/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -41,8 +41,8 @@ static void panfrost_gem_free_object(struct drm_gem_object 
*obj)
 
for (i = 0; i < n_sgt; i++) {
if (bo->sgts[i].sgl) {
-   dma_unmap_sg(pfdev->dev, bo->sgts[i].sgl,
-bo->sgts[i].nents, 
DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(pfdev->dev, &bo->sgts[i],
+ DMA_BIDIRECTIONAL, 0);
sg_free_table(&bo->sgts[i]);
}
}
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c 
b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index e8f7b11352d2..776448c527ea 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -253,7 +253,7 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct 
panfrost_mmu *mmu,
struct io_pgtable_ops *ops = mmu->pgtbl_ops;
u64 start_iova = iova;
 
-   for_each_sg(sgt->sgl, sgl, sgt->nents, count) {
+   for_each_sgtable_dma_sg(sgt, sgl, count) {
unsigned long paddr = sg_dma_address(sgl);
size_t len = sg_dma_len(sgl);
 
@@ -517,10 +517,9 @@ static int panfrost_mmu_map_fault_addr(struct 
panfrost_device *pfdev, int as,
if (ret)
goto err_pages;
 
-   if (!dma_map_sg(pfdev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL)) {
-   ret = -EINVAL;
+   ret = dma_map_sgtable(pfdev->dev, sgt, DMA_BIDIRECTIONAL, 0);
+   if (ret)
goto err_map;
-   }
 
mmu_map_sg(pfdev, bomapping->mmu, addr,
   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
-- 
2.17.1

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


[PATCH v9 23/32] xen: gntdev: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Acked-by: Juergen Gross 
---
 drivers/xen/gntdev-dmabuf.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index b1b6eebafd5d..4c13cbc99896 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -247,10 +247,9 @@ static void dmabuf_exp_ops_detach(struct dma_buf *dma_buf,
 
if (sgt) {
if (gntdev_dmabuf_attach->dir != DMA_NONE)
-   dma_unmap_sg_attrs(attach->dev, sgt->sgl,
-  sgt->nents,
-  gntdev_dmabuf_attach->dir,
-  DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(attach->dev, sgt,
+ gntdev_dmabuf_attach->dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sgt);
}
 
@@ -288,8 +287,8 @@ dmabuf_exp_ops_map_dma_buf(struct dma_buf_attachment 
*attach,
sgt = dmabuf_pages_to_sgt(gntdev_dmabuf->pages,
  gntdev_dmabuf->nr_pages);
if (!IS_ERR(sgt)) {
-   if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
- DMA_ATTR_SKIP_CPU_SYNC)) {
+   if (dma_map_sgtable(attach->dev, sgt, dir,
+   DMA_ATTR_SKIP_CPU_SYNC)) {
sg_free_table(sgt);
kfree(sgt);
sgt = ERR_PTR(-ENOMEM);
@@ -633,7 +632,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct 
device *dev,
 
/* Now convert sgt to array of pages and check for page validity. */
i = 0;
-   for_each_sg_page(sgt->sgl, &sg_iter, sgt->nents, 0) {
+   for_each_sgtable_page(sgt, &sg_iter, 0) {
struct page *page = sg_page_iter_page(&sg_iter);
/*
 * Check if page is valid: this can happen if we are given
-- 
2.17.1

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


[PATCH v9 13/32] drm: omapdrm: use common helper for extracting pages array

2020-08-25 Thread Marek Szyprowski
Use common helper for converting a sg_table object into struct
page pointer array.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/omapdrm/omap_gem.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
b/drivers/gpu/drm/omapdrm/omap_gem.c
index d0d12d5dd76c..ff0c4b0c3fd0 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1297,10 +1297,9 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct 
drm_device *dev, size_t size,
omap_obj->dma_addr = sg_dma_address(sgt->sgl);
} else {
/* Create pages list from sgt */
-   struct sg_page_iter iter;
struct page **pages;
unsigned int npages;
-   unsigned int i = 0;
+   unsigned int ret;
 
npages = DIV_ROUND_UP(size, PAGE_SIZE);
pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL);
@@ -1311,14 +1310,9 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct 
drm_device *dev, size_t size,
}
 
omap_obj->pages = pages;
-
-   for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) {
-   pages[i++] = sg_page_iter_page(&iter);
-   if (i > npages)
-   break;
-   }
-
-   if (WARN_ON(i != npages)) {
+   ret = drm_prime_sg_to_page_addr_arrays(sgt, pages, NULL,
+  npages);
+   if (WARN_ON(ret)) {
omap_gem_free_object(obj);
obj = ERR_PTR(-ENOMEM);
goto done;
-- 
2.17.1

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


[PATCH v9 11/32] drm: mediatek: use common helper for extracting pages array

2020-08-25 Thread Marek Szyprowski
Use common helper for converting a sg_table object into struct
page pointer array.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/mediatek/mtk_drm_gem.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c 
b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index 3654ec732029..0583e557ad37 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -233,9 +233,7 @@ void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj)
 {
struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
struct sg_table *sgt;
-   struct sg_page_iter iter;
unsigned int npages;
-   unsigned int i = 0;
 
if (mtk_gem->kvaddr)
return mtk_gem->kvaddr;
@@ -249,11 +247,8 @@ void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj)
if (!mtk_gem->pages)
goto out;
 
-   for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) {
-   mtk_gem->pages[i++] = sg_page_iter_page(&iter);
-   if (i > npages)
-   break;
-   }
+   drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages);
+
mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
   pgprot_writecombine(PAGE_KERNEL));
 
-- 
2.17.1

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


[PATCH v9 30/32] samples: vfio-mdev/mbochs: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

While touching this code, also add missing call to dma_unmap_sgtable.

Signed-off-by: Marek Szyprowski 
---
 samples/vfio-mdev/mbochs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 3cc5e5921682..e03068917273 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -846,7 +846,7 @@ static struct sg_table *mbochs_map_dmabuf(struct 
dma_buf_attachment *at,
if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount,
  0, dmabuf->mode.size, GFP_KERNEL) < 0)
goto err2;
-   if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction))
+   if (dma_map_sgtable(at->dev, sg, direction, 0))
goto err3;
 
return sg;
@@ -868,6 +868,7 @@ static void mbochs_unmap_dmabuf(struct dma_buf_attachment 
*at,
 
dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
 
+   dma_unmap_sgtable(at->dev, sg, direction, 0);
sg_free_table(sg);
kfree(sg);
 }
-- 
2.17.1

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


[PATCH v9 29/32] rapidio: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/rapidio/devices/rio_mport_cdev.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c 
b/drivers/rapidio/devices/rio_mport_cdev.c
index a30342942e26..89eb3d212652 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -573,8 +573,7 @@ static void dma_req_free(struct kref *ref)
refcount);
struct mport_cdev_priv *priv = req->priv;
 
-   dma_unmap_sg(req->dmach->device->dev,
-req->sgt.sgl, req->sgt.nents, req->dir);
+   dma_unmap_sgtable(req->dmach->device->dev, &req->sgt, req->dir, 0);
sg_free_table(&req->sgt);
if (req->page_list) {
unpin_user_pages(req->page_list, req->nr_pages);
@@ -814,7 +813,6 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
struct mport_dev *md = priv->md;
struct dma_chan *chan;
int ret;
-   int nents;
 
if (xfer->length == 0)
return -EINVAL;
@@ -930,15 +928,14 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
xfer->offset, xfer->length);
}
 
-   nents = dma_map_sg(chan->device->dev,
-  req->sgt.sgl, req->sgt.nents, dir);
-   if (nents == 0) {
+   ret = dma_map_sgtable(chan->device->dev, &req->sgt, dir, 0);
+   if (ret) {
rmcd_error("Failed to map SG list");
ret = -EFAULT;
goto err_pg;
}
 
-   ret = do_dma_request(req, xfer, sync, nents);
+   ret = do_dma_request(req, xfer, sync, req->sgt.nents);
 
if (ret >= 0) {
if (sync == RIO_TRANSFER_ASYNC)
-- 
2.17.1

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


[PATCH v9 26/32] dmabuf: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Acked-by: Gerd Hoffmann 
---
 drivers/dma-buf/heaps/heap-helpers.c | 13 ++---
 drivers/dma-buf/udmabuf.c|  7 +++
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/dma-buf/heaps/heap-helpers.c 
b/drivers/dma-buf/heaps/heap-helpers.c
index 9f964ca3f59c..d0696cf937af 100644
--- a/drivers/dma-buf/heaps/heap-helpers.c
+++ b/drivers/dma-buf/heaps/heap-helpers.c
@@ -140,13 +140,12 @@ struct sg_table *dma_heap_map_dma_buf(struct 
dma_buf_attachment *attachment,
  enum dma_data_direction direction)
 {
struct dma_heaps_attachment *a = attachment->priv;
-   struct sg_table *table;
-
-   table = &a->table;
+   struct sg_table *table = &a->table;
+   int ret;
 
-   if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
-   direction))
-   table = ERR_PTR(-ENOMEM);
+   ret = dma_map_sgtable(attachment->dev, table, direction, 0);
+   if (ret)
+   table = ERR_PTR(ret);
return table;
 }
 
@@ -154,7 +153,7 @@ static void dma_heap_unmap_dma_buf(struct 
dma_buf_attachment *attachment,
   struct sg_table *table,
   enum dma_data_direction direction)
 {
-   dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
+   dma_unmap_sgtable(attachment->dev, table, direction, 0);
 }
 
 static vm_fault_t dma_heap_vm_fault(struct vm_fault *vmf)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index acb26c627d27..89e293bd9252 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -63,10 +63,9 @@ static struct sg_table *get_sg_table(struct device *dev, 
struct dma_buf *buf,
GFP_KERNEL);
if (ret < 0)
goto err;
-   if (!dma_map_sg(dev, sg->sgl, sg->nents, direction)) {
-   ret = -EINVAL;
+   ret = dma_map_sgtable(dev, sg, direction, 0);
+   if (ret < 0)
goto err;
-   }
return sg;
 
 err:
@@ -78,7 +77,7 @@ static struct sg_table *get_sg_table(struct device *dev, 
struct dma_buf *buf,
 static void put_sg_table(struct device *dev, struct sg_table *sg,
 enum dma_data_direction direction)
 {
-   dma_unmap_sg(dev, sg->sgl, sg->nents, direction);
+   dma_unmap_sgtable(dev, sg, direction, 0);
sg_free_table(sg);
kfree(sg);
 }
-- 
2.17.1

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


[PATCH v9 28/32] misc: fastrpc: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/misc/fastrpc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 7939c55daceb..9d6867749316 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -518,7 +518,7 @@ fastrpc_map_dma_buf(struct dma_buf_attachment *attachment,
 
table = &a->sgt;
 
-   if (!dma_map_sg(attachment->dev, table->sgl, table->nents, dir))
+   if (!dma_map_sgtable(attachment->dev, table, dir, 0))
return ERR_PTR(-ENOMEM);
 
return table;
@@ -528,7 +528,7 @@ static void fastrpc_unmap_dma_buf(struct dma_buf_attachment 
*attach,
  struct sg_table *table,
  enum dma_data_direction dir)
 {
-   dma_unmap_sg(attach->dev, table->sgl, table->nents, dir);
+   dma_unmap_sgtable(attach->dev, table, dir, 0);
 }
 
 static void fastrpc_release(struct dma_buf *dmabuf)
-- 
2.17.1

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


[PATCH v9 00/32] DRM: fix struct sg_table nents vs. orig_nents misuse

2020-08-25 Thread Marek Szyprowski
Dear All,

During the Exynos DRM GEM rework and fixing the issues in the.
drm_prime_sg_to_page_addr_arrays() function [1] I've noticed that most
drivers in DRM framework incorrectly use nents and orig_nents entries of
the struct sg_table.

In case of the most DMA-mapping implementations exchanging those two
entries or using nents for all loops on the scatterlist is harmless,
because they both have the same value. There exists however a DMA-mapping
implementations, for which such incorrect usage breaks things. The nents
returned by dma_map_sg() might be lower than the nents passed as its
parameter and this is perfectly fine. DMA framework or IOMMU is allowed
to join consecutive chunks while mapping if such operation is supported
by the underlying HW (bus, bridge, IOMMU, etc). Example of the case
where dma_map_sg() might return 1 'DMA' chunk for the 4 'physical' pages
is described here [2]

The DMA-mapping framework documentation [3] states that dma_map_sg()
returns the numer of the created entries in the DMA address space.
However the subsequent calls to dma_sync_sg_for_{device,cpu} and
dma_unmap_sg must be called with the original number of entries passed to
dma_map_sg. The common pattern in DRM drivers were to assign the
dma_map_sg() return value to sg_table->nents and use that value for
the subsequent calls to dma_sync_sg_* or dma_unmap_sg functions. Also
the code iterated over nents times to access the pages stored in the
processed scatterlist, while it should use orig_nents as the numer of
the page entries.

I've tried to identify all such incorrect usage of sg_table->nents and
this is a result of my research. It looks that the incorrect pattern has
been copied over the many drivers mainly in the DRM subsystem. Too bad in
most cases it even worked correctly if the system used a simple, linear
DMA-mapping implementation, for which swapping nents and orig_nents
doesn't make any difference. To avoid similar issues in the future, I've
introduced a common wrappers for DMA-mapping calls, which operate directly
on the sg_table objects. I've also added wrappers for iterating over the
scatterlists stored in the sg_table objects and applied them where
possible. This, together with some common DRM prime helpers, allowed me
to almost get rid of all nents/orig_nents usage in the drivers. I hope
that such change makes the code robust, easier to follow and copy/paste
safe.

The biggest TODO is DRM/i915 driver and I don't feel brave enough to fix
it fully. The driver creatively uses sg_table->orig_nents to store the
size of the allocate scatterlist and ignores the number of the entries
returned by dma_map_sg function. In this patchset I only fixed the
sg_table objects exported by dmabuf related functions. I hope that I
didn't break anything there.

Patches are based on top of Linux next-20200825. The required changes to
DMA-mapping framework has been already merged to v5.8-rc1.

I would like ask for merging of the 1-27 patches via DRM misc tree.

Best regards,
Marek Szyprowski


References:

[1] https://lkml.org/lkml/2020/3/27/555
[2] https://lkml.org/lkml/2020/3/29/65
[3] Documentation/DMA-API-HOWTO.txt
[4] 
https://lore.kernel.org/linux-iommu/20200512121931.gd20...@lst.de/T/#ma18c958a48c3b241d5409517fa7d192eef87459b

Changelog:

v9:
- rebased onto Linux next-20200825, which is based on v5.9-rc2; fixed conflicts
- dropped merged patches

v8:
- rapidio: fixed issues pointed by kbuilt test robot (use of uninitialized
variable
- vb2: rebased after recent changes in the code

v7: 
https://lore.kernel.org/linux-iommu/20200619103636.11974-1-m.szyprow...@samsung.com/T/
- changed DMA page interators to standard DMA SG iterators in drm/prime and
  videobuf2-dma-contig as suggested by Robin Murphy
- fixed build issues

v6: 
https://lore.kernel.org/linux-iommu/20200618153956.29558-1-m.szyprow...@samsung.com/T/
- rebased onto Linux next-20200618, which is based on v5.8-rc1; fixed conflicts

v5: 
https://lore.kernel.org/linux-iommu/20200513132114.6046-1-m.szyprow...@samsung.com/T/
- fixed some minor style issues and typos
- fixed lack of the attrs argument in ion, dmabuf, rapidio, fastrpc and
  vfio patches

v4: https://lore.kernel.org/linux-iommu/20200512121931.gd20...@lst.de/T/
- added for_each_sgtable_* wrappers and applied where possible
- added drm_prime_get_contiguous_size() and applied where possible
- applied drm_prime_sg_to_page_addr_arrays() where possible to remove page
  extraction from sg_table objects
- added documentation for the introduced wrappers
- improved patches description a bit

v3: 
https://lore.kernel.org/dri-devel/20200505083926.28503-1-m.szyprow...@samsung.com/
- introduce dma_*_sgtable_* wrappers and use them in all patches

v2: 
https://lore.kernel.org/linux-iommu/c01c9766-9778-fd1f-f36e-2dc7bd376...@arm.com/T/
- dropped most of the changes to drm/i915
- added fixes for rcar-du, xen, media and ion
- fixed a few issues pointed by kb

[PATCH v9 06/32] drm: exynos: use common helper for a scatterlist contiguity check

2020-08-25 Thread Marek Szyprowski
Use common helper for checking the contiguity of the imported dma-buf.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Andrzej Hajda 
Acked-by : Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 23 +++
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index efa476858db5..1716a023bca0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -431,27 +431,10 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device 
*dev,
 {
struct exynos_drm_gem *exynos_gem;
 
-   if (sgt->nents < 1)
+   /* check if the entries in the sg_table are contiguous */
+   if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) {
+   DRM_ERROR("buffer chunks must be mapped contiguously");
return ERR_PTR(-EINVAL);
-
-   /*
-* Check if the provided buffer has been mapped as contiguous
-* into DMA address space.
-*/
-   if (sgt->nents > 1) {
-   dma_addr_t next_addr = sg_dma_address(sgt->sgl);
-   struct scatterlist *s;
-   unsigned int i;
-
-   for_each_sg(sgt->sgl, s, sgt->nents, i) {
-   if (!sg_dma_len(s))
-   break;
-   if (sg_dma_address(s) != next_addr) {
-   DRM_ERROR("buffer chunks must be mapped 
contiguously");
-   return ERR_PTR(-EINVAL);
-   }
-   next_addr = sg_dma_address(s) + sg_dma_len(s);
-   }
}
 
exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size);
-- 
2.17.1

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


[PATCH v9 20/32] drm: virtio: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Acked-by: Gerd Hoffmann 
---
 drivers/gpu/drm/virtio/virtgpu_object.c | 36 ++---
 drivers/gpu/drm/virtio/virtgpu_vq.c | 12 -
 2 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c 
b/drivers/gpu/drm/virtio/virtgpu_object.c
index e83651b7747d..a0559d3ed362 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -72,9 +72,8 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
 
if (shmem->pages) {
if (shmem->mapped) {
-   dma_unmap_sg(vgdev->vdev->dev.parent,
-shmem->pages->sgl, shmem->mapped,
-DMA_TO_DEVICE);
+   dma_unmap_sgtable(vgdev->vdev->dev.parent,
+shmem->pages, DMA_TO_DEVICE, 0);
shmem->mapped = 0;
}
 
@@ -158,13 +157,13 @@ static int virtio_gpu_object_shmem_init(struct 
virtio_gpu_device *vgdev,
}
 
if (use_dma_api) {
-   shmem->mapped = dma_map_sg(vgdev->vdev->dev.parent,
-  shmem->pages->sgl,
-  shmem->pages->nents,
-  DMA_TO_DEVICE);
-   *nents = shmem->mapped;
+   ret = dma_map_sgtable(vgdev->vdev->dev.parent,
+ shmem->pages, DMA_TO_DEVICE, 0);
+   if (ret)
+   return ret;
+   *nents = shmem->mapped = shmem->pages->nents;
} else {
-   *nents = shmem->pages->nents;
+   *nents = shmem->pages->orig_nents;
}
 
*ents = kmalloc_array(*nents, sizeof(struct virtio_gpu_mem_entry),
@@ -174,13 +173,20 @@ static int virtio_gpu_object_shmem_init(struct 
virtio_gpu_device *vgdev,
return -ENOMEM;
}
 
-   for_each_sg(shmem->pages->sgl, sg, *nents, si) {
-   (*ents)[si].addr = cpu_to_le64(use_dma_api
-  ? sg_dma_address(sg)
-  : sg_phys(sg));
-   (*ents)[si].length = cpu_to_le32(sg->length);
-   (*ents)[si].padding = 0;
+   if (use_dma_api) {
+   for_each_sgtable_dma_sg(shmem->pages, sg, si) {
+   (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg));
+   (*ents)[si].length = cpu_to_le32(sg_dma_len(sg));
+   (*ents)[si].padding = 0;
+   }
+   } else {
+   for_each_sgtable_sg(shmem->pages, sg, si) {
+   (*ents)[si].addr = cpu_to_le64(sg_phys(sg));
+   (*ents)[si].length = cpu_to_le32(sg->length);
+   (*ents)[si].padding = 0;
+   }
}
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c 
b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 53af60d484a4..7947b1047bd0 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -302,7 +302,7 @@ static struct sg_table *vmalloc_to_sgt(char *data, uint32_t 
size, int *sg_ents)
return NULL;
}
 
-   for_each_sg(sgt->sgl, sg, *sg_ents, i) {
+   for_each_sgtable_sg(sgt, sg, i) {
pg = vmalloc_to_page(data);
if (!pg) {
sg_free_table(sgt);
@@ -603,9 +603,8 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct 
virtio_gpu_device *vgdev,
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
 
if (use_dma_api)
-  

[PATCH v9 12/32] drm: msm: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Acked-by: Rob Clark 
---
 drivers/gpu/drm/msm/msm_gem.c| 13 +
 drivers/gpu/drm/msm/msm_gpummu.c | 14 ++
 drivers/gpu/drm/msm/msm_iommu.c  |  2 +-
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index b2f49152b4d4..8c7ae812b813 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -53,11 +53,10 @@ static void sync_for_device(struct msm_gem_object *msm_obj)
struct device *dev = msm_obj->base.dev->dev;
 
if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) {
-   dma_sync_sg_for_device(dev, msm_obj->sgt->sgl,
-   msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_sync_sgtable_for_device(dev, msm_obj->sgt,
+   DMA_BIDIRECTIONAL);
} else {
-   dma_map_sg(dev, msm_obj->sgt->sgl,
-   msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_map_sgtable(dev, msm_obj->sgt, DMA_BIDIRECTIONAL, 0);
}
 }
 
@@ -66,11 +65,9 @@ static void sync_for_cpu(struct msm_gem_object *msm_obj)
struct device *dev = msm_obj->base.dev->dev;
 
if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) {
-   dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl,
-   msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_sync_sgtable_for_cpu(dev, msm_obj->sgt, DMA_BIDIRECTIONAL);
} else {
-   dma_unmap_sg(dev, msm_obj->sgt->sgl,
-   msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(dev, msm_obj->sgt, DMA_BIDIRECTIONAL, 0);
}
 }
 
diff --git a/drivers/gpu/drm/msm/msm_gpummu.c b/drivers/gpu/drm/msm/msm_gpummu.c
index 310a31b05faa..319f06c28235 100644
--- a/drivers/gpu/drm/msm/msm_gpummu.c
+++ b/drivers/gpu/drm/msm/msm_gpummu.c
@@ -30,21 +30,19 @@ static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t 
iova,
 {
struct msm_gpummu *gpummu = to_msm_gpummu(mmu);
unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
-   struct scatterlist *sg;
+   struct sg_dma_page_iter dma_iter;
unsigned prot_bits = 0;
-   unsigned i, j;
 
if (prot & IOMMU_WRITE)
prot_bits |= 1;
if (prot & IOMMU_READ)
prot_bits |= 2;
 
-   for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-   dma_addr_t addr = sg->dma_address;
-   for (j = 0; j < sg->length / GPUMMU_PAGE_SIZE; j++, idx++) {
-   gpummu->table[idx] = addr | prot_bits;
-   addr += GPUMMU_PAGE_SIZE;
-   }
+   for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
+   dma_addr_t addr = sg_page_iter_dma_address(&dma_iter);
+
+   BUILD_BUG_ON(GPUMMU_PAGE_SIZE != PAGE_SIZE);
+   gpummu->table[idx++] = addr | prot_bits;
}
 
/* we can improve by deferring flush for multiple map() */
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 3a381a9674c9..6c31e65834c6 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -36,7 +36,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
struct msm_iommu *iommu = to_msm_iommu(mmu);
size_t ret;
 
-   ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
+   ret = iommu_map_sgtable(iommu->domain, iova, sgt, prot);
WARN_ON(!ret);
 
return (ret == len) ? 0 : -EINVAL;
-- 
2.17.1

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


[PATCH v9 18/32] drm: tegra: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/tegra/gem.c   | 27 ++-
 drivers/gpu/drm/tegra/plane.c | 15 +--
 2 files changed, 15 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 723df142a981..01d94befab11 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -98,8 +98,8 @@ static struct sg_table *tegra_bo_pin(struct device *dev, 
struct host1x_bo *bo,
 * the SG table needs to be copied to avoid overwriting any
 * other potential users of the original SG table.
 */
-   err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, 
obj->sgt->nents,
-GFP_KERNEL);
+   err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl,
+obj->sgt->orig_nents, GFP_KERNEL);
if (err < 0)
goto free;
} else {
@@ -196,8 +196,7 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, 
struct tegra_bo *bo)
 
bo->iova = bo->mm->start;
 
-   bo->size = iommu_map_sg(tegra->domain, bo->iova, bo->sgt->sgl,
-   bo->sgt->nents, prot);
+   bo->size = iommu_map_sgtable(tegra->domain, bo->iova, bo->sgt, prot);
if (!bo->size) {
dev_err(tegra->drm->dev, "failed to map buffer\n");
err = -ENOMEM;
@@ -264,8 +263,7 @@ static struct tegra_bo *tegra_bo_alloc_object(struct 
drm_device *drm,
 static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo)
 {
if (bo->pages) {
-   dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
-DMA_FROM_DEVICE);
+   dma_unmap_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0);
drm_gem_put_pages(&bo->gem, bo->pages, true, true);
sg_free_table(bo->sgt);
kfree(bo->sgt);
@@ -290,12 +288,9 @@ static int tegra_bo_get_pages(struct drm_device *drm, 
struct tegra_bo *bo)
goto put_pages;
}
 
-   err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents,
-DMA_FROM_DEVICE);
-   if (err == 0) {
-   err = -EFAULT;
+   err = dma_map_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0);
+   if (err)
goto free_sgt;
-   }
 
return 0;
 
@@ -571,7 +566,7 @@ tegra_gem_prime_map_dma_buf(struct dma_buf_attachment 
*attach,
goto free;
}
 
-   if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
+   if (dma_map_sgtable(attach->dev, sgt, dir, 0))
goto free;
 
return sgt;
@@ -590,7 +585,7 @@ static void tegra_gem_prime_unmap_dma_buf(struct 
dma_buf_attachment *attach,
struct tegra_bo *bo = to_tegra_bo(gem);
 
if (bo->pages)
-   dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+   dma_unmap_sgtable(attach->dev, sgt, dir, 0);
 
sg_free_table(sgt);
kfree(sgt);
@@ -609,8 +604,7 @@ static int tegra_gem_prime_begin_cpu_access(struct dma_buf 
*buf,
struct drm_device *drm = gem->dev;
 
if (bo->pages)
-   dma_sync_sg_for_cpu(drm->dev, bo->sgt->sgl, bo->sgt->nents,
-   DMA_FROM_DEVICE);
+   dma_sync_sgtable_for_cpu(drm->dev, bo->sgt, DMA_FROM_DEVICE);
 
return 0;
 }
@@ -623,8 +617,7 @@ static int tegra_gem_prime_end_cpu_access(struct dma_buf 
*buf,
struct drm_device *drm = gem->dev;
 
if (bo->pages)
-   dma_sync_sg_for_device(drm->dev, bo->sgt->sgl, bo->sgt->nents,
-  DMA_TO_DEVICE);
+   dma_sync_sgtable_for_device(drm->dev, bo

[PATCH v9 22/32] drm: xen: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

Fix the code to refer to proper nents or orig_nents entries. This driver
reports the number of the pages in the imported scatterlist, so it should
refer to sg_table->orig_nents entry.

Signed-off-by: Marek Szyprowski 
Acked-by: Oleksandr Andrushchenko 
---
 drivers/gpu/drm/xen/xen_drm_front_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c 
b/drivers/gpu/drm/xen/xen_drm_front_gem.c
index 39ff95b75357..0e57c80058b2 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_gem.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c
@@ -216,7 +216,7 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret);
 
DRM_DEBUG("Imported buffer of size %zu with nents %u\n",
- size, sgt->nents);
+ size, sgt->orig_nents);
 
return &xen_obj->base;
 }
-- 
2.17.1

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


[PATCH v9 03/32] drm: core: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Andrzej Hajda 
---
 drivers/gpu/drm/drm_cache.c|  2 +-
 drivers/gpu/drm/drm_gem_shmem_helper.c | 14 +-
 drivers/gpu/drm/drm_prime.c| 11 ++-
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 03e01b000f7a..0fe3c496002a 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -127,7 +127,7 @@ drm_clflush_sg(struct sg_table *st)
struct sg_page_iter sg_iter;
 
mb(); /*CLFLUSH is ordered only by using memory barriers*/
-   for_each_sg_page(st->sgl, &sg_iter, st->nents, 0)
+   for_each_sgtable_page(st, &sg_iter, 0)
drm_clflush_page(sg_page_iter_page(&sg_iter));
mb(); /*Make sure that all cache line entry is flushed*/
 
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 4b7cfbac4daa..47d8211221f2 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -126,8 +126,8 @@ void drm_gem_shmem_free_object(struct drm_gem_object *obj)
drm_prime_gem_destroy(obj, shmem->sgt);
} else {
if (shmem->sgt) {
-   dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl,
-shmem->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(obj->dev->dev, shmem->sgt,
+ DMA_BIDIRECTIONAL, 0);
sg_free_table(shmem->sgt);
kfree(shmem->sgt);
}
@@ -424,8 +424,7 @@ void drm_gem_shmem_purge_locked(struct drm_gem_object *obj)
 
WARN_ON(!drm_gem_shmem_is_purgeable(shmem));
 
-   dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl,
-shmem->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(obj->dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
sg_free_table(shmem->sgt);
kfree(shmem->sgt);
shmem->sgt = NULL;
@@ -697,12 +696,17 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct 
drm_gem_object *obj)
goto err_put_pages;
}
/* Map the pages for use by the h/w. */
-   dma_map_sg(obj->dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+   ret = dma_map_sgtable(obj->dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
+   if (ret)
+   goto err_free_sgt;
 
shmem->sgt = sgt;
 
return sgt;
 
+err_free_sgt:
+   sg_free_table(sgt);
+   kfree(sgt);
 err_put_pages:
drm_gem_shmem_put_pages(shmem);
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 5d181bf60a44..c45b0cc6e31d 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -617,6 +617,7 @@ struct sg_table *drm_gem_map_dma_buf(struct 
dma_buf_attachment *attach,
 {
struct drm_gem_object *obj = attach->dmabuf->priv;
struct sg_table *sgt;
+   int ret;
 
if (WARN_ON(dir == DMA_NONE))
return ERR_PTR(-EINVAL);
@@ -626,11 +627,12 @@ struct sg_table *drm_gem_map_dma_buf(struct 
dma_buf_attachment *attach,
else
sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
 
-   if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
- DMA_ATTR_SKIP_CPU_SYNC)) {
+   ret = dma_map_sgtable(attach->dev, sgt, dir,
+ DMA_ATTR_SKIP_CPU_SYNC);
+   if (ret) {
sg_free_table(sgt);
kfree(sgt);
-   sgt = ERR_PTR(-ENOMEM);
+   sgt = ERR_PTR(ret);
}
 
return sgt;
@@ -652,8 +654,7 @@ void drm_gem_unmap_dma_buf(struct

[PATCH v9 02/32] drm: prime: use sgtable iterators in drm_prime_sg_to_page_addr_arrays()

2020-08-25 Thread Marek Szyprowski
Replace the current hand-crafted code for extracting pages and DMA
addresses from the given scatterlist by the much more robust
code based on the generic scatterlist iterators and recently
introduced sg_table-based wrappers. The resulting code is simple and
easy to understand, so the comment describing the old code is no
longer needed.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Andrzej Hajda 
---
 drivers/gpu/drm/drm_prime.c | 49 -
 1 file changed, 15 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 4ed5ed1f078c..5d181bf60a44 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -990,45 +990,26 @@ EXPORT_SYMBOL(drm_gem_prime_import);
 int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
 dma_addr_t *addrs, int max_entries)
 {
-   unsigned count;
-   struct scatterlist *sg;
-   struct page *page;
-   u32 page_len, page_index;
-   dma_addr_t addr;
-   u32 dma_len, dma_index;
-
-   /*
-* Scatterlist elements contains both pages and DMA addresses, but
-* one shoud not assume 1:1 relation between them. The sg->length is
-* the size of the physical memory chunk described by the sg->page,
-* while sg_dma_len(sg) is the size of the DMA (IO virtual) chunk
-* described by the sg_dma_address(sg).
-*/
-   page_index = 0;
-   dma_index = 0;
-   for_each_sg(sgt->sgl, sg, sgt->nents, count) {
-   page_len = sg->length;
-   page = sg_page(sg);
-   dma_len = sg_dma_len(sg);
-   addr = sg_dma_address(sg);
-
-   while (pages && page_len > 0) {
-   if (WARN_ON(page_index >= max_entries))
+   struct sg_dma_page_iter dma_iter;
+   struct sg_page_iter page_iter;
+   struct page **p = pages;
+   dma_addr_t *a = addrs;
+
+   if (pages) {
+   for_each_sgtable_page(sgt, &page_iter, 0) {
+   if (p - pages >= max_entries)
return -1;
-   pages[page_index] = page;
-   page++;
-   page_len -= PAGE_SIZE;
-   page_index++;
+   *p++ = sg_page_iter_page(&page_iter);
}
-   while (addrs && dma_len > 0) {
-   if (WARN_ON(dma_index >= max_entries))
+   }
+   if (addrs) {
+   for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
+   if (a - addrs >= max_entries)
return -1;
-   addrs[dma_index] = addr;
-   addr += PAGE_SIZE;
-   dma_len -= PAGE_SIZE;
-   dma_index++;
+   *a++ = sg_page_iter_dma_address(&dma_iter);
}
}
+
return 0;
 }
 EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
-- 
2.17.1

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


[PATCH v9 25/32] drm: rcar-du: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

dma_map_sgtable() function returns zero or an error code, so adjust the
return value check for the vsp1_du_map_sg() function.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Laurent Pinchart 
---
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  | 3 +--
 drivers/media/platform/vsp1/vsp1_drm.c | 8 
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c 
b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index f1a81c9b184d..a27bff999649 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -197,9 +197,8 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct 
drm_framebuffer *fb,
goto fail;
 
ret = vsp1_du_map_sg(vsp->vsp, sgt);
-   if (!ret) {
+   if (ret) {
sg_free_table(sgt);
-   ret = -ENOMEM;
goto fail;
}
}
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c 
b/drivers/media/platform/vsp1/vsp1_drm.c
index a4a45d68a6ef..86d5e3f4b1ff 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -912,8 +912,8 @@ int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt)
 * skip cache sync. This will need to be revisited when support for
 * non-coherent buffers will be added to the DU driver.
 */
-   return dma_map_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents,
-   DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+   return dma_map_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE,
+  DMA_ATTR_SKIP_CPU_SYNC);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_map_sg);
 
@@ -921,8 +921,8 @@ void vsp1_du_unmap_sg(struct device *dev, struct sg_table 
*sgt)
 {
struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 
-   dma_unmap_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents,
-  DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg);
 
-- 
2.17.1

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


[PATCH v9 14/32] drm: omapdrm: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

Fix the code to refer to proper nents or orig_nents entries. This driver
checks for a buffer contiguity in DMA address space, so it should test
sg_table->nents entry.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/omapdrm/omap_gem.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
b/drivers/gpu/drm/omapdrm/omap_gem.c
index ff0c4b0c3fd0..a7a9a0afe2b6 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -48,7 +48,7 @@ struct omap_gem_object {
 *   OMAP_BO_MEM_DMA_API flag set)
 *
 * - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set)
-*   if they are physically contiguous (when sgt->orig_nents == 1)
+*   if they are physically contiguous (when sgt->nents == 1)
 *
 * - buffers mapped through the TILER when dma_addr_cnt is not zero, in
 *   which case the DMA address points to the TILER aperture
@@ -1279,7 +1279,7 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct 
drm_device *dev, size_t size,
union omap_gem_size gsize;
 
/* Without a DMM only physically contiguous buffers can be supported. */
-   if (sgt->orig_nents != 1 && !priv->has_dmm)
+   if (sgt->nents != 1 && !priv->has_dmm)
return ERR_PTR(-EINVAL);
 
gsize.bytes = PAGE_ALIGN(size);
@@ -1293,7 +1293,7 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct 
drm_device *dev, size_t size,
 
omap_obj->sgt = sgt;
 
-   if (sgt->orig_nents == 1) {
+   if (sgt->nents == 1) {
omap_obj->dma_addr = sg_dma_address(sgt->sgl);
} else {
/* Create pages list from sgt */
-- 
2.17.1

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


[PATCH v9 08/32] drm: i915: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

This driver creatively uses sg_table->orig_nents to store the size of the
allocated scatterlist and ignores the number of the entries returned by
dma_map_sg function. The sg_table->orig_nents is (mis)used to properly
free the (over)allocated scatterlist.

This patch only introduces the common DMA-mapping wrappers operating
directly on the struct sg_table objects to the dmabuf related functions,
so the other drivers, which might share buffers with i915 could rely on
the properly set nents and orig_nents values.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c   | 11 +++
 drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c |  7 +++
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c 
b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 2679380159fc..8a988592715b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -48,12 +48,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct 
dma_buf_attachment *attachme
src = sg_next(src);
}
 
-   if (!dma_map_sg_attrs(attachment->dev,
- st->sgl, st->nents, dir,
- DMA_ATTR_SKIP_CPU_SYNC)) {
-   ret = -ENOMEM;
+   ret = dma_map_sgtable(attachment->dev, st, dir, DMA_ATTR_SKIP_CPU_SYNC);
+   if (ret)
goto err_free_sg;
-   }
 
return st;
 
@@ -73,9 +70,7 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment 
*attachment,
 {
struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
 
-   dma_unmap_sg_attrs(attachment->dev,
-  sg->sgl, sg->nents, dir,
-  DMA_ATTR_SKIP_CPU_SYNC);
+   dma_unmap_sgtable(attachment->dev, sg, dir, DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sg);
kfree(sg);
 
diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c 
b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
index debaf7b18ab5..be30b27e2926 100644
--- a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
@@ -28,10 +28,9 @@ static struct sg_table *mock_map_dma_buf(struct 
dma_buf_attachment *attachment,
sg = sg_next(sg);
}
 
-   if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
-   err = -ENOMEM;
+   err = dma_map_sgtable(attachment->dev, st, dir, 0);
+   if (err)
goto err_st;
-   }
 
return st;
 
@@ -46,7 +45,7 @@ static void mock_unmap_dma_buf(struct dma_buf_attachment 
*attachment,
   struct sg_table *st,
   enum dma_data_direction dir)
 {
-   dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir);
+   dma_unmap_sgtable(attachment->dev, st, dir, 0);
sg_free_table(st);
kfree(st);
 }
-- 
2.17.1

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


[PATCH v9 19/32] drm: v3d: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Eric Anholt 
---
 drivers/gpu/drm/v3d/v3d_mmu.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c
index 3b81ea28c0bb..5a453532901f 100644
--- a/drivers/gpu/drm/v3d/v3d_mmu.c
+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
@@ -90,18 +90,17 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo)
struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev);
u32 page = bo->node.start;
u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
-   unsigned int count;
-   struct scatterlist *sgl;
+   struct sg_dma_page_iter dma_iter;
 
-   for_each_sg(shmem_obj->sgt->sgl, sgl, shmem_obj->sgt->nents, count) {
-   u32 page_address = sg_dma_address(sgl) >> V3D_MMU_PAGE_SHIFT;
+   for_each_sgtable_dma_page(shmem_obj->sgt, &dma_iter, 0) {
+   dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter);
+   u32 page_address = dma_addr >> V3D_MMU_PAGE_SHIFT;
u32 pte = page_prot | page_address;
u32 i;
 
-   BUG_ON(page_address + (sg_dma_len(sgl) >> V3D_MMU_PAGE_SHIFT) >=
+   BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >=
   BIT(24));
-
-   for (i = 0; i < sg_dma_len(sgl) >> V3D_MMU_PAGE_SHIFT; i++)
+   for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++)
v3d->pt[page++] = pte + i;
}
 
-- 
2.17.1

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


[PATCH v9 07/32] drm: exynos: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Andrzej Hajda 
Acked-by : Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 03be31427181..967a5cdc120e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -395,8 +395,8 @@ static void g2d_userptr_put_dma_addr(struct g2d_data *g2d,
return;
 
 out:
-   dma_unmap_sg(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt->sgl,
-   g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt,
+ DMA_BIDIRECTIONAL, 0);
 
pages = frame_vector_pages(g2d_userptr->vec);
if (!IS_ERR(pages)) {
@@ -511,10 +511,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
g2d_data *g2d,
 
g2d_userptr->sgt = sgt;
 
-   if (!dma_map_sg(to_dma_dev(g2d->drm_dev), sgt->sgl, sgt->nents,
-   DMA_BIDIRECTIONAL)) {
+   ret = dma_map_sgtable(to_dma_dev(g2d->drm_dev), sgt,
+ DMA_BIDIRECTIONAL, 0);
+   if (ret) {
DRM_DEV_ERROR(g2d->dev, "failed to map sgt with dma region.\n");
-   ret = -ENOMEM;
goto err_sg_free_table;
}
 
-- 
2.17.1

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


[PATCH v9 10/32] drm: mediatek: use common helper for a scatterlist contiguity check

2020-08-25 Thread Marek Szyprowski
Use common helper for checking the contiguity of the imported dma-buf and
do this check before allocating resources, so the error path is simpler.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/mediatek/mtk_drm_gem.c | 28 ++
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c 
b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index 6190cc3b7b0d..3654ec732029 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -212,37 +212,21 @@ struct drm_gem_object 
*mtk_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg)
 {
struct mtk_drm_gem_obj *mtk_gem;
-   int ret;
-   struct scatterlist *s;
-   unsigned int i;
-   dma_addr_t expected;
 
-   mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size);
+   /* check if the entries in the sg_table are contiguous */
+   if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) {
+   DRM_ERROR("sg_table is not contiguous");
+   return ERR_PTR(-EINVAL);
+   }
 
+   mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size);
if (IS_ERR(mtk_gem))
return ERR_CAST(mtk_gem);
 
-   expected = sg_dma_address(sg->sgl);
-   for_each_sg(sg->sgl, s, sg->nents, i) {
-   if (!sg_dma_len(s))
-   break;
-
-   if (sg_dma_address(s) != expected) {
-   DRM_ERROR("sg_table is not contiguous");
-   ret = -EINVAL;
-   goto err_gem_free;
-   }
-   expected = sg_dma_address(s) + sg_dma_len(s);
-   }
-
mtk_gem->dma_addr = sg_dma_address(sg->sgl);
mtk_gem->sg = sg;
 
return &mtk_gem->base;
-
-err_gem_free:
-   kfree(mtk_gem);
-   return ERR_PTR(ret);
 }
 
 void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj)
-- 
2.17.1

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


[PATCH v9 05/32] drm: etnaviv: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/etnaviv/etnaviv_gem.c | 12 +---
 drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 13 +++--
 2 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c 
b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index f06e19e7be04..eaf1949bc2e4 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -27,7 +27,7 @@ static void etnaviv_gem_scatter_map(struct etnaviv_gem_object 
*etnaviv_obj)
 * because display controller, GPU, etc. are not coherent.
 */
if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
-   dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+   dma_map_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
 }
 
 static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object 
*etnaviv_obj)
@@ -51,7 +51,7 @@ static void etnaviv_gem_scatterlist_unmap(struct 
etnaviv_gem_object *etnaviv_obj
 * discard those writes.
 */
if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
-   dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
 }
 
 /* called with etnaviv_obj->lock held */
@@ -404,9 +404,8 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
}
 
if (etnaviv_obj->flags & ETNA_BO_CACHED) {
-   dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl,
-   etnaviv_obj->sgt->nents,
-   etnaviv_op_to_dma_dir(op));
+   dma_sync_sgtable_for_cpu(dev->dev, etnaviv_obj->sgt,
+etnaviv_op_to_dma_dir(op));
etnaviv_obj->last_cpu_prep_op = op;
}
 
@@ -421,8 +420,7 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
if (etnaviv_obj->flags & ETNA_BO_CACHED) {
/* fini without a prep is almost certainly a userspace error */
WARN_ON(etnaviv_obj->last_cpu_prep_op == 0);
-   dma_sync_sg_for_device(dev->dev, etnaviv_obj->sgt->sgl,
-   etnaviv_obj->sgt->nents,
+   dma_sync_sgtable_for_device(dev->dev, etnaviv_obj->sgt,
etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op));
etnaviv_obj->last_cpu_prep_op = 0;
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c 
b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 3607d348c298..13b100553a0b 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -79,7 +79,7 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context 
*context, u32 iova,
if (!context || !sgt)
return -EINVAL;
 
-   for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+   for_each_sgtable_dma_sg(sgt, sg, i) {
u32 pa = sg_dma_address(sg) - sg->offset;
size_t bytes = sg_dma_len(sg) + sg->offset;
 
@@ -95,14 +95,7 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context 
*context, u32 iova,
return 0;
 
 fail:
-   da = iova;
-
-   for_each_sg(sgt->sgl, sg, i, j) {
-   size_t bytes = sg_dma_len(sg) + sg->offset;
-
-   etnaviv_context_unmap(context, da, bytes);
-   da += bytes;
-   }
+   etnaviv_context_unmap(context, iova, da - iova);
return ret;
 }
 
@@ -113,7 +106,7 @@ static void etnaviv_iommu_unmap(struct 
etnaviv_iommu_context *context, u32 iova,
unsigned int da = iova;
int i;
 
-   for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+   for_each_sgtable_dma_sg(sgt, sg, i) {
size_t bytes = sg_dma_len(sg) + sg->offset;
 
etnaviv_context_unmap(context, da, bytes);
-- 
2.17.1


[PATCH v9 04/32] drm: armada: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/armada/armada_gem.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_gem.c 
b/drivers/gpu/drm/armada/armada_gem.c
index 8005614d2e6b..bedd8937d8a1 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -395,7 +395,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment 
*attach,
 
mapping = dobj->obj.filp->f_mapping;
 
-   for_each_sg(sgt->sgl, sg, count, i) {
+   for_each_sgtable_sg(sgt, sg, i) {
struct page *page;
 
page = shmem_read_mapping_page(mapping, i);
@@ -407,8 +407,8 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment 
*attach,
sg_set_page(sg, page, PAGE_SIZE, 0);
}
 
-   if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) {
-   num = sgt->nents;
+   if (dma_map_sgtable(attach->dev, sgt, dir, 0)) {
+   num = count;
goto release;
}
} else if (dobj->page) {
@@ -418,7 +418,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment 
*attach,
 
sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0);
 
-   if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
+   if (dma_map_sgtable(attach->dev, sgt, dir, 0))
goto free_table;
} else if (dobj->linear) {
/* Single contiguous physical region - no struct page */
@@ -449,11 +449,11 @@ static void armada_gem_prime_unmap_dma_buf(struct 
dma_buf_attachment *attach,
int i;
 
if (!dobj->linear)
-   dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+   dma_unmap_sgtable(attach->dev, sgt, dir, 0);
 
if (dobj->obj.filp) {
struct scatterlist *sg;
-   for_each_sg(sgt->sgl, sg, sgt->nents, i)
+   for_each_sgtable_sg(sgt, sg, i)
put_page(sg_page(sg));
}
 
-- 
2.17.1

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


[PATCH v9 16/32] drm: rockchip: use common helper for a scatterlist contiguity check

2020-08-25 Thread Marek Szyprowski
Use common helper for checking the contiguity of the imported dma-buf.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 19 +--
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index b9275ba7c5a5..2970e534e2bb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -460,23 +460,6 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct 
drm_gem_object *obj)
return sgt;
 }
 
-static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt,
-int count)
-{
-   struct scatterlist *s;
-   dma_addr_t expected = sg_dma_address(sgt->sgl);
-   unsigned int i;
-   unsigned long size = 0;
-
-   for_each_sg(sgt->sgl, s, count, i) {
-   if (sg_dma_address(s) != expected)
-   break;
-   expected = sg_dma_address(s) + sg_dma_len(s);
-   size += sg_dma_len(s);
-   }
-   return size;
-}
-
 static int
 rockchip_gem_iommu_map_sg(struct drm_device *drm,
  struct dma_buf_attachment *attach,
@@ -498,7 +481,7 @@ rockchip_gem_dma_map_sg(struct drm_device *drm,
if (!count)
return -EINVAL;
 
-   if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) {
+   if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) {
DRM_ERROR("failed to map sg_table to contiguous linear 
address.\n");
dma_unmap_sg(drm->dev, sg->sgl, sg->nents,
 DMA_BIDIRECTIONAL);
-- 
2.17.1

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


[PATCH v9 21/32] drm: vmwgfx: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Acked-by: Roland Scheidegger 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
index ab524ab3b0b4..f2f2bff1eedf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
@@ -362,8 +362,7 @@ static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt 
*vmw_tt)
 {
struct device *dev = vmw_tt->dev_priv->dev->dev;
 
-   dma_unmap_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.nents,
-   DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(dev, &vmw_tt->sgt, DMA_BIDIRECTIONAL, 0);
vmw_tt->sgt.nents = vmw_tt->sgt.orig_nents;
 }
 
@@ -383,16 +382,8 @@ static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt 
*vmw_tt)
 static int vmw_ttm_map_for_dma(struct vmw_ttm_tt *vmw_tt)
 {
struct device *dev = vmw_tt->dev_priv->dev->dev;
-   int ret;
-
-   ret = dma_map_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.orig_nents,
-DMA_BIDIRECTIONAL);
-   if (unlikely(ret == 0))
-   return -ENOMEM;
 
-   vmw_tt->sgt.nents = ret;
-
-   return 0;
+   return dma_map_sgtable(dev, &vmw_tt->sgt, DMA_BIDIRECTIONAL, 0);
 }
 
 /**
@@ -449,10 +440,10 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
if (unlikely(ret != 0))
goto out_sg_alloc_fail;
 
-   if (vsgt->num_pages > vmw_tt->sgt.nents) {
+   if (vsgt->num_pages > vmw_tt->sgt.orig_nents) {
uint64_t over_alloc =
sgl_size * (vsgt->num_pages -
-   vmw_tt->sgt.nents);
+   vmw_tt->sgt.orig_nents);
 
ttm_mem_global_free(glob, over_alloc);
vmw_tt->sg_alloc_size -= over_alloc;
-- 
2.17.1

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


[PATCH v9 17/32] drm: rockchip: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
---
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 23 +
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 2970e534e2bb..cb50f2ba2e46 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -36,8 +36,8 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object 
*rk_obj)
 
rk_obj->dma_addr = rk_obj->mm.start;
 
-   ret = iommu_map_sg(private->domain, rk_obj->dma_addr, rk_obj->sgt->sgl,
-  rk_obj->sgt->nents, prot);
+   ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt,
+   prot);
if (ret < rk_obj->base.size) {
DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n",
  ret, rk_obj->base.size);
@@ -98,11 +98,10 @@ static int rockchip_gem_get_pages(struct 
rockchip_gem_object *rk_obj)
 * TODO: Replace this by drm_clflush_sg() once it can be implemented
 * without relying on symbols that are not exported.
 */
-   for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i)
+   for_each_sgtable_sg(rk_obj->sgt, s, i)
sg_dma_address(s) = sg_phys(s);
 
-   dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents,
-  DMA_TO_DEVICE);
+   dma_sync_sgtable_for_device(drm->dev, rk_obj->sgt, DMA_TO_DEVICE);
 
return 0;
 
@@ -350,8 +349,8 @@ void rockchip_gem_free_object(struct drm_gem_object *obj)
if (private->domain) {
rockchip_gem_iommu_unmap(rk_obj);
} else {
-   dma_unmap_sg(drm->dev, rk_obj->sgt->sgl,
-rk_obj->sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(drm->dev, rk_obj->sgt,
+ DMA_BIDIRECTIONAL, 0);
}
drm_prime_gem_destroy(obj, rk_obj->sgt);
} else {
@@ -476,15 +475,13 @@ rockchip_gem_dma_map_sg(struct drm_device *drm,
struct sg_table *sg,
struct rockchip_gem_object *rk_obj)
 {
-   int count = dma_map_sg(drm->dev, sg->sgl, sg->nents,
-  DMA_BIDIRECTIONAL);
-   if (!count)
-   return -EINVAL;
+   int err = dma_map_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0);
+   if (err)
+   return err;
 
if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) {
DRM_ERROR("failed to map sg_table to contiguous linear 
address.\n");
-   dma_unmap_sg(drm->dev, sg->sgl, sg->nents,
-DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0);
return -EINVAL;
}
 
-- 
2.17.1

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


[PATCH v9 27/32] staging: tegra-vde: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Dmitry Osipenko 
---
 drivers/staging/media/tegra-vde/iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/tegra-vde/iommu.c 
b/drivers/staging/media/tegra-vde/iommu.c
index 6af863d92123..adf8dc7ee25c 100644
--- a/drivers/staging/media/tegra-vde/iommu.c
+++ b/drivers/staging/media/tegra-vde/iommu.c
@@ -36,8 +36,8 @@ int tegra_vde_iommu_map(struct tegra_vde *vde,
 
addr = iova_dma_addr(&vde->iova, iova);
 
-   size = iommu_map_sg(vde->domain, addr, sgt->sgl, sgt->nents,
-   IOMMU_READ | IOMMU_WRITE);
+   size = iommu_map_sgtable(vde->domain, addr, sgt,
+IOMMU_READ | IOMMU_WRITE);
if (!size) {
__free_iova(&vde->iova, iova);
return -ENXIO;
-- 
2.17.1

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


[PATCH v9 01/32] drm: prime: add common helper to check scatterlist contiguity

2020-08-25 Thread Marek Szyprowski
It is a common operation done by DRM drivers to check the contiguity
of the DMA-mapped buffer described by a scatterlist in the
sg_table object. Let's add a common helper for this operation.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Andrzej Hajda 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 23 +++--
 drivers/gpu/drm/drm_prime.c  | 31 
 include/drm/drm_prime.h  |  2 ++
 3 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index 822edeadbab3..59b9ca207b42 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -471,26 +471,9 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
 {
struct drm_gem_cma_object *cma_obj;
 
-   if (sgt->nents != 1) {
-   /* check if the entries in the sg_table are contiguous */
-   dma_addr_t next_addr = sg_dma_address(sgt->sgl);
-   struct scatterlist *s;
-   unsigned int i;
-
-   for_each_sg(sgt->sgl, s, sgt->nents, i) {
-   /*
-* sg_dma_address(s) is only valid for entries
-* that have sg_dma_len(s) != 0
-*/
-   if (!sg_dma_len(s))
-   continue;
-
-   if (sg_dma_address(s) != next_addr)
-   return ERR_PTR(-EINVAL);
-
-   next_addr = sg_dma_address(s) + sg_dma_len(s);
-   }
-   }
+   /* check if the entries in the sg_table are contiguous */
+   if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size)
+   return ERR_PTR(-EINVAL);
 
/* Create a CMA GEM buffer. */
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 1693aa7c14b5..4ed5ed1f078c 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -825,6 +825,37 @@ struct sg_table *drm_prime_pages_to_sg(struct page 
**pages, unsigned int nr_page
 }
 EXPORT_SYMBOL(drm_prime_pages_to_sg);
 
+/**
+ * drm_prime_get_contiguous_size - returns the contiguous size of the buffer
+ * @sgt: sg_table describing the buffer to check
+ *
+ * This helper calculates the contiguous size in the DMA address space
+ * of the the buffer described by the provided sg_table.
+ *
+ * This is useful for implementing
+ * &drm_gem_object_funcs.gem_prime_import_sg_table.
+ */
+unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt)
+{
+   dma_addr_t expected = sg_dma_address(sgt->sgl);
+   struct scatterlist *sg;
+   unsigned long size = 0;
+   int i;
+
+   for_each_sgtable_dma_sg(sgt, sg, i) {
+   unsigned int len = sg_dma_len(sg);
+
+   if (!len)
+   break;
+   if (sg_dma_address(sg) != expected)
+   break;
+   expected += len;
+   size += len;
+   }
+   return size;
+}
+EXPORT_SYMBOL(drm_prime_get_contiguous_size);
+
 /**
  * drm_gem_prime_export - helper library implementation of the export callback
  * @obj: GEM object to export
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
index 9af7422b44cf..47ef11614627 100644
--- a/include/drm/drm_prime.h
+++ b/include/drm/drm_prime.h
@@ -92,6 +92,8 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, 
unsigned int nr_page
 struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
 int flags);
 
+unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt);
+
 /* helper functions for importing */
 struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
struct dma_buf *dma_buf,
-- 
2.17.1

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


[PATCH v9 09/32] drm: lima: fix common struct sg_table related issues

2020-08-25 Thread Marek Szyprowski
The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function
returns the number of the created entries in the DMA address space.
However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and
dma_unmap_sg must be called with the original number of the entries
passed to the dma_map_sg().

struct sg_table is a common structure used for describing a non-contiguous
memory buffer, used commonly in the DRM and graphics subsystems. It
consists of a scatterlist with memory pages and DMA addresses (sgl entry),
as well as the number of scatterlist entries: CPU pages (orig_nents entry)
and DMA mapped pages (nents entry).

It turned out that it was a common mistake to misuse nents and orig_nents
entries, calling DMA-mapping functions with a wrong number of entries or
ignoring the number of mapped entries returned by the dma_map_sg()
function.

To avoid such issues, lets use a common dma-mapping wrappers operating
directly on the struct sg_table objects and use scatterlist page
iterators where possible. This, almost always, hides references to the
nents and orig_nents entries, making the code robust, easier to follow
and copy/paste safe.

Signed-off-by: Marek Szyprowski 
Reviewed-by: Qiang Yu 
---
 drivers/gpu/drm/lima/lima_gem.c | 11 ---
 drivers/gpu/drm/lima/lima_vm.c  |  5 ++---
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
index 155f2b4b4030..11223fe348df 100644
--- a/drivers/gpu/drm/lima/lima_gem.c
+++ b/drivers/gpu/drm/lima/lima_gem.c
@@ -69,8 +69,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
return ret;
 
if (bo->base.sgt) {
-   dma_unmap_sg(dev, bo->base.sgt->sgl,
-bo->base.sgt->nents, DMA_BIDIRECTIONAL);
+   dma_unmap_sgtable(dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
sg_free_table(bo->base.sgt);
} else {
bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
@@ -80,7 +79,13 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
}
}
 
-   dma_map_sg(dev, sgt.sgl, sgt.nents, DMA_BIDIRECTIONAL);
+   ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
+   if (ret) {
+   sg_free_table(&sgt);
+   kfree(bo->base.sgt);
+   bo->base.sgt = NULL;
+   return ret;
+   }
 
*bo->base.sgt = sgt;
 
diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c
index 5b92fb82674a..2b2739adc7f5 100644
--- a/drivers/gpu/drm/lima/lima_vm.c
+++ b/drivers/gpu/drm/lima/lima_vm.c
@@ -124,7 +124,7 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, 
bool create)
if (err)
goto err_out1;
 
-   for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter, bo->base.sgt->nents, 
0) {
+   for_each_sgtable_dma_page(bo->base.sgt, &sg_iter, 0) {
err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter),
   bo_va->node.start + offset);
if (err)
@@ -298,8 +298,7 @@ int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, 
int pageoff)
mutex_lock(&vm->lock);
 
base = bo_va->node.start + (pageoff << PAGE_SHIFT);
-   for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter,
-bo->base.sgt->nents, pageoff) {
+   for_each_sgtable_dma_page(bo->base.sgt, &sg_iter, pageoff) {
err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter),
   base + offset);
if (err)
-- 
2.17.1

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


Re: [PATCH 11/23] drm/gem_vram/ttm: move to driver backend destroy function.

2020-08-25 Thread Thomas Zimmermann
Hi

Am 26.08.20 um 03:44 schrieb Dave Airlie:
> From: Dave Airlie 
> 
> Signed-off-by: Dave Airlie 
> ---
>  drivers/gpu/drm/drm_gem_vram_helper.c | 7 +--
>  1 file changed, 1 insertion(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c 
> b/drivers/gpu/drm/drm_gem_vram_helper.c
> index 788557bc5c01..93586a310971 100644
> --- a/drivers/gpu/drm/drm_gem_vram_helper.c
> +++ b/drivers/gpu/drm/drm_gem_vram_helper.c
> @@ -973,10 +973,6 @@ static void backend_func_destroy(struct ttm_bo_device 
> *bdev, struct ttm_tt *tt)
>   kfree(tt);
>  }
>  
> -static struct ttm_backend_func backend_func = {
> - .destroy = backend_func_destroy
> -};
> -
>  /*
>   * TTM BO device
>   */
> @@ -991,8 +987,6 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct 
> ttm_buffer_object *bo,
>   if (!tt)
>   return NULL;
>  
> - tt->func = &backend_func;
> -
>   ret = ttm_tt_init(tt, bo, page_flags);
>   if (ret < 0)
>   goto err_ttm_tt_init;
> @@ -1055,6 +1049,7 @@ static int bo_driver_io_mem_reserve(struct 
> ttm_bo_device *bdev,
>  
>  static struct ttm_bo_driver bo_driver = {
>   .ttm_tt_create = bo_driver_ttm_tt_create,
> + .ttm_tt_destroy = backend_func_destroy,

Please rename backend_func_destroy to bo_driver_ttm_tt_destroy. With
this change

Acked-by: Thomas Zimmermann 

Best regards
Thomas

>   .eviction_valuable = ttm_bo_eviction_valuable,
>   .evict_flags = bo_driver_evict_flags,
>   .move_notify = bo_driver_move_notify,
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer



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


[PATCH 23/23] drm/ttm: change ordering of args to map/unmap helpers.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

These tooks the same args in a different order to the dma
ones, just make things look nicer.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ++--
 drivers/gpu/drm/nouveau/nouveau_bo.c| 4 ++--
 drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++--
 drivers/gpu/drm/ttm/ttm_page_alloc.c| 8 +---
 include/drm/ttm/ttm_page_alloc.h| 8 +---
 5 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 9eb243ff2ba6..c03093828112 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1339,7 +1339,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
 
/* fall back to generic helper to populate the page array
 * and map them to the device */
-   return ttm_populate_and_map_pages(adev->dev, >t->ttm, ctx);
+   return ttm_populate_and_map_pages(>t->ttm, adev->dev, ctx);
 }
 
 /**
@@ -1382,7 +1382,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_bo_device 
*bdev, struct ttm_tt *
 #endif
 
/* fall back to generic helper to unmap and unpopulate array */
-   ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm);
+   ttm_unmap_and_unpopulate_pages(>t->ttm, adev->dev);
 }
 
 /**
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 644f15412dce..9988c7572e77 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1294,7 +1294,7 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
return ttm_dma_populate((void *)ttm, dev, ctx);
}
 #endif
-   return ttm_populate_and_map_pages(dev, ttm_dma, ctx);
+   return ttm_populate_and_map_pages(ttm_dma, dev, ctx);
 }
 
 static void
@@ -1326,7 +1326,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev,
}
 #endif
 
-   ttm_unmap_and_unpopulate_pages(dev, ttm_dma);
+   ttm_unmap_and_unpopulate_pages(ttm_dma, dev);
 }
 
 static void
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index c9f7fc112a84..8e3f3da08bff 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -644,7 +644,7 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device 
*bdev,
}
 #endif
 
-   return ttm_populate_and_map_pages(rdev->dev, >t->ttm, ctx);
+   return ttm_populate_and_map_pages(>t->ttm, rdev->dev, ctx);
 }
 
 static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt 
*ttm)
@@ -676,7 +676,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_bo_device 
*bdev, struct ttm_tt *
}
 #endif
 
-   ttm_unmap_and_unpopulate_pages(rdev->dev, >t->ttm);
+   ttm_unmap_and_unpopulate_pages(>t->ttm, rdev->dev);
 }
 
 int radeon_ttm_tt_set_userptr(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 028ba94d7824..726ea4893a20 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -1094,8 +1094,9 @@ void ttm_pool_unpopulate(struct ttm_tt *ttm)
 }
 EXPORT_SYMBOL(ttm_pool_unpopulate);
 
-int ttm_populate_and_map_pages(struct device *dev, struct ttm_dma_tt *tt,
-   struct ttm_operation_ctx *ctx)
+int ttm_populate_and_map_pages(struct ttm_dma_tt *tt,
+  struct device *dev,
+  struct ttm_operation_ctx *ctx)
 {
unsigned i, j;
int r;
@@ -1137,7 +1138,8 @@ int ttm_populate_and_map_pages(struct device *dev, struct 
ttm_dma_tt *tt,
 }
 EXPORT_SYMBOL(ttm_populate_and_map_pages);
 
-void ttm_unmap_and_unpopulate_pages(struct device *dev, struct ttm_dma_tt *tt)
+void ttm_unmap_and_unpopulate_pages(struct ttm_dma_tt *tt,
+   struct device *dev)
 {
unsigned i, j;
 
diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h
index a6b6ef5f9bf4..b786ce75920b 100644
--- a/include/drm/ttm/ttm_page_alloc.h
+++ b/include/drm/ttm/ttm_page_alloc.h
@@ -61,13 +61,15 @@ void ttm_pool_unpopulate(struct ttm_tt *ttm);
 /**
  * Populates and DMA maps pages to fullfil a ttm_dma_populate() request
  */
-int ttm_populate_and_map_pages(struct device *dev, struct ttm_dma_tt *tt,
-   struct ttm_operation_ctx *ctx);
+int ttm_populate_and_map_pages(struct ttm_dma_tt *tt,
+  struct device *dev,
+  struct ttm_operation_ctx *ctx);
 
 /**
  * Unpopulates and DMA unmaps pages as part of a
  * ttm_dma_unpopulate() request */
-void ttm_unmap_and_unpopulate_pages(struct device *dev, struct ttm_dma_tt *tt);
+void ttm_unmap_and_unpopulate_pages(struct ttm_dma_tt *tt,
+   struct device *dev);
 
 /**
  * Output the state of pools to debugfs file
-- 
2.27.0

___

[00/23] ttm tt refactoring.

2020-08-25 Thread Dave Airlie
This is based on top of misc-next with Christians io rework for nouveau.

https://github.com/airlied/linux/tree/ttm-tt-cleanup (is a complete tree)

The idea is to move towards ttm_tt being just a backing store for system
allocated pages + dma info, and not be anything to do with a global TT.

First is a couple of minor cleanups, then drops bdev from ttm_tt,
and moves the func table into the bdev driver table instead, makes
drivers deal with the agp differences, then cleans up the mess.

It tries to cleanup ttm_tt a bit more as well, in the end ttm_tt
is getting to what I'd like it to represent, the next step is tackling
the whole bind/unbind/move stuff I think.

Dave.


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


[PATCH 05/23] drm/qxl: move bind/unbind/destroy to the driver function table.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/qxl/qxl_ttm.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
index c3530c6e46bd..4970c3450e88 100644
--- a/drivers/gpu/drm/qxl/qxl_ttm.c
+++ b/drivers/gpu/drm/qxl/qxl_ttm.c
@@ -134,12 +134,6 @@ static void qxl_ttm_backend_destroy(struct ttm_bo_device 
*bdev,
kfree(gtt);
 }
 
-static struct ttm_backend_func qxl_backend_func = {
-   .bind = &qxl_ttm_backend_bind,
-   .unbind = &qxl_ttm_backend_unbind,
-   .destroy = &qxl_ttm_backend_destroy,
-};
-
 static struct ttm_tt *qxl_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
 {
@@ -150,7 +144,6 @@ static struct ttm_tt *qxl_ttm_tt_create(struct 
ttm_buffer_object *bo,
gtt = kzalloc(sizeof(struct qxl_ttm_tt), GFP_KERNEL);
if (gtt == NULL)
return NULL;
-   gtt->ttm.func = &qxl_backend_func;
gtt->qdev = qdev;
if (ttm_tt_init(>t->ttm, bo, page_flags)) {
kfree(gtt);
@@ -195,6 +188,9 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo,
 
 static struct ttm_bo_driver qxl_bo_driver = {
.ttm_tt_create = &qxl_ttm_tt_create,
+   .ttm_tt_bind = &qxl_ttm_backend_bind,
+   .ttm_tt_destroy = &qxl_ttm_backend_destroy,
+   .ttm_tt_unbind = &qxl_ttm_backend_unbind,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = &qxl_evict_flags,
.move = &qxl_bo_move,
-- 
2.27.0

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


[PATCH 21/23] drm/ttm: store populated status in upper page flag bits.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 include/drm/ttm/ttm_tt.h | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 2aa4cd7d6451..3b87ce43864a 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -42,6 +42,8 @@ struct ttm_operation_ctx;
 #define TTM_PAGE_FLAG_SG  (1 << 8)
 #define TTM_PAGE_FLAG_NO_RETRY   (1 << 9)
 
+#define TTM_PAGE_FLAG_PRIV_POPULATED  (1 << 31)
+
 enum ttm_caching_state {
tt_uncached,
tt_wc,
@@ -69,17 +71,19 @@ struct ttm_tt {
unsigned long num_pages;
struct file *swap_storage;
enum ttm_caching_state caching_state;
-   bool _populated;
 };
 
 static inline bool ttm_tt_is_populated(struct ttm_tt *tt)
 {
-   return tt->_populated;
+   return tt->page_flags & TTM_PAGE_FLAG_PRIV_POPULATED;
 }
 
 static inline void ttm_tt_set_populated(struct ttm_tt *tt, bool flag)
 {
-   tt->_populated = flag;
+   if (flag)
+   tt->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED;
+   else
+   tt->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED;
 }
 
 /**
-- 
2.27.0

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


[PATCH 13/23] drm/ttm: get rid of agp specific populate/unpopulate paths.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/nouveau/nouveau_bo.c  |  4 ++--
 drivers/gpu/drm/radeon/radeon_ttm.c   |  4 ++--
 drivers/gpu/drm/ttm/ttm_agp_backend.c | 17 -
 include/drm/ttm/ttm_tt.h  |  2 --
 4 files changed, 4 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index f16401feb965..08499e1a56c2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1280,7 +1280,7 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
 
 #if IS_ENABLED(CONFIG_AGP)
if (drm->agp.bridge) {
-   return ttm_agp_tt_populate(bdev, ttm, ctx);
+   return ttm_pool_populate(ttm, ctx);
}
 #endif
 
@@ -1309,7 +1309,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev,
 
 #if IS_ENABLED(CONFIG_AGP)
if (drm->agp.bridge) {
-   ttm_agp_tt_unpopulate(bdev, ttm);
+   ttm_pool_unpopulate(ttm);
return;
}
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index af5479ea154c..eacfc591bf79 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -628,7 +628,7 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device 
*bdev,
 
 #if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
-   return ttm_agp_tt_populate(bdev, ttm, ctx);
+   return ttm_pool_populate(ttm, ctx);
}
 #endif
 
@@ -658,7 +658,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_bo_device 
*bdev, struct ttm_tt *
 
 #if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
-   ttm_agp_tt_unpopulate(bdev, ttm);
+   ttm_pool_unpopulate(ttm);
return;
}
 #endif
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c 
b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index 8072fb7c5bc8..3d0a5e9f4c5f 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -133,20 +133,3 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object 
*bo,
return &agp_be->ttm;
 }
 EXPORT_SYMBOL(ttm_agp_tt_create);
-
-int ttm_agp_tt_populate(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
-{
-   if (ttm->state != tt_unpopulated)
-   return 0;
-
-   return ttm_pool_populate(ttm, ctx);
-}
-EXPORT_SYMBOL(ttm_agp_tt_populate);
-
-void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev,
-  struct ttm_tt *ttm)
-{
-   ttm_pool_unpopulate(ttm);
-}
-EXPORT_SYMBOL(ttm_agp_tt_unpopulate);
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 5a34f1640865..591d4927d501 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -264,8 +264,6 @@ void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm);
 struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo,
 struct agp_bridge_data *bridge,
 uint32_t page_flags);
-int ttm_agp_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_operation_ctx *ctx);
-void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm);
 int ttm_agp_bind(struct ttm_bo_device *bdev,
 struct ttm_tt *ttm, struct ttm_resource *bo_mem);
 void ttm_agp_unbind(struct ttm_bo_device *bdev,
-- 
2.27.0

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


[PATCH 17/23] drm/ttm: split populated/bound state flags.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Get bound out is the next step.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c|  4 ++--
 drivers/gpu/drm/nouveau/nouveau_bo.c   |  4 ++--
 drivers/gpu/drm/radeon/radeon_mn.c |  2 +-
 drivers/gpu/drm/radeon/radeon_ttm.c|  4 ++--
 drivers/gpu/drm/ttm/ttm_bo_util.c  |  2 +-
 drivers/gpu/drm/ttm/ttm_page_alloc.c   |  6 +++---
 drivers/gpu/drm/ttm/ttm_page_alloc_dma.c   |  6 +++---
 drivers/gpu/drm/ttm/ttm_tt.c   | 19 +--
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c |  2 +-
 include/drm/ttm/ttm_tt.h   | 10 --
 11 files changed, 30 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index adac24625191..c1c3691c3b9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1301,7 +1301,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
return -ENOMEM;
 
ttm->page_flags |= TTM_PAGE_FLAG_SG;
-   ttm->state = tt_unbound;
+   ttm->populated = true;
return 0;
}
 
@@ -1321,7 +1321,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address,
 ttm->num_pages);
-   ttm->state = tt_unbound;
+   ttm->populated = true;
return 0;
}
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 478e498da965..e9de922ae921 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1264,14 +1264,14 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
struct device *dev;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
 
-   if (ttm->state != tt_unpopulated)
+   if (ttm->populated)
return 0;
 
if (slave && ttm_dma->sg) {
/* make userspace faulting work */
drm_prime_sg_to_page_addr_arrays(ttm_dma->sg, ttm->pages,
 ttm_dma->dma_address, 
ttm->num_pages);
-   ttm->state = tt_unbound;
+   ttm->populated = true;
return 0;
}
 
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c 
b/drivers/gpu/drm/radeon/radeon_mn.c
index f93829f08a4d..5f57df7e6f08 100644
--- a/drivers/gpu/drm/radeon/radeon_mn.c
+++ b/drivers/gpu/drm/radeon/radeon_mn.c
@@ -53,7 +53,7 @@ static bool radeon_mn_invalidate(struct mmu_interval_notifier 
*mn,
struct ttm_operation_ctx ctx = { false, false };
long r;
 
-   if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
+   if (!bo->tbo.ttm || bo->tbo.ttm->bound == false)
return true;
 
if (!mmu_notifier_range_blockable(range))
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index f5cbe5d13d33..f9e4e64a6d64 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -615,14 +615,14 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device 
*bdev,
return -ENOMEM;
 
ttm->page_flags |= TTM_PAGE_FLAG_SG;
-   ttm->state = tt_unbound;
+   ttm->populated = true;
return 0;
}
 
if (slave && gtt->ttm.sg) {
drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address, 
ttm->num_pages);
-   ttm->state = tt_unbound;
+   ttm->populated = true;
return 0;
}
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 3b17fe3cb57a..d5d841270e38 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -251,7 +251,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 * Don't move nonexistent data. Clear destination instead.
 */
if (old_iomap == NULL &&
-   (ttm == NULL || (ttm->state == tt_unpopulated &&
+   (ttm == NULL || (!ttm->populated &&
 !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED {
memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
goto out2;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index b40a4678c296..2d30a2deadb5 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -1044,7 +1044,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned 
mem_count_update)
 put_pages:
ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,

[PATCH 20/23] drm/ttm: add populated accessors

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

next step move populated into upper page flag bits

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c|  4 ++--
 drivers/gpu/drm/nouveau/nouveau_bo.c   |  4 ++--
 drivers/gpu/drm/radeon/radeon_ttm.c|  4 ++--
 drivers/gpu/drm/ttm/ttm_bo_util.c  |  2 +-
 drivers/gpu/drm/ttm/ttm_page_alloc.c   |  6 +++---
 drivers/gpu/drm/ttm/ttm_page_alloc_dma.c   |  6 +++---
 drivers/gpu/drm/ttm/ttm_tt.c   | 10 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  4 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c |  2 +-
 include/drm/ttm/ttm_tt.h   | 12 +++-
 10 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index e8a56e64bc38..9eb243ff2ba6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1307,7 +1307,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
return -ENOMEM;
 
ttm->page_flags |= TTM_PAGE_FLAG_SG;
-   ttm->populated = true;
+   ttm_tt_set_populated(ttm, true);
return 0;
}
 
@@ -1327,7 +1327,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address,
 ttm->num_pages);
-   ttm->populated = true;
+   ttm_tt_set_populated(ttm, true);
return 0;
}
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index f6b6ef7a8868..644f15412dce 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1269,14 +1269,14 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
struct device *dev;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
 
-   if (ttm->populated)
+   if (ttm_tt_is_populated(ttm))
return 0;
 
if (slave && ttm_dma->sg) {
/* make userspace faulting work */
drm_prime_sg_to_page_addr_arrays(ttm_dma->sg, ttm->pages,
 ttm_dma->dma_address, 
ttm->num_pages);
-   ttm->populated = true;
+   ttm_tt_set_populated(ttm, true);
return 0;
}
 
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index 6f64f949c202..c9f7fc112a84 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -621,14 +621,14 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device 
*bdev,
return -ENOMEM;
 
ttm->page_flags |= TTM_PAGE_FLAG_SG;
-   ttm->populated = true;
+   ttm_tt_set_populated(ttm, true);
return 0;
}
 
if (slave && gtt->ttm.sg) {
drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address, 
ttm->num_pages);
-   ttm->populated = true;
+   ttm_tt_set_populated(ttm, true);
return 0;
}
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index c6262fda1fb8..33146953141a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -257,7 +257,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 * Don't move nonexistent data. Clear destination instead.
 */
if (old_iomap == NULL &&
-   (ttm == NULL || (!ttm->populated &&
+   (ttm == NULL || (!ttm_tt_is_populated(ttm) &&
 !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED {
memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
goto out2;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c 
b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 2d30a2deadb5..028ba94d7824 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -1044,7 +1044,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned 
mem_count_update)
 put_pages:
ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags,
  ttm->caching_state);
-   ttm->populated = false;
+   ttm_tt_set_populated(ttm, false);
 }
 
 int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
@@ -1053,7 +1053,7 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct 
ttm_operation_ctx *ctx)
unsigned i;
int ret;
 
-   if (ttm->populated)
+   if (ttm_tt_is_populated(ttm))
return 0;
 
if (ttm_check_under_lowerlimit(mem_glob, ttm->num_pages, ctx))
@@ -1083,7 +1083,7 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct 
ttm_o

[PATCH 15/23] drm/ttm: drop the tt backend function paths.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

These are now driver side.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/ttm/ttm_tt.c | 15 +++---
 include/drm/ttm/ttm_tt.h | 39 
 2 files changed, 3 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 73c97dcfa512..67aa7fe39432 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -222,10 +222,7 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm)
fput(ttm->swap_storage);
 
ttm->swap_storage = NULL;
-   if (bdev->driver->ttm_tt_destroy)
-   bdev->driver->ttm_tt_destroy(bdev, ttm);
-   else
-   ttm->func->destroy(bdev, ttm);
+   bdev->driver->ttm_tt_destroy(bdev, ttm);
 }
 
 static void ttm_tt_init_fields(struct ttm_tt *ttm,
@@ -313,10 +310,7 @@ EXPORT_SYMBOL(ttm_dma_tt_fini);
 void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
 {
if (ttm->state == tt_bound) {
-   if (bdev->driver->ttm_tt_unbind)
-   bdev->driver->ttm_tt_unbind(bdev, ttm);
-   else
-   ttm->func->unbind(bdev, ttm);
+   bdev->driver->ttm_tt_unbind(bdev, ttm);
ttm->state = tt_unbound;
}
 }
@@ -337,10 +331,7 @@ int ttm_tt_bind(struct ttm_bo_device *bdev,
if (ret)
return ret;
 
-   if (bdev->driver->ttm_tt_bind)
-   ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem);
-   else
-   ret = ttm->func->bind(bdev, ttm, bo_mem);
+   ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem);
if (unlikely(ret != 0))
return ret;
 
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index bdc8aadf3246..146544ba1c10 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -48,47 +48,9 @@ enum ttm_caching_state {
tt_cached
 };
 
-struct ttm_backend_func {
-   /**
-* struct ttm_backend_func member bind
-*
-* @ttm: Pointer to a struct ttm_tt.
-* @bo_mem: Pointer to a struct ttm_resource describing the
-* memory type and location for binding.
-*
-* Bind the backend pages into the aperture in the location
-* indicated by @bo_mem. This function should be able to handle
-* differences between aperture and system page sizes.
-*/
-   int (*bind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_resource *bo_mem);
-
-   /**
-* struct ttm_backend_func member unbind
-*
-* @ttm: Pointer to a struct ttm_tt.
-*
-* Unbind previously bound backend pages. This function should be
-* able to handle differences between aperture and system page sizes.
-*/
-   void (*unbind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm);
-
-   /**
-* struct ttm_backend_func member destroy
-*
-* @ttm: Pointer to a struct ttm_tt.
-*
-* Destroy the backend. This will be call back from ttm_tt_destroy so
-* don't call ttm_tt_destroy from the callback or infinite loop.
-*/
-   void (*destroy) (struct ttm_bo_device *bdev, struct ttm_tt *ttm);
-};
-
 /**
  * struct ttm_tt
  *
- * @func: Pointer to a struct ttm_backend_func that describes
- * the backend methods.
- * pointer.
  * @pages: Array of pages backing the data.
  * @num_pages: Number of pages in the page array.
  * @bdev: Pointer to the current struct ttm_bo_device.
@@ -102,7 +64,6 @@ struct ttm_backend_func {
  * memory.
  */
 struct ttm_tt {
-   struct ttm_backend_func *func;
struct page **pages;
uint32_t page_flags;
unsigned long num_pages;
-- 
2.27.0

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


[PATCH 02/23] drm/radeon/ttm: don't store driver copy of device pointer.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

This can be gotten back from bdev.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/radeon/radeon_ttm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index f6311f404db8..0923a8601112 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -412,7 +412,6 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device 
*bdev, struct ttm_reso
  */
 struct radeon_ttm_tt {
struct ttm_dma_tt   ttm;
-   struct radeon_device*rdev;
u64 offset;
 
uint64_tuserptr;
@@ -515,6 +514,7 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
   struct ttm_resource *bo_mem)
 {
struct radeon_ttm_tt *gtt = (void*)ttm;
+   struct radeon_device *rdev = radeon_get_rdev(ttm->bdev);
uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ |
RADEON_GART_PAGE_WRITE;
int r;
@@ -531,7 +531,7 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
}
if (ttm->caching_state == tt_cached)
flags |= RADEON_GART_PAGE_SNOOP;
-   r = radeon_gart_bind(gtt->rdev, gtt->offset, ttm->num_pages,
+   r = radeon_gart_bind(rdev, gtt->offset, ttm->num_pages,
 ttm->pages, gtt->ttm.dma_address, flags);
if (r) {
DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
@@ -544,8 +544,9 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
 static void radeon_ttm_backend_unbind(struct ttm_tt *ttm)
 {
struct radeon_ttm_tt *gtt = (void *)ttm;
+   struct radeon_device *rdev = radeon_get_rdev(ttm->bdev);
 
-   radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages);
+   radeon_gart_unbind(rdev, gtt->offset, ttm->num_pages);
 
if (gtt->userptr)
radeon_ttm_tt_unpin_userptr(ttm);
@@ -584,7 +585,6 @@ static struct ttm_tt *radeon_ttm_tt_create(struct 
ttm_buffer_object *bo,
return NULL;
}
gtt->ttm.ttm.func = &radeon_backend_func;
-   gtt->rdev = rdev;
if (ttm_dma_tt_init(>t->ttm, bo, page_flags)) {
kfree(gtt);
return NULL;
-- 
2.27.0

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


[PATCH 18/23] drm/ttm: move bound flag and use a utility wrapper

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

If we move the bound flag out then the tt destroy is much
cleaner in a bo level wrapper, the code is in a few places,
leave the ttm_tt_destroy just about destroying the backing store.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |  1 +
 drivers/gpu/drm/nouveau/nouveau_bo.c|  1 +
 drivers/gpu/drm/radeon/radeon_mn.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_ttm.c |  1 +
 drivers/gpu/drm/ttm/ttm_bo.c| 15 +++---
 drivers/gpu/drm/ttm/ttm_bo_util.c   | 27 ++---
 drivers/gpu/drm/ttm/ttm_tt.c| 19 +
 include/drm/ttm/ttm_bo_api.h|  1 +
 include/drm/ttm/ttm_bo_driver.h |  1 +
 include/drm/ttm/ttm_tt.h|  4 +---
 10 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index c1c3691c3b9f..116407c77f02 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -551,6 +551,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object 
*bo, bool evict,
if (unlikely(r)) {
goto out_cleanup;
}
+   bo->ttm_bound = true;
 
/* blit VRAM to GTT */
r = amdgpu_move_blit(bo, evict, &tmp_mem, old_mem);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e9de922ae921..9ac4b37aed87 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -879,6 +879,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool 
evict, bool intr,
ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg, &ctx);
if (ret)
goto out;
+   bo->ttm_bound = true;
 
ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, &tmp_reg);
if (ret)
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c 
b/drivers/gpu/drm/radeon/radeon_mn.c
index 5f57df7e6f08..e1f0d6ab4c86 100644
--- a/drivers/gpu/drm/radeon/radeon_mn.c
+++ b/drivers/gpu/drm/radeon/radeon_mn.c
@@ -53,7 +53,7 @@ static bool radeon_mn_invalidate(struct mmu_interval_notifier 
*mn,
struct ttm_operation_ctx ctx = { false, false };
long r;
 
-   if (!bo->tbo.ttm || bo->tbo.ttm->bound == false)
+   if (!bo->tbo.ttm || bo->tbo.ttm_bound == false)
return true;
 
if (!mmu_notifier_range_blockable(range))
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index f9e4e64a6d64..71c2a78911cd 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -239,6 +239,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object 
*bo,
if (unlikely(r)) {
goto out_cleanup;
}
+   bo->ttm_bound = true;
r = radeon_move_blit(bo, true, no_wait_gpu, &tmp_mem, old_mem);
if (unlikely(r)) {
goto out_cleanup;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index fa9012c8d11a..bf27d185c23f 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -282,9 +282,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object 
*bo,
goto out_err;
 
if (mem->mem_type != TTM_PL_SYSTEM) {
-   ret = ttm_tt_bind(bdev, bo->ttm, mem, ctx);
-   if (ret)
-   goto out_err;
+   if (bo->ttm_bound == false) {
+   ret = ttm_tt_bind(bdev, bo->ttm, mem, ctx);
+   if (ret)
+   goto out_err;
+   bo->ttm_bound = true;
+   }
}
 
if (bo->mem.mem_type == TTM_PL_SYSTEM) {
@@ -324,8 +327,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object 
*bo,
 out_err:
new_man = ttm_manager_type(bdev, bo->mem.mem_type);
if (!new_man->use_tt) {
-   ttm_tt_destroy(bdev, bo->ttm);
-   bo->ttm = NULL;
+   ttm_bo_tt_destroy(bo, bo->ttm);
}
 
return ret;
@@ -344,8 +346,7 @@ static void ttm_bo_cleanup_memtype_use(struct 
ttm_buffer_object *bo)
if (bo->bdev->driver->move_notify)
bo->bdev->driver->move_notify(bo, false, NULL);
 
-   ttm_tt_destroy(bo->bdev, bo->ttm);
-   bo->ttm = NULL;
+   ttm_bo_tt_destroy(bo, bo->ttm);
ttm_resource_free(bo, &bo->mem);
 }
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index d5d841270e38..8b50b250da0c 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -51,7 +51,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
 }
 
 int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
-  struct ttm_operation_ctx *ctx,
+   struct ttm_operation_ctx *c

[PATCH 19/23] drm/ttm: split bind and populate out.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Make populating the backing store an explicit separate step

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |  7 ++-
 drivers/gpu/drm/nouveau/nouveau_bo.c|  6 +-
 drivers/gpu/drm/radeon/radeon_ttm.c |  7 ++-
 drivers/gpu/drm/ttm/ttm_bo.c|  5 -
 drivers/gpu/drm/ttm/ttm_bo_util.c   |  6 +-
 drivers/gpu/drm/ttm/ttm_tt.c| 16 +---
 include/drm/ttm/ttm_tt.h|  3 +--
 7 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 116407c77f02..e8a56e64bc38 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -546,8 +546,13 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object 
*bo, bool evict,
goto out_cleanup;
}
 
+   r = ttm_tt_populate(bo->bdev, bo->ttm, ctx);
+   if (unlikely(r)) {
+   goto out_cleanup;
+   }
+
/* Bind the memory to the GTT space */
-   r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, ctx);
+   r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem);
if (unlikely(r)) {
goto out_cleanup;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 9ac4b37aed87..f6b6ef7a8868 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -876,7 +876,11 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool 
evict, bool intr,
if (ret)
return ret;
 
-   ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg, &ctx);
+   ret = ttm_tt_populate(bo->bdev, bo->ttm, &ctx);
+   if (ret)
+   goto out;
+
+   ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg);
if (ret)
goto out;
bo->ttm_bound = true;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index 71c2a78911cd..6f64f949c202 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -235,7 +235,12 @@ static int radeon_move_vram_ram(struct ttm_buffer_object 
*bo,
goto out_cleanup;
}
 
-   r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, &ctx);
+   r = ttm_tt_populate(bo->bdev, bo->ttm, &ctx);
+   if (unlikely(r)) {
+   goto out_cleanup;
+   }
+
+   r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem);
if (unlikely(r)) {
goto out_cleanup;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index bf27d185c23f..bf5f31d9996a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -282,8 +282,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object 
*bo,
goto out_err;
 
if (mem->mem_type != TTM_PL_SYSTEM) {
+   ret = ttm_tt_populate(bdev, bo->ttm, ctx);
+   if (ret)
+   goto out_err;
if (bo->ttm_bound == false) {
-   ret = ttm_tt_bind(bdev, bo->ttm, mem, ctx);
+   ret = ttm_tt_bind(bdev, bo->ttm, mem);
if (ret)
goto out_err;
bo->ttm_bound = true;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 8b50b250da0c..c6262fda1fb8 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -80,7 +80,11 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
return ret;
 
if (new_mem->mem_type != TTM_PL_SYSTEM) {
-   ret = ttm_tt_bind(bo->bdev, ttm, new_mem, ctx);
+   ret = ttm_tt_populate(bo->bdev, ttm, ctx);
+   if (unlikely(ret != 0))
+   return ret;
+
+   ret = ttm_tt_bind(bo->bdev, ttm, new_mem);
if (unlikely(ret != 0))
return ret;
bo->ttm_bound = true;
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 8d4f946cd9e0..288fd952bdbe 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -307,22 +307,15 @@ void ttm_tt_unbind(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm)
 }
 
 int ttm_tt_bind(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm, struct ttm_resource *bo_mem,
-   struct ttm_operation_ctx *ctx)
+   struct ttm_tt *ttm, struct ttm_resource *bo_mem)
 {
-   int ret = 0;
-
if (!ttm)
return -EINVAL;
 
-   ret = ttm_tt_populate(bdev, ttm, ctx);
-   if (ret)
-   return ret;
+   if (WARN_ON(!ttm->populated))
+   return -EINVAL;
 
-   ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem);
-   if (unlikely(ret != 0))
-

[PATCH 22/23] drm/ttm: two minor struct reorgs to fill holes.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

These are just minor changes that fill some obvious holes.

Signed-off-by: Dave Airlie 
---
 include/drm/ttm/ttm_placement.h | 2 +-
 include/drm/ttm/ttm_tt.h| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h
index e88a8e39767b..ded0f42a143c 100644
--- a/include/drm/ttm/ttm_placement.h
+++ b/include/drm/ttm/ttm_placement.h
@@ -100,8 +100,8 @@ struct ttm_place {
  */
 struct ttm_placement {
unsignednum_placement;
-   const struct ttm_place  *placement;
unsignednum_busy_placement;
+   const struct ttm_place  *placement;
const struct ttm_place  *busy_placement;
 };
 
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 3b87ce43864a..573254930a3f 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -68,9 +68,9 @@ enum ttm_caching_state {
 struct ttm_tt {
struct page **pages;
uint32_t page_flags;
+   enum ttm_caching_state caching_state;
unsigned long num_pages;
struct file *swap_storage;
-   enum ttm_caching_state caching_state;
 };
 
 static inline bool ttm_tt_is_populated(struct ttm_tt *tt)
-- 
2.27.0

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


[PATCH 14/23] drm/ttm/agp: remove bdev from agp helpers

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Since the agp bind/unbind/destroy are now getting called from drivers
rather than via the func table, drop the bdev parameter.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/nouveau/nouveau_bo.c  |  6 +++---
 drivers/gpu/drm/radeon/radeon_ttm.c   |  6 +++---
 drivers/gpu/drm/ttm/ttm_agp_backend.c | 11 ---
 include/drm/ttm/ttm_tt.h  |  9 +++--
 4 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 08499e1a56c2..0a8c092e0f2e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -676,7 +676,7 @@ nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm,
struct nouveau_drm *drm = nouveau_bdev(bdev);
 
if (drm->agp.bridge) {
-   return ttm_agp_bind(bdev, ttm, reg);
+   return ttm_agp_bind(ttm, reg);
}
 #endif
return nouveau_sgdma_bind(bdev, ttm, reg);
@@ -689,7 +689,7 @@ nouveau_ttm_tt_unbind(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm)
struct nouveau_drm *drm = nouveau_bdev(bdev);
 
if (drm->agp.bridge) {
-   ttm_agp_unbind(bdev, ttm);
+   ttm_agp_unbind(ttm);
return;
}
 #endif
@@ -1331,7 +1331,7 @@ nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev,
 #if IS_ENABLED(CONFIG_AGP)
struct nouveau_drm *drm = nouveau_bdev(bdev);
if (drm->agp.bridge) {
-   ttm_agp_destroy(bdev, ttm);
+   ttm_agp_destroy(ttm);
return;
}
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index eacfc591bf79..6b7af313389d 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -696,7 +696,7 @@ static int radeon_ttm_tt_bind(struct ttm_bo_device *bdev,
 
 #if IS_ENABLED(CONFIG_AGP)
if (rdev->flags & RADEON_IS_AGP) {
-   return ttm_agp_bind(bdev, ttm, bo_mem);
+   return ttm_agp_bind(ttm, bo_mem);
}
 #endif
 
@@ -710,7 +710,7 @@ static void radeon_ttm_tt_unbind(struct ttm_bo_device *bdev,
struct radeon_device *rdev = radeon_get_rdev(bdev);
 
if (rdev->flags & RADEON_IS_AGP) {
-   ttm_agp_unbind(bdev, ttm);
+   ttm_agp_unbind(ttm);
return;
}
 #endif
@@ -724,7 +724,7 @@ static void radeon_ttm_tt_destroy(struct ttm_bo_device 
*bdev,
struct radeon_device *rdev = radeon_get_rdev(bdev);
 
if (rdev->flags & RADEON_IS_AGP) {
-   ttm_agp_destroy(bdev, ttm);
+   ttm_agp_destroy(ttm);
return;
}
 #endif
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c 
b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index 3d0a5e9f4c5f..7b36fdaab766 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -48,8 +48,7 @@ struct ttm_agp_backend {
struct agp_bridge_data *bridge;
 };
 
-int ttm_agp_bind(struct ttm_bo_device *bdev,
-struct ttm_tt *ttm, struct ttm_resource *bo_mem)
+int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
struct page *dummy_read_page = ttm_bo_glob.dummy_read_page;
@@ -84,8 +83,7 @@ int ttm_agp_bind(struct ttm_bo_device *bdev,
 }
 EXPORT_SYMBOL(ttm_agp_bind);
 
-void ttm_agp_unbind(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm)
+void ttm_agp_unbind(struct ttm_tt *ttm)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
 
@@ -100,13 +98,12 @@ void ttm_agp_unbind(struct ttm_bo_device *bdev,
 }
 EXPORT_SYMBOL(ttm_agp_unbind);
 
-void ttm_agp_destroy(struct ttm_bo_device *bdev,
-struct ttm_tt *ttm)
+void ttm_agp_destroy(struct ttm_tt *ttm)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
 
if (agp_be->mem)
-   ttm_agp_unbind(bdev, ttm);
+   ttm_agp_unbind(ttm);
ttm_tt_fini(ttm);
kfree(agp_be);
 }
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 591d4927d501..bdc8aadf3246 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -264,12 +264,9 @@ void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm);
 struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo,
 struct agp_bridge_data *bridge,
 uint32_t page_flags);
-int ttm_agp_bind(struct ttm_bo_device *bdev,
-struct ttm_tt *ttm, struct ttm_resource *bo_mem);
-void ttm_agp_unbind(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm);
-void ttm_agp_destroy(struct ttm_bo_device *bdev,
-struct ttm_tt *ttm);
+int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem);
+vo

[PATCH 16/23] drm/ttm: move sg pointer into ttm_dma_tt

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

This is only used by drivers that have a dma tt backing store.

Signed-off-by: Dave Airlie 
---
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |  3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c   | 32 +--
 drivers/gpu/drm/nouveau/nouveau_bo.c  |  4 +--
 drivers/gpu/drm/nouveau/nouveau_mem.c |  2 +-
 drivers/gpu/drm/radeon/radeon_ttm.c   | 26 +++
 drivers/gpu/drm/ttm/ttm_tt.c  |  4 ++-
 include/drm/ttm/ttm_tt.h  |  2 +-
 7 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index aa2b328c6202..b2faa02c0263 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1231,8 +1231,9 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
goto err_bo_create;
}
if (bo_type == ttm_bo_type_sg) {
+   struct ttm_dma_tt *dma_ttm = (struct ttm_dma_tt *)bo->tbo.ttm;
bo->tbo.sg = sg;
-   bo->tbo.ttm->sg = sg;
+   dma_ttm->sg = sg;
}
bo->kfd_bo = *mem;
(*mem)->bo = bo;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index f07e7121bcc5..adac24625191 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -985,25 +985,25 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device 
*bdev,
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
 
/* Allocate an SG array and squash pages into it */
-   r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0,
+   r = sg_alloc_table_from_pages(gtt->ttm.sg, ttm->pages, ttm->num_pages, 
0,
  ttm->num_pages << PAGE_SHIFT,
  GFP_KERNEL);
if (r)
goto release_sg;
 
/* Map SG to device */
-   r = dma_map_sgtable(adev->dev, ttm->sg, direction, 0);
+   r = dma_map_sgtable(adev->dev, gtt->ttm.sg, direction, 0);
if (r)
goto release_sg;
 
/* convert SG to linear array of pages and dma addresses */
-   drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
+   drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address, ttm->num_pages);
 
return 0;
 
 release_sg:
-   kfree(ttm->sg);
+   kfree(gtt->ttm.sg);
return r;
 }
 
@@ -1021,12 +1021,12 @@ static void amdgpu_ttm_tt_unpin_userptr(struct 
ttm_bo_device *bdev,
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
 
/* double check that we don't free the table twice */
-   if (!ttm->sg->sgl)
+   if (!gtt->ttm.sg->sgl)
return;
 
/* unmap the pages mapped to the device */
-   dma_unmap_sgtable(adev->dev, ttm->sg, direction, 0);
-   sg_free_table(ttm->sg);
+   dma_unmap_sgtable(adev->dev, gtt->ttm.sg, direction, 0);
+   sg_free_table(gtt->ttm.sg);
 
 #if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
if (gtt->range) {
@@ -1296,8 +1296,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
 
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
if (gtt && gtt->userptr) {
-   ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
-   if (!ttm->sg)
+   gtt->ttm.sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+   if (!gtt->ttm.sg)
return -ENOMEM;
 
ttm->page_flags |= TTM_PAGE_FLAG_SG;
@@ -1306,7 +1306,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
}
 
if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
-   if (!ttm->sg) {
+   if (!gtt->ttm.sg) {
struct dma_buf_attachment *attach;
struct sg_table *sgt;
 
@@ -1315,10 +1315,10 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device 
*bdev,
if (IS_ERR(sgt))
return PTR_ERR(sgt);
 
-   ttm->sg = sgt;
+   gtt->ttm.sg = sgt;
}
 
-   drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
+   drm_prime_sg_to_page_addr_arrays(gtt->ttm.sg, ttm->pages,
 gtt->ttm.dma_address,
 ttm->num_pages);
ttm->state = tt_unbound;
@@ -1349,17 +1349,17 @@ static void amdgpu_ttm_tt_unpopulate(struct 
ttm_bo_device *bdev, struct ttm_tt *
 
if (gtt && gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
-   kfree(ttm->sg);
+   kfree(gtt->ttm.sg);
ttm->page_flags &= ~TTM_PAGE_FLAG_SG;
return;
}
 
-  

[PATCH 10/23] drm/amdgpu/ttm: move to driver backend binding funcs

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 9592505563bf..f07e7121bcc5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1255,12 +1255,6 @@ static void amdgpu_ttm_backend_destroy(struct 
ttm_bo_device *bdev,
kfree(gtt);
 }
 
-static struct ttm_backend_func amdgpu_backend_func = {
-   .bind = &amdgpu_ttm_backend_bind,
-   .unbind = &amdgpu_ttm_backend_unbind,
-   .destroy = &amdgpu_ttm_backend_destroy,
-};
-
 /**
  * amdgpu_ttm_tt_create - Create a ttm_tt object for a given BO
  *
@@ -1277,7 +1271,6 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct 
ttm_buffer_object *bo,
if (gtt == NULL) {
return NULL;
}
-   gtt->ttm.ttm.func = &amdgpu_backend_func;
gtt->gobj = &bo->base;
 
/* allocate space for the uninitialized page entries */
@@ -1679,6 +1672,9 @@ static struct ttm_bo_driver amdgpu_bo_driver = {
.ttm_tt_create = &amdgpu_ttm_tt_create,
.ttm_tt_populate = &amdgpu_ttm_tt_populate,
.ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate,
+   .ttm_tt_bind = &amdgpu_ttm_backend_bind,
+   .ttm_tt_unbind = &amdgpu_ttm_backend_unbind,
+   .ttm_tt_destroy = &amdgpu_ttm_backend_destroy,
.eviction_valuable = amdgpu_ttm_bo_eviction_valuable,
.evict_flags = &amdgpu_evict_flags,
.move = &amdgpu_bo_move,
-- 
2.27.0

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


[PATCH 12/23] drm/ttm/agp: drop back end bindings from agp

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

These aren't used anymore.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/ttm/ttm_agp_backend.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c 
b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index fbf98cd1a3e5..8072fb7c5bc8 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -112,12 +112,6 @@ void ttm_agp_destroy(struct ttm_bo_device *bdev,
 }
 EXPORT_SYMBOL(ttm_agp_destroy);
 
-static struct ttm_backend_func ttm_agp_func = {
-   .bind = ttm_agp_bind,
-   .unbind = ttm_agp_unbind,
-   .destroy = ttm_agp_destroy,
-};
-
 struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo,
 struct agp_bridge_data *bridge,
 uint32_t page_flags)
@@ -130,7 +124,6 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object 
*bo,
 
agp_be->mem = NULL;
agp_be->bridge = bridge;
-   agp_be->ttm.func = &ttm_agp_func;
 
if (ttm_tt_init(&agp_be->ttm, bo, page_flags)) {
kfree(agp_be);
-- 
2.27.0

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


[PATCH 09/23] drm/vmwgfx: move to driver binding functions

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
index a76a7f542dd8..6757be98be14 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
@@ -668,12 +668,6 @@ static void vmw_ttm_unpopulate(struct ttm_bo_device *bdev,
ttm_pool_unpopulate(ttm);
 }
 
-static struct ttm_backend_func vmw_ttm_func = {
-   .bind = vmw_ttm_bind,
-   .unbind = vmw_ttm_unbind,
-   .destroy = vmw_ttm_destroy,
-};
-
 static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
 {
@@ -684,7 +678,6 @@ static struct ttm_tt *vmw_ttm_tt_create(struct 
ttm_buffer_object *bo,
if (!vmw_be)
return NULL;
 
-   vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev);
vmw_be->mob = NULL;
 
@@ -770,6 +763,9 @@ struct ttm_bo_driver vmw_bo_driver = {
.ttm_tt_create = &vmw_ttm_tt_create,
.ttm_tt_populate = &vmw_ttm_populate,
.ttm_tt_unpopulate = &vmw_ttm_unpopulate,
+   .ttm_tt_bind = &vmw_ttm_bind,
+   .ttm_tt_unbind = &vmw_ttm_unbind,
+   .ttm_tt_destroy = &vmw_ttm_destroy,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = vmw_evict_flags,
.move = NULL,
-- 
2.27.0

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


[PATCH 11/23] drm/gem_vram/ttm: move to driver backend destroy function.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/drm_gem_vram_helper.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c 
b/drivers/gpu/drm/drm_gem_vram_helper.c
index 788557bc5c01..93586a310971 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -973,10 +973,6 @@ static void backend_func_destroy(struct ttm_bo_device 
*bdev, struct ttm_tt *tt)
kfree(tt);
 }
 
-static struct ttm_backend_func backend_func = {
-   .destroy = backend_func_destroy
-};
-
 /*
  * TTM BO device
  */
@@ -991,8 +987,6 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct 
ttm_buffer_object *bo,
if (!tt)
return NULL;
 
-   tt->func = &backend_func;
-
ret = ttm_tt_init(tt, bo, page_flags);
if (ret < 0)
goto err_ttm_tt_init;
@@ -1055,6 +1049,7 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device 
*bdev,
 
 static struct ttm_bo_driver bo_driver = {
.ttm_tt_create = bo_driver_ttm_tt_create,
+   .ttm_tt_destroy = backend_func_destroy,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = bo_driver_evict_flags,
.move_notify = bo_driver_move_notify,
-- 
2.27.0

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


[PATCH 01/23] drm/amdgpu/ttm: remove unused parameter to move blit

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index d7f668dbc9e0..00b2c0359735 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -455,7 +455,7 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
  * help move buffers to and from VRAM.
  */
 static int amdgpu_move_blit(struct ttm_buffer_object *bo,
-   bool evict, bool no_wait_gpu,
+   bool evict,
struct ttm_resource *new_mem,
struct ttm_resource *old_mem)
 {
@@ -553,7 +553,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object 
*bo, bool evict,
}
 
/* blit VRAM to GTT */
-   r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, &tmp_mem, old_mem);
+   r = amdgpu_move_blit(bo, evict, &tmp_mem, old_mem);
if (unlikely(r)) {
goto out_cleanup;
}
@@ -603,7 +603,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object 
*bo, bool evict,
}
 
/* copy to VRAM */
-   r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, new_mem, old_mem);
+   r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
if (unlikely(r)) {
goto out_cleanup;
}
@@ -692,7 +692,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, 
bool evict,
   new_mem->mem_type == TTM_PL_VRAM) {
r = amdgpu_move_ram_vram(bo, evict, ctx, new_mem);
} else {
-   r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu,
+   r = amdgpu_move_blit(bo, evict,
 new_mem, old_mem);
}
 
-- 
2.27.0

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


[PATCH 08/23] drm/nouveau/ttm: use driver bind/unbind/destroy functions.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/nouveau/nouveau_bo.c| 45 +
 drivers/gpu/drm/nouveau/nouveau_sgdma.c | 54 ++---
 drivers/gpu/drm/nouveau/nouveau_ttm.h   |  3 ++
 3 files changed, 60 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 9e6425a0cb3f..f16401feb965 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -668,6 +668,34 @@ nouveau_ttm_tt_create(struct ttm_buffer_object *bo, 
uint32_t page_flags)
return nouveau_sgdma_create_ttm(bo, page_flags);
 }
 
+static int
+nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm,
+   struct ttm_resource *reg)
+{
+#if IS_ENABLED(CONFIG_AGP)
+   struct nouveau_drm *drm = nouveau_bdev(bdev);
+
+   if (drm->agp.bridge) {
+   return ttm_agp_bind(bdev, ttm, reg);
+   }
+#endif
+   return nouveau_sgdma_bind(bdev, ttm, reg);
+}
+
+static void
+nouveau_ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
+{
+#if IS_ENABLED(CONFIG_AGP)
+   struct nouveau_drm *drm = nouveau_bdev(bdev);
+
+   if (drm->agp.bridge) {
+   ttm_agp_unbind(bdev, ttm);
+   return;
+   }
+#endif
+   nouveau_sgdma_unbind(bdev, ttm);
+}
+
 static void
 nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 {
@@ -1296,6 +1324,20 @@ nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev,
ttm_unmap_and_unpopulate_pages(dev, ttm_dma);
 }
 
+static void
+nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev,
+  struct ttm_tt *ttm)
+{
+#if IS_ENABLED(CONFIG_AGP)
+   struct nouveau_drm *drm = nouveau_bdev(bdev);
+   if (drm->agp.bridge) {
+   ttm_agp_destroy(bdev, ttm);
+   return;
+   }
+#endif
+   nouveau_sgdma_destroy(bdev, ttm);
+}
+
 void
 nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool 
exclusive)
 {
@@ -1311,6 +1353,9 @@ struct ttm_bo_driver nouveau_bo_driver = {
.ttm_tt_create = &nouveau_ttm_tt_create,
.ttm_tt_populate = &nouveau_ttm_tt_populate,
.ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
+   .ttm_tt_bind = &nouveau_ttm_tt_bind,
+   .ttm_tt_unbind = &nouveau_ttm_tt_unbind,
+   .ttm_tt_destroy = &nouveau_ttm_tt_destroy,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = nouveau_bo_evict_flags,
.move_notify = nouveau_bo_move_ntfy,
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c 
b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 6000c650b105..05e542254e1f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -14,7 +14,7 @@ struct nouveau_sgdma_be {
struct nouveau_mem *mem;
 };
 
-static void
+void
 nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
 {
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
@@ -25,10 +25,11 @@ nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm)
}
 }
 
-static int
-nv04_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_resource *reg)
+int
+nouveau_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_resource *reg)
 {
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
+   struct nouveau_drm *drm = nouveau_bdev(bdev);
struct nouveau_mem *mem = nouveau_mem(reg);
int ret;
 
@@ -36,65 +37,34 @@ nv04_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt 
*ttm, struct ttm_resou
if (ret)
return ret;
 
-   ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]);
-   if (ret) {
-   nouveau_mem_fini(mem);
-   return ret;
+   if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
+   ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]);
+   if (ret) {
+   nouveau_mem_fini(mem);
+   return ret;
+   }
}
 
nvbe->mem = mem;
return 0;
 }
 
-static void
-nv04_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
+void
+nouveau_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
 {
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
nouveau_mem_fini(nvbe->mem);
 }
 
-static struct ttm_backend_func nv04_sgdma_backend = {
-   .bind   = nv04_sgdma_bind,
-   .unbind = nv04_sgdma_unbind,
-   .destroy= nouveau_sgdma_destroy
-};
-
-static int
-nv50_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_resource *reg)
-{
-   struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
-   struct nouveau_mem *mem = nouveau_mem(reg);
-   int ret;
-
-   ret = nouveau_mem_host(reg, &nvbe->ttm);
- 

[PATCH 07/23] drm/radeon/ttm: move to driver binding/destroy functions.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Do agp decision in the driver, instead of special binding funcs

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/radeon/radeon.h|  7 +-
 drivers/gpu/drm/radeon/radeon_cs.c |  2 +-
 drivers/gpu/drm/radeon/radeon_gem.c|  6 +-
 drivers/gpu/drm/radeon/radeon_object.c |  2 +-
 drivers/gpu/drm/radeon/radeon_prime.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_ttm.c| 92 --
 drivers/gpu/drm/radeon/radeon_vm.c |  2 +-
 7 files changed, 81 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index cc4f58d16589..df6f0b49836b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -2815,10 +2815,11 @@ extern void radeon_legacy_set_clock_gating(struct 
radeon_device *rdev, int enabl
 extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int 
enable);
 extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 
domain);
 extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
-extern int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,
+extern int radeon_ttm_tt_set_userptr(struct radeon_device *rdev,
+struct ttm_tt *ttm, uint64_t addr,
 uint32_t flags);
-extern bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm);
-extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm);
+extern bool radeon_ttm_tt_has_userptr(struct radeon_device *rdev, struct 
ttm_tt *ttm);
+extern bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, struct 
ttm_tt *ttm);
 extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc 
*mc, u64 base);
 extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc 
*mc);
 extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index 33ae1b883268..21ce2f9502c0 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -160,7 +160,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser 
*p)
p->relocs[i].allowed_domains = domain;
}
 
-   if (radeon_ttm_tt_has_userptr(p->relocs[i].robj->tbo.ttm)) {
+   if (radeon_ttm_tt_has_userptr(p->rdev, 
p->relocs[i].robj->tbo.ttm)) {
uint32_t domain = p->relocs[i].preferred_domains;
if (!(domain & RADEON_GEM_DOMAIN_GTT)) {
DRM_ERROR("Only RADEON_GEM_DOMAIN_GTT is "
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index 7f5dfe04789e..e5c4271e64ed 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -331,7 +331,7 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void 
*data,
goto handle_lockup;
 
bo = gem_to_radeon_bo(gobj);
-   r = radeon_ttm_tt_set_userptr(bo->tbo.ttm, args->addr, args->flags);
+   r = radeon_ttm_tt_set_userptr(rdev, bo->tbo.ttm, args->addr, 
args->flags);
if (r)
goto release_object;
 
@@ -420,7 +420,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
return -ENOENT;
}
robj = gem_to_radeon_bo(gobj);
-   if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) {
+   if (radeon_ttm_tt_has_userptr(robj->rdev, robj->tbo.ttm)) {
drm_gem_object_put(gobj);
return -EPERM;
}
@@ -721,7 +721,7 @@ int radeon_gem_op_ioctl(struct drm_device *dev, void *data,
robj = gem_to_radeon_bo(gobj);
 
r = -EPERM;
-   if (radeon_ttm_tt_has_userptr(robj->tbo.ttm))
+   if (radeon_ttm_tt_has_userptr(robj->rdev, robj->tbo.ttm))
goto out;
 
r = radeon_bo_reserve(robj, false);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
b/drivers/gpu/drm/radeon/radeon_object.c
index bb7582afd803..3fcd15d21ddc 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -331,7 +331,7 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 
domain, u64 max_offset,
struct ttm_operation_ctx ctx = { false, false };
int r, i;
 
-   if (radeon_ttm_tt_has_userptr(bo->tbo.ttm))
+   if (radeon_ttm_tt_has_userptr(bo->rdev, bo->tbo.ttm))
return -EPERM;
 
if (bo->pin_count) {
diff --git a/drivers/gpu/drm/radeon/radeon_prime.c 
b/drivers/gpu/drm/radeon/radeon_prime.c
index b906e8fbd5f3..d6d9c8b46ab4 100644
--- a/drivers/gpu/drm/radeon/radeon_prime.c
+++ b/drivers/gpu/drm/radeon/radeon_prime.c
@@ -121,7 +121,7 @@ struct dma_buf *radeon_gem_prime_export(struct 
drm_gem_object *gobj,
int flags)
 {
struct radeon_bo *bo = gem_to_radeon_bo(gobj);
-   if (radeon_ttm_tt_has_userptr(bo->tbo.ttm))
+   if (radeon_ttm_tt_h

[PATCH 06/23] drm/ttm/agp: export bind/unbind/destroy for drivers to use.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/ttm/ttm_agp_backend.c | 15 +--
 include/drm/ttm/ttm_tt.h  |  6 ++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c 
b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index 934a69491547..fbf98cd1a3e5 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -48,8 +48,8 @@ struct ttm_agp_backend {
struct agp_bridge_data *bridge;
 };
 
-static int ttm_agp_bind(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm, struct ttm_resource *bo_mem)
+int ttm_agp_bind(struct ttm_bo_device *bdev,
+struct ttm_tt *ttm, struct ttm_resource *bo_mem)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
struct page *dummy_read_page = ttm_bo_glob.dummy_read_page;
@@ -82,9 +82,10 @@ static int ttm_agp_bind(struct ttm_bo_device *bdev,
 
return ret;
 }
+EXPORT_SYMBOL(ttm_agp_bind);
 
-static void ttm_agp_unbind(struct ttm_bo_device *bdev,
-  struct ttm_tt *ttm)
+void ttm_agp_unbind(struct ttm_bo_device *bdev,
+   struct ttm_tt *ttm)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
 
@@ -97,9 +98,10 @@ static void ttm_agp_unbind(struct ttm_bo_device *bdev,
agp_be->mem = NULL;
}
 }
+EXPORT_SYMBOL(ttm_agp_unbind);
 
-static void ttm_agp_destroy(struct ttm_bo_device *bdev,
-   struct ttm_tt *ttm)
+void ttm_agp_destroy(struct ttm_bo_device *bdev,
+struct ttm_tt *ttm)
 {
struct ttm_agp_backend *agp_be = container_of(ttm, struct 
ttm_agp_backend, ttm);
 
@@ -108,6 +110,7 @@ static void ttm_agp_destroy(struct ttm_bo_device *bdev,
ttm_tt_fini(ttm);
kfree(agp_be);
 }
+EXPORT_SYMBOL(ttm_agp_destroy);
 
 static struct ttm_backend_func ttm_agp_func = {
.bind = ttm_agp_bind,
diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
index 6bda88f8da46..5a34f1640865 100644
--- a/include/drm/ttm/ttm_tt.h
+++ b/include/drm/ttm/ttm_tt.h
@@ -266,6 +266,12 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object 
*bo,
 uint32_t page_flags);
 int ttm_agp_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct 
ttm_operation_ctx *ctx);
 void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm);
+int ttm_agp_bind(struct ttm_bo_device *bdev,
+struct ttm_tt *ttm, struct ttm_resource *bo_mem);
+void ttm_agp_unbind(struct ttm_bo_device *bdev,
+   struct ttm_tt *ttm);
+void ttm_agp_destroy(struct ttm_bo_device *bdev,
+struct ttm_tt *ttm);
 #endif
 
 #endif
-- 
2.27.0

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


[PATCH 04/23] drm/ttm: add optional bind/unbind via driver.

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

I want to remove the backend funcs

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/ttm/ttm_tt.c| 15 +++---
 include/drm/ttm/ttm_bo_driver.h | 36 +
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 50a899104022..73c97dcfa512 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -222,7 +222,10 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct 
ttm_tt *ttm)
fput(ttm->swap_storage);
 
ttm->swap_storage = NULL;
-   ttm->func->destroy(bdev, ttm);
+   if (bdev->driver->ttm_tt_destroy)
+   bdev->driver->ttm_tt_destroy(bdev, ttm);
+   else
+   ttm->func->destroy(bdev, ttm);
 }
 
 static void ttm_tt_init_fields(struct ttm_tt *ttm,
@@ -310,7 +313,10 @@ EXPORT_SYMBOL(ttm_dma_tt_fini);
 void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
 {
if (ttm->state == tt_bound) {
-   ttm->func->unbind(bdev, ttm);
+   if (bdev->driver->ttm_tt_unbind)
+   bdev->driver->ttm_tt_unbind(bdev, ttm);
+   else
+   ttm->func->unbind(bdev, ttm);
ttm->state = tt_unbound;
}
 }
@@ -331,7 +337,10 @@ int ttm_tt_bind(struct ttm_bo_device *bdev,
if (ret)
return ret;
 
-   ret = ttm->func->bind(bdev, ttm, bo_mem);
+   if (bdev->driver->ttm_tt_bind)
+   ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem);
+   else
+   ret = ttm->func->bind(bdev, ttm, bo_mem);
if (unlikely(ret != 0))
return ret;
 
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index ebba282667ba..32c0651cc0fd 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -90,6 +90,42 @@ struct ttm_bo_driver {
 */
void (*ttm_tt_unpopulate)(struct ttm_bo_device *bdev, struct ttm_tt 
*ttm);
 
+   /**
+* ttm_tt_bind
+*
+* @bdev: Pointer to a ttm device
+* @ttm: Pointer to a struct ttm_tt.
+* @bo_mem: Pointer to a struct ttm_resource describing the
+* memory type and location for binding.
+*
+* Bind the backend pages into the aperture in the location
+* indicated by @bo_mem. This function should be able to handle
+* differences between aperture and system page sizes.
+*/
+   int (*ttm_tt_bind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm, 
struct ttm_resource *bo_mem);
+
+   /**
+* ttm_tt_unbind
+*
+* @bdev: Pointer to a ttm device
+* @ttm: Pointer to a struct ttm_tt.
+*
+* Unbind previously bound backend pages. This function should be
+* able to handle differences between aperture and system page sizes.
+*/
+   void (*ttm_tt_unbind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm);
+
+   /**
+* ttm_tt_destroy
+*
+* @bdev: Pointer to a ttm device
+* @ttm: Pointer to a struct ttm_tt.
+*
+* Destroy the backend. This will be call back from ttm_tt_destroy so
+* don't call ttm_tt_destroy from the callback or infinite loop.
+*/
+   void (*ttm_tt_destroy)(struct ttm_bo_device *bdev, struct ttm_tt *ttm);
+
/**
 * struct ttm_bo_driver member eviction_valuable
 *
-- 
2.27.0

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


[PATCH 03/23] drm/ttm: remove bdev from ttm_tt

2020-08-25 Thread Dave Airlie
From: Dave Airlie 

I want to split this structure up and use it differently,
step one remove bdev pointer from it and pass it explicitly.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c| 40 +++
 drivers/gpu/drm/drm_gem_vram_helper.c  |  2 +-
 drivers/gpu/drm/nouveau/nouveau_bo.c   | 16 
 drivers/gpu/drm/nouveau/nouveau_sgdma.c|  8 ++--
 drivers/gpu/drm/qxl/qxl_ttm.c  |  9 +++--
 drivers/gpu/drm/radeon/radeon_ttm.c| 40 ++-
 drivers/gpu/drm/ttm/ttm_agp_backend.c  | 17 +---
 drivers/gpu/drm/ttm/ttm_bo.c   |  8 ++--
 drivers/gpu/drm/ttm/ttm_bo_util.c  | 14 +++
 drivers/gpu/drm/ttm/ttm_bo_vm.c|  2 +-
 drivers/gpu/drm/ttm/ttm_tt.c   | 45 --
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 16 +---
 include/drm/ttm/ttm_bo_driver.h|  7 ++--
 include/drm/ttm/ttm_tt.h   | 25 ++--
 15 files changed, 139 insertions(+), 114 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 00b2c0359735..9592505563bf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -547,7 +547,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object 
*bo, bool evict,
}
 
/* Bind the memory to the GTT space */
-   r = ttm_tt_bind(bo->ttm, &tmp_mem, ctx);
+   r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, ctx);
if (unlikely(r)) {
goto out_cleanup;
}
@@ -973,9 +973,10 @@ void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, 
struct page **pages)
  *
  * Called by amdgpu_ttm_backend_bind()
  **/
-static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
+static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device *bdev,
+struct ttm_tt *ttm)
 {
-   struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
+   struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
int r;
 
@@ -1009,9 +1010,10 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
 /**
  * amdgpu_ttm_tt_unpin_userptr - Unpin and unmap userptr pages
  */
-static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
+static void amdgpu_ttm_tt_unpin_userptr(struct ttm_bo_device *bdev,
+   struct ttm_tt *ttm)
 {
-   struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
+   struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
 
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
@@ -1092,16 +1094,17 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device 
*adev,
  * Called by ttm_tt_bind() on behalf of ttm_bo_handle_move_mem().
  * This handles binding GTT memory to the device address space.
  */
-static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm,
+static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev,
+  struct ttm_tt *ttm,
   struct ttm_resource *bo_mem)
 {
-   struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
+   struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = (void*)ttm;
uint64_t flags;
int r = 0;
 
if (gtt->userptr) {
-   r = amdgpu_ttm_tt_pin_userptr(ttm);
+   r = amdgpu_ttm_tt_pin_userptr(bdev, ttm);
if (r) {
DRM_ERROR("failed to pin userptr\n");
return r;
@@ -1219,15 +1222,16 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object 
*tbo)
  * Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and
  * ttm_tt_destroy().
  */
-static void amdgpu_ttm_backend_unbind(struct ttm_tt *ttm)
+static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev,
+ struct ttm_tt *ttm)
 {
-   struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
+   struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
int r;
 
/* if the pages have userptr pinning then clear that first */
if (gtt->userptr)
-   amdgpu_ttm_tt_unpin_userptr(ttm);
+   amdgpu_ttm_tt_unpin_userptr(bdev, ttm);
 
if (gtt->offset == AMDGPU_BO_INVALID_OFFSET)
return;
@@ -1239,7 +1243,8 @@ static void amdgpu_ttm_backend_unbind(struct ttm_tt *ttm)
  gtt->ttm.ttm.num_pages, gtt->offset);
 }
 
-static void amdgpu_ttm_backend_destroy(struct ttm_tt *ttm)
+static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev,
+  struct ttm_tt *ttm)
 {
struct amdgpu_ttm_tt *gtt = (void *)ttm;
 
@@ -1289,10 +1294,11 @@ static struct ttm_tt *amdgpu_t

Re: [PATCH 2/3] drm/nouveau: move io_reserve_lru handling into the driver v4

2020-08-25 Thread Dave Airlie
On Sat, 22 Aug 2020 at 02:01, Christian König
 wrote:
>
> While working on TTM cleanups I've found that the io_reserve_lru used by
> Nouveau is actually not working at all.
>
> In general we should remove driver specific handling from the memory
> management, so this patch moves the io_reserve_lru handling into Nouveau
> instead.
>
> v2: don't call ttm_bo_unmap_virtual in nouveau_ttm_io_mem_reserve
> v3: rebased and use both base and offset in the check
> v4: fix small typos and test the patch
>
> Signed-off-by: Christian König 
> Acked-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/nouveau/nouveau_bo.c  | 111 --
>  drivers/gpu/drm/nouveau/nouveau_bo.h  |   3 +
>  drivers/gpu/drm/nouveau/nouveau_drv.h |   2 +
>  drivers/gpu/drm/nouveau/nouveau_ttm.c |  44 +-
>  4 files changed, 135 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c 
> b/drivers/gpu/drm/nouveau/nouveau_bo.c
> index 5392e5fea5d4..ee0e135ddcbb 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
> @@ -137,6 +137,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
> struct nouveau_bo *nvbo = nouveau_bo(bo);
>
> WARN_ON(nvbo->pin_refcnt > 0);
> +   nouveau_bo_del_io_reserve_lru(bo);
> nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
>
> /*
> @@ -304,6 +305,7 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int 
> align, u32 flags,
>
> nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
> nouveau_bo_placement_set(nvbo, flags, 0);
> +   INIT_LIST_HEAD(&nvbo->io_reserve_lru);
>
> ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type,
>   &nvbo->placement, align >> PAGE_SHIFT, false,
> @@ -574,6 +576,26 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
> PAGE_SIZE, DMA_FROM_DEVICE);
>  }
>
> +void nouveau_bo_add_io_reserve_lru(struct ttm_buffer_object *bo)
> +{
> +   struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
> +   struct nouveau_bo *nvbo = nouveau_bo(bo);
> +
> +   mutex_lock(&drm->ttm.io_reserve_mutex);
> +   list_move_tail(&nvbo->io_reserve_lru, &drm->ttm.io_reserve_lru);
> +   mutex_unlock(&drm->ttm.io_reserve_mutex);
> +}
> +
> +void nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object *bo)
> +{
> +   struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
> +   struct nouveau_bo *nvbo = nouveau_bo(bo);
> +
> +   mutex_lock(&drm->ttm.io_reserve_mutex);
> +   list_del_init(&nvbo->io_reserve_lru);
> +   mutex_unlock(&drm->ttm.io_reserve_mutex);
> +}
> +
>  int
>  nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
> bool no_wait_gpu)
> @@ -888,6 +910,8 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool 
> evict,
> if (bo->destroy != nouveau_bo_del_ttm)
> return;
>
> +   nouveau_bo_del_io_reserve_lru(bo);
> +
> if (mem && new_reg->mem_type != TTM_PL_SYSTEM &&
> mem->mem.page == nvbo->page) {
> list_for_each_entry(vma, &nvbo->vma_list, head) {
> @@ -1018,23 +1042,54 @@ nouveau_bo_verify_access(struct ttm_buffer_object 
> *bo, struct file *filp)
>   filp->private_data);
>  }
>
> +static void
> +nouveau_ttm_io_mem_free_locked(struct nouveau_drm *drm,
> +  struct ttm_resource *reg)
> +{
> +   struct nouveau_mem *mem = nouveau_mem(reg);
> +
> +   if (!reg->bus.base && !reg->bus.offset)
> +   return; /* already freed */
> +
> +   if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
> +   switch (reg->mem_type) {
> +   case TTM_PL_TT:
> +   if (mem->kind)
> +   nvif_object_unmap_handle(&mem->mem.object);
> +   break;
> +   case TTM_PL_VRAM:
> +   nvif_object_unmap_handle(&mem->mem.object);
> +   break;
> +   default:
> +   break;
> +   }
> +   }
> +   reg->bus.base = 0;
> +   reg->bus.offset = 0;
> +}
> +
>  static int
>  nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource 
> *reg)
>  {
> struct nouveau_drm *drm = nouveau_bdev(bdev);
> struct nvkm_device *device = nvxx_device(&drm->client.device);
> struct nouveau_mem *mem = nouveau_mem(reg);
> +   int ret;
> +
> +   if (reg->bus.base || reg->bus.offset)
> +   return 0; /* already mapped */
>
> reg->bus.addr = NULL;
> -   reg->bus.offset = 0;
> reg->bus.size = reg->num_pages << PAGE_SHIFT;
> -   reg->bus.base = 0;
> reg->bus.is_iomem = false;
>
> +   mutex_lock(&drm->ttm.io_reserve_mutex);
> +retry:
> switch (reg->mem_type) {
> case TTM_PL_SYSTEM:
> /* System memory */
> -   return 0;
> +  

linux-next: build failure after merge of the drm-misc tree

2020-08-25 Thread Stephen Rothwell
Hi all,

After merging the drm-misc tree, today's linux-next build (x86_64
allmodconfig) failed like this:

drivers/gpu/drm/qxl/qxl_display.c: In function 
'qxl_display_read_client_monitors_config':
include/drm/drm_modeset_lock.h:167:7: error: implicit declaration of function 
'drm_drv_uses_atomic_modeset' [-Werror=implicit-function-declaration]
  167 |  if (!drm_drv_uses_atomic_modeset(dev))\
  |   ^~~
drivers/gpu/drm/qxl/qxl_display.c:187:2: note: in expansion of macro 
'DRM_MODESET_LOCK_ALL_BEGIN'
  187 |  DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
  |  ^~
drivers/gpu/drm/qxl/qxl_display.c:189:35: error: macro 
"DRM_MODESET_LOCK_ALL_END" requires 3 arguments, but only 2 given
  189 |  DRM_MODESET_LOCK_ALL_END(ctx, ret);
  |   ^
In file included from include/drm/drm_crtc.h:36,
 from include/drm/drm_atomic.h:31,
 from drivers/gpu/drm/qxl/qxl_display.c:29:
include/drm/drm_modeset_lock.h:194: note: macro "DRM_MODESET_LOCK_ALL_END" 
defined here
  194 | #define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret)\
  | 
drivers/gpu/drm/qxl/qxl_display.c:189:2: error: 'DRM_MODESET_LOCK_ALL_END' 
undeclared (first use in this function)
  189 |  DRM_MODESET_LOCK_ALL_END(ctx, ret);
  |  ^~~~
drivers/gpu/drm/qxl/qxl_display.c:189:2: note: each undeclared identifier is 
reported only once for each function it appears in
drivers/gpu/drm/qxl/qxl_display.c:187:2: error: label 'modeset_lock_fail' used 
but not defined
  187 |  DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
  |  ^~
In file included from include/drm/drm_crtc.h:36,
 from include/drm/drm_atomic.h:31,
 from drivers/gpu/drm/qxl/qxl_display.c:29:
include/drm/drm_modeset_lock.h:170:1: warning: label 'modeset_lock_retry' 
defined but not used [-Wunused-label]
  170 | modeset_lock_retry:   \
  | ^~
drivers/gpu/drm/qxl/qxl_display.c:187:2: note: in expansion of macro 
'DRM_MODESET_LOCK_ALL_BEGIN'
  187 |  DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
  |  ^~
drivers/gpu/drm/qxl/qxl_display.c: In function 'qxl_framebuffer_surface_dirty':
drivers/gpu/drm/qxl/qxl_display.c:434:35: error: macro 
"DRM_MODESET_LOCK_ALL_END" requires 3 arguments, but only 2 given
  434 |  DRM_MODESET_LOCK_ALL_END(ctx, ret);
  |   ^
In file included from include/drm/drm_crtc.h:36,
 from include/drm/drm_atomic.h:31,
 from drivers/gpu/drm/qxl/qxl_display.c:29:
include/drm/drm_modeset_lock.h:194: note: macro "DRM_MODESET_LOCK_ALL_END" 
defined here
  194 | #define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret)\
  | 
drivers/gpu/drm/qxl/qxl_display.c:434:2: error: 'DRM_MODESET_LOCK_ALL_END' 
undeclared (first use in this function)
  434 |  DRM_MODESET_LOCK_ALL_END(ctx, ret);
  |  ^~~~
drivers/gpu/drm/qxl/qxl_display.c:411:2: error: label 'modeset_lock_fail' used 
but not defined
  411 |  DRM_MODESET_LOCK_ALL_BEGIN(fb->dev, ctx, 
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
  |  ^~
In file included from include/drm/drm_crtc.h:36,
 from include/drm/drm_atomic.h:31,
 from drivers/gpu/drm/qxl/qxl_display.c:29:
include/drm/drm_modeset_lock.h:170:1: warning: label 'modeset_lock_retry' 
defined but not used [-Wunused-label]
  170 | modeset_lock_retry:   \
  | ^~
drivers/gpu/drm/qxl/qxl_display.c:411:2: note: in expansion of macro 
'DRM_MODESET_LOCK_ALL_BEGIN'
  411 |  DRM_MODESET_LOCK_ALL_BEGIN(fb->dev, ctx, 
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
  |  ^~

Caused by commit

  bbaac1354cc9 ("drm/qxl: Replace deprecated function in qxl_display")

interacting with commit

  77ef38574beb ("drm/modeset-lock: Take the modeset BKL for legacy drivers")

from the drm-misc-fixes tree.

drivers/gpu/drm/qxl/qxl_display.c manages to include
drm/drm_modeset_lock.h by some indirect route, but fails to have
drm/drm_drv.h similarly included.  In fact, drm/drm_modeset_lock.h should
have included drm/drm_drv.h since it uses things declared there, and
drivers/gpu/drm/qxl/qxl_display.c should include drm/drm_modeset_lock.h
similarly.

I have added the following hack patch for today.

From: Stephen Rothwell 
Date: Wed, 26 Aug 2020 10:40:18 +1000
Subject: [PATCH] fix interaction with drm-misc-fix commit

Signed-off-by: Stephen Rothwell 
---
 drivers/gpu/drm/qxl/qxl_display.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_display.c 
b/drivers/gpu/drm/qxl/qxl_display.c
index fa79688013b7..6063f3a15329 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -26,6 +26,7 @@
 #include 
 #

linux-next: manual merge of the drm-misc tree with the amdgpu tree

2020-08-25 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the drm-misc tree got conflicts in:

  drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
  drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c

between commits:

  cacbbe7c0065 ("drm/amdgpu: move stolen memory from gmc to mman")
  72de33f8f7ba ("drm/amdgpu: move IP discovery data to mman")
  87ded5caeec3 ("drm/amdgpu: move vram usage by vbios to mman (v2)")
  1348969ab68c ("drm/amdgpu: drm_device to amdgpu_device by inline-f (v2)")

from the amdgpu tree and commits:

  6c28aed6e5b7 ("drm/amdgfx/ttm: use wrapper to get ttm memory managers")
  9de59bc20149 ("drm/ttm: rename ttm_mem_type_manager -> ttm_resource_manager.")
  4f297b9c82e1 ("drm/amdgpu/ttm: move vram/gtt mgr allocations to mman.")

from the drm-misc tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index e1b66898cb76,697bc2c6fdb2..
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@@ -47,10 -46,10 +46,10 @@@ static ssize_t amdgpu_mem_info_gtt_tota
struct device_attribute *attr, char *buf)
  {
struct drm_device *ddev = dev_get_drvdata(dev);
 -  struct amdgpu_device *adev = ddev->dev_private;
 +  struct amdgpu_device *adev = drm_to_adev(ddev);
- 
+   struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, 
TTM_PL_TT);
return snprintf(buf, PAGE_SIZE, "%llu\n",
-   (adev->mman.bdev.man[TTM_PL_TT].size) * PAGE_SIZE);
+   man->size * PAGE_SIZE);
  }
  
  /**
@@@ -65,10 -64,10 +64,10 @@@ static ssize_t amdgpu_mem_info_gtt_used
struct device_attribute *attr, char *buf)
  {
struct drm_device *ddev = dev_get_drvdata(dev);
 -  struct amdgpu_device *adev = ddev->dev_private;
 +  struct amdgpu_device *adev = drm_to_adev(ddev);
- 
+   struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, 
TTM_PL_TT);
return snprintf(buf, PAGE_SIZE, "%llu\n",
-   amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT]));
+   amdgpu_gtt_mgr_usage(man));
  }
  
  static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO,
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 63e541409549,fc5f7ac53d0a..
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@@ -2316,8 -2251,8 +2261,8 @@@ static int amdgpu_mm_dump_table(struct 
struct drm_info_node *node = (struct drm_info_node *)m->private;
unsigned ttm_pl = (uintptr_t)node->info_ent->data;
struct drm_device *dev = node->minor->dev;
 -  struct amdgpu_device *adev = dev->dev_private;
 +  struct amdgpu_device *adev = drm_to_adev(dev);
-   struct ttm_mem_type_manager *man = &adev->mman.bdev.man[ttm_pl];
+   struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, 
ttm_pl);
struct drm_printer p = drm_seq_file_printer(m);
  
man->func->debug(man, &p);
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index de37ceff0e56,7ba2be37e6ba..
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@@ -60,22 -75,8 +75,24 @@@ struct amdgpu_mman 
/* Scheduler entity for buffer moves */
struct drm_sched_entity entity;
  
 +  uint64_tstolen_vga_size;
 +  struct amdgpu_bo*stolen_vga_memory;
 +  uint64_tstolen_extended_size;
 +  struct amdgpu_bo*stolen_extended_memory;
 +  boolkeep_stolen_vga_memory;
 +
 +  /* discovery */
 +  uint8_t *discovery_bin;
 +  uint32_tdiscovery_tmr_size;
 +  struct amdgpu_bo*discovery_memory;
 +
 +  /* firmware VRAM reservation */
 +  u64 fw_vram_usage_start_offset;
 +  u64 fw_vram_usage_size;
 +  struct amdgpu_bo*fw_vram_usage_reserved_bo;
 +  void*fw_vram_usage_va;
+   struct amdgpu_vram_mgr vram_mgr;
+   struct amdgpu_gtt_mgr gtt_mgr;
  };
  
  struct amdgpu_copy_mem {
diff --cc drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 91098a385ed6,7574be6cd7a0..
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@@ -81,10 -84,10 +84,10 @@@ static ssize_t amdgpu_mem_info_vram_use
struct device_attribute *attr, char *buf)
  {
struct drm_device *ddev = dev_ge

linux-next: manual merge of the drm-misc tree with Linus' tree

2020-08-25 Thread Stephen Rothwell
Hi all,

Today's linux-next merge of the drm-misc tree got conflicts in:

  drivers/video/fbdev/arcfb.c
  drivers/video/fbdev/atmel_lcdfb.c
  drivers/video/fbdev/savage/savagefb_driver.c

between commit:

  df561f6688fe ("treewide: Use fallthrough pseudo-keyword")

from Linus' tree and commit:

  ad04fae0de07 ("fbdev: Use fallthrough pseudo-keyword")

from the drm-misc tree.

I fixed it up (they are much the same, I just used the version from Linus'
tree) and can carry the fix as necessary. This is now fixed as far as
linux-next is concerned, but any non trivial conflicts should be mentioned
to your upstream maintainer when your tree is submitted for merging.
You may also want to consider cooperating with the maintainer of the
conflicting tree to minimise any particularly complex conflicts.



-- 
Cheers,
Stephen Rothwell


pgp_GFmsxClt6.pgp
Description: OpenPGP digital signature
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/i915/display: fix uninitialized variable

2020-08-25 Thread trix
From: Tom Rix 

clang static analysis flags this error

intel_combo_phy.c:268:7: warning: The left expression of the
  compound assignment is an uninitialized value.
  The computed value will also be garbage
ret &= check_phy_reg(...
~~~ ^

ret has no initial values, in icl_combo_phy_verify_state() ret is
set by the next statment and then updated by similar &= logic.

Because the check_phy_req() are only register reads, reorder the
statements.

Fixes: 239bef676d8e ("drm/i915/display: Implement new combo phy initialization 
step")
Signed-off-by: Tom Rix 
---
 drivers/gpu/drm/i915/display/intel_combo_phy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c 
b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index 6968de4f3477..7622ef66c987 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -264,6 +264,8 @@ static bool icl_combo_phy_verify_state(struct 
drm_i915_private *dev_priv,
if (!icl_combo_phy_enabled(dev_priv, phy))
return false;
 
+   ret = cnl_verify_procmon_ref_values(dev_priv, phy);
+
if (INTEL_GEN(dev_priv) >= 12) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN0(phy),
 ICL_PORT_TX_DW8_ODCC_CLK_SEL |
@@ -276,8 +278,6 @@ static bool icl_combo_phy_verify_state(struct 
drm_i915_private *dev_priv,
 DCC_MODE_SELECT_CONTINUOSLY);
}
 
-   ret = cnl_verify_procmon_ref_values(dev_priv, phy);
-
if (phy_is_master(dev_priv, phy)) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy),
 IREFGEN, IREFGEN);
-- 
2.18.1

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


Re: [PATCH v4 1/2] dt-bindings: display: himax, hx8837: Add Himax HX8837 bindings

2020-08-25 Thread Rob Herring
On Wed, 19 Aug 2020 12:22:45 +0200, Lubomir Rintel wrote:
> Himax HX8837 is a secondary display controller used to drive the panel
> on OLPC platforms.
> 
> Signed-off-by: Lubomir Rintel 
> 
> ---
> Changes since v3:
> - Moved to bindings/display/
> - Added the ports
> - Converted to YAML
> - Removed Pavel's Ack, because the changes are substantial
> 
> Changes since v2:
> - s/betweend/between/
> 
> Changes since v1:
> - s/load-gpio/load-gpios/
> - Use interrupt bindings instead of gpio for the IRQ
> 
>  .../bindings/display/bridge/himax,hx8837.yaml | 96 +++
>  1 file changed, 96 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/bridge/himax,hx8837.yaml
> 

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


Re: [PATCH 1/2] dt-bindings: display: simple: add Innolux LS075AT011

2020-08-25 Thread Rob Herring
On Wed, 19 Aug 2020 12:12:05 +0200, Lubomir Rintel wrote:
> Add the Innolux LS075AT011 7.5" (1200x900) color/reflective LCD panel to
> the panel-simple compatible list. This panel is used in the OLPC laptops.
> 
> Signed-off-by: Lubomir Rintel 
> ---
>  .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

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


Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output

2020-08-25 Thread Stefan Wahren
Hi Maxime,

Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> Hi Stefan,
>
> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>> Hi,
>>>
>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
 On Wed, 8 Jul 2020 at 18:43, Maxime Ripard  wrote:
> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> the HVS and the PV, we need to add some delay after disabling the PV 
> output
> and before disabling the HDMI controller. 20ms seems to be good enough so
> let's use that.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c 
> b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d0b326e1df0a..7b178d67187f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc 
> *crtc,
> ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +   mdelay(20);
 mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
 not msleep instead?
>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>> solution since there's definitely some chance you overshoot and end up
>>> with a higher time than the one you targeted.
>> usleep_range(min, max) isn't a solution?
> My understanding of usleep_range was that you can still overshoot, even
> though it's backed by an HR timer so the resolution is not a jiffy. Are
> we certain that we're going to be in that range?

you are right there is no guarantee about the upper wake up time.

And it's not worth the effort to poll the FIFO state until its empty
(using 20 ms as timeout)?

>
> Maxime
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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


[PATCH v6.5 14/14] drm/print: Add tracefs support to the drm logging helpers

2020-08-25 Thread Sean Paul
From: Sean Paul 

This patch adds a new module parameter called drm.trace which accepts
the same mask as drm.debug. When a debug category is enabled, log
messages will be put in a new tracefs instance called drm for
consumption.

Using the new tracefs instance will allow distros to enable drm logging
in production without impacting performance or spamming the system
logs.

Cc: Daniel Vetter 
Cc: David Airlie 
Cc: Jani Nikula 
Cc: Joonas Lahtinen 
Cc: Pekka Paalanen 
Cc: Rob Clark 
Cc: Steven Rostedt 
Cc: Thomas Zimmermann 
Cc: Ville Syrjälä 
Cc: Chris Wilson 
Cc: Steven Rostedt 
Reported-by: kernel test robot  # warning reported in v6
Acked-by: Pekka Paalanen 
Signed-off-by: Sean Paul 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20191010204823.195540-1-s...@poorly.run
 #v1
Link: 
https://lists.freedesktop.org/archives/dri-devel/2019-November/243230.html #v2
Link: 
https://patchwork.freedesktop.org/patch/msgid/20191212203301.142437-1-s...@poorly.run
 #v3
Link: 
https://patchwork.freedesktop.org/patch/msgid/20200114172155.215463-1-s...@poorly.run
 #v4
Link: 
https://patchwork.freedesktop.org/patch/msgid/20200608210505.48519-14-s...@poorly.run
 #v5
Link: 
https://patchwork.freedesktop.org/patch/msgid/20200818210510.49730-15-s...@poorly.run
 #v6

Changes in v5:
-Re-write to use trace_array and the tracefs instance support
Changes in v6:
-Use the new trace_array_init_printk() to initialize global trace
 buffers
Changes in v6.5:
-Fix kernel test robot warning
-Add a trace printf in __drm_err
---
 Documentation/gpu/drm-uapi.rst |   6 +
 drivers/gpu/drm/drm_drv.c  |   3 +
 drivers/gpu/drm/drm_print.c| 223 -
 include/drm/drm_print.h|  63 --
 4 files changed, 255 insertions(+), 40 deletions(-)

diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 7dce175f6d75..0297ff71f8f8 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -424,6 +424,12 @@ Debugfs Support
 .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
:export:
 
+DRM Tracing
+---
+
+.. kernel-doc:: drivers/gpu/drm/drm_print.c
+   :doc: DRM Tracing
+
 Sysfs Support
 =
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 13068fdf4331..555b40580497 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -1107,12 +1107,15 @@ static void drm_core_exit(void)
drm_sysfs_destroy();
idr_destroy(&drm_minors_idr);
drm_connector_ida_destroy();
+   drm_trace_cleanup();
 }
 
 static int __init drm_core_init(void)
 {
int ret;
 
+   drm_trace_init();
+
drm_connector_ida_init();
idr_init(&drm_minors_idr);
 
diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 4d984a01b3a3..64d9a724c2df 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -43,17 +44,34 @@
 unsigned int __drm_debug_syslog;
 EXPORT_SYMBOL(__drm_debug_syslog);
 
-MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug 
category.\n"
-"\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n"
-"\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n"
-"\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n"
-"\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n"
-"\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n"
-"\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n"
-"\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n"
-"\t\tBit 8 (0x100) will enable DP messages (displayport code)");
+/*
+ * __drm_debug_trace: Enable debug output in drm tracing instance.
+ * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
+ */
+unsigned int __drm_debug_trace;
+EXPORT_SYMBOL(__drm_debug_trace);
+
+#define DEBUG_PARM_DESC(dst) \
+"Enable debug output to " dst ", where each bit enables a debug category.\n" \
+"\t\tBit 0 (0x01)  will enable CORE messages (drm core code)\n" \
+"\t\tBit 1 (0x02)  will enable DRIVER messages (drm controller code)\n" \
+"\t\tBit 2 (0x04)  will enable KMS messages (modesetting code)\n" \
+"\t\tBit 3 (0x08)  will enable PRIME messages (prime code)\n" \
+"\t\tBit 4 (0x10)  will enable ATOMIC messages (atomic code)\n" \
+"\t\tBit 5 (0x20)  will enable VBL messages (vblank code)\n" \
+"\t\tBit 7 (0x80)  will enable LEASE messages (leasing code)\n" \
+"\t\tBit 8 (0x100) will enable DP messages (displayport code)"
+
+MODULE_PARM_DESC(debug, DEBUG_PARM_DESC("syslog"));
 module_param_named(debug, __drm_debug_syslog, int, 0600);
 
+MODULE_PARM_DESC(trace, DEBUG_PARM_DESC("tracefs"));
+module_param_named(trace, __drm_debug_trace, int, 0600);
+
+#ifdef CONFIG_TRACING
+struct trace_array *trace_arr;
+#endif
+
 void __drm_puts_coredump(struct drm_printer *p, const char *str)
 {
struct drm_print_iterator *iterator = p->arg;
@@ -166,6 +184,2

Re: [PATCH 00/49] DRM driver for Hikey 970

2020-08-25 Thread Sam Ravnborg
Hi Mauro.

Laurent and I discussed this driver a little on irc.
Some highlights:

This parts could use register names:
+   writel(0x2, noc_dss_base + 0xc);
+   writel(0x2, noc_dss_base + 0x8c);
+   writel(0x2, noc_dss_base + 0x10c);
+   writel(0x2, noc_dss_base + 0x18c);

The two nodes in the DT for DPE and DSI uses overlapping range for reg
entries. It looks like a syscon node or some iommu thing is needed to do
this properly.

The chain will lok like this:

DPE -> DSI -> video mux -> {adv7533, panel}

But drm_bridge has not yet support for such non-linear setup.
The recommendation is to focus on the HDMI prat. Then we can later
come up with support for a video mux.

The video mux should have a dedicated node with one input node and two
output nodes. Which is also where the gpio should be.

The DSI node references two DPHY instances - should it be PHY driver(s)?

Does the DSI part contain one or two instances. Clocks looks duplicated.

Does the DPE and DSI share a lot of register blocks - or does it just
look like this from a first point of view?

You can read though the logs here:
https://people.freedesktop.org/~cbrill/dri-log/index.php

Could you please try to get back on some of the points above so we can
help you move forward in the right direction.

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


[RFC v4 19/20] drm/i915/dp: Extract drm_dp_read_dpcd_caps()

2020-08-25 Thread Lyude Paul
Since DP 1.3, it's been possible for DP receivers to specify an
additional set of DPCD capabilities, which can take precedence over the
capabilities reported at DP_DPCD_REV.

Basically any device supporting DP is going to need to read these in an
identical manner, in particular nouveau, so let's go ahead and just move
this code out of i915 into a shared DRM DP helper that we can use in
other drivers.

v2:
* Remove redundant dpcd[DP_DPCD_REV] == 0 check
* Fix drm_dp_dpcd_read() ret checks

Signed-off-by: Lyude Paul 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/drm_dp_helper.c | 77 +
 drivers/gpu/drm/i915/display/intel_dp.c | 60 +---
 drivers/gpu/drm/i915/display/intel_dp.h |  1 -
 drivers/gpu/drm/i915/display/intel_lspcon.c |  2 +-
 include/drm/drm_dp_helper.h |  3 +
 5 files changed, 83 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 67ad05eb05b7e..9c99d21b42c15 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -433,6 +433,83 @@ static u8 drm_dp_downstream_port_count(const u8 
dpcd[DP_RECEIVER_CAP_SIZE])
return port_count;
 }
 
+static int drm_dp_read_extended_dpcd_caps(struct drm_dp_aux *aux,
+ u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   u8 dpcd_ext[6];
+   int ret;
+
+   /*
+* Prior to DP1.3 the bit represented by
+* DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
+* If it is set DP_DPCD_REV at h could be at a value less than
+* the true capability of the panel. The only way to check is to
+* then compare h and 2200h.
+*/
+   if (!(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+ DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
+   return 0;
+
+   ret = drm_dp_dpcd_read(aux, DP_DP13_DPCD_REV, &dpcd_ext,
+  sizeof(dpcd_ext));
+   if (ret < 0)
+   return ret;
+   if (ret != sizeof(dpcd_ext))
+   return -EIO;
+
+   if (dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
+   DRM_DEBUG_KMS("%s: Extended DPCD rev less than base DPCD rev 
(%d > %d)\n",
+ aux->name, dpcd[DP_DPCD_REV],
+ dpcd_ext[DP_DPCD_REV]);
+   return 0;
+   }
+
+   if (!memcmp(dpcd, dpcd_ext, sizeof(dpcd_ext)))
+   return 0;
+
+   DRM_DEBUG_KMS("%s: Base DPCD: %*ph\n",
+ aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
+
+   memcpy(dpcd, dpcd_ext, sizeof(dpcd_ext));
+
+   return 0;
+}
+
+/**
+ * drm_dp_read_dpcd_caps() - read DPCD caps and extended DPCD caps if
+ * available
+ * @aux: DisplayPort AUX channel
+ * @dpcd: Buffer to store the resulting DPCD in
+ *
+ * Attempts to read the base DPCD caps for @aux. Additionally, this function
+ * checks for and reads the extended DPRX caps (%DP_DP13_DPCD_REV) if
+ * present.
+ *
+ * Returns: %0 if the DPCD was read successfully, negative error code
+ * otherwise.
+ */
+int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
+ u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   int ret;
+
+   ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
+   if (ret < 0)
+   return ret;
+   if (ret != DP_RECEIVER_CAP_SIZE || dpcd[DP_DPCD_REV] == 0)
+   return -EIO;
+
+   ret = drm_dp_read_extended_dpcd_caps(aux, dpcd);
+   if (ret < 0)
+   return ret;
+
+   DRM_DEBUG_KMS("%s: DPCD: %*ph\n",
+ aux->name, DP_RECEIVER_CAP_SIZE, dpcd);
+
+   return ret;
+}
+EXPORT_SYMBOL(drm_dp_read_dpcd_caps);
+
 /**
  * drm_dp_downstream_read_info() - read DPCD downstream port info if available
  * @aux: DisplayPort AUX channel
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 4337321a3be4f..fb7872e2a0b93 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4449,62 +4449,6 @@ intel_dp_link_down(struct intel_encoder *encoder,
}
 }
 
-static void
-intel_dp_extended_receiver_capabilities(struct intel_dp *intel_dp)
-{
-   struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-   u8 dpcd_ext[6];
-
-   /*
-* Prior to DP1.3 the bit represented by
-* DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
-* if it is set DP_DPCD_REV at h could be at a value less than
-* the true capability of the panel. The only way to check is to
-* then compare h and 2200h.
-*/
-   if (!(intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
- DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
-   return;
-
-   if (drm_dp_dpcd_read(&intel_dp->aux, DP_DP13_DPCD_REV,
-&dpcd_ext, sizeof(dpcd_ext)) != sizeof(dpcd_ext)) {
-   drm_err(&i915->drm,
- 

[RFC v4 13/20] drm/i915/dp: Extract drm_dp_downstream_read_info()

2020-08-25 Thread Lyude Paul
We're going to be doing the same probing process in nouveau for
determining downstream DP port capabilities, so let's deduplicate the
work by moving i915's code for handling this into a shared helper:
drm_dp_downstream_read_info().

Note that when we do this, we also do make some functional changes while
we're at it:
* We always clear the downstream port info before trying to read it,
  just to make things easier for the caller
* We skip reading downstream port info if the DPCD indicates that we
  don't support downstream port info
* We only read as many bytes as needed for the reported number of
  downstream ports, no sense in reading the whole thing every time

v2:
* Fixup logic for calculating the downstream port length to account for
  the fact that downstream port caps can be either 1 byte or 4 bytes
  long. We can actually skip fixing the max_clock/max_bpc helpers here
  since they all check for DP_DETAILED_CAP_INFO_AVAILABLE anyway.
* Fix ret code check for drm_dp_dpcd_read

Reviewed-by: Sean Paul 
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/drm_dp_helper.c | 46 +
 drivers/gpu/drm/i915/display/intel_dp.c | 14 ++--
 include/drm/drm_dp_helper.h |  3 ++
 3 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 4c21cf69dad5a..4f845995f1f66 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -423,6 +423,52 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_send_real_edid_checksum);
 
+static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   u8 port_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_PORT_COUNT_MASK;
+
+   if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE && 
port_count > 4)
+   port_count = 4;
+
+   return port_count;
+}
+
+/**
+ * drm_dp_downstream_read_info() - read DPCD downstream port info if available
+ * @aux: DisplayPort AUX channel
+ * @dpcd: A cached copy of the port's DPCD
+ * @downstream_ports: buffer to store the downstream port info in
+ *
+ * Returns: 0 if either the downstream port info was read successfully or
+ * there was no downstream info to read, or a negative error code otherwise.
+ */
+int drm_dp_downstream_read_info(struct drm_dp_aux *aux,
+   const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+   u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS])
+{
+   int ret;
+   u8 len;
+
+   memset(downstream_ports, 0, DP_MAX_DOWNSTREAM_PORTS);
+
+   /* No downstream info to read */
+   if (!drm_dp_is_branch(dpcd) ||
+   dpcd[DP_DPCD_REV] < DP_DPCD_REV_10 ||
+   !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+   return 0;
+
+   len = drm_dp_downstream_port_count(dpcd);
+   if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE)
+   len *= 4;
+
+   ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, 
len);
+   if (ret < 0)
+   return ret;
+
+   return ret == len ? 0 : -EIO;
+}
+EXPORT_SYMBOL(drm_dp_downstream_read_info);
+
 /**
  * drm_dp_downstream_max_clock() - extract branch device max
  * pixel rate for legacy VGA
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 1e29d3a012856..984e49194ca31 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4685,18 +4685,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
return false;
}
 
-   if (!drm_dp_is_branch(intel_dp->dpcd))
-   return true; /* native DP sink */
-
-   if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
-   return true; /* no per-port downstream info */
-
-   if (drm_dp_dpcd_read(&intel_dp->aux, DP_DOWNSTREAM_PORT_0,
-intel_dp->downstream_ports,
-DP_MAX_DOWNSTREAM_PORTS) < 0)
-   return false; /* downstream port status fetch failed */
-
-   return true;
+   return drm_dp_downstream_read_info(&intel_dp->aux, intel_dp->dpcd,
+  intel_dp->downstream_ports) == 0;
 }
 
 static bool
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 5c28199248626..1349f16564ace 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1613,6 +1613,9 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
u8 real_edid_checksum);
 
+int drm_dp_downstream_read_info(struct drm_dp_aux *aux,
+   const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+   u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]);
 int drm_dp_downstream_max_cl

[RFC v4 12/20] drm/nouveau/kms: Only use hpd_work for reprobing in HPD paths

2020-08-25 Thread Lyude Paul
Currently we perform both short IRQ handling for DP, and connector
reprobing in the HPD IRQ handler. However since we need to grab
connection_mutex in order to reprobe a connector, in theory we could
accidentally block ourselves from handling any short IRQs until after a
modeset completes if a connector hotplug happens to occur in parallel
with a modeset.

I haven't seen this actually happen yet, but since we're cleaning up
nouveau's hotplug handling code anyway and we already have a hpd worker,
we can simply fix this by only relying on the HPD worker to actually
reprobe connectors when we receive a HPD IRQ. We also add a mask to
nouveau_drm to keep track of which connectors are waiting to be reprobed
in response to an HPD IRQ.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 42 +
 drivers/gpu/drm/nouveau/nouveau_connector.h |  1 +
 drivers/gpu/drm/nouveau/nouveau_display.c   | 70 ++---
 drivers/gpu/drm/nouveau/nouveau_display.h   |  1 +
 drivers/gpu/drm/nouveau/nouveau_dp.c|  2 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   |  4 +-
 drivers/gpu/drm/nouveau/nouveau_drv.h   |  2 +
 7 files changed, 86 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 4a29f691c08e4..637e91594fbe8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1138,6 +1138,20 @@ nouveau_connector_funcs_lvds = {
.early_unregister = nouveau_connector_early_unregister,
 };
 
+void
+nouveau_connector_hpd(struct drm_connector *connector)
+{
+   struct nouveau_drm *drm = nouveau_drm(connector->dev);
+   u32 mask = drm_connector_mask(connector);
+
+   mutex_lock(&drm->hpd_lock);
+   if (!(drm->hpd_pending & mask)) {
+   drm->hpd_pending |= mask;
+   schedule_work(&drm->hpd_work);
+   }
+   mutex_unlock(&drm->hpd_lock);
+}
+
 static int
 nouveau_connector_hotplug(struct nvif_notify *notify)
 {
@@ -1147,8 +1161,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
-   const char *name = connector->name;
-   int ret;
bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
 
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
@@ -1156,31 +1168,9 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
return NVIF_NOTIFY_KEEP;
}
 
-   ret = pm_runtime_get(drm->dev->dev);
-   if (ret == 0) {
-   /* We can't block here if there's a pending PM request
-* running, as we'll deadlock nouveau_display_fini() when it
-* calls nvif_put() on our nvif_notify struct. So, simply
-* defer the hotplug event until the device finishes resuming
-*/
-   NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n",
-name);
-   schedule_work(&drm->hpd_work);
-
-   pm_runtime_put_noidle(drm->dev->dev);
-   return NVIF_NOTIFY_KEEP;
-   } else if (ret != 1 && ret != -EACCES) {
-   NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n",
-   name, ret);
-   return NVIF_NOTIFY_DROP;
-   }
-
-   NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
-
-   drm_helper_hpd_irq_event(connector->dev);
+   NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name);
+   nouveau_connector_hpd(connector);
 
-   pm_runtime_mark_last_busy(drm->dev->dev);
-   pm_runtime_put_autosuspend(drm->dev->dev);
return NVIF_NOTIFY_KEEP;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h 
b/drivers/gpu/drm/nouveau/nouveau_connector.h
index d6de5cb8e2238..d0b859c4a80ea 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -187,6 +187,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
 
 struct drm_connector *
 nouveau_connector_create(struct drm_device *, const struct dcb_output *);
+void nouveau_connector_hpd(struct drm_connector *connector);
 
 extern int nouveau_tv_disable;
 extern int nouveau_ignorelid;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 13016769a194b..bceb48a2dfca6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -457,16 +457,70 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = 
{
}  \
 } while(0)
 
+void
+nouveau_display_hpd_resume(struct drm_device *dev)
+{
+   struct nouveau_drm *drm = nouveau_drm(dev);
+
+   mutex_lock(&drm->hpd_lock);
+   

[RFC v4 14/20] drm/nouveau/kms/nv50-: Use downstream DP clock limits for mode validation

2020-08-25 Thread Lyude Paul
This adds support for querying the maximum clock rate of a downstream
port on a DisplayPort connection. Generally, downstream ports refer to
active dongles which can have their own pixel clock limits.

Note as well, we also start marking the connector as disconnected if we
can't read the DPCD, since we wouldn't be able to do anything without
DPCD access anyway.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  3 +++
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 15 +++
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  1 +
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 8e1effb10425d..d2141ca16107b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1258,7 +1258,10 @@ nv50_mstc_detect(struct drm_connector *connector,
 
ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr,
 mstc->port);
+   if (ret != connector_status_connected)
+   goto out;
 
+out:
pm_runtime_mark_last_busy(connector->dev->dev);
pm_runtime_put_autosuspend(connector->dev->dev);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 71d095409c90d..c200f197083f9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -61,6 +61,11 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector,
mstm->can_mst = drm_dp_has_mst(aux, dpcd);
}
 
+   ret = drm_dp_downstream_read_info(aux, dpcd,
+ outp->dp.downstream_ports);
+   if (ret < 0)
+   return connector_status_disconnected;
+
return connector_status_connected;
 }
 
@@ -176,8 +181,6 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
 /* TODO:
  * - Use the minimum possible BPC here, once we add support for the max bpc
  *   property.
- * - Validate the mode against downstream port caps (see
- *   drm_dp_downstream_max_clock())
  * - Validate against the DP caps advertised by the GPU (we don't check these
  *   yet)
  */
@@ -188,15 +191,19 @@ nv50_dp_mode_valid(struct drm_connector *connector,
   unsigned *out_clock)
 {
const unsigned min_clock = 25000;
-   unsigned max_clock, clock;
+   unsigned max_clock, ds_clock, clock;
enum drm_mode_status ret;
 
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
return MODE_NO_INTERLACE;
 
max_clock = outp->dp.link_nr * outp->dp.link_bw;
-   clock = mode->clock * (connector->display_info.bpc * 3) / 10;
+   ds_clock = drm_dp_downstream_max_clock(outp->dp.dpcd,
+  outp->dp.downstream_ports);
+   if (ds_clock)
+   max_clock = min(max_clock, ds_clock);
 
+   clock = mode->clock * (connector->display_info.bpc * 3) / 10;
ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
&clock);
if (out_clock)
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index eef4643f5f982..c1924a4529a7b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -72,6 +72,7 @@ struct nouveau_encoder {
struct mutex hpd_irq_lock;
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
+   u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct drm_dp_desc desc;
} dp;
};
-- 
2.26.2

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


[RFC v4 16/20] drm/i915/dp: Extract drm_dp_get_sink_count()

2020-08-25 Thread Lyude Paul
And of course, we'll also need to read the sink count from other drivers
as well if we're checking whether or not it's supported. So, let's
extract the code for this into another helper.

v2:
* Fix drm_dp_dpcd_readb() ret check
* Add back comment and move back sink_count assignment in intel_dp_get_dpcd()

Signed-off-by: Lyude Paul 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/drm_dp_helper.c | 22 ++
 drivers/gpu/drm/i915/display/intel_dp.c | 11 +--
 include/drm/drm_dp_helper.h |  1 +
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 863e0babc1903..67ad05eb05b7e 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -736,6 +736,28 @@ bool drm_dp_has_sink_count(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_dp_has_sink_count);
 
+/**
+ * drm_dp_get_sink_count() - Retrieve the sink count for a given sink
+ * @aux: The DP AUX channel to use
+ *
+ * Returns: The current sink count reported by @aux, or a negative error code
+ * otherwise.
+ */
+int drm_dp_get_sink_count(struct drm_dp_aux *aux)
+{
+   u8 count;
+   int ret;
+
+   ret = drm_dp_dpcd_readb(aux, DP_SINK_COUNT, &count);
+   if (ret < 0)
+   return ret;
+   if (ret != 1)
+   return -EIO;
+
+   return DP_GET_SINK_COUNT(count);
+}
+EXPORT_SYMBOL(drm_dp_get_sink_count);
+
 /*
  * I2C-over-AUX implementation
  */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 35a4779a442e2..4337321a3be4f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4648,6 +4648,8 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp)
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
+   int ret;
+
if (!intel_dp_read_dpcd(intel_dp))
return false;
 
@@ -4664,11 +4666,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
}
 
if (intel_dp_has_sink_count(intel_dp)) {
-   u8 count;
-   ssize_t r;
-
-   r = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_COUNT, &count);
-   if (r < 1)
+   ret = drm_dp_get_sink_count(&intel_dp->aux);
+   if (ret < 0)
return false;
 
/*
@@ -4676,7 +4675,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 * a member variable in intel_dp will track any changes
 * between short pulse interrupts.
 */
-   intel_dp->sink_count = DP_GET_SINK_COUNT(count);
+   intel_dp->sink_count = ret;
 
/*
 * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index a1413a531eaf4..0c141fc81aaa8 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1635,6 +1635,7 @@ struct drm_dp_desc;
 bool drm_dp_has_sink_count(struct drm_connector *connector,
   const u8 dpcd[DP_RECEIVER_CAP_SIZE],
   const struct drm_dp_desc *desc);
+int drm_dp_get_sink_count(struct drm_dp_aux *aux);
 
 void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
 void drm_dp_aux_init(struct drm_dp_aux *aux);
-- 
2.26.2

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


[RFC v4 08/20] drm/nouveau/kms/nv50-: Refactor and cleanup DP HPD handling

2020-08-25 Thread Lyude Paul
First some backstory here: Currently, we keep track of whether or not
we've enabled MST or not by trying to piggy-back off the MST helpers.
This means that in order to check whether MST is enabled or not, we
actually need to grab drm_dp_mst_topology_mgr.lock.

Back when I originally wrote this, I did this piggy-backing with the
intention that I'd eventually be teaching our MST helpers how to recover
when an MST device has stopped responding, which in turn would require
the MST helpers having a way of disabling MST independently of the
driver. Note that this was before I reworked locking in the MST helpers,
so at the time we were sticking random things under &mgr->lock - which
grabbing this lock was meant to protect against.

This never came to fruition because doing such a reset safely turned out
to be a lot more painful and impossible then it sounds, and also just
risks us working around issues with our MST handlers that should be
properly fixed instead. Even if it did though, simply calling
drm_dp_mst_topology_mgr_set_mst() from the MST helpers (with the
exception of when we're tearing down our MST managers, that's always OK)
wouldn't have been a bad idea, since drivers like nouveau and i915 need
to do their own book keeping immediately after disabling MST.
So-implementing that would likely require adding a hook for
helper-triggered MST disables anyway.

So, fast forward to now - we want to start adding support for all of the
miscellaneous bits of the DP protocol (for both SST and MST) we're
missing before moving on to supporting more complicated features like
supporting different BPP values on MST, DSC, etc. Since many of these
features only exist on SST and make use of DP HPD IRQs, we want to be
able to atomically check whether we're servicing an MST IRQ or SST IRQ
in nouveau_connector_hotplug(). Currently we literally don't do this at
all, and just handle any kind of possible DP IRQ we could get including
ESIs - even if MST isn't actually enabled.

This would be very complicated and difficult to fix if we need to hold
&mgr->lock while handling SST IRQs to ensure that the MST topology
state doesn't change under us. What we really want here is to do our own
tracking of whether MST is enabled or not, similar to drivers like i915,
and define our own locking order to decomplicate things and avoid
hitting locking issues in the future.

So, let's do this by refactoring our MST probing/enabling code to use
our own MST bookkeeping, along with adding a lock for protecting DP
state that needs to be checked outside of our connector probing
functions. While we're at it, we also remove a bunch of unneeded steps
we perform when probing/enabling MST:

* Enabling bits in MSTM_CTRL before calling drm_dp_mst_topology_mgr_set_mst().
  I don't think these ever actually did anything, since the nvif methods
  for enabling MST don't actually do anything DPCD related and merely
  indicate to nvkm that we've turned on MST.
* Checking the MSTM_CTRL bit is intact when checking the state of an
  enabled MST topology in nv50_mstm_detect(). I just added this to be safe
  originally, but now that we try reading the DPCD when probing DP
  connectors it shouldn't be needed as that will abort our hotplug probing
  if the device was removed well before we start checking for MST..
* All of the duplicate DPCD version checks.

This leaves us with much nicer looking code, a much more sensible
locking scheme, and an easy way of checking whether MST is enabled or
not for handling DP HPD IRQs.

v2:
* Get rid of accidental newlines
v4:
* Fix uninitialized usage of mstm in nv50_mstm_detect() - thanks kernel
  bot!

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/dispnv04/disp.c |   6 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 192 +---
 drivers/gpu/drm/nouveau/nouveau_connector.c |  14 +-
 drivers/gpu/drm/nouveau/nouveau_display.c   |   2 +-
 drivers/gpu/drm/nouveau/nouveau_display.h   |   2 +-
 drivers/gpu/drm/nouveau/nouveau_dp.c| 132 --
 drivers/gpu/drm/nouveau/nouveau_encoder.h   |  33 +++-
 7 files changed, 244 insertions(+), 137 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c 
b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 3f046b917c85c..3ee836dc5058f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -54,8 +54,9 @@ nv04_encoder_get_connector(struct nouveau_encoder *encoder)
 }
 
 static void
-nv04_display_fini(struct drm_device *dev, bool suspend)
+nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend)
 {
+   struct nouveau_drm *drm = nouveau_drm(dev);
struct nv04_display *disp = nv04_display(dev);
struct drm_crtc *crtc;
 
@@ -67,6 +68,9 @@ nv04_display_fini(struct drm_device *dev, bool suspend)
if (nv_two_heads(dev))
NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0);
 
+   if (!runtime)
+   cancel_work_sync(&drm->hpd_work);

[RFC v4 09/20] drm/i915/dp: Extract drm_dp_has_mst()

2020-08-25 Thread Lyude Paul
Just a tiny drive-by cleanup, we can consolidate i915's code for
checking for MST support into a helper to be shared across drivers.

Signed-off-by: Lyude Paul 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 18 ++
 include/drm/drm_dp_mst_helper.h | 22 ++
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 79c27f91f42c0..1e29d3a012856 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4699,20 +4699,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
return true;
 }
 
-static bool
-intel_dp_sink_can_mst(struct intel_dp *intel_dp)
-{
-   u8 mstm_cap;
-
-   if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
-   return false;
-
-   if (drm_dp_dpcd_readb(&intel_dp->aux, DP_MSTM_CAP, &mstm_cap) != 1)
-   return false;
-
-   return mstm_cap & DP_MST_CAP;
-}
-
 static bool
 intel_dp_can_mst(struct intel_dp *intel_dp)
 {
@@ -4720,7 +4706,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp)
 
return i915->params.enable_dp_mst &&
intel_dp->can_mst &&
-   intel_dp_sink_can_mst(intel_dp);
+   drm_dp_has_mst(&intel_dp->aux, intel_dp->dpcd);
 }
 
 static void
@@ -4729,7 +4715,7 @@ intel_dp_configure_mst(struct intel_dp *intel_dp)
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_encoder *encoder =
&dp_to_dig_port(intel_dp)->base;
-   bool sink_can_mst = intel_dp_sink_can_mst(intel_dp);
+   bool sink_can_mst = drm_dp_has_mst(&intel_dp->aux, intel_dp->dpcd);
 
drm_dbg_kms(&i915->drm,
"[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: 
%s\n",
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 8b9eb4db3381c..2d8983a713e8c 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -911,4 +911,26 @@ __drm_dp_mst_state_iter_get(struct drm_atomic_state *state,
for ((__i) = 0; (__i) < (__state)->num_private_objs; (__i)++) \
for_each_if(__drm_dp_mst_state_iter_get((__state), &(mgr), 
NULL, &(new_state), (__i)))
 
+/**
+ * drm_dp_has_mst() - check whether or not a sink supports MST
+ * @aux: The DP AUX channel to use
+ * @dpcd: A cached copy of the DPCD capabilities for this sink
+ *
+ * Returns: %True if the sink supports MST, %false otherwise
+ */
+static inline bool
+drm_dp_has_mst(struct drm_dp_aux *aux,
+  const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+   u8 mstm_cap;
+
+   if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12)
+   return false;
+
+   if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1)
+   return false;
+
+   return !!(mstm_cap & DP_MST_CAP);
+}
+
 #endif
-- 
2.26.2

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


[RFC v4 18/20] drm/nouveau/kms: Don't change EDID when it hasn't actually changed

2020-08-25 Thread Lyude Paul
Currently in nouveau_connector_ddc_detect() and
nouveau_connector_detect_lvds(), we start the connector probing process
by releasing the previous EDID and informing DRM of the change. However,
since commit 5186421cbfe2 ("drm: Introduce epoch counter to
drm_connector") drm_connector_update_edid_property() actually checks
whether the new EDID we've specified is different from the previous one,
and updates the connector's epoch accordingly if it is. But, because we
always set the EDID to NULL first in nouveau_connector_ddc_detect() and
nouveau_connector_detect_lvds() we end up making DRM think that the EDID
changes every single time we do a connector probe - which isn't needed.

So, let's fix this by not clearing the EDID at the start of the
connector probing process, and instead simply changing or removing it
once near the end of the probing process. This will help prevent us from
sending unneeded hotplug events to userspace when nothing has actually
changed.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 54 ++---
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 637e91594fbe8..49dd0cbc332ff 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -528,6 +528,17 @@ nouveau_connector_set_encoder(struct drm_connector 
*connector,
}
 }
 
+static void
+nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
+  struct edid *edid)
+{
+   struct edid *old_edid = nv_connector->edid;
+
+   drm_connector_update_edid_property(&nv_connector->base, edid);
+   kfree(old_edid);
+   nv_connector->edid = edid;
+}
+
 static enum drm_connector_status
 nouveau_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -541,13 +552,6 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
int ret;
enum drm_connector_status conn_status = connector_status_disconnected;
 
-   /* Cleanup the previous EDID block. */
-   if (nv_connector->edid) {
-   drm_connector_update_edid_property(connector, NULL);
-   kfree(nv_connector->edid);
-   nv_connector->edid = NULL;
-   }
-
/* Outputs are only polled while runtime active, so resuming the
 * device here is unnecessary (and would deadlock upon runtime suspend
 * because it waits for polling to finish). We do however, want to
@@ -560,22 +564,23 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
ret = pm_runtime_get_sync(dev->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_put_autosuspend(dev->dev);
+   nouveau_connector_set_edid(nv_connector, NULL);
return conn_status;
}
}
 
nv_encoder = nouveau_connector_ddc_detect(connector);
if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
+   struct edid *new_edid;
+
if ((vga_switcheroo_handler_flags() &
 VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
nv_connector->type == DCB_CONNECTOR_LVDS)
-   nv_connector->edid = drm_get_edid_switcheroo(connector,
-i2c);
+   new_edid = drm_get_edid_switcheroo(connector, i2c);
else
-   nv_connector->edid = drm_get_edid(connector, i2c);
+   new_edid = drm_get_edid(connector, i2c);
 
-   drm_connector_update_edid_property(connector,
-   nv_connector->edid);
+   nouveau_connector_set_edid(nv_connector, new_edid);
if (!nv_connector->edid) {
NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
 connector->name);
@@ -609,6 +614,8 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
conn_status = connector_status_connected;
drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid);
goto out;
+   } else {
+   nouveau_connector_set_edid(nv_connector, NULL);
}
 
nv_encoder = nouveau_connector_of_detect(connector);
@@ -652,18 +659,12 @@ nouveau_connector_detect_lvds(struct drm_connector 
*connector, bool force)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
+   struct edid *edid = NULL;
enum drm_connector_status status = connector_status_disconnected;
 
-   /* Cleanup the previous EDID block. */
-   if (nv_connector->edid) {
-   drm_

[RFC v4 20/20] drm/nouveau/kms: Start using drm_dp_read_dpcd_caps()

2020-08-25 Thread Lyude Paul
Now that we've extracted i915's code for reading both the normal DPCD
caps and extended DPCD caps into a shared helper, let's start using this
in nouveau to enable us to start checking extended DPCD caps for free.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 89afc97ee2591..271a0a863a0e1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -55,15 +55,13 @@ nouveau_dp_probe_dpcd(struct nouveau_connector 
*nv_connector,
int ret;
u8 *dpcd = outp->dp.dpcd;
 
-   ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
-   if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) {
-   ret = drm_dp_read_desc(aux, &outp->dp.desc,
-  drm_dp_is_branch(dpcd));
-   if (ret < 0)
-   goto out;
-   } else {
+   ret = drm_dp_read_dpcd_caps(aux, dpcd);
+   if (ret < 0)
+   goto out;
+
+   ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd));
+   if (ret < 0)
goto out;
-   }
 
if (nouveau_mst) {
mstm = outp->dp.mstm;
-- 
2.26.2

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


[RFC v4 11/20] drm/nouveau/kms: Move drm_dp_cec_unset_edid() into nouveau_connector_detect()

2020-08-25 Thread Lyude Paul
For whatever reason we currently unset the EDID for DP CEC support when
responding to the connector being unplugged, instead of just doing it in
nouveau_connector_detect() where we set the CEC EDID. This isn't really
needed and could even potentially cause us to forget to unset the EDID
if the connector is removed without a corresponding hpd event, so let's
fix that.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index b90591114faaf..4a29f691c08e4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -633,10 +633,11 @@ nouveau_connector_detect(struct drm_connector *connector, 
bool force)
conn_status = connector_status_connected;
goto out;
}
-
}
 
  out:
+   if (!nv_connector->edid)
+   drm_dp_cec_unset_edid(&nv_connector->aux);
 
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
@@ -1174,8 +1175,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
return NVIF_NOTIFY_DROP;
}
 
-   if (!plugged)
-   drm_dp_cec_unset_edid(&nv_connector->aux);
NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
 
drm_helper_hpd_irq_event(connector->dev);
-- 
2.26.2

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


[RFC v4 04/20] drm/nouveau/kms/nv50-: Use macros for DP registers in nouveau_dp.c

2020-08-25 Thread Lyude Paul
No functional changes.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 8db9216d52c69..4030806e3522b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -50,11 +50,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
if (ret != sizeof(dpcd))
return ret;
 
-   nv_encoder->dp.link_bw = 27000 * dpcd[1];
-   nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
+   nv_encoder->dp.link_bw = 27000 * dpcd[DP_MAX_LINK_RATE];
+   nv_encoder->dp.link_nr =
+   dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
 
NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
-nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
+nv_encoder->dp.link_nr, nv_encoder->dp.link_bw,
+dpcd[DP_DPCD_REV]);
NV_DEBUG(drm, "encoder: %dx%d\n",
 nv_encoder->dcb->dpconf.link_nr,
 nv_encoder->dcb->dpconf.link_bw);
-- 
2.26.2

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


[RFC v4 15/20] drm/i915/dp: Extract drm_dp_has_sink_count()

2020-08-25 Thread Lyude Paul
Since other drivers are also going to need to be aware of the sink count
in order to do proper dongle detection, we might as well steal i915's
DP_SINK_COUNT helpers and move them into DRM helpers so that other
dirvers can use them as well.

Note that this also starts using intel_dp_has_sink_count() in
intel_dp_detect_dpcd(), which is a functional change.

Signed-off-by: Lyude Paul 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/drm_dp_helper.c | 22 ++
 drivers/gpu/drm/i915/display/intel_dp.c | 21 -
 include/drm/drm_dp_helper.h |  8 +++-
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 4f845995f1f66..863e0babc1903 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -714,6 +714,28 @@ void drm_dp_set_subconnector_property(struct drm_connector 
*connector,
 }
 EXPORT_SYMBOL(drm_dp_set_subconnector_property);
 
+/**
+ * drm_dp_has_sink_count() - Check whether a given connector has a valid sink
+ * count
+ * @connector: The DRM connector to check
+ * @dpcd: A cached copy of the connector's DPCD RX capabilities
+ * @desc: A cached copy of the connector's DP descriptor
+ *
+ * Returns: %True if the (e)DP connector has a valid sink count that should
+ * be probed, %false otherwise.
+ */
+bool drm_dp_has_sink_count(struct drm_connector *connector,
+  const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+  const struct drm_dp_desc *desc)
+{
+   /* Some eDP panels don't set a valid value for the sink count */
+   return connector->connector_type != DRM_MODE_CONNECTOR_eDP &&
+   dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 &&
+   dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT &&
+   !drm_dp_has_quirk(desc, 0, DP_DPCD_QUIRK_NO_SINK_COUNT);
+}
+EXPORT_SYMBOL(drm_dp_has_sink_count);
+
 /*
  * I2C-over-AUX implementation
  */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 984e49194ca31..35a4779a442e2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4634,6 +4634,16 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
return true;
 }
 
+static bool
+intel_dp_has_sink_count(struct intel_dp *intel_dp)
+{
+   if (!intel_dp->attached_connector)
+   return false;
+
+   return drm_dp_has_sink_count(&intel_dp->attached_connector->base,
+intel_dp->dpcd,
+&intel_dp->desc);
+}
 
 static bool
 intel_dp_get_dpcd(struct intel_dp *intel_dp)
@@ -4653,13 +4663,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
intel_dp_set_common_rates(intel_dp);
}
 
-   /*
-* Some eDP panels do not set a valid value for sink count, that is why
-* it don't care about read it here and in intel_edp_init_dpcd().
-*/
-   if (!intel_dp_is_edp(intel_dp) &&
-   !drm_dp_has_quirk(&intel_dp->desc, 0,
- DP_DPCD_QUIRK_NO_SINK_COUNT)) {
+   if (intel_dp_has_sink_count(intel_dp)) {
u8 count;
ssize_t r;
 
@@ -5939,9 +5943,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
return connector_status_connected;
 
/* If we're HPD-aware, SINK_COUNT changes dynamically */
-   if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+   if (intel_dp_has_sink_count(intel_dp) &&
intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
-
return intel_dp->sink_count ?
connector_status_connected : connector_status_disconnected;
}
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 1349f16564ace..a1413a531eaf4 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1631,6 +1631,11 @@ void drm_dp_set_subconnector_property(struct 
drm_connector *connector,
  const u8 *dpcd,
  const u8 port_cap[4]);
 
+struct drm_dp_desc;
+bool drm_dp_has_sink_count(struct drm_connector *connector,
+  const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+  const struct drm_dp_desc *desc);
+
 void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
 void drm_dp_aux_init(struct drm_dp_aux *aux);
 int drm_dp_aux_register(struct drm_dp_aux *aux);
@@ -1689,7 +1694,8 @@ enum drm_dp_quirk {
 * @DP_DPCD_QUIRK_NO_SINK_COUNT:
 *
 * The device does not set SINK_COUNT to a non-zero value.
-* The driver should ignore SINK_COUNT during detection.
+* The driver should ignore SINK_COUNT during detection. Note that
+* drm_dp_has_sink_count() automatically checks for this quirk.
 */
DP_DPCD_QUIRK_NO_SINK_COUNT,
/**
-- 
2.26.2

___

[RFC v4 17/20] drm/nouveau/kms/nv50-: Add support for DP_SINK_COUNT

2020-08-25 Thread Lyude Paul
This is another bit that we never implemented for nouveau: dongle
detection. When a "dongle", e.g. an active display adaptor, is hooked up
to the system and causes an HPD to be fired, we don't actually know
whether or not there's anything plugged into the dongle without checking
the sink count. As a result, plugging in a dongle without anything
plugged into it currently results in a bogus EDID retrieval error in the kernel 
log.

Additionally, most dongles won't send another long HPD signal if the
user suddenly plugs something in, they'll only send a short HPD IRQ with
the expectation that the source will check the sink count and reprobe
the connector if it's changed - something we don't actually do. As a
result, nothing will happen if the user plugs the dongle in before
plugging something into the dongle.

So, let's fix this by checking the sink count in both
nouveau_dp_probe_dpcd() and nouveau_dp_irq(), and reprobing the
connector if things change.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c  | 54 ---
 drivers/gpu/drm/nouveau/nouveau_encoder.h |  2 +
 2 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index c200f197083f9..89afc97ee2591 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -36,12 +36,22 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream 
(default: enabled)");
 static int nouveau_mst = 1;
 module_param_named(mst, nouveau_mst, int, 0400);
 
+static bool
+nouveau_dp_has_sink_count(struct drm_connector *connector,
+ struct nouveau_encoder *outp)
+{
+   return drm_dp_has_sink_count(connector, outp->dp.dpcd,
+&outp->dp.desc);
+}
+
 static enum drm_connector_status
 nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector,
  struct nouveau_encoder *outp)
 {
+   struct drm_connector *connector = &nv_connector->base;
struct drm_dp_aux *aux = &nv_connector->aux;
struct nv50_mstm *mstm = NULL;
+   enum drm_connector_status status = connector_status_disconnected;
int ret;
u8 *dpcd = outp->dp.dpcd;
 
@@ -50,9 +60,9 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector,
ret = drm_dp_read_desc(aux, &outp->dp.desc,
   drm_dp_is_branch(dpcd));
if (ret < 0)
-   return connector_status_disconnected;
+   goto out;
} else {
-   return connector_status_disconnected;
+   goto out;
}
 
if (nouveau_mst) {
@@ -61,12 +71,33 @@ nouveau_dp_probe_dpcd(struct nouveau_connector 
*nv_connector,
mstm->can_mst = drm_dp_has_mst(aux, dpcd);
}
 
+   if (nouveau_dp_has_sink_count(connector, outp)) {
+   ret = drm_dp_get_sink_count(aux);
+   if (ret < 0)
+   goto out;
+
+   outp->dp.sink_count = ret;
+
+   /*
+* Dongle connected, but no display. Don't bother reading
+* downstream port info
+*/
+   if (!outp->dp.sink_count)
+   return connector_status_disconnected;
+   }
+
ret = drm_dp_downstream_read_info(aux, dpcd,
  outp->dp.downstream_ports);
if (ret < 0)
-   return connector_status_disconnected;
+   goto out;
 
-   return connector_status_connected;
+   status = connector_status_connected;
+out:
+   if (status != connector_status_connected) {
+   /* Clear any cached info */
+   outp->dp.sink_count = 0;
+   }
+   return status;
 }
 
 int
@@ -159,6 +190,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
struct drm_connector *connector = &nv_connector->base;
struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
struct nv50_mstm *mstm;
+   int ret;
+   bool send_hpd = false;
 
if (!outp)
return;
@@ -170,12 +203,23 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
 
if (mstm && mstm->is_mst) {
if (!nv50_mstm_service(drm, nv_connector, mstm))
-   nouveau_connector_hpd(connector);
+   send_hpd = true;
} else {
drm_dp_cec_irq(&nv_connector->aux);
+
+   if (nouveau_dp_has_sink_count(connector, outp)) {
+   ret = drm_dp_get_sink_count(&nv_connector->aux);
+   if (ret != outp->dp.sink_count)
+   send_hpd = true;
+   if (ret >= 0)
+   outp->dp.sink_count = ret;
+   }
}
 
mutex_unlock(&outp->dp.hpd_irq_lock);
+
+   if (s

[RFC v4 10/20] drm/nouveau/kms: Use new drm_dp_has_mst() helper for checking MST caps

2020-08-25 Thread Lyude Paul
Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 16 +++-
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 032afc73e2a33..201c0b4335563 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -44,7 +44,6 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector,
struct nv50_mstm *mstm = NULL;
int ret;
u8 *dpcd = outp->dp.dpcd;
-   u8 tmp;
 
ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) {
@@ -56,19 +55,10 @@ nouveau_dp_probe_dpcd(struct nouveau_connector 
*nv_connector,
return connector_status_disconnected;
}
 
-   if (nouveau_mst)
+   if (nouveau_mst) {
mstm = outp->dp.mstm;
-
-   if (mstm) {
-   if (dpcd[DP_DPCD_REV] >= DP_DPCD_REV_12) {
-   ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &tmp);
-   if (ret < 0)
-   return connector_status_disconnected;
-
-   mstm->can_mst = !!(tmp & DP_MST_CAP);
-   } else {
-   mstm->can_mst = false;
-   }
+   if (mstm)
+   mstm->can_mst = drm_dp_has_mst(aux, dpcd);
}
 
return connector_status_connected;
-- 
2.26.2

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


[RFC v4 07/20] drm/nouveau/kms/nv50-: Use drm_dp_dpcd_(readb|writeb)() in nv50_sor_disable()

2020-08-25 Thread Lyude Paul
Just use drm_dp_dpcd_(readb|writeb)() so we get automatic DPCD logging

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 255a281249bc8..612d98fa0a2dc 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1630,19 +1630,22 @@ nv50_sor_disable(struct drm_encoder *encoder,
 {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
+   struct nouveau_connector *nv_connector =
+   nv50_outp_get_old_connector(nv_encoder, state);
 
nv_encoder->crtc = NULL;
 
if (nv_crtc) {
-   struct nvkm_i2c_aux *aux = nv_encoder->aux;
+   struct drm_dp_aux *aux = &nv_connector->aux;
u8 pwr;
 
-   if (aux) {
-   int ret = nvkm_rdaux(aux, DP_SET_POWER, &pwr, 1);
+   if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
+   int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr);
+
if (ret == 0) {
pwr &= ~DP_SET_POWER_MASK;
pwr |=  DP_SET_POWER_D3;
-   nvkm_wraux(aux, DP_SET_POWER, &pwr, 1);
+   drm_dp_dpcd_writeb(aux, DP_SET_POWER, pwr);
}
}
 
-- 
2.26.2

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


[RFC v4 03/20] drm/nouveau/kms/nv50-: Just use drm_dp_dpcd_read() in nouveau_dp.c

2020-08-25 Thread Lyude Paul
Since this actually logs accesses, we should probably always be using
this imho…

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index c4e9c21d4dd2b..8db9216d52c69 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -42,16 +42,12 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
 {
struct drm_device *dev = nv_encoder->base.base.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
-   struct nvkm_i2c_aux *aux;
-   u8 dpcd[8];
+   struct drm_dp_aux *aux = &nv_connector->aux;
+   u8 dpcd[DP_RECEIVER_CAP_SIZE];
int ret;
 
-   aux = nv_encoder->aux;
-   if (!aux)
-   return -ENODEV;
-
-   ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
-   if (ret)
+   ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE);
+   if (ret != sizeof(dpcd))
return ret;
 
nv_encoder->dp.link_bw = 27000 * dpcd[1];
-- 
2.26.2

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


[RFC v4 02/20] drm/nouveau/kms/nv50-: Remove open-coded drm_dp_read_desc()

2020-08-25 Thread Lyude Paul
Noticed this while going through our DP code - we use an open-coded
version of drm_dp_read_desc() instead of just using the helper, so
change that. This will also let us use quirks in the future if we end up
needing them.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c |  3 ++-
 drivers/gpu/drm/nouveau/nouveau_dp.c| 30 +++--
 drivers/gpu/drm/nouveau/nouveau_encoder.h   |  4 ++-
 3 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 7674025a4bfe8..e12957e6faa7c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -435,7 +435,8 @@ nouveau_connector_ddc_detect(struct drm_connector 
*connector)
 
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_DP:
-   ret = nouveau_dp_detect(nv_encoder);
+   ret = nouveau_dp_detect(nouveau_connector(connector),
+   nv_encoder);
if (ret == NOUVEAU_DP_MST)
return NULL;
else if (ret == NOUVEAU_DP_SST)
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index ee778ddc95fae..c4e9c21d4dd2b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -36,27 +36,9 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream 
(default: enabled)");
 static int nouveau_mst = 1;
 module_param_named(mst, nouveau_mst, int, 0400);
 
-static void
-nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 
*dpcd)
-{
-   struct nouveau_drm *drm = nouveau_drm(dev);
-   u8 buf[3];
-
-   if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
-   return;
-
-   if (!nvkm_rdaux(aux, DP_SINK_OUI, buf, 3))
-   NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n",
-buf[0], buf[1], buf[2]);
-
-   if (!nvkm_rdaux(aux, DP_BRANCH_OUI, buf, 3))
-   NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n",
-buf[0], buf[1], buf[2]);
-
-}
-
 int
-nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
+nouveau_dp_detect(struct nouveau_connector *nv_connector,
+ struct nouveau_encoder *nv_encoder)
 {
struct drm_device *dev = nv_encoder->base.base.dev;
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -89,7 +71,13 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
NV_DEBUG(drm, "maximum: %dx%d\n",
 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
-   nouveau_dp_probe_oui(dev, aux, dpcd);
+   ret = drm_dp_read_desc(&nv_connector->aux, &nv_encoder->dp.desc,
+  drm_dp_is_branch(dpcd));
+   if (ret) {
+   NV_ERROR(drm, "Failed to read DP descriptor on %s: %d\n",
+nv_connector->base.name, ret);
+   return ret;
+   }
 
ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst);
if (ret == 1)
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h 
b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index a72c412ac8b14..6424cdcb4913f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -33,6 +33,7 @@
 #include 
 #include "dispnv04/disp.h"
 struct nv50_head_atom;
+struct nouveau_connector;
 
 #define NV_DPMS_CLEARED 0x80
 
@@ -64,6 +65,7 @@ struct nouveau_encoder {
struct nv50_mstm *mstm;
int link_nr;
int link_bw;
+   struct drm_dp_desc desc;
} dp;
};
 
@@ -104,7 +106,7 @@ enum nouveau_dp_status {
NOUVEAU_DP_MST,
 };
 
-int nouveau_dp_detect(struct nouveau_encoder *);
+int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *);
 enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
struct nouveau_encoder *,
const struct drm_display_mode *,
-- 
2.26.2

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


[RFC v4 00/20] drm/dp, i915, nouveau: Cleanup nouveau HPD and add DP features from i915

2020-08-25 Thread Lyude Paul
Most of the reason I'm asking for an RFC here is because this
code pulls a lot of code out of i915 and into shared DP helpers.

Anyway-nouveau's HPD related code has been collecting dust for a while.
Other then the occasional runtime PM related and MST related fixes,
we're missing a lot of nice things that have been added to DRM since
this was originally written. Additionally, the code is just really
unoptimized in general:

* We handle connector probing in the same context that we handle short
  IRQs in for DP, which means connector probing could potentially block
  ESI handling for MST
* When we receive a hotplug event from a connector, we reprobe every
  single connector instead of just the connector that was hotplugged
* Additionally because of the above reason, combined with the fact I had
  the bad idea of reusing some of the MST locks when I last rewrote
  nouveau's DP MST detection, trying to handle any other events that
  require short HPD IRQs is a bit awkward to actually implement.
* We don't actually properly check whether EDIDs change or not when
  reprobing, which means we basically send out a hotplug event every
  single time we receive one even if nothing has changed

Additionally, the code for handling DP that we have in nouveau is also
quite unoptimized in general, doesn't use a lot of helpers that have
been added since it was written, and is also missing quite a number of
features:

* Downstream port capability probing
* Extended DPRX cap parsing
* SINK_COUNT handling for hpd on dongles

Luckily for us - all of these are implemented in i915 already. Since
there's no reason for us to reinvent the wheel, and having more shared
code is always nice, I decided to take the opportunity to extract the
code for all of these features from i915 into a set of core DP helpers,
which both i915 and nouveau (and hopefully other drivers in the future)
can use.

As well, this patch series also addesses the other general
connector probing related issues I mentioned above, along with rewriting
how we handle MST probing so we don't hit any surprise locking design
issues in the future.

As a note - most of this work is motivated by the fact that I'm
planning on adding max_bpc/output_bpc prop support, DSC support (for
both MST and SST, along with proper helpers for handling bandwidth
limitations and DSC), and fallback link retraining. I figured I might as
clean this code up and implement missing DP features like the ones
mentioned here before moving on to those tasks.

Lyude Paul (20):
  drm/nouveau/kms: Fix some indenting in nouveau_dp_detect()
  drm/nouveau/kms/nv50-: Remove open-coded drm_dp_read_desc()
  drm/nouveau/kms/nv50-: Just use drm_dp_dpcd_read() in nouveau_dp.c
  drm/nouveau/kms/nv50-: Use macros for DP registers in nouveau_dp.c
  drm/nouveau/kms: Don't clear DP_MST_CTRL DPCD in nv50_mstm_new()
  drm/nouveau/kms: Search for encoders' connectors properly
  drm/nouveau/kms/nv50-: Use drm_dp_dpcd_(readb|writeb)() in
nv50_sor_disable()
  drm/nouveau/kms/nv50-: Refactor and cleanup DP HPD handling
  drm/i915/dp: Extract drm_dp_has_mst()
  drm/nouveau/kms: Use new drm_dp_has_mst() helper for checking MST caps
  drm/nouveau/kms: Move drm_dp_cec_unset_edid() into
nouveau_connector_detect()
  drm/nouveau/kms: Only use hpd_work for reprobing in HPD paths
  drm/i915/dp: Extract drm_dp_downstream_read_info()
  drm/nouveau/kms/nv50-: Use downstream DP clock limits for mode
validation
  drm/i915/dp: Extract drm_dp_has_sink_count()
  drm/i915/dp: Extract drm_dp_get_sink_count()
  drm/nouveau/kms/nv50-: Add support for DP_SINK_COUNT
  drm/nouveau/kms: Don't change EDID when it hasn't actually changed
  drm/i915/dp: Extract drm_dp_read_dpcd_caps()
  drm/nouveau/kms: Start using drm_dp_read_dpcd_caps()

 drivers/gpu/drm/drm_dp_helper.c | 167 +++
 drivers/gpu/drm/i915/display/intel_dp.c | 124 ++--
 drivers/gpu/drm/i915/display/intel_dp.h |   1 -
 drivers/gpu/drm/i915/display/intel_lspcon.c |   2 +-
 drivers/gpu/drm/nouveau/dispnv04/dac.c  |   2 +-
 drivers/gpu/drm/nouveau/dispnv04/dfp.c  |   7 +-
 drivers/gpu/drm/nouveau/dispnv04/disp.c |  24 +-
 drivers/gpu/drm/nouveau/dispnv04/disp.h |   4 +
 drivers/gpu/drm/nouveau/dispnv04/tvnv04.c   |   2 +-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c   |   2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 305 +++-
 drivers/gpu/drm/nouveau/nouveau_connector.c | 132 -
 drivers/gpu/drm/nouveau/nouveau_connector.h |   1 +
 drivers/gpu/drm/nouveau/nouveau_display.c   |  72 -
 drivers/gpu/drm/nouveau/nouveau_display.h   |   3 +-
 drivers/gpu/drm/nouveau/nouveau_dp.c| 211 +++---
 drivers/gpu/drm/nouveau/nouveau_drm.c   |   4 +-
 drivers/gpu/drm/nouveau/nouveau_drv.h   |   2 +
 drivers/gpu/drm/nouveau/nouveau_encoder.h   |  48 ++-
 include/drm/drm_dp_helper.h |  15 +-
 include/drm/drm_dp_mst_helper.h |  22 ++
 21 files changed, 761 insertions(+),

[RFC v4 05/20] drm/nouveau/kms: Don't clear DP_MST_CTRL DPCD in nv50_mstm_new()

2020-08-25 Thread Lyude Paul
Since fa3cdf8d0b09 ("drm/nouveau: Reset MST branching unit before
enabling") we've been clearing DP_MST_CTRL before we start enabling MST.
Since then clearing DP_MST_CTRL in nv50_mstm_new() has been unnecessary
and redundant, so let's remove it.

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index e7874877da858..c4d138f0ca054 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1535,17 +1535,6 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct 
drm_dp_aux *aux, int aux_max,
struct drm_device *dev = outp->base.base.dev;
struct nv50_mstm *mstm;
int ret;
-   u8 dpcd;
-
-   /* This is a workaround for some monitors not functioning
-* correctly in MST mode on initial module load.  I think
-* some bad interaction with the VBIOS may be responsible.
-*
-* A good ol' off and on again seems to work here ;)
-*/
-   ret = drm_dp_dpcd_readb(aux, DP_DPCD_REV, &dpcd);
-   if (ret >= 0 && dpcd >= 0x12)
-   drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0);
 
if (!(mstm = *pmstm = kzalloc(sizeof(*mstm), GFP_KERNEL)))
return -ENOMEM;
-- 
2.26.2

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


[RFC v4 06/20] drm/nouveau/kms: Search for encoders' connectors properly

2020-08-25 Thread Lyude Paul
While the way we find the associated connector for an encoder is just
fine for legacy modesetting, it's not correct for nv50+ since that uses
atomic modesetting. For reference, see the drm_encoder kdocs.

Fix this by removing nouveau_encoder_connector_get(), and replacing it
with nv04_encoder_get_connector(), nv50_outp_get_old_connector(), and
nv50_outp_get_new_connector().

v2:
* Don't line-wrap for_each_(old|new)_connector_in_state in
  nv50_outp_get_(old|new)_connector() - sravn
v3:
* Fix potential uninitialized usage of nv_connector (needs to be
  initialized to NULL at the start). Thanks kernel test robot!
v4:
* Actually fix uninitialized nv_connector usage in
  nv50_audio_component_get_eld(). The previous fix wouldn't have worked
  since we would have started out with nv_connector == NULL, but
  wouldn't clear it after a single drm_for_each_encoder() iteration.
  Thanks again Kernel bot!

Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/dispnv04/dac.c  |  2 +-
 drivers/gpu/drm/nouveau/dispnv04/dfp.c  |  7 +-
 drivers/gpu/drm/nouveau/dispnv04/disp.c | 18 +
 drivers/gpu/drm/nouveau/dispnv04/disp.h |  4 +
 drivers/gpu/drm/nouveau/dispnv04/tvnv04.c   |  2 +-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c   |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 88 +
 drivers/gpu/drm/nouveau/nouveau_connector.c | 14 
 drivers/gpu/drm/nouveau/nouveau_encoder.h   |  6 +-
 9 files changed, 105 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c 
b/drivers/gpu/drm/nouveau/dispnv04/dac.c
index ffdd447d87068..22d10f3285597 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dac.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
@@ -419,7 +419,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
-nouveau_encoder_connector_get(nv_encoder)->base.name,
+nv04_encoder_get_connector(nv_encoder)->base.name,
 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c 
b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index f9f4482c79b54..42687ea2a4ca3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -184,7 +184,8 @@ static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
 {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-   struct nouveau_connector *nv_connector = 
nouveau_encoder_connector_get(nv_encoder);
+   struct nouveau_connector *nv_connector =
+   nv04_encoder_get_connector(nv_encoder);
 
if (!nv_connector->native_mode ||
nv_connector->scaling_mode == DRM_MODE_SCALE_NONE ||
@@ -478,7 +479,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
-nouveau_encoder_connector_get(nv_encoder)->base.name,
+nv04_encoder_get_connector(nv_encoder)->base.name,
 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
@@ -591,7 +592,7 @@ static void nv04_dfp_restore(struct drm_encoder *encoder)
 
if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) {
struct nouveau_connector *connector =
-   nouveau_encoder_connector_get(nv_encoder);
+   nv04_encoder_get_connector(nv_encoder);
 
if (connector && connector->native_mode)
call_lvds_script(dev, nv_encoder->dcb, head,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c 
b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 900ab69df7e8f..3f046b917c85c 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -35,6 +35,24 @@
 
 #include 
 
+struct nouveau_connector *
+nv04_encoder_get_connector(struct nouveau_encoder *encoder)
+{
+   struct drm_device *dev = to_drm_encoder(encoder)->dev;
+   struct drm_connector *connector;
+   struct drm_connector_list_iter conn_iter;
+   struct nouveau_connector *nv_connector = NULL;
+
+   drm_connector_list_iter_begin(dev, &conn_iter);
+   drm_for_each_connector_iter(connector, &conn_iter) {
+   if (connector->encoder == to_drm_encoder(encoder))
+   nv_connector = nouveau_connector(connector);
+   }
+   drm_connector_list_iter_end(&conn_iter);
+
+   return nv_connector;
+}
+
 static void
 nv04_display_fini(struct drm_device *dev, bool suspend)
 {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h 
b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index 495d3284e8766..5ace5e906949a 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
@@

[RFC v4 01/20] drm/nouveau/kms: Fix some indenting in nouveau_dp_detect()

2020-08-25 Thread Lyude Paul
Signed-off-by: Lyude Paul 
Reviewed-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_dp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c 
b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 8a0f7994e1aeb..ee778ddc95fae 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -76,10 +76,10 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
 
NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
-nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
+nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
NV_DEBUG(drm, "encoder: %dx%d\n",
-nv_encoder->dcb->dpconf.link_nr,
-nv_encoder->dcb->dpconf.link_bw);
+nv_encoder->dcb->dpconf.link_nr,
+nv_encoder->dcb->dpconf.link_bw);
 
if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr)
nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
@@ -87,7 +87,7 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
 
NV_DEBUG(drm, "maximum: %dx%d\n",
-nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
+nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
nouveau_dp_probe_oui(dev, aux, dpcd);
 
-- 
2.26.2

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


Re: [PATCH 00/49] DRM driver for Hikey 970

2020-08-25 Thread Sam Ravnborg
Hi Mauro

> Before posting the big patch series again, let me send the new
> version folded into a single patch.
> 
> If you'd like to see the entire thing, I'm placing it here:
> 
>   
> https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/hikey970_v2/

Review 3/3

For next submission then to ease review it would be nice that the patch
is spilt up a little. Maybe something like:
- HW specific stuff in two patches (header fiels with register + setup
  code)
- Display driver files
- DSI driver files
- build stuff (Makefile, Kconfig fragments)
So all splits on file level - which should be easy to do.

This will make it easier for more people to give feedback. It is a bit
much to walk through 4k loc or what the full size is.
And then we can also provide a-b or r-b for fragments so the reviewed
parts can be ignored for later reviews.


For the DSI parts I may be hit by the old "when you have a hammer then
everything looks like a nail syndrome".
In my case the hammer is the bridge interface.

Suggestions:
- Move encoder to display driver
- Move connector creation to display driver (using
  drm_bridge_connector_init())
- Use drm_bridge interface for the DSI driver parts
- Maybe use the HDMI bridge driver as a chained driver - I did not look
  to close on this
- Use the standard bridge interface to find the bridge and drop use of
  the component framework

I hope that some other drm people chime in here.
Either to tell this is non-sense or confirm this is the way to go.

The above does not give any hint how to use the gpio_mux to shift
between the panel and HDMI. This logic needs to be in the display driver
as the bridge driver will only be used for HDMI - as I understand the
code. And I do not know how to do it.

Some details in the following that are not related to the above.

Sam

> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c 
> b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
> new file mode 100644
> index ..a2eed961b7d5
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
> @@ -0,0 +1,2126 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * DesignWare MIPI DSI Host Controller v1.02 driver
> + *
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + *
> + * Author:
> + *   
> + *   
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
Sort

> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
Sort

> +
> +#include "kirin9xx_dw_dsi_reg.h"
> +#include "kirin9xx_dpe.h"
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin9xx_drm_dpe_utils.h"
Sort

> +
> +#define PHY_REF_CLK_RATE 1920
> +#define PHY_REF_CLK_PERIOD_PS(10 / (PHY_REF_CLK_RATE / 1000))
> +
> +#define encoder_to_dsi(encoder) \
> + container_of(encoder, struct dw_dsi, encoder)
> +#define host_to_dsi(host) \
> + container_of(host, struct dw_dsi, host)
> +#define connector_to_dsi(connector) \
> + container_of(connector, struct dw_dsi, connector)
Move the upcast next to the struct definition.


> +#define DSS_REDUCE(x)((x) > 0 ? ((x) - 1) : (x))
> +
> +enum dsi_output_client {
> + OUT_HDMI = 0,
> + OUT_PANEL,
> + OUT_MAX
> +};
> +
> +struct mipi_phy_params {
I did not check all fiels but I managed to find at least one unused
field. Cheack and delete what is unused.
> + u64 lane_byte_clk;
> + u32 clk_division;
> +
> + u32 clk_lane_lp2hs_time;
> + u32 clk_lane_hs2lp_time;
> + u32 data_lane_lp2hs_time;
> + u32 data_lane_hs2lp_time;
> + u32 clk2data_delay;
> + u32 data2clk_delay;
> +
> + u32 clk_pre_delay;
> + u32 clk_post_delay;
> + u32 clk_t_lpx;
> + u32 clk_t_hs_prepare;
> + u32 clk_t_hs_zero;
> + u32 clk_t_hs_trial;
> + u32 clk_t_wakeup;
> + u32 data_pre_delay;
> + u32 data_post_delay;
> + u32 data_t_lpx;
> + u32 data_t_hs_prepare;
> + u32 data_t_hs_zero;
> + u32 data_t_hs_trial;
> + u32 data_t_ta_go;
> + u32 data_t_ta_get;
> + u32 data_t_wakeup;
> +
> + u32 phy_stop_wait_time;
> +
> + u32 rg_vrefsel_vcm;
> + u32 rg_hstx_ckg_sel;
> + u32 rg_pll_fbd_div5f;
> + u32 rg_pll_fbd_div1f;
> + u32 rg_pll_fbd_2p;
> + u32 rg_pll_enbwt;
> + u32 rg_pll_fbd_p;
> + u32 rg_pll_fbd_s;
> + u32 rg_pll_pre_div1p;
> + u32 rg_pll_pre_p;
> + u32 rg_pll_vco_750m;
> + u32 rg_pll_lpf_rs;
> + u32 rg_pll_lpf_cs;
> + u32 rg_pll_enswc;
> + u32 rg_pll_chp;
> +
Some indent gone wrong here?
> + u32 pll_register_override;  /* 0x1E[0] */
> + u32 pll_power_down; /* 0x1E[1] */
> + u32 rg_band_sel;/* 0x1E[2] */
> + u32 rg_phase_gen_en;/* 0x1E[3] */
> + u32 reload_sel; /

Re: [REGRESSION] omapdrm/N900 display broken

2020-08-25 Thread Tomi Valkeinen
Hi Laurent,

On 23/08/2020 19:26, Aaro Koskinen wrote:
> Hi,
> 
> On Tue, Aug 04, 2020 at 03:39:37PM +0300, Tomi Valkeinen wrote:
>> On 04/08/2020 15:13, Tomi Valkeinen wrote:
> 
>>> Can you try to pinpoint a bit where the hang happens? Maybe add
>>> DRM/omapdrm debug prints, or perhaps sysrq works and it shows a lock
>>> that's in deadlock.
>>
>> Also, one data point would be to disable venc, e.g. set venc status to
>> "disabled" in dts.
> 
> Disabling venc makes no difference.
> 
> The hang happens in drm_fb_helper_initial_config(). I followed the
> "HANG DEBUGGING" tips in the function comment text and enabled
> fb.lockless_register_fb=1 to get more (serial) console output.
> 
> Now I get this:
> 
> [6.514739] omapdss_dss 4805.dss: supply vdda_video not found, using 
> dummy regulator
> [6.566375] DSS: OMAP DSS rev 2.0
> [6.571807] omapdss_dss 4805.dss: bound 48050400.dispc (ops 
> dispc_component_ops)
> [6.580749] omapdrm omapdrm.0: DMM not available, disable DMM support
> [6.587982] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
> [6.626617] [ cut here ]
> [6.631774] WARNING: CPU: 0 PID: 18 at drivers/gpu/drm/drm_bridge.c:708 
> drm_atomic_helper_commit_modeset_enables+0x134/0x268
> [6.643768] Modules linked in:
> [6.647033] CPU: 0 PID: 18 Comm: kworker/0:1 Tainted: G U
> 5.8.0-omap3-los_16068+-4-g2e7d4a7efefd-dirty #2
> [6.658966] Hardware name: Nokia RX-51 board
> [6.663635] Workqueue: events deferred_probe_work_func
> [6.669097] [] (unwind_backtrace) from [] 
> (show_stack+0x10/0x14)
> [6.677429] [] (show_stack) from [] (__warn+0xbc/0xd4)
> [6.684844] [] (__warn) from [] 
> (warn_slowpath_fmt+0x60/0xb8)
> [6.692901] [] (warn_slowpath_fmt) from [] 
> (drm_atomic_helper_commit_modeset_enables+0x134/0x268)
> [6.704254] [] (drm_atomic_helper_commit_modeset_enables) from 
> [] (omap_atomic_commit_tail+0xb4/0xc0)
> [6.715972] [] (omap_atomic_commit_tail) from [] 
> (commit_tail+0x9c/0x1a8)
> [6.725128] [] (commit_tail) from [] 
> (drm_atomic_helper_commit+0x134/0x158)
> [6.734466] [] (drm_atomic_helper_commit) from [] 
> (drm_client_modeset_commit_atomic+0x16c/0x208)
> [6.745727] [] (drm_client_modeset_commit_atomic) from 
> [] (drm_client_modeset_commit_locked+0x58/0x184)
> [6.757629] [] (drm_client_modeset_commit_locked) from 
> [] (drm_client_modeset_commit+0x24/0x40)
> [6.768798] [] (drm_client_modeset_commit) from [] 
> (__drm_fb_helper_restore_fbdev_mode_unlocked+0xa0/0xc8)
> [6.780975] [] (__drm_fb_helper_restore_fbdev_mode_unlocked) 
> from [] (drm_fb_helper_set_par+0x38/0x64)
> [6.792785] [] (drm_fb_helper_set_par) from [] 
> (fbcon_init+0x3d4/0x568)
> [6.801757] [] (fbcon_init) from [] 
> (visual_init+0xb8/0xfc)
> [6.809631] [] (visual_init) from [] 
> (do_bind_con_driver+0x1e0/0x3bc)
> [6.818267] [] (do_bind_con_driver) from [] 
> (do_take_over_console+0x138/0x1d8)
> [6.827880] [] (do_take_over_console) from [] 
> (do_fbcon_takeover+0x74/0xd4)
> [6.837219] [] (do_fbcon_takeover) from [] 
> (register_framebuffer+0x204/0x2d8)
> [6.846740] [] (register_framebuffer) from [] 
> (__drm_fb_helper_initial_config_and_unlock+0x3a4/0x554)
> [6.858459] [] (__drm_fb_helper_initial_config_and_unlock) from 
> [] (omap_fbdev_init+0x84/0xbc)
> [6.869537] [] (omap_fbdev_init) from [] 
> (pdev_probe+0x580/0x7d8)
> [6.877807] [] (pdev_probe) from [] 
> (platform_drv_probe+0x48/0x98)

Laurent, does this ring any bells? The WARN comes in 
drm_atomic_bridge_chain_enable() when
drm_atomic_get_old_bridge_state() returns null for (presumably) sdi bridge.

I'm not sure why the bridge state would not be there.

Aaro, you can probably debug easier if you disable CONFIG_FRAMEBUFFER_CONSOLE, 
or even
CONFIG_DRM_FBDEV_EMULATION.

 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] drm/sun4i: lvds: Invert the LVDS polarity

2020-08-25 Thread Chen-Yu Tsai
On Sat, Jul 4, 2020 at 9:38 PM Maxime Ripard  wrote:
>
> The LVDS controller can invert the polarity / lanes of the LVDS output.
> The default polarity causes some issues on some panels.
>
> However, U-Boot has always used the opposite polarity without any reported
> issue, and the only currently supported LVDS panel in-tree (the TBS A711)
> seems to be able to work with both settings.
>
> Let's just use the same polarity than U-Boot to be more consistent and
> hopefully support all the panels.
>
> Cc: Ondrej Jirman 
> Signed-off-by: Maxime Ripard 

Reviewed-by: Chen-Yu Tsai 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/amdgpu/dc: Require primary plane to be enabled whenever the CRTC is

2020-08-25 Thread Kazlauskas, Nicholas

On 2020-08-22 5:59 a.m., Michel Dänzer wrote:

On 2020-08-21 8:07 p.m., Kazlauskas, Nicholas wrote:

On 2020-08-21 12:57 p.m., Michel Dänzer wrote:

From: Michel Dänzer 

Don't check drm_crtc_state::active for this either, per its
documentation in include/drm/drm_crtc.h:

   * Hence drivers must not consult @active in their various
   * &drm_mode_config_funcs.atomic_check callback to reject an atomic
   * commit.

The atomic helpers disable the CRTC as needed for disabling the primary
plane.

This prevents at least the following problems if the primary plane gets
disabled (e.g. due to destroying the FB assigned to the primary plane,
as happens e.g. with mutter in Wayland mode):

* Toggling CRTC active to 1 failed if the cursor plane was enabled
    (e.g. via legacy DPMS property & cursor ioctl).
* Enabling the cursor plane failed, e.g. via the legacy cursor ioctl.


We previously had the requirement that the primary plane must be enabled
but some userspace expects that they can enable just the overlay plane
without anything else.

I think the chromuiumos atomictest validates that this works as well:

So is DRM going forward then with the expectation that this is wrong
behavior from userspace?

We require at least one plane to be enabled to display a cursor, but it
doesn't necessarily need to be the primary.


It's a "pick your poison" situation:

1) Currently the checks are invalid (atomic_check must not decide based
on drm_crtc_state::active), and it's easy for legacy KMS userspace to
accidentally hit errors trying to enable/move the cursor or switch DPMS
off → on.

2) Accurately rejecting only atomic states where the cursor plane is
enabled but all other planes are off would break the KMS helper code,
which can only deal with the "CRTC on & primary plane off is not
allowed" case specifically.

3) This patch addresses 1) & 2) but may break existing atomic userspace
which wants to enable an overlay plane while disabling the primary plane.


I do think in principle atomic userspace is expected to handle case 3)
and leave the primary plane enabled. However, this is not ideal from an
energy consumption PoV. Therefore, here's another idea for a possible
way out of this quagmire:

amdgpu_dm does not reject any atomic states based on which planes are
enabled in it. If the cursor plane is enabled but all other planes are
off, amdgpu_dm internally either:

a) Enables an overlay plane and makes it invisible, e.g. by assigning a
minimum size FB with alpha = 0.

b) Enables the primary plane and assigns a minimum size FB (scaled up to
the required size) containing all black, possibly using compression.
(Trying to minimize the memory bandwidth)


Does either of these seem feasible? If both do, which one would be
preferable?




It's really the same solution since DCN doesn't make a distinction 
between primary or overlay planes in hardware. DCE doesn't have overlay 
planes enabled so this is not relevant there.


The old behavior (pre 5.1?) was to silently accept the commit even 
though the screen would be completely black instead of outright 
rejecting the commit.


I almost wonder if that makes more sense in the short term here since 
the only "userspace" affected here is IGT. We'll fail the CRC checks, 
but no userspace actually tries to actively use a cursor with no primary 
plane enabled from my understanding.


In the long term I think we can work on getting cursor actually on the 
screen in this case, though I can't say I really like having to reserve 
some small buffer (eg. 16x16) for allowing lightup on this corner case.


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


Re: [Nouveau] [PATCH 1/2] drm/nouveau/kms/nv50-: Program notifier offset before requesting disp caps

2020-08-25 Thread Lyude Paul
On Tue, 2020-08-25 at 08:28 +1000, Ben Skeggs wrote:
> On Tue, 25 Aug 2020 at 04:33, Lyude Paul  wrote:
> > Not entirely sure why this never came up when I originally tested this
> > (maybe some BIOSes already have this setup?) but the ->caps_init vfunc
> > appears to cause the display engine to throw an exception on driver
> > init, at least on my ThinkPad P72:
> > 
> > nouveau :01:00.0: disp: chid 0 mthd 008c data  508c 102b
> > 
> > This is magic nvidia speak for "You need to have the DMA notifier offset
> > programmed before you can call NV507D_GET_CAPABILITIES." So, let's fix
> > this by doing that, and also perform an update afterwards to prevent
> > racing with the GPU when reading capabilities.
> > 
> > Changes since v1:
> > * Don't just program the DMA notifier offset, make sure to actually
> >   perform an update
> I'm not sure there's a need to send an Update() method here, I believe
> GetCapabilities() is an action method on its own right?
> 

I'm not entirely sure about this part tbh. I do know that we need to call
GetCapabilities() _after_ the DMA notifier offset is programmed. But, my
assumption was that if GetCapabilities() requires a DMA notifier offset to store
its results in, we'd probably want to fire an update or something to make sure
that we're not reading before it finishes writing capabilities?

> Ben.
> 
> > Signed-off-by: Lyude Paul 
> > Fixes: 4a2cb4181b07 ("drm/nouveau/kms/nv50-: Probe SOR and PIOR caps for DP
> > interlacing support")
> > Cc:  # v5.8+
> > ---
> >  drivers/gpu/drm/nouveau/dispnv50/core507d.c | 25 -
> >  1 file changed, 19 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c
> > b/drivers/gpu/drm/nouveau/dispnv50/core507d.c
> > index e341f572c2696..5e86feec3b720 100644
> > --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c
> > +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c
> > @@ -65,13 +65,26 @@ core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
> >  int
> >  core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
> >  {
> > -   u32 *push = evo_wait(&disp->core->chan, 2);
> > +   struct nv50_core *core = disp->core;
> > +   u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {0};
> > +   u32 *push;
> > 
> > -   if (push) {
> > -   evo_mthd(push, 0x008c, 1);
> > -   evo_data(push, 0x0);
> > -   evo_kick(push, &disp->core->chan);
> > -   }
> > +   core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY);
> > +
> > +   push = evo_wait(&core->chan, 4);
> > +   if (!push)
> > +   return 0;
> > +
> > +   evo_mthd(push, 0x0084, 1);
> > +   evo_data(push, 0x8000 | NV50_DISP_CORE_NTFY);
> > +   evo_mthd(push, 0x008c, 1);
> > +   evo_data(push, 0x0);
> > +   evo_kick(push, &core->chan);
> > +
> > +   core->func->update(core, interlock, false);
> > +   if (core->func->ntfy_wait_done(disp->sync, NV50_DISP_CORE_NTFY,
> > +  core->chan.base.device))
> > +   NV_ERROR(drm, "core notifier timeout\n");
> > 
> > return 0;
> >  }
> > --
> > 2.26.2
> > 
> > ___
> > Nouveau mailing list
> > nouv...@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/nouveau
-- 
Sincerely,
  Lyude Paul (she/her)
  Software Engineer at Red Hat

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


Re: [PATCH v5 1/3] drm/vkms: Decouple crc operations from composer

2020-08-25 Thread Melissa Wen
On Mon, Aug 24, 2020 at 11:31 PM Rodrigo Siqueira
 wrote:
>
> In the vkms_composer.c, some of the functions related to CRC and compose
> have interdependence between each other. This patch reworks some
> functions inside vkms_composer to make crc and composer computation
> decoupled.
>
> This patch is preparation work for making vkms able to support new
> features.
>
> Signed-off-by: Rodrigo Siqueira 
> ---
>  drivers/gpu/drm/vkms/vkms_composer.c | 49 
>  1 file changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index 4f3b07a32b60..4d8bc04bb6ee 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -108,35 +108,31 @@ static void compose_cursor(struct vkms_composer 
> *cursor_composer,
>   primary_composer, cursor_composer);
>  }
>
> -static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer,
> - struct vkms_composer *cursor_composer)
> +static int compose_planes(void **vaddr_out,
> + struct vkms_composer *primary_composer,
> + struct vkms_composer *cursor_composer)
>  {
> struct drm_framebuffer *fb = &primary_composer->fb;
> struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
> struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
> -   void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
> -   u32 crc = 0;
>
> -   if (!vaddr_out) {
> -   DRM_ERROR("Failed to allocate memory for output frame.");
> -   return 0;
> +   if (!*vaddr_out) {
> +   *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
> +   if (!*vaddr_out) {
> +   DRM_ERROR("Cannot allocate memory for output frame.");
> +   return -ENOMEM;
> +   }
> }
>
> -   if (WARN_ON(!vkms_obj->vaddr)) {
> -   kfree(vaddr_out);
> -   return crc;
> -   }
> +   if (WARN_ON(!vkms_obj->vaddr))
> +   return -EINVAL;
>
> -   memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
> +   memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
>
> if (cursor_composer)
> -   compose_cursor(cursor_composer, primary_composer, vaddr_out);
> +   compose_cursor(cursor_composer, primary_composer, *vaddr_out);
>
> -   crc = compute_crc(vaddr_out, primary_composer);
> -
> -   kfree(vaddr_out);
> -
> -   return crc;
> +   return 0;
>  }
>
>  /**
> @@ -157,9 +153,11 @@ void vkms_composer_worker(struct work_struct *work)
> struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
> struct vkms_composer *primary_composer = NULL;
> struct vkms_composer *cursor_composer = NULL;
> +   void *vaddr_out = NULL;
> u32 crc32 = 0;
> u64 frame_start, frame_end;
> bool crc_pending;
> +   int ret;
>
> spin_lock_irq(&out->composer_lock);
> frame_start = crtc_state->frame_start;
> @@ -183,14 +181,25 @@ void vkms_composer_worker(struct work_struct *work)
> if (crtc_state->num_active_planes == 2)
> cursor_composer = crtc_state->active_planes[1]->composer;
>
> -   if (primary_composer)
> -   crc32 = _vkms_get_crc(primary_composer, cursor_composer);
> +   if (!primary_composer)
> +   return;
> +
> +   ret = compose_planes(&vaddr_out, primary_composer, cursor_composer);
> +   if (ret) {
> +   if (ret == -EINVAL)
> +   kfree(vaddr_out);
> +   return;
> +   }
> +
> +   crc32 = compute_crc(vaddr_out, primary_composer);
>
> /*
>  * The worker can fall behind the vblank hrtimer, make sure we catch 
> up.
>  */
> while (frame_start <= frame_end)
> drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32);
> +
> +   kfree(vaddr_out);
>  }
>
>  static const char * const pipe_crc_sources[] = {"auto"};
> --
> 2.28.0
>

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


Re: [PATCH v5 3/3] drm/vkms: Add support for writeback

2020-08-25 Thread Melissa Wen
On Tue, Aug 25, 2020 at 12:45 PM Melissa Wen  wrote:
>
> On 08/24, Rodrigo Siqueira wrote:
> > This patch implements the necessary functions to add writeback support
> > for vkms. This feature is useful for testing compositors if you don't
> > have hardware with writeback support.
> >
> > Change in V4 (Emil and Melissa):
> > - Move signal completion above drm_crtc_add_crc_entry()
> > - Make writeback always available
> > - Use appropriate namespace
> > - Drop fb check in vkms_wb_atomic_commit
> > - Make vkms_set_composer visible for writeback code
> > - Enable composer operation on prepare_job and disable it on cleanup_job
> >
> > Change in V3 (Daniel):
> > - If writeback is enabled, compose everything into the writeback buffer
> > instead of CRC private buffer
> > - Guarantees that the CRC will match exactly what we have in the
> > writeback buffer.
> >
> > Change in V2:
> > - Rework signal completion (Brian)
> > - Integrates writeback with active_planes (Daniel)
> > - Compose cursor (Daniel)
> >
> > Signed-off-by: Rodrigo Siqueira 
> > ---
> >  drivers/gpu/drm/vkms/Makefile |   9 +-
> >  drivers/gpu/drm/vkms/vkms_composer.c  |  21 +++-
> >  drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
> >  drivers/gpu/drm/vkms/vkms_output.c|   4 +
> >  drivers/gpu/drm/vkms/vkms_writeback.c | 143 ++
> >  5 files changed, 181 insertions(+), 7 deletions(-)
> >  create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c
> >
> > diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
> > index 0b767d7efa24..333d3cead0e3 100644
> > --- a/drivers/gpu/drm/vkms/Makefile
> > +++ b/drivers/gpu/drm/vkms/Makefile
> > @@ -1,4 +1,11 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> > -vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o 
> > vkms_composer.o
> > +vkms-y := \
> > + vkms_drv.o \
> > + vkms_plane.o \
> > + vkms_output.o \
> > + vkms_crtc.o \
> > + vkms_gem.o \
> > + vkms_composer.o \
> > + vkms_writeback.o
> >
> >  obj-$(CONFIG_DRM_VKMS) += vkms.o
> > diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> > b/drivers/gpu/drm/vkms/vkms_composer.c
> > index 387b0690a64a..656085c4ebf3 100644
> > --- a/drivers/gpu/drm/vkms/vkms_composer.c
> > +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> > @@ -163,16 +163,17 @@ void vkms_composer_worker(struct work_struct *work)
> >   struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
> >   struct vkms_composer *primary_composer = NULL;
> >   struct vkms_composer *cursor_composer = NULL;
> > + bool crc_pending, wb_pending;
> >   void *vaddr_out = NULL;
> >   u32 crc32 = 0;
> >   u64 frame_start, frame_end;
> > - bool crc_pending;
> >   int ret;
> >
> >   spin_lock_irq(&out->composer_lock);
> >   frame_start = crtc_state->frame_start;
> >   frame_end = crtc_state->frame_end;
> >   crc_pending = crtc_state->crc_pending;
> > + wb_pending = crtc_state->wb_pending;
> >   crtc_state->frame_start = 0;
> >   crtc_state->frame_end = 0;
> >   crtc_state->crc_pending = false;
> > @@ -194,22 +195,32 @@ void vkms_composer_worker(struct work_struct *work)
> >   if (!primary_composer)
> >   return;
> >
> > + if (wb_pending)
> > + vaddr_out = crtc_state->active_writeback;
> > +
> >   ret = compose_planes(&vaddr_out, primary_composer, cursor_composer);
> >   if (ret) {
> > - if (ret == -EINVAL)
> > + if (ret == -EINVAL && !wb_pending)
> >   kfree(vaddr_out);
> >   return;
> >   }
> >
> >   crc32 = compute_crc(vaddr_out, primary_composer);
> >
> > + if (wb_pending) {
> > + drm_writeback_signal_completion(&out->wb_connector, 0);
> > + spin_lock_irq(&out->composer_lock);
> > + crtc_state->wb_pending = false;
> > + spin_unlock_irq(&out->composer_lock);
> > + } else {
> > + kfree(vaddr_out);
> > + }
> > +
> >   /*
> >* The worker can fall behind the vblank hrtimer, make sure we catch 
> > up.
> >*/
> >   while (frame_start <= frame_end)
> >   drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32);
> > -
> > - kfree(vaddr_out);
> >  }
> >
> >  static const char * const pipe_crc_sources[] = {"auto"};
> > @@ -252,7 +263,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const 
> > char *src_name,
> >   return 0;
> >  }
> >
> > -static void vkms_set_composer(struct vkms_output *out, bool enabled)
> > +void vkms_set_composer(struct vkms_output *out, bool enabled)
> >  {
> >   bool old_enabled;
> >
> > diff --git a/drivers/gpu/drm/vkms/vkms_drv.h 
> > b/drivers/gpu/drm/vkms/vkms_drv.h
> > index f4036bb0b9a8..641d8bc52a3a 100644
> > --- a/drivers/gpu/drm/vkms/vkms_drv.h
> > +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> > @@ -8,6 +8,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #define XRES_MIN20
> >  

Re: [PATCH v5 0/3] drm/vkms: Introduces writeback support

2020-08-25 Thread Melissa Wen
Hi Rodrigo,

Nice work!

I tested this on the kms_writeback set of subtests and works fine.

I have also checked it on the other IGT tests that I usually uses:
- kms_cursor_crc/cursor-alpha-transparent was affected by a small
  problem in the bitmap_clear of the get_pixel_from_buffer function,
  that I pointed out inline. Please, check it.
- kms_flip and kms_pipe_crc_basic works as expected (was not affected).

Best regards,

Melissa Wen

On 08/24, Rodrigo Siqueira wrote:
> This is the V5 version of a series that introduces the writeback support
> to VKMS. The first two patches of this series are a pre-work for the
> latest patch that adds the writeback connector, this patchset can be seen
> in two parts: 
> 
> * A pre-work that aims to make vkms composer operations a little bit more
>   generic; these patches try to centralize the vkms framebuffer operations.
> * The final patch enables the support for writeback in vkms.
> 
> In the previous review, Emil suggested multiple changes in the series. I
> tried to apply most of the recommendations except for some suggestions
> which I was not able to incorporate due to compilation issues, or other
> suggestions that may complicate this series review. I left some changes
> for future patches for keeping this patchset simple with the hope of
> landing this feature soon in order to support VKMS user's requirements.
> Emil, let me know if you want me to change any other thing.
> 
> It is important to highlight that from the previous series to the
> current version of this patchset we had some changes in the VKMS that
> made it unstable.  In particular, our previous writeback series stopped
> working properly due to changes in our commit tail.  Thanks to Melissa
> working in the instability issue and her latest fixes to VKMS, I finally
> could update writeback and make it work again. The main update in the
> latest patch is the use of vkms_set_composer when the writeback work
> starts (enable composer) and after the writeback end (disable composer).
> 
> Best Regard
> 
> Rodrigo Siqueira (3):
>   drm/vkms: Decouple crc operations from composer
>   drm/vkms: Compute CRC without change input data
>   drm/vkms: Add support for writeback
> 
>  drivers/gpu/drm/vkms/Makefile |   9 +-
>  drivers/gpu/drm/vkms/vkms_composer.c  | 102 +++---
>  drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
>  drivers/gpu/drm/vkms/vkms_output.c|   4 +
>  drivers/gpu/drm/vkms/vkms_writeback.c | 143 ++
>  5 files changed, 231 insertions(+), 38 deletions(-)
>  create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c
> 
> -- 
> 2.28.0
> 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


  1   2   >