Skip to content

Commit c5758fc

Browse files
sreekanthbrcmmartinkpetersen
authored andcommitted
scsi: mpi3mr: Gracefully handle online FW update operation
Enhance driver to gracefully handle discrepancies in certain key data sizes between firmware update operations as mentioned below: - The driver displays an error message and marks the controller as unrecoverable if the firmware reports ReplyFrameSize that is greater than the current ReplyFrameSize. - If the firmware reports ReplyFrameSize greater than the current ReplyFrameSize then the driver uses the current ReplyFrameSize while copying the reply messages. - The driver displays an error message and marks the controller as unrecoverable if the firmware reports MaxOperationalReplyQueues less than the currently allocated operational reply queues count. - If the firmware reports MaxOperationalReplyQueues that is greater than the currently allocated operational reply queue count then the driver ignores the new increased value and uses the previously allocated number of operational queues only. - If the firmware reports MaxDevHandle greater than the previously used MaxDevHandle value after a reset then the driver re-allocates the 'device remove pending bitmap' buffer with the newer size using krealloc(). Link: https://lore.kernel.org/r/20211220141159.16117-18-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent b64845a commit c5758fc

2 files changed

Lines changed: 92 additions & 18 deletions

File tree

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ struct mpi3mr_ioc {
752752
dma_addr_t reply_buf_dma_max_address;
753753

754754
u16 reply_free_qsz;
755+
u16 reply_sz;
755756
struct dma_pool *reply_free_q_pool;
756757
__le64 *reply_free_q;
757758
dma_addr_t reply_free_q_dma;

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
static int
1414
mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, u32 reset_reason);
1515
static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc);
16+
static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
17+
struct mpi3_ioc_facts_data *facts_data);
1618

1719
#if defined(writeq) && defined(CONFIG_64BIT)
1820
static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr)
@@ -376,7 +378,7 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc,
376378
if (def_reply) {
377379
cmdptr->state |= MPI3MR_CMD_REPLY_VALID;
378380
memcpy((u8 *)cmdptr->reply, (u8 *)def_reply,
379-
mrioc->facts.reply_sz);
381+
mrioc->reply_sz);
380382
}
381383
if (cmdptr->is_waiting) {
382384
complete(&cmdptr->done);
@@ -996,6 +998,66 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
996998
return retval;
997999
}
9981000

1001+
/**
1002+
* mpi3mr_revalidate_factsdata - validate IOCFacts parameters
1003+
* during reset/resume
1004+
* @mrioc: Adapter instance reference
1005+
*
1006+
* Return zero if the new IOCFacts parameters value is compatible with
1007+
* older values else return -EPERM
1008+
*/
1009+
static int
1010+
mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
1011+
{
1012+
u16 dev_handle_bitmap_sz;
1013+
void *removepend_bitmap;
1014+
1015+
if (mrioc->facts.reply_sz > mrioc->reply_sz) {
1016+
ioc_err(mrioc,
1017+
"cannot increase reply size from %d to %d\n",
1018+
mrioc->reply_sz, mrioc->facts.reply_sz);
1019+
return -EPERM;
1020+
}
1021+
1022+
if (mrioc->facts.max_op_reply_q < mrioc->num_op_reply_q) {
1023+
ioc_err(mrioc,
1024+
"cannot reduce number of operational reply queues from %d to %d\n",
1025+
mrioc->num_op_reply_q,
1026+
mrioc->facts.max_op_reply_q);
1027+
return -EPERM;
1028+
}
1029+
1030+
if (mrioc->facts.max_op_req_q < mrioc->num_op_req_q) {
1031+
ioc_err(mrioc,
1032+
"cannot reduce number of operational request queues from %d to %d\n",
1033+
mrioc->num_op_req_q, mrioc->facts.max_op_req_q);
1034+
return -EPERM;
1035+
}
1036+
1037+
dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8;
1038+
if (mrioc->facts.max_devhandle % 8)
1039+
dev_handle_bitmap_sz++;
1040+
if (dev_handle_bitmap_sz > mrioc->dev_handle_bitmap_sz) {
1041+
removepend_bitmap = krealloc(mrioc->removepend_bitmap,
1042+
dev_handle_bitmap_sz, GFP_KERNEL);
1043+
if (!removepend_bitmap) {
1044+
ioc_err(mrioc,
1045+
"failed to increase removepend_bitmap sz from: %d to %d\n",
1046+
mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
1047+
return -EPERM;
1048+
}
1049+
memset(removepend_bitmap + mrioc->dev_handle_bitmap_sz, 0,
1050+
dev_handle_bitmap_sz - mrioc->dev_handle_bitmap_sz);
1051+
mrioc->removepend_bitmap = removepend_bitmap;
1052+
ioc_info(mrioc,
1053+
"increased dev_handle_bitmap_sz from %d to %d\n",
1054+
mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
1055+
mrioc->dev_handle_bitmap_sz = dev_handle_bitmap_sz;
1056+
}
1057+
1058+
return 0;
1059+
}
1060+
9991061
/**
10001062
* mpi3mr_bring_ioc_ready - Bring controller to ready state
10011063
* @mrioc: Adapter instance reference
@@ -1854,8 +1916,13 @@ static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc)
18541916
mrioc->intr_info_count - mrioc->op_reply_q_offset;
18551917
if (!mrioc->num_queues)
18561918
mrioc->num_queues = min_t(int, num_queues, msix_count_op_q);
1857-
num_queues = mrioc->num_queues;
1858-
ioc_info(mrioc, "Trying to create %d Operational Q pairs\n",
1919+
/*
1920+
* During reset set the num_queues to the number of queues
1921+
* that was set before the reset.
1922+
*/
1923+
num_queues = mrioc->num_op_reply_q ?
1924+
mrioc->num_op_reply_q : mrioc->num_queues;
1925+
ioc_info(mrioc, "trying to create %d operational queue pairs\n",
18591926
num_queues);
18601927

18611928
if (!mrioc->req_qinfo) {
@@ -2447,6 +2514,7 @@ static int mpi3mr_issue_iocfacts(struct mpi3mr_ioc *mrioc,
24472514
goto out_unlock;
24482515
}
24492516
memcpy(facts_data, (u8 *)data, data_len);
2517+
mpi3mr_process_factsdata(mrioc, facts_data);
24502518
out_unlock:
24512519
mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
24522520
mutex_unlock(&mrioc->init_cmds.mutex);
@@ -2593,12 +2661,6 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
25932661
ioc_info(mrioc, "DMA mask %d InitialPE status 0x%x\n",
25942662
mrioc->facts.dma_mask, (facts_flags &
25952663
MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK));
2596-
2597-
mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD;
2598-
2599-
if (reset_devices)
2600-
mrioc->max_host_ios = min_t(int, mrioc->max_host_ios,
2601-
MPI3MR_HOST_IOS_KDUMP);
26022664
}
26032665

26042666
/**
@@ -2618,18 +2680,18 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc)
26182680
if (mrioc->init_cmds.reply)
26192681
return retval;
26202682

2621-
mrioc->init_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL);
2683+
mrioc->init_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL);
26222684
if (!mrioc->init_cmds.reply)
26232685
goto out_failed;
26242686

26252687
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
2626-
mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz,
2688+
mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->reply_sz,
26272689
GFP_KERNEL);
26282690
if (!mrioc->dev_rmhs_cmds[i].reply)
26292691
goto out_failed;
26302692
}
26312693

2632-
mrioc->host_tm_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL);
2694+
mrioc->host_tm_cmds.reply = kzalloc(mrioc->reply_sz, GFP_KERNEL);
26332695
if (!mrioc->host_tm_cmds.reply)
26342696
goto out_failed;
26352697

@@ -2655,7 +2717,7 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc)
26552717
mrioc->sense_buf_q_sz = mrioc->num_sense_bufs + 1;
26562718

26572719
/* reply buffer pool, 16 byte align */
2658-
sz = mrioc->num_reply_bufs * mrioc->facts.reply_sz;
2720+
sz = mrioc->num_reply_bufs * mrioc->reply_sz;
26592721
mrioc->reply_buf_pool = dma_pool_create("reply_buf pool",
26602722
&mrioc->pdev->dev, sz, 16, 0);
26612723
if (!mrioc->reply_buf_pool) {
@@ -2731,10 +2793,10 @@ static void mpimr_initialize_reply_sbuf_queues(struct mpi3mr_ioc *mrioc)
27312793
u32 sz, i;
27322794
dma_addr_t phy_addr;
27332795

2734-
sz = mrioc->num_reply_bufs * mrioc->facts.reply_sz;
2796+
sz = mrioc->num_reply_bufs * mrioc->reply_sz;
27352797
ioc_info(mrioc,
27362798
"reply buf pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB), reply_dma(0x%llx)\n",
2737-
mrioc->reply_buf, mrioc->num_reply_bufs, mrioc->facts.reply_sz,
2799+
mrioc->reply_buf, mrioc->num_reply_bufs, mrioc->reply_sz,
27382800
(sz / 1024), (unsigned long long)mrioc->reply_buf_dma);
27392801
sz = mrioc->reply_free_qsz * 8;
27402802
ioc_info(mrioc,
@@ -2754,7 +2816,7 @@ static void mpimr_initialize_reply_sbuf_queues(struct mpi3mr_ioc *mrioc)
27542816

27552817
/* initialize Reply buffer Queue */
27562818
for (i = 0, phy_addr = mrioc->reply_buf_dma;
2757-
i < mrioc->num_reply_bufs; i++, phy_addr += mrioc->facts.reply_sz)
2819+
i < mrioc->num_reply_bufs; i++, phy_addr += mrioc->reply_sz)
27582820
mrioc->reply_free_q[i] = cpu_to_le64(phy_addr);
27592821
mrioc->reply_free_q[i] = cpu_to_le64(0);
27602822

@@ -3459,7 +3521,13 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
34593521
goto out_failed;
34603522
}
34613523

3462-
mpi3mr_process_factsdata(mrioc, &facts_data);
3524+
mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD;
3525+
3526+
if (reset_devices)
3527+
mrioc->max_host_ios = min_t(int, mrioc->max_host_ios,
3528+
MPI3MR_HOST_IOS_KDUMP);
3529+
3530+
mrioc->reply_sz = mrioc->facts.reply_sz;
34633531

34643532
retval = mpi3mr_check_reset_dma_mask(mrioc);
34653533
if (retval) {
@@ -3582,7 +3650,12 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
35823650
goto out_failed;
35833651
}
35843652

3585-
mpi3mr_process_factsdata(mrioc, &facts_data);
3653+
dprint_reset(mrioc, "validating ioc_facts\n");
3654+
retval = mpi3mr_revalidate_factsdata(mrioc);
3655+
if (retval) {
3656+
ioc_err(mrioc, "failed to revalidate ioc_facts data\n");
3657+
goto out_failed_noretry;
3658+
}
35863659

35873660
mpi3mr_print_ioc_info(mrioc);
35883661

0 commit comments

Comments
 (0)