@@ -516,7 +516,9 @@ static __always_inline bool evdi_swap_dequeue_for_file(struct evdi_device *evdi,
516516 int * out_poll_id )
517517{
518518 struct evdi_file_priv * priv ;
519- int start , i ;
519+ struct drm_file * owner ;
520+ int start , i , poll_id , d ;
521+ u64 seq , payload ;
520522
521523 if (unlikely (!evdi || !file || !out || !out_poll_id ))
522524 return false;
@@ -527,10 +529,7 @@ static __always_inline bool evdi_swap_dequeue_for_file(struct evdi_device *evdi,
527529
528530 start = (int )(priv -> swap_rr % LINDROID_MAX_CONNECTORS );
529531 for (i = 0 ; i < LINDROID_MAX_CONNECTORS ; i ++ ) {
530- const int d = (start + i ) % LINDROID_MAX_CONNECTORS ;
531- u64 seq , payload ;
532- int poll_id ;
533- struct drm_file * owner ;
532+ d = (start + i ) % LINDROID_MAX_CONNECTORS ;
534533
535534 if (!evdi_swap_mailbox_read_stable (evdi , d , & seq , & payload , & poll_id , & owner ))
536535 continue ;
@@ -578,26 +577,15 @@ int evdi_ioctl_poll(struct drm_device *dev, void *data, struct drm_file *file)
578577 }
579578
580579 event = evdi_event_dequeue (evdi );
581- if (likely (event )) {
582- cmd -> event = event -> type ;
583- cmd -> poll_id = event -> poll_id ;
584- payload_size = evdi_event_serialize_payload (event ,
585- payload_buf , sizeof (payload_buf ));
586- if (payload_size && cmd -> data ) {
587- if (evdi_copy_to_user_allow_partial (cmd -> data ,
588- payload_buf , payload_size )) {
589- evdi_event_free (event );
590- return - EFAULT ;
591- }
592- }
593- evdi_event_free (event );
594- return 0 ;
580+ if (event ) {
581+ goto deliver ;
595582 }
596583
597584 ret = evdi_event_wait (evdi , file );
598585 if (ret )
599586 return ret ;
600587
588+ /* Check mailbox again after wake */
601589 if (evdi_swap_dequeue_for_file (evdi , file , & sw , & poll_id )) {
602590 cmd -> event = swap_to ;
603591 cmd -> poll_id = poll_id ;
@@ -613,16 +601,19 @@ int evdi_ioctl_poll(struct drm_device *dev, void *data, struct drm_file *file)
613601 if (!event )
614602 return - EAGAIN ;
615603
604+ deliver :
616605 cmd -> event = event -> type ;
617606 cmd -> poll_id = event -> poll_id ;
618607
619- payload_size = evdi_event_serialize_payload (event , payload_buf ,
620- sizeof (payload_buf ));
608+ payload_size = evdi_event_serialize_payload (event ,
609+ payload_buf , sizeof (payload_buf ));
610+
621611 if (payload_size && cmd -> data ) {
622612 if (evdi_copy_to_user_allow_partial (cmd -> data ,
623- payload_buf , payload_size )) {
624- evdi_event_free (event );
625- return - EFAULT ;
613+ payload_buf ,
614+ payload_size )) {
615+ evdi_event_free (event );
616+ return - EFAULT ;
626617 }
627618 }
628619
@@ -991,35 +982,6 @@ int evdi_ioctl_destroy_buff_callback(struct drm_device *dev, void *data, struct
991982 return 0 ;
992983}
993984
994- int evdi_ioctl_swap_callback (struct drm_device * dev , void * data , struct drm_file * file )
995- {
996- struct evdi_device * evdi = dev -> dev_private ;
997-
998- struct drm_evdi_swap_callback * cb = data ;
999- int d ;
1000-
1001- if (unlikely (!evdi || !cb ))
1002- return - EINVAL ;
1003-
1004- for (d = 0 ; d < LINDROID_MAX_CONNECTORS ; d ++ ) {
1005- if (!atomic_read (& evdi -> swap_pending [d ]))
1006- continue ;
1007- if (atomic_read (& evdi -> swap_pending_pollid [d ]) != cb -> poll_id )
1008- continue ;
1009-
1010- atomic_set (& evdi -> swap_pending_pollid [d ], 0 );
1011- atomic_set (& evdi -> swap_pending [d ], 0 );
1012- wake_up_interruptible (& evdi -> swap_ack_waitq );
1013- break ;
1014- }
1015-
1016- EVDI_PERF_INC64 (& evdi_perf .ioctl_calls [5 ]);
1017-
1018- evdi_wakeup_pollers (evdi );
1019-
1020- return 0 ;
1021- }
1022-
1023985int evdi_ioctl_create_buff_callback (struct drm_device * dev , void * data , struct drm_file * file )
1024986{
1025987 struct evdi_device * evdi = dev -> dev_private ;
@@ -1078,36 +1040,32 @@ static int evdi_queue_int_event(struct evdi_device *evdi,
10781040int evdi_queue_swap_event (struct evdi_device * evdi ,
10791041 int id , int display_id , struct drm_file * owner )
10801042{
1081- struct evdi_swap_mailbox * mb ;
10821043 struct drm_file * client ;
1044+ struct evdi_swap_mailbox * mb ;
10831045 u64 payload ;
10841046 int poll_id ;
10851047
10861048 if (unlikely (!evdi ))
10871049 return - EINVAL ;
1050+
10881051 if (unlikely (display_id < 0 || display_id >= LINDROID_MAX_CONNECTORS ))
10891052 return - EINVAL ;
1053+
10901054 if (unlikely (atomic_read (& evdi -> events .stopping )))
10911055 return - ENODEV ;
10921056
1093- /* Do not overwrite an un-ACKed swap */
1094- if (atomic_cmpxchg (& evdi -> swap_pending [display_id ], 0 , 1 ) != 0 )
1095- return - EBUSY ;
1096-
10971057 client = READ_ONCE (evdi -> drm_client );
1058+
10981059 if (client )
10991060 owner = client ;
11001061
1101- if (unlikely (!owner )) {
1102- atomic_set (& evdi -> swap_pending [display_id ], 0 );
1062+ if (unlikely (!owner ))
11031063 return - ENODEV ;
1104- }
11051064
11061065 mb = & evdi -> swap_mailbox [display_id ];
11071066 payload = evdi_swap_pack (id , display_id );
1108- poll_id = atomic_inc_return (& evdi -> events .next_poll_id );
11091067
1110- atomic_set (& evdi -> swap_pending_pollid [ display_id ], poll_id );
1068+ poll_id = atomic_inc_return (& evdi -> events . next_poll_id );
11111069
11121070 atomic64_inc (& mb -> seq ); // odd
11131071 WRITE_ONCE (mb -> owner , owner );
@@ -1117,7 +1075,12 @@ int evdi_queue_swap_event(struct evdi_device *evdi,
11171075 atomic64_inc (& mb -> seq ); // even
11181076
11191077 EVDI_PERF_INC64 (& evdi_perf .swap_updates );
1078+
1079+ // Swap events do not use the standard event queue! Do not use evdi_wakeup_pollers
1080+ // here or set wake pending!
1081+ evdi_smp_wmb ();
11201082 wake_up_interruptible (& evdi -> events .wait_queue );
1083+
11211084 return 0 ;
11221085}
11231086
@@ -1143,3 +1106,32 @@ int evdi_queue_create_event(struct evdi_device *evdi,
11431106 int poll_id = atomic_inc_return (& evdi -> events .next_poll_id );
11441107 return evdi_queue_create_event_with_id (evdi , params , owner , poll_id );
11451108}
1109+
1110+ int evdi_ioctl_vsync (struct drm_device * dev ,
1111+ void * data ,
1112+ struct drm_file * file )
1113+ {
1114+ struct evdi_device * evdi = dev -> dev_private ;
1115+ struct drm_evdi_vsync * vs = data ;
1116+ struct drm_crtc * crtc ;
1117+ int slot ;
1118+
1119+ EVDI_PERF_INC64 (& evdi_perf .ioctl_calls [2 ]);
1120+
1121+ if (unlikely (atomic_read (& evdi -> events .stopping )))
1122+ return - ENODEV ;
1123+
1124+ slot = vs -> display_id ;
1125+
1126+ if (slot < 0 || slot >= LINDROID_MAX_CONNECTORS )
1127+ return - EINVAL ;
1128+
1129+ crtc = & evdi -> pipe [slot ].crtc ;
1130+
1131+ if (drm_crtc_vblank_get (crtc ) == 0 ) {
1132+ drm_crtc_handle_vblank (crtc );
1133+ drm_crtc_vblank_put (crtc );
1134+ }
1135+
1136+ return 0 ;
1137+ }
0 commit comments