/* * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include "gr_config_priv.h" static void gr_config_init_pes_tpc(struct gk20a *g, struct nvgpu_gr_config *config, u32 gpc_index) { u32 pes_index; u32 pes_tpc_mask; u32 pes_tpc_count; for (pes_index = 0; pes_index < config->pe_count_per_gpc; pes_index++) { pes_tpc_mask = g->ops.gr.config.get_pes_tpc_mask(g, config, gpc_index, pes_index); pes_tpc_count = hweight32(pes_tpc_mask); /* detect PES presence by seeing if there are * TPCs connected to it. */ if (pes_tpc_count != 0U) { config->gpc_ppc_count[gpc_index] = nvgpu_safe_add_u32( config->gpc_ppc_count[gpc_index], 1U); } config->pes_tpc_count[pes_index][gpc_index] = pes_tpc_count; config->pes_tpc_mask[pes_index][gpc_index] = pes_tpc_mask; } } static void gr_config_init_gpc_skip_mask(struct nvgpu_gr_config *config, u32 gpc_index) { u32 pes_heavy_index; u32 gpc_new_skip_mask = 0U; u32 pes_tpc_cnt = 0U, pes_tpc_mask = 0U; if (config->pe_count_per_gpc <= 1U) { goto skip_mask_end; } pes_tpc_cnt = nvgpu_safe_add_u32( config->pes_tpc_count[0][gpc_index], config->pes_tpc_count[1][gpc_index]); pes_heavy_index = (config->pes_tpc_count[0][gpc_index] > config->pes_tpc_count[1][gpc_index]) ? 0U : 1U; if ((pes_tpc_cnt == 5U) || ((pes_tpc_cnt == 4U) && (config->pes_tpc_count[0][gpc_index] != config->pes_tpc_count[1][gpc_index]))) { pes_tpc_mask = nvgpu_safe_sub_u32( config->pes_tpc_mask[pes_heavy_index][gpc_index], 1U); gpc_new_skip_mask = config->pes_tpc_mask[pes_heavy_index][gpc_index] ^ (config->pes_tpc_mask[pes_heavy_index][gpc_index] & pes_tpc_mask); } skip_mask_end: config->gpc_skip_mask[gpc_index] = gpc_new_skip_mask; } static void gr_config_log_info(struct gk20a *g, struct nvgpu_gr_config *config) { u32 gpc_index, pes_index; nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "max_gpc_count: %d", config->max_gpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_count: %d", config->gpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_mask: 0x%x", config->gpc_mask); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "max_tpc_per_gpc_count: %d", config->max_tpc_per_gpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "max_tpc_count: %d", config->max_tpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "tpc_count: %d", config->tpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "sm_count_per_tpc: %d", config->sm_count_per_tpc); #ifdef CONFIG_NVGPU_GRAPHICS nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "max_zcull_per_gpc_count: %d", config->max_zcull_per_gpc_count); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "zcb_count: %d", config->zcb_count); #endif nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "pe_count_per_gpc: %d", config->pe_count_per_gpc); nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "ppc_count: %d", config->ppc_count); for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_tpc_count[%d] : %d", gpc_index, config->gpc_tpc_count[gpc_index]); } for (gpc_index = 0; gpc_index < config->max_gpc_count; gpc_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_tpc_mask[%d] : 0x%x", gpc_index, config->gpc_tpc_mask[gpc_index]); } #ifdef CONFIG_NVGPU_GRAPHICS for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_zcb_count[%d] : %d", gpc_index, config->gpc_zcb_count[gpc_index]); } #endif for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_ppc_count[%d] : %d", gpc_index, config->gpc_ppc_count[gpc_index]); } for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "gpc_skip_mask[%d] : 0x%x", gpc_index, config->gpc_skip_mask[gpc_index]); } for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { for (pes_index = 0; pes_index < config->pe_count_per_gpc; pes_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "pes_tpc_count[%d][%d] : %d", pes_index, gpc_index, config->pes_tpc_count[pes_index][gpc_index]); } } for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { for (pes_index = 0; pes_index < config->pe_count_per_gpc; pes_index++) { nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "pes_tpc_mask[%d][%d] : 0x%x", pes_index, gpc_index, config->pes_tpc_mask[pes_index][gpc_index]); } } } static void gr_config_set_gpc_mask(struct gk20a *g, struct nvgpu_gr_config *config) { #ifdef CONFIG_NVGPU_DGPU if (g->ops.gr.config.get_gpc_mask != NULL) { config->gpc_mask = g->ops.gr.config.get_gpc_mask(g); } else #endif { config->gpc_mask = nvgpu_safe_sub_u32(BIT32(config->gpc_count), 1U); } } static bool gr_config_alloc_valid(struct nvgpu_gr_config *config) { if ((config->gpc_tpc_count == NULL) || (config->gpc_tpc_mask == NULL) || #ifdef CONFIG_NVGPU_GRAPHICS (config->gpc_zcb_count == NULL) || #endif (config->gpc_ppc_count == NULL) || (config->gpc_skip_mask == NULL)) { return false; } return true; } static void gr_config_free_mem(struct gk20a *g, struct nvgpu_gr_config *config) { u32 pes_index; for (pes_index = 0U; pes_index < config->pe_count_per_gpc; pes_index++) { nvgpu_kfree(g, config->pes_tpc_count[pes_index]); nvgpu_kfree(g, config->pes_tpc_mask[pes_index]); } nvgpu_kfree(g, config->gpc_skip_mask); nvgpu_kfree(g, config->gpc_ppc_count); #ifdef CONFIG_NVGPU_GRAPHICS nvgpu_kfree(g, config->gpc_zcb_count); #endif nvgpu_kfree(g, config->gpc_tpc_mask); nvgpu_kfree(g, config->gpc_tpc_count); } static bool gr_config_alloc_struct_mem(struct gk20a *g, struct nvgpu_gr_config *config) { u32 pes_index; u32 total_tpc_cnt; size_t sm_info_size; size_t gpc_size, sm_size; size_t pd_tbl_size; total_tpc_cnt = nvgpu_safe_mult_u32(config->gpc_count, config->max_tpc_per_gpc_count); sm_size = nvgpu_safe_mult_u64((size_t)config->sm_count_per_tpc, sizeof(struct nvgpu_sm_info)); /* allocate for max tpc per gpc */ sm_info_size = nvgpu_safe_mult_u64((size_t)total_tpc_cnt, sm_size); config->sm_to_cluster = nvgpu_kzalloc(g, sm_info_size); if (config->sm_to_cluster == NULL) { nvgpu_err(g, "sm_to_cluster == NULL"); goto alloc_err; } #ifdef CONFIG_NVGPU_SM_DIVERSITY if (nvgpu_is_enabled(g, NVGPU_SUPPORT_SM_DIVERSITY)) { config->sm_to_cluster_redex_config = nvgpu_kzalloc(g, sm_info_size); if (config->sm_to_cluster_redex_config == NULL) { nvgpu_err(g, "sm_to_cluster_redex_config == NULL"); goto clean_alloc_mem; } } #endif config->no_of_sm = 0; gpc_size = nvgpu_safe_mult_u64((size_t)config->gpc_count, sizeof(u32)); config->gpc_tpc_count = nvgpu_kzalloc(g, gpc_size); #ifdef CONFIG_NVGPU_GRAPHICS if (!nvgpu_is_enabled(g, NVGPU_SUPPORT_MIG)) { config->max_zcull_per_gpc_count = nvgpu_get_litter_value(g, GPU_LIT_NUM_ZCULL_BANKS); config->gpc_zcb_count = nvgpu_kzalloc(g, gpc_size); } #endif config->gpc_ppc_count = nvgpu_kzalloc(g, gpc_size); pd_tbl_size = nvgpu_safe_mult_u64( (size_t)g->ops.gr.config.get_pd_dist_skip_table_size(), sizeof(u32)); pd_tbl_size = nvgpu_safe_mult_u64(pd_tbl_size, 4UL); config->gpc_skip_mask = nvgpu_kzalloc(g, pd_tbl_size); if (gr_config_alloc_valid(config) == false) { goto clean_alloc_mem; } for (pes_index = 0U; pes_index < config->pe_count_per_gpc; pes_index++) { config->pes_tpc_count[pes_index] = nvgpu_kzalloc(g, gpc_size); config->pes_tpc_mask[pes_index] = nvgpu_kzalloc(g, gpc_size); if ((config->pes_tpc_count[pes_index] == NULL) || (config->pes_tpc_mask[pes_index] == NULL)) { goto clean_alloc_mem; } } return true; clean_alloc_mem: nvgpu_kfree(g, config->sm_to_cluster); config->sm_to_cluster = NULL; #ifdef CONFIG_NVGPU_SM_DIVERSITY if (config->sm_to_cluster_redex_config != NULL) { nvgpu_kfree(g, config->sm_to_cluster_redex_config); config->sm_to_cluster_redex_config = NULL; } #endif gr_config_free_mem(g, config); alloc_err: return false; } static int gr_config_init_mig_gpcs(struct nvgpu_gr_config *config) { struct gk20a *g = config->g; u32 cur_gr_instance = g->mig.cur_gr_instance; u32 gpc_phys_id; u32 gpc_id; config->max_gpc_count = nvgpu_grmgr_get_gr_num_gpcs(g, cur_gr_instance); config->gpc_count = nvgpu_grmgr_get_gr_num_gpcs(g, cur_gr_instance); if (config->gpc_count == 0U) { nvgpu_err(g, "gpc_count==0!"); return -EINVAL; } config->gpc_mask = nvgpu_safe_sub_u32(BIT32(config->gpc_count), 1U); config->gpc_tpc_mask = nvgpu_kzalloc(g, config->max_gpc_count * sizeof(u32)); if (config->gpc_tpc_mask == NULL) { return -ENOMEM; } /* Required to read gpc_tpc_mask below */ config->max_tpc_per_gpc_count = g->ops.top.get_max_tpc_per_gpc_count(g); /* Fuse regsiters index GPCs by physical ID */ for (gpc_id = 0; gpc_id < config->gpc_count; gpc_id++) { gpc_phys_id = nvgpu_grmgr_get_gr_gpc_phys_id(g, cur_gr_instance, gpc_id); config->gpc_tpc_mask[gpc_id] = g->ops.gr.config.get_gpc_tpc_mask(g, config, gpc_phys_id); } return 0; } static int gr_config_init_gpcs(struct nvgpu_gr_config *config) { struct gk20a *g = config->g; u32 gpc_index; config->max_gpc_count = g->ops.top.get_max_gpc_count(g); config->gpc_count = g->ops.priv_ring.get_gpc_count(g); if (config->gpc_count == 0U) { nvgpu_err(g, "gpc_count==0!"); return -EINVAL; } gr_config_set_gpc_mask(g, config); config->gpc_tpc_mask = nvgpu_kzalloc(g, config->max_gpc_count * sizeof(u32)); if (config->gpc_tpc_mask == NULL) { return -ENOMEM; } /* Required to read gpc_tpc_mask below */ config->max_tpc_per_gpc_count = g->ops.top.get_max_tpc_per_gpc_count(g); for (gpc_index = 0; gpc_index < config->max_gpc_count; gpc_index++) { config->gpc_tpc_mask[gpc_index] = g->ops.gr.config.get_gpc_tpc_mask(g, config, gpc_index); } return 0; } struct nvgpu_gr_config *nvgpu_gr_config_init(struct gk20a *g) { struct nvgpu_gr_config *config; u32 gpc_index; int err; config = nvgpu_kzalloc(g, sizeof(*config)); if (config == NULL) { return NULL; } config->g = g; if (nvgpu_is_enabled(g, NVGPU_SUPPORT_MIG)) { err = gr_config_init_mig_gpcs(config); if (err < 0) { nvgpu_err(g, "MIG GPC config init failed"); return NULL; } } else { err = gr_config_init_gpcs(config); if (err < 0) { nvgpu_err(g, "GPC config init failed"); return NULL; } } config->max_tpc_count = nvgpu_safe_mult_u32(config->max_gpc_count, config->max_tpc_per_gpc_count); config->pe_count_per_gpc = nvgpu_get_litter_value(g, GPU_LIT_NUM_PES_PER_GPC); if (config->pe_count_per_gpc > GK20A_GR_MAX_PES_PER_GPC) { nvgpu_err(g, "too many pes per gpc"); goto clean_up_init; } config->sm_count_per_tpc = nvgpu_get_litter_value(g, GPU_LIT_NUM_SM_PER_TPC); if (config->sm_count_per_tpc == 0U) { nvgpu_err(g, "sm_count_per_tpc==0!"); goto clean_up_init; } if (gr_config_alloc_struct_mem(g, config) == false) { goto clean_up_init; } config->ppc_count = 0; config->tpc_count = 0; #ifdef CONFIG_NVGPU_GRAPHICS config->zcb_count = 0; #endif for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { config->gpc_tpc_count[gpc_index] = g->ops.gr.config.get_tpc_count_in_gpc(g, config, gpc_index); config->tpc_count = nvgpu_safe_add_u32(config->tpc_count, config->gpc_tpc_count[gpc_index]); #ifdef CONFIG_NVGPU_GRAPHICS if (!nvgpu_is_enabled(g, NVGPU_SUPPORT_MIG)) { config->gpc_zcb_count[gpc_index] = g->ops.gr.config.get_zcull_count_in_gpc(g, config, gpc_index); config->zcb_count = nvgpu_safe_add_u32(config->zcb_count, config->gpc_zcb_count[gpc_index]); } #endif gr_config_init_pes_tpc(g, config, gpc_index); config->ppc_count = nvgpu_safe_add_u32(config->ppc_count, config->gpc_ppc_count[gpc_index]); gr_config_init_gpc_skip_mask(config, gpc_index); } gr_config_log_info(g, config); return config; clean_up_init: nvgpu_kfree(g, config); return NULL; } #ifdef CONFIG_NVGPU_GRAPHICS static u32 prime_set[18] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61 }; /* * Return map tiles count for given index * Return 0 if index is out-of-bounds */ u32 nvgpu_gr_config_get_map_tile_count(struct nvgpu_gr_config *config, u32 index) { if (index >= config->map_tile_count) { return 0; } return config->map_tiles[index]; } u8 *nvgpu_gr_config_get_map_tiles(struct nvgpu_gr_config *config) { return config->map_tiles; } u32 nvgpu_gr_config_get_map_row_offset(struct nvgpu_gr_config *config) { return config->map_row_offset; } int nvgpu_gr_config_init_map_tiles(struct gk20a *g, struct nvgpu_gr_config *config) { s32 comm_denom; s32 mul_factor; s32 *init_frac = NULL; s32 *init_err = NULL; s32 *run_err = NULL; u32 *sorted_num_tpcs = NULL; u32 *sorted_to_unsorted_gpc_map = NULL; u32 gpc_index; u32 gpc_mark = 0; u32 num_tpc; u32 max_tpc_count = 0; u32 swap; u32 tile_count; u32 index; bool delete_map = false; bool gpc_sorted; int ret = 0; u32 num_gpcs = nvgpu_get_litter_value(g, GPU_LIT_NUM_GPCS); u32 num_tpc_per_gpc = nvgpu_get_litter_value(g, GPU_LIT_NUM_TPC_PER_GPC); u32 map_tile_count = num_gpcs * num_tpc_per_gpc; nvgpu_log(g, gpu_dbg_gr, " "); init_frac = nvgpu_kzalloc(g, num_gpcs * sizeof(s32)); init_err = nvgpu_kzalloc(g, num_gpcs * sizeof(s32)); run_err = nvgpu_kzalloc(g, num_gpcs * sizeof(s32)); sorted_num_tpcs = nvgpu_kzalloc(g, (size_t)num_gpcs * (size_t)num_tpc_per_gpc * sizeof(s32)); sorted_to_unsorted_gpc_map = nvgpu_kzalloc(g, (size_t)num_gpcs * sizeof(s32)); if (!((init_frac != NULL) && (init_err != NULL) && (run_err != NULL) && (sorted_num_tpcs != NULL) && (sorted_to_unsorted_gpc_map != NULL))) { ret = -ENOMEM; goto clean_up; } config->map_row_offset = 0xFFFFFFFFU; if (config->tpc_count == 3U) { config->map_row_offset = 2; } else if (config->tpc_count < 3U) { config->map_row_offset = 1; } else { config->map_row_offset = 3; for (index = 1U; index < 18U; index++) { u32 prime = prime_set[index]; if ((config->tpc_count % prime) != 0U) { config->map_row_offset = prime; break; } } } switch (config->tpc_count) { case 15: config->map_row_offset = 6; break; case 14: config->map_row_offset = 5; break; case 13: config->map_row_offset = 2; break; case 11: config->map_row_offset = 7; break; case 10: config->map_row_offset = 6; break; case 7: case 5: config->map_row_offset = 1; break; default: nvgpu_log(g, gpu_dbg_info | gpu_dbg_gr, "unsupported tpc count = %u", config->tpc_count); break; } if (config->map_tiles != NULL) { if (config->map_tile_count != config->tpc_count) { delete_map = true; } for (tile_count = 0; tile_count < config->map_tile_count; tile_count++) { if (nvgpu_gr_config_get_map_tile_count(config, tile_count) >= config->tpc_count) { delete_map = true; } } if (delete_map) { nvgpu_kfree(g, config->map_tiles); config->map_tiles = NULL; config->map_tile_count = 0; } } if (config->map_tiles == NULL) { config->map_tiles = nvgpu_kzalloc(g, map_tile_count * sizeof(u8)); if (config->map_tiles == NULL) { ret = -ENOMEM; goto clean_up; } config->map_tile_count = map_tile_count; for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { sorted_num_tpcs[gpc_index] = config->gpc_tpc_count[gpc_index]; sorted_to_unsorted_gpc_map[gpc_index] = gpc_index; } gpc_sorted = false; while (!gpc_sorted) { gpc_sorted = true; for (gpc_index = 0U; gpc_index < config->gpc_count - 1U; gpc_index++) { if (sorted_num_tpcs[gpc_index + 1U] > sorted_num_tpcs[gpc_index]) { gpc_sorted = false; swap = sorted_num_tpcs[gpc_index]; sorted_num_tpcs[gpc_index] = sorted_num_tpcs[gpc_index + 1U]; sorted_num_tpcs[gpc_index + 1U] = swap; swap = sorted_to_unsorted_gpc_map[gpc_index]; sorted_to_unsorted_gpc_map[gpc_index] = sorted_to_unsorted_gpc_map[gpc_index + 1U]; sorted_to_unsorted_gpc_map[gpc_index + 1U] = swap; } } } for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { if (config->gpc_tpc_count[gpc_index] > max_tpc_count) { max_tpc_count = config->gpc_tpc_count[gpc_index]; } } mul_factor = S32(config->gpc_count) * S32(max_tpc_count); if ((U32(mul_factor) & 0x1U) != 0U) { mul_factor = 2; } else { mul_factor = 1; } comm_denom = S32(config->gpc_count) * S32(max_tpc_count) * mul_factor; for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { num_tpc = sorted_num_tpcs[gpc_index]; init_frac[gpc_index] = S32(num_tpc) * S32(config->gpc_count) * mul_factor; if (num_tpc != 0U) { init_err[gpc_index] = S32(gpc_index) * S32(max_tpc_count) * mul_factor - comm_denom/2; } else { init_err[gpc_index] = 0; } run_err[gpc_index] = init_frac[gpc_index] + init_err[gpc_index]; } while (gpc_mark < config->tpc_count) { for (gpc_index = 0; gpc_index < config->gpc_count; gpc_index++) { if ((run_err[gpc_index] * 2) >= comm_denom) { config->map_tiles[gpc_mark++] = (u8)sorted_to_unsorted_gpc_map[gpc_index]; run_err[gpc_index] += init_frac[gpc_index] - comm_denom; } else { run_err[gpc_index] += init_frac[gpc_index]; } } } } clean_up: nvgpu_kfree(g, init_frac); nvgpu_kfree(g, init_err); nvgpu_kfree(g, run_err); nvgpu_kfree(g, sorted_num_tpcs); nvgpu_kfree(g, sorted_to_unsorted_gpc_map); if (ret != 0) { nvgpu_err(g, "fail"); } else { nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gr, "done"); } return ret; } u32 nvgpu_gr_config_get_max_zcull_per_gpc_count(struct nvgpu_gr_config *config) { return config->max_zcull_per_gpc_count; } u32 nvgpu_gr_config_get_zcb_count(struct nvgpu_gr_config *config) { return config->zcb_count; } u32 nvgpu_gr_config_get_gpc_zcb_count(struct nvgpu_gr_config *config, u32 gpc_index) { return config->gpc_zcb_count[gpc_index]; } #endif void nvgpu_gr_config_deinit(struct gk20a *g, struct nvgpu_gr_config *config) { if (config == NULL) { return; } gr_config_free_mem(g, config); #ifdef CONFIG_NVGPU_GRAPHICS nvgpu_kfree(g, config->map_tiles); #endif nvgpu_kfree(g, config->sm_to_cluster); #ifdef CONFIG_NVGPU_SM_DIVERSITY if (config->sm_to_cluster_redex_config != NULL) { nvgpu_kfree(g, config->sm_to_cluster_redex_config); config->sm_to_cluster_redex_config = NULL; } #endif } u32 nvgpu_gr_config_get_max_gpc_count(struct nvgpu_gr_config *config) { return config->max_gpc_count; } u32 nvgpu_gr_config_get_max_tpc_per_gpc_count(struct nvgpu_gr_config *config) { return config->max_tpc_per_gpc_count; } u32 nvgpu_gr_config_get_max_tpc_count(struct nvgpu_gr_config *config) { return config->max_tpc_count; } u32 nvgpu_gr_config_get_gpc_count(struct nvgpu_gr_config *config) { return config->gpc_count; } u32 nvgpu_gr_config_get_tpc_count(struct nvgpu_gr_config *config) { return config->tpc_count; } u32 nvgpu_gr_config_get_ppc_count(struct nvgpu_gr_config *config) { return config->ppc_count; } u32 nvgpu_gr_config_get_pe_count_per_gpc(struct nvgpu_gr_config *config) { return config->pe_count_per_gpc; } u32 nvgpu_gr_config_get_sm_count_per_tpc(struct nvgpu_gr_config *config) { return config->sm_count_per_tpc; } u32 nvgpu_gr_config_get_gpc_ppc_count(struct nvgpu_gr_config *config, u32 gpc_index) { return config->gpc_ppc_count[gpc_index]; } u32 *nvgpu_gr_config_get_gpc_tpc_count_base(struct nvgpu_gr_config *config) { return config->gpc_tpc_count; } u32 nvgpu_gr_config_get_gpc_tpc_count(struct nvgpu_gr_config *config, u32 gpc_index) { if (gpc_index >= config->gpc_count) { return 0; } return config->gpc_tpc_count[gpc_index]; } u32 nvgpu_gr_config_get_pes_tpc_count(struct nvgpu_gr_config *config, u32 gpc_index, u32 pes_index) { return config->pes_tpc_count[pes_index][gpc_index]; } u32 *nvgpu_gr_config_get_gpc_tpc_mask_base(struct nvgpu_gr_config *config) { return config->gpc_tpc_mask; } u32 nvgpu_gr_config_get_gpc_tpc_mask(struct nvgpu_gr_config *config, u32 gpc_index) { return config->gpc_tpc_mask[gpc_index]; } void nvgpu_gr_config_set_gpc_tpc_mask(struct nvgpu_gr_config *config, u32 gpc_index, u32 val) { config->gpc_tpc_mask[gpc_index] = val; } u32 nvgpu_gr_config_get_gpc_skip_mask(struct nvgpu_gr_config *config, u32 gpc_index) { if (gpc_index >= config->gpc_count) { return 0; } return config->gpc_skip_mask[gpc_index]; } u32 nvgpu_gr_config_get_pes_tpc_mask(struct nvgpu_gr_config *config, u32 gpc_index, u32 pes_index) { return config->pes_tpc_mask[pes_index][gpc_index]; } u32 nvgpu_gr_config_get_gpc_mask(struct nvgpu_gr_config *config) { return config->gpc_mask; } u32 nvgpu_gr_config_get_no_of_sm(struct nvgpu_gr_config *config) { return config->no_of_sm; } void nvgpu_gr_config_set_no_of_sm(struct nvgpu_gr_config *config, u32 no_of_sm) { config->no_of_sm = no_of_sm; } struct nvgpu_sm_info *nvgpu_gr_config_get_sm_info(struct nvgpu_gr_config *config, u32 sm_id) { return &config->sm_to_cluster[sm_id]; } #ifdef CONFIG_NVGPU_SM_DIVERSITY struct nvgpu_sm_info *nvgpu_gr_config_get_redex_sm_info( struct nvgpu_gr_config *config, u32 sm_id) { return &config->sm_to_cluster_redex_config[sm_id]; } #endif u32 nvgpu_gr_config_get_sm_info_gpc_index(struct nvgpu_sm_info *sm_info) { return sm_info->gpc_index; } void nvgpu_gr_config_set_sm_info_gpc_index(struct nvgpu_sm_info *sm_info, u32 gpc_index) { sm_info->gpc_index = gpc_index; } u32 nvgpu_gr_config_get_sm_info_tpc_index(struct nvgpu_sm_info *sm_info) { return sm_info->tpc_index; } void nvgpu_gr_config_set_sm_info_tpc_index(struct nvgpu_sm_info *sm_info, u32 tpc_index) { sm_info->tpc_index = tpc_index; } u32 nvgpu_gr_config_get_sm_info_global_tpc_index(struct nvgpu_sm_info *sm_info) { return sm_info->global_tpc_index; } void nvgpu_gr_config_set_sm_info_global_tpc_index(struct nvgpu_sm_info *sm_info, u32 global_tpc_index) { sm_info->global_tpc_index = global_tpc_index; } u32 nvgpu_gr_config_get_sm_info_sm_index(struct nvgpu_sm_info *sm_info) { return sm_info->sm_index; } void nvgpu_gr_config_set_sm_info_sm_index(struct nvgpu_sm_info *sm_info, u32 sm_index) { sm_info->sm_index = sm_index; }