brintos

brintos / linux-shallow public Read only

0
0
Text · 8.2 KiB · c2ee5e1 Raw
300 lines · c
1// SPDX-License-Identifier: MIT2 3/*4 * Copyright © 2020 Intel Corporation5 */6 7#include <linux/bitmap.h>8#include <linux/string_helpers.h>9 10#include "i915_drv.h"11#include "intel_gt_debugfs.h"12#include "intel_gt_regs.h"13#include "intel_sseu_debugfs.h"14 15static void cherryview_sseu_device_status(struct intel_gt *gt,16					  struct sseu_dev_info *sseu)17{18#define SS_MAX 219	struct intel_uncore *uncore = gt->uncore;20	const int ss_max = SS_MAX;21	u32 sig1[SS_MAX], sig2[SS_MAX];22	int ss;23 24	sig1[0] = intel_uncore_read(uncore, CHV_POWER_SS0_SIG1);25	sig1[1] = intel_uncore_read(uncore, CHV_POWER_SS1_SIG1);26	sig2[0] = intel_uncore_read(uncore, CHV_POWER_SS0_SIG2);27	sig2[1] = intel_uncore_read(uncore, CHV_POWER_SS1_SIG2);28 29	for (ss = 0; ss < ss_max; ss++) {30		unsigned int eu_cnt;31 32		if (sig1[ss] & CHV_SS_PG_ENABLE)33			/* skip disabled subslice */34			continue;35 36		sseu->slice_mask = BIT(0);37		sseu->subslice_mask.hsw[0] |= BIT(ss);38		eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) +39			 ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) +40			 ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) +41			 ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2);42		sseu->eu_total += eu_cnt;43		sseu->eu_per_subslice = max_t(unsigned int,44					      sseu->eu_per_subslice, eu_cnt);45	}46#undef SS_MAX47}48 49static void gen11_sseu_device_status(struct intel_gt *gt,50				     struct sseu_dev_info *sseu)51{52#define SS_MAX 853	struct intel_uncore *uncore = gt->uncore;54	const struct intel_gt_info *info = &gt->info;55	u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];56	int s, ss;57 58	for (s = 0; s < info->sseu.max_slices; s++) {59		/*60		 * FIXME: Valid SS Mask respects the spec and read61		 * only valid bits for those registers, excluding reserved62		 * although this seems wrong because it would leave many63		 * subslices without ACK.64		 */65		s_reg[s] = intel_uncore_read(uncore, GEN10_SLICE_PGCTL_ACK(s)) &66			GEN10_PGCTL_VALID_SS_MASK(s);67		eu_reg[2 * s] = intel_uncore_read(uncore,68						  GEN10_SS01_EU_PGCTL_ACK(s));69		eu_reg[2 * s + 1] = intel_uncore_read(uncore,70						      GEN10_SS23_EU_PGCTL_ACK(s));71	}72 73	eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |74		     GEN9_PGCTL_SSA_EU19_ACK |75		     GEN9_PGCTL_SSA_EU210_ACK |76		     GEN9_PGCTL_SSA_EU311_ACK;77	eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |78		     GEN9_PGCTL_SSB_EU19_ACK |79		     GEN9_PGCTL_SSB_EU210_ACK |80		     GEN9_PGCTL_SSB_EU311_ACK;81 82	for (s = 0; s < info->sseu.max_slices; s++) {83		if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)84			/* skip disabled slice */85			continue;86 87		sseu->slice_mask |= BIT(s);88		sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];89 90		for (ss = 0; ss < info->sseu.max_subslices; ss++) {91			unsigned int eu_cnt;92 93			if (info->sseu.has_subslice_pg &&94			    !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))95				/* skip disabled subslice */96				continue;97 98			eu_cnt = 2 * hweight32(eu_reg[2 * s + ss / 2] &99					       eu_mask[ss % 2]);100			sseu->eu_total += eu_cnt;101			sseu->eu_per_subslice = max_t(unsigned int,102						      sseu->eu_per_subslice,103						      eu_cnt);104		}105	}106#undef SS_MAX107}108 109static void gen9_sseu_device_status(struct intel_gt *gt,110				    struct sseu_dev_info *sseu)111{112#define SS_MAX 3113	struct intel_uncore *uncore = gt->uncore;114	const struct intel_gt_info *info = &gt->info;115	u32 s_reg[SS_MAX], eu_reg[2 * SS_MAX], eu_mask[2];116	int s, ss;117 118	for (s = 0; s < info->sseu.max_slices; s++) {119		s_reg[s] = intel_uncore_read(uncore, GEN9_SLICE_PGCTL_ACK(s));120		eu_reg[2 * s] =121			intel_uncore_read(uncore, GEN9_SS01_EU_PGCTL_ACK(s));122		eu_reg[2 * s + 1] =123			intel_uncore_read(uncore, GEN9_SS23_EU_PGCTL_ACK(s));124	}125 126	eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |127		     GEN9_PGCTL_SSA_EU19_ACK |128		     GEN9_PGCTL_SSA_EU210_ACK |129		     GEN9_PGCTL_SSA_EU311_ACK;130	eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |131		     GEN9_PGCTL_SSB_EU19_ACK |132		     GEN9_PGCTL_SSB_EU210_ACK |133		     GEN9_PGCTL_SSB_EU311_ACK;134 135	for (s = 0; s < info->sseu.max_slices; s++) {136		if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)137			/* skip disabled slice */138			continue;139 140		sseu->slice_mask |= BIT(s);141 142		if (IS_GEN9_BC(gt->i915))143			sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];144 145		for (ss = 0; ss < info->sseu.max_subslices; ss++) {146			unsigned int eu_cnt;147 148			if (IS_GEN9_LP(gt->i915)) {149				if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))150					/* skip disabled subslice */151					continue;152 153				sseu->subslice_mask.hsw[s] |= BIT(ss);154			}155 156			eu_cnt = eu_reg[2 * s + ss / 2] & eu_mask[ss % 2];157			eu_cnt = 2 * hweight32(eu_cnt);158 159			sseu->eu_total += eu_cnt;160			sseu->eu_per_subslice = max_t(unsigned int,161						      sseu->eu_per_subslice,162						      eu_cnt);163		}164	}165#undef SS_MAX166}167 168static void bdw_sseu_device_status(struct intel_gt *gt,169				   struct sseu_dev_info *sseu)170{171	const struct intel_gt_info *info = &gt->info;172	u32 slice_info = intel_uncore_read(gt->uncore, GEN8_GT_SLICE_INFO);173	int s;174 175	sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK;176 177	if (sseu->slice_mask) {178		sseu->eu_per_subslice = info->sseu.eu_per_subslice;179		for (s = 0; s < fls(sseu->slice_mask); s++)180			sseu->subslice_mask.hsw[s] = info->sseu.subslice_mask.hsw[s];181		sseu->eu_total = sseu->eu_per_subslice *182				 intel_sseu_subslice_total(sseu);183 184		/* subtract fused off EU(s) from enabled slice(s) */185		for (s = 0; s < fls(sseu->slice_mask); s++) {186			u8 subslice_7eu = info->sseu.subslice_7eu[s];187 188			sseu->eu_total -= hweight8(subslice_7eu);189		}190	}191}192 193static void i915_print_sseu_info(struct seq_file *m,194				 bool is_available_info,195				 bool has_pooled_eu,196				 const struct sseu_dev_info *sseu)197{198	const char *type = is_available_info ? "Available" : "Enabled";199 200	seq_printf(m, "  %s Slice Mask: %04x\n", type,201		   sseu->slice_mask);202	seq_printf(m, "  %s Slice Total: %u\n", type,203		   hweight8(sseu->slice_mask));204	seq_printf(m, "  %s Subslice Total: %u\n", type,205		   intel_sseu_subslice_total(sseu));206	intel_sseu_print_ss_info(type, sseu, m);207	seq_printf(m, "  %s EU Total: %u\n", type,208		   sseu->eu_total);209	seq_printf(m, "  %s EU Per Subslice: %u\n", type,210		   sseu->eu_per_subslice);211 212	if (!is_available_info)213		return;214 215	seq_printf(m, "  Has Pooled EU: %s\n", str_yes_no(has_pooled_eu));216	if (has_pooled_eu)217		seq_printf(m, "  Min EU in pool: %u\n", sseu->min_eu_in_pool);218 219	seq_printf(m, "  Has Slice Power Gating: %s\n",220		   str_yes_no(sseu->has_slice_pg));221	seq_printf(m, "  Has Subslice Power Gating: %s\n",222		   str_yes_no(sseu->has_subslice_pg));223	seq_printf(m, "  Has EU Power Gating: %s\n",224		   str_yes_no(sseu->has_eu_pg));225}226 227/*228 * this is called from top-level debugfs as well, so we can't get the gt from229 * the seq_file.230 */231int intel_sseu_status(struct seq_file *m, struct intel_gt *gt)232{233	struct drm_i915_private *i915 = gt->i915;234	const struct intel_gt_info *info = &gt->info;235	struct sseu_dev_info *sseu;236	intel_wakeref_t wakeref;237 238	if (GRAPHICS_VER(i915) < 8)239		return -ENODEV;240 241	seq_puts(m, "SSEU Device Info\n");242	i915_print_sseu_info(m, true, HAS_POOLED_EU(i915), &info->sseu);243 244	seq_puts(m, "SSEU Device Status\n");245 246	sseu = kzalloc(sizeof(*sseu), GFP_KERNEL);247	if (!sseu)248		return -ENOMEM;249 250	intel_sseu_set_info(sseu, info->sseu.max_slices,251			    info->sseu.max_subslices,252			    info->sseu.max_eus_per_subslice);253 254	with_intel_runtime_pm(&i915->runtime_pm, wakeref) {255		if (IS_CHERRYVIEW(i915))256			cherryview_sseu_device_status(gt, sseu);257		else if (IS_BROADWELL(i915))258			bdw_sseu_device_status(gt, sseu);259		else if (GRAPHICS_VER(i915) == 9)260			gen9_sseu_device_status(gt, sseu);261		else if (GRAPHICS_VER(i915) >= 11)262			gen11_sseu_device_status(gt, sseu);263	}264 265	i915_print_sseu_info(m, false, HAS_POOLED_EU(i915), sseu);266 267	kfree(sseu);268 269	return 0;270}271 272static int sseu_status_show(struct seq_file *m, void *unused)273{274	struct intel_gt *gt = m->private;275 276	return intel_sseu_status(m, gt);277}278DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_status);279 280static int sseu_topology_show(struct seq_file *m, void *unused)281{282	struct intel_gt *gt = m->private;283	struct drm_printer p = drm_seq_file_printer(m);284 285	intel_sseu_print_topology(gt->i915, &gt->info.sseu, &p);286 287	return 0;288}289DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_topology);290 291void intel_sseu_debugfs_register(struct intel_gt *gt, struct dentry *root)292{293	static const struct intel_gt_debugfs_file files[] = {294		{ "sseu_status", &sseu_status_fops, NULL },295		{ "sseu_topology", &sseu_topology_fops, NULL },296	};297 298	intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gt);299}300