FILE
rpc.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
1/* 2 * Copyright 2023 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22#include <rm/rpc.h> 23 24#include "nvrm/rpcfn.h" 25 26#define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE 27#define GSP_MSG_MAX_SIZE (GSP_MSG_MIN_SIZE * 16) 28 29/** 30 * DOC: GSP message queue element 31 * 32 * https://github.com/NVIDIA/open-gpu-kernel-modules/blob/535/src/nvidia/inc/kernel/gpu/gsp/message_queue_priv.h 33 * 34 * The GSP command queue and status queue are message queues for the 35 * communication between software and GSP. The software submits the GSP 36 * RPC via the GSP command queue, GSP writes the status of the submitted 37 * RPC in the status queue. 38 * 39 * A GSP message queue element consists of three parts: 40 * 41 * - message element header (struct r535_gsp_msg), which mostly maintains 42 * the metadata for queuing the element. 43 * 44 * - RPC message header (struct nvfw_gsp_rpc), which maintains the info 45 * of the RPC. E.g., the RPC function number. 46 * 47 * - The payload, where the RPC message stays. E.g. the params of a 48 * specific RPC function. Some RPC functions also have their headers 49 * in the payload. E.g. rm_alloc, rm_control. 50 * 51 * The memory layout of a GSP message element can be illustrated below:: 52 * 53 * +------------------------+ 54 * | Message Element Header | 55 * | (r535_gsp_msg) | 56 * | | 57 * | (r535_gsp_msg.data) | 58 * | | | 59 * |----------V-------------| 60 * | GSP RPC Header | 61 * | (nvfw_gsp_rpc) | 62 * | | 63 * | (nvfw_gsp_rpc.data) | 64 * | | | 65 * |----------V-------------| 66 * | Payload | 67 * | | 68 * | header(optional) | 69 * | params | 70 * +------------------------+ 71 * 72 * The max size of a message queue element is 16 pages (including the 73 * headers). When a GSP message to be sent is larger than 16 pages, the 74 * message should be split into multiple elements and sent accordingly. 75 * 76 * In the bunch of the split elements, the first element has the expected 77 * function number, while the rest of the elements are sent with the 78 * function number NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD. 79 * 80 * GSP consumes the elements from the cmdq and always writes the result 81 * back to the msgq. The result is also formed as split elements. 82 * 83 * Terminology: 84 * 85 * - gsp_msg(msg): GSP message element (element header + GSP RPC header + 86 * payload) 87 * - gsp_rpc(rpc): GSP RPC (RPC header + payload) 88 * - gsp_rpc_buf: buffer for (GSP RPC header + payload) 89 * - gsp_rpc_len: size of (GSP RPC header + payload) 90 * - params_size: size of params in the payload 91 * - payload_size: size of (header if exists + params) in the payload 92 */ 93 94struct r535_gsp_msg { 95 u8 auth_tag_buffer[16]; 96 u8 aad_buffer[16]; 97 u32 checksum; 98 u32 sequence; 99 u32 elem_count; 100 u32 pad; 101 u8 data[]; 102}; 103 104struct nvfw_gsp_rpc { 105 u32 header_version; 106 u32 signature; 107 u32 length; 108 u32 function; 109 u32 rpc_result; 110 u32 rpc_result_private; 111 u32 sequence; 112 union { 113 u32 spare; 114 u32 cpuRmGfid; 115 }; 116 u8 data[]; 117}; 118 119#define GSP_MSG_HDR_SIZE offsetof(struct r535_gsp_msg, data) 120 121#define to_gsp_hdr(p, header) \ 122 container_of((void *)p, typeof(*header), data) 123 124#define to_payload_hdr(p, header) \ 125 container_of((void *)p, typeof(*header), params) 126 127int 128r535_rpc_status_to_errno(uint32_t rpc_status) 129{ 130 switch (rpc_status) { 131 case 0x55: /* NV_ERR_NOT_READY */ 132 case 0x66: /* NV_ERR_TIMEOUT_RETRY */ 133 return -EBUSY; 134 case 0x51: /* NV_ERR_NO_MEMORY */ 135 return -ENOMEM; 136 default: 137 return -EINVAL; 138 } 139} 140 141static int 142r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *ptime) 143{ 144 u32 size, rptr = *gsp->msgq.rptr; 145 int used; 146 147 size = DIV_ROUND_UP(GSP_MSG_HDR_SIZE + gsp_rpc_len, 148 GSP_PAGE_SIZE); 149 if (WARN_ON(!size || size >= gsp->msgq.cnt)) 150 return -EINVAL; 151 152 do { 153 u32 wptr = *gsp->msgq.wptr; 154 155 used = wptr + gsp->msgq.cnt - rptr; 156 if (used >= gsp->msgq.cnt) 157 used -= gsp->msgq.cnt; 158 if (used >= size) 159 break; 160 161 usleep_range(1, 2); 162 } while (--(*ptime)); 163 164 if (WARN_ON(!*ptime)) 165 return -ETIMEDOUT; 166 167 return used; 168} 169 170static struct r535_gsp_msg * 171r535_gsp_msgq_get_entry(struct nvkm_gsp *gsp) 172{ 173 u32 rptr = *gsp->msgq.rptr; 174 175 /* Skip the first page, which is the message queue info */ 176 return (void *)((u8 *)gsp->shm.msgq.ptr + GSP_PAGE_SIZE + 177 rptr * GSP_PAGE_SIZE); 178} 179 180/** 181 * DOC: Receive a GSP message queue element 182 * 183 * Receiving a GSP message queue element from the message queue consists of 184 * the following steps: 185 * 186 * - Peek the element from the queue: r535_gsp_msgq_peek(). 187 * Peek the first page of the element to determine the total size of the 188 * message before allocating the proper memory. 189 * 190 * - Allocate memory for the message. 191 * Once the total size of the message is determined from the GSP message 192 * queue element, the caller of r535_gsp_msgq_recv() allocates the 193 * required memory. 194 * 195 * - Receive the message: r535_gsp_msgq_recv(). 196 * Copy the message into the allocated memory. Advance the read pointer. 197 * If the message is a large GSP message, r535_gsp_msgq_recv() calls 198 * r535_gsp_msgq_recv_one_elem() repeatedly to receive continuation parts 199 * until the complete message is received. 200 * r535_gsp_msgq_recv() assembles the payloads of cotinuation parts into 201 * the return of the large GSP message. 202 * 203 * - Free the allocated memory: r535_gsp_msg_done(). 204 * The user is responsible for freeing the memory allocated for the GSP 205 * message pages after they have been processed. 206 */ 207static void * 208r535_gsp_msgq_peek(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) 209{ 210 struct r535_gsp_msg *mqe; 211 int ret; 212 213 ret = r535_gsp_msgq_wait(gsp, gsp_rpc_len, retries); 214 if (ret < 0) 215 return ERR_PTR(ret); 216 217 mqe = r535_gsp_msgq_get_entry(gsp); 218 219 return mqe->data; 220} 221 222struct r535_gsp_msg_info { 223 int *retries; 224 u32 gsp_rpc_len; 225 void *gsp_rpc_buf; 226 bool continuation; 227}; 228 229static void 230r535_gsp_msg_dump(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg, int lvl); 231 232static void * 233r535_gsp_msgq_recv_one_elem(struct nvkm_gsp *gsp, 234 struct r535_gsp_msg_info *info) 235{ 236 u8 *buf = info->gsp_rpc_buf; 237 u32 rptr = *gsp->msgq.rptr; 238 struct r535_gsp_msg *mqe; 239 u32 size, expected, len; 240 int ret; 241 242 expected = info->gsp_rpc_len; 243 244 ret = r535_gsp_msgq_wait(gsp, expected, info->retries); 245 if (ret < 0) 246 return ERR_PTR(ret); 247 248 mqe = r535_gsp_msgq_get_entry(gsp); 249 250 if (info->continuation) { 251 struct nvfw_gsp_rpc *rpc = (struct nvfw_gsp_rpc *)mqe->data; 252 253 if (rpc->function != NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD) { 254 nvkm_error(&gsp->subdev, 255 "Not a continuation of a large RPC\n"); 256 r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); 257 return ERR_PTR(-EIO); 258 } 259 } 260 261 size = ALIGN(expected + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); 262 263 len = ((gsp->msgq.cnt - rptr) * GSP_PAGE_SIZE) - sizeof(*mqe); 264 len = min_t(u32, expected, len); 265 266 if (info->continuation) 267 memcpy(buf, mqe->data + sizeof(struct nvfw_gsp_rpc), 268 len - sizeof(struct nvfw_gsp_rpc)); 269 else 270 memcpy(buf, mqe->data, len); 271 272 expected -= len; 273 274 if (expected) { 275 mqe = (void *)((u8 *)gsp->shm.msgq.ptr + 0x1000 + 0 * 0x1000); 276 memcpy(buf + len, mqe, expected); 277 } 278 279 rptr = (rptr + DIV_ROUND_UP(size, GSP_PAGE_SIZE)) % gsp->msgq.cnt; 280 281 mb(); 282 (*gsp->msgq.rptr) = rptr; 283 return buf; 284} 285 286static void * 287r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) 288{ 289 struct r535_gsp_msg *mqe; 290 const u32 max_rpc_size = GSP_MSG_MAX_SIZE - sizeof(*mqe); 291 struct nvfw_gsp_rpc *rpc; 292 struct r535_gsp_msg_info info = {0}; 293 u32 expected = gsp_rpc_len; 294 void *buf; 295 296 mqe = r535_gsp_msgq_get_entry(gsp); 297 rpc = (struct nvfw_gsp_rpc *)mqe->data; 298 299 if (WARN_ON(rpc->length > max_rpc_size)) 300 return NULL; 301 302 buf = kvmalloc(max_t(u32, rpc->length, expected), GFP_KERNEL); 303 if (!buf) 304 return ERR_PTR(-ENOMEM); 305 306 info.gsp_rpc_buf = buf; 307 info.retries = retries; 308 info.gsp_rpc_len = rpc->length; 309 310 buf = r535_gsp_msgq_recv_one_elem(gsp, &info); 311 if (IS_ERR(buf)) { 312 kvfree(info.gsp_rpc_buf); 313 info.gsp_rpc_buf = NULL; 314 return buf; 315 } 316 317 if (expected <= max_rpc_size) 318 return buf; 319 320 info.gsp_rpc_buf += info.gsp_rpc_len; 321 expected -= info.gsp_rpc_len; 322 323 while (expected) { 324 u32 size; 325 326 rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries); 327 if (IS_ERR_OR_NULL(rpc)) { 328 kvfree(buf); 329 return rpc; 330 } 331 332 info.gsp_rpc_len = rpc->length; 333 info.continuation = true; 334 335 rpc = r535_gsp_msgq_recv_one_elem(gsp, &info); 336 if (IS_ERR_OR_NULL(rpc)) { 337 kvfree(buf); 338 return rpc; 339 } 340 341 size = info.gsp_rpc_len - sizeof(*rpc); 342 expected -= size; 343 info.gsp_rpc_buf += size; 344 } 345 346 rpc = buf; 347 rpc->length = gsp_rpc_len; 348 return buf; 349} 350 351static int 352r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *rpc) 353{ 354 struct r535_gsp_msg *msg = to_gsp_hdr(rpc, msg); 355 struct r535_gsp_msg *cqe; 356 u32 gsp_rpc_len = msg->checksum; 357 u64 *ptr = (void *)msg; 358 u64 *end; 359 u64 csum = 0; 360 int free, time = 1000000; 361 u32 wptr, size, step, len; 362 u32 off = 0; 363 364 len = ALIGN(GSP_MSG_HDR_SIZE + gsp_rpc_len, GSP_PAGE_SIZE); 365 366 end = (u64 *)((char *)ptr + len); 367 msg->pad = 0; 368 msg->checksum = 0; 369 msg->sequence = gsp->cmdq.seq++; 370 msg->elem_count = DIV_ROUND_UP(len, 0x1000); 371 372 while (ptr < end) 373 csum ^= *ptr++; 374 375 msg->checksum = upper_32_bits(csum) ^ lower_32_bits(csum); 376 377 wptr = *gsp->cmdq.wptr; 378 do { 379 do { 380 free = *gsp->cmdq.rptr + gsp->cmdq.cnt - wptr - 1; 381 if (free >= gsp->cmdq.cnt) 382 free -= gsp->cmdq.cnt; 383 if (free >= 1) 384 break; 385 386 usleep_range(1, 2); 387 } while(--time); 388 389 if (WARN_ON(!time)) { 390 kvfree(msg); 391 return -ETIMEDOUT; 392 } 393 394 cqe = (void *)((u8 *)gsp->shm.cmdq.ptr + 0x1000 + wptr * 0x1000); 395 step = min_t(u32, free, (gsp->cmdq.cnt - wptr)); 396 size = min_t(u32, len, step * GSP_PAGE_SIZE); 397 398 memcpy(cqe, (u8 *)msg + off, size); 399 400 wptr += DIV_ROUND_UP(size, 0x1000); 401 if (wptr == gsp->cmdq.cnt) 402 wptr = 0; 403 404 off += size; 405 len -= size; 406 } while (len); 407 408 nvkm_trace(&gsp->subdev, "cmdq: wptr %d\n", wptr); 409 wmb(); 410 (*gsp->cmdq.wptr) = wptr; 411 mb(); 412 413 nvkm_falcon_wr32(&gsp->falcon, 0xc00, 0x00000000); 414 415 kvfree(msg); 416 return 0; 417} 418 419static void * 420r535_gsp_cmdq_get(struct nvkm_gsp *gsp, u32 gsp_rpc_len) 421{ 422 struct r535_gsp_msg *msg; 423 u32 size = GSP_MSG_HDR_SIZE + gsp_rpc_len; 424 425 size = ALIGN(size, GSP_MSG_MIN_SIZE); 426 msg = kvzalloc(size, GFP_KERNEL); 427 if (!msg) 428 return ERR_PTR(-ENOMEM); 429 430 msg->checksum = gsp_rpc_len; 431 return msg->data; 432} 433 434static void 435r535_gsp_msg_done(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg) 436{ 437 kvfree(msg); 438} 439 440static void 441r535_gsp_msg_dump(struct nvkm_gsp *gsp, struct nvfw_gsp_rpc *msg, int lvl) 442{ 443 if (gsp->subdev.debug >= lvl) { 444 nvkm_printk__(&gsp->subdev, lvl, info, 445 "msg fn:%d len:0x%x/0x%zx res:0x%x resp:0x%x\n", 446 msg->function, msg->length, msg->length - sizeof(*msg), 447 msg->rpc_result, msg->rpc_result_private); 448 print_hex_dump(KERN_INFO, "msg: ", DUMP_PREFIX_OFFSET, 16, 1, 449 msg->data, msg->length - sizeof(*msg), true); 450 } 451} 452 453struct nvfw_gsp_rpc * 454r535_gsp_msg_recv(struct nvkm_gsp *gsp, int fn, u32 gsp_rpc_len) 455{ 456 struct nvkm_subdev *subdev = &gsp->subdev; 457 struct nvfw_gsp_rpc *rpc; 458 int retries = 4000000, i; 459 460retry: 461 rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), &retries); 462 if (IS_ERR_OR_NULL(rpc)) 463 return rpc; 464 465 rpc = r535_gsp_msgq_recv(gsp, gsp_rpc_len, &retries); 466 if (IS_ERR_OR_NULL(rpc)) 467 return rpc; 468 469 if (rpc->rpc_result) { 470 r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); 471 r535_gsp_msg_done(gsp, rpc); 472 return ERR_PTR(-EINVAL); 473 } 474 475 r535_gsp_msg_dump(gsp, rpc, NV_DBG_TRACE); 476 477 if (fn && rpc->function == fn) { 478 if (gsp_rpc_len) { 479 if (rpc->length < gsp_rpc_len) { 480 nvkm_error(subdev, "rpc len %d < %d\n", 481 rpc->length, gsp_rpc_len); 482 r535_gsp_msg_dump(gsp, rpc, NV_DBG_ERROR); 483 r535_gsp_msg_done(gsp, rpc); 484 return ERR_PTR(-EIO); 485 } 486 487 return rpc; 488 } 489 490 r535_gsp_msg_done(gsp, rpc); 491 return NULL; 492 } 493 494 for (i = 0; i < gsp->msgq.ntfy_nr; i++) { 495 struct nvkm_gsp_msgq_ntfy *ntfy = &gsp->msgq.ntfy[i]; 496 497 if (ntfy->fn == rpc->function) { 498 if (ntfy->func) 499 ntfy->func(ntfy->priv, ntfy->fn, rpc->data, 500 rpc->length - sizeof(*rpc)); 501 break; 502 } 503 } 504 505 if (i == gsp->msgq.ntfy_nr) 506 r535_gsp_msg_dump(gsp, rpc, NV_DBG_WARN); 507 508 r535_gsp_msg_done(gsp, rpc); 509 if (fn) 510 goto retry; 511 512 if (*gsp->msgq.rptr != *gsp->msgq.wptr) 513 goto retry; 514 515 return NULL; 516} 517 518int 519r535_gsp_msg_ntfy_add(struct nvkm_gsp *gsp, u32 fn, nvkm_gsp_msg_ntfy_func func, void *priv) 520{ 521 int ret = 0; 522 523 mutex_lock(&gsp->msgq.mutex); 524 if (WARN_ON(gsp->msgq.ntfy_nr >= ARRAY_SIZE(gsp->msgq.ntfy))) { 525 ret = -ENOSPC; 526 } else { 527 gsp->msgq.ntfy[gsp->msgq.ntfy_nr].fn = fn; 528 gsp->msgq.ntfy[gsp->msgq.ntfy_nr].func = func; 529 gsp->msgq.ntfy[gsp->msgq.ntfy_nr].priv = priv; 530 gsp->msgq.ntfy_nr++; 531 } 532 mutex_unlock(&gsp->msgq.mutex); 533 return ret; 534} 535 536int 537r535_gsp_rpc_poll(struct nvkm_gsp *gsp, u32 fn) 538{ 539 void *repv; 540 541 mutex_lock(&gsp->cmdq.mutex); 542 repv = r535_gsp_msg_recv(gsp, fn, 0); 543 mutex_unlock(&gsp->cmdq.mutex); 544 if (IS_ERR(repv)) 545 return PTR_ERR(repv); 546 547 return 0; 548} 549 550static void * 551r535_gsp_rpc_handle_reply(struct nvkm_gsp *gsp, u32 fn, 552 enum nvkm_gsp_rpc_reply_policy policy, 553 u32 gsp_rpc_len) 554{ 555 struct nvfw_gsp_rpc *reply; 556 void *repv = NULL; 557 558 switch (policy) { 559 case NVKM_GSP_RPC_REPLY_NOWAIT: 560 case NVKM_GSP_RPC_REPLY_NOSEQ: 561 break; 562 case NVKM_GSP_RPC_REPLY_RECV: 563 reply = r535_gsp_msg_recv(gsp, fn, gsp_rpc_len); 564 if (!IS_ERR_OR_NULL(reply)) 565 repv = reply->data; 566 else 567 repv = reply; 568 break; 569 case NVKM_GSP_RPC_REPLY_POLL: 570 repv = r535_gsp_msg_recv(gsp, fn, 0); 571 break; 572 } 573 574 return repv; 575} 576 577static void * 578r535_gsp_rpc_send(struct nvkm_gsp *gsp, void *payload, 579 enum nvkm_gsp_rpc_reply_policy policy, u32 gsp_rpc_len) 580{ 581 struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); 582 u32 fn = rpc->function; 583 int ret; 584 585 if (gsp->subdev.debug >= NV_DBG_TRACE) { 586 nvkm_trace(&gsp->subdev, "rpc fn:%d len:0x%x/0x%zx\n", rpc->function, 587 rpc->length, rpc->length - sizeof(*rpc)); 588 print_hex_dump(KERN_INFO, "rpc: ", DUMP_PREFIX_OFFSET, 16, 1, 589 rpc->data, rpc->length - sizeof(*rpc), true); 590 } 591 592 if (policy == NVKM_GSP_RPC_REPLY_NOSEQ) 593 rpc->sequence = 0; 594 else 595 rpc->sequence = gsp->rpc_seq++; 596 597 ret = r535_gsp_cmdq_push(gsp, rpc); 598 if (ret) 599 return ERR_PTR(ret); 600 601 return r535_gsp_rpc_handle_reply(gsp, fn, policy, gsp_rpc_len); 602} 603 604static void 605r535_gsp_rpc_done(struct nvkm_gsp *gsp, void *repv) 606{ 607 struct nvfw_gsp_rpc *rpc = container_of(repv, typeof(*rpc), data); 608 609 r535_gsp_msg_done(gsp, rpc); 610} 611 612static void * 613r535_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 payload_size) 614{ 615 struct nvfw_gsp_rpc *rpc; 616 617 rpc = r535_gsp_cmdq_get(gsp, ALIGN(sizeof(*rpc) + payload_size, 618 sizeof(u64))); 619 if (IS_ERR(rpc)) 620 return ERR_CAST(rpc); 621 622 rpc->header_version = 0x03000000; 623 rpc->signature = ('C' << 24) | ('P' << 16) | ('R' << 8) | 'V'; 624 rpc->function = fn; 625 rpc->rpc_result = 0xffffffff; 626 rpc->rpc_result_private = 0xffffffff; 627 rpc->length = sizeof(*rpc) + payload_size; 628 return rpc->data; 629} 630 631static void * 632r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload, 633 enum nvkm_gsp_rpc_reply_policy policy, u32 gsp_rpc_len) 634{ 635 struct nvfw_gsp_rpc *rpc = to_gsp_hdr(payload, rpc); 636 struct r535_gsp_msg *msg = to_gsp_hdr(rpc, msg); 637 const u32 max_rpc_size = GSP_MSG_MAX_SIZE - sizeof(*msg); 638 const u32 max_payload_size = max_rpc_size - sizeof(*rpc); 639 u32 payload_size = rpc->length - sizeof(*rpc); 640 void *repv; 641 642 mutex_lock(&gsp->cmdq.mutex); 643 if (payload_size > max_payload_size) { 644 const u32 fn = rpc->function; 645 u32 remain_payload_size = payload_size; 646 void *next; 647 648 /* Send initial RPC. */ 649 next = r535_gsp_rpc_get(gsp, fn, max_payload_size); 650 if (IS_ERR(next)) { 651 repv = next; 652 goto done; 653 } 654 655 memcpy(next, payload, max_payload_size); 656 657 repv = r535_gsp_rpc_send(gsp, next, NVKM_GSP_RPC_REPLY_NOWAIT, 0); 658 if (IS_ERR(repv)) 659 goto done; 660 661 payload += max_payload_size; 662 remain_payload_size -= max_payload_size; 663 664 /* Remaining chunks sent as CONTINUATION_RECORD RPCs. */ 665 while (remain_payload_size) { 666 u32 size = min(remain_payload_size, 667 max_payload_size); 668 669 next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size); 670 if (IS_ERR(next)) { 671 repv = next; 672 goto done; 673 } 674 675 memcpy(next, payload, size); 676 677 repv = r535_gsp_rpc_send(gsp, next, NVKM_GSP_RPC_REPLY_NOWAIT, 0); 678 if (IS_ERR(repv)) 679 goto done; 680 681 payload += size; 682 remain_payload_size -= size; 683 } 684 685 /* Wait for reply. */ 686 repv = r535_gsp_rpc_handle_reply(gsp, fn, policy, payload_size + 687 sizeof(*rpc)); 688 if (!IS_ERR(repv)) 689 kvfree(msg); 690 } else { 691 repv = r535_gsp_rpc_send(gsp, payload, policy, gsp_rpc_len); 692 } 693 694done: 695 mutex_unlock(&gsp->cmdq.mutex); 696 return repv; 697} 698 699const struct nvkm_rm_api_rpc 700r535_rpc = { 701 .get = r535_gsp_rpc_get, 702 .push = r535_gsp_rpc_push, 703 .done = r535_gsp_rpc_done, 704};
~/
Read-only file preview.