/* If there's no LS FW managing bootstrapping of other LS falcons, *wedependontheHSfirmwarebeingabletodoitinstead.
*/ if (!rtos) { /* Which isn't possible everywhere... */ if ((mask & acr->func->bootstrap_falcons) == mask) { int ret = nvkm_acr_reload(acr); if (ret) return ret;
if (list_empty(&acr->hsfw) || !acr->func || !acr->func->wpr_layout) {
nvkm_debug(subdev, "No HSFW(s)\n");
nvkm_acr_cleanup(acr); return0;
}
/* Determine layout/size of WPR image up-front, as we need to know *ittoallocatememorybeforewebeginconstructingit.
*/
list_for_each_entry_safe(lsfw, lsft, &acr->lsfw, head) { /* Cull unknown falcons that are present in WPR image. */ if (acr->wpr_fw) { if (!lsfw->func) {
nvkm_acr_lsfw_del(lsfw); continue;
}
wpr_size = acr->wpr_fw->size;
}
/* Ensure we've fetched falcon configuration. */
ret = nvkm_falcon_get(lsfw->falcon, subdev); if (ret) return ret;
/* Ensure the falcon that'll provide ACR functions is booted first. */
rtos = nvkm_acr_rtos(acr); if (rtos) {
falcons = rtos->func->bootstrap_falcons;
list_move(&rtos->head, &acr->lsf);
} else {
falcons = acr->func->bootstrap_falcons;
}
/* Cull falcons that can't be bootstrapped, or the HSFW can fail to *bootandleavetheGPUinaweirdstate.
*/
list_for_each_entry_safe(lsfw, lsft, &acr->lsfw, head) { if (!(falcons & BIT_ULL(lsfw->id))) {
nvkm_warn(subdev, "%s falcon cannot be bootstrapped\n",
nvkm_acr_lsf_id(lsfw->id));
nvkm_acr_lsfw_del(lsfw);
}
}
if (!acr->wpr_fw || acr->wpr_comp)
wpr_size = acr->func->wpr_layout(acr);
/* Allocate/Locate WPR + fill ucode blob pointer. * *dGPU:allocateWPR+shadowblob *Tegra:locateWPRwithregs,ensuresizeissufficient, *allocateucodeblob.
*/
ret = acr->func->wpr_alloc(acr, wpr_size); if (ret) return ret;
nvkm_debug(subdev, "WPR region is from 0x%llx-0x%llx (shadow 0x%llx)\n",
acr->wpr_start, acr->wpr_end, acr->shadow_start);
/* Write WPR to ucode blob. */
nvkm_kmap(acr->wpr); if (acr->wpr_fw && !acr->wpr_comp)
nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size);
if (!acr->wpr_fw || acr->wpr_comp)
acr->func->wpr_build(acr, rtos);
acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev);
if (acr->wpr_fw && acr->wpr_comp) {
nvkm_kmap(acr->wpr); for (i = 0; i < acr->wpr_fw->size; i += 4) {
u32 us = nvkm_ro32(acr->wpr, i);
u32 fw = ((u32 *)acr->wpr_fw->data)[i/4]; if (fw != us) {
nvkm_warn(subdev, "%08x: %08x %08x\n",
i, us, fw);
}
} return -EINVAL;
}
nvkm_done(acr->wpr);
/* Allocate instance block for ACR-related stuff. */
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true,
&acr->inst); if (ret) return ret;
ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "acr", &acr->vmm); if (ret) return ret;
acr->vmm->debug = acr->subdev.debug;
ret = nvkm_vmm_join(acr->vmm, acr->inst); if (ret) return ret;
staticint
nvkm_acr_ctor_wpr(struct nvkm_acr *acr, int ver)
{ struct nvkm_subdev *subdev = &acr->subdev; struct nvkm_device *device = subdev->device; int ret;
ret = nvkm_firmware_get(subdev, "acr/wpr", ver, &acr->wpr_fw); if (ret < 0) return ret;
/* Pre-add LSFs in the order they appear in the FW WPR image so that *we'reabletodoabinarycomparisonwithourowngenerator.
*/
ret = acr->func->wpr_parse(acr); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.