mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00:00
scsi: mpt3sas: Use firmware recommended queue depth
Currently, the mpt3sas driver sets the default queue depth based on the physical interface of the attached device: - SAS : 254 - SATA: 32 - NVMe: 128 The IOC firmware provides a recommended queue depth for each device through SAS IO Unit Page1 for SAS/SATA and PCIe IO Unit Page 1 for NVMe devices. If the host sets the queue depth greater than the firmware recommended value, then the IOC places the I/Os above the recommended queue depth in an internal pending queue. This consumes outstanding host-credit/resources, thereby leading to potential starvation of other devices. To avoid this, use the device depth recommended by the IOC firmware. Link: https://lore.kernel.org/r/20210809072639.21228-2-suganath-prabu.subramani@broadcom.com Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
44f88ef3c9
commit
787f2448c2
5 changed files with 165 additions and 6 deletions
|
@ -5365,6 +5365,73 @@ _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc)
|
|||
&ioc->diag_trigger_mpi, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_assign_fw_reported_qd - Get FW reported QD for SAS/SATA devices.
|
||||
* - On failure set default QD values.
|
||||
* @ioc : per adapter object
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*
|
||||
*/
|
||||
static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
|
||||
Mpi26PCIeIOUnitPage1_t pcie_iounit_pg1;
|
||||
int sz;
|
||||
int rc = 0;
|
||||
|
||||
ioc->max_wideport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
ioc->max_narrowport_qd = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
ioc->max_sata_qd = MPT3SAS_SATA_QUEUE_DEPTH;
|
||||
ioc->max_nvme_qd = MPT3SAS_NVME_QUEUE_DEPTH;
|
||||
if (!ioc->is_gen35_ioc)
|
||||
goto out;
|
||||
/* sas iounit page 1 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData);
|
||||
sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_iounit_pg1) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
return rc;
|
||||
}
|
||||
rc = mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
|
||||
sas_iounit_pg1, sz);
|
||||
if (rc) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
}
|
||||
ioc->max_wideport_qd =
|
||||
(le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth)) ?
|
||||
le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth) :
|
||||
MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
ioc->max_narrowport_qd =
|
||||
(le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth)) ?
|
||||
le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth) :
|
||||
MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
ioc->max_sata_qd = (sas_iounit_pg1->SATAMaxQDepth) ?
|
||||
sas_iounit_pg1->SATAMaxQDepth : MPT3SAS_SATA_QUEUE_DEPTH;
|
||||
/* pcie iounit page 1 */
|
||||
rc = mpt3sas_config_get_pcie_iounit_pg1(ioc, &mpi_reply,
|
||||
&pcie_iounit_pg1, sizeof(Mpi26PCIeIOUnitPage1_t));
|
||||
if (rc) {
|
||||
pr_err("%s: failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
}
|
||||
ioc->max_nvme_qd = (le16_to_cpu(pcie_iounit_pg1.NVMeMaxQueueDepth)) ?
|
||||
(le16_to_cpu(pcie_iounit_pg1.NVMeMaxQueueDepth)) :
|
||||
MPT3SAS_NVME_QUEUE_DEPTH;
|
||||
out:
|
||||
dinitprintk(ioc, pr_err(
|
||||
"MaxWidePortQD: 0x%x MaxNarrowPortQD: 0x%x MaxSataQD: 0x%x MaxNvmeQD: 0x%x\n",
|
||||
ioc->max_wideport_qd, ioc->max_narrowport_qd,
|
||||
ioc->max_sata_qd, ioc->max_nvme_qd));
|
||||
kfree(sas_iounit_pg1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_static_config_pages - static start of day config pages
|
||||
* @ioc: per adapter object
|
||||
|
@ -5434,6 +5501,9 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
|
|||
ioc_warn(ioc,
|
||||
"TimeSync Interval in Manuf page-11 is not enabled. Periodic Time-Sync will be disabled\n");
|
||||
}
|
||||
rc = _base_assign_fw_reported_qd(ioc);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
|
|
@ -576,6 +576,7 @@ struct _sas_device {
|
|||
u8 is_chassis_slot_valid;
|
||||
u8 connector_name[5];
|
||||
struct kref refcount;
|
||||
u8 port_type;
|
||||
struct hba_port *port;
|
||||
struct sas_rphy *rphy;
|
||||
};
|
||||
|
@ -1443,6 +1444,10 @@ struct MPT3SAS_ADAPTER {
|
|||
u8 tm_custom_handling;
|
||||
u8 nvme_abort_timeout;
|
||||
u16 max_shutdown_latency;
|
||||
u16 max_wideport_qd;
|
||||
u16 max_narrowport_qd;
|
||||
u16 max_nvme_qd;
|
||||
u8 max_sata_qd;
|
||||
|
||||
/* static config pages */
|
||||
struct mpt3sas_facts facts;
|
||||
|
@ -1848,6 +1853,9 @@ int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
|
|||
int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
|
||||
u32 form, u32 handle);
|
||||
int mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
|
||||
u16 sz);
|
||||
int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
|
||||
u16 sz);
|
||||
|
|
|
@ -1168,6 +1168,43 @@ mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
|
|||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_pcie_iounit_pg1 - obtain pcie iounit page 1
|
||||
* @ioc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* @sz: size of buffer passed in config_page
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
|
||||
u16 sz)
|
||||
{
|
||||
Mpi2ConfigRequest_t mpi_request;
|
||||
int r;
|
||||
|
||||
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
|
||||
mpi_request.Function = MPI2_FUNCTION_CONFIG;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
|
||||
mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
|
||||
mpi_request.Header.PageNumber = 1;
|
||||
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
|
||||
if (r)
|
||||
goto out;
|
||||
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
r = _config_request(ioc, &mpi_request, mpi_reply,
|
||||
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
|
||||
* @ioc: per adapter object
|
||||
|
|
|
@ -3820,9 +3820,10 @@ enable_sdev_max_qd_store(struct device *cdev,
|
|||
}
|
||||
} else if (sas_target_priv_data->flags &
|
||||
MPT_TARGET_FLAGS_PCIE_DEVICE)
|
||||
qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
|
||||
qdepth = ioc->max_nvme_qd;
|
||||
else
|
||||
qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
qdepth = (sas_target_priv_data->sas_dev->port_type > 1) ?
|
||||
ioc->max_wideport_qd : ioc->max_narrowport_qd;
|
||||
|
||||
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
|
|
|
@ -1803,7 +1803,7 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
|||
* limit max device queue for SATA to 32 if enable_sdev_max_qd
|
||||
* is disabled.
|
||||
*/
|
||||
if (ioc->enable_sdev_max_qd)
|
||||
if (ioc->enable_sdev_max_qd || ioc->is_gen35_ioc)
|
||||
goto not_sata;
|
||||
|
||||
sas_device_priv_data = sdev->hostdata;
|
||||
|
@ -2657,7 +2657,7 @@ scsih_slave_configure(struct scsi_device *sdev)
|
|||
return 1;
|
||||
}
|
||||
|
||||
qdepth = MPT3SAS_NVME_QUEUE_DEPTH;
|
||||
qdepth = ioc->max_nvme_qd;
|
||||
ds = "NVMe";
|
||||
sdev_printk(KERN_INFO, sdev,
|
||||
"%s: handle(0x%04x), wwid(0x%016llx), port(%d)\n",
|
||||
|
@ -2709,7 +2709,8 @@ scsih_slave_configure(struct scsi_device *sdev)
|
|||
sas_device->volume_handle = volume_handle;
|
||||
sas_device->volume_wwid = volume_wwid;
|
||||
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
|
||||
qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
|
||||
qdepth = (sas_device->port_type > 1) ?
|
||||
ioc->max_wideport_qd : ioc->max_narrowport_qd;
|
||||
ssp_target = 1;
|
||||
if (sas_device->device_info &
|
||||
MPI2_SAS_DEVICE_INFO_SEP) {
|
||||
|
@ -2721,7 +2722,7 @@ scsih_slave_configure(struct scsi_device *sdev)
|
|||
} else
|
||||
ds = "SSP";
|
||||
} else {
|
||||
qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
|
||||
qdepth = ioc->max_sata_qd;
|
||||
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
|
||||
ds = "STP";
|
||||
else if (sas_device->device_info &
|
||||
|
@ -7371,6 +7372,10 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
|
|||
|
||||
/* get device name */
|
||||
sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
|
||||
sas_device->port_type = sas_device_pg0.MaxPortConnections;
|
||||
ioc_info(ioc,
|
||||
"handle(0x%0x) sas_address(0x%016llx) port_type(0x%0x)\n",
|
||||
handle, sas_device->sas_address, sas_device->port_type);
|
||||
|
||||
if (ioc->wait_for_discovery_to_complete)
|
||||
_scsih_sas_device_init_add(ioc, sas_device);
|
||||
|
@ -9603,6 +9608,42 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _scsih_update_device_qdepth - Update QD during Reset.
|
||||
* @ioc: per adapter object
|
||||
*
|
||||
*/
|
||||
static void
|
||||
_scsih_update_device_qdepth(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
struct MPT3SAS_DEVICE *sas_device_priv_data;
|
||||
struct MPT3SAS_TARGET *sas_target_priv_data;
|
||||
struct _sas_device *sas_device;
|
||||
struct scsi_device *sdev;
|
||||
u16 qdepth;
|
||||
|
||||
ioc_info(ioc, "Update devices with firmware reported queue depth\n");
|
||||
shost_for_each_device(sdev, ioc->shost) {
|
||||
sas_device_priv_data = sdev->hostdata;
|
||||
if (sas_device_priv_data && sas_device_priv_data->sas_target) {
|
||||
sas_target_priv_data = sas_device_priv_data->sas_target;
|
||||
sas_device = sas_device_priv_data->sas_target->sas_dev;
|
||||
if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_PCIE_DEVICE)
|
||||
qdepth = ioc->max_nvme_qd;
|
||||
else if (sas_device &&
|
||||
sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
|
||||
qdepth = (sas_device->port_type > 1) ?
|
||||
ioc->max_wideport_qd : ioc->max_narrowport_qd;
|
||||
else if (sas_device &&
|
||||
sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
|
||||
qdepth = ioc->max_sata_qd;
|
||||
else
|
||||
continue;
|
||||
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _scsih_mark_responding_sas_device - mark a sas_devices as responding
|
||||
* @ioc: per adapter object
|
||||
|
@ -10654,6 +10695,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
|
|||
_scsih_remove_unresponding_devices(ioc);
|
||||
_scsih_del_dirty_vphy(ioc);
|
||||
_scsih_del_dirty_port_entries(ioc);
|
||||
if (ioc->is_gen35_ioc)
|
||||
_scsih_update_device_qdepth(ioc);
|
||||
_scsih_scan_for_devices_after_reset(ioc);
|
||||
/*
|
||||
* If diag reset has occurred during the driver load
|
||||
|
|
Loading…
Reference in a new issue