summaryrefslogtreecommitdiff
path: root/drivers/scsi/megaraid/megaraid_sas_base.c
diff options
context:
space:
mode:
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>2017-02-10 00:59:10 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2017-02-13 07:26:21 -0500
commit15dd03811d99dcf828f4eeb2c2b6a02ddc1201c7 (patch)
treede0ec9921f775d30a502b827a2c13a5cb1215a19 /drivers/scsi/megaraid/megaraid_sas_base.c
parentf4fc209326c79b03fecd38a6709cf08da47f15f7 (diff)
scsi: megaraid_sas: NVME Interface detection and prop settings
Adding detection logic for NVME device attached behind Ventura controller. Driver set HostPageSize in IOC_INIT frame to inform about page size for NVME devices. Firmware reports NVME page size to the driver. PD INFO DCMD provide new interface type NVME_PD. Driver set property of NVME device. Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_base.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c170
1 files changed, 121 insertions, 49 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 23fb78a631f2..f383bf2cc0a8 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -116,8 +116,8 @@ static int megasas_ld_list_query(struct megasas_instance *instance,
static int megasas_issue_init_mfi(struct megasas_instance *instance);
static int megasas_register_aen(struct megasas_instance *instance,
u32 seq_num, u32 class_locale_word);
-static int
-megasas_get_pd_info(struct megasas_instance *instance, u16 device_id);
+static void megasas_get_pd_info(struct megasas_instance *instance,
+ struct scsi_device *sdev);
/*
* PCI ID table for all supported controllers
*/
@@ -1738,16 +1738,21 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no)
}
/*
-* megasas_update_sdev_properties - Update sdev structure based on controller's FW capabilities
+* megasas_set_dynamic_target_properties -
+* Device property set by driver may not be static and it is required to be
+* updated after OCR
+*
+* set tm_capable.
+* set dma alignment (only for eedp protection enable vd).
*
* @sdev: OS provided scsi device
*
* Returns void
*/
-void megasas_update_sdev_properties(struct scsi_device *sdev)
+void megasas_set_dynamic_target_properties(struct scsi_device *sdev)
{
- u16 pd_index = 0;
- u32 device_id, ld;
+ u16 pd_index = 0, ld;
+ u32 device_id;
struct megasas_instance *instance;
struct fusion_context *fusion;
struct MR_PRIV_DEVICE *mr_device_priv_data;
@@ -1772,57 +1777,102 @@ void megasas_update_sdev_properties(struct scsi_device *sdev)
raid = MR_LdRaidGet(ld, local_map_ptr);
if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER)
- blk_queue_update_dma_alignment(sdev->request_queue,
- 0x7);
+ blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
mr_device_priv_data->is_tm_capable =
raid->capability.tmCapable;
} else if (instance->use_seqnum_jbod_fp) {
pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
- sdev->id;
+ sdev->id;
pd_sync = (void *)fusion->pd_seq_sync
[(instance->pd_seq_map_id - 1) & 1];
mr_device_priv_data->is_tm_capable =
- pd_sync->seq[pd_index].capability.tmCapable;
+ pd_sync->seq[pd_index].capability.tmCapable;
}
}
-static void megasas_set_device_queue_depth(struct scsi_device *sdev)
+/*
+ * megasas_set_nvme_device_properties -
+ * set nomerges=2
+ * set virtual page boundary = 4K (current mr_nvme_pg_size is 4K).
+ * set maximum io transfer = MDTS of NVME device provided by MR firmware.
+ *
+ * MR firmware provides value in KB. Caller of this function converts
+ * kb into bytes.
+ *
+ * e.a MDTS=5 means 2^5 * nvme page size. (In case of 4K page size,
+ * MR firmware provides value 128 as (32 * 4K) = 128K.
+ *
+ * @sdev: scsi device
+ * @max_io_size: maximum io transfer size
+ *
+ */
+static inline void
+megasas_set_nvme_device_properties(struct scsi_device *sdev, u32 max_io_size)
{
- u16 pd_index = 0;
- int ret = DCMD_FAILED;
struct megasas_instance *instance;
+ u32 mr_nvme_pg_size;
- instance = megasas_lookup_instance(sdev->host->host_no);
+ instance = (struct megasas_instance *)sdev->host->hostdata;
+ mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
+ MR_DEFAULT_NVME_PAGE_SIZE);
- if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
- pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
+ blk_queue_max_hw_sectors(sdev->request_queue, (max_io_size / 512));
- if (instance->pd_info) {
- mutex_lock(&instance->hba_mutex);
- ret = megasas_get_pd_info(instance, pd_index);
- mutex_unlock(&instance->hba_mutex);
- }
+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, sdev->request_queue);
+ blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1);
+}
- if (ret != DCMD_SUCCESS)
- return;
- if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
+/*
+ * megasas_set_static_target_properties -
+ * Device property set by driver are static and it is not required to be
+ * updated after OCR.
+ *
+ * set io timeout
+ * set device queue depth
+ * set nvme device properties. see - megasas_set_nvme_device_properties
+ *
+ * @sdev: scsi device
+ *
+ */
+static void megasas_set_static_target_properties(struct scsi_device *sdev)
+{
+ u16 target_index = 0;
+ u8 interface_type;
+ u32 device_qd = MEGASAS_DEFAULT_CMD_PER_LUN;
+ u32 max_io_size_kb = MR_DEFAULT_NVME_MDTS_KB;
+ struct megasas_instance *instance;
+ struct MR_PRIV_DEVICE *mr_device_priv_data;
- switch (instance->pd_list[pd_index].interface) {
- case SAS_PD:
- scsi_change_queue_depth(sdev, MEGASAS_SAS_QD);
- break;
+ instance = megasas_lookup_instance(sdev->host->host_no);
+ mr_device_priv_data = sdev->hostdata;
+ interface_type = mr_device_priv_data->interface_type;
- case SATA_PD:
- scsi_change_queue_depth(sdev, MEGASAS_SATA_QD);
- break;
+ /*
+ * The RAID firmware may require extended timeouts.
+ */
+ blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ);
- default:
- scsi_change_queue_depth(sdev, MEGASAS_DEFAULT_PD_QD);
- }
- }
+ target_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
+
+ switch (interface_type) {
+ case SAS_PD:
+ device_qd = MEGASAS_SAS_QD;
+ break;
+ case SATA_PD:
+ device_qd = MEGASAS_SATA_QD;
+ break;
+ case NVME_PD:
+ device_qd = MEGASAS_NVME_QD;
+ break;
}
+
+ if (instance->nvme_page_size && max_io_size_kb)
+ megasas_set_nvme_device_properties(sdev, (max_io_size_kb << 10));
+
+ scsi_change_queue_depth(sdev, device_qd);
+
}
@@ -1841,14 +1891,18 @@ static int megasas_slave_configure(struct scsi_device *sdev)
return -ENXIO;
}
}
- megasas_set_device_queue_depth(sdev);
- megasas_update_sdev_properties(sdev);
- /*
- * The RAID firmware may require extended timeouts.
- */
- blk_queue_rq_timeout(sdev->request_queue,
- scmd_timeout * HZ);
+ mutex_lock(&instance->hba_mutex);
+ /* Send DCMD to Firmware and cache the information */
+ if ((instance->pd_info) && !MEGASAS_IS_LOGICAL(sdev))
+ megasas_get_pd_info(instance, sdev);
+
+ megasas_set_static_target_properties(sdev);
+
+ mutex_unlock(&instance->hba_mutex);
+
+ /* This sdev property may change post OCR */
+ megasas_set_dynamic_target_properties(sdev);
return 0;
}
@@ -3986,18 +4040,22 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) {
return INITIATE_OCR;
}
-static int
-megasas_get_pd_info(struct megasas_instance *instance, u16 device_id)
+static void
+megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev)
{
int ret;
struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd;
+ struct MR_PRIV_DEVICE *mr_device_priv_data;
+ u16 device_id = 0;
+
+ device_id = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
cmd = megasas_get_cmd(instance);
if (!cmd) {
dev_err(&instance->pdev->dev, "Failed to get cmd %s\n", __func__);
- return -ENOMEM;
+ return;
}
dcmd = &cmd->frame->dcmd;
@@ -4024,7 +4082,9 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id)
switch (ret) {
case DCMD_SUCCESS:
- instance->pd_list[device_id].interface =
+ mr_device_priv_data = sdev->hostdata;
+ le16_to_cpus((u16 *)&instance->pd_info->state.ddf.pdType);
+ mr_device_priv_data->interface_type =
instance->pd_info->state.ddf.pdType.intf;
break;
@@ -4051,7 +4111,7 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id)
if (ret != DCMD_TIMEOUT)
megasas_return_cmd(instance, cmd);
- return ret;
+ return;
}
/*
* megasas_get_pd_list_info - Returns FW's pd_list structure
@@ -5020,8 +5080,8 @@ skip_alloc:
static int megasas_init_fw(struct megasas_instance *instance)
{
u32 max_sectors_1;
- u32 max_sectors_2;
- u32 tmp_sectors, msix_enable, scratch_pad_2, scratch_pad_3;
+ u32 max_sectors_2, tmp_sectors, msix_enable;
+ u32 scratch_pad_2, scratch_pad_3, scratch_pad_4;
resource_size_t base_addr;
struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info = NULL;
@@ -5202,6 +5262,18 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (instance->instancet->init_adapter(instance))
goto fail_init_adapter;
+ if (instance->is_ventura) {
+ scratch_pad_4 =
+ readl(&instance->reg_set->outbound_scratch_pad_4);
+ if ((scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK) >=
+ MR_DEFAULT_NVME_PAGE_SHIFT)
+ instance->nvme_page_size =
+ (1 << (scratch_pad_4 & MR_NVME_PAGE_SIZE_MASK));
+
+ dev_info(&instance->pdev->dev,
+ "NVME page size\t: (%d)\n", instance->nvme_page_size);
+ }
+
if (instance->msix_vectors ?
megasas_setup_irqs_msix(instance, 1) :
megasas_setup_irqs_ioapic(instance))