Skip to content

Commit 6a35449

Browse files
Ranjan Kumargregkh
authored andcommitted
scsi: mpi3mr: Avoid reply queue full condition
[ Upstream commit f08b24d ] 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>
1 parent b1e0b4f commit 6a35449

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ extern atomic64_t event_counter;
8181

8282
/* Admin queue management definitions */
8383
#define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K)
84-
#define MPI3MR_ADMIN_REPLY_Q_SIZE (4 * MPI3MR_PAGE_SIZE_4K)
84+
#define MPI3MR_ADMIN_REPLY_Q_SIZE (8 * MPI3MR_PAGE_SIZE_4K)
8585
#define MPI3MR_ADMIN_REQ_FRAME_SZ 128
8686
#define MPI3MR_ADMIN_REPLY_FRAME_SZ 16
8787

8888
/* Operational queue management definitions */
8989
#define MPI3MR_OP_REQ_Q_QD 512
9090
#define MPI3MR_OP_REP_Q_QD 1024
91+
#define MPI3MR_OP_REP_Q_QD2K 2048
9192
#define MPI3MR_OP_REP_Q_QD4K 4096
9293
#define MPI3MR_OP_REQ_Q_SEG_SIZE 4096
9394
#define MPI3MR_OP_REP_Q_SEG_SIZE 4096
@@ -329,6 +330,7 @@ enum mpi3mr_reset_reason {
329330
#define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28
330331
#define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20
331332

333+
332334
/* Queue type definitions */
333335
enum queue_type {
334336
MPI3MR_DEFAULT_QUEUE = 0,
@@ -388,6 +390,7 @@ struct mpi3mr_ioc_facts {
388390
u16 max_msix_vectors;
389391
u8 personality;
390392
u8 dma_mask;
393+
bool max_req_limit;
391394
u8 protocol_flags;
392395
u8 sge_mod_mask;
393396
u8 sge_mod_value;
@@ -457,6 +460,8 @@ struct op_req_qinfo {
457460
* @enable_irq_poll: Flag to indicate polling is enabled
458461
* @in_use: Queue is handled by poll/ISR
459462
* @qtype: Type of queue (types defined in enum queue_type)
463+
* @qfull_watermark: Watermark defined in reply queue to avoid
464+
* reply queue full
460465
*/
461466
struct op_reply_qinfo {
462467
u16 ci;
@@ -472,6 +477,7 @@ struct op_reply_qinfo {
472477
bool enable_irq_poll;
473478
atomic_t in_use;
474479
enum queue_type qtype;
480+
u16 qfull_watermark;
475481
};
476482

477483
/**
@@ -1154,6 +1160,8 @@ struct scmd_priv {
11541160
* @snapdump_trigger_active: Snapdump trigger active flag
11551161
* @pci_err_recovery: PCI error recovery in progress
11561162
* @block_on_pci_err: Block IO during PCI error recovery
1163+
* @reply_qfull_count: Occurences of reply queue full avoidance kicking-in
1164+
* @prevent_reply_qfull: Enable reply queue prevention
11571165
*/
11581166
struct mpi3mr_ioc {
11591167
struct list_head list;
@@ -1352,6 +1360,8 @@ struct mpi3mr_ioc {
13521360
bool fw_release_trigger_active;
13531361
bool pci_err_recovery;
13541362
bool block_on_pci_err;
1363+
atomic_t reply_qfull_count;
1364+
bool prevent_reply_qfull;
13551365
};
13561366

13571367
/**

drivers/scsi/mpi3mr/mpi3mr_app.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3060,6 +3060,29 @@ reply_queue_count_show(struct device *dev, struct device_attribute *attr,
30603060

30613061
static DEVICE_ATTR_RO(reply_queue_count);
30623062

3063+
/**
3064+
* reply_qfull_count_show - Show reply qfull count
3065+
* @dev: class device
3066+
* @attr: Device attributes
3067+
* @buf: Buffer to copy
3068+
*
3069+
* Retrieves the current value of the reply_qfull_count from the mrioc structure and
3070+
* formats it as a string for display.
3071+
*
3072+
* Return: sysfs_emit() return
3073+
*/
3074+
static ssize_t
3075+
reply_qfull_count_show(struct device *dev, struct device_attribute *attr,
3076+
char *buf)
3077+
{
3078+
struct Scsi_Host *shost = class_to_shost(dev);
3079+
struct mpi3mr_ioc *mrioc = shost_priv(shost);
3080+
3081+
return sysfs_emit(buf, "%u\n", atomic_read(&mrioc->reply_qfull_count));
3082+
}
3083+
3084+
static DEVICE_ATTR_RO(reply_qfull_count);
3085+
30633086
/**
30643087
* logging_level_show - Show controller debug level
30653088
* @dev: class device
@@ -3152,6 +3175,7 @@ static struct attribute *mpi3mr_host_attrs[] = {
31523175
&dev_attr_fw_queue_depth.attr,
31533176
&dev_attr_op_req_q_count.attr,
31543177
&dev_attr_reply_queue_count.attr,
3178+
&dev_attr_reply_qfull_count.attr,
31553179
&dev_attr_logging_level.attr,
31563180
&dev_attr_adp_state.attr,
31573181
NULL,

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,15 +2104,22 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
21042104
}
21052105

21062106
reply_qid = qidx + 1;
2107-
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
2108-
if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) &&
2109-
!mrioc->pdev->revision)
2110-
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
2107+
2108+
if (mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) {
2109+
if (mrioc->pdev->revision)
2110+
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
2111+
else
2112+
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K;
2113+
} else
2114+
op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD2K;
2115+
21112116
op_reply_q->ci = 0;
21122117
op_reply_q->ephase = 1;
21132118
atomic_set(&op_reply_q->pend_ios, 0);
21142119
atomic_set(&op_reply_q->in_use, 0);
21152120
op_reply_q->enable_irq_poll = false;
2121+
op_reply_q->qfull_watermark =
2122+
op_reply_q->num_replies - (MPI3MR_THRESHOLD_REPLY_COUNT * 2);
21162123

21172124
if (!op_reply_q->q_segments) {
21182125
retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx);
@@ -2416,8 +2423,10 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
24162423
void *segment_base_addr;
24172424
u16 req_sz = mrioc->facts.op_req_sz;
24182425
struct segments *segments = op_req_q->q_segments;
2426+
struct op_reply_qinfo *op_reply_q = NULL;
24192427

24202428
reply_qidx = op_req_q->reply_qid - 1;
2429+
op_reply_q = mrioc->op_reply_qinfo + reply_qidx;
24212430

24222431
if (mrioc->unrecoverable)
24232432
return -EFAULT;
@@ -2448,6 +2457,15 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
24482457
goto out;
24492458
}
24502459

2460+
/* Reply queue is nearing to get full, push back IOs to SML */
2461+
if ((mrioc->prevent_reply_qfull == true) &&
2462+
(atomic_read(&op_reply_q->pend_ios) >
2463+
(op_reply_q->qfull_watermark))) {
2464+
atomic_inc(&mrioc->reply_qfull_count);
2465+
retval = -EAGAIN;
2466+
goto out;
2467+
}
2468+
24512469
segment_base_addr = segments[pi / op_req_q->segment_qd].segment;
24522470
req_entry = (u8 *)segment_base_addr +
24532471
((pi % op_req_q->segment_qd) * req_sz);
@@ -3091,6 +3109,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
30913109
mrioc->facts.dma_mask = (facts_flags &
30923110
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
30933111
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
3112+
mrioc->facts.dma_mask = (facts_flags &
3113+
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
3114+
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
30943115
mrioc->facts.protocol_flags = facts_data->protocol_flags;
30953116
mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
30963117
mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
@@ -4214,6 +4235,9 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
42144235
mrioc->shost->transportt = mpi3mr_transport_template;
42154236
}
42164237

4238+
if (mrioc->facts.max_req_limit)
4239+
mrioc->prevent_reply_qfull = true;
4240+
42174241
mrioc->reply_sz = mrioc->facts.reply_sz;
42184242

42194243
retval = mpi3mr_check_reset_dma_mask(mrioc);

0 commit comments

Comments
 (0)