Commit 7315c0ed authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-fixes-2019-12-12' of...

Merge tag 'drm-misc-next-fixes-2019-12-12' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

-mgag200: more startadd mitigation (Thomas)
-panfrost: devfreq fix + several memory fixes (Steven, Boris)

Cc: Boris Brezillon <boris.brezillon@collabora.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20191212140145.GA145200@art_vandelay
parents cdf1d28c 0a523998
...@@ -30,9 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400); ...@@ -30,9 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400);
static struct drm_driver driver; static struct drm_driver driver;
static const struct pci_device_id pciidlist[] = { static const struct pci_device_id pciidlist[] = {
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_VENDOR_ID_SUN, 0x4852, 0, 0, { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD}, G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV }, { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB }, { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
......
...@@ -18,15 +18,18 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev); ...@@ -18,15 +18,18 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev);
static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags) u32 flags)
{ {
struct panfrost_device *pfdev = dev_get_drvdata(dev); struct dev_pm_opp *opp;
int err; int err;
opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp))
return PTR_ERR(opp);
dev_pm_opp_put(opp);
err = dev_pm_opp_set_rate(dev, *freq); err = dev_pm_opp_set_rate(dev, *freq);
if (err) if (err)
return err; return err;
*freq = clk_get_rate(pfdev->clock);
return 0; return 0;
} }
...@@ -60,20 +63,10 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, ...@@ -60,20 +63,10 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
return 0; return 0;
} }
static int panfrost_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct panfrost_device *pfdev = platform_get_drvdata(to_platform_device(dev));
*freq = clk_get_rate(pfdev->clock);
return 0;
}
static struct devfreq_dev_profile panfrost_devfreq_profile = { static struct devfreq_dev_profile panfrost_devfreq_profile = {
.polling_ms = 50, /* ~3 frames */ .polling_ms = 50, /* ~3 frames */
.target = panfrost_devfreq_target, .target = panfrost_devfreq_target,
.get_dev_status = panfrost_devfreq_get_dev_status, .get_dev_status = panfrost_devfreq_get_dev_status,
.get_cur_freq = panfrost_devfreq_get_cur_freq,
}; };
int panfrost_devfreq_init(struct panfrost_device *pfdev) int panfrost_devfreq_init(struct panfrost_device *pfdev)
......
...@@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data, ...@@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data,
} }
/* Don't allow mmapping of heap objects as pages are not pinned. */ /* Don't allow mmapping of heap objects as pages are not pinned. */
if (to_panfrost_bo(gem_obj)->is_heap) if (to_panfrost_bo(gem_obj)->is_heap) {
return -EINVAL; ret = -EINVAL;
goto out;
}
ret = drm_gem_create_mmap_offset(gem_obj); ret = drm_gem_create_mmap_offset(gem_obj);
if (ret == 0) if (ret == 0)
args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
drm_gem_object_put_unlocked(gem_obj);
out:
drm_gem_object_put_unlocked(gem_obj);
return ret; return ret;
} }
...@@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data, ...@@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
return -ENOENT; return -ENOENT;
} }
mutex_lock(&pfdev->shrinker_lock);
args->retained = drm_gem_shmem_madvise(gem_obj, args->madv); args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
if (args->retained) { if (args->retained) {
struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj); struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
mutex_lock(&pfdev->shrinker_lock);
if (args->madv == PANFROST_MADV_DONTNEED) if (args->madv == PANFROST_MADV_DONTNEED)
list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list); list_add_tail(&bo->base.madv_list,
&pfdev->shrinker_list);
else if (args->madv == PANFROST_MADV_WILLNEED) else if (args->madv == PANFROST_MADV_WILLNEED)
list_del_init(&bo->base.madv_list); list_del_init(&bo->base.madv_list);
mutex_unlock(&pfdev->shrinker_lock);
} }
mutex_unlock(&pfdev->shrinker_lock);
drm_gem_object_put_unlocked(gem_obj); drm_gem_object_put_unlocked(gem_obj);
return 0; return 0;
...@@ -443,7 +445,7 @@ panfrost_postclose(struct drm_device *dev, struct drm_file *file) ...@@ -443,7 +445,7 @@ panfrost_postclose(struct drm_device *dev, struct drm_file *file)
{ {
struct panfrost_file_priv *panfrost_priv = file->driver_priv; struct panfrost_file_priv *panfrost_priv = file->driver_priv;
panfrost_perfcnt_close(panfrost_priv); panfrost_perfcnt_close(file);
panfrost_job_close(panfrost_priv); panfrost_job_close(panfrost_priv);
panfrost_mmu_pgtable_free(panfrost_priv); panfrost_mmu_pgtable_free(panfrost_priv);
......
...@@ -19,6 +19,16 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) ...@@ -19,6 +19,16 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_gem_object *bo = to_panfrost_bo(obj);
struct panfrost_device *pfdev = obj->dev->dev_private; struct panfrost_device *pfdev = obj->dev->dev_private;
/*
* Make sure the BO is no longer inserted in the shrinker list before
* taking care of the destruction itself. If we don't do that we have a
* race condition between this function and what's done in
* panfrost_gem_shrinker_scan().
*/
mutex_lock(&pfdev->shrinker_lock);
list_del_init(&bo->base.madv_list);
mutex_unlock(&pfdev->shrinker_lock);
if (bo->sgts) { if (bo->sgts) {
int i; int i;
int n_sgt = bo->base.base.size / SZ_2M; int n_sgt = bo->base.base.size / SZ_2M;
...@@ -33,15 +43,10 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) ...@@ -33,15 +43,10 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
kfree(bo->sgts); kfree(bo->sgts);
} }
mutex_lock(&pfdev->shrinker_lock);
if (!list_empty(&bo->base.madv_list))
list_del(&bo->base.madv_list);
mutex_unlock(&pfdev->shrinker_lock);
drm_gem_shmem_free_object(obj); drm_gem_shmem_free_object(obj);
} }
static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv) int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
{ {
int ret; int ret;
size_t size = obj->size; size_t size = obj->size;
...@@ -80,7 +85,7 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p ...@@ -80,7 +85,7 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p
return ret; return ret;
} }
static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv) void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
{ {
struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_gem_object *bo = to_panfrost_bo(obj);
struct panfrost_file_priv *priv = file_priv->driver_priv; struct panfrost_file_priv *priv = file_priv->driver_priv;
......
...@@ -45,6 +45,10 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv, ...@@ -45,6 +45,10 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv,
u32 flags, u32 flags,
uint32_t *handle); uint32_t *handle);
int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv);
void panfrost_gem_close(struct drm_gem_object *obj,
struct drm_file *file_priv);
void panfrost_gem_shrinker_init(struct drm_device *dev); void panfrost_gem_shrinker_init(struct drm_device *dev);
void panfrost_gem_shrinker_cleanup(struct drm_device *dev); void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
......
...@@ -67,9 +67,10 @@ static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev) ...@@ -67,9 +67,10 @@ static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev)
} }
static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
struct panfrost_file_priv *user, struct drm_file *file_priv,
unsigned int counterset) unsigned int counterset)
{ {
struct panfrost_file_priv *user = file_priv->driver_priv;
struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
struct drm_gem_shmem_object *bo; struct drm_gem_shmem_object *bo;
u32 cfg; u32 cfg;
...@@ -91,14 +92,14 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, ...@@ -91,14 +92,14 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
perfcnt->bo = to_panfrost_bo(&bo->base); perfcnt->bo = to_panfrost_bo(&bo->base);
/* Map the perfcnt buf in the address space attached to file_priv. */ /* Map the perfcnt buf in the address space attached to file_priv. */
ret = panfrost_mmu_map(perfcnt->bo); ret = panfrost_gem_open(&perfcnt->bo->base.base, file_priv);
if (ret) if (ret)
goto err_put_bo; goto err_put_bo;
perfcnt->buf = drm_gem_shmem_vmap(&bo->base); perfcnt->buf = drm_gem_shmem_vmap(&bo->base);
if (IS_ERR(perfcnt->buf)) { if (IS_ERR(perfcnt->buf)) {
ret = PTR_ERR(perfcnt->buf); ret = PTR_ERR(perfcnt->buf);
goto err_put_bo; goto err_close_bo;
} }
/* /*
...@@ -157,14 +158,17 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, ...@@ -157,14 +158,17 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
err_vunmap: err_vunmap:
drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf); drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
err_close_bo:
panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
err_put_bo: err_put_bo:
drm_gem_object_put_unlocked(&bo->base); drm_gem_object_put_unlocked(&bo->base);
return ret; return ret;
} }
static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
struct panfrost_file_priv *user) struct drm_file *file_priv)
{ {
struct panfrost_file_priv *user = file_priv->driver_priv;
struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
if (user != perfcnt->user) if (user != perfcnt->user)
...@@ -180,6 +184,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, ...@@ -180,6 +184,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
perfcnt->user = NULL; perfcnt->user = NULL;
drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf); drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
perfcnt->buf = NULL; perfcnt->buf = NULL;
panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
drm_gem_object_put_unlocked(&perfcnt->bo->base.base); drm_gem_object_put_unlocked(&perfcnt->bo->base.base);
perfcnt->bo = NULL; perfcnt->bo = NULL;
pm_runtime_mark_last_busy(pfdev->dev); pm_runtime_mark_last_busy(pfdev->dev);
...@@ -191,7 +196,6 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, ...@@ -191,7 +196,6 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data, int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct panfrost_file_priv *pfile = file_priv->driver_priv;
struct panfrost_device *pfdev = dev->dev_private; struct panfrost_device *pfdev = dev->dev_private;
struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
struct drm_panfrost_perfcnt_enable *req = data; struct drm_panfrost_perfcnt_enable *req = data;
...@@ -207,10 +211,10 @@ int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data, ...@@ -207,10 +211,10 @@ int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
mutex_lock(&perfcnt->lock); mutex_lock(&perfcnt->lock);
if (req->enable) if (req->enable)
ret = panfrost_perfcnt_enable_locked(pfdev, pfile, ret = panfrost_perfcnt_enable_locked(pfdev, file_priv,
req->counterset); req->counterset);
else else
ret = panfrost_perfcnt_disable_locked(pfdev, pfile); ret = panfrost_perfcnt_disable_locked(pfdev, file_priv);
mutex_unlock(&perfcnt->lock); mutex_unlock(&perfcnt->lock);
return ret; return ret;
...@@ -248,15 +252,16 @@ int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data, ...@@ -248,15 +252,16 @@ int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data,
return ret; return ret;
} }
void panfrost_perfcnt_close(struct panfrost_file_priv *pfile) void panfrost_perfcnt_close(struct drm_file *file_priv)
{ {
struct panfrost_file_priv *pfile = file_priv->driver_priv;
struct panfrost_device *pfdev = pfile->pfdev; struct panfrost_device *pfdev = pfile->pfdev;
struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
pm_runtime_get_sync(pfdev->dev); pm_runtime_get_sync(pfdev->dev);
mutex_lock(&perfcnt->lock); mutex_lock(&perfcnt->lock);
if (perfcnt->user == pfile) if (perfcnt->user == pfile)
panfrost_perfcnt_disable_locked(pfdev, pfile); panfrost_perfcnt_disable_locked(pfdev, file_priv);
mutex_unlock(&perfcnt->lock); mutex_unlock(&perfcnt->lock);
pm_runtime_mark_last_busy(pfdev->dev); pm_runtime_mark_last_busy(pfdev->dev);
pm_runtime_put_autosuspend(pfdev->dev); pm_runtime_put_autosuspend(pfdev->dev);
......
...@@ -9,7 +9,7 @@ void panfrost_perfcnt_sample_done(struct panfrost_device *pfdev); ...@@ -9,7 +9,7 @@ void panfrost_perfcnt_sample_done(struct panfrost_device *pfdev);
void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev); void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev);
int panfrost_perfcnt_init(struct panfrost_device *pfdev); int panfrost_perfcnt_init(struct panfrost_device *pfdev);
void panfrost_perfcnt_fini(struct panfrost_device *pfdev); void panfrost_perfcnt_fini(struct panfrost_device *pfdev);
void panfrost_perfcnt_close(struct panfrost_file_priv *pfile); void panfrost_perfcnt_close(struct drm_file *file_priv);
int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data, int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data, int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment