Skip to content

Commit 1df07a7

Browse files
committed
Merge branch 'vmwgfx-fixes-4.20' of git://people.freedesktop.org/~thomash/linux into drm-fixes
One regression fix for avoiding kernel OOM, one cleanup return fix. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Hellstrom <thellstrom@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181213122815.10581-1-thellstrom@vmware.com
2 parents a805ce6 + fd56746 commit 1df07a7

File tree

6 files changed

+103
-4
lines changed

6 files changed

+103
-4
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949

5050
#define VMWGFX_REPO "In Tree"
5151

52+
#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE)
53+
5254

5355
/**
5456
* Fully encoded drm commands. Might move to vmw_drm.h
@@ -918,7 +920,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
918920
spin_unlock(&dev_priv->cap_lock);
919921
}
920922

921-
923+
vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN);
922924
ret = vmw_kms_init(dev_priv);
923925
if (unlikely(ret != 0))
924926
goto out_no_kms;

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,9 @@ struct vmw_private {
606606

607607
struct vmw_cmdbuf_man *cman;
608608
DECLARE_BITMAP(irqthread_pending, VMW_IRQTHREAD_MAX);
609+
610+
/* Validation memory reservation */
611+
struct vmw_validation_mem vvm;
609612
};
610613

611614
static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
@@ -846,6 +849,8 @@ extern int vmw_ttm_global_init(struct vmw_private *dev_priv);
846849
extern void vmw_ttm_global_release(struct vmw_private *dev_priv);
847850
extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
848851

852+
extern void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv,
853+
size_t gran);
849854
/**
850855
* TTM buffer object driver - vmwgfx_ttm_buffer.c
851856
*/

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,6 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
17381738
void *buf)
17391739
{
17401740
struct vmw_buffer_object *vmw_bo;
1741-
int ret;
17421741

17431742
struct {
17441743
uint32_t header;
@@ -1748,7 +1747,6 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
17481747
return vmw_translate_guest_ptr(dev_priv, sw_context,
17491748
&cmd->body.ptr,
17501749
&vmw_bo);
1751-
return ret;
17521750
}
17531751

17541752

@@ -3837,6 +3835,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
38373835
struct sync_file *sync_file = NULL;
38383836
DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
38393837

3838+
vmw_validation_set_val_mem(&val_ctx, &dev_priv->vvm);
3839+
38403840
if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
38413841
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
38423842
if (out_fence_fd < 0) {

drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,39 @@ void vmw_ttm_global_release(struct vmw_private *dev_priv)
9696
drm_global_item_unref(&dev_priv->bo_global_ref.ref);
9797
drm_global_item_unref(&dev_priv->mem_global_ref);
9898
}
99+
100+
/* struct vmw_validation_mem callback */
101+
static int vmw_vmt_reserve(struct vmw_validation_mem *m, size_t size)
102+
{
103+
static struct ttm_operation_ctx ctx = {.interruptible = false,
104+
.no_wait_gpu = false};
105+
struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
106+
107+
return ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ctx);
108+
}
109+
110+
/* struct vmw_validation_mem callback */
111+
static void vmw_vmt_unreserve(struct vmw_validation_mem *m, size_t size)
112+
{
113+
struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm);
114+
115+
return ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
116+
}
117+
118+
/**
119+
* vmw_validation_mem_init_ttm - Interface the validation memory tracker
120+
* to ttm.
121+
* @dev_priv: Pointer to struct vmw_private. The reason we choose a vmw private
122+
* rather than a struct vmw_validation_mem is to make sure assumption in the
123+
* callbacks that struct vmw_private derives from struct vmw_validation_mem
124+
* holds true.
125+
* @gran: The recommended allocation granularity
126+
*/
127+
void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv, size_t gran)
128+
{
129+
struct vmw_validation_mem *vvm = &dev_priv->vvm;
130+
131+
vvm->reserve_mem = vmw_vmt_reserve;
132+
vvm->unreserve_mem = vmw_vmt_unreserve;
133+
vvm->gran = gran;
134+
}

drivers/gpu/drm/vmwgfx/vmwgfx_validation.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,25 @@ void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
104104
return NULL;
105105

106106
if (ctx->mem_size_left < size) {
107-
struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
107+
struct page *page;
108108

109+
if (ctx->vm && ctx->vm_size_left < PAGE_SIZE) {
110+
int ret = ctx->vm->reserve_mem(ctx->vm, ctx->vm->gran);
111+
112+
if (ret)
113+
return NULL;
114+
115+
ctx->vm_size_left += ctx->vm->gran;
116+
ctx->total_mem += ctx->vm->gran;
117+
}
118+
119+
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
109120
if (!page)
110121
return NULL;
111122

123+
if (ctx->vm)
124+
ctx->vm_size_left -= PAGE_SIZE;
125+
112126
list_add_tail(&page->lru, &ctx->page_list);
113127
ctx->page_address = page_address(page);
114128
ctx->mem_size_left = PAGE_SIZE;
@@ -138,6 +152,11 @@ static void vmw_validation_mem_free(struct vmw_validation_context *ctx)
138152
}
139153

140154
ctx->mem_size_left = 0;
155+
if (ctx->vm && ctx->total_mem) {
156+
ctx->vm->unreserve_mem(ctx->vm, ctx->total_mem);
157+
ctx->total_mem = 0;
158+
ctx->vm_size_left = 0;
159+
}
141160
}
142161

143162
/**

drivers/gpu/drm/vmwgfx/vmwgfx_validation.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@
3333
#include <linux/ww_mutex.h>
3434
#include <drm/ttm/ttm_execbuf_util.h>
3535

36+
/**
37+
* struct vmw_validation_mem - Custom interface to provide memory reservations
38+
* for the validation code.
39+
* @reserve_mem: Callback to reserve memory
40+
* @unreserve_mem: Callback to unreserve memory
41+
* @gran: Reservation granularity. Contains a hint how much memory should
42+
* be reserved in each call to @reserve_mem(). A slow implementation may want
43+
* reservation to be done in large batches.
44+
*/
45+
struct vmw_validation_mem {
46+
int (*reserve_mem)(struct vmw_validation_mem *m, size_t size);
47+
void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size);
48+
size_t gran;
49+
};
50+
3651
/**
3752
* struct vmw_validation_context - Per command submission validation context
3853
* @ht: Hash table used to find resource- or buffer object duplicates
@@ -47,6 +62,10 @@
4762
* buffer objects
4863
* @mem_size_left: Free memory left in the last page in @page_list
4964
* @page_address: Kernel virtual address of the last page in @page_list
65+
* @vm: A pointer to the memory reservation interface or NULL if no
66+
* memory reservation is needed.
67+
* @vm_size_left: Amount of reserved memory that so far has not been allocated.
68+
* @total_mem: Amount of reserved memory.
5069
*/
5170
struct vmw_validation_context {
5271
struct drm_open_hash *ht;
@@ -59,6 +78,9 @@ struct vmw_validation_context {
5978
unsigned int merge_dups;
6079
unsigned int mem_size_left;
6180
u8 *page_address;
81+
struct vmw_validation_mem *vm;
82+
size_t vm_size_left;
83+
size_t total_mem;
6284
};
6385

6486
struct vmw_buffer_object;
@@ -101,6 +123,21 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
101123
return !list_empty(&ctx->bo_list);
102124
}
103125

126+
/**
127+
* vmw_validation_set_val_mem - Register a validation mem object for
128+
* validation memory reservation
129+
* @ctx: The validation context
130+
* @vm: Pointer to a struct vmw_validation_mem
131+
*
132+
* Must be set before the first attempt to allocate validation memory.
133+
*/
134+
static inline void
135+
vmw_validation_set_val_mem(struct vmw_validation_context *ctx,
136+
struct vmw_validation_mem *vm)
137+
{
138+
ctx->vm = vm;
139+
}
140+
104141
/**
105142
* vmw_validation_set_ht - Register a hash table for duplicate finding
106143
* @ctx: The validation context

0 commit comments

Comments
 (0)