scsi: Add SHT->unlocked_qcmd for host_lock less SHT->queuecommand() dispatch
Subsystems (2)
RFC v4 1/19 scsi: Add SHT->unlocked_qcmd for host_lock less SHT->queuecommand() dispatch
From: Nicholas Bellinger <[email protected]>
This patch adds scsi_dispatch_cmd_unlocked() and scsi_dispatch_cmd_locked() which are now called directly from scsi_dispatch_cmd() depending upon what is reported by SHT->unlocked_qcmd on a per driver basis. Note that by default unlocked_qcmd is disabled, and all LLDs not defining a SHT->unlocked_qcmd will be using the legacy scsi_dispatch_cmd_locked().
This patch also drops the usage of scsi_cmd_get_serial() in scsi_dispatch_cmd() and assumes the legacy SCSI LLDs that depend upon struct scsi_cmnd->serial_number will call the now EXPORT_SYMBOL()'ed scsi_cmd_get_serial() call.
This patch also adds a Jen's recommended blk_test_rq_complete(), which is used by scsi_error.c:scsi_try_to_abort_cmd() here:
if (blk_test_rq_complete(scmd->request))
return SUCCESS;instead of checking for the legacy (scmd->serial_number == 0).
Finally, this patch also converts the remaining struct Scsi_Host->cmd_serial_number to atomic_t following a recommedation by Joe Eykholt to start struct Scsi_Host-> cmd_serial_number at 1, and increment each serial_number by 2 so that the serial is odd, and wraps to 1 instead of 0. struct Scsi_Host->cmd_serial_number is initialized to '1' in drivers/scsi/hosts.c:scsi_host_alloc().
Many thanks to Vasu Dev, Tim Chen, Mike Christie, Joe Eykholt, Mike Anderson, Christof Schmitt, Brian King and Jens Axboe for their help with this series!
--- block/blk.h | 4 ++ drivers/scsi/hosts.c | 5 +++ drivers/scsi/scsi.c | 89 ++++++++++++++++++++++++++++++++++----------- drivers/scsi/scsi_error.c | 10 ++++-- include/scsi/scsi_cmnd.h | 1 + include/scsi/scsi_host.h | 16 +++++++-- 6 files changed, 98 insertions(+), 27 deletions(-)
block/blk.h +4 -0
@@ -46,6 +46,10 @@ static inline void blk_clear_rq_complete(struct request *rq)clear_bit (REQ_ATOM_COMPLETE , &rq->atomic_flags); } +static inline int blk_test_rq_complete (struct request *rq) +{ +return test_bit (REQ_ATOM_COMPLETE , &rq->atomic_flags); +}/* * Internal elevator interface */
drivers/scsi/hosts.c +5 -0
@@ -380,6 +380,11 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; + shost->unlocked_qcmd = sht->unlocked_qcmd; +/* +* Set the default shost->cmd_serial_number to 1. +*/ +atomic_set (&shost->cmd_serial_number,1 );if (sht->supported_mode ==MODE_UNKNOWN )/* means we didn't set it ... default to INITIATOR */
drivers/scsi/scsi.c +68 -21
116 lines not on this page · raw message
drivers/scsi/scsi_error.c +7 -3
@@ -39,6 +39,8 @@#include "scsi_logging.h" #include "scsi_transport_api.h" +#include <../block/blk.h> /* For REQ_ATOM_COMPLETE */ +#include <trace/events/scsi.h> #define SENSE_TIMEOUT (10*HZ)
@@ -645,11 +647,13 @@ static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)static int scsi_try_to_abort_cmd (struct scsi_cmnd *scmd) {/* -* scsi_done was called just after the command timed out and before -* we had a chance to process it. (db) +* Use the struct request atomic_flags here to check if +* block/blk.h:blk_mark_rq_complete() has already been called +* from the block softirq */ -if (scmd->serial_number ==0 ) +if (blk_test_rq_complete (scmd->request))return SUCCESS ; +return __scsi_try_to_abort_cmd (scmd); }
include/scsi/scsi_cmnd.h +1 -0
@@ -136,6 +136,7 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t);extern void scsi_put_command (struct scsi_cmnd *);extern void __scsi_put_command (struct Scsi_Host *,struct scsi_cmnd *,struct device *); +extern void scsi_cmd_get_serial (struct scsi_cmnd *);extern void scsi_finish_command (struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
include/scsi/scsi_host.h +13 -3
@@ -460,6 +460,12 @@ struct scsi_host_template {*/ unsigned ordered_tag:1; +/* +* True if the LLD allows for unlocked struct Scsi_Host->host_lock +* SHT->queuecommand() calls to increase performance. +*/ + unsigned unlocked_qcmd:1; +/* * Countdown for host blocking with no commands outstanding. */
@@ -602,10 +608,9 @@ struct Scsi_Host {short unsigned int max_sectors;unsigned long dma_boundary;/* -* Used to assign serial numbers to the cmds. -* Protected by the host lock. +* Used to assign serial numbers to the cmds in scsi_cmd_get_serial() */ -unsigned long cmd_serial_number; +atomic_t cmd_serial_number; unsigned active_mode:2; unsigned unchecked_isa_dma:1;
@@ -630,6 +635,11 @@ struct Scsi_Host {*/ unsigned ordered_tag:1; +/* +* Unlocked scsi_dispatch_cmd() -> SHT->queuecommand() support +*/ + unsigned unlocked_qcmd:1; +/* Task mgmt function in progress */ unsigned tmf_in_progress:1;
Signature · 1 line
1.7.3