From 2a5c98d2d2fe2aeaf95274a48fc9d92b5955dc74 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 31 Aug 2020 14:35:18 -0700 Subject: scsi: fc: Add 256GBit speed setting to SCSI FC transport Add 256GBit speed setting to the SCSI FC transport. This speed can be reached via FC trunking techniques. Link: https://lore.kernel.org/r/20200831213518.48409-1-james.smart@broadcom.com Reviewed-by: Himanshu Madhani Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- include/scsi/scsi_transport_fc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/scsi') diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 7db2dd783834..1c7dd35cb7a0 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -124,6 +124,7 @@ enum fc_vport_state { #define FC_PORTSPEED_25GBIT 0x800 #define FC_PORTSPEED_64GBIT 0x1000 #define FC_PORTSPEED_128GBIT 0x2000 +#define FC_PORTSPEED_256GBIT 0x4000 #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ /* -- cgit v1.2.3 From ed5dd6a67d5eac5fb8873697b55dc1699752a9f3 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 10 Sep 2020 15:50:56 +0800 Subject: scsi: core: Only re-run queue in scsi_end_request() if device queue is busy The request queue is currently run unconditionally in scsi_end_request() if both target queue and host queue are ready. Recently Long Li reported that cost of a queue run can be very heavy in case of high queue depth. Improve this situation by only running the request queue when this LUN is busy. Link: https://lore.kernel.org/r/20200910075056.36509-1-ming.lei@redhat.com Reported-by: Long Li Tested-by: Long Li Tested-by: Kashyap Desai Reviewed-by: Bart Van Assche Reviewed-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Reviewed-by: John Garry Signed-off-by: Ming Lei Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 48 ++++++++++++++++++++++++++++++++++++++++++---- include/scsi/scsi_device.h | 1 + 2 files changed, 45 insertions(+), 4 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7c6dd6f75190..f0ee11dc07e4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -549,10 +549,27 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) static void scsi_run_queue_async(struct scsi_device *sdev) { if (scsi_target(sdev)->single_lun || - !list_empty(&sdev->host->starved_list)) + !list_empty(&sdev->host->starved_list)) { kblockd_schedule_work(&sdev->requeue_work); - else - blk_mq_run_hw_queues(sdev->request_queue, true); + } else { + /* + * smp_mb() present in sbitmap_queue_clear() or implied in + * .end_io is for ordering writing .device_busy in + * scsi_device_unbusy() and reading sdev->restarts. + */ + int old = atomic_read(&sdev->restarts); + + /* + * ->restarts has to be kept as non-zero if new budget + * contention occurs. + * + * No need to run queue when either another re-run + * queue wins in updating ->restarts or a new budget + * contention occurs. + */ + if (old && atomic_cmpxchg(&sdev->restarts, old, 0) == old) + blk_mq_run_hw_queues(sdev->request_queue, true); + } } /* Returns false when no more bytes to process, true if there are more */ @@ -1612,7 +1629,30 @@ static bool scsi_mq_get_budget(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; - return scsi_dev_queue_ready(q, sdev); + if (scsi_dev_queue_ready(q, sdev)) + return true; + + atomic_inc(&sdev->restarts); + + /* + * Orders atomic_inc(&sdev->restarts) and atomic_read(&sdev->device_busy). + * .restarts must be incremented before .device_busy is read because the + * code in scsi_run_queue_async() depends on the order of these operations. + */ + smp_mb__after_atomic(); + + /* + * If all in-flight requests originated from this LUN are completed + * before reading .device_busy, sdev->device_busy will be observed as + * zero, then blk_mq_delay_run_hw_queues() will dispatch this request + * soon. Otherwise, completion of one of these requests will observe + * the .restarts flag, and the request queue will be run for handling + * this request, see scsi_end_request(). + */ + if (unlikely(atomic_read(&sdev->device_busy) == 0 && + !scsi_device_blocked(sdev))) + blk_mq_delay_run_hw_queues(sdev->request_queue, SCSI_QUEUE_DELAY); + return false; } static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index bc5909033d13..1a5c9a3df6d6 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -109,6 +109,7 @@ struct scsi_device { atomic_t device_busy; /* commands actually active on LLDD */ atomic_t device_blocked; /* Device returned QUEUE_FULL. */ + atomic_t restarts; spinlock_t list_lock; struct list_head starved_entry; unsigned short queue_depth; /* How deep of a queue we want */ -- cgit v1.2.3 From 7010645ba7256992818b518163f46bd4cdf8002a Mon Sep 17 00:00:00 2001 From: Roman Bolshakov Date: Tue, 29 Sep 2020 15:59:57 +0300 Subject: scsi: target: core: Add CONTROL field for trace events trace-cmd report doesn't show events from target subsystem because scsi_command_size() leaks through event format string: [target:target_sequencer_start] function scsi_command_size not defined [target:target_cmd_complete] function scsi_command_size not defined Addition of scsi_command_size() to plugin_scsi.c in trace-cmd doesn't help because an expression is used inside TP_printk(). trace-cmd event parser doesn't understand minus sign inside [ ]: Error: expected ']' but read '-' Rather than duplicating kernel code in plugin_scsi.c, provide a dedicated field for CONTROL byte. Link: https://lore.kernel.org/r/20200929125957.83069-1-r.bolshakov@yadro.com Reviewed-by: Mike Christie Signed-off-by: Roman Bolshakov Signed-off-by: Martin K. Petersen --- include/scsi/scsi_common.h | 7 +++++++ include/trace/events/target.h | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'include/scsi') diff --git a/include/scsi/scsi_common.h b/include/scsi/scsi_common.h index 731ac09ed231..5b567b43e1b1 100644 --- a/include/scsi/scsi_common.h +++ b/include/scsi/scsi_common.h @@ -25,6 +25,13 @@ scsi_command_size(const unsigned char *cmnd) scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]); } +static inline unsigned char +scsi_command_control(const unsigned char *cmnd) +{ + return (cmnd[0] == VARIABLE_LENGTH_CMD) ? + cmnd[1] : cmnd[COMMAND_SIZE(cmnd[0]) - 1]; +} + /* Returns a human-readable name for the device */ extern const char *scsi_device_type(unsigned type); diff --git a/include/trace/events/target.h b/include/trace/events/target.h index 77408edd29d2..67fad2677ed5 100644 --- a/include/trace/events/target.h +++ b/include/trace/events/target.h @@ -141,6 +141,7 @@ TRACE_EVENT(target_sequencer_start, __field( unsigned int, opcode ) __field( unsigned int, data_length ) __field( unsigned int, task_attribute ) + __field( unsigned char, control ) __array( unsigned char, cdb, TCM_MAX_COMMAND_SIZE ) __string( initiator, cmd->se_sess->se_node_acl->initiatorname ) ), @@ -151,6 +152,7 @@ TRACE_EVENT(target_sequencer_start, __entry->opcode = cmd->t_task_cdb[0]; __entry->data_length = cmd->data_length; __entry->task_attribute = cmd->sam_task_attr; + __entry->control = scsi_command_control(cmd->t_task_cdb); memcpy(__entry->cdb, cmd->t_task_cdb, TCM_MAX_COMMAND_SIZE); __assign_str(initiator, cmd->se_sess->se_node_acl->initiatorname); ), @@ -160,9 +162,7 @@ TRACE_EVENT(target_sequencer_start, __entry->tag, show_opcode_name(__entry->opcode), __entry->data_length, __print_hex(__entry->cdb, 16), show_task_attribute_name(__entry->task_attribute), - scsi_command_size(__entry->cdb) <= 16 ? - __entry->cdb[scsi_command_size(__entry->cdb) - 1] : - __entry->cdb[1] + __entry->control ) ); @@ -178,6 +178,7 @@ TRACE_EVENT(target_cmd_complete, __field( unsigned int, opcode ) __field( unsigned int, data_length ) __field( unsigned int, task_attribute ) + __field( unsigned char, control ) __field( unsigned char, scsi_status ) __field( unsigned char, sense_length ) __array( unsigned char, cdb, TCM_MAX_COMMAND_SIZE ) @@ -191,6 +192,7 @@ TRACE_EVENT(target_cmd_complete, __entry->opcode = cmd->t_task_cdb[0]; __entry->data_length = cmd->data_length; __entry->task_attribute = cmd->sam_task_attr; + __entry->control = scsi_command_control(cmd->t_task_cdb); __entry->scsi_status = cmd->scsi_status; __entry->sense_length = cmd->scsi_status == SAM_STAT_CHECK_CONDITION ? min(18, ((u8 *) cmd->sense_buffer)[SPC_ADD_SENSE_LEN_OFFSET] + 8) : 0; @@ -208,9 +210,7 @@ TRACE_EVENT(target_cmd_complete, show_opcode_name(__entry->opcode), __entry->data_length, __print_hex(__entry->cdb, 16), show_task_attribute_name(__entry->task_attribute), - scsi_command_size(__entry->cdb) <= 16 ? - __entry->cdb[scsi_command_size(__entry->cdb) - 1] : - __entry->cdb[1] + __entry->control ) ); -- cgit v1.2.3