9090#include <drm/i915_drm.h>
9191
9292#include "gt/intel_lrc_reg.h"
93- #include "gt/intel_workarounds.h"
9493
9594#include "i915_drv.h"
9695#include "i915_globals.h"
@@ -141,15 +140,31 @@ static void lut_close(struct i915_gem_context *ctx)
141140}
142141
143142static struct intel_context *
144- lookup_user_engine (struct i915_gem_context * ctx , u16 class , u16 instance )
143+ lookup_user_engine (struct i915_gem_context * ctx ,
144+ unsigned long flags ,
145+ const struct i915_engine_class_instance * ci )
146+ #define LOOKUP_USER_INDEX BIT (0 )
145147{
146- struct intel_engine_cs * engine ;
148+ int idx ;
147149
148- engine = intel_engine_lookup_user (ctx -> i915 , class , instance );
149- if (!engine )
150+ if (!!(flags & LOOKUP_USER_INDEX ) != i915_gem_context_user_engines (ctx ))
150151 return ERR_PTR (- EINVAL );
151152
152- return i915_gem_context_get_engine (ctx , engine -> id );
153+ if (!i915_gem_context_user_engines (ctx )) {
154+ struct intel_engine_cs * engine ;
155+
156+ engine = intel_engine_lookup_user (ctx -> i915 ,
157+ ci -> engine_class ,
158+ ci -> engine_instance );
159+ if (!engine )
160+ return ERR_PTR (- EINVAL );
161+
162+ idx = engine -> id ;
163+ } else {
164+ idx = ci -> engine_instance ;
165+ }
166+
167+ return i915_gem_context_get_engine (ctx , idx );
153168}
154169
155170static inline int new_hw_id (struct drm_i915_private * i915 , gfp_t gfp )
@@ -257,6 +272,17 @@ static void free_engines(struct i915_gem_engines *e)
257272 __free_engines (e , e -> num_engines );
258273}
259274
275+ static void free_engines_rcu (struct work_struct * wrk )
276+ {
277+ struct i915_gem_engines * e =
278+ container_of (wrk , struct i915_gem_engines , rcu .work );
279+ struct drm_i915_private * i915 = e -> i915 ;
280+
281+ mutex_lock (& i915 -> drm .struct_mutex );
282+ free_engines (e );
283+ mutex_unlock (& i915 -> drm .struct_mutex );
284+ }
285+
260286static struct i915_gem_engines * default_engines (struct i915_gem_context * ctx )
261287{
262288 struct intel_engine_cs * engine ;
@@ -1352,9 +1378,7 @@ static int set_sseu(struct i915_gem_context *ctx,
13521378 if (user_sseu .flags || user_sseu .rsvd )
13531379 return - EINVAL ;
13541380
1355- ce = lookup_user_engine (ctx ,
1356- user_sseu .engine .engine_class ,
1357- user_sseu .engine .engine_instance );
1381+ ce = lookup_user_engine (ctx , 0 , & user_sseu .engine );
13581382 if (IS_ERR (ce ))
13591383 return PTR_ERR (ce );
13601384
@@ -1379,6 +1403,217 @@ static int set_sseu(struct i915_gem_context *ctx,
13791403 return ret ;
13801404}
13811405
1406+ struct set_engines {
1407+ struct i915_gem_context * ctx ;
1408+ struct i915_gem_engines * engines ;
1409+ };
1410+
1411+ static const i915_user_extension_fn set_engines__extensions [] = {
1412+ };
1413+
1414+ static int
1415+ set_engines (struct i915_gem_context * ctx ,
1416+ const struct drm_i915_gem_context_param * args )
1417+ {
1418+ struct i915_context_param_engines __user * user =
1419+ u64_to_user_ptr (args -> value );
1420+ struct set_engines set = { .ctx = ctx };
1421+ unsigned int num_engines , n ;
1422+ u64 extensions ;
1423+ int err ;
1424+
1425+ if (!args -> size ) { /* switch back to legacy user_ring_map */
1426+ if (!i915_gem_context_user_engines (ctx ))
1427+ return 0 ;
1428+
1429+ set .engines = default_engines (ctx );
1430+ if (IS_ERR (set .engines ))
1431+ return PTR_ERR (set .engines );
1432+
1433+ goto replace ;
1434+ }
1435+
1436+ BUILD_BUG_ON (!IS_ALIGNED (sizeof (* user ), sizeof (* user -> engines )));
1437+ if (args -> size < sizeof (* user ) ||
1438+ !IS_ALIGNED (args -> size , sizeof (* user -> engines ))) {
1439+ DRM_DEBUG ("Invalid size for engine array: %d\n" ,
1440+ args -> size );
1441+ return - EINVAL ;
1442+ }
1443+
1444+ /*
1445+ * Note that I915_EXEC_RING_MASK limits execbuf to only using the
1446+ * first 64 engines defined here.
1447+ */
1448+ num_engines = (args -> size - sizeof (* user )) / sizeof (* user -> engines );
1449+
1450+ set .engines = kmalloc (struct_size (set .engines , engines , num_engines ),
1451+ GFP_KERNEL );
1452+ if (!set .engines )
1453+ return - ENOMEM ;
1454+
1455+ set .engines -> i915 = ctx -> i915 ;
1456+ for (n = 0 ; n < num_engines ; n ++ ) {
1457+ struct i915_engine_class_instance ci ;
1458+ struct intel_engine_cs * engine ;
1459+
1460+ if (copy_from_user (& ci , & user -> engines [n ], sizeof (ci ))) {
1461+ __free_engines (set .engines , n );
1462+ return - EFAULT ;
1463+ }
1464+
1465+ if (ci .engine_class == (u16 )I915_ENGINE_CLASS_INVALID &&
1466+ ci .engine_instance == (u16 )I915_ENGINE_CLASS_INVALID_NONE ) {
1467+ set .engines -> engines [n ] = NULL ;
1468+ continue ;
1469+ }
1470+
1471+ engine = intel_engine_lookup_user (ctx -> i915 ,
1472+ ci .engine_class ,
1473+ ci .engine_instance );
1474+ if (!engine ) {
1475+ DRM_DEBUG ("Invalid engine[%d]: { class:%d, instance:%d }\n" ,
1476+ n , ci .engine_class , ci .engine_instance );
1477+ __free_engines (set .engines , n );
1478+ return - ENOENT ;
1479+ }
1480+
1481+ set .engines -> engines [n ] = intel_context_create (ctx , engine );
1482+ if (!set .engines -> engines [n ]) {
1483+ __free_engines (set .engines , n );
1484+ return - ENOMEM ;
1485+ }
1486+ }
1487+ set .engines -> num_engines = num_engines ;
1488+
1489+ err = - EFAULT ;
1490+ if (!get_user (extensions , & user -> extensions ))
1491+ err = i915_user_extensions (u64_to_user_ptr (extensions ),
1492+ set_engines__extensions ,
1493+ ARRAY_SIZE (set_engines__extensions ),
1494+ & set );
1495+ if (err ) {
1496+ free_engines (set .engines );
1497+ return err ;
1498+ }
1499+
1500+ replace :
1501+ mutex_lock (& ctx -> engines_mutex );
1502+ if (args -> size )
1503+ i915_gem_context_set_user_engines (ctx );
1504+ else
1505+ i915_gem_context_clear_user_engines (ctx );
1506+ rcu_swap_protected (ctx -> engines , set .engines , 1 );
1507+ mutex_unlock (& ctx -> engines_mutex );
1508+
1509+ INIT_RCU_WORK (& set .engines -> rcu , free_engines_rcu );
1510+ queue_rcu_work (system_wq , & set .engines -> rcu );
1511+
1512+ return 0 ;
1513+ }
1514+
1515+ static struct i915_gem_engines *
1516+ __copy_engines (struct i915_gem_engines * e )
1517+ {
1518+ struct i915_gem_engines * copy ;
1519+ unsigned int n ;
1520+
1521+ copy = kmalloc (struct_size (e , engines , e -> num_engines ), GFP_KERNEL );
1522+ if (!copy )
1523+ return ERR_PTR (- ENOMEM );
1524+
1525+ copy -> i915 = e -> i915 ;
1526+ for (n = 0 ; n < e -> num_engines ; n ++ ) {
1527+ if (e -> engines [n ])
1528+ copy -> engines [n ] = intel_context_get (e -> engines [n ]);
1529+ else
1530+ copy -> engines [n ] = NULL ;
1531+ }
1532+ copy -> num_engines = n ;
1533+
1534+ return copy ;
1535+ }
1536+
1537+ static int
1538+ get_engines (struct i915_gem_context * ctx ,
1539+ struct drm_i915_gem_context_param * args )
1540+ {
1541+ struct i915_context_param_engines __user * user ;
1542+ struct i915_gem_engines * e ;
1543+ size_t n , count , size ;
1544+ int err = 0 ;
1545+
1546+ err = mutex_lock_interruptible (& ctx -> engines_mutex );
1547+ if (err )
1548+ return err ;
1549+
1550+ e = NULL ;
1551+ if (i915_gem_context_user_engines (ctx ))
1552+ e = __copy_engines (i915_gem_context_engines (ctx ));
1553+ mutex_unlock (& ctx -> engines_mutex );
1554+ if (IS_ERR_OR_NULL (e )) {
1555+ args -> size = 0 ;
1556+ return PTR_ERR_OR_ZERO (e );
1557+ }
1558+
1559+ count = e -> num_engines ;
1560+
1561+ /* Be paranoid in case we have an impedance mismatch */
1562+ if (!check_struct_size (user , engines , count , & size )) {
1563+ err = - EINVAL ;
1564+ goto err_free ;
1565+ }
1566+ if (overflows_type (size , args -> size )) {
1567+ err = - EINVAL ;
1568+ goto err_free ;
1569+ }
1570+
1571+ if (!args -> size ) {
1572+ args -> size = size ;
1573+ goto err_free ;
1574+ }
1575+
1576+ if (args -> size < size ) {
1577+ err = - EINVAL ;
1578+ goto err_free ;
1579+ }
1580+
1581+ user = u64_to_user_ptr (args -> value );
1582+ if (!access_ok (user , size )) {
1583+ err = - EFAULT ;
1584+ goto err_free ;
1585+ }
1586+
1587+ if (put_user (0 , & user -> extensions )) {
1588+ err = - EFAULT ;
1589+ goto err_free ;
1590+ }
1591+
1592+ for (n = 0 ; n < count ; n ++ ) {
1593+ struct i915_engine_class_instance ci = {
1594+ .engine_class = I915_ENGINE_CLASS_INVALID ,
1595+ .engine_instance = I915_ENGINE_CLASS_INVALID_NONE ,
1596+ };
1597+
1598+ if (e -> engines [n ]) {
1599+ ci .engine_class = e -> engines [n ]-> engine -> uabi_class ;
1600+ ci .engine_instance = e -> engines [n ]-> engine -> instance ;
1601+ }
1602+
1603+ if (copy_to_user (& user -> engines [n ], & ci , sizeof (ci ))) {
1604+ err = - EFAULT ;
1605+ goto err_free ;
1606+ }
1607+ }
1608+
1609+ args -> size = size ;
1610+
1611+ err_free :
1612+ INIT_RCU_WORK (& e -> rcu , free_engines_rcu );
1613+ queue_rcu_work (system_wq , & e -> rcu );
1614+ return err ;
1615+ }
1616+
13821617static int ctx_setparam (struct drm_i915_file_private * fpriv ,
13831618 struct i915_gem_context * ctx ,
13841619 struct drm_i915_gem_context_param * args )
@@ -1452,6 +1687,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
14521687 ret = set_ppgtt (fpriv , ctx , args );
14531688 break ;
14541689
1690+ case I915_CONTEXT_PARAM_ENGINES :
1691+ ret = set_engines (ctx , args );
1692+ break ;
1693+
14551694 case I915_CONTEXT_PARAM_BAN_PERIOD :
14561695 default :
14571696 ret = - EINVAL ;
@@ -1596,9 +1835,7 @@ static int get_sseu(struct i915_gem_context *ctx,
15961835 if (user_sseu .flags || user_sseu .rsvd )
15971836 return - EINVAL ;
15981837
1599- ce = lookup_user_engine (ctx ,
1600- user_sseu .engine .engine_class ,
1601- user_sseu .engine .engine_instance );
1838+ ce = lookup_user_engine (ctx , 0 , & user_sseu .engine );
16021839 if (IS_ERR (ce ))
16031840 return PTR_ERR (ce );
16041841
@@ -1682,6 +1919,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
16821919 ret = get_ppgtt (file_priv , ctx , args );
16831920 break ;
16841921
1922+ case I915_CONTEXT_PARAM_ENGINES :
1923+ ret = get_engines (ctx , args );
1924+ break ;
1925+
16851926 case I915_CONTEXT_PARAM_BAN_PERIOD :
16861927 default :
16871928 ret = - EINVAL ;
0 commit comments