Patch "scsi: mpt3sas: Avoid sleeping in interrupt context" has been added to the 4.10-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
scsi: mpt3sas: Avoid sleeping in interrupt context
to the 4.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
scsi-mpt3sas-avoid-sleeping-in-interrupt-context.patch
and it can be found in the queue-4.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
8893cf6cb1cf56334c05120e23092dbfc9423ebbMon Sep 17 00:00:00 2001
From: Bart Van Assche <[email protected]>
Date: Wed, 1 Mar 2017 09:00:36 -0800
Subject: scsi: mpt3sas: Avoid sleeping in interrupt context
From: Bart Van Assche <[email protected]>
commit 8893cf6cb1cf56334c05120e23092dbfc9423ebb upstream.
Commit 669f044170d8 ("scsi: srp_transport: Move queuecommand() wait code to SCSI core") can make scsi_internal_device_block() sleep. However, the mpt3sas driver can call this function from an interrupt handler. Hence add a second argument to scsi_internal_device_block() that restores the old behavior of this function for the mpt3sas handler.
The call chain that triggered an "IRQ handler enabled interrupts" complaint is as follows:
_base_interrupt()
-> _base_async_event()
-> mpt3sas_scsih_event_callback()
-> _scsih_check_topo_delete_events()
-> _scsih_block_io_to_children_attached_directly()
-> _scsih_block_io_device()
-> _scsih_internal_device_block()
-> scsi_internal_device_block()--- drivers/scsi/mpt3sas/mpt3sas_base.h | 3 --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 ++-- drivers/scsi/scsi_lib.c | 14 ++++++++++---- drivers/scsi/scsi_priv.h | 3 --- include/scsi/scsi_device.h | 4 ++++ 5 files changed, 16 insertions(+), 12 deletions(-)
drivers/scsi/mpt3sas/mpt3sas_base.h +0 -3
@@ -1443,9 +1443,6 @@ void mpt3sas_transport_update_links(stru u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);extern struct sas_function_template mpt3sas_transport_functions;extern struct scsi_transport_template *mpt3sas_transport_template; -extern int scsi_internal_device_block (struct scsi_device *sdev); -extern int scsi_internal_device_unblock (struct scsi_device *sdev, -enum scsi_device_state new_state);/* trigger data externs */ void mpt3sas_send_trigger_data_event (struct MPT3SAS_ADAPTER *ioc,struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
drivers/scsi/mpt3sas/mpt3sas_scsih.c +2 -2
@@ -2840,7 +2840,7 @@ _scsih_internal_device_block(struct scsi sas_device_priv_data->sas_target->handle); sas_device_priv_data->block =1 ; - r =scsi_internal_device_block (sdev); + r =scsi_internal_device_block (sdev, false);if (r == -EINVAL ) sdev_printk(KERN_WARNING, sdev, "device_block failed with return(%d) for handle(0x%04x)\n",
@@ -2876,7 +2876,7 @@ _scsih_internal_device_unblock(struct sc"performing a block followed by an unblock\n" , r, sas_device_priv_data->sas_target->handle); sas_device_priv_data->block =1 ; - r =scsi_internal_device_block (sdev); + r =scsi_internal_device_block (sdev, false);if (r) sdev_printk(KERN_WARNING, sdev, "retried device_block " "failed with return(%d) for handle(0x%04x)\n",
drivers/scsi/scsi_lib.c +10 -4
@@ -2880,6 +2880,8 @@ EXPORT_SYMBOL(scsi_target_resume);/** * scsi_internal_device_block - internal function to put a device temporarily into the SDEV_BLOCK state * @sdev: device to block +* @wait: Whether or not to wait until ongoing .queuecommand() / +* .queue_rq() calls have finished. * * Block request made by scsi lld's to temporarily stop all * scsi commands on the specified device. May sleep.
@@ -2897,7 +2899,7 @@ EXPORT_SYMBOL(scsi_target_resume);* remove the rport mutex lock and unlock calls from srp_queuecommand(). */ int -scsi_internal_device_block (struct scsi_device *sdev) +scsi_internal_device_block (struct scsi_device *sdev,bool wait) {struct request_queue *q = sdev->request_queue;unsigned long flags;
@@ -2917,12 +2919,16 @@ scsi_internal_device_block(struct scsi_d* request queue. */ if (q->mq_ops) { -blk_mq_quiesce_queue (q); +if (wait) +blk_mq_quiesce_queue (q); +else +blk_mq_stop_hw_queues (q); }else {spin_lock_irqsave (q->queue_lock, flags);blk_stop_queue (q);spin_unlock_irqrestore (q->queue_lock, flags); -scsi_wait_for_queuecommand (sdev); +if (wait) +scsi_wait_for_queuecommand (sdev); }return 0 ;
@@ -2984,7 +2990,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_ustatic void device_block (struct scsi_device *sdev,void *data) { -scsi_internal_device_block (sdev); +scsi_internal_device_block (sdev, true); } static int
drivers/scsi/scsi_priv.h +0 -3
@@ -189,8 +189,5 @@ static inline void scsi_dh_remove_device*/ #define SCSI_DEVICE_BLOCK_MAX_TIMEOUT 600/* units in seconds */ -extern int scsi_internal_device_block (struct scsi_device *sdev); -extern int scsi_internal_device_unblock (struct scsi_device *sdev, -enum scsi_device_state new_state);#endif /* _SCSI_PRIV_H */
include/scsi/scsi_device.h +4 -0
@@ -475,6 +475,10 @@ static inline int scsi_device_created(st sdev->sdev_state ==SDEV_CREATED_BLOCK ; } +int scsi_internal_device_block (struct scsi_device *sdev,bool wait); +int scsi_internal_device_unblock (struct scsi_device *sdev, +enum scsi_device_state new_state); +/* accessor functions for the SCSI parameters */ static inline int scsi_device_sync (struct scsi_device *sdev) {
Patches currently in stable-queue which might be from [email protected] are
queue-4.10/scsi-mpt3sas-avoid-sleeping-in-interrupt-context.patch