scsi: mpi3mr: Avoid reply queue full condition
[ Upstream commit f08b24d82749117ce779cc66689e8594341130d3 ] To avoid reply queue full condition, update the driver to check IOCFacts capabilities for qfull. Update the operational reply queue's Consumer Index after processing 100 replies. If pending I/Os on a reply queue exceeds a threshold (reply_queue_depth - 200), then return I/O back to OS to retry. Also increase default admin reply queue size to 2K. Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com> Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com> Link: https://lore.kernel.org/r/20250129100850.25430-2-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
b1e0b4f494
commit
6a35449df8
@@ -81,13 +81,14 @@ extern atomic64_t event_counter;
|
|||||||
|
|
||||||
/* Admin queue management definitions */
|
/* Admin queue management definitions */
|
||||||
#define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K)
|
#define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K)
|
||||||
#define MPI3MR_ADMIN_REPLY_Q_SIZE (4 * MPI3MR_PAGE_SIZE_4K)
|
#define MPI3MR_ADMIN_REPLY_Q_SIZE (8 * MPI3MR_PAGE_SIZE_4K)
|
||||||
#define MPI3MR_ADMIN_REQ_FRAME_SZ 128
|
#define MPI3MR_ADMIN_REQ_FRAME_SZ 128
|
||||||
#define MPI3MR_ADMIN_REPLY_FRAME_SZ 16
|
#define MPI3MR_ADMIN_REPLY_FRAME_SZ 16
|
||||||
|
|
||||||
/* Operational queue management definitions */
|
/* Operational queue management definitions */
|
||||||
#define MPI3MR_OP_REQ_Q_QD 512
|
#define MPI3MR_OP_REQ_Q_QD 512
|
||||||
#define MPI3MR_OP_REP_Q_QD 1024
|
#define MPI3MR_OP_REP_Q_QD 1024
|
||||||
|
#define MPI3MR_OP_REP_Q_QD2K 2048
|
||||||
#define MPI3MR_OP_REP_Q_QD4K 4096
|
#define MPI3MR_OP_REP_Q_QD4K 4096
|
||||||
#define MPI3MR_OP_REQ_Q_SEG_SIZE 4096
|
#define MPI3MR_OP_REQ_Q_SEG_SIZE 4096
|
||||||
#define MPI3MR_OP_REP_Q_SEG_SIZE 4096
|
#define MPI3MR_OP_REP_Q_SEG_SIZE 4096
|
||||||
@@ -329,6 +330,7 @@ enum mpi3mr_reset_reason {
|
|||||||
#define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28
|
#define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28
|
||||||
#define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20
|
#define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20
|
||||||
|
|
||||||
|
|
||||||
/* Queue type definitions */
|
/* Queue type definitions */
|
||||||
enum queue_type {
|
enum queue_type {
|
||||||
MPI3MR_DEFAULT_QUEUE = 0,
|
MPI3MR_DEFAULT_QUEUE = 0,
|
||||||
@@ -388,6 +390,7 @@ struct mpi3mr_ioc_facts {
|
|||||||
u16 max_msix_vectors;
|
u16 max_msix_vectors;
|
||||||
u8 personality;
|
u8 personality;
|
||||||
u8 dma_mask;
|
u8 dma_mask;
|
||||||
|
bool max_req_limit;
|
||||||
u8 protocol_flags;
|
u8 protocol_flags;
|
||||||
u8 sge_mod_mask;
|
u8 sge_mod_mask;
|
||||||
u8 sge_mod_value;
|
u8 sge_mod_value;
|
||||||
@@ -457,6 +460,8 @@ struct op_req_qinfo {
|
|||||||
* @enable_irq_poll: Flag to indicate polling is enabled
|
* @enable_irq_poll: Flag to indicate polling is enabled
|
||||||
* @in_use: Queue is handled by poll/ISR
|
* @in_use: Queue is handled by poll/ISR
|
||||||
* @qtype: Type of queue (types defined in enum queue_type)
|
* @qtype: Type of queue (types defined in enum queue_type)
|
||||||
|
* @qfull_watermark: Watermark defined in reply queue to avoid
|
||||||
|
* reply queue full
|
||||||
*/
|
*/
|
||||||
struct op_reply_qinfo {
|
struct op_reply_qinfo {
|
||||||
u16 ci;
|
u16 ci;
|
||||||
@@ -472,6 +477,7 @@ struct op_reply_qinfo {
|
|||||||
bool enable_irq_poll;
|
bool enable_irq_poll;
|
||||||
atomic_t in_use;
|
atomic_t in_use;
|
||||||
enum queue_type qtype;
|
enum queue_type qtype;
|
||||||
|
u16 qfull_watermark;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1154,6 +1160,8 @@ struct scmd_priv {
|
|||||||
* @snapdump_trigger_active: Snapdump trigger active flag
|
* @snapdump_trigger_active: Snapdump trigger active flag
|
||||||
* @pci_err_recovery: PCI error recovery in progress
|
* @pci_err_recovery: PCI error recovery in progress
|
||||||
* @block_on_pci_err: Block IO during PCI error recovery
|
* @block_on_pci_err: Block IO during PCI error recovery
|
||||||
|
* @reply_qfull_count: Occurences of reply queue full avoidance kicking-in
|
||||||
|
* @prevent_reply_qfull: Enable reply queue prevention
|
||||||
*/
|
*/
|
||||||
struct mpi3mr_ioc {
|
struct mpi3mr_ioc {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -1352,6 +1360,8 @@ struct mpi3mr_ioc {
|
|||||||
bool fw_release_trigger_active;
|
bool fw_release_trigger_active;
|
||||||
bool pci_err_recovery;
|
bool pci_err_recovery;
|
||||||
bool block_on_pci_err;
|
bool block_on_pci_err;
|
||||||
|
atomic_t reply_qfull_count;
|
||||||
|
bool prevent_reply_qfull;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3060,6 +3060,29 @@ reply_queue_count_show(struct device *dev, struct device_attribute *attr,
|
|||||||
|
|
||||||
static DEVICE_ATTR_RO(reply_queue_count);
|
static DEVICE_ATTR_RO(reply_queue_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reply_qfull_count_show - Show reply qfull count
|
||||||
|
* @dev: class device
|
||||||
|
* @attr: Device attributes
|
||||||
|
* @buf: Buffer to copy
|
||||||
|
*
|
||||||
|
* Retrieves the current value of the reply_qfull_count from the mrioc structure and
|
||||||
|
* formats it as a string for display.
|
||||||
|
*
|
||||||
|
* Return: sysfs_emit() return
|
||||||
|
*/
|
||||||
|
static ssize_t
|
||||||
|
reply_qfull_count_show(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct Scsi_Host *shost = class_to_shost(dev);
|
||||||
|
struct mpi3mr_ioc *mrioc = shost_priv(shost);
|
||||||
|
|
||||||
|
return sysfs_emit(buf, "%u\n", atomic_read(&mrioc->reply_qfull_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RO(reply_qfull_count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* logging_level_show - Show controller debug level
|
* logging_level_show - Show controller debug level
|
||||||
* @dev: class device
|
* @dev: class device
|
||||||
@@ -3152,6 +3175,7 @@ static struct attribute *mpi3mr_host_attrs[] = {
|
|||||||
&dev_attr_fw_queue_depth.attr,
|
&dev_attr_fw_queue_depth.attr,
|
||||||
&dev_attr_op_req_q_count.attr,
|
&dev_attr_op_req_q_count.attr,
|
||||||
&dev_attr_reply_queue_count.attr,
|
&dev_attr_reply_queue_count.attr,
|
||||||
|
&dev_attr_reply_qfull_count.attr,
|
||||||
&dev_attr_logging_level.attr,
|
&dev_attr_logging_level.attr,
|
||||||
&dev_attr_adp_state.attr,
|
&dev_attr_adp_state.attr,
|
||||||
NULL,
|
NULL,
|
||||||
|
|||||||
@@ -2104,15 +2104,22 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reply_qid = qidx + 1;
|
reply_qid = qidx + 1;
|
||||||
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
|
|
||||||
if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) &&
|
if (mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) {
|
||||||
!mrioc->pdev->revision)
|
if (mrioc->pdev->revision)
|
||||||
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
|
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
|
||||||
|
else
|
||||||
|
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
|
||||||
|
} else
|
||||||
|
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD2K;
|
||||||
|
|
||||||
op_reply_q->ci = 0;
|
op_reply_q->ci = 0;
|
||||||
op_reply_q->ephase = 1;
|
op_reply_q->ephase = 1;
|
||||||
atomic_set(&op_reply_q->pend_ios, 0);
|
atomic_set(&op_reply_q->pend_ios, 0);
|
||||||
atomic_set(&op_reply_q->in_use, 0);
|
atomic_set(&op_reply_q->in_use, 0);
|
||||||
op_reply_q->enable_irq_poll = false;
|
op_reply_q->enable_irq_poll = false;
|
||||||
|
op_reply_q->qfull_watermark =
|
||||||
|
op_reply_q->num_replies - (MPI3MR_THRESHOLD_REPLY_COUNT * 2);
|
||||||
|
|
||||||
if (!op_reply_q->q_segments) {
|
if (!op_reply_q->q_segments) {
|
||||||
retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx);
|
retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx);
|
||||||
@@ -2416,8 +2423,10 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
|
|||||||
void *segment_base_addr;
|
void *segment_base_addr;
|
||||||
u16 req_sz = mrioc->facts.op_req_sz;
|
u16 req_sz = mrioc->facts.op_req_sz;
|
||||||
struct segments *segments = op_req_q->q_segments;
|
struct segments *segments = op_req_q->q_segments;
|
||||||
|
struct op_reply_qinfo *op_reply_q = NULL;
|
||||||
|
|
||||||
reply_qidx = op_req_q->reply_qid - 1;
|
reply_qidx = op_req_q->reply_qid - 1;
|
||||||
|
op_reply_q = mrioc->op_reply_qinfo + reply_qidx;
|
||||||
|
|
||||||
if (mrioc->unrecoverable)
|
if (mrioc->unrecoverable)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@@ -2448,6 +2457,15 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reply queue is nearing to get full, push back IOs to SML */
|
||||||
|
if ((mrioc->prevent_reply_qfull == true) &&
|
||||||
|
(atomic_read(&op_reply_q->pend_ios) >
|
||||||
|
(op_reply_q->qfull_watermark))) {
|
||||||
|
atomic_inc(&mrioc->reply_qfull_count);
|
||||||
|
retval = -EAGAIN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
segment_base_addr = segments[pi / op_req_q->segment_qd].segment;
|
segment_base_addr = segments[pi / op_req_q->segment_qd].segment;
|
||||||
req_entry = (u8 *)segment_base_addr +
|
req_entry = (u8 *)segment_base_addr +
|
||||||
((pi % op_req_q->segment_qd) * req_sz);
|
((pi % op_req_q->segment_qd) * req_sz);
|
||||||
@@ -3091,6 +3109,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
|
|||||||
mrioc->facts.dma_mask = (facts_flags &
|
mrioc->facts.dma_mask = (facts_flags &
|
||||||
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
|
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
|
||||||
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
|
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
|
||||||
|
mrioc->facts.dma_mask = (facts_flags &
|
||||||
|
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
|
||||||
|
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
|
||||||
mrioc->facts.protocol_flags = facts_data->protocol_flags;
|
mrioc->facts.protocol_flags = facts_data->protocol_flags;
|
||||||
mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
|
mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
|
||||||
mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
|
mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
|
||||||
@@ -4214,6 +4235,9 @@ retry_init:
|
|||||||
mrioc->shost->transportt = mpi3mr_transport_template;
|
mrioc->shost->transportt = mpi3mr_transport_template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mrioc->facts.max_req_limit)
|
||||||
|
mrioc->prevent_reply_qfull = true;
|
||||||
|
|
||||||
mrioc->reply_sz = mrioc->facts.reply_sz;
|
mrioc->reply_sz = mrioc->facts.reply_sz;
|
||||||
|
|
||||||
retval = mpi3mr_check_reset_dma_mask(mrioc);
|
retval = mpi3mr_check_reset_dma_mask(mrioc);
|
||||||
|
|||||||
Reference in New Issue
Block a user