88#include <linux/aperture.h>
99#include <linux/delay.h>
1010#include <linux/fault-inject.h>
11+ #include <linux/jiffies.h>
1112#include <linux/units.h>
1213
1314#include <drm/drm_atomic_helper.h>
@@ -65,9 +66,13 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
6566{
6667 struct xe_device * xe = to_xe_device (dev );
6768 struct xe_drm_client * client ;
69+ struct xe_user * user ;
6870 struct xe_file * xef ;
6971 int ret = - ENOMEM ;
72+ unsigned long flags ;
73+ unsigned int uid = 0 ;
7074 struct task_struct * task = NULL ;
75+ const struct cred * cred = NULL ;
7176
7277 xef = kzalloc (sizeof (* xef ), GFP_KERNEL );
7378 if (!xef )
@@ -94,11 +99,52 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
9499
95100 task = get_pid_task (rcu_access_pointer (file -> pid ), PIDTYPE_PID );
96101 if (task ) {
102+ cred = get_task_cred (task );
103+ if (cred ) {
104+ uid = cred -> euid .val ;
105+ put_cred (cred );
106+ }
97107 xef -> process_name = kstrdup (task -> comm , GFP_KERNEL );
98108 xef -> pid = task -> pid ;
99109 put_task_struct (task );
100110 }
101111
112+ /*
113+ * Check if the calling process/uid has already been registered
114+ * by the xe driver during a previous file open call. If so then
115+ * take a reference to this xe file and add it to the list of xe
116+ * files belonging to the this process' xe user
117+ */
118+ spin_lock_irqsave (& xe -> work_period .lock , flags );
119+ list_for_each_entry (user , & xe -> work_period .user_list , entry ) {
120+ if (user -> uid == uid ) {
121+ xef -> user = xe_user_get (user );
122+ goto filelist_add ;
123+ }
124+ }
125+ /* list_add could be ordered wrt to list_for_each_entry */
126+ smp_mb ();
127+
128+ /*
129+ * We couldn't find a xe user for this process. allocate a new
130+ * xe user structure and register it to the xe driver
131+ */
132+ user = xe_user_alloc (uid );
133+ if (!user ) {
134+ goto spin_unlk ;
135+ }
136+
137+ user -> last_timestamp_ns = ktime_get_raw_ns ();
138+ list_add (& user -> entry , & xe -> work_period .user_list );
139+ xef -> user = user ;
140+
141+ filelist_add :
142+ spin_lock (& user -> filelist_lock );
143+ list_add (& xef -> user_link , & user -> filelist );
144+ spin_unlock (& user -> filelist_lock );
145+ user -> xe = xe ;
146+ spin_unlk :
147+ spin_unlock_irqrestore (& xe -> work_period .lock , flags );
102148 return 0 ;
103149}
104150
@@ -113,6 +159,9 @@ static void xe_file_destroy(struct kref *ref)
113159
114160 xe_drm_client_put (xef -> client );
115161 kfree (xef -> process_name );
162+
163+ list_del (& xef -> user_link );
164+ xe_user_put (xef -> user );
116165 kfree (xef );
117166}
118167
@@ -231,6 +280,24 @@ static long xe_drm_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo
231280#define xe_drm_compat_ioctl NULL
232281#endif
233282
283+ static void work_period_timer_fn (struct timer_list * timer )
284+ {
285+ struct xe_device * xe = container_of (timer , typeof (* xe ), work_period .timer );
286+ struct xe_user * user ;
287+ unsigned long timeout = 0 ;
288+
289+ spin_lock (& xe -> work_period .lock );
290+ if (!list_empty (& xe -> work_period .user_list )) {
291+ list_for_each_entry (user , & xe -> work_period .user_list , entry ) {
292+ queue_work (xe -> work_period .wq , & user -> work );
293+ }
294+ }
295+ spin_unlock (& xe -> work_period .lock );
296+ timeout = jiffies + msecs_to_jiffies (500 );
297+
298+ mod_timer (timer , timeout );
299+ }
300+
234301static const struct file_operations xe_driver_fops = {
235302 .owner = THIS_MODULE ,
236303 .open = drm_open ,
@@ -291,6 +358,11 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy)
291358 if (xe -> destroy_wq )
292359 destroy_workqueue (xe -> destroy_wq );
293360
361+ if (xe -> work_period .wq )
362+ destroy_workqueue (xe -> work_period .wq );
363+
364+ del_timer (& xe -> work_period .timer );
365+
294366 ttm_device_fini (& xe -> ttm );
295367}
296368
@@ -350,13 +422,22 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
350422 INIT_LIST_HEAD (& xe -> pinned .external_vram );
351423 INIT_LIST_HEAD (& xe -> pinned .evicted );
352424
425+ spin_lock_init (& xe -> work_period .lock );
426+ INIT_LIST_HEAD (& xe -> work_period .user_list );
427+ timer_setup (& xe -> work_period .timer , work_period_timer_fn , 0 );
428+ xe -> work_period .timer .expires = jiffies + msecs_to_jiffies (1000 );
429+ add_timer (& xe -> work_period .timer );
430+
431+ xe -> work_period .wq = alloc_workqueue ("xe-work-period-wq" , 0 , 0 );
432+
353433 xe -> preempt_fence_wq = alloc_ordered_workqueue ("xe-preempt-fence-wq" ,
354434 WQ_MEM_RECLAIM );
355435 xe -> ordered_wq = alloc_ordered_workqueue ("xe-ordered-wq" , 0 );
356436 xe -> unordered_wq = alloc_workqueue ("xe-unordered-wq" , 0 , 0 );
357437 xe -> destroy_wq = alloc_workqueue ("xe-destroy-wq" , 0 , 0 );
358438 if (!xe -> ordered_wq || !xe -> unordered_wq ||
359- !xe -> preempt_fence_wq || !xe -> destroy_wq ) {
439+ !xe -> preempt_fence_wq || !xe -> destroy_wq ||
440+ !xe -> work_period .wq ) {
360441 /*
361442 * Cleanup done in xe_device_destroy via
362443 * drmm_add_action_or_reset register above
0 commit comments