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>
This commit is contained in:
parent
f4fc209326
commit
15dd03811d
|
@ -733,7 +733,6 @@ struct megasas_pd_list {
|
|||
u16 tid;
|
||||
u8 driveType;
|
||||
u8 driveState;
|
||||
u8 interface;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -1530,8 +1529,8 @@ struct megasas_register_set {
|
|||
u32 outbound_scratch_pad ; /*00B0h*/
|
||||
u32 outbound_scratch_pad_2; /*00B4h*/
|
||||
u32 outbound_scratch_pad_3; /*00B8h*/
|
||||
u32 outbound_scratch_pad_4; /*00BCh*/
|
||||
|
||||
u32 reserved_4; /*00BCh*/
|
||||
|
||||
u32 inbound_low_queue_port ; /*00C0h*/
|
||||
|
||||
|
@ -1864,6 +1863,7 @@ union megasas_frame {
|
|||
struct MR_PRIV_DEVICE {
|
||||
bool is_tm_capable;
|
||||
bool tm_busy;
|
||||
u8 interface_type;
|
||||
};
|
||||
struct megasas_cmd;
|
||||
|
||||
|
@ -2055,17 +2055,24 @@ struct MR_DRV_SYSTEM_INFO {
|
|||
};
|
||||
|
||||
enum MR_PD_TYPE {
|
||||
UNKNOWN_DRIVE = 0,
|
||||
PARALLEL_SCSI = 1,
|
||||
SAS_PD = 2,
|
||||
SATA_PD = 3,
|
||||
FC_PD = 4,
|
||||
UNKNOWN_DRIVE = 0,
|
||||
PARALLEL_SCSI = 1,
|
||||
SAS_PD = 2,
|
||||
SATA_PD = 3,
|
||||
FC_PD = 4,
|
||||
NVME_PD = 5,
|
||||
};
|
||||
|
||||
/* JBOD Queue depth definitions */
|
||||
#define MEGASAS_SATA_QD 32
|
||||
#define MEGASAS_SAS_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 {
|
||||
|
||||
|
@ -2209,6 +2216,7 @@ struct megasas_instance {
|
|||
bool is_ventura;
|
||||
bool msix_combined;
|
||||
u16 max_raid_mapsize;
|
||||
u32 nvme_page_size;
|
||||
};
|
||||
struct MR_LD_VF_MAP {
|
||||
u32 size;
|
||||
|
@ -2428,6 +2436,7 @@ int megasas_get_ctrl_info(struct megasas_instance *instance);
|
|||
/* PD sequence */
|
||||
int
|
||||
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,
|
||||
u8 crash_buf_state);
|
||||
void megasas_free_host_crash_buffer(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_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 = (struct megasas_instance *)sdev->host->hostdata;
|
||||
mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
|
||||
MR_DEFAULT_NVME_PAGE_SIZE);
|
||||
|
||||
blk_queue_max_hw_sectors(sdev->request_queue, (max_io_size / 512));
|
||||
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, sdev->request_queue);
|
||||
blk_queue_virt_boundary(sdev->request_queue, mr_nvme_pg_size - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
instance = megasas_lookup_instance(sdev->host->host_no);
|
||||
mr_device_priv_data = sdev->hostdata;
|
||||
interface_type = mr_device_priv_data->interface_type;
|
||||
|
||||
if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
|
||||
pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
|
||||
/*
|
||||
* The RAID firmware may require extended timeouts.
|
||||
*/
|
||||
blk_queue_rq_timeout(sdev->request_queue, scmd_timeout * HZ);
|
||||
|
||||
if (instance->pd_info) {
|
||||
mutex_lock(&instance->hba_mutex);
|
||||
ret = megasas_get_pd_info(instance, pd_index);
|
||||
mutex_unlock(&instance->hba_mutex);
|
||||
}
|
||||
target_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
|
||||
|
||||
if (ret != DCMD_SUCCESS)
|
||||
return;
|
||||
|
||||
if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
|
||||
|
||||
switch (instance->pd_list[pd_index].interface) {
|
||||
case SAS_PD:
|
||||
scsi_change_queue_depth(sdev, MEGASAS_SAS_QD);
|
||||
break;
|
||||
|
||||
case SATA_PD:
|
||||
scsi_change_queue_depth(sdev, MEGASAS_SATA_QD);
|
||||
break;
|
||||
|
||||
default:
|
||||
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)
|
|||
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))
|
||||
|
|
|
@ -376,7 +376,8 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
|
|||
|
||||
fusion->sg_dma_pool =
|
||||
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 */
|
||||
fusion->sense_dma_pool =
|
||||
pci_pool_create("mr_sense", instance->pdev,
|
||||
|
@ -823,6 +824,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
|
|||
MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE : 0;
|
||||
IOCInitMessage->SystemRequestFrameBaseAddress = cpu_to_le64(fusion->io_request_frames_phys);
|
||||
IOCInitMessage->HostMSIxVectors = instance->msix_vectors;
|
||||
IOCInitMessage->HostPageSize = MR_DEFAULT_NVME_PAGE_SHIFT;
|
||||
init_frame = (struct megasas_init_frame *)cmd->frame;
|
||||
memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
|
||||
|
||||
|
@ -3935,7 +3937,7 @@ transition_to_ready:
|
|||
megasas_setup_jbod_map(instance);
|
||||
|
||||
shost_for_each_device(sdev, shost)
|
||||
megasas_update_sdev_properties(sdev);
|
||||
megasas_set_dynamic_target_properties(sdev);
|
||||
|
||||
/* reset stream detection array */
|
||||
if (instance->is_ventura) {
|
||||
|
|
|
@ -657,7 +657,7 @@ struct MPI2_IOC_INIT_REQUEST {
|
|||
__le16 HeaderVersion; /* 0x0E */
|
||||
u32 Reserved5; /* 0x10 */
|
||||
__le16 Reserved6; /* 0x14 */
|
||||
u8 Reserved7; /* 0x16 */
|
||||
u8 HostPageSize; /* 0x16 */
|
||||
u8 HostMSIxVectors; /* 0x17 */
|
||||
__le16 Reserved8; /* 0x18 */
|
||||
__le16 SystemRequestFrameSize; /* 0x1A */
|
||||
|
|
Loading…
Reference in New Issue