From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch converts struct Scsi_Host->cmd_serial_number to an atomic_t so that scsi_cmd_get_serial() can be safely called without struct Scsi_Host->host_lock in scsi_dispatch_cmd(). This patch also adds a struct Scsi_Host->use_serial_number to signal serial_number usage, but this is now disabled by default in scsi_host_alloc(). One special item in scsi_cmd_get_serial() recommended by Joe Eykholt is 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. Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/scsi/hosts.c | 4 ++++ drivers/scsi/scsi.c | 13 ++++++++++--- include/scsi/scsi_host.h | 8 +++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 8a8f803..aff1c9c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -380,6 +380,10 @@ 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; + /* + * 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 */ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ad0ed21..4724ce7 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -636,9 +636,16 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) */ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd) { - cmd->serial_number = host->cmd_serial_number++; - if (cmd->serial_number == 0) - cmd->serial_number = host->cmd_serial_number++; + /* + * The use of per struct scsi_cmnd->serial_number is disabled by default + */ + if (!(host->use_serial_number)) + return; + /* + * Increment the host->cmd_serial_number by 2 so cmd->serial_number + * is always odd and wraps to 1 instead of 0. + */ + cmd->serial_number = atomic_add_return(2, &host->cmd_serial_number); } /** diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index b7bdecb..b08d0f2 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -602,10 +602,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; @@ -636,6 +635,9 @@ struct Scsi_Host { /* Asynchronous scan in progress */ unsigned async_scan:1; + /* Signal usage of per struct scsi_cmnd->serial_number */ + unsigned use_serial_number:1; + /* * Optional work queue to be utilized by the transport */ -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html