mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-22 02:20:40 +00:00
Short summary of fixes pull:
nouveau: - dp: Don't probe DP ports twice - nv04: Fix OOB access - nv50: Disable AUX bus for disconnected DP ports - nvkm: Fix race condition panel: - Don't unregister DSI devices in several drivers ttm: - Stop pooling cached NUMA pages v3d: - Fix enabled_ns increment vmwgfx: - Fix PRIME import/export - Fix CRTC's atomic check for primary planes - Sort plane formats by preference -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmYgygMACgkQaA3BHVML eiNuaggAvTBSC4y5VRmfMGy81PSIRUbz5Rckl9UqhCWZ2A6NLPygSVaa9T8mwq2o J5UYpv9gKbWF4frZBh06/DiNjiXoh1jOhev1xv5mWXc16/B057NqDN2scwDq35uE zF9fas/R0QL/wB8ZBgWcfHBhanwzKJ9Q66ckiJCjDt/4vUWVfUEyn3YqAhrx0S2b CEOtItAYqiiunSvI/CcnxAlvGwK6YxNQpzqtNAU5WAQT3Ra5YDJ1BKUxllWbNT94 9OO5tTYlVH4o7m94koPui6Nb0/BHNsHcTXMul0EVcOgJzp9BxkkdvRC/yTIT7OjL WSBc9CBNXhGlG2GD9KTOpnnlQDEYlQ== =SIZO -----END PGP SIGNATURE----- Merge tag 'drm-misc-fixes-2024-04-18' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes Short summary of fixes pull: nouveau: - dp: Don't probe DP ports twice - nv04: Fix OOB access - nv50: Disable AUX bus for disconnected DP ports - nvkm: Fix race condition panel: - Don't unregister DSI devices in several drivers ttm: - Stop pooling cached NUMA pages v3d: - Fix enabled_ns increment vmwgfx: - Fix PRIME import/export - Fix CRTC's atomic check for primary planes - Sort plane formats by preference Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20240418072229.GA8983@localhost.localdomain
This commit is contained in:
commit
5493bf2d0f
17 changed files with 186 additions and 57 deletions
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_bios.h"
|
||||
#include "nouveau_reg.h"
|
||||
#include "dispnv04/hw.h"
|
||||
#include "nouveau_encoder.h"
|
||||
|
@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
|
|||
*/
|
||||
if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
|
||||
if (*conn == 0xf2005014 && *conf == 0xffffffff) {
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
|
|||
#ifdef __powerpc__
|
||||
/* Apple iMac G4 NV17 */
|
||||
if (of_machine_is_compatible("PowerMac4,5")) {
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make up some sane defaults */
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
|
||||
bios->legacy.i2c_indices.crt, 1, 1);
|
||||
bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
|
||||
|
||||
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
|
||||
bios->legacy.i2c_indices.tv,
|
||||
all_heads, 0);
|
||||
all_heads, DCB_OUTPUT_A);
|
||||
|
||||
else if (bios->tmds.output0_script_ptr ||
|
||||
bios->tmds.output1_script_ptr)
|
||||
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
|
||||
bios->legacy.i2c_indices.panel,
|
||||
all_heads, 1);
|
||||
all_heads, DCB_OUTPUT_B);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -225,12 +225,18 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
|
|||
u8 *dpcd = nv_encoder->dp.dpcd;
|
||||
int ret = NOUVEAU_DP_NONE, hpd;
|
||||
|
||||
/* If we've already read the DPCD on an eDP device, we don't need to
|
||||
* reread it as it won't change
|
||||
/* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we
|
||||
* haven't probed them once before.
|
||||
*/
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
|
||||
dpcd[DP_DPCD_REV] != 0)
|
||||
return NOUVEAU_DP_SST;
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
if (connector->status == connector_status_connected)
|
||||
return NOUVEAU_DP_SST;
|
||||
else if (connector->status == connector_status_disconnected)
|
||||
return NOUVEAU_DP_NONE;
|
||||
}
|
||||
|
||||
// Ensure that the aux bus is enabled for probing
|
||||
drm_dp_dpcd_set_powered(&nv_connector->aux, true);
|
||||
|
||||
mutex_lock(&nv_encoder->dp.hpd_irq_lock);
|
||||
if (mstm) {
|
||||
|
@ -293,6 +299,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
|
|||
if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST)
|
||||
nv50_mstm_remove(mstm);
|
||||
|
||||
/* GSP doesn't like when we try to do aux transactions on a port it considers disconnected,
|
||||
* and since we don't really have a usecase for that anyway - just disable the aux bus here
|
||||
* if we've decided the connector is disconnected
|
||||
*/
|
||||
if (ret == NOUVEAU_DP_NONE)
|
||||
drm_dp_dpcd_set_powered(&nv_connector->aux, false);
|
||||
|
||||
mutex_unlock(&nv_encoder->dp.hpd_irq_lock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
|
|||
void __iomem *map = NULL;
|
||||
|
||||
/* Already mapped? */
|
||||
if (refcount_inc_not_zero(&iobj->maps))
|
||||
if (refcount_inc_not_zero(&iobj->maps)) {
|
||||
/* read barrier match the wmb on refcount set */
|
||||
smp_rmb();
|
||||
return iobj->map;
|
||||
}
|
||||
|
||||
/* Take the lock, and re-check that another thread hasn't
|
||||
* already mapped the object in the meantime.
|
||||
|
@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
|
|||
iobj->base.memory.ptrs = &nv50_instobj_fast;
|
||||
else
|
||||
iobj->base.memory.ptrs = &nv50_instobj_slow;
|
||||
/* barrier to ensure the ptrs are written before refcount is set */
|
||||
smp_wmb();
|
||||
refcount_set(&iobj->maps, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -614,8 +614,6 @@ static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
|
|||
struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(ctx->dsi);
|
||||
mipi_dsi_device_unregister(ctx->dsi);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
|
|
|
@ -253,8 +253,6 @@ static void visionox_rm69299_remove(struct mipi_dsi_device *dsi)
|
|||
struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(ctx->dsi);
|
||||
mipi_dsi_device_unregister(ctx->dsi);
|
||||
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
|
|
|
@ -288,17 +288,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
|
|||
enum ttm_caching caching,
|
||||
unsigned int order)
|
||||
{
|
||||
if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE)
|
||||
if (pool->use_dma_alloc)
|
||||
return &pool->caching[caching].orders[order];
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
switch (caching) {
|
||||
case ttm_write_combined:
|
||||
if (pool->nid != NUMA_NO_NODE)
|
||||
return &pool->caching[caching].orders[order];
|
||||
|
||||
if (pool->use_dma32)
|
||||
return &global_dma32_write_combined[order];
|
||||
|
||||
return &global_write_combined[order];
|
||||
case ttm_uncached:
|
||||
if (pool->nid != NUMA_NO_NODE)
|
||||
return &pool->caching[caching].orders[order];
|
||||
|
||||
if (pool->use_dma32)
|
||||
return &global_dma32_uncached[order];
|
||||
|
||||
|
@ -566,11 +572,17 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev,
|
|||
pool->use_dma_alloc = use_dma_alloc;
|
||||
pool->use_dma32 = use_dma32;
|
||||
|
||||
if (use_dma_alloc || nid != NUMA_NO_NODE) {
|
||||
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
|
||||
for (j = 0; j < NR_PAGE_ORDERS; ++j)
|
||||
ttm_pool_type_init(&pool->caching[i].orders[j],
|
||||
pool, i, j);
|
||||
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
|
||||
for (j = 0; j < NR_PAGE_ORDERS; ++j) {
|
||||
struct ttm_pool_type *pt;
|
||||
|
||||
/* Initialize only pool types which are actually used */
|
||||
pt = ttm_pool_select_type(pool, i, j);
|
||||
if (pt != &pool->caching[i].orders[j])
|
||||
continue;
|
||||
|
||||
ttm_pool_type_init(pt, pool, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_pool_init);
|
||||
|
@ -599,10 +611,16 @@ void ttm_pool_fini(struct ttm_pool *pool)
|
|||
{
|
||||
unsigned int i, j;
|
||||
|
||||
if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) {
|
||||
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
|
||||
for (j = 0; j < NR_PAGE_ORDERS; ++j)
|
||||
ttm_pool_type_fini(&pool->caching[i].orders[j]);
|
||||
for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
|
||||
for (j = 0; j < NR_PAGE_ORDERS; ++j) {
|
||||
struct ttm_pool_type *pt;
|
||||
|
||||
pt = ttm_pool_select_type(pool, i, j);
|
||||
if (pt != &pool->caching[i].orders[j])
|
||||
continue;
|
||||
|
||||
ttm_pool_type_fini(pt);
|
||||
}
|
||||
}
|
||||
|
||||
/* We removed the pool types from the LRU, but we need to also make sure
|
||||
|
|
|
@ -105,7 +105,6 @@ v3d_irq(int irq, void *arg)
|
|||
struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv;
|
||||
u64 runtime = local_clock() - file->start_ns[V3D_BIN];
|
||||
|
||||
file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN];
|
||||
file->jobs_sent[V3D_BIN]++;
|
||||
v3d->queue[V3D_BIN].jobs_sent++;
|
||||
|
||||
|
@ -126,7 +125,6 @@ v3d_irq(int irq, void *arg)
|
|||
struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv;
|
||||
u64 runtime = local_clock() - file->start_ns[V3D_RENDER];
|
||||
|
||||
file->enabled_ns[V3D_RENDER] += local_clock() - file->start_ns[V3D_RENDER];
|
||||
file->jobs_sent[V3D_RENDER]++;
|
||||
v3d->queue[V3D_RENDER].jobs_sent++;
|
||||
|
||||
|
@ -147,7 +145,6 @@ v3d_irq(int irq, void *arg)
|
|||
struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv;
|
||||
u64 runtime = local_clock() - file->start_ns[V3D_CSD];
|
||||
|
||||
file->enabled_ns[V3D_CSD] += local_clock() - file->start_ns[V3D_CSD];
|
||||
file->jobs_sent[V3D_CSD]++;
|
||||
v3d->queue[V3D_CSD].jobs_sent++;
|
||||
|
||||
|
@ -195,7 +192,6 @@ v3d_hub_irq(int irq, void *arg)
|
|||
struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv;
|
||||
u64 runtime = local_clock() - file->start_ns[V3D_TFU];
|
||||
|
||||
file->enabled_ns[V3D_TFU] += local_clock() - file->start_ns[V3D_TFU];
|
||||
file->jobs_sent[V3D_TFU]++;
|
||||
v3d->queue[V3D_TFU].jobs_sent++;
|
||||
|
||||
|
|
|
@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
|
|||
.no_wait_gpu = false
|
||||
};
|
||||
u32 j, initial_line = dst_offset / dst_stride;
|
||||
struct vmw_bo_blit_line_data d;
|
||||
struct vmw_bo_blit_line_data d = {0};
|
||||
int ret = 0;
|
||||
struct page **dst_pages = NULL;
|
||||
struct page **src_pages = NULL;
|
||||
|
||||
/* Buffer objects need to be either pinned or reserved: */
|
||||
if (!(dst->pin_count))
|
||||
|
@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!src->ttm->pages && src->ttm->sg) {
|
||||
src_pages = kvmalloc_array(src->ttm->num_pages,
|
||||
sizeof(struct page *), GFP_KERNEL);
|
||||
if (!src_pages)
|
||||
return -ENOMEM;
|
||||
ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
|
||||
src->ttm->num_pages);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
if (!dst->ttm->pages && dst->ttm->sg) {
|
||||
dst_pages = kvmalloc_array(dst->ttm->num_pages,
|
||||
sizeof(struct page *), GFP_KERNEL);
|
||||
if (!dst_pages) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
|
||||
dst->ttm->num_pages);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
d.mapped_dst = 0;
|
||||
d.mapped_src = 0;
|
||||
d.dst_addr = NULL;
|
||||
d.src_addr = NULL;
|
||||
d.dst_pages = dst->ttm->pages;
|
||||
d.src_pages = src->ttm->pages;
|
||||
d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
|
||||
d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
|
||||
d.dst_num_pages = PFN_UP(dst->resource->size);
|
||||
d.src_num_pages = PFN_UP(src->resource->size);
|
||||
d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
|
||||
|
@ -504,6 +529,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
|
|||
kunmap_atomic(d.src_addr);
|
||||
if (d.dst_addr)
|
||||
kunmap_atomic(d.dst_addr);
|
||||
if (src_pages)
|
||||
kvfree(src_pages);
|
||||
if (dst_pages)
|
||||
kvfree(dst_pages);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
|
|||
{
|
||||
struct ttm_operation_ctx ctx = {
|
||||
.interruptible = params->bo_type != ttm_bo_type_kernel,
|
||||
.no_wait_gpu = false
|
||||
.no_wait_gpu = false,
|
||||
.resv = params->resv,
|
||||
};
|
||||
struct ttm_device *bdev = &dev_priv->bdev;
|
||||
struct drm_device *vdev = &dev_priv->drm;
|
||||
|
@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
|
|||
|
||||
vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
|
||||
ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
|
||||
&vmw_bo->placement, 0, &ctx, NULL,
|
||||
NULL, destroy);
|
||||
&vmw_bo->placement, 0, &ctx,
|
||||
params->sg, params->resv, destroy);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ struct vmw_bo_params {
|
|||
enum ttm_bo_type bo_type;
|
||||
size_t size;
|
||||
bool pin;
|
||||
struct dma_resv *resv;
|
||||
struct sg_table *sg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {
|
|||
|
||||
.prime_fd_to_handle = vmw_prime_fd_to_handle,
|
||||
.prime_handle_to_fd = vmw_prime_handle_to_fd,
|
||||
.gem_prime_import_sg_table = vmw_prime_import_sg_table,
|
||||
|
||||
.fops = &vmwgfx_driver_fops,
|
||||
.name = VMWGFX_DRIVER_NAME,
|
||||
|
|
|
@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
|
|||
struct drm_file *file_priv,
|
||||
uint32_t handle, uint32_t flags,
|
||||
int *prime_fd);
|
||||
struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *table);
|
||||
|
||||
/*
|
||||
* MemoryOBject management - vmwgfx_mob.c
|
||||
|
|
|
@ -149,6 +149,38 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *table)
|
||||
{
|
||||
int ret;
|
||||
struct vmw_private *dev_priv = vmw_priv(dev);
|
||||
struct drm_gem_object *gem = NULL;
|
||||
struct vmw_bo *vbo;
|
||||
struct vmw_bo_params params = {
|
||||
.domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
|
||||
.busy_domain = VMW_BO_DOMAIN_SYS,
|
||||
.bo_type = ttm_bo_type_sg,
|
||||
.size = attach->dmabuf->size,
|
||||
.pin = false,
|
||||
.resv = attach->dmabuf->resv,
|
||||
.sg = table,
|
||||
|
||||
};
|
||||
|
||||
dma_resv_lock(params.resv, NULL);
|
||||
|
||||
ret = vmw_bo_create(dev_priv, ¶ms, &vbo);
|
||||
if (ret != 0)
|
||||
goto out_no_bo;
|
||||
|
||||
vbo->tbo.base.funcs = &vmw_gem_object_funcs;
|
||||
|
||||
gem = &vbo->tbo.base;
|
||||
out_no_bo:
|
||||
dma_resv_unlock(params.resv);
|
||||
return gem;
|
||||
}
|
||||
|
||||
int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp)
|
||||
|
|
|
@ -933,6 +933,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
|
|||
int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct vmw_private *vmw = vmw_priv(crtc->dev);
|
||||
struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state,
|
||||
crtc);
|
||||
struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
|
||||
|
@ -940,9 +941,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
bool has_primary = new_state->plane_mask &
|
||||
drm_plane_mask(crtc->primary);
|
||||
|
||||
/* We always want to have an active plane with an active CRTC */
|
||||
if (has_primary != new_state->enable)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* This is fine in general, but broken userspace might expect
|
||||
* some actual rendering so give a clue as why it's blank.
|
||||
*/
|
||||
if (new_state->enable && !has_primary)
|
||||
drm_dbg_driver(&vmw->drm,
|
||||
"CRTC without a primary plane will be blank.\n");
|
||||
|
||||
|
||||
if (new_state->connector_mask != connector_mask &&
|
||||
|
|
|
@ -243,10 +243,10 @@ struct vmw_framebuffer_bo {
|
|||
|
||||
|
||||
static const uint32_t __maybe_unused vmw_primary_plane_formats[] = {
|
||||
DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_XRGB1555,
|
||||
};
|
||||
|
||||
static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = {
|
||||
|
|
|
@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev,
|
|||
int fd, u32 *handle)
|
||||
{
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
int ret = ttm_prime_fd_to_handle(tfile, fd, handle);
|
||||
|
||||
return ttm_prime_fd_to_handle(tfile, fd, handle);
|
||||
if (ret)
|
||||
ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vmw_prime_handle_to_fd(struct drm_device *dev,
|
||||
|
@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
|
|||
int *prime_fd)
|
||||
{
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
|
||||
int ret;
|
||||
|
||||
if (handle > VMWGFX_NUM_MOB)
|
||||
ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
|
||||
else
|
||||
ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
|
|||
switch (dev_priv->map_mode) {
|
||||
case vmw_dma_map_bind:
|
||||
case vmw_dma_map_populate:
|
||||
vsgt->sgt = &vmw_tt->sgt;
|
||||
ret = sg_alloc_table_from_pages_segment(
|
||||
&vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
|
||||
(unsigned long)vsgt->num_pages << PAGE_SHIFT,
|
||||
dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out_sg_alloc_fail;
|
||||
if (vmw_tt->dma_ttm.page_flags & TTM_TT_FLAG_EXTERNAL) {
|
||||
vsgt->sgt = vmw_tt->dma_ttm.sg;
|
||||
} else {
|
||||
vsgt->sgt = &vmw_tt->sgt;
|
||||
ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt,
|
||||
vsgt->pages, vsgt->num_pages, 0,
|
||||
(unsigned long)vsgt->num_pages << PAGE_SHIFT,
|
||||
dma_get_max_seg_size(dev_priv->drm.dev),
|
||||
GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out_sg_alloc_fail;
|
||||
}
|
||||
|
||||
ret = vmw_ttm_map_for_dma(vmw_tt);
|
||||
if (unlikely(ret != 0))
|
||||
|
@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
|
|||
return 0;
|
||||
|
||||
out_map_fail:
|
||||
sg_free_table(vmw_tt->vsgt.sgt);
|
||||
vmw_tt->vsgt.sgt = NULL;
|
||||
drm_warn(&dev_priv->drm, "VSG table map failed!");
|
||||
sg_free_table(vsgt->sgt);
|
||||
vsgt->sgt = NULL;
|
||||
out_sg_alloc_fail:
|
||||
return ret;
|
||||
}
|
||||
|
@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
|
|||
static int vmw_ttm_populate(struct ttm_device *bdev,
|
||||
struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
|
||||
|
||||
/* TODO: maybe completely drop this ? */
|
||||
if (ttm_tt_is_populated(ttm))
|
||||
return 0;
|
||||
|
||||
ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
|
||||
if (external && ttm->sg)
|
||||
return drm_prime_sg_to_dma_addr_array(ttm->sg,
|
||||
ttm->dma_address,
|
||||
ttm->num_pages);
|
||||
|
||||
return ret;
|
||||
return ttm_pool_alloc(&bdev->pool, ttm, ctx);
|
||||
}
|
||||
|
||||
static void vmw_ttm_unpopulate(struct ttm_device *bdev,
|
||||
|
@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev,
|
|||
{
|
||||
struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
|
||||
dma_ttm);
|
||||
bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
|
||||
|
||||
if (external)
|
||||
return;
|
||||
|
||||
vmw_ttm_unbind(bdev, ttm);
|
||||
|
||||
|
@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
|
|||
{
|
||||
struct vmw_ttm_tt *vmw_be;
|
||||
int ret;
|
||||
bool external = bo->type == ttm_bo_type_sg;
|
||||
|
||||
vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
|
||||
if (!vmw_be)
|
||||
|
@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
|
|||
vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
|
||||
vmw_be->mob = NULL;
|
||||
|
||||
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
|
||||
if (external)
|
||||
page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE;
|
||||
|
||||
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)
|
||||
ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,
|
||||
ttm_cached);
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue