diff mbox

[4/4] drm/i915/selftests: Introduce live tests of private PAT management

Message ID 1504641507-14084-4-git-send-email-zhi.a.wang@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Wang, Zhi A Sept. 5, 2017, 7:58 p.m. UTC
Introduce two live tests of private PAT managment:

igt_ppat_init - This test is to check if all the PPAT configuration is
written into HW.

igt_ppat_get - This test performs several sub-tests on intel_ppat_get()
and intel_ppat_put().

The "perfect match" test case will try to get a PPAT entry with an existing
value, then check if the returned PPAT entry is the same one.

The "alloc entries" test case will run out of PPAT table, and check if all
the requested values are put into the newly allocated PPAT entries.

The "partial match" test case will generate a parital matched value from
the existing PPAT table and try to match it.

The "put entries" test case will free all the PPAT entries that allocated
in "alloc entries" test case. It will check if the values of freed PPAT
entries turn into ppat->clear_value.

An example output of these test cases on my SKL box is:

[   38.934158] ppat: check private PAT on HW
[   38.942498] ppat: OK
[   38.946752] ppat: ppat table before the test
[   38.955580] ppat 0: 0x7
[   38.960509] ppat 2: 0xa
[   38.965484] ppat 3: 0x0
[   38.970267] ppat 4: 0xb
[   38.975387] ppat: make sure it's same with HW ppat table
[   38.985996] ppat: check private PAT on HW
[   38.994492] ppat: OK
[   38.998921] ppat: case 1: perfect match
[   39.006706] ppat: OK
[   39.011135] ppat: case 2: alloc new entries
[   39.019825] ppat: alloc new entry value 0x37 index 1
[   39.029771] ppat: alloc new entry value 0x27 index 5
[   39.039829] ppat: alloc new entry value 0x17 index 6
[   39.050076] ppat: alloc new entry value 0x3b index 7
[   39.059980] ppat: OK
[   39.064570] ppat: case 3: partial match
[   39.072354] ppat: generate value 0x2b
[   39.079432] ppat: partial match entry value 0x3b index 7
[   39.090219] ppat: put entries
[   39.096061] ppat: put entry value 0x37 index 1
[   39.105262] ppat: put entry value 0x27 index 5
[   39.114150] ppat: put entry value 0x17 index 6
[   39.123154] ppat: put entry value 0x3b index 7
[   39.132335] ppat: OK
[   39.136588] ppat: ppat table after the test
[   39.145239] ppat 0: 0x7
[   39.150198] ppat 2: 0xa
[   39.154981] ppat 3: 0x0
[   39.160100] ppat 4: 0xb
[   39.165058] ppat: make sure it's same with HW ppat table
[   39.175844] ppat: check private PAT on HW
[   39.184007] ppat: OK
[   39.188261] ppat: OK

Cc: Ben Widawsky <benjamin.widawsky@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Zhi Wang <zhi.a.wang@intel.com>
---
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 280 ++++++++++++++++++++++++++
 1 file changed, 280 insertions(+)

Comments

Chris Wilson Sept. 7, 2017, 9:30 p.m. UTC | #1
Quoting Zhi Wang (2017-09-05 20:58:27)
> Introduce two live tests of private PAT managment:
> 
> igt_ppat_init - This test is to check if all the PPAT configuration is
> written into HW.
> 
> igt_ppat_get - This test performs several sub-tests on intel_ppat_get()
> and intel_ppat_put().
> 
> The "perfect match" test case will try to get a PPAT entry with an existing
> value, then check if the returned PPAT entry is the same one.
> 
> The "alloc entries" test case will run out of PPAT table, and check if all
> the requested values are put into the newly allocated PPAT entries.
> 
> The "partial match" test case will generate a parital matched value from
> the existing PPAT table and try to match it.
> 
> The "put entries" test case will free all the PPAT entries that allocated
> in "alloc entries" test case. It will check if the values of freed PPAT
> entries turn into ppat->clear_value.
> 
> An example output of these test cases on my SKL box is:
> 
> [   38.934158] ppat: check private PAT on HW
> [   38.942498] ppat: OK
> [   38.946752] ppat: ppat table before the test
> [   38.955580] ppat 0: 0x7
> [   38.960509] ppat 2: 0xa
> [   38.965484] ppat 3: 0x0
> [   38.970267] ppat 4: 0xb
> [   38.975387] ppat: make sure it's same with HW ppat table
> [   38.985996] ppat: check private PAT on HW
> [   38.994492] ppat: OK
> [   38.998921] ppat: case 1: perfect match
> [   39.006706] ppat: OK
> [   39.011135] ppat: case 2: alloc new entries
> [   39.019825] ppat: alloc new entry value 0x37 index 1
> [   39.029771] ppat: alloc new entry value 0x27 index 5
> [   39.039829] ppat: alloc new entry value 0x17 index 6
> [   39.050076] ppat: alloc new entry value 0x3b index 7
> [   39.059980] ppat: OK
> [   39.064570] ppat: case 3: partial match
> [   39.072354] ppat: generate value 0x2b
> [   39.079432] ppat: partial match entry value 0x3b index 7
> [   39.090219] ppat: put entries
> [   39.096061] ppat: put entry value 0x37 index 1
> [   39.105262] ppat: put entry value 0x27 index 5
> [   39.114150] ppat: put entry value 0x17 index 6
> [   39.123154] ppat: put entry value 0x3b index 7
> [   39.132335] ppat: OK
> [   39.136588] ppat: ppat table after the test
> [   39.145239] ppat 0: 0x7
> [   39.150198] ppat 2: 0xa
> [   39.154981] ppat 3: 0x0
> [   39.160100] ppat 4: 0xb
> [   39.165058] ppat: make sure it's same with HW ppat table
> [   39.175844] ppat: check private PAT on HW
> [   39.184007] ppat: OK
> [   39.188261] ppat: OK

You don't feel this is too verbose? It's just noise (even at pr_debug
and so usually hidden) for the signal is in the failure condition, which
appears well documented.

I couldn't see any failure conditions tested, checking the handling of
ENOSPC and then reallocation will be important.
-Chris
kernel test robot Sept. 8, 2017, 8:57 a.m. UTC | #2
Hi Zhi,

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20170908]
[cannot apply to v4.13]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Zhi-Wang/drm-i915-Factor-out-setup_private_pat/20170908-154240
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-x001-201736 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
                    from include/asm-generic/bug.h:15,
                    from arch/x86/include/asm/bug.h:81,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/gfp.h:4,
                    from include/linux/slab.h:14,
                    from drivers/gpu/drm/i915/i915_gem_gtt.c:26:
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c: In function 'igt_ppat_get':
   include/linux/kern_levels.h:4:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:136:11: note: in definition of macro 'no_printk'
       printk(fmt, ##__VA_ARGS__); \
              ^~~
   include/linux/kern_levels.h:14:20: note: in expansion of macro 'KERN_SOH'
    #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
                       ^~~~~~~~
   include/linux/printk.h:339:12: note: in expansion of macro 'KERN_DEBUG'
     no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
               ^~~~~~~~~~
>> drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1293:3: note: in expansion of macro 'pr_debug'
      pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
      ^~~~~~~~
   include/linux/kern_levels.h:4:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:136:11: note: in definition of macro 'no_printk'
       printk(fmt, ##__VA_ARGS__); \
              ^~~
   include/linux/kern_levels.h:14:20: note: in expansion of macro 'KERN_SOH'
    #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
                       ^~~~~~~~
   include/linux/printk.h:339:12: note: in expansion of macro 'KERN_DEBUG'
     no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
               ^~~~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1330:2: note: in expansion of macro 'pr_debug'
     pr_debug("ppat: partial match entry value 0x%x index %lu\n",
     ^~~~~~~~
   include/linux/kern_levels.h:4:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:136:11: note: in definition of macro 'no_printk'
       printk(fmt, ##__VA_ARGS__); \
              ^~~
   include/linux/kern_levels.h:14:20: note: in expansion of macro 'KERN_SOH'
    #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
                       ^~~~~~~~
   include/linux/printk.h:339:12: note: in expansion of macro 'KERN_DEBUG'
     no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
               ^~~~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1343:4: note: in expansion of macro 'pr_debug'
       pr_debug("ppat: put entry value 0x%x index %lu\n",
       ^~~~~~~~

vim +/pr_debug +1293 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c

  1205	
  1206	static int igt_ppat_get(void *arg)
  1207	{
  1208		struct drm_i915_private *i915 = arg;
  1209		struct intel_ppat *ppat = &i915->ppat;
  1210		const struct intel_ppat_entry **entries;
  1211		const struct intel_ppat_entry *entry;
  1212		unsigned int size = 0;
  1213		u8 value;
  1214		int i, ret;
  1215	
  1216		if (!ppat->max_entries)
  1217			return 0;
  1218	
  1219		pr_debug("ppat: ppat table before the test\n");
  1220	
  1221		for_each_set_bit(i, ppat->used, ppat->max_entries)
  1222			pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
  1223	
  1224		pr_debug("ppat: make sure it's same with HW ppat table\n");
  1225	
  1226		ret = igt_ppat_init(i915);
  1227		if (ret)
  1228			return ret;
  1229	
  1230		pr_debug("ppat: case 1: perfect match\n");
  1231	
  1232		entry = intel_ppat_get(i915, ppat->entries[0].value);
  1233		if (IS_ERR(entry))
  1234			return PTR_ERR(entry);
  1235	
  1236		if (entry != &ppat->entries[0]) {
  1237			pr_err("not expected entry\n");
  1238			intel_ppat_put(entry);
  1239			return -EINVAL;
  1240		}
  1241	
  1242		intel_ppat_put(entry);
  1243	
  1244		pr_debug("ppat: OK\n");
  1245		pr_debug("ppat: case 2: alloc new entries\n");
  1246	
  1247		entries = NULL;
  1248		ret = 0;
  1249	
  1250		while (!ppat_table_is_full(ppat)) {
  1251			const struct intel_ppat_entry **p_entry;
  1252			DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES);
  1253	
  1254			bitmap_copy(used, ppat->used, ppat->max_entries);
  1255	
  1256			entries = krealloc(entries, (size + 1) *
  1257					   sizeof(struct intel_ppat_entry *),
  1258					   GFP_KERNEL);
  1259			if (!entries) {
  1260				ret = -ENOSPC;
  1261				break;
  1262			}
  1263	
  1264			p_entry = &entries[size++];
  1265			*p_entry = NULL;
  1266	
  1267			value = generate_new_value(ppat, false);
  1268			if (!value) {
  1269				pr_err("cannot fill the unused PPAT entries?\n");
  1270				ret = -EINVAL;
  1271				break;
  1272			}
  1273	
  1274			*p_entry = entry = intel_ppat_get(i915, value);
  1275			if (IS_ERR(entry)) {
  1276				pr_err("fail to get new entry\n");
  1277				ret = PTR_ERR(entry);
  1278				break;
  1279			}
  1280	
  1281			if (entry->value != value) {
  1282				pr_err("fail to get expected new value\n");
  1283				ret = -EINVAL;
  1284				break;
  1285			}
  1286	
  1287			if (bitmap_equal(used, ppat->used, ppat->max_entries)) {
  1288				pr_err("fail to alloc a new entry\n");
  1289				ret = -EINVAL;
  1290				break;
  1291			}
  1292	
> 1293			pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
  1294				entry->value, entry - ppat->entries);
  1295		}
  1296	
  1297		if (!ret)
  1298			pr_debug("ppat: OK\n");
  1299	
  1300		if (!entries)
  1301			pr_debug("ppat: ppat table is full, skip\n");
  1302	
  1303		if (ret)
  1304			goto ppat_put;
  1305	
  1306		pr_debug("ppat: case 3: partial match\n");
  1307	
  1308		value = generate_new_value(ppat, true);
  1309		if (!value) {
  1310			pr_err("fail to get new value\n");
  1311			ret = -EINVAL;
  1312			goto ppat_put;
  1313		}
  1314	
  1315		pr_debug("ppat: generate value 0x%x\n", value);
  1316	
  1317		entry = intel_ppat_get(i915, value);
  1318		if (IS_ERR(entry)) {
  1319			pr_err("fail to get new entry\n");
  1320			ret = PTR_ERR(entry);
  1321			goto ppat_put;
  1322		}
  1323	
  1324		if (!(entry->value != value &&
  1325		    GEN8_PPAT_GET_CA(entry->value) == GEN8_PPAT_GET_CA(value))) {
  1326			pr_err("fail to get expected value\n");
  1327			ret = -EINVAL;
  1328		}
  1329	
  1330		pr_debug("ppat: partial match entry value 0x%x index %lu\n",
  1331			entry->value, entry - ppat->entries);
  1332	
  1333		intel_ppat_put(entry);
  1334	
  1335	ppat_put:
  1336		if (entries) {
  1337			pr_debug("ppat: put entries\n");
  1338	
  1339			for (i = 0; i < size; i++) {
  1340				if (IS_ERR(entries[i]) || !entries[i])
  1341					continue;
  1342	
  1343				pr_debug("ppat: put entry value 0x%x index %lu\n",
  1344					entries[i]->value, entries[i] - ppat->entries);
  1345	
  1346				intel_ppat_put(entries[i]);
  1347	
  1348				if (entries[i]->value != ppat->clear_value) {
  1349					pr_err("fail to put ppat value\n");
  1350					ret = -EINVAL;
  1351					break;
  1352				}
  1353			}
  1354			pr_debug("ppat: OK\n");
  1355			kfree(entries);
  1356			entries = NULL;
  1357		}
  1358	
  1359		pr_debug("ppat: ppat table after the test\n");
  1360	
  1361		for_each_set_bit(i, ppat->used, ppat->max_entries)
  1362			pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
  1363	
  1364		pr_debug("ppat: make sure it's same with HW ppat table\n");
  1365	
  1366		ret = igt_ppat_init(i915);
  1367		if (ret)
  1368			return ret;
  1369	
  1370		pr_debug("ppat: OK\n");
  1371	
  1372		return ret;
  1373	}
  1374	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Sept. 8, 2017, 9:40 a.m. UTC | #3
Hi Zhi,

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20170908]
[cannot apply to v4.13]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Zhi-Wang/drm-i915-Factor-out-setup_private_pat/20170908-154240
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
                    from include/asm-generic/bug.h:15,
                    from arch/x86/include/asm/bug.h:81,
                    from include/linux/bug.h:4,
                    from include/linux/mmdebug.h:4,
                    from include/linux/gfp.h:4,
                    from include/linux/slab.h:14,
                    from drivers/gpu/drm/i915/i915_gem_gtt.c:26:
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c: In function 'igt_ppat_get':
>> drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1293:12: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'int' [-Wformat=]
      pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
               ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
    #define pr_fmt(fmt) fmt
                        ^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
     dynamic_pr_debug(fmt, ##__VA_ARGS__)
     ^~~~~~~~~~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1293:3: note: in expansion of macro 'pr_debug'
      pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
      ^~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1330:11: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'int' [-Wformat=]
     pr_debug("ppat: partial match entry value 0x%x index %lu\n",
              ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
    #define pr_fmt(fmt) fmt
                        ^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
     dynamic_pr_debug(fmt, ##__VA_ARGS__)
     ^~~~~~~~~~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1330:2: note: in expansion of macro 'pr_debug'
     pr_debug("ppat: partial match entry value 0x%x index %lu\n",
     ^~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1343:13: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'int' [-Wformat=]
       pr_debug("ppat: put entry value 0x%x index %lu\n",
                ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
    #define pr_fmt(fmt) fmt
                        ^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
     dynamic_pr_debug(fmt, ##__VA_ARGS__)
     ^~~~~~~~~~~~~~~~
   drivers/gpu/drm/i915/selftests/i915_gem_gtt.c:1343:4: note: in expansion of macro 'pr_debug'
       pr_debug("ppat: put entry value 0x%x index %lu\n",
       ^~~~~~~~

vim +1293 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c

  1205	
  1206	static int igt_ppat_get(void *arg)
  1207	{
  1208		struct drm_i915_private *i915 = arg;
  1209		struct intel_ppat *ppat = &i915->ppat;
  1210		const struct intel_ppat_entry **entries;
  1211		const struct intel_ppat_entry *entry;
  1212		unsigned int size = 0;
  1213		u8 value;
  1214		int i, ret;
  1215	
  1216		if (!ppat->max_entries)
  1217			return 0;
  1218	
  1219		pr_debug("ppat: ppat table before the test\n");
  1220	
  1221		for_each_set_bit(i, ppat->used, ppat->max_entries)
  1222			pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
  1223	
  1224		pr_debug("ppat: make sure it's same with HW ppat table\n");
  1225	
  1226		ret = igt_ppat_init(i915);
  1227		if (ret)
  1228			return ret;
  1229	
  1230		pr_debug("ppat: case 1: perfect match\n");
  1231	
  1232		entry = intel_ppat_get(i915, ppat->entries[0].value);
  1233		if (IS_ERR(entry))
  1234			return PTR_ERR(entry);
  1235	
  1236		if (entry != &ppat->entries[0]) {
  1237			pr_err("not expected entry\n");
  1238			intel_ppat_put(entry);
  1239			return -EINVAL;
  1240		}
  1241	
  1242		intel_ppat_put(entry);
  1243	
  1244		pr_debug("ppat: OK\n");
  1245		pr_debug("ppat: case 2: alloc new entries\n");
  1246	
  1247		entries = NULL;
  1248		ret = 0;
  1249	
  1250		while (!ppat_table_is_full(ppat)) {
  1251			const struct intel_ppat_entry **p_entry;
  1252			DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES);
  1253	
  1254			bitmap_copy(used, ppat->used, ppat->max_entries);
  1255	
  1256			entries = krealloc(entries, (size + 1) *
  1257					   sizeof(struct intel_ppat_entry *),
  1258					   GFP_KERNEL);
  1259			if (!entries) {
  1260				ret = -ENOSPC;
  1261				break;
  1262			}
  1263	
  1264			p_entry = &entries[size++];
  1265			*p_entry = NULL;
  1266	
  1267			value = generate_new_value(ppat, false);
  1268			if (!value) {
  1269				pr_err("cannot fill the unused PPAT entries?\n");
  1270				ret = -EINVAL;
  1271				break;
  1272			}
  1273	
  1274			*p_entry = entry = intel_ppat_get(i915, value);
  1275			if (IS_ERR(entry)) {
  1276				pr_err("fail to get new entry\n");
  1277				ret = PTR_ERR(entry);
  1278				break;
  1279			}
  1280	
  1281			if (entry->value != value) {
  1282				pr_err("fail to get expected new value\n");
  1283				ret = -EINVAL;
  1284				break;
  1285			}
  1286	
  1287			if (bitmap_equal(used, ppat->used, ppat->max_entries)) {
  1288				pr_err("fail to alloc a new entry\n");
  1289				ret = -EINVAL;
  1290				break;
  1291			}
  1292	
> 1293			pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
  1294				entry->value, entry - ppat->entries);
  1295		}
  1296	
  1297		if (!ret)
  1298			pr_debug("ppat: OK\n");
  1299	
  1300		if (!entries)
  1301			pr_debug("ppat: ppat table is full, skip\n");
  1302	
  1303		if (ret)
  1304			goto ppat_put;
  1305	
  1306		pr_debug("ppat: case 3: partial match\n");
  1307	
  1308		value = generate_new_value(ppat, true);
  1309		if (!value) {
  1310			pr_err("fail to get new value\n");
  1311			ret = -EINVAL;
  1312			goto ppat_put;
  1313		}
  1314	
  1315		pr_debug("ppat: generate value 0x%x\n", value);
  1316	
  1317		entry = intel_ppat_get(i915, value);
  1318		if (IS_ERR(entry)) {
  1319			pr_err("fail to get new entry\n");
  1320			ret = PTR_ERR(entry);
  1321			goto ppat_put;
  1322		}
  1323	
  1324		if (!(entry->value != value &&
  1325		    GEN8_PPAT_GET_CA(entry->value) == GEN8_PPAT_GET_CA(value))) {
  1326			pr_err("fail to get expected value\n");
  1327			ret = -EINVAL;
  1328		}
  1329	
  1330		pr_debug("ppat: partial match entry value 0x%x index %lu\n",
  1331			entry->value, entry - ppat->entries);
  1332	
  1333		intel_ppat_put(entry);
  1334	
  1335	ppat_put:
  1336		if (entries) {
  1337			pr_debug("ppat: put entries\n");
  1338	
  1339			for (i = 0; i < size; i++) {
  1340				if (IS_ERR(entries[i]) || !entries[i])
  1341					continue;
  1342	
  1343				pr_debug("ppat: put entry value 0x%x index %lu\n",
  1344					entries[i]->value, entries[i] - ppat->entries);
  1345	
  1346				intel_ppat_put(entries[i]);
  1347	
  1348				if (entries[i]->value != ppat->clear_value) {
  1349					pr_err("fail to put ppat value\n");
  1350					ret = -EINVAL;
  1351					break;
  1352				}
  1353			}
  1354			pr_debug("ppat: OK\n");
  1355			kfree(entries);
  1356			entries = NULL;
  1357		}
  1358	
  1359		pr_debug("ppat: ppat table after the test\n");
  1360	
  1361		for_each_set_bit(i, ppat->used, ppat->max_entries)
  1362			pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
  1363	
  1364		pr_debug("ppat: make sure it's same with HW ppat table\n");
  1365	
  1366		ret = igt_ppat_init(i915);
  1367		if (ret)
  1368			return ret;
  1369	
  1370		pr_debug("ppat: OK\n");
  1371	
  1372		return ret;
  1373	}
  1374	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index 6b132ca..cda0a41 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -1094,6 +1094,284 @@  static int igt_ggtt_page(void *arg)
 	return err;
 }
 
+static int check_cnl_ppat_init(struct drm_i915_private *dev_priv)
+{
+	struct intel_ppat *ppat = &dev_priv->ppat;
+	int i;
+
+	for (i = 0; i < ppat->max_entries; i++) {
+		u32 value = I915_READ(GEN10_PAT_INDEX(i));
+		if (value != ppat->entries[i].value) {
+			pr_err("expected PPAT value isn't written into HW\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int check_bdw_ppat_init(struct drm_i915_private *dev_priv)
+{
+	struct intel_ppat *ppat = &dev_priv->ppat;
+	u64 pat, hw_pat;
+	int i;
+
+	pat = hw_pat = 0;
+
+	for (i = 0; i < ppat->max_entries; i++)
+		pat |= GEN8_PPAT(i, ppat->entries[i].value);
+
+	hw_pat = I915_READ(GEN8_PRIVATE_PAT_HI);
+	hw_pat <<= 32;
+	hw_pat |= I915_READ(GEN8_PRIVATE_PAT_LO);
+
+	if (pat != hw_pat) {
+		pr_err("expected PPAT value isn't written into HW\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int igt_ppat_init(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	int ret;
+
+	if (!i915->ppat.max_entries)
+		return 0;
+
+	pr_debug("ppat: check private PAT on HW\n");
+
+	if (INTEL_GEN(i915) >= 10)
+		ret = check_cnl_ppat_init(i915);
+	else
+		ret = check_bdw_ppat_init(i915);
+
+	if (!ret)
+		pr_debug("ppat: OK\n");
+
+	return ret;
+}
+
+static u8 generate_new_value(struct intel_ppat *ppat, bool partial)
+{
+	u8 ca[] = { GEN8_PPAT_WB, GEN8_PPAT_WC, GEN8_PPAT_WT, GEN8_PPAT_UC };
+	u8 tc[] = { GEN8_PPAT_LLC, GEN8_PPAT_LLCELLC, GEN8_PPAT_LLCeLLC };
+	u8 age[] = { GEN8_PPAT_AGE(3), GEN8_PPAT_AGE(2), GEN8_PPAT_AGE(1), GEN8_PPAT_AGE(0) };
+	u8 value = 0;
+	bool same;
+	int ca_index, tc_index, age_index, i;
+
+#define for_each_ppat_attr(ca_index, tc_index, age_index) \
+	for ((ca_index) = 0 ; (ca_index) < ARRAY_SIZE(ca); (ca_index)++) \
+	for ((tc_index) = 0; (tc_index) < ARRAY_SIZE(tc); (tc_index)++) \
+	for ((age_index) = 0; (age_index) < ARRAY_SIZE(age); (age_index)++)
+
+	for_each_ppat_attr(ca_index, tc_index, age_index) {
+		value = age[age_index] | ca[ca_index] | tc[tc_index];
+		same = false;
+
+		for_each_set_bit(i, ppat->used, ppat->max_entries) {
+			if (value != ppat->entries[i].value)
+				continue;
+
+			same = true;
+			break;
+		}
+
+		if (same)
+			continue;
+
+		if (!partial)
+			return value;
+
+		/* partial match, cache attribute has to be the same. */
+		for_each_set_bit(i, ppat->used, ppat->max_entries) {
+			if (GEN8_PPAT_GET_CA(value) !=
+			    GEN8_PPAT_GET_CA(ppat->entries[i].value))
+				continue;
+
+			return value;
+		}
+	}
+#undef for_each_ppat_attr
+	return 0;
+}
+
+static inline bool ppat_table_is_full(struct intel_ppat *ppat)
+{
+	return bitmap_weight(ppat->used, ppat->max_entries) ==
+		ppat->max_entries;
+}
+
+static int igt_ppat_get(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct intel_ppat *ppat = &i915->ppat;
+	const struct intel_ppat_entry **entries;
+	const struct intel_ppat_entry *entry;
+	unsigned int size = 0;
+	u8 value;
+	int i, ret;
+
+	if (!ppat->max_entries)
+		return 0;
+
+	pr_debug("ppat: ppat table before the test\n");
+
+	for_each_set_bit(i, ppat->used, ppat->max_entries)
+		pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
+
+	pr_debug("ppat: make sure it's same with HW ppat table\n");
+
+	ret = igt_ppat_init(i915);
+	if (ret)
+		return ret;
+
+	pr_debug("ppat: case 1: perfect match\n");
+
+	entry = intel_ppat_get(i915, ppat->entries[0].value);
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	if (entry != &ppat->entries[0]) {
+		pr_err("not expected entry\n");
+		intel_ppat_put(entry);
+		return -EINVAL;
+	}
+
+	intel_ppat_put(entry);
+
+	pr_debug("ppat: OK\n");
+	pr_debug("ppat: case 2: alloc new entries\n");
+
+	entries = NULL;
+	ret = 0;
+
+	while (!ppat_table_is_full(ppat)) {
+		const struct intel_ppat_entry **p_entry;
+		DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES);
+
+		bitmap_copy(used, ppat->used, ppat->max_entries);
+
+		entries = krealloc(entries, (size + 1) *
+				   sizeof(struct intel_ppat_entry *),
+				   GFP_KERNEL);
+		if (!entries) {
+			ret = -ENOSPC;
+			break;
+		}
+
+		p_entry = &entries[size++];
+		*p_entry = NULL;
+
+		value = generate_new_value(ppat, false);
+		if (!value) {
+			pr_err("cannot fill the unused PPAT entries?\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		*p_entry = entry = intel_ppat_get(i915, value);
+		if (IS_ERR(entry)) {
+			pr_err("fail to get new entry\n");
+			ret = PTR_ERR(entry);
+			break;
+		}
+
+		if (entry->value != value) {
+			pr_err("fail to get expected new value\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		if (bitmap_equal(used, ppat->used, ppat->max_entries)) {
+			pr_err("fail to alloc a new entry\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		pr_debug("ppat: alloc new entry value 0x%x index %lu\n",
+			entry->value, entry - ppat->entries);
+	}
+
+	if (!ret)
+		pr_debug("ppat: OK\n");
+
+	if (!entries)
+		pr_debug("ppat: ppat table is full, skip\n");
+
+	if (ret)
+		goto ppat_put;
+
+	pr_debug("ppat: case 3: partial match\n");
+
+	value = generate_new_value(ppat, true);
+	if (!value) {
+		pr_err("fail to get new value\n");
+		ret = -EINVAL;
+		goto ppat_put;
+	}
+
+	pr_debug("ppat: generate value 0x%x\n", value);
+
+	entry = intel_ppat_get(i915, value);
+	if (IS_ERR(entry)) {
+		pr_err("fail to get new entry\n");
+		ret = PTR_ERR(entry);
+		goto ppat_put;
+	}
+
+	if (!(entry->value != value &&
+	    GEN8_PPAT_GET_CA(entry->value) == GEN8_PPAT_GET_CA(value))) {
+		pr_err("fail to get expected value\n");
+		ret = -EINVAL;
+	}
+
+	pr_debug("ppat: partial match entry value 0x%x index %lu\n",
+		entry->value, entry - ppat->entries);
+
+	intel_ppat_put(entry);
+
+ppat_put:
+	if (entries) {
+		pr_debug("ppat: put entries\n");
+
+		for (i = 0; i < size; i++) {
+			if (IS_ERR(entries[i]) || !entries[i])
+				continue;
+
+			pr_debug("ppat: put entry value 0x%x index %lu\n",
+				entries[i]->value, entries[i] - ppat->entries);
+
+			intel_ppat_put(entries[i]);
+
+			if (entries[i]->value != ppat->clear_value) {
+				pr_err("fail to put ppat value\n");
+				ret = -EINVAL;
+				break;
+			}
+		}
+		pr_debug("ppat: OK\n");
+		kfree(entries);
+		entries = NULL;
+	}
+
+	pr_debug("ppat: ppat table after the test\n");
+
+	for_each_set_bit(i, ppat->used, ppat->max_entries)
+		pr_debug("ppat %d: 0x%x\n", i, ppat->entries[i].value);
+
+	pr_debug("ppat: make sure it's same with HW ppat table\n");
+
+	ret = igt_ppat_init(i915);
+	if (ret)
+		return ret;
+
+	pr_debug("ppat: OK\n");
+
+	return ret;
+}
+
 static void track_vma_bind(struct i915_vma *vma)
 {
 	struct drm_i915_gem_object *obj = vma->obj;
@@ -1560,6 +1838,8 @@  int i915_gem_gtt_live_selftests(struct drm_i915_private *i915)
 		SUBTEST(igt_ggtt_pot),
 		SUBTEST(igt_ggtt_fill),
 		SUBTEST(igt_ggtt_page),
+		SUBTEST(igt_ppat_init),
+		SUBTEST(igt_ppat_get),
 	};
 
 	GEM_BUG_ON(offset_in_page(i915->ggtt.base.total));