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