scsi: core: Only process PM requests if rpm_status != RPM_ACTIVE
Instead of submitting all SCSI commands submitted with scsi_execute() to a SCSI device if rpm_status != RPM_ACTIVE, only submit RQF_PM (power management requests) if rpm_status != RPM_ACTIVE. This patch makes the SCSI core handle the runtime power management status (rpm_status) as it should be handled. Link: https://lore.kernel.org/r/20201209052951.16136-7-bvanassche@acm.org Cc: Can Guo <cang@codeaurora.org> Cc: Stanley Chu <stanley.chu@mediatek.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Ming Lei <ming.lei@redhat.com> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: Martin Kepplinger <martin.kepplinger@puri.sm> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Jens Axboe <axboe@kernel.dk> Reviewed-by: Can Guo <cang@codeaurora.org> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
cfefd9f824
commit
e6044f714b
@ -249,7 +249,8 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
|
|||||||
|
|
||||||
req = blk_get_request(sdev->request_queue,
|
req = blk_get_request(sdev->request_queue,
|
||||||
data_direction == DMA_TO_DEVICE ?
|
data_direction == DMA_TO_DEVICE ?
|
||||||
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT);
|
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
|
||||||
|
rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
|
||||||
if (IS_ERR(req))
|
if (IS_ERR(req))
|
||||||
return ret;
|
return ret;
|
||||||
rq = scsi_req(req);
|
rq = scsi_req(req);
|
||||||
@ -1206,6 +1207,8 @@ static blk_status_t
|
|||||||
scsi_device_state_check(struct scsi_device *sdev, struct request *req)
|
scsi_device_state_check(struct scsi_device *sdev, struct request *req)
|
||||||
{
|
{
|
||||||
switch (sdev->sdev_state) {
|
switch (sdev->sdev_state) {
|
||||||
|
case SDEV_CREATED:
|
||||||
|
return BLK_STS_OK;
|
||||||
case SDEV_OFFLINE:
|
case SDEV_OFFLINE:
|
||||||
case SDEV_TRANSPORT_OFFLINE:
|
case SDEV_TRANSPORT_OFFLINE:
|
||||||
/*
|
/*
|
||||||
@ -1232,18 +1235,18 @@ scsi_device_state_check(struct scsi_device *sdev, struct request *req)
|
|||||||
return BLK_STS_RESOURCE;
|
return BLK_STS_RESOURCE;
|
||||||
case SDEV_QUIESCE:
|
case SDEV_QUIESCE:
|
||||||
/*
|
/*
|
||||||
* If the devices is blocked we defer normal commands.
|
* If the device is blocked we only accept power management
|
||||||
|
* commands.
|
||||||
*/
|
*/
|
||||||
if (req && !(req->rq_flags & RQF_PREEMPT))
|
if (req && WARN_ON_ONCE(!(req->rq_flags & RQF_PM)))
|
||||||
return BLK_STS_RESOURCE;
|
return BLK_STS_RESOURCE;
|
||||||
return BLK_STS_OK;
|
return BLK_STS_OK;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* For any other not fully online state we only allow
|
* For any other not fully online state we only allow
|
||||||
* special commands. In particular any user initiated
|
* power management commands.
|
||||||
* command is not allowed.
|
|
||||||
*/
|
*/
|
||||||
if (req && !(req->rq_flags & RQF_PREEMPT))
|
if (req && !(req->rq_flags & RQF_PM))
|
||||||
return BLK_STS_IOERR;
|
return BLK_STS_IOERR;
|
||||||
return BLK_STS_OK;
|
return BLK_STS_OK;
|
||||||
}
|
}
|
||||||
@ -2517,15 +2520,13 @@ void sdev_evt_send_simple(struct scsi_device *sdev,
|
|||||||
EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
|
EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scsi_device_quiesce - Block user issued commands.
|
* scsi_device_quiesce - Block all commands except power management.
|
||||||
* @sdev: scsi device to quiesce.
|
* @sdev: scsi device to quiesce.
|
||||||
*
|
*
|
||||||
* This works by trying to transition to the SDEV_QUIESCE state
|
* This works by trying to transition to the SDEV_QUIESCE state
|
||||||
* (which must be a legal transition). When the device is in this
|
* (which must be a legal transition). When the device is in this
|
||||||
* state, only special requests will be accepted, all others will
|
* state, only power management requests will be accepted, all others will
|
||||||
* be deferred. Since special requests may also be requeued requests,
|
* be deferred.
|
||||||
* a successful return doesn't guarantee the device will be
|
|
||||||
* totally quiescent.
|
|
||||||
*
|
*
|
||||||
* Must be called with user context, may sleep.
|
* Must be called with user context, may sleep.
|
||||||
*
|
*
|
||||||
@ -2587,12 +2588,12 @@ void scsi_device_resume(struct scsi_device *sdev)
|
|||||||
* device deleted during suspend)
|
* device deleted during suspend)
|
||||||
*/
|
*/
|
||||||
mutex_lock(&sdev->state_mutex);
|
mutex_lock(&sdev->state_mutex);
|
||||||
|
if (sdev->sdev_state == SDEV_QUIESCE)
|
||||||
|
scsi_device_set_state(sdev, SDEV_RUNNING);
|
||||||
if (sdev->quiesced_by) {
|
if (sdev->quiesced_by) {
|
||||||
sdev->quiesced_by = NULL;
|
sdev->quiesced_by = NULL;
|
||||||
blk_clear_pm_only(sdev->request_queue);
|
blk_clear_pm_only(sdev->request_queue);
|
||||||
}
|
}
|
||||||
if (sdev->sdev_state == SDEV_QUIESCE)
|
|
||||||
scsi_device_set_state(sdev, SDEV_RUNNING);
|
|
||||||
mutex_unlock(&sdev->state_mutex);
|
mutex_unlock(&sdev->state_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(scsi_device_resume);
|
EXPORT_SYMBOL(scsi_device_resume);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user