|
|
24d93b |
From a28d10b2a9bec8714f59e12fe7fb53bfe8c6ef17 Mon Sep 17 00:00:00 2001
|
|
|
24d93b |
From: Sasikumar Chandrasekaran <sasikumar.pc@broadcom.com>
|
|
|
24d93b |
Date: Tue, 10 Jan 2017 18:20:46 -0500
|
|
|
24d93b |
Subject: [PATCH 04/11] scsi: megaraid_sas: SAS3.5 Generic Megaraid Controllers
|
|
|
24d93b |
Stream Detection and IO Coalescing
|
|
|
24d93b |
|
|
|
24d93b |
Detect sequential Write IOs and pass the hint that it is part of sequential
|
|
|
24d93b |
stream to help HBA Firmware do the Full Stripe Writes. For read IOs on
|
|
|
24d93b |
certain RAID volumes like Read Ahead volumes,this will help driver to
|
|
|
24d93b |
send it to Firmware even if the IOs can potentially be sent to
|
|
|
24d93b |
hardware directly (called fast path) bypassing firmware.
|
|
|
24d93b |
|
|
|
24d93b |
Design: 8 streams are maintained per RAID volume as per the combined
|
|
|
24d93b |
firmware/driver design. When there is no stream detected the LRU stream
|
|
|
24d93b |
is used for next potential stream and LRU/MRU map is updated to make this
|
|
|
24d93b |
as MRU stream. Every time a stream is detected the MRU map
|
|
|
24d93b |
is updated to make the current stream as MRU stream.
|
|
|
24d93b |
|
|
|
24d93b |
Signed-off-by: Sasikumar Chandrasekaran <sasikumar.pc@broadcom.com>
|
|
|
24d93b |
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
|
|
|
24d93b |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
|
24d93b |
---
|
|
|
24d93b |
drivers/scsi/megaraid/megaraid_sas.h | 1 +
|
|
|
24d93b |
drivers/scsi/megaraid/megaraid_sas_base.c | 43 +++++++-
|
|
|
24d93b |
drivers/scsi/megaraid/megaraid_sas_fp.c | 2 +
|
|
|
24d93b |
drivers/scsi/megaraid/megaraid_sas_fusion.c | 165 +++++++++++++++++++++++-----
|
|
|
24d93b |
drivers/scsi/megaraid/megaraid_sas_fusion.h | 117 +++++++++++++++++++-
|
|
|
24d93b |
5 files changed, 297 insertions(+), 31 deletions(-)
|
|
|
24d93b |
|
|
|
24d93b |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
|
|
|
24d93b |
index ccef47b..f387b32 100644
|
|
|
24d93b |
--- a/drivers/scsi/megaraid/megaraid_sas.h
|
|
|
24d93b |
+++ b/drivers/scsi/megaraid/megaraid_sas.h
|
|
|
24d93b |
@@ -2070,6 +2070,7 @@ struct megasas_instance {
|
|
|
24d93b |
/* used to sync fire the cmd to fw */
|
|
|
24d93b |
spinlock_t hba_lock;
|
|
|
24d93b |
/* used to synch producer, consumer ptrs in dpc */
|
|
|
24d93b |
+ spinlock_t stream_lock;
|
|
|
24d93b |
spinlock_t completion_lock;
|
|
|
24d93b |
struct dma_pool *frame_dma_pool;
|
|
|
24d93b |
struct dma_pool *sense_dma_pool;
|
|
|
24d93b |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
|
24d93b |
index c78d7ee..0722286 100644
|
|
|
24d93b |
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
|
24d93b |
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
|
24d93b |
@@ -5048,7 +5048,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|
|
24d93b |
struct megasas_register_set __iomem *reg_set;
|
|
|
24d93b |
struct megasas_ctrl_info *ctrl_info = NULL;
|
|
|
24d93b |
unsigned long bar_list;
|
|
|
24d93b |
- int i, loop, fw_msix_count = 0;
|
|
|
24d93b |
+ int i, j, loop, fw_msix_count = 0;
|
|
|
24d93b |
struct IOV_111 *iovPtr;
|
|
|
24d93b |
struct fusion_context *fusion;
|
|
|
24d93b |
|
|
|
24d93b |
@@ -5235,6 +5235,36 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|
|
24d93b |
}
|
|
|
24d93b |
|
|
|
24d93b |
memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
|
|
|
24d93b |
+
|
|
|
24d93b |
+ /* stream detection initialization */
|
|
|
24d93b |
+ if (instance->is_ventura) {
|
|
|
24d93b |
+ fusion->stream_detect_by_ld =
|
|
|
24d93b |
+ kzalloc(sizeof(struct LD_STREAM_DETECT *)
|
|
|
24d93b |
+ * MAX_LOGICAL_DRIVES_EXT,
|
|
|
24d93b |
+ GFP_KERNEL);
|
|
|
24d93b |
+ if (!fusion->stream_detect_by_ld) {
|
|
|
24d93b |
+ dev_err(&instance->pdev->dev,
|
|
|
24d93b |
+ "unable to allocate stream detection for pool of LDs\n");
|
|
|
24d93b |
+ goto fail_get_ld_pd_list;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+ for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i) {
|
|
|
24d93b |
+ fusion->stream_detect_by_ld[i] =
|
|
|
24d93b |
+ kmalloc(sizeof(struct LD_STREAM_DETECT),
|
|
|
24d93b |
+ GFP_KERNEL);
|
|
|
24d93b |
+ if (!fusion->stream_detect_by_ld[i]) {
|
|
|
24d93b |
+ dev_err(&instance->pdev->dev,
|
|
|
24d93b |
+ "unable to allocate stream detect by LD\n ");
|
|
|
24d93b |
+ for (j = 0; j < i; ++j)
|
|
|
24d93b |
+ kfree(fusion->stream_detect_by_ld[j]);
|
|
|
24d93b |
+ kfree(fusion->stream_detect_by_ld);
|
|
|
24d93b |
+ fusion->stream_detect_by_ld = NULL;
|
|
|
24d93b |
+ goto fail_get_ld_pd_list;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+ fusion->stream_detect_by_ld[i]->mru_bit_map
|
|
|
24d93b |
+ = MR_STREAM_BITMAP;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+
|
|
|
24d93b |
if (megasas_ld_list_query(instance,
|
|
|
24d93b |
MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
|
|
|
24d93b |
megasas_get_ld_list(instance);
|
|
|
24d93b |
@@ -5354,6 +5384,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|
|
24d93b |
|
|
|
24d93b |
return 0;
|
|
|
24d93b |
|
|
|
24d93b |
+fail_get_ld_pd_list:
|
|
|
24d93b |
+ instance->instancet->disable_intr(instance);
|
|
|
24d93b |
fail_get_pd_list:
|
|
|
24d93b |
instance->instancet->disable_intr(instance);
|
|
|
24d93b |
megasas_destroy_irqs(instance);
|
|
|
24d93b |
@@ -5896,6 +5928,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
|
|
|
24d93b |
|
|
|
24d93b |
spin_lock_init(&instance->mfi_pool_lock);
|
|
|
24d93b |
spin_lock_init(&instance->hba_lock);
|
|
|
24d93b |
+ spin_lock_init(&instance->stream_lock);
|
|
|
24d93b |
spin_lock_init(&instance->completion_lock);
|
|
|
24d93b |
|
|
|
24d93b |
mutex_init(&instance->reset_mutex);
|
|
|
24d93b |
@@ -6363,6 +6396,14 @@ static void megasas_detach_one(struct pci_dev *pdev)
|
|
|
24d93b |
if (instance->msix_vectors)
|
|
|
24d93b |
pci_disable_msix(instance->pdev);
|
|
|
24d93b |
|
|
|
24d93b |
+ if (instance->is_ventura) {
|
|
|
24d93b |
+ for (i = 0; i < MAX_LOGICAL_DRIVES_EXT; ++i)
|
|
|
24d93b |
+ kfree(fusion->stream_detect_by_ld[i]);
|
|
|
24d93b |
+ kfree(fusion->stream_detect_by_ld);
|
|
|
24d93b |
+ fusion->stream_detect_by_ld = NULL;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+
|
|
|
24d93b |
+
|
|
|
24d93b |
if (instance->ctrl_context) {
|
|
|
24d93b |
megasas_release_fusion(instance);
|
|
|
24d93b |
pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
|
|
|
24d93b |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
|
|
|
24d93b |
index e413113..fe5b074 100644
|
|
|
24d93b |
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
|
|
|
24d93b |
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
|
|
|
24d93b |
@@ -933,6 +933,8 @@ MR_BuildRaidContext(struct megasas_instance *instance,
|
|
|
24d93b |
|
|
|
24d93b |
ld = MR_TargetIdToLdGet(ldTgtId, map);
|
|
|
24d93b |
raid = MR_LdRaidGet(ld, map);
|
|
|
24d93b |
+ /*check read ahead bit*/
|
|
|
24d93b |
+ io_info->ra_capable = raid->capability.ra_capable;
|
|
|
24d93b |
|
|
|
24d93b |
/*
|
|
|
24d93b |
* if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero
|
|
|
24d93b |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
|
|
|
24d93b |
index 27c6a1f..946f7c0 100644
|
|
|
24d93b |
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
|
|
|
24d93b |
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
|
|
|
24d93b |
@@ -1704,6 +1704,90 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
|
|
|
24d93b |
}
|
|
|
24d93b |
|
|
|
24d93b |
/**
|
|
|
24d93b |
+ * megasas_stream_detect - stream detection on read and and write IOs
|
|
|
24d93b |
+ * @instance: Adapter soft state
|
|
|
24d93b |
+ * @cmd: Command to be prepared
|
|
|
24d93b |
+ * @io_info: IO Request info
|
|
|
24d93b |
+ *
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+
|
|
|
24d93b |
+/** stream detection on read and and write IOs */
|
|
|
24d93b |
+static void megasas_stream_detect(struct megasas_instance *instance,
|
|
|
24d93b |
+ struct megasas_cmd_fusion *cmd,
|
|
|
24d93b |
+ struct IO_REQUEST_INFO *io_info)
|
|
|
24d93b |
+{
|
|
|
24d93b |
+ struct fusion_context *fusion = instance->ctrl_context;
|
|
|
24d93b |
+ u32 device_id = io_info->ldTgtId;
|
|
|
24d93b |
+ struct LD_STREAM_DETECT *current_ld_sd
|
|
|
24d93b |
+ = fusion->stream_detect_by_ld[device_id];
|
|
|
24d93b |
+ u32 *track_stream = ¤t_ld_sd->mru_bit_map, stream_num;
|
|
|
24d93b |
+ u32 shifted_values, unshifted_values;
|
|
|
24d93b |
+ u32 index_value_mask, shifted_values_mask;
|
|
|
24d93b |
+ int i;
|
|
|
24d93b |
+ bool is_read_ahead = false;
|
|
|
24d93b |
+ struct STREAM_DETECT *current_sd;
|
|
|
24d93b |
+ /* find possible stream */
|
|
|
24d93b |
+ for (i = 0; i < MAX_STREAMS_TRACKED; ++i) {
|
|
|
24d93b |
+ stream_num =
|
|
|
24d93b |
+ (*track_stream >> (i * BITS_PER_INDEX_STREAM)) &
|
|
|
24d93b |
+ STREAM_MASK;
|
|
|
24d93b |
+ current_sd = ¤t_ld_sd->stream_track[stream_num];
|
|
|
24d93b |
+ /* if we found a stream, update the raid
|
|
|
24d93b |
+ * context and also update the mruBitMap
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ /* boundary condition */
|
|
|
24d93b |
+ if ((current_sd->next_seq_lba) &&
|
|
|
24d93b |
+ (io_info->ldStartBlock >= current_sd->next_seq_lba) &&
|
|
|
24d93b |
+ (io_info->ldStartBlock <= (current_sd->next_seq_lba+32)) &&
|
|
|
24d93b |
+ (current_sd->is_read == io_info->isRead)) {
|
|
|
24d93b |
+
|
|
|
24d93b |
+ if ((io_info->ldStartBlock != current_sd->next_seq_lba)
|
|
|
24d93b |
+ && ((!io_info->isRead) || (!is_read_ahead)))
|
|
|
24d93b |
+ /*
|
|
|
24d93b |
+ * Once the API availible we need to change this.
|
|
|
24d93b |
+ * At this point we are not allowing any gap
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ continue;
|
|
|
24d93b |
+
|
|
|
24d93b |
+ cmd->io_request->RaidContext.raid_context_g35.stream_detected = true;
|
|
|
24d93b |
+ current_sd->next_seq_lba =
|
|
|
24d93b |
+ io_info->ldStartBlock + io_info->numBlocks;
|
|
|
24d93b |
+ /*
|
|
|
24d93b |
+ * update the mruBitMap LRU
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ shifted_values_mask =
|
|
|
24d93b |
+ (1 << i * BITS_PER_INDEX_STREAM) - 1;
|
|
|
24d93b |
+ shifted_values = ((*track_stream & shifted_values_mask)
|
|
|
24d93b |
+ << BITS_PER_INDEX_STREAM);
|
|
|
24d93b |
+ index_value_mask =
|
|
|
24d93b |
+ STREAM_MASK << i * BITS_PER_INDEX_STREAM;
|
|
|
24d93b |
+ unshifted_values =
|
|
|
24d93b |
+ *track_stream & ~(shifted_values_mask |
|
|
|
24d93b |
+ index_value_mask);
|
|
|
24d93b |
+ *track_stream =
|
|
|
24d93b |
+ unshifted_values | shifted_values | stream_num;
|
|
|
24d93b |
+ return;
|
|
|
24d93b |
+
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+ /*
|
|
|
24d93b |
+ * if we did not find any stream, create a new one
|
|
|
24d93b |
+ * from the least recently used
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ stream_num =
|
|
|
24d93b |
+ (*track_stream >> ((MAX_STREAMS_TRACKED - 1) * BITS_PER_INDEX_STREAM)) &
|
|
|
24d93b |
+ STREAM_MASK;
|
|
|
24d93b |
+ current_sd = ¤t_ld_sd->stream_track[stream_num];
|
|
|
24d93b |
+ current_sd->is_read = io_info->isRead;
|
|
|
24d93b |
+ current_sd->next_seq_lba = io_info->ldStartBlock + io_info->numBlocks;
|
|
|
24d93b |
+ *track_stream =
|
|
|
24d93b |
+ (((*track_stream & ZERO_LAST_STREAM) << 4) | stream_num);
|
|
|
24d93b |
+ return;
|
|
|
24d93b |
+
|
|
|
24d93b |
+}
|
|
|
24d93b |
+
|
|
|
24d93b |
+/**
|
|
|
24d93b |
* megasas_build_ldio_fusion - Prepares IOs to devices
|
|
|
24d93b |
* @instance: Adapter soft state
|
|
|
24d93b |
* @scp: SCSI command
|
|
|
24d93b |
@@ -1725,15 +1809,17 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
struct fusion_context *fusion;
|
|
|
24d93b |
struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
|
|
|
24d93b |
u8 *raidLUN;
|
|
|
24d93b |
+ unsigned long spinlock_flags;
|
|
|
24d93b |
|
|
|
24d93b |
device_id = MEGASAS_DEV_INDEX(scp);
|
|
|
24d93b |
|
|
|
24d93b |
fusion = instance->ctrl_context;
|
|
|
24d93b |
|
|
|
24d93b |
io_request = cmd->io_request;
|
|
|
24d93b |
- io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id);
|
|
|
24d93b |
- io_request->RaidContext.status = 0;
|
|
|
24d93b |
- io_request->RaidContext.exStatus = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.VirtualDiskTgtId =
|
|
|
24d93b |
+ cpu_to_le16(device_id);
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.status = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.exStatus = 0;
|
|
|
24d93b |
|
|
|
24d93b |
req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc;
|
|
|
24d93b |
|
|
|
24d93b |
@@ -1804,11 +1890,11 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
|
|
|
24d93b |
if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >=
|
|
|
24d93b |
instance->fw_supported_vd_count) || (!fusion->fast_path_io)) {
|
|
|
24d93b |
- io_request->RaidContext.regLockFlags = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.regLockFlags = 0;
|
|
|
24d93b |
fp_possible = 0;
|
|
|
24d93b |
} else {
|
|
|
24d93b |
if (MR_BuildRaidContext(instance, &io_info,
|
|
|
24d93b |
- &io_request->RaidContext,
|
|
|
24d93b |
+ &io_request->RaidContext.raid_context,
|
|
|
24d93b |
local_map_ptr, &raidLUN))
|
|
|
24d93b |
fp_possible = io_info.fpOkForIo;
|
|
|
24d93b |
}
|
|
|
24d93b |
@@ -1819,6 +1905,18 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
|
|
|
24d93b |
raw_smp_processor_id() % instance->msix_vectors : 0;
|
|
|
24d93b |
|
|
|
24d93b |
+ if (instance->is_ventura) {
|
|
|
24d93b |
+ spin_lock_irqsave(&instance->stream_lock, spinlock_flags);
|
|
|
24d93b |
+ megasas_stream_detect(instance, cmd, &io_info);
|
|
|
24d93b |
+ spin_unlock_irqrestore(&instance->stream_lock, spinlock_flags);
|
|
|
24d93b |
+ /* In ventura if stream detected for a read and it is read ahead
|
|
|
24d93b |
+ * capable make this IO as LDIO
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ if (io_request->RaidContext.raid_context_g35.stream_detected &&
|
|
|
24d93b |
+ io_info.isRead && io_info.ra_capable)
|
|
|
24d93b |
+ fp_possible = false;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+
|
|
|
24d93b |
if (fp_possible) {
|
|
|
24d93b |
megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
|
|
|
24d93b |
local_map_ptr, start_lba_lo);
|
|
|
24d93b |
@@ -1827,15 +1925,16 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
(MPI2_REQ_DESCRIPT_FLAGS_FP_IO
|
|
|
24d93b |
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
|
|
|
24d93b |
if (fusion->adapter_type == INVADER_SERIES) {
|
|
|
24d93b |
- if (io_request->RaidContext.regLockFlags ==
|
|
|
24d93b |
+ if (io_request->RaidContext.raid_context.regLockFlags ==
|
|
|
24d93b |
REGION_TYPE_UNUSED)
|
|
|
24d93b |
cmd->request_desc->SCSIIO.RequestFlags =
|
|
|
24d93b |
(MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
|
|
|
24d93b |
MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
|
|
|
24d93b |
- io_request->RaidContext.Type = MPI2_TYPE_CUDA;
|
|
|
24d93b |
- io_request->RaidContext.nseg = 0x1;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.Type
|
|
|
24d93b |
+ = MPI2_TYPE_CUDA;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.nseg = 0x1;
|
|
|
24d93b |
io_request->IoFlags |= cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
|
|
|
24d93b |
- io_request->RaidContext.regLockFlags |=
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.regLockFlags |=
|
|
|
24d93b |
(MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
|
|
|
24d93b |
MR_RL_FLAGS_SEQ_NUM_ENABLE);
|
|
|
24d93b |
}
|
|
|
24d93b |
@@ -1862,22 +1961,24 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
/* populate the LUN field */
|
|
|
24d93b |
memcpy(io_request->LUN, raidLUN, 8);
|
|
|
24d93b |
} else {
|
|
|
24d93b |
- io_request->RaidContext.timeoutValue =
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.timeoutValue =
|
|
|
24d93b |
cpu_to_le16(local_map_ptr->raidMap.fpPdIoTimeoutSec);
|
|
|
24d93b |
cmd->request_desc->SCSIIO.RequestFlags =
|
|
|
24d93b |
(MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
|
|
|
24d93b |
<< MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
|
|
|
24d93b |
if (fusion->adapter_type == INVADER_SERIES) {
|
|
|
24d93b |
if (io_info.do_fp_rlbypass ||
|
|
|
24d93b |
- (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED))
|
|
|
24d93b |
+ (io_request->RaidContext.raid_context.regLockFlags
|
|
|
24d93b |
+ == REGION_TYPE_UNUSED))
|
|
|
24d93b |
cmd->request_desc->SCSIIO.RequestFlags =
|
|
|
24d93b |
(MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
|
|
|
24d93b |
MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
|
|
|
24d93b |
- io_request->RaidContext.Type = MPI2_TYPE_CUDA;
|
|
|
24d93b |
- io_request->RaidContext.regLockFlags |=
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.Type
|
|
|
24d93b |
+ = MPI2_TYPE_CUDA;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.regLockFlags |=
|
|
|
24d93b |
(MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
|
|
|
24d93b |
MR_RL_FLAGS_SEQ_NUM_ENABLE);
|
|
|
24d93b |
- io_request->RaidContext.nseg = 0x1;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.nseg = 0x1;
|
|
|
24d93b |
}
|
|
|
24d93b |
io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
|
|
|
24d93b |
io_request->DevHandle = cpu_to_le16(device_id);
|
|
|
24d93b |
@@ -1913,7 +2014,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
|
|
|
24d93b |
io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
|
|
|
24d93b |
/* get RAID_Context pointer */
|
|
|
24d93b |
- pRAID_Context = &io_request->RaidContext;
|
|
|
24d93b |
+ pRAID_Context = &io_request->RaidContext.raid_context;
|
|
|
24d93b |
/* Check with FW team */
|
|
|
24d93b |
pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
|
|
|
24d93b |
pRAID_Context->regLockRowLBA = 0;
|
|
|
24d93b |
@@ -2000,7 +2101,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
|
|
|
24d93b |
io_request = cmd->io_request;
|
|
|
24d93b |
/* get RAID_Context pointer */
|
|
|
24d93b |
- pRAID_Context = &io_request->RaidContext;
|
|
|
24d93b |
+ pRAID_Context = &io_request->RaidContext.raid_context;
|
|
|
24d93b |
pRAID_Context->regLockFlags = 0;
|
|
|
24d93b |
pRAID_Context->regLockRowLBA = 0;
|
|
|
24d93b |
pRAID_Context->regLockLength = 0;
|
|
|
24d93b |
@@ -2094,9 +2195,9 @@ megasas_build_io_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
io_request->Control = 0;
|
|
|
24d93b |
io_request->EEDPBlockSize = 0;
|
|
|
24d93b |
io_request->ChainOffset = 0;
|
|
|
24d93b |
- io_request->RaidContext.RAIDFlags = 0;
|
|
|
24d93b |
- io_request->RaidContext.Type = 0;
|
|
|
24d93b |
- io_request->RaidContext.nseg = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.RAIDFlags = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.Type = 0;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.nseg = 0;
|
|
|
24d93b |
|
|
|
24d93b |
memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len);
|
|
|
24d93b |
/*
|
|
|
24d93b |
@@ -2143,8 +2244,8 @@ megasas_build_io_fusion(struct megasas_instance *instance,
|
|
|
24d93b |
/* numSGE store lower 8 bit of sge_count.
|
|
|
24d93b |
* numSGEExt store higher 8 bit of sge_count
|
|
|
24d93b |
*/
|
|
|
24d93b |
- io_request->RaidContext.numSGE = sge_count;
|
|
|
24d93b |
- io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8);
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.numSGE = sge_count;
|
|
|
24d93b |
+ io_request->RaidContext.raid_context.numSGEExt = (u8)(sge_count >> 8);
|
|
|
24d93b |
|
|
|
24d93b |
io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
|
|
|
24d93b |
|
|
|
24d93b |
@@ -2303,8 +2404,8 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
|
|
|
24d93b |
cmd_fusion->scmd->SCp.ptr = NULL;
|
|
|
24d93b |
|
|
|
24d93b |
scmd_local = cmd_fusion->scmd;
|
|
|
24d93b |
- status = scsi_io_req->RaidContext.status;
|
|
|
24d93b |
- extStatus = scsi_io_req->RaidContext.exStatus;
|
|
|
24d93b |
+ status = scsi_io_req->RaidContext.raid_context.status;
|
|
|
24d93b |
+ extStatus = scsi_io_req->RaidContext.raid_context.exStatus;
|
|
|
24d93b |
|
|
|
24d93b |
switch (scsi_io_req->Function) {
|
|
|
24d93b |
case MPI2_FUNCTION_SCSI_TASK_MGMT:
|
|
|
24d93b |
@@ -2337,8 +2438,8 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
|
|
|
24d93b |
case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
|
|
|
24d93b |
/* Map the FW Cmd Status */
|
|
|
24d93b |
map_cmd_status(cmd_fusion, status, extStatus);
|
|
|
24d93b |
- scsi_io_req->RaidContext.status = 0;
|
|
|
24d93b |
- scsi_io_req->RaidContext.exStatus = 0;
|
|
|
24d93b |
+ scsi_io_req->RaidContext.raid_context.status = 0;
|
|
|
24d93b |
+ scsi_io_req->RaidContext.raid_context.exStatus = 0;
|
|
|
24d93b |
if (megasas_cmd_type(scmd_local) == READ_WRITE_LDIO)
|
|
|
24d93b |
atomic_dec(&instance->ldio_outstanding);
|
|
|
24d93b |
megasas_return_cmd_fusion(instance, cmd_fusion);
|
|
|
24d93b |
@@ -2901,7 +3002,7 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
|
|
|
24d93b |
&& !(cmd_mfi->flags & DRV_DCMD_SKIP_REFIRE);
|
|
|
24d93b |
if (refire_cmd)
|
|
|
24d93b |
megasas_fire_cmd_fusion(instance, req_desc,
|
|
|
24d93b |
- instance->is_ventura);
|
|
|
24d93b |
+ instance->is_ventura);
|
|
|
24d93b |
else
|
|
|
24d93b |
megasas_return_cmd(instance, cmd_mfi);
|
|
|
24d93b |
}
|
|
|
24d93b |
@@ -3390,7 +3491,7 @@ int megasas_check_mpio_paths(struct megasas_instance *instance,
|
|
|
24d93b |
/* Core fusion reset function */
|
|
|
24d93b |
int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
|
|
|
24d93b |
{
|
|
|
24d93b |
- int retval = SUCCESS, i, convert = 0;
|
|
|
24d93b |
+ int retval = SUCCESS, i, j, convert = 0;
|
|
|
24d93b |
struct megasas_instance *instance;
|
|
|
24d93b |
struct megasas_cmd_fusion *cmd_fusion;
|
|
|
24d93b |
struct fusion_context *fusion;
|
|
|
24d93b |
@@ -3555,6 +3656,16 @@ transition_to_ready:
|
|
|
24d93b |
shost_for_each_device(sdev, shost)
|
|
|
24d93b |
megasas_update_sdev_properties(sdev);
|
|
|
24d93b |
|
|
|
24d93b |
+ /* reset stream detection array */
|
|
|
24d93b |
+ if (instance->is_ventura) {
|
|
|
24d93b |
+ for (j = 0; j < MAX_LOGICAL_DRIVES_EXT; ++j) {
|
|
|
24d93b |
+ memset(fusion->stream_detect_by_ld[j],
|
|
|
24d93b |
+ 0, sizeof(struct LD_STREAM_DETECT));
|
|
|
24d93b |
+ fusion->stream_detect_by_ld[j]->mru_bit_map
|
|
|
24d93b |
+ = MR_STREAM_BITMAP;
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+ }
|
|
|
24d93b |
+
|
|
|
24d93b |
clear_bit(MEGASAS_FUSION_IN_RESET,
|
|
|
24d93b |
&instance->reset_flags);
|
|
|
24d93b |
instance->instancet->enable_intr(instance);
|
|
|
24d93b |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
|
|
|
24d93b |
index 3cd3d0a..d9cf496 100644
|
|
|
24d93b |
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
|
|
|
24d93b |
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
|
|
|
24d93b |
@@ -133,12 +133,95 @@ struct RAID_CONTEXT {
|
|
|
24d93b |
u8 resvd2;
|
|
|
24d93b |
};
|
|
|
24d93b |
|
|
|
24d93b |
+/*
|
|
|
24d93b |
+ * Raid Context structure which describes ventura MegaRAID specific
|
|
|
24d93b |
+ * IO Paramenters ,This resides at offset 0x60 where the SGL normally
|
|
|
24d93b |
+ * starts in MPT IO Frames
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+struct RAID_CONTEXT_G35 {
|
|
|
24d93b |
+#if defined(__BIG_ENDIAN_BITFIELD)
|
|
|
24d93b |
+ u16 resvd0:8;
|
|
|
24d93b |
+ u16 nseg:4;
|
|
|
24d93b |
+ u16 type:4;
|
|
|
24d93b |
+#else
|
|
|
24d93b |
+ u16 type:4; /* 0x00 */
|
|
|
24d93b |
+ u16 nseg:4; /* 0x00 */
|
|
|
24d93b |
+ u16 resvd0:8;
|
|
|
24d93b |
+#endif
|
|
|
24d93b |
+ u16 timeout_value; /* 0x02 -0x03 */
|
|
|
24d93b |
+ union {
|
|
|
24d93b |
+ struct {
|
|
|
24d93b |
+#if defined(__BIG_ENDIAN_BITFIELD)
|
|
|
24d93b |
+ u16 set_divert:4;
|
|
|
24d93b |
+ u16 cpu_sel:4;
|
|
|
24d93b |
+ u16 log:1;
|
|
|
24d93b |
+ u16 rw:1;
|
|
|
24d93b |
+ u16 sbs:1;
|
|
|
24d93b |
+ u16 sqn:1;
|
|
|
24d93b |
+ u16 fwn:1;
|
|
|
24d93b |
+ u16 c2f:1;
|
|
|
24d93b |
+ u16 sld:1;
|
|
|
24d93b |
+ u16 reserved:1;
|
|
|
24d93b |
+#else
|
|
|
24d93b |
+ u16 reserved:1;
|
|
|
24d93b |
+ u16 sld:1;
|
|
|
24d93b |
+ u16 c2f:1;
|
|
|
24d93b |
+ u16 fwn:1;
|
|
|
24d93b |
+ u16 sqn:1;
|
|
|
24d93b |
+ u16 sbs:1;
|
|
|
24d93b |
+ u16 rw:1;
|
|
|
24d93b |
+ u16 log:1;
|
|
|
24d93b |
+ u16 cpu_sel:4;
|
|
|
24d93b |
+ u16 set_divert:4;
|
|
|
24d93b |
+#endif
|
|
|
24d93b |
+ } bits;
|
|
|
24d93b |
+ u16 s;
|
|
|
24d93b |
+ } routing_flags; /* 0x04 -0x05 routing flags */
|
|
|
24d93b |
+ u16 virtual_disk_tgt_id; /* 0x06 -0x07 */
|
|
|
24d93b |
+ u64 reg_lock_row_lba; /* 0x08 - 0x0F */
|
|
|
24d93b |
+ u32 reg_lock_length; /* 0x10 - 0x13 */
|
|
|
24d93b |
+ union {
|
|
|
24d93b |
+ u16 next_lmid; /* 0x14 - 0x15 */
|
|
|
24d93b |
+ u16 peer_smid; /* used for the raid 1/10 fp writes */
|
|
|
24d93b |
+ } smid;
|
|
|
24d93b |
+ u8 ex_status; /* 0x16 : OUT */
|
|
|
24d93b |
+ u8 status; /* 0x17 status */
|
|
|
24d93b |
+ u8 RAIDFlags; /* 0x18 resvd[7:6], ioSubType[5:4],
|
|
|
24d93b |
+ * resvd[3:1], preferredCpu[0]
|
|
|
24d93b |
+ */
|
|
|
24d93b |
+ u8 span_arm; /* 0x1C span[7:5], arm[4:0] */
|
|
|
24d93b |
+ u16 config_seq_num; /* 0x1A -0x1B */
|
|
|
24d93b |
+#if defined(__BIG_ENDIAN_BITFIELD) /* 0x1C - 0x1D */
|
|
|
24d93b |
+ u16 stream_detected:1;
|
|
|
24d93b |
+ u16 reserved:3;
|
|
|
24d93b |
+ u16 num_sge:12;
|
|
|
24d93b |
+#else
|
|
|
24d93b |
+ u16 num_sge:12;
|
|
|
24d93b |
+ u16 reserved:3;
|
|
|
24d93b |
+ u16 stream_detected:1;
|
|
|
24d93b |
+#endif
|
|
|
24d93b |
+ u8 resvd2[2]; /* 0x1E-0x1F */
|
|
|
24d93b |
+};
|
|
|
24d93b |
+
|
|
|
24d93b |
+union RAID_CONTEXT_UNION {
|
|
|
24d93b |
+ struct RAID_CONTEXT raid_context;
|
|
|
24d93b |
+ struct RAID_CONTEXT_G35 raid_context_g35;
|
|
|
24d93b |
+};
|
|
|
24d93b |
+
|
|
|
24d93b |
#define RAID_CTX_SPANARM_ARM_SHIFT (0)
|
|
|
24d93b |
#define RAID_CTX_SPANARM_ARM_MASK (0x1f)
|
|
|
24d93b |
|
|
|
24d93b |
#define RAID_CTX_SPANARM_SPAN_SHIFT (5)
|
|
|
24d93b |
#define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
|
|
|
24d93b |
|
|
|
24d93b |
+/* number of bits per index in U32 TrackStream */
|
|
|
24d93b |
+#define BITS_PER_INDEX_STREAM 4
|
|
|
24d93b |
+#define INVALID_STREAM_NUM 16
|
|
|
24d93b |
+#define MR_STREAM_BITMAP 0x76543210
|
|
|
24d93b |
+#define STREAM_MASK ((1 << BITS_PER_INDEX_STREAM) - 1)
|
|
|
24d93b |
+#define ZERO_LAST_STREAM 0x0fffffff
|
|
|
24d93b |
+#define MAX_STREAMS_TRACKED 8
|
|
|
24d93b |
+
|
|
|
24d93b |
/*
|
|
|
24d93b |
* define region lock types
|
|
|
24d93b |
*/
|
|
|
24d93b |
@@ -409,7 +492,7 @@ struct MPI2_RAID_SCSI_IO_REQUEST {
|
|
|
24d93b |
u8 LUN[8]; /* 0x34 */
|
|
|
24d93b |
__le32 Control; /* 0x3C */
|
|
|
24d93b |
union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
|
|
|
24d93b |
- struct RAID_CONTEXT RaidContext; /* 0x60 */
|
|
|
24d93b |
+ union RAID_CONTEXT_UNION RaidContext; /* 0x60 */
|
|
|
24d93b |
union MPI2_SGE_IO_UNION SGL; /* 0x80 */
|
|
|
24d93b |
};
|
|
|
24d93b |
|
|
|
24d93b |
@@ -656,11 +739,13 @@ struct MR_LD_RAID {
|
|
|
24d93b |
u32 encryptionType:8;
|
|
|
24d93b |
u32 pdPiMode:4;
|
|
|
24d93b |
u32 ldPiMode:4;
|
|
|
24d93b |
- u32 reserved5:3;
|
|
|
24d93b |
+ u32 reserved5:2;
|
|
|
24d93b |
+ u32 ra_capable:1;
|
|
|
24d93b |
u32 fpCapable:1;
|
|
|
24d93b |
#else
|
|
|
24d93b |
u32 fpCapable:1;
|
|
|
24d93b |
- u32 reserved5:3;
|
|
|
24d93b |
+ u32 ra_capable:1;
|
|
|
24d93b |
+ u32 reserved5:2;
|
|
|
24d93b |
u32 ldPiMode:4;
|
|
|
24d93b |
u32 pdPiMode:4;
|
|
|
24d93b |
u32 encryptionType:8;
|
|
|
24d93b |
@@ -745,6 +830,7 @@ struct IO_REQUEST_INFO {
|
|
|
24d93b |
u64 start_row;
|
|
|
24d93b |
u8 span_arm; /* span[7:5], arm[4:0] */
|
|
|
24d93b |
u8 pd_after_lb;
|
|
|
24d93b |
+ bool ra_capable;
|
|
|
24d93b |
};
|
|
|
24d93b |
|
|
|
24d93b |
struct MR_LD_TARGET_SYNC {
|
|
|
24d93b |
@@ -930,6 +1016,30 @@ struct MR_PD_CFG_SEQ_NUM_SYNC {
|
|
|
24d93b |
struct MR_PD_CFG_SEQ seq[1];
|
|
|
24d93b |
} __packed;
|
|
|
24d93b |
|
|
|
24d93b |
+/* stream detection */
|
|
|
24d93b |
+struct STREAM_DETECT {
|
|
|
24d93b |
+ u64 next_seq_lba; /* next LBA to match sequential access */
|
|
|
24d93b |
+ struct megasas_cmd_fusion *first_cmd_fusion; /* first cmd in group */
|
|
|
24d93b |
+ struct megasas_cmd_fusion *last_cmd_fusion; /* last cmd in group */
|
|
|
24d93b |
+ u32 count_cmds_in_stream; /* count of host commands in this stream */
|
|
|
24d93b |
+ u16 num_sges_in_group; /* total number of SGEs in grouped IOs */
|
|
|
24d93b |
+ u8 is_read; /* SCSI OpCode for this stream */
|
|
|
24d93b |
+ u8 group_depth; /* total number of host commands in group */
|
|
|
24d93b |
+ /* TRUE if cannot add any more commands to this group */
|
|
|
24d93b |
+ bool group_flush;
|
|
|
24d93b |
+ u8 reserved[7]; /* pad to 64-bit alignment */
|
|
|
24d93b |
+};
|
|
|
24d93b |
+
|
|
|
24d93b |
+struct LD_STREAM_DETECT {
|
|
|
24d93b |
+ bool write_back; /* TRUE if WB, FALSE if WT */
|
|
|
24d93b |
+ bool fp_write_enabled;
|
|
|
24d93b |
+ bool members_ssds;
|
|
|
24d93b |
+ bool fp_cache_bypass_capable;
|
|
|
24d93b |
+ u32 mru_bit_map; /* bitmap used to track MRU and LRU stream indicies */
|
|
|
24d93b |
+ /* this is the array of stream detect structures (one per stream) */
|
|
|
24d93b |
+ struct STREAM_DETECT stream_track[MAX_STREAMS_TRACKED];
|
|
|
24d93b |
+};
|
|
|
24d93b |
+
|
|
|
24d93b |
struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
|
|
|
24d93b |
u64 RDPQBaseAddress;
|
|
|
24d93b |
u32 Reserved1;
|
|
|
24d93b |
@@ -983,6 +1093,7 @@ struct fusion_context {
|
|
|
24d93b |
struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
|
|
|
24d93b |
LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
|
|
|
24d93b |
u8 adapter_type;
|
|
|
24d93b |
+ struct LD_STREAM_DETECT **stream_detect_by_ld;
|
|
|
24d93b |
};
|
|
|
24d93b |
|
|
|
24d93b |
union desc_value {
|
|
|
24d93b |
--
|
|
|
24d93b |
1.8.3.1
|
|
|
24d93b |
|