drm/i915/gvt: clean up unsubmited workloads before destroying kmem cache

This is to fix a memory leak issue caused by unfreed gvtg workload objects.
Walk through the workload list and free all of the remained workloads
before destroying kmem cache.

[179.885211] INFO: Object 0xffff9cef10003b80 @offset=7040
[179.885657] kmem_cache_destroy gvt-g_vgpu_workload: Slab cache still has objects
[179.886146] CPU: 2 PID: 2318 Comm: win_lucas Tainted: G    B   W       4.11.0+ #1
[179.887223] Call Trace:
[179.887394]  dump_stack+0x63/0x90
[179.887617]  kmem_cache_destroy+0x1cf/0x1e0
[179.887960]  intel_vgpu_clean_execlist+0x15/0x20 [i915]
[179.888365]  intel_gvt_destroy_vgpu+0x4c/0xd0 [i915]
[179.888688]  intel_vgpu_remove+0x2a/0x30 [kvmgt]
[179.888988]  mdev_device_remove_ops+0x23/0x50 [mdev]
[179.889309]  mdev_device_remove+0xe4/0x190 [mdev]
[179.889615]  remove_store+0x7d/0xb0 [mdev]
[179.889885]  dev_attr_store+0x18/0x30
[179.890129]  sysfs_kf_write+0x37/0x40
[179.890371]  kernfs_fop_write+0x107/0x180
[179.890632]  __vfs_write+0x37/0x160
[179.890865]  ? kmem_cache_alloc+0xd7/0x1b0
[179.891116]  ? apparmor_file_permission+0x1a/0x20
[179.891372]  ? security_file_permission+0x3b/0xc0
[179.891628]  vfs_write+0xb8/0x1b0
[179.891812]  SyS_write+0x55/0xc0
[179.891992]  entry_SYSCALL_64_fastpath+0x1e/0xad

Signed-off-by: Changbin Du <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
This commit is contained in:
Changbin Du 2017-05-22 17:46:58 +08:00 коммит произвёл Zhenyu Wang
Родитель 1999f108c9
Коммит e274086e47
1 изменённых файлов: 20 добавлений и 10 удалений

Просмотреть файл

@ -779,8 +779,26 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
}
static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_engine_cs *engine;
struct intel_vgpu_workload *pos, *n;
unsigned int tmp;
/* free the unsubmited workloads in the queues. */
for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
list_for_each_entry_safe(pos, n,
&vgpu->workload_q_head[engine->id], list) {
list_del_init(&pos->list);
free_workload(pos);
}
}
}
void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)
{
clean_workloads(vgpu, ALL_ENGINES);
kmem_cache_destroy(vgpu->workloads);
}
@ -811,17 +829,9 @@ void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_engine_cs *engine;
struct intel_vgpu_workload *pos, *n;
unsigned int tmp;
for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
/* free the unsubmited workload in the queue */
list_for_each_entry_safe(pos, n,
&vgpu->workload_q_head[engine->id], list) {
list_del_init(&pos->list);
free_workload(pos);
}
clean_workloads(vgpu, engine_mask);
for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
init_vgpu_execlist(vgpu, engine->id);
}
}