diff options
author | Bart Van Assche <bart.vanassche@wdc.com> | 2018-01-05 12:19:09 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-01-09 19:10:20 -0500 |
commit | 203f8c250e2195371d418b1e8466e4caf1a0ed51 (patch) | |
tree | 4a9b736baad695ac73ebaa50e0efef6205f8f59d | |
parent | 4bf236a3330e97d275e5848420f7e31948fef07a (diff) |
block, scsi: Fix race between SPI domain validation and system suspend
Avoid that the following warning is reported when suspending a system
that is using the mptspi driver:
WARNING: CPU: 0 PID: 4187 at drivers/scsi/scsi_lib.c:2960 scsi_device_quiesce+0x20/0xb0
EIP: scsi_device_quiesce+0x20/0xb0
Call Trace:
spi_dv_device+0x65/0x5f0 [scsi_transport_spi]
mptspi_dv_device+0x4d/0x170 [mptspi]
mptspi_dv_renegotiate_work+0x49/0xc0 [mptspi]
process_one_work+0x190/0x2e0
worker_thread+0x37/0x3f0
kthread+0xcb/0x100
ret_from_fork+0x19/0x24
Fixes: 3a0a529971ec (block, scsi: Make SCSI quiesce and resume work reliably)
Reported-by: Woody Suwalski <terraluna977@gmail.com>
Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
[ rjw : Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 10ebb213ddb3..871ea582029e 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/sysfs.h> | 27 | #include <linux/sysfs.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/suspend.h> | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include "scsi_priv.h" | 31 | #include "scsi_priv.h" |
31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
@@ -1009,11 +1010,20 @@ spi_dv_device(struct scsi_device *sdev) | |||
1009 | u8 *buffer; | 1010 | u8 *buffer; |
1010 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; | 1011 | const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; |
1011 | 1012 | ||
1013 | /* | ||
1014 | * Because this function and the power management code both call | ||
1015 | * scsi_device_quiesce(), it is not safe to perform domain validation | ||
1016 | * while suspend or resume is in progress. Hence the | ||
1017 | * lock/unlock_system_sleep() calls. | ||
1018 | */ | ||
1019 | lock_system_sleep(); | ||
1020 | |||
1012 | if (unlikely(spi_dv_in_progress(starget))) | 1021 | if (unlikely(spi_dv_in_progress(starget))) |
1013 | return; | 1022 | goto unlock; |
1014 | 1023 | ||
1015 | if (unlikely(scsi_device_get(sdev))) | 1024 | if (unlikely(scsi_device_get(sdev))) |
1016 | return; | 1025 | goto unlock; |
1026 | |||
1017 | spi_dv_in_progress(starget) = 1; | 1027 | spi_dv_in_progress(starget) = 1; |
1018 | 1028 | ||
1019 | buffer = kzalloc(len, GFP_KERNEL); | 1029 | buffer = kzalloc(len, GFP_KERNEL); |
@@ -1049,6 +1059,8 @@ spi_dv_device(struct scsi_device *sdev) | |||
1049 | out_put: | 1059 | out_put: |
1050 | spi_dv_in_progress(starget) = 0; | 1060 | spi_dv_in_progress(starget) = 0; |
1051 | scsi_device_put(sdev); | 1061 | scsi_device_put(sdev); |
1062 | unlock: | ||
1063 | unlock_system_sleep(); | ||
1052 | } | 1064 | } |
1053 | EXPORT_SYMBOL(spi_dv_device); | 1065 | EXPORT_SYMBOL(spi_dv_device); |
1054 | 1066 | ||