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
This commit is contained in:
Emmanuel Vadot committed 2026-11-05 15:50:51 +01:00
1 parent 3e9ff26d2a
commit bbb90912eb
1 file changed
+4 -9
+4 -9
View File
@@ -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");