From bbb90912eb3260260ad5cb3fc2f4c5ad4c144d7e Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Tue, 27 Oct 2026 19:12:53 +0100 Subject: [PATCH] sdhci: Defer XPT_SET_TRAN_SETTINGS to the slot taskqueue Only XPT_MMC_SET_TRAN_SETTINGS was handed to the slot taskqueue. XPT_SET_TRAN_SETTINGS, which mmc_xpt.c issues too, still called sdhci_cam_settran_settings() directly from the CAM done thread with the CAM device lock held. Changing the bus clock can sleep (clk_set_freq() takes the clock topology sx lock), which panics with "sleeping thread holds CAM device lock". Handle both opcodes the same way and complete the request from the taskqueue. Differential Revision: https://reviews.freebsd.org/D61013 --- sys/dev/sdhci/sdhci.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 5e2e868ccd7a..4de70fcd1393 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -2784,9 +2784,12 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.status = CAM_REQ_CMP; break; } + case XPT_SET_TRAN_SETTINGS: case XPT_MMC_SET_TRAN_SETTINGS: if (sdhci_debug > 1) - slot_printf(slot, "Got XPT_MMC_SET_TRAN_SETTINGS\n"); + slot_printf(slot, "Got XPT_%sSET_TRAN_SETTINGS\n", + ccb->ccb_h.func_code == XPT_MMC_SET_TRAN_SETTINGS ? + "MMC_" : ""); if (slot->settran_ccb != NULL) { ccb->ccb_h.status = CAM_BUSY; break; @@ -2796,14 +2799,6 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb) slot->settran_ccb = ccb; taskqueue_enqueue(slot->tq, &slot->settran_task); return; - case XPT_SET_TRAN_SETTINGS: - if (sdhci_debug > 1) - slot_printf(slot, "Got XPT_SET_TRAN_SETTINGS\n"); - if (sdhci_cam_settran_settings(slot, ccb) != 0) - ccb->ccb_h.status = CAM_REQ_INVALID; - else - ccb->ccb_h.status = CAM_REQ_CMP; - break; case XPT_RESET_BUS: if (sdhci_debug > 1) slot_printf(slot, "Got XPT_RESET_BUS, ACK it...\n");