1/* $NetBSD: nouveau_nvkm_engine_sec2_base.c,v 1.2 2021/12/18 23:45:37 riastradh Exp $ */ 2 3/* 4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24#include <sys/cdefs.h> 25__KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_sec2_base.c,v 1.2 2021/12/18 23:45:37 riastradh Exp $"); 26 27#include "priv.h" 28 29#include <core/firmware.h> 30#include <subdev/top.h> 31 32static void 33nvkm_sec2_recv(struct work_struct *work) 34{ 35 struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work); 36 37 if (!sec2->initmsg_received) { 38 int ret = sec2->func->initmsg(sec2); 39 if (ret) { 40 nvkm_error(&sec2->engine.subdev, 41 "error parsing init message: %d\n", ret); 42 return; 43 } 44 45 sec2->initmsg_received = true; 46 } 47 48 nvkm_falcon_msgq_recv(sec2->msgq); 49} 50 51static void 52nvkm_sec2_intr(struct nvkm_engine *engine) 53{ 54 struct nvkm_sec2 *sec2 = nvkm_sec2(engine); 55 sec2->func->intr(sec2); 56} 57 58static int 59nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) 60{ 61 struct nvkm_sec2 *sec2 = nvkm_sec2(engine); 62 63 flush_work(&sec2->work); 64 65 if (suspend) { 66 nvkm_falcon_cmdq_fini(sec2->cmdq); 67 sec2->initmsg_received = false; 68 } 69 70 return 0; 71} 72 73static void * 74nvkm_sec2_dtor(struct nvkm_engine *engine) 75{ 76 struct nvkm_sec2 *sec2 = nvkm_sec2(engine); 77 nvkm_falcon_msgq_del(&sec2->msgq); 78 nvkm_falcon_cmdq_del(&sec2->cmdq); 79 nvkm_falcon_qmgr_del(&sec2->qmgr); 80 nvkm_falcon_dtor(&sec2->falcon); 81 return sec2; 82} 83 84static const struct nvkm_engine_func 85nvkm_sec2 = { 86 .dtor = nvkm_sec2_dtor, 87 .fini = nvkm_sec2_fini, 88 .intr = nvkm_sec2_intr, 89}; 90 91int 92nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, 93 int index, u32 addr, struct nvkm_sec2 **psec2) 94{ 95 struct nvkm_sec2 *sec2; 96 int ret; 97 98 if (!(sec2 = *psec2 = kzalloc(sizeof(*sec2), GFP_KERNEL))) 99 return -ENOMEM; 100 101 ret = nvkm_engine_ctor(&nvkm_sec2, device, index, true, &sec2->engine); 102 if (ret) 103 return ret; 104 105 fwif = nvkm_firmware_load(&sec2->engine.subdev, fwif, "Sec2", sec2); 106 if (IS_ERR(fwif)) 107 return PTR_ERR(fwif); 108 109 sec2->func = fwif->func; 110 111 ret = nvkm_falcon_ctor(sec2->func->flcn, &sec2->engine.subdev, 112 nvkm_subdev_name[index], addr, &sec2->falcon); 113 if (ret) 114 return ret; 115 116 if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr)) || 117 (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq)) || 118 (ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq))) 119 return ret; 120 121 INIT_WORK(&sec2->work, nvkm_sec2_recv); 122 return 0; 123}; 124