linux/drivers/scsi
Johan Hovold b03f7ed9af scsi: ufs: core: Fix devfreq deadlocks
[ Upstream commit ba81043753 ]

There is a lock inversion and rwsem read-lock recursion in the devfreq
target callback which can lead to deadlocks.

Specifically, ufshcd_devfreq_scale() already holds a clk_scaling_lock
read lock when toggling the write booster, which involves taking the
dev_cmd mutex before taking another clk_scaling_lock read lock.

This can lead to a deadlock if another thread:

  1) tries to acquire the dev_cmd and clk_scaling locks in the correct
     order, or

  2) takes a clk_scaling write lock before the attempt to take the
     clk_scaling read lock a second time.

Fix this by dropping the clk_scaling_lock before toggling the write booster
as was done before commit 0e9d4ca43b ("scsi: ufs: Protect some contexts
from unexpected clock scaling").

While the devfreq callbacks are already serialised, add a second
serialising mutex to handle the unlikely case where a callback triggered
through the devfreq sysfs interface is racing with a request to disable
clock scaling through the UFS controller 'clkscale_enable' sysfs
attribute. This could otherwise lead to the write booster being left
disabled after having disabled clock scaling.

Also take the new mutex in ufshcd_clk_scaling_allow() to make sure that any
pending write booster update has completed on return.

Note that this currently only affects Qualcomm platforms since commit
87bd05016a ("scsi: ufs: core: Allow host driver to disable wb toggling
during clock scaling").

The lock inversion (i.e. 1 above) was reported by lockdep as:

 ======================================================
 WARNING: possible circular locking dependency detected
 6.1.0-next-20221216 #211 Not tainted
 ------------------------------------------------------
 kworker/u16:2/71 is trying to acquire lock:
 ffff076280ba98a0 (&hba->dev_cmd.lock){+.+.}-{3:3}, at: ufshcd_query_flag+0x50/0x1c0

 but task is already holding lock:
 ffff076280ba9cf0 (&hba->clk_scaling_lock){++++}-{3:3}, at: ufshcd_devfreq_scale+0x2b8/0x380

 which lock already depends on the new lock.
[  +0.011606]
 the existing dependency chain (in reverse order) is:

 -> #1 (&hba->clk_scaling_lock){++++}-{3:3}:
        lock_acquire+0x68/0x90
        down_read+0x58/0x80
        ufshcd_exec_dev_cmd+0x70/0x2c0
        ufshcd_verify_dev_init+0x68/0x170
        ufshcd_probe_hba+0x398/0x1180
        ufshcd_async_scan+0x30/0x320
        async_run_entry_fn+0x34/0x150
        process_one_work+0x288/0x6c0
        worker_thread+0x74/0x450
        kthread+0x118/0x120
        ret_from_fork+0x10/0x20

 -> #0 (&hba->dev_cmd.lock){+.+.}-{3:3}:
        __lock_acquire+0x12a0/0x2240
        lock_acquire.part.0+0xcc/0x220
        lock_acquire+0x68/0x90
        __mutex_lock+0x98/0x430
        mutex_lock_nested+0x2c/0x40
        ufshcd_query_flag+0x50/0x1c0
        ufshcd_query_flag_retry+0x64/0x100
        ufshcd_wb_toggle+0x5c/0x120
        ufshcd_devfreq_scale+0x2c4/0x380
        ufshcd_devfreq_target+0xf4/0x230
        devfreq_set_target+0x84/0x2f0
        devfreq_update_target+0xc4/0xf0
        devfreq_monitor+0x38/0x1f0
        process_one_work+0x288/0x6c0
        worker_thread+0x74/0x450
        kthread+0x118/0x120
        ret_from_fork+0x10/0x20

 other info that might help us debug this:
  Possible unsafe locking scenario:
        CPU0                    CPU1
        ----                    ----
   lock(&hba->clk_scaling_lock);
                                lock(&hba->dev_cmd.lock);
                                lock(&hba->clk_scaling_lock);
   lock(&hba->dev_cmd.lock);

  *** DEADLOCK ***

Fixes: 0e9d4ca43b ("scsi: ufs: Protect some contexts from unexpected clock scaling")
Cc: stable@vger.kernel.org      # 5.12
Cc: Can Guo <quic_cang@quicinc.com>
Tested-by: Andrew Halaney <ahalaney@redhat.com>
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20230116161201.16923-1-johan+linaro@kernel.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-02-01 08:27:26 +01:00
..
aacraid
aic7xxx
aic94xx
arcmsr
arm
be2iscsi scsi: iscsi: Fix session removal on shutdown 2022-08-17 14:23:45 +02:00
bfa
bnx2fc
bnx2i scsi: iscsi: Fix session removal on shutdown 2022-08-17 14:23:45 +02:00
csiostor
cxgbi scsi: iscsi: Rename iscsi_conn_queue_work() 2022-10-26 12:35:15 +02:00
cxlflash
device_handler
dpt
elx scsi: elx: libefc: Fix second parameter type in state callbacks 2022-12-31 13:14:44 +01:00
esas2r
fcoe scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails 2022-12-31 13:14:25 +01:00
fnic
hisi_sas scsi: hisi_sas: Set a port invalid only if there are no devices attached when refreshing port id 2023-02-01 08:27:18 +01:00
ibmvscsi scsi: ibmvfc: Avoid path failures during live migration 2022-12-02 17:41:02 +01:00
ibmvscsi_tgt
isci
libfc
libsas scsi: libsas: Fix use-after-free bug in smp_execute_task_sg() 2022-10-26 12:35:15 +02:00
lpfc scsi: lpfc: Fix hard lockup when reading the rx_monitor from debugfs 2022-12-31 13:14:43 +01:00
megaraid scsi: megaraid_sas: Fix double kfree() 2022-09-15 11:30:00 +02:00
mpi3mr scsi: mpi3mr: Refer CONFIG_SCSI_MPI3MR in Makefile 2023-01-18 11:48:53 +01:00
mpt3sas scsi: mpt3sas: Remove scsi_dma_map() error messages 2023-01-18 11:48:58 +01:00
mvsas
pcmcia
pm8001 scsi: pm80xx: Enable upper inbound, outbound queues 2022-04-20 09:34:11 +02:00
qedf scsi: qedf: Populate sysfs attributes for vport 2022-10-26 12:34:26 +02:00
qedi scsi: iscsi: Fix session removal on shutdown 2022-08-17 14:23:45 +02:00
qla2xxx scsi: qla2xxx: Fix crash when I/O abort times out 2022-12-31 13:14:47 +01:00
qla4xxx
smartpqi scsi: smartpqi: Fix DMA direction for RAID requests 2022-08-17 14:23:51 +02:00
snic scsi: snic: Fix possible UAF in snic_tgt_create() 2022-12-31 13:14:25 +01:00
sym53c8xx_2
ufs scsi: ufs: core: Fix devfreq deadlocks 2023-02-01 08:27:26 +01:00
.gitignore
3w-9xxx.c scsi: 3w-9xxx: Avoid disabling device if failing to enable it 2022-10-26 12:35:46 +02:00
3w-9xxx.h
3w-sas.c
3w-sas.h
3w-xxxx.c
3w-xxxx.h
53c700.c
53c700.h
53c700.scr
53c700_d.h_shipped
BusLogic.c
BusLogic.h
FlashPoint.c
Kconfig
Makefile
NCR5380.c
NCR5380.h
a100u2w.c
a100u2w.h
a2091.c
a2091.h
a3000.c
a3000.h
a4000t.c
advansys.c
aha152x.c
aha152x.h
aha1542.c
aha1542.h
aha1740.c
aha1740.h
am53c974.c
atari_scsi.c
atp870u.c
atp870u.h
bvme6000_scsi.c
ch.c
constants.c
dc395x.c
dc395x.h
dmx3191d.c
dpt_i2o.c
dpti.h
esp_scsi.c
esp_scsi.h
fdomain.c
fdomain.h
fdomain_isa.c
fdomain_pci.c
g_NCR5380.c
gvp11.c
gvp11.h
hosts.c
hpsa.c scsi: hpsa: Fix allocation size for scsi_host_alloc() 2023-02-01 08:27:22 +01:00
hpsa.h
hpsa_cmd.h
hptiop.c
hptiop.h
imm.c
imm.h
initio.c
initio.h
ipr.c scsi: ipr: Fix WARNING in ipr_init() 2022-12-31 13:14:25 +01:00
ipr.h
ips.c
ips.h
iscsi_boot_sysfs.c
iscsi_tcp.c scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername() 2022-10-26 12:35:16 +02:00
iscsi_tcp.h scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername() 2022-10-26 12:35:16 +02:00
jazz_esp.c
lasi700.c
libiscsi.c scsi: iscsi: Add recv workqueue helpers 2022-10-26 12:35:15 +02:00
libiscsi_tcp.c
mac53c94.c
mac53c94.h
mac_esp.c
mac_scsi.c
megaraid.c
megaraid.h
mesh.c
mesh.h
mvme16x_scsi.c
mvme147.c
mvme147.h
mvumi.c
mvumi.h
myrb.c
myrb.h
myrs.c
myrs.h
ncr53c8xx.c
ncr53c8xx.h scsi: ncr53c8xx: Use SAM status values 2021-01-22 21:14:12 -05:00
nsp32.c
nsp32.h
nsp32_debug.c
nsp32_io.h
pmcraid.c
pmcraid.h
ppa.c
ppa.h
ps3rom.c
qla1280.c
qla1280.h
qlogicfas.c
qlogicfas408.c
qlogicfas408.h
qlogicpti.c
qlogicpti.h
raid_class.c
script_asm.pl
scsi.c
scsi.h
scsi_bsg.c
scsi_common.c
scsi_debug.c scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper() 2022-12-31 13:14:25 +01:00
scsi_debugfs.c
scsi_debugfs.h
scsi_devinfo.c
scsi_dh.c
scsi_error.c scsi: core: Fix a race between scsi_done() and scsi_timeout() 2022-12-31 13:14:21 +01:00
scsi_ioctl.c
scsi_lib.c
scsi_lib_dma.c
scsi_logging.c
scsi_logging.h
scsi_netlink.c
scsi_pm.c
scsi_priv.h
scsi_proc.c
scsi_sas_internal.h
scsi_scan.c
scsi_sysctl.c
scsi_sysfs.c scsi: core: Restrict legal sdev_state transitions via sysfs 2022-11-10 18:15:34 +01:00
scsi_trace.c
scsi_transport_api.h
scsi_transport_fc.c
scsi_transport_iscsi.c scsi: iscsi: Fix multiple iSCSI session unbind events sent to userspace 2023-02-01 08:27:16 +01:00
scsi_transport_sas.c scsi: scsi_transport_sas: Fix error handling in sas_phy_add() 2022-11-26 09:24:35 +01:00
scsi_transport_spi.c
scsi_transport_srp.c
scsicam.c
sd.c scsi: sd: Revert "scsi: sd: Remove a local variable" 2022-11-03 23:59:20 +09:00
sd.h
sd_dif.c
sd_zbc.c
sense_codes.h
ses.c
sg.c
sgiwd93.c
sim710.c
sni_53c710.c
sr.c scsi: sr: Fix typo in CDROM(CLOSETRAY|EJECT) handling 2022-04-13 20:59:15 +02:00
sr.h
sr_ioctl.c
sr_vendor.c
st.c
st.h
st_options.h
stex.c scsi: stex: Properly zero out the passthrough command structure 2022-10-15 07:59:01 +02:00
storvsc_drv.c scsi: storvsc: Fix handling of srb_status and capacity change events 2022-12-02 17:41:03 +01:00
sun3_scsi.c
sun3_scsi_vme.c
sun3x_esp.c
sun_esp.c
virtio_scsi.c
vmw_pvscsi.c
vmw_pvscsi.h
wd33c93.c
wd33c93.h
wd719x.c
wd719x.h
xen-scsifront.c
zalon.c
zorro7xx.c
zorro_esp.c