Commit 15dd0381 authored by Shivasharan S's avatar Shivasharan S Committed by Martin K. Petersen

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: default avatarShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f4fc2093
...@@ -733,7 +733,6 @@ struct megasas_pd_list { ...@@ -733,7 +733,6 @@ struct megasas_pd_list {
u16 tid; u16 tid;
u8 driveType; u8 driveType;
u8 driveState; u8 driveState;
u8 interface;
} __packed; } __packed;
/* /*
...@@ -1530,8 +1529,8 @@ struct megasas_register_set { ...@@ -1530,8 +1529,8 @@ struct megasas_register_set {
u32 outbound_scratch_pad ; /*00B0h*/ u32 outbound_scratch_pad ; /*00B0h*/
u32 outbound_scratch_pad_2; /*00B4h*/ u32 outbound_scratch_pad_2; /*00B4h*/
u32 outbound_scratch_pad_3; /*00B8h*/ u32 outbound_scratch_pad_3; /*00B8h*/
u32 outbound_scratch_pad_4; /*00BCh*/
u32 reserved_4; /*00BCh*/
u32 inbound_low_queue_port ; /*00C0h*/ u32 inbound_low_queue_port ; /*00C0h*/
...@@ -1864,6 +1863,7 @@ union megasas_frame { ...@@ -1864,6 +1863,7 @@ union megasas_frame {
struct MR_PRIV_DEVICE { struct MR_PRIV_DEVICE {
bool is_tm_capable; bool is_tm_capable;
bool tm_busy; bool tm_busy;
u8 interface_type;
}; };
struct megasas_cmd; struct megasas_cmd;
...@@ -2055,17 +2055,24 @@ struct MR_DRV_SYSTEM_INFO { ...@@ -2055,17 +2055,24 @@ struct MR_DRV_SYSTEM_INFO {
}; };
enum MR_PD_TYPE { enum MR_PD_TYPE {
UNKNOWN_DRIVE = 0, UNKNOWN_DRIVE = 0,
PARALLEL_SCSI = 1, PARALLEL_SCSI = 1,
SAS_PD = 2, SAS_PD = 2,
SATA_PD = 3, SATA_PD = 3,
FC_PD = 4, FC_PD = 4,
NVME_PD = 5,
}; };
/* JBOD Queue depth definitions */ /* JBOD Queue depth definitions */
#define MEGASAS_SATA_QD 32 #define MEGASAS_SATA_QD 32
#define MEGASAS_SAS_QD 64 #define MEGASAS_SAS_QD 64
#define MEGASAS_DEFAULT_PD_QD 64 #define MEGASAS_DEFAULT_PD_QD 64
#define MEGASAS_NVME_QD 32
#define MR_DEFAULT_NVME_PAGE_SIZE 4096
#define MR_DEFAULT_NVME_PAGE_SHIFT 12
#define MR_DEFAULT_NVME_MDTS_KB 128
#define MR_NVME_PAGE_SIZE_MASK 0x000000FF
struct megasas_instance { struct megasas_instance {
...@@ -2209,6 +2216,7 @@ struct megasas_instance { ...@@ -2209,6 +2216,7 @@ struct megasas_instance {
bool is_ventura; bool is_ventura;
bool msix_combined; bool msix_combined;
u16 max_raid_mapsize; u16 max_raid_mapsize;
u32 nvme_page_size;
}; };
struct MR_LD_VF_MAP { struct MR_LD_VF_MAP {
u32 size; u32 size;
...@@ -2428,6 +2436,7 @@ int megasas_get_ctrl_info(struct megasas_instance *instance); ...@@ -2428,6 +2436,7 @@ int megasas_get_ctrl_info(struct megasas_instance *instance);
/* PD sequence */ /* PD sequence */
int int
megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend); megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend);
void megasas_set_dynamic_target_properties(struct scsi_device *sdev);
int megasas_set_crash_dump_params(struct megasas_instance *instance, int megasas_set_crash_dump_params(struct megasas_instance *instance,
u8 crash_buf_state); u8 crash_buf_state);
void megasas_free_host_crash_buffer(struct megasas_instance *instance); void megasas_free_host_crash_buffer(struct megasas_instance *instance);
......
...@@ -116,8 +116,8 @@ static int megasas_ld_list_query(struct megasas_instance *instance, ...@@ -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_issue_init_mfi(struct megasas_instance *instance);
static int megasas_register_aen(struct megasas_instance *instance, static int megasas_register_aen(struct megasas_instance *instance,
u32 seq_num, u32 class_locale_word); u32 seq_num, u32 class_locale_word);
static int static void megasas_get_pd_info(struct megasas_instance *instance,
megasas_get_pd_info(struct megasas_instance *instance, u16 device_id); struct scsi_device *sdev);
/* /*
* PCI ID table for all supported controllers * PCI ID table for all supported controllers
*/ */
...@@ -1738,16 +1738,21 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no) ...@@ -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 * @sdev: OS provided scsi device
* *
* Returns void * 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; u16 pd_index = 0, ld;
u32 device_id, ld; u32 device_id;
struct megasas_instance *instance; struct megasas_instance *instance;
struct fusion_context *fusion; struct fusion_context *fusion;
struct MR_PRIV_DEVICE *mr_device_priv_data; struct MR_PRIV_DEVICE *mr_device_priv_data;
...@@ -1772,57 +1777,102 @@ void megasas_update_sdev_properties(struct scsi_device *sdev) ...@@ -1772,57 +1777,102 @@ void megasas_update_sdev_properties(struct scsi_device *sdev)
raid = MR_LdRaidGet(ld, local_map_ptr); raid = MR_LdRaidGet(ld, local_map_ptr);
if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER)
blk_queue_update_dma_alignment(sdev->request_queue, blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
0x7);
mr_device_priv_data->is_tm_capable = mr_device_priv_data->is_tm_capable =
raid->capability.tmCapable; raid->capability.tmCapable;
} else if (instance->use_seqnum_jbod_fp) { } else if (instance->use_seqnum_jbod_fp) {
pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
sdev->id; sdev->id;
pd_sync = (void *)fusion->pd_seq_sync pd_sync = (void *)fusion->pd_seq_sync
[(instance->pd_seq_map_id - 1) & 1]; [(instance->pd_seq_map_id - 1) & 1];
mr_device_priv_data->is_tm_capable = 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; 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) { blk_queue_max_hw_sectors(sdev->request_queue, (max_io_size / 512));
pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
if (instance->pd_info) { queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, sdev->request_queue);
mutex_lock(&instance->hba_mutex); blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1);
ret = megasas_get_pd_info(instance, pd_index); }
mutex_unlock(&instance->hba_mutex);
}
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) { instance = megasas_lookup_instance(sdev->host->host_no);
case SAS_PD: mr_device_priv_data = sdev->hostdata;
scsi_change_queue_depth(sdev, MEGASAS_SAS_QD); interface_type = mr_device_priv_data->interface_type;
break;
case SATA_PD: /*
scsi_change_queue_depth(sdev, MEGASAS_SATA_QD); * The RAID firmware may require extended timeouts.
break; */
blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ);
default: target_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
scsi_change_queue_depth(sdev, MEGASAS_DEFAULT_PD_QD);
} 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) ...@@ -1841,14 +1891,18 @@ static int megasas_slave_configure(struct scsi_device *sdev)
return -ENXIO; return -ENXIO;
} }
} }
megasas_set_device_queue_depth(sdev);
megasas_update_sdev_properties(sdev);
/* mutex_lock(&instance->hba_mutex);
* The RAID firmware may require extended timeouts. /* Send DCMD to Firmware and cache the information */
*/ if ((instance->pd_info) && !MEGASAS_IS_LOGICAL(sdev))
blk_queue_rq_timeout(sdev->request_queue, megasas_get_pd_info(instance, sdev);
scmd_timeout * HZ);
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; return 0;
} }
...@@ -3986,18 +4040,22 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) { ...@@ -3986,18 +4040,22 @@ dcmd_timeout_ocr_possible(struct megasas_instance *instance) {
return INITIATE_OCR; return INITIATE_OCR;
} }
static int static void
megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev)
{ {
int ret; int ret;
struct megasas_cmd *cmd; struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd; 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); cmd = megasas_get_cmd(instance);
if (!cmd) { if (!cmd) {
dev_err(&instance->pdev->dev, "Failed to get cmd %s\n", __func__); dev_err(&instance->pdev->dev, "Failed to get cmd %s\n", __func__);
return -ENOMEM; return;
} }
dcmd = &cmd->frame->dcmd; dcmd = &cmd->frame->dcmd;
...@@ -4024,7 +4082,9 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) ...@@ -4024,7 +4082,9 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id)
switch (ret) { switch (ret) {
case DCMD_SUCCESS: 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; instance->pd_info->state.ddf.pdType.intf;
break; break;
...@@ -4051,7 +4111,7 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id) ...@@ -4051,7 +4111,7 @@ megasas_get_pd_info(struct megasas_instance *instance, u16 device_id)
if (ret != DCMD_TIMEOUT) if (ret != DCMD_TIMEOUT)
megasas_return_cmd(instance, cmd); megasas_return_cmd(instance, cmd);
return ret; return;
} }
/* /*
* megasas_get_pd_list_info - Returns FW's pd_list structure * megasas_get_pd_list_info - Returns FW's pd_list structure
...@@ -5020,8 +5080,8 @@ megasas_setup_jbod_map(struct megasas_instance *instance) ...@@ -5020,8 +5080,8 @@ megasas_setup_jbod_map(struct megasas_instance *instance)
static int megasas_init_fw(struct megasas_instance *instance) static int megasas_init_fw(struct megasas_instance *instance)
{ {
u32 max_sectors_1; u32 max_sectors_1;
u32 max_sectors_2; u32 max_sectors_2, tmp_sectors, msix_enable;
u32 tmp_sectors, msix_enable, scratch_pad_2, scratch_pad_3; u32 scratch_pad_2, scratch_pad_3, scratch_pad_4;
resource_size_t base_addr; resource_size_t base_addr;
struct megasas_register_set __iomem *reg_set; struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info = NULL; struct megasas_ctrl_info *ctrl_info = NULL;
...@@ -5202,6 +5262,18 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -5202,6 +5262,18 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (instance->instancet->init_adapter(instance)) if (instance->instancet->init_adapter(instance))
goto fail_init_adapter; 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 ? if (instance->msix_vectors ?
megasas_setup_irqs_msix(instance, 1) : megasas_setup_irqs_msix(instance, 1) :
megasas_setup_irqs_ioapic(instance)) megasas_setup_irqs_ioapic(instance))
......
...@@ -376,7 +376,8 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) ...@@ -376,7 +376,8 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
fusion->sg_dma_pool = fusion->sg_dma_pool =
pci_pool_create("mr_sg", instance->pdev, pci_pool_create("mr_sg", instance->pdev,
instance->max_chain_frame_sz, 4, 0); instance->max_chain_frame_sz,
MR_DEFAULT_NVME_PAGE_SIZE, 0);
/* SCSI_SENSE_BUFFERSIZE = 96 bytes */ /* SCSI_SENSE_BUFFERSIZE = 96 bytes */
fusion->sense_dma_pool = fusion->sense_dma_pool =
pci_pool_create("mr_sense", instance->pdev, pci_pool_create("mr_sense", instance->pdev,
...@@ -823,6 +824,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -823,6 +824,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0; MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys); IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
IOCInitMessage->HostMSIxVectors = instance->msix_vectors; IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT;
init_frame = (struct megasas_init_frame *)cmd->frame; init_frame = (struct megasas_init_frame *)cmd->frame;
memset(init_frame, 0, MEGAMFI_FRAME_SIZE); memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
...@@ -3935,7 +3937,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) ...@@ -3935,7 +3937,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int reason)
megasas_setup_jbod_map(instance); megasas_setup_jbod_map(instance);
shost_for_each_device(sdev, shost) shost_for_each_device(sdev, shost)
megasas_update_sdev_properties(sdev); megasas_set_dynamic_target_properties(sdev);
/* reset stream detection array */ /* reset stream detection array */
if (instance->is_ventura) { if (instance->is_ventura) {
......
...@@ -657,7 +657,7 @@ struct MPI2_IOC_INIT_REQUEST { ...@@ -657,7 +657,7 @@ struct MPI2_IOC_INIT_REQUEST {
__le16 HeaderVersion; /* 0x0E */ __le16 HeaderVersion; /* 0x0E */
u32 Reserved5; /* 0x10 */ u32 Reserved5; /* 0x10 */
__le16 Reserved6; /* 0x14 */ __le16 Reserved6; /* 0x14 */
u8 Reserved7; /* 0x16 */ u8 HostPageSize; /* 0x16 */
u8 HostMSIxVectors; /* 0x17 */ u8 HostMSIxVectors; /* 0x17 */
__le16 Reserved8; /* 0x18 */ __le16 Reserved8; /* 0x18 */
__le16 SystemRequestFrameSize; /* 0x1A */ __le16 SystemRequestFrameSize; /* 0x1A */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment