Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge patch series "mei: connect to card in D3cold"

Alexander Usyskin <alexander.usyskin@intel.com> says:

When discrete graphic card enters D3cold th CSC engine is powered down.

On wakeup from the D3cold full HECI link reset is required. The driver
should detect that firmware requests link reset and initiate the link
reset flow.

In the usual flow the connect IOCTL will trigger the wake from D3cold
and corresponding link reset. The MEI driver invalidates all open
handles on link reset including the one that triggered the wake
rendering this connection unusable. To break this loop make connect
detect that it is interrupted by link reset and retry connect attempt
after reset was completed.

Link: https://lore.kernel.org/r/20250918130435.3327400-1-alexander.usyskin@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

+62 -77
+1 -1
drivers/misc/mei/bus.c
··· 814 814 815 815 ret = mei_cl_connect(cl, cldev->me_cl, NULL); 816 816 if (ret < 0) { 817 - dev_err(&cldev->dev, "cannot connect\n"); 817 + dev_dbg(&cldev->dev, "cannot connect\n"); 818 818 mei_cl_bus_vtag_free(cldev); 819 819 } 820 820
+17 -42
drivers/misc/mei/hw-me.c
··· 494 494 } 495 495 496 496 /** 497 - * mei_me_check_fw_reset - check for the firmware reset error and exception conditions 498 - * 499 - * @dev: mei device 500 - */ 501 - static void mei_me_check_fw_reset(struct mei_device *dev) 502 - { 503 - struct mei_fw_status fw_status; 504 - char fw_sts_str[MEI_FW_STATUS_STR_SZ] = {0}; 505 - int ret; 506 - u32 fw_pm_event = 0; 507 - 508 - if (!dev->saved_fw_status_flag) 509 - goto end; 510 - 511 - if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) { 512 - ret = mei_fw_status(dev, &fw_status); 513 - if (!ret) { 514 - fw_pm_event = fw_status.status[1] & PCI_CFG_HFS_2_PM_EVENT_MASK; 515 - if (fw_pm_event != PCI_CFG_HFS_2_PM_CMOFF_TO_CMX_ERROR && 516 - fw_pm_event != PCI_CFG_HFS_2_PM_CM_RESET_ERROR) 517 - goto end; 518 - } else { 519 - dev_err(&dev->dev, "failed to read firmware status: %d\n", ret); 520 - } 521 - } 522 - 523 - mei_fw_status2str(&dev->saved_fw_status, fw_sts_str, sizeof(fw_sts_str)); 524 - dev_warn(&dev->dev, "unexpected reset: fw_pm_event = 0x%x, dev_state = %u fw status = %s\n", 525 - fw_pm_event, dev->saved_dev_state, fw_sts_str); 526 - 527 - end: 528 - if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) 529 - dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DONE; 530 - dev->saved_fw_status_flag = false; 531 - } 532 - 533 - /** 534 497 * mei_me_hw_start - hw start routine 535 498 * 536 499 * @dev: mei device ··· 503 540 { 504 541 int ret = mei_me_hw_ready_wait(dev); 505 542 506 - if (kind_is_gsc(dev) || kind_is_gscfi(dev)) 507 - mei_me_check_fw_reset(dev); 543 + if ((kind_is_gsc(dev) || kind_is_gscfi(dev)) && 544 + dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) 545 + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DONE; 508 546 if (ret) 509 547 return ret; 510 548 dev_dbg(&dev->dev, "hw is ready\n"); ··· 1337 1373 /* check if we need to start the dev */ 1338 1374 if (!mei_host_is_ready(dev)) { 1339 1375 if (mei_hw_is_ready(dev)) { 1340 - dev_dbg(&dev->dev, "we need to start the dev.\n"); 1341 - dev->recvd_hw_ready = true; 1342 - wake_up(&dev->wait_hw_ready); 1376 + /* synchronized by dev mutex */ 1377 + if (waitqueue_active(&dev->wait_hw_ready)) { 1378 + dev_dbg(&dev->dev, "we need to start the dev.\n"); 1379 + dev->recvd_hw_ready = true; 1380 + wake_up(&dev->wait_hw_ready); 1381 + } else if (dev->dev_state != MEI_DEV_UNINITIALIZED && 1382 + dev->dev_state != MEI_DEV_POWERING_DOWN && 1383 + dev->dev_state != MEI_DEV_POWER_DOWN) { 1384 + dev_dbg(&dev->dev, "Force link reset.\n"); 1385 + schedule_work(&dev->reset_work); 1386 + } else { 1387 + dev_dbg(&dev->dev, "Ignore this interrupt in state = %d\n", 1388 + dev->dev_state); 1389 + } 1343 1390 } else { 1344 1391 dev_dbg(&dev->dev, "Spurious Interrupt\n"); 1345 1392 }
+2
drivers/misc/mei/hw.h
··· 27 27 #define MKHI_RCV_TIMEOUT 500 /* receive timeout in msec */ 28 28 #define MKHI_RCV_TIMEOUT_SLOW 10000 /* receive timeout in msec, slow FW */ 29 29 30 + #define MEI_LINK_RESET_WAIT_TIMEOUT_MSEC 500 /* Max wait timeout for link reset, in msec */ 31 + 30 32 /* 31 33 * FW page size for DMA allocations 32 34 */
+3 -18
drivers/misc/mei/init.c
··· 89 89 } 90 90 EXPORT_SYMBOL_GPL(mei_cancel_work); 91 91 92 - static void mei_save_fw_status(struct mei_device *dev) 93 - { 94 - struct mei_fw_status fw_status; 95 - int ret; 96 - 97 - ret = mei_fw_status(dev, &fw_status); 98 - if (ret) { 99 - dev_err(&dev->dev, "failed to read firmware status: %d\n", ret); 100 - return; 101 - } 102 - 103 - dev->saved_dev_state = dev->dev_state; 104 - dev->saved_fw_status_flag = true; 105 - memcpy(&dev->saved_fw_status, &fw_status, sizeof(fw_status)); 106 - } 107 - 108 92 /** 109 93 * mei_reset - resets host and fw. 110 94 * ··· 112 128 if (kind_is_gsc(dev) || kind_is_gscfi(dev)) { 113 129 dev_dbg(&dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", 114 130 mei_dev_state_str(state), fw_sts_str); 115 - mei_save_fw_status(dev); 116 131 } else { 117 132 dev_warn(&dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", 118 133 mei_dev_state_str(state), fw_sts_str); ··· 382 399 init_waitqueue_head(&dev->wait_hw_ready); 383 400 init_waitqueue_head(&dev->wait_pg); 384 401 init_waitqueue_head(&dev->wait_hbm_start); 385 - dev->dev_state = MEI_DEV_INITIALIZING; 402 + dev->dev_state = MEI_DEV_UNINITIALIZED; 403 + init_waitqueue_head(&dev->wait_dev_state); 386 404 dev->reset_count = 0; 387 405 388 406 INIT_LIST_HEAD(&dev->write_list); ··· 426 442 dev->timeouts.hbm = mei_secs_to_jiffies(MEI_HBM_TIMEOUT); 427 443 dev->timeouts.mkhi_recv = msecs_to_jiffies(MKHI_RCV_TIMEOUT); 428 444 } 445 + dev->timeouts.link_reset_wait = msecs_to_jiffies(MEI_LINK_RESET_WAIT_TIMEOUT_MSEC); 429 446 } 430 447 EXPORT_SYMBOL_GPL(mei_device_init);
+34 -9
drivers/misc/mei/main.c
··· 423 423 cl->state != MEI_FILE_DISCONNECTED) 424 424 return -EBUSY; 425 425 426 + retry: 426 427 /* find ME client we're trying to connect to */ 427 428 me_cl = mei_me_cl_by_uuid(dev, in_client_uuid); 428 429 if (!me_cl) { ··· 454 453 cl_dbg(dev, cl, "Can connect?\n"); 455 454 456 455 rets = mei_cl_connect(cl, me_cl, file); 456 + 457 + if (rets && cl->status == -EFAULT && 458 + (dev->dev_state == MEI_DEV_RESETTING || 459 + dev->dev_state == MEI_DEV_INIT_CLIENTS)) { 460 + /* in link reset, wait for it completion */ 461 + mutex_unlock(&dev->device_lock); 462 + rets = wait_event_interruptible_timeout(dev->wait_dev_state, 463 + dev->dev_state == MEI_DEV_ENABLED, 464 + dev->timeouts.link_reset_wait); 465 + mutex_lock(&dev->device_lock); 466 + if (rets < 0) { 467 + if (signal_pending(current)) 468 + rets = -EINTR; 469 + goto end; 470 + } 471 + if (dev->dev_state != MEI_DEV_ENABLED) { 472 + rets = -ETIME; 473 + goto end; 474 + } 475 + mei_me_cl_put(me_cl); 476 + goto retry; 477 + } 457 478 458 479 end: 459 480 mei_me_cl_put(me_cl); ··· 669 646 struct mei_cl *cl = file->private_data; 670 647 struct mei_connect_client_data conn; 671 648 struct mei_connect_client_data_vtag conn_vtag; 672 - const uuid_le *cl_uuid; 649 + uuid_le cl_uuid; 673 650 struct mei_client *props; 674 651 u8 vtag; 675 652 u32 notify_get, notify_req; ··· 697 674 rets = -EFAULT; 698 675 goto out; 699 676 } 700 - cl_uuid = &conn.in_client_uuid; 677 + cl_uuid = conn.in_client_uuid; 701 678 props = &conn.out_client_properties; 702 679 vtag = 0; 703 680 704 - rets = mei_vt_support_check(dev, cl_uuid); 681 + rets = mei_vt_support_check(dev, &cl_uuid); 705 682 if (rets == -ENOTTY) 706 683 goto out; 707 684 if (!rets) 708 - rets = mei_ioctl_connect_vtag(file, cl_uuid, props, 685 + rets = mei_ioctl_connect_vtag(file, &cl_uuid, props, 709 686 vtag); 710 687 else 711 - rets = mei_ioctl_connect_client(file, cl_uuid, props); 688 + rets = mei_ioctl_connect_client(file, &cl_uuid, props); 712 689 if (rets) 713 690 goto out; 714 691 ··· 730 707 goto out; 731 708 } 732 709 733 - cl_uuid = &conn_vtag.connect.in_client_uuid; 710 + cl_uuid = conn_vtag.connect.in_client_uuid; 734 711 props = &conn_vtag.out_client_properties; 735 712 vtag = conn_vtag.connect.vtag; 736 713 737 - rets = mei_vt_support_check(dev, cl_uuid); 714 + rets = mei_vt_support_check(dev, &cl_uuid); 738 715 if (rets == -EOPNOTSUPP) 739 716 cl_dbg(dev, cl, "FW Client %pUl does not support vtags\n", 740 - cl_uuid); 717 + &cl_uuid); 741 718 if (rets) 742 719 goto out; 743 720 ··· 747 724 goto out; 748 725 } 749 726 750 - rets = mei_ioctl_connect_vtag(file, cl_uuid, props, vtag); 727 + rets = mei_ioctl_connect_vtag(file, &cl_uuid, props, vtag); 751 728 if (rets) 752 729 goto out; 753 730 ··· 1142 1119 return; 1143 1120 1144 1121 dev->dev_state = state; 1122 + 1123 + wake_up_interruptible_all(&dev->wait_dev_state); 1145 1124 1146 1125 if (!dev->cdev) 1147 1126 return;
+5 -7
drivers/misc/mei/mei_dev.h
··· 57 57 58 58 /* MEI device states */ 59 59 enum mei_dev_state { 60 - MEI_DEV_INITIALIZING = 0, 60 + MEI_DEV_UNINITIALIZED = 0, 61 + MEI_DEV_INITIALIZING, 61 62 MEI_DEV_INIT_CLIENTS, 62 63 MEI_DEV_ENABLED, 63 64 MEI_DEV_RESETTING, ··· 466 465 unsigned int d0i3; /* D0i3 set/unset max response time, in jiffies */ 467 466 unsigned long hbm; /* HBM operation timeout, in jiffies */ 468 467 unsigned long mkhi_recv; /* receive timeout, in jiffies */ 468 + unsigned long link_reset_wait; /* link reset wait timeout, in jiffies */ 469 469 }; 470 470 471 471 /** ··· 497 495 * 498 496 * @reset_count : number of consecutive resets 499 497 * @dev_state : device state 498 + * @wait_dev_state: wait queue for device state change 500 499 * @hbm_state : state of host bus message protocol 501 500 * @pxp_mode : PXP device mode 502 501 * @init_clients_timer : HBM init handshake timeout ··· 551 548 * 552 549 * @dbgfs_dir : debugfs mei root directory 553 550 * 554 - * @saved_fw_status : saved firmware status 555 - * @saved_dev_state : saved device state 556 - * @saved_fw_status_flag : flag indicating that firmware status was saved 557 551 * @gsc_reset_to_pxp : state of reset to the PXP mode 558 552 * 559 553 * @ops: : hw specific operations ··· 587 587 */ 588 588 unsigned long reset_count; 589 589 enum mei_dev_state dev_state; 590 + wait_queue_head_t wait_dev_state; 590 591 enum mei_hbm_state hbm_state; 591 592 enum mei_dev_pxp_mode pxp_mode; 592 593 u16 init_clients_timer; ··· 651 650 struct dentry *dbgfs_dir; 652 651 #endif /* CONFIG_DEBUG_FS */ 653 652 654 - struct mei_fw_status saved_fw_status; 655 - enum mei_dev_state saved_dev_state; 656 - bool saved_fw_status_flag; 657 653 enum mei_dev_reset_to_pxp gsc_reset_to_pxp; 658 654 659 655 const struct mei_hw_ops *ops;