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

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "scsi: ufs: ufs-pci: Fix hibernate state transition for Intel MTL-like host controllers"

Adrian Hunter <adrian.hunter@intel.com> says:

Hi

Here is V2 of a couple of fixes for Intel MTL-like UFS host controllers,
related to link Hibernation state.

Following the fixes are some improvements for the enabling and disabling
of UIC Completion interrupts.

Link: https://lore.kernel.org/r/20250723165856.145750-1-adrian.hunter@intel.com

Conflicts:
drivers/ufs/core/ufshcd.c

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+49 -79
+40 -55
drivers/ufs/core/ufshcd.c
··· 364 364 } 365 365 EXPORT_SYMBOL_GPL(ufshcd_disable_irq); 366 366 367 + /** 368 + * ufshcd_enable_intr - enable interrupts 369 + * @hba: per adapter instance 370 + * @intrs: interrupt bits 371 + */ 372 + static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs) 373 + { 374 + u32 old_val = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 375 + u32 new_val = old_val | intrs; 376 + 377 + if (new_val != old_val) 378 + ufshcd_writel(hba, new_val, REG_INTERRUPT_ENABLE); 379 + } 380 + 381 + /** 382 + * ufshcd_disable_intr - disable interrupts 383 + * @hba: per adapter instance 384 + * @intrs: interrupt bits 385 + */ 386 + static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs) 387 + { 388 + u32 old_val = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 389 + u32 new_val = old_val & ~intrs; 390 + 391 + if (new_val != old_val) 392 + ufshcd_writel(hba, new_val, REG_INTERRUPT_ENABLE); 393 + } 394 + 367 395 static void ufshcd_configure_wb(struct ufs_hba *hba) 368 396 { 369 397 if (!ufshcd_is_wb_allowed(hba)) ··· 2624 2596 */ 2625 2597 int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) 2626 2598 { 2599 + unsigned long flags; 2627 2600 int ret; 2628 2601 2629 2602 if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD) ··· 2633 2604 ufshcd_hold(hba); 2634 2605 mutex_lock(&hba->uic_cmd_mutex); 2635 2606 ufshcd_add_delay_before_dme_cmd(hba); 2607 + 2608 + spin_lock_irqsave(hba->host->host_lock, flags); 2609 + ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); 2610 + spin_unlock_irqrestore(hba->host->host_lock, flags); 2636 2611 2637 2612 ret = __ufshcd_send_uic_cmd(hba, uic_cmd); 2638 2613 if (!ret) ··· 2712 2679 ufshcd_sgl_to_prdt(hba, lrbp, sg_segments, scsi_sglist(cmd)); 2713 2680 2714 2681 return ufshcd_crypto_fill_prdt(hba, lrbp); 2715 - } 2716 - 2717 - /** 2718 - * ufshcd_enable_intr - enable interrupts 2719 - * @hba: per adapter instance 2720 - * @intrs: interrupt bits 2721 - */ 2722 - static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs) 2723 - { 2724 - u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 2725 - 2726 - set |= intrs; 2727 - ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); 2728 - } 2729 - 2730 - /** 2731 - * ufshcd_disable_intr - disable interrupts 2732 - * @hba: per adapter instance 2733 - * @intrs: interrupt bits 2734 - */ 2735 - static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs) 2736 - { 2737 - u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 2738 - 2739 - set &= ~intrs; 2740 - ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); 2741 2682 } 2742 2683 2743 2684 /** ··· 4325 4318 unsigned long flags; 4326 4319 u8 status; 4327 4320 int ret; 4328 - bool reenable_intr = false; 4329 4321 4330 4322 mutex_lock(&hba->uic_cmd_mutex); 4331 4323 ufshcd_add_delay_before_dme_cmd(hba); ··· 4335 4329 goto out_unlock; 4336 4330 } 4337 4331 hba->uic_async_done = &uic_async_done; 4338 - if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) { 4339 - ufshcd_disable_intr(hba, UIC_COMMAND_COMPL); 4340 - /* 4341 - * Make sure UIC command completion interrupt is disabled before 4342 - * issuing UIC command. 4343 - */ 4344 - ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 4345 - reenable_intr = true; 4346 - } 4332 + ufshcd_disable_intr(hba, UIC_COMMAND_COMPL); 4347 4333 spin_unlock_irqrestore(hba->host->host_lock, flags); 4348 4334 ret = __ufshcd_send_uic_cmd(hba, cmd); 4349 4335 if (ret) { ··· 4379 4381 spin_lock_irqsave(hba->host->host_lock, flags); 4380 4382 hba->active_uic_cmd = NULL; 4381 4383 hba->uic_async_done = NULL; 4382 - if (reenable_intr) 4383 - ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); 4384 4384 if (ret && !hba->pm_op_in_progress) { 4385 4385 ufshcd_set_link_broken(hba); 4386 4386 ufshcd_schedule_eh_work(hba); ··· 4409 4413 { 4410 4414 int ret; 4411 4415 4416 + if (uic_cmd->argument1 != UIC_ARG_MIB(PA_PWRMODE) || 4417 + uic_cmd->command != UIC_CMD_DME_SET) 4418 + return ufshcd_send_uic_cmd(hba, uic_cmd); 4419 + 4412 4420 if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD) 4413 4421 return 0; 4414 4422 4415 4423 ufshcd_hold(hba); 4416 - 4417 - if (uic_cmd->argument1 == UIC_ARG_MIB(PA_PWRMODE) && 4418 - uic_cmd->command == UIC_CMD_DME_SET) { 4419 - ret = ufshcd_uic_pwr_ctrl(hba, uic_cmd); 4420 - goto out; 4421 - } 4422 - 4423 - mutex_lock(&hba->uic_cmd_mutex); 4424 - ufshcd_add_delay_before_dme_cmd(hba); 4425 - 4426 - ret = __ufshcd_send_uic_cmd(hba, uic_cmd); 4427 - if (!ret) 4428 - ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd); 4429 - 4430 - mutex_unlock(&hba->uic_cmd_mutex); 4431 - 4432 - out: 4424 + ret = ufshcd_uic_pwr_ctrl(hba, uic_cmd); 4433 4425 ufshcd_release(hba); 4426 + 4434 4427 return ret; 4435 4428 } 4436 4429
+9 -24
drivers/ufs/host/ufshcd-pci.c
··· 22 22 23 23 #define MAX_SUPP_MAC 64 24 24 25 - struct ufs_host { 26 - void (*late_init)(struct ufs_hba *hba); 27 - }; 28 - 29 25 enum intel_ufs_dsm_func_id { 30 26 INTEL_DSM_FNS = 0, 31 27 INTEL_DSM_RESET = 1, 32 28 }; 33 29 34 30 struct intel_host { 35 - struct ufs_host ufs_host; 36 31 u32 dsm_fns; 37 32 u32 active_ltr; 38 33 u32 idle_ltr; ··· 403 408 return ufs_intel_common_init(hba); 404 409 } 405 410 406 - static void ufs_intel_lkf_late_init(struct ufs_hba *hba) 411 + static int ufs_intel_lkf_init(struct ufs_hba *hba) 407 412 { 413 + int err; 414 + 415 + hba->nop_out_timeout = 200; 416 + hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; 417 + hba->caps |= UFSHCD_CAP_CRYPTO; 418 + err = ufs_intel_common_init(hba); 408 419 /* LKF always needs a full reset, so set PM accordingly */ 409 420 if (hba->caps & UFSHCD_CAP_DEEPSLEEP) { 410 421 hba->spm_lvl = UFS_PM_LVL_6; ··· 419 418 hba->spm_lvl = UFS_PM_LVL_5; 420 419 hba->rpm_lvl = UFS_PM_LVL_5; 421 420 } 422 - } 423 - 424 - static int ufs_intel_lkf_init(struct ufs_hba *hba) 425 - { 426 - struct ufs_host *ufs_host; 427 - int err; 428 - 429 - hba->nop_out_timeout = 200; 430 - hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; 431 - hba->caps |= UFSHCD_CAP_CRYPTO; 432 - err = ufs_intel_common_init(hba); 433 - ufs_host = ufshcd_get_variant(hba); 434 - ufs_host->late_init = ufs_intel_lkf_late_init; 435 421 return err; 436 422 } 437 423 ··· 432 444 433 445 static int ufs_intel_mtl_init(struct ufs_hba *hba) 434 446 { 447 + hba->rpm_lvl = UFS_PM_LVL_2; 448 + hba->spm_lvl = UFS_PM_LVL_2; 435 449 hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN; 436 450 return ufs_intel_common_init(hba); 437 451 } ··· 564 574 static int 565 575 ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 566 576 { 567 - struct ufs_host *ufs_host; 568 577 struct ufs_hba *hba; 569 578 void __iomem *mmio_base; 570 579 int err; ··· 595 606 dev_err(&pdev->dev, "Initialization failed\n"); 596 607 return err; 597 608 } 598 - 599 - ufs_host = ufshcd_get_variant(hba); 600 - if (ufs_host && ufs_host->late_init) 601 - ufs_host->late_init(hba); 602 609 603 610 pm_runtime_put_noidle(&pdev->dev); 604 611 pm_runtime_allow(&pdev->dev);