1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Management-Controller-to-Driver Interface 4 * 5 * Copyright 2008-2013 Solarflare Communications Inc. 6 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. 7 */ 8 #include <linux/delay.h> 9 #include <linux/slab.h> 10 #include <linux/io.h> 11 #include <linux/spinlock.h> 12 #include <linux/netdevice.h> 13 #include <linux/etherdevice.h> 14 #include <linux/ethtool.h> 15 #include <linux/if_vlan.h> 16 #include <linux/timer.h> 17 #include <linux/list.h> 18 #include <linux/pci.h> 19 #include <linux/device.h> 20 #include <linux/rwsem.h> 21 #include <linux/vmalloc.h> 22 #include <net/netevent.h> 23 #include <linux/log2.h> 24 #include <linux/net_tstamp.h> 25 #include <linux/wait.h> 26 #include <linux/cdx/bitfield.h> 27 28 #include <linux/cdx/mcdi.h> 29 #include "mcdid.h" 30 31 static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd); 32 static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx); 33 static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx, 34 struct cdx_mcdi_cmd *cmd, 35 unsigned int *handle); 36 static void cdx_mcdi_start_or_queue(struct cdx_mcdi_iface *mcdi, 37 bool allow_retry); 38 static void cdx_mcdi_cmd_start_or_queue(struct cdx_mcdi_iface *mcdi, 39 struct cdx_mcdi_cmd *cmd); 40 static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi, 41 struct cdx_mcdi_cmd *cmd, 42 struct cdx_dword *outbuf, 43 int len, 44 struct list_head *cleanup_list); 45 static void cdx_mcdi_timeout_cmd(struct cdx_mcdi_iface *mcdi, 46 struct cdx_mcdi_cmd *cmd, 47 struct list_head *cleanup_list); 48 static void cdx_mcdi_cmd_work(struct work_struct *context); 49 static void cdx_mcdi_mode_fail(struct cdx_mcdi *cdx, struct list_head *cleanup_list); 50 static void _cdx_mcdi_display_error(struct cdx_mcdi *cdx, unsigned int cmd, 51 size_t inlen, int raw, int arg, int err_no); 52 53 static bool cdx_cmd_cancelled(struct cdx_mcdi_cmd *cmd) 54 { 55 return cmd->state == MCDI_STATE_RUNNING_CANCELLED; 56 } 57 58 static void cdx_mcdi_cmd_release(struct kref *ref) 59 { 60 kfree(container_of(ref, struct cdx_mcdi_cmd, ref)); 61 } 62 63 static unsigned int cdx_mcdi_cmd_handle(struct cdx_mcdi_cmd *cmd) 64 { 65 return cmd->handle; 66 } 67 68 static void _cdx_mcdi_remove_cmd(struct cdx_mcdi_iface *mcdi, 69 struct cdx_mcdi_cmd *cmd, 70 struct list_head *cleanup_list) 71 { 72 /* if cancelled, the completers have already been called */ 73 if (cdx_cmd_cancelled(cmd)) 74 return; 75 76 if (cmd->completer) { 77 list_add_tail(&cmd->cleanup_list, cleanup_list); 78 ++mcdi->outstanding_cleanups; 79 kref_get(&cmd->ref); 80 } 81 } 82 83 static void cdx_mcdi_remove_cmd(struct cdx_mcdi_iface *mcdi, 84 struct cdx_mcdi_cmd *cmd, 85 struct list_head *cleanup_list) 86 { 87 list_del(&cmd->list); 88 _cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); 89 cmd->state = MCDI_STATE_FINISHED; 90 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 91 if (list_empty(&mcdi->cmd_list)) 92 wake_up(&mcdi->cmd_complete_wq); 93 } 94 95 static unsigned long cdx_mcdi_rpc_timeout(struct cdx_mcdi *cdx, unsigned int cmd) 96 { 97 if (!cdx->mcdi_ops->mcdi_rpc_timeout) 98 return MCDI_RPC_TIMEOUT; 99 else 100 return cdx->mcdi_ops->mcdi_rpc_timeout(cdx, cmd); 101 } 102 103 /** 104 * cdx_mcdi_init - Initialize MCDI (Management Controller Driver Interface) state 105 * @cdx: Handle to the CDX MCDI structure 106 * 107 * This function allocates and initializes internal MCDI structures and resources 108 * for the CDX device, including the workqueue, locking primitives, and command 109 * tracking mechanisms. It sets the initial operating mode and prepares the device 110 * for MCDI operations. 111 * 112 * Return: 113 * * 0 - on success 114 * * -ENOMEM - if memory allocation or workqueue creation fails 115 */ 116 int cdx_mcdi_init(struct cdx_mcdi *cdx) 117 { 118 struct cdx_mcdi_iface *mcdi; 119 int rc = -ENOMEM; 120 121 cdx->mcdi = kzalloc(sizeof(*cdx->mcdi), GFP_KERNEL); 122 if (!cdx->mcdi) 123 goto fail; 124 125 mcdi = cdx_mcdi_if(cdx); 126 mcdi->cdx = cdx; 127 128 mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0); 129 if (!mcdi->workqueue) 130 goto fail2; 131 mutex_init(&mcdi->iface_lock); 132 mcdi->mode = MCDI_MODE_EVENTS; 133 INIT_LIST_HEAD(&mcdi->cmd_list); 134 init_waitqueue_head(&mcdi->cmd_complete_wq); 135 136 mcdi->new_epoch = true; 137 138 return 0; 139 fail2: 140 kfree(cdx->mcdi); 141 cdx->mcdi = NULL; 142 fail: 143 return rc; 144 } 145 EXPORT_SYMBOL_GPL(cdx_mcdi_init); 146 147 /** 148 * cdx_mcdi_finish - Cleanup MCDI (Management Controller Driver Interface) state 149 * @cdx: Handle to the CDX MCDI structure 150 * 151 * This function is responsible for cleaning up the MCDI (Management Controller Driver Interface) 152 * resources associated with a cdx_mcdi structure. Also destroys the mcdi workqueue. 153 * 154 */ 155 void cdx_mcdi_finish(struct cdx_mcdi *cdx) 156 { 157 struct cdx_mcdi_iface *mcdi; 158 159 mcdi = cdx_mcdi_if(cdx); 160 if (!mcdi) 161 return; 162 163 cdx_mcdi_wait_for_cleanup(cdx); 164 165 destroy_workqueue(mcdi->workqueue); 166 kfree(cdx->mcdi); 167 cdx->mcdi = NULL; 168 } 169 EXPORT_SYMBOL_GPL(cdx_mcdi_finish); 170 171 static bool cdx_mcdi_flushed(struct cdx_mcdi_iface *mcdi, bool ignore_cleanups) 172 { 173 bool flushed; 174 175 mutex_lock(&mcdi->iface_lock); 176 flushed = list_empty(&mcdi->cmd_list) && 177 (ignore_cleanups || !mcdi->outstanding_cleanups); 178 mutex_unlock(&mcdi->iface_lock); 179 return flushed; 180 } 181 182 /* Wait for outstanding MCDI commands to complete. */ 183 static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx) 184 { 185 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 186 187 if (!mcdi) 188 return; 189 190 wait_event(mcdi->cmd_complete_wq, 191 cdx_mcdi_flushed(mcdi, false)); 192 } 193 194 int cdx_mcdi_wait_for_quiescence(struct cdx_mcdi *cdx, 195 unsigned int timeout_jiffies) 196 { 197 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 198 DEFINE_WAIT_FUNC(wait, woken_wake_function); 199 int rc = 0; 200 201 if (!mcdi) 202 return -EINVAL; 203 204 flush_workqueue(mcdi->workqueue); 205 206 add_wait_queue(&mcdi->cmd_complete_wq, &wait); 207 208 while (!cdx_mcdi_flushed(mcdi, true)) { 209 rc = wait_woken(&wait, TASK_IDLE, timeout_jiffies); 210 if (rc) 211 continue; 212 break; 213 } 214 215 remove_wait_queue(&mcdi->cmd_complete_wq, &wait); 216 217 if (rc > 0) 218 rc = 0; 219 else if (rc == 0) 220 rc = -ETIMEDOUT; 221 222 return rc; 223 } 224 225 static u8 cdx_mcdi_payload_csum(const struct cdx_dword *hdr, size_t hdr_len, 226 const struct cdx_dword *sdu, size_t sdu_len) 227 { 228 u8 *p = (u8 *)hdr; 229 u8 csum = 0; 230 int i; 231 232 for (i = 0; i < hdr_len; i++) 233 csum += p[i]; 234 235 p = (u8 *)sdu; 236 for (i = 0; i < sdu_len; i++) 237 csum += p[i]; 238 239 return ~csum & 0xff; 240 } 241 242 static void cdx_mcdi_send_request(struct cdx_mcdi *cdx, 243 struct cdx_mcdi_cmd *cmd) 244 { 245 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 246 const struct cdx_dword *inbuf = cmd->inbuf; 247 size_t inlen = cmd->inlen; 248 struct cdx_dword hdr[2]; 249 size_t hdr_len; 250 bool not_epoch; 251 u32 xflags; 252 253 if (!mcdi) 254 return; 255 256 mcdi->prev_seq = cmd->seq; 257 mcdi->seq_held_by[cmd->seq] = cmd; 258 mcdi->db_held_by = cmd; 259 cmd->started = jiffies; 260 261 not_epoch = !mcdi->new_epoch; 262 xflags = 0; 263 264 /* MCDI v2 */ 265 WARN_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V2); 266 CDX_POPULATE_DWORD_7(hdr[0], 267 MCDI_HEADER_RESPONSE, 0, 268 MCDI_HEADER_RESYNC, 1, 269 MCDI_HEADER_CODE, MC_CMD_V2_EXTN, 270 MCDI_HEADER_DATALEN, 0, 271 MCDI_HEADER_SEQ, cmd->seq, 272 MCDI_HEADER_XFLAGS, xflags, 273 MCDI_HEADER_NOT_EPOCH, not_epoch); 274 CDX_POPULATE_DWORD_3(hdr[1], 275 MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd->cmd, 276 MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen, 277 MC_CMD_V2_EXTN_IN_MESSAGE_TYPE, 278 MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM); 279 hdr_len = 8; 280 281 hdr[0].cdx_u32 |= (__force __le32)(cdx_mcdi_payload_csum(hdr, hdr_len, inbuf, inlen) << 282 MCDI_HEADER_XFLAGS_LBN); 283 284 print_hex_dump_debug("MCDI REQ HEADER: ", DUMP_PREFIX_NONE, 32, 4, hdr, hdr_len, false); 285 print_hex_dump_debug("MCDI REQ PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, inbuf, inlen, false); 286 287 cdx->mcdi_ops->mcdi_request(cdx, hdr, hdr_len, inbuf, inlen); 288 289 mcdi->new_epoch = false; 290 } 291 292 static int cdx_mcdi_errno(struct cdx_mcdi *cdx, unsigned int mcdi_err) 293 { 294 switch (mcdi_err) { 295 case 0: 296 case MC_CMD_ERR_QUEUE_FULL: 297 return mcdi_err; 298 case MC_CMD_ERR_EPERM: 299 return -EPERM; 300 case MC_CMD_ERR_ENOENT: 301 return -ENOENT; 302 case MC_CMD_ERR_EINTR: 303 return -EINTR; 304 case MC_CMD_ERR_EAGAIN: 305 return -EAGAIN; 306 case MC_CMD_ERR_EACCES: 307 return -EACCES; 308 case MC_CMD_ERR_EBUSY: 309 return -EBUSY; 310 case MC_CMD_ERR_EINVAL: 311 return -EINVAL; 312 case MC_CMD_ERR_ERANGE: 313 return -ERANGE; 314 case MC_CMD_ERR_EDEADLK: 315 return -EDEADLK; 316 case MC_CMD_ERR_ENOSYS: 317 return -EOPNOTSUPP; 318 case MC_CMD_ERR_ETIME: 319 return -ETIME; 320 case MC_CMD_ERR_EALREADY: 321 return -EALREADY; 322 case MC_CMD_ERR_ENOSPC: 323 return -ENOSPC; 324 case MC_CMD_ERR_ENOMEM: 325 return -ENOMEM; 326 case MC_CMD_ERR_ENOTSUP: 327 return -EOPNOTSUPP; 328 case MC_CMD_ERR_ALLOC_FAIL: 329 return -ENOBUFS; 330 case MC_CMD_ERR_MAC_EXIST: 331 return -EADDRINUSE; 332 case MC_CMD_ERR_NO_EVB_PORT: 333 return -EAGAIN; 334 default: 335 return -EPROTO; 336 } 337 } 338 339 static void cdx_mcdi_process_cleanup_list(struct cdx_mcdi *cdx, 340 struct list_head *cleanup_list) 341 { 342 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 343 unsigned int cleanups = 0; 344 345 if (!mcdi) 346 return; 347 348 while (!list_empty(cleanup_list)) { 349 struct cdx_mcdi_cmd *cmd = 350 list_first_entry(cleanup_list, 351 struct cdx_mcdi_cmd, cleanup_list); 352 cmd->completer(cdx, cmd->cookie, cmd->rc, 353 cmd->outbuf, cmd->outlen); 354 list_del(&cmd->cleanup_list); 355 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 356 ++cleanups; 357 } 358 359 if (cleanups) { 360 bool all_done; 361 362 mutex_lock(&mcdi->iface_lock); 363 CDX_WARN_ON_PARANOID(cleanups > mcdi->outstanding_cleanups); 364 all_done = (mcdi->outstanding_cleanups -= cleanups) == 0; 365 mutex_unlock(&mcdi->iface_lock); 366 if (all_done) 367 wake_up(&mcdi->cmd_complete_wq); 368 } 369 } 370 371 static void _cdx_mcdi_cancel_cmd(struct cdx_mcdi_iface *mcdi, 372 unsigned int handle, 373 struct list_head *cleanup_list) 374 { 375 struct cdx_mcdi_cmd *cmd; 376 377 list_for_each_entry(cmd, &mcdi->cmd_list, list) 378 if (cdx_mcdi_cmd_handle(cmd) == handle) { 379 switch (cmd->state) { 380 case MCDI_STATE_QUEUED: 381 case MCDI_STATE_RETRY: 382 pr_debug("command %#x inlen %zu cancelled in queue\n", 383 cmd->cmd, cmd->inlen); 384 /* if not yet running, properly cancel it */ 385 cmd->rc = -EPIPE; 386 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); 387 break; 388 case MCDI_STATE_RUNNING: 389 case MCDI_STATE_RUNNING_CANCELLED: 390 case MCDI_STATE_FINISHED: 391 default: 392 /* invalid state? */ 393 WARN_ON(1); 394 } 395 break; 396 } 397 } 398 399 static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd) 400 { 401 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 402 LIST_HEAD(cleanup_list); 403 404 if (!mcdi) 405 return; 406 407 mutex_lock(&mcdi->iface_lock); 408 cdx_mcdi_timeout_cmd(mcdi, cmd, &cleanup_list); 409 mutex_unlock(&mcdi->iface_lock); 410 cdx_mcdi_process_cleanup_list(cdx, &cleanup_list); 411 } 412 413 struct cdx_mcdi_blocking_data { 414 struct kref ref; 415 bool done; 416 wait_queue_head_t wq; 417 int rc; 418 struct cdx_dword *outbuf; 419 size_t outlen; 420 size_t outlen_actual; 421 }; 422 423 static void cdx_mcdi_blocking_data_release(struct kref *ref) 424 { 425 kfree(container_of(ref, struct cdx_mcdi_blocking_data, ref)); 426 } 427 428 static void cdx_mcdi_rpc_completer(struct cdx_mcdi *cdx, unsigned long cookie, 429 int rc, struct cdx_dword *outbuf, 430 size_t outlen_actual) 431 { 432 struct cdx_mcdi_blocking_data *wait_data = 433 (struct cdx_mcdi_blocking_data *)cookie; 434 435 wait_data->rc = rc; 436 memcpy(wait_data->outbuf, outbuf, 437 min(outlen_actual, wait_data->outlen)); 438 wait_data->outlen_actual = outlen_actual; 439 /* memory barrier */ 440 smp_wmb(); 441 wait_data->done = true; 442 wake_up(&wait_data->wq); 443 kref_put(&wait_data->ref, cdx_mcdi_blocking_data_release); 444 } 445 446 static int cdx_mcdi_rpc_sync(struct cdx_mcdi *cdx, unsigned int cmd, 447 const struct cdx_dword *inbuf, size_t inlen, 448 struct cdx_dword *outbuf, size_t outlen, 449 size_t *outlen_actual, bool quiet) 450 { 451 struct cdx_mcdi_blocking_data *wait_data; 452 struct cdx_mcdi_cmd *cmd_item; 453 unsigned int handle; 454 int rc; 455 456 if (outlen_actual) 457 *outlen_actual = 0; 458 459 wait_data = kmalloc(sizeof(*wait_data), GFP_KERNEL); 460 if (!wait_data) 461 return -ENOMEM; 462 463 cmd_item = kmalloc(sizeof(*cmd_item), GFP_KERNEL); 464 if (!cmd_item) { 465 kfree(wait_data); 466 return -ENOMEM; 467 } 468 469 kref_init(&wait_data->ref); 470 wait_data->done = false; 471 init_waitqueue_head(&wait_data->wq); 472 wait_data->outbuf = outbuf; 473 wait_data->outlen = outlen; 474 475 kref_init(&cmd_item->ref); 476 cmd_item->quiet = quiet; 477 cmd_item->cookie = (unsigned long)wait_data; 478 cmd_item->completer = &cdx_mcdi_rpc_completer; 479 cmd_item->cmd = cmd; 480 cmd_item->inlen = inlen; 481 cmd_item->inbuf = inbuf; 482 483 /* Claim an extra reference for the completer to put. */ 484 kref_get(&wait_data->ref); 485 rc = cdx_mcdi_rpc_async_internal(cdx, cmd_item, &handle); 486 if (rc) { 487 kref_put(&wait_data->ref, cdx_mcdi_blocking_data_release); 488 goto out; 489 } 490 491 if (!wait_event_timeout(wait_data->wq, wait_data->done, 492 cdx_mcdi_rpc_timeout(cdx, cmd)) && 493 !wait_data->done) { 494 pr_err("MC command 0x%x inlen %zu timed out (sync)\n", 495 cmd, inlen); 496 497 cdx_mcdi_cancel_cmd(cdx, cmd_item); 498 499 wait_data->rc = -ETIMEDOUT; 500 wait_data->outlen_actual = 0; 501 } 502 503 if (outlen_actual) 504 *outlen_actual = wait_data->outlen_actual; 505 rc = wait_data->rc; 506 507 out: 508 kref_put(&wait_data->ref, cdx_mcdi_blocking_data_release); 509 510 return rc; 511 } 512 513 static bool cdx_mcdi_get_seq(struct cdx_mcdi_iface *mcdi, unsigned char *seq) 514 { 515 *seq = mcdi->prev_seq; 516 do { 517 *seq = (*seq + 1) % ARRAY_SIZE(mcdi->seq_held_by); 518 } while (mcdi->seq_held_by[*seq] && *seq != mcdi->prev_seq); 519 return !mcdi->seq_held_by[*seq]; 520 } 521 522 static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx, 523 struct cdx_mcdi_cmd *cmd, 524 unsigned int *handle) 525 { 526 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 527 LIST_HEAD(cleanup_list); 528 529 if (!mcdi) { 530 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 531 return -ENETDOWN; 532 } 533 534 if (mcdi->mode == MCDI_MODE_FAIL) { 535 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 536 return -ENETDOWN; 537 } 538 539 cmd->mcdi = mcdi; 540 INIT_WORK(&cmd->work, cdx_mcdi_cmd_work); 541 INIT_LIST_HEAD(&cmd->list); 542 INIT_LIST_HEAD(&cmd->cleanup_list); 543 cmd->rc = 0; 544 cmd->outbuf = NULL; 545 cmd->outlen = 0; 546 547 queue_work(mcdi->workqueue, &cmd->work); 548 return 0; 549 } 550 551 static void cdx_mcdi_cmd_start_or_queue(struct cdx_mcdi_iface *mcdi, 552 struct cdx_mcdi_cmd *cmd) 553 { 554 struct cdx_mcdi *cdx = mcdi->cdx; 555 u8 seq; 556 557 if (!mcdi->db_held_by && 558 cdx_mcdi_get_seq(mcdi, &seq)) { 559 cmd->seq = seq; 560 cmd->reboot_seen = false; 561 cdx_mcdi_send_request(cdx, cmd); 562 cmd->state = MCDI_STATE_RUNNING; 563 } else { 564 cmd->state = MCDI_STATE_QUEUED; 565 } 566 } 567 568 /* try to advance other commands */ 569 static void cdx_mcdi_start_or_queue(struct cdx_mcdi_iface *mcdi, 570 bool allow_retry) 571 { 572 struct cdx_mcdi_cmd *cmd, *tmp; 573 574 list_for_each_entry_safe(cmd, tmp, &mcdi->cmd_list, list) 575 if (cmd->state == MCDI_STATE_QUEUED || 576 (cmd->state == MCDI_STATE_RETRY && allow_retry)) 577 cdx_mcdi_cmd_start_or_queue(mcdi, cmd); 578 } 579 580 /** 581 * cdx_mcdi_process_cmd - Process an incoming MCDI response 582 * @cdx: Handle to the CDX MCDI structure 583 * @outbuf: Pointer to the response buffer received from the management controller 584 * @len: Length of the response buffer in bytes 585 * 586 * This function handles a response from the management controller. It locates the 587 * corresponding command using the sequence number embedded in the header, 588 * completes the command if it is still pending, and initiates any necessary cleanup. 589 * 590 * The function assumes that the response buffer is well-formed and at least one 591 * dword in size. 592 */ 593 void cdx_mcdi_process_cmd(struct cdx_mcdi *cdx, struct cdx_dword *outbuf, int len) 594 { 595 struct cdx_mcdi_iface *mcdi; 596 struct cdx_mcdi_cmd *cmd; 597 LIST_HEAD(cleanup_list); 598 unsigned int respseq; 599 600 if (!len || !outbuf) { 601 pr_err("Got empty MC response\n"); 602 return; 603 } 604 605 mcdi = cdx_mcdi_if(cdx); 606 if (!mcdi) 607 return; 608 609 respseq = CDX_DWORD_FIELD(outbuf[0], MCDI_HEADER_SEQ); 610 611 mutex_lock(&mcdi->iface_lock); 612 cmd = mcdi->seq_held_by[respseq]; 613 614 if (cmd) { 615 if (cmd->state == MCDI_STATE_FINISHED) { 616 mutex_unlock(&mcdi->iface_lock); 617 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 618 return; 619 } 620 621 cdx_mcdi_complete_cmd(mcdi, cmd, outbuf, len, &cleanup_list); 622 } else { 623 pr_err("MC response unexpected for seq : %0X\n", respseq); 624 } 625 626 mutex_unlock(&mcdi->iface_lock); 627 628 cdx_mcdi_process_cleanup_list(mcdi->cdx, &cleanup_list); 629 } 630 EXPORT_SYMBOL_GPL(cdx_mcdi_process_cmd); 631 632 static void cdx_mcdi_cmd_work(struct work_struct *context) 633 { 634 struct cdx_mcdi_cmd *cmd = 635 container_of(context, struct cdx_mcdi_cmd, work); 636 struct cdx_mcdi_iface *mcdi = cmd->mcdi; 637 638 mutex_lock(&mcdi->iface_lock); 639 640 cmd->handle = mcdi->prev_handle++; 641 list_add_tail(&cmd->list, &mcdi->cmd_list); 642 cdx_mcdi_cmd_start_or_queue(mcdi, cmd); 643 644 mutex_unlock(&mcdi->iface_lock); 645 } 646 647 /* 648 * Returns true if the MCDI module is finished with the command. 649 * (examples of false would be if the command was proxied, or it was 650 * rejected by the MC due to lack of resources and requeued). 651 */ 652 static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi, 653 struct cdx_mcdi_cmd *cmd, 654 struct cdx_dword *outbuf, 655 int len, 656 struct list_head *cleanup_list) 657 { 658 size_t resp_hdr_len, resp_data_len; 659 struct cdx_mcdi *cdx = mcdi->cdx; 660 unsigned int respcmd, error; 661 bool completed = false; 662 int rc; 663 664 /* ensure the command can't go away before this function returns */ 665 kref_get(&cmd->ref); 666 667 respcmd = CDX_DWORD_FIELD(outbuf[0], MCDI_HEADER_CODE); 668 error = CDX_DWORD_FIELD(outbuf[0], MCDI_HEADER_ERROR); 669 670 if (respcmd != MC_CMD_V2_EXTN) { 671 resp_hdr_len = 4; 672 resp_data_len = CDX_DWORD_FIELD(outbuf[0], MCDI_HEADER_DATALEN); 673 } else { 674 resp_data_len = 0; 675 resp_hdr_len = 8; 676 if (len >= 8) 677 resp_data_len = 678 CDX_DWORD_FIELD(outbuf[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); 679 } 680 681 if ((resp_hdr_len + resp_data_len) > len) { 682 pr_warn("Incomplete MCDI response received %d. Expected %zu\n", 683 len, (resp_hdr_len + resp_data_len)); 684 resp_data_len = 0; 685 } 686 687 print_hex_dump_debug("MCDI RESP HEADER: ", DUMP_PREFIX_NONE, 32, 4, 688 outbuf, resp_hdr_len, false); 689 print_hex_dump_debug("MCDI RESP PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, 690 outbuf + (resp_hdr_len / 4), resp_data_len, false); 691 692 if (error && resp_data_len == 0) { 693 /* MC rebooted during command */ 694 rc = -EIO; 695 } else { 696 if (WARN_ON_ONCE(error && resp_data_len < 4)) 697 resp_data_len = 4; 698 if (error) { 699 rc = CDX_DWORD_FIELD(outbuf[resp_hdr_len / 4], CDX_DWORD); 700 if (!cmd->quiet) { 701 int err_arg = 0; 702 703 if (resp_data_len >= MC_CMD_ERR_ARG_OFST + 4) { 704 int offset = (resp_hdr_len + MC_CMD_ERR_ARG_OFST) / 4; 705 706 err_arg = CDX_DWORD_VAL(outbuf[offset]); 707 } 708 709 _cdx_mcdi_display_error(cdx, cmd->cmd, 710 cmd->inlen, rc, err_arg, 711 cdx_mcdi_errno(cdx, rc)); 712 } 713 rc = cdx_mcdi_errno(cdx, rc); 714 } else { 715 rc = 0; 716 } 717 } 718 719 /* free doorbell */ 720 if (mcdi->db_held_by == cmd) 721 mcdi->db_held_by = NULL; 722 723 if (cdx_cmd_cancelled(cmd)) { 724 list_del(&cmd->list); 725 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 726 completed = true; 727 } else if (rc == MC_CMD_ERR_QUEUE_FULL) { 728 cmd->state = MCDI_STATE_RETRY; 729 } else { 730 cmd->rc = rc; 731 cmd->outbuf = outbuf + DIV_ROUND_UP(resp_hdr_len, 4); 732 cmd->outlen = resp_data_len; 733 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); 734 completed = true; 735 } 736 737 /* free sequence number and buffer */ 738 mcdi->seq_held_by[cmd->seq] = NULL; 739 740 cdx_mcdi_start_or_queue(mcdi, rc != MC_CMD_ERR_QUEUE_FULL); 741 742 /* wake up anyone waiting for flush */ 743 wake_up(&mcdi->cmd_complete_wq); 744 745 kref_put(&cmd->ref, cdx_mcdi_cmd_release); 746 747 return completed; 748 } 749 750 static void cdx_mcdi_timeout_cmd(struct cdx_mcdi_iface *mcdi, 751 struct cdx_mcdi_cmd *cmd, 752 struct list_head *cleanup_list) 753 { 754 struct cdx_mcdi *cdx = mcdi->cdx; 755 756 pr_err("MC command 0x%x inlen %zu state %d timed out after %u ms\n", 757 cmd->cmd, cmd->inlen, cmd->state, 758 jiffies_to_msecs(jiffies - cmd->started)); 759 760 cmd->rc = -ETIMEDOUT; 761 cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list); 762 763 cdx_mcdi_mode_fail(cdx, cleanup_list); 764 } 765 766 /** 767 * cdx_mcdi_rpc - Issue an MCDI command and wait for completion 768 * @cdx: NIC through which to issue the command 769 * @cmd: Command type number 770 * @inbuf: Command parameters 771 * @inlen: Length of command parameters, in bytes. Must be a multiple 772 * of 4 and no greater than %MCDI_CTL_SDU_LEN_MAX_V1. 773 * @outbuf: Response buffer. May be %NULL if @outlen is 0. 774 * @outlen: Length of response buffer, in bytes. If the actual 775 * response is longer than @outlen & ~3, it will be truncated 776 * to that length. 777 * @outlen_actual: Pointer through which to return the actual response 778 * length. May be %NULL if this is not needed. 779 * 780 * This function may sleep and therefore must be called in process 781 * context. 782 * 783 * Return: A negative error code, or zero if successful. The error 784 * code may come from the MCDI response or may indicate a failure 785 * to communicate with the MC. In the former case, the response 786 * will still be copied to @outbuf and *@outlen_actual will be 787 * set accordingly. In the latter case, *@outlen_actual will be 788 * set to zero. 789 */ 790 int cdx_mcdi_rpc(struct cdx_mcdi *cdx, unsigned int cmd, 791 const struct cdx_dword *inbuf, size_t inlen, 792 struct cdx_dword *outbuf, size_t outlen, 793 size_t *outlen_actual) 794 { 795 return cdx_mcdi_rpc_sync(cdx, cmd, inbuf, inlen, outbuf, outlen, 796 outlen_actual, false); 797 } 798 EXPORT_SYMBOL_GPL(cdx_mcdi_rpc); 799 800 /** 801 * cdx_mcdi_rpc_async - Schedule an MCDI command to run asynchronously 802 * @cdx: NIC through which to issue the command 803 * @cmd: Command type number 804 * @inbuf: Command parameters 805 * @inlen: Length of command parameters, in bytes 806 * @complete: Function to be called on completion or cancellation. 807 * @cookie: Arbitrary value to be passed to @complete. 808 * 809 * This function does not sleep and therefore may be called in atomic 810 * context. It will fail if event queues are disabled or if MCDI 811 * event completions have been disabled due to an error. 812 * 813 * If it succeeds, the @complete function will be called exactly once 814 * in process context, when one of the following occurs: 815 * (a) the completion event is received (in process context) 816 * (b) event queues are disabled (in the process that disables them) 817 */ 818 int 819 cdx_mcdi_rpc_async(struct cdx_mcdi *cdx, unsigned int cmd, 820 const struct cdx_dword *inbuf, size_t inlen, 821 cdx_mcdi_async_completer *complete, unsigned long cookie) 822 { 823 struct cdx_mcdi_cmd *cmd_item = 824 kmalloc(sizeof(struct cdx_mcdi_cmd) + inlen, GFP_ATOMIC); 825 826 if (!cmd_item) 827 return -ENOMEM; 828 829 kref_init(&cmd_item->ref); 830 cmd_item->quiet = true; 831 cmd_item->cookie = cookie; 832 cmd_item->completer = complete; 833 cmd_item->cmd = cmd; 834 cmd_item->inlen = inlen; 835 /* inbuf is probably not valid after return, so take a copy */ 836 cmd_item->inbuf = (struct cdx_dword *)(cmd_item + 1); 837 memcpy(cmd_item + 1, inbuf, inlen); 838 839 return cdx_mcdi_rpc_async_internal(cdx, cmd_item, NULL); 840 } 841 842 static void _cdx_mcdi_display_error(struct cdx_mcdi *cdx, unsigned int cmd, 843 size_t inlen, int raw, int arg, int err_no) 844 { 845 pr_err("MC command 0x%x inlen %d failed err_no=%d (raw=%d) arg=%d\n", 846 cmd, (int)inlen, err_no, raw, arg); 847 } 848 849 /* 850 * Set MCDI mode to fail to prevent any new commands, then cancel any 851 * outstanding commands. 852 * Caller must hold the mcdi iface_lock. 853 */ 854 static void cdx_mcdi_mode_fail(struct cdx_mcdi *cdx, struct list_head *cleanup_list) 855 { 856 struct cdx_mcdi_iface *mcdi = cdx_mcdi_if(cdx); 857 858 if (!mcdi) 859 return; 860 861 mcdi->mode = MCDI_MODE_FAIL; 862 863 while (!list_empty(&mcdi->cmd_list)) { 864 struct cdx_mcdi_cmd *cmd; 865 866 cmd = list_first_entry(&mcdi->cmd_list, struct cdx_mcdi_cmd, 867 list); 868 _cdx_mcdi_cancel_cmd(mcdi, cdx_mcdi_cmd_handle(cmd), cleanup_list); 869 } 870 } 871