Skip to content

Commit 8b7de6a

Browse files
Jakob Bornecrantzairlied
authored andcommitted
vmwgfx: Rework fence event action
Signed-off-by: Jakob Bornecrantz <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 8bf4222 commit 8b7de6a

File tree

2 files changed

+104
-118
lines changed

2 files changed

+104
-118
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,18 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id);
657657
int vmw_overlay_num_overlays(struct vmw_private *dev_priv);
658658
int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv);
659659

660+
/**
661+
* Fence function - vmwgfx_fence.c
662+
*/
663+
664+
int vmw_event_fence_action_queue(struct drm_file *file_priv,
665+
struct vmw_fence_obj *fence,
666+
struct drm_pending_event *event,
667+
uint32_t *tv_sec,
668+
uint32_t *tv_usec,
669+
bool interruptible);
670+
671+
660672
/**
661673
* GMR Id manager
662674
*/

drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

Lines changed: 92 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ struct vmw_user_fence {
6969
* be assigned the current time tv_usec val when the fence signals.
7070
*/
7171
struct vmw_event_fence_action {
72-
struct drm_pending_event e;
7372
struct vmw_fence_action action;
73+
74+
struct drm_pending_event *event;
7475
struct vmw_fence_obj *fence;
7576
struct drm_device *dev;
76-
struct kref kref;
77-
uint32_t size;
77+
7878
uint32_t *tv_sec;
7979
uint32_t *tv_usec;
8080
};
@@ -783,49 +783,6 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
783783
TTM_REF_USAGE);
784784
}
785785

786-
/**
787-
* vmw_event_fence_action_destroy
788-
*
789-
* @kref: The struct kref embedded in a struct vmw_event_fence_action.
790-
*
791-
* The vmw_event_fence_action destructor that may be called either after
792-
* the fence action cleanup, or when the event is delivered.
793-
* It frees both the vmw_event_fence_action struct and the actual
794-
* event structure copied to user-space.
795-
*/
796-
static void vmw_event_fence_action_destroy(struct kref *kref)
797-
{
798-
struct vmw_event_fence_action *eaction =
799-
container_of(kref, struct vmw_event_fence_action, kref);
800-
struct ttm_mem_global *mem_glob =
801-
vmw_mem_glob(vmw_priv(eaction->dev));
802-
uint32_t size = eaction->size;
803-
804-
kfree(eaction->e.event);
805-
kfree(eaction);
806-
ttm_mem_global_free(mem_glob, size);
807-
}
808-
809-
810-
/**
811-
* vmw_event_fence_action_delivered
812-
*
813-
* @e: The struct drm_pending_event embedded in a struct
814-
* vmw_event_fence_action.
815-
*
816-
* The struct drm_pending_event destructor that is called by drm
817-
* once the event is delivered. Since we don't know whether this function
818-
* will be called before or after the fence action destructor, we
819-
* free a refcount and destroy if it becomes zero.
820-
*/
821-
static void vmw_event_fence_action_delivered(struct drm_pending_event *e)
822-
{
823-
struct vmw_event_fence_action *eaction =
824-
container_of(e, struct vmw_event_fence_action, e);
825-
826-
kref_put(&eaction->kref, vmw_event_fence_action_destroy);
827-
}
828-
829786

830787
/**
831788
* vmw_event_fence_action_seq_passed
@@ -836,18 +793,16 @@ static void vmw_event_fence_action_delivered(struct drm_pending_event *e)
836793
* This function is called when the seqno of the fence where @action is
837794
* attached has passed. It queues the event on the submitter's event list.
838795
* This function is always called from atomic context, and may be called
839-
* from irq context. It ups a refcount reflecting that we now have two
840-
* destructors.
796+
* from irq context.
841797
*/
842798
static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
843799
{
844800
struct vmw_event_fence_action *eaction =
845801
container_of(action, struct vmw_event_fence_action, action);
846802
struct drm_device *dev = eaction->dev;
847-
struct drm_file *file_priv = eaction->e.file_priv;
803+
struct drm_file *file_priv = eaction->event->file_priv;
848804
unsigned long irq_flags;
849805

850-
kref_get(&eaction->kref);
851806
spin_lock_irqsave(&dev->event_lock, irq_flags);
852807

853808
if (likely(eaction->tv_sec != NULL)) {
@@ -858,7 +813,7 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
858813
*eaction->tv_usec = tv.tv_usec;
859814
}
860815

861-
list_add_tail(&eaction->e.link, &file_priv->event_list);
816+
list_add_tail(&eaction->event->link, &file_priv->event_list);
862817
wake_up_all(&file_priv->event_wait);
863818
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
864819
}
@@ -878,7 +833,7 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
878833
container_of(action, struct vmw_event_fence_action, action);
879834

880835
vmw_fence_obj_unreference(&eaction->fence);
881-
kref_put(&eaction->kref, vmw_event_fence_action_destroy);
836+
kfree(eaction);
882837
}
883838

884839

@@ -946,56 +901,108 @@ void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
946901
* an error code, the caller needs to free that object.
947902
*/
948903

949-
int vmw_event_fence_action_create(struct drm_file *file_priv,
950-
struct vmw_fence_obj *fence,
951-
struct drm_event *event,
952-
uint32_t *tv_sec,
953-
uint32_t *tv_usec,
954-
bool interruptible)
904+
int vmw_event_fence_action_queue(struct drm_file *file_priv,
905+
struct vmw_fence_obj *fence,
906+
struct drm_pending_event *event,
907+
uint32_t *tv_sec,
908+
uint32_t *tv_usec,
909+
bool interruptible)
955910
{
956911
struct vmw_event_fence_action *eaction;
957-
struct ttm_mem_global *mem_glob =
958-
vmw_mem_glob(fence->fman->dev_priv);
959912
struct vmw_fence_manager *fman = fence->fman;
960-
uint32_t size = fman->event_fence_action_size +
961-
ttm_round_pot(event->length);
962-
int ret;
963-
964-
/*
965-
* Account for internal structure size as well as the
966-
* event size itself.
967-
*/
968913

969-
ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible);
970-
if (unlikely(ret != 0))
971-
return ret;
972914

973915
eaction = kzalloc(sizeof(*eaction), GFP_KERNEL);
974-
if (unlikely(eaction == NULL)) {
975-
ttm_mem_global_free(mem_glob, size);
916+
if (unlikely(eaction == NULL))
976917
return -ENOMEM;
977-
}
978918

979-
eaction->e.event = event;
980-
eaction->e.file_priv = file_priv;
981-
eaction->e.destroy = vmw_event_fence_action_delivered;
919+
eaction->event = event;
982920

983921
eaction->action.seq_passed = vmw_event_fence_action_seq_passed;
984922
eaction->action.cleanup = vmw_event_fence_action_cleanup;
985923
eaction->action.type = VMW_ACTION_EVENT;
986924

987925
eaction->fence = vmw_fence_obj_reference(fence);
988926
eaction->dev = fman->dev_priv->dev;
989-
eaction->size = size;
990927
eaction->tv_sec = tv_sec;
991928
eaction->tv_usec = tv_usec;
992929

993-
kref_init(&eaction->kref);
994930
vmw_fence_obj_add_action(fence, &eaction->action);
995931

996932
return 0;
997933
}
998934

935+
struct vmw_event_fence_pending {
936+
struct drm_pending_event base;
937+
struct drm_vmw_event_fence event;
938+
};
939+
940+
int vmw_event_fence_action_create(struct drm_file *file_priv,
941+
struct vmw_fence_obj *fence,
942+
uint32_t flags,
943+
uint64_t user_data,
944+
bool interruptible)
945+
{
946+
struct vmw_event_fence_pending *event;
947+
struct drm_device *dev = fence->fman->dev_priv->dev;
948+
unsigned long irq_flags;
949+
int ret;
950+
951+
spin_lock_irqsave(&dev->event_lock, irq_flags);
952+
953+
ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0;
954+
if (likely(ret == 0))
955+
file_priv->event_space -= sizeof(event->event);
956+
957+
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
958+
959+
if (unlikely(ret != 0)) {
960+
DRM_ERROR("Failed to allocate event space for this file.\n");
961+
goto out_no_space;
962+
}
963+
964+
965+
event = kzalloc(sizeof(event->event), GFP_KERNEL);
966+
if (unlikely(event == NULL)) {
967+
DRM_ERROR("Failed to allocate an event.\n");
968+
ret = -ENOMEM;
969+
goto out_no_event;
970+
}
971+
972+
event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
973+
event->event.base.length = sizeof(*event);
974+
event->event.user_data = user_data;
975+
976+
event->base.event = &event->event.base;
977+
event->base.file_priv = file_priv;
978+
event->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
979+
980+
981+
if (flags & DRM_VMW_FE_FLAG_REQ_TIME)
982+
ret = vmw_event_fence_action_queue(file_priv, fence,
983+
&event->base,
984+
&event->event.tv_sec,
985+
&event->event.tv_usec,
986+
interruptible);
987+
else
988+
ret = vmw_event_fence_action_queue(file_priv, fence,
989+
&event->base,
990+
NULL,
991+
NULL,
992+
interruptible);
993+
if (ret != 0)
994+
goto out_no_queue;
995+
996+
out_no_queue:
997+
event->base.destroy(&event->base);
998+
out_no_event:
999+
spin_lock_irqsave(&dev->event_lock, irq_flags);
1000+
file_priv->event_space += sizeof(*event);
1001+
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
1002+
out_no_space:
1003+
return ret;
1004+
}
1005+
9991006
int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10001007
struct drm_file *file_priv)
10011008
{
@@ -1008,8 +1015,6 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10081015
(struct drm_vmw_fence_rep __user *)(unsigned long)
10091016
arg->fence_rep;
10101017
uint32_t handle;
1011-
unsigned long irq_flags;
1012-
struct drm_vmw_event_fence *event;
10131018
int ret;
10141019

10151020
/*
@@ -1062,59 +1067,28 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10621067

10631068
BUG_ON(fence == NULL);
10641069

1065-
spin_lock_irqsave(&dev->event_lock, irq_flags);
1066-
1067-
ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0;
1068-
if (likely(ret == 0))
1069-
file_priv->event_space -= sizeof(*event);
1070-
1071-
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
1072-
1073-
if (unlikely(ret != 0)) {
1074-
DRM_ERROR("Failed to allocate event space for this file.\n");
1075-
goto out_no_event_space;
1076-
}
1077-
1078-
event = kzalloc(sizeof(*event), GFP_KERNEL);
1079-
if (unlikely(event == NULL)) {
1080-
DRM_ERROR("Failed to allocate an event.\n");
1081-
goto out_no_event;
1082-
}
1083-
1084-
event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
1085-
event->base.length = sizeof(*event);
1086-
event->user_data = arg->user_data;
1087-
10881070
if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME)
10891071
ret = vmw_event_fence_action_create(file_priv, fence,
1090-
&event->base,
1091-
&event->tv_sec,
1092-
&event->tv_usec,
1072+
arg->flags,
1073+
arg->user_data,
10931074
true);
10941075
else
10951076
ret = vmw_event_fence_action_create(file_priv, fence,
1096-
&event->base,
1097-
NULL,
1098-
NULL,
1077+
arg->flags,
1078+
arg->user_data,
10991079
true);
11001080

11011081
if (unlikely(ret != 0)) {
11021082
if (ret != -ERESTARTSYS)
11031083
DRM_ERROR("Failed to attach event to fence.\n");
1104-
goto out_no_attach;
1084+
goto out_no_create;
11051085
}
11061086

11071087
vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
11081088
handle);
11091089
vmw_fence_obj_unreference(&fence);
11101090
return 0;
1111-
out_no_attach:
1112-
kfree(event);
1113-
out_no_event:
1114-
spin_lock_irqsave(&dev->event_lock, irq_flags);
1115-
file_priv->event_space += sizeof(*event);
1116-
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
1117-
out_no_event_space:
1091+
out_no_create:
11181092
if (user_fence_rep != NULL)
11191093
ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
11201094
handle, TTM_REF_USAGE);

0 commit comments

Comments
 (0)