Skip to content

Commit fe6db61

Browse files
sreekanthbrcmmartinkpetersen
authored andcommitted
scsi: mpi3mr: Handle offline FW activation in graceful manner
Currently the driver marks the controller as unrecoverable if there is an asynchronous reset or fault during the initialization, reinitialization post reset, and OS resume. Enhance driver to retry the initialization, re-initialization, and resume sequences for a maximum of 3 times if the controller became faulty or asynchronously reset due to a firmware activation during the initialization sequence. Link: https://lore.kernel.org/r/20211220141159.16117-15-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 59bd9cf commit fe6db61

3 files changed

Lines changed: 120 additions & 128 deletions

File tree

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,6 @@ enum mpi3mr_iocstate {
185185
MRIOC_STATE_UNRECOVERABLE,
186186
};
187187

188-
/* Init type definitions */
189-
enum mpi3mr_init_type {
190-
MPI3MR_IT_INIT = 0,
191-
MPI3MR_IT_RESET,
192-
MPI3MR_IT_RESUME,
193-
};
194-
195-
/* Cleanup reason definitions */
196-
enum mpi3mr_cleanup_reason {
197-
MPI3MR_COMPLETE_CLEANUP = 0,
198-
MPI3MR_REINIT_FAILURE,
199-
MPI3MR_SUSPEND,
200-
};
201-
202188
/* Reset reason code definitions*/
203189
enum mpi3mr_reset_reason {
204190
MPI3MR_RESET_FROM_BRINGUP = 1,
@@ -634,6 +620,7 @@ struct scmd_priv {
634620
* @ready_timeout: Controller ready timeout
635621
* @intr_info: Interrupt cookie pointer
636622
* @intr_info_count: Number of interrupt cookies
623+
* @is_intr_info_set: Flag to indicate intr info is setup
637624
* @num_queues: Number of operational queues
638625
* @num_op_req_q: Number of operational request queues
639626
* @req_qinfo: Operational request queue info pointer
@@ -743,6 +730,7 @@ struct mpi3mr_ioc {
743730

744731
struct mpi3mr_intr_info *intr_info;
745732
u16 intr_info_count;
733+
bool is_intr_info_set;
746734

747735
u16 num_queues;
748736
u16 num_op_req_q;
@@ -873,8 +861,9 @@ struct delayed_dev_rmhs_node {
873861

874862
int mpi3mr_setup_resources(struct mpi3mr_ioc *mrioc);
875863
void mpi3mr_cleanup_resources(struct mpi3mr_ioc *mrioc);
876-
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type);
877-
void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 reason);
864+
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc);
865+
int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume);
866+
void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc);
878867
int mpi3mr_issue_port_enable(struct mpi3mr_ioc *mrioc, u8 async);
879868
int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req,
880869
u16 admin_req_sz, u8 ignore_reset);
@@ -891,6 +880,7 @@ void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc,
891880
u64 sense_buf_dma);
892881

893882
void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc);
883+
void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc);
894884
void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
895885
struct mpi3_event_notification_reply *event_reply);
896886
void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 81 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static void mpi3mr_cleanup_isr(struct mpi3mr_ioc *mrioc)
8282
kfree(mrioc->intr_info);
8383
mrioc->intr_info = NULL;
8484
mrioc->intr_info_count = 0;
85+
mrioc->is_intr_info_set = false;
8586
pci_free_irq_vectors(mrioc->pdev);
8687
}
8788

@@ -675,6 +676,9 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one)
675676
int i;
676677
struct irq_affinity desc = { .pre_vectors = 1};
677678

679+
if (mrioc->is_intr_info_set)
680+
return 0;
681+
678682
mpi3mr_cleanup_isr(mrioc);
679683

680684
if (setup_one || reset_devices)
@@ -726,6 +730,8 @@ static int mpi3mr_setup_isr(struct mpi3mr_ioc *mrioc, u8 setup_one)
726730
goto out_failed;
727731
}
728732
}
733+
if (reset_devices || !setup_one)
734+
mrioc->is_intr_info_set = true;
729735
mrioc->intr_info_count = max_vectors;
730736
mpi3mr_ioc_enable_intr(mrioc);
731737
return 0;
@@ -1712,7 +1718,8 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx)
17121718
goto out_unlock;
17131719
}
17141720
op_reply_q->qid = reply_qid;
1715-
mrioc->intr_info[midx].op_reply_q = op_reply_q;
1721+
if (midx < mrioc->intr_info_count)
1722+
mrioc->intr_info[midx].op_reply_q = op_reply_q;
17161723

17171724
out_unlock:
17181725
mrioc->init_cmds.state = MPI3MR_CMD_NOTUSED;
@@ -3074,6 +3081,9 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc)
30743081
u32 sz, i;
30753082
u16 num_chains;
30763083

3084+
if (mrioc->chain_sgl_list)
3085+
return retval;
3086+
30773087
num_chains = mrioc->max_host_ios / MPI3MR_CHAINBUF_FACTOR;
30783088

30793089
if (prot_mask & (SHOST_DIX_TYPE0_PROTECTION
@@ -3452,39 +3462,26 @@ static int mpi3mr_enable_events(struct mpi3mr_ioc *mrioc)
34523462
*
34533463
* Return: 0 on success and non-zero on failure.
34543464
*/
3455-
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
3465+
int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
34563466
{
34573467
int retval = 0;
3468+
u8 retry = 0;
34583469
struct mpi3_ioc_facts_data facts_data;
34593470

3460-
mrioc->irqpoll_sleep = MPI3MR_IRQ_POLL_SLEEP;
3461-
mrioc->change_count = 0;
3462-
if (init_type == MPI3MR_IT_INIT) {
3463-
mrioc->cpu_count = num_online_cpus();
3464-
retval = mpi3mr_setup_resources(mrioc);
3465-
if (retval) {
3466-
ioc_err(mrioc, "Failed to setup resources:error %d\n",
3467-
retval);
3468-
goto out_nocleanup;
3469-
}
3470-
}
3471-
3471+
retry_init:
34723472
retval = mpi3mr_bring_ioc_ready(mrioc);
34733473
if (retval) {
34743474
ioc_err(mrioc, "Failed to bring ioc ready: error %d\n",
34753475
retval);
3476-
goto out_failed;
3476+
goto out_failed_noretry;
34773477
}
34783478

3479-
if (init_type != MPI3MR_IT_RESET) {
3480-
retval = mpi3mr_setup_isr(mrioc, 1);
3481-
if (retval) {
3482-
ioc_err(mrioc, "Failed to setup ISR error %d\n",
3483-
retval);
3484-
goto out_failed;
3485-
}
3486-
} else
3487-
mpi3mr_ioc_enable_intr(mrioc);
3479+
retval = mpi3mr_setup_isr(mrioc, 1);
3480+
if (retval) {
3481+
ioc_err(mrioc, "Failed to setup ISR error %d\n",
3482+
retval);
3483+
goto out_failed_noretry;
3484+
}
34883485

34893486
retval = mpi3mr_issue_iocfacts(mrioc, &facts_data);
34903487
if (retval) {
@@ -3494,13 +3491,12 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
34943491
}
34953492

34963493
mpi3mr_process_factsdata(mrioc, &facts_data);
3497-
if (init_type == MPI3MR_IT_INIT) {
3498-
retval = mpi3mr_check_reset_dma_mask(mrioc);
3499-
if (retval) {
3500-
ioc_err(mrioc, "Resetting dma mask failed %d\n",
3501-
retval);
3502-
goto out_failed;
3503-
}
3494+
3495+
retval = mpi3mr_check_reset_dma_mask(mrioc);
3496+
if (retval) {
3497+
ioc_err(mrioc, "Resetting dma mask failed %d\n",
3498+
retval);
3499+
goto out_failed_noretry;
35043500
}
35053501

35063502
mpi3mr_print_ioc_info(mrioc);
@@ -3510,16 +3506,14 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
35103506
ioc_err(mrioc,
35113507
"%s :Failed to allocated reply sense buffers %d\n",
35123508
__func__, retval);
3513-
goto out_failed;
3509+
goto out_failed_noretry;
35143510
}
35153511

3516-
if (init_type == MPI3MR_IT_INIT) {
3517-
retval = mpi3mr_alloc_chain_bufs(mrioc);
3518-
if (retval) {
3519-
ioc_err(mrioc, "Failed to allocated chain buffers %d\n",
3520-
retval);
3521-
goto out_failed;
3522-
}
3512+
retval = mpi3mr_alloc_chain_bufs(mrioc);
3513+
if (retval) {
3514+
ioc_err(mrioc, "Failed to allocated chain buffers %d\n",
3515+
retval);
3516+
goto out_failed_noretry;
35233517
}
35243518

35253519
retval = mpi3mr_issue_iocinit(mrioc);
@@ -3535,13 +3529,11 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
35353529
goto out_failed;
35363530
}
35373531

3538-
if (init_type != MPI3MR_IT_RESET) {
3539-
retval = mpi3mr_setup_isr(mrioc, 0);
3540-
if (retval) {
3541-
ioc_err(mrioc, "Failed to re-setup ISR, error %d\n",
3542-
retval);
3543-
goto out_failed;
3544-
}
3532+
retval = mpi3mr_setup_isr(mrioc, 0);
3533+
if (retval) {
3534+
ioc_err(mrioc, "Failed to re-setup ISR, error %d\n",
3535+
retval);
3536+
goto out_failed_noretry;
35453537
}
35463538

35473539
retval = mpi3mr_create_op_queues(mrioc);
@@ -3551,42 +3543,37 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type)
35513543
goto out_failed;
35523544
}
35533545

3554-
if ((init_type != MPI3MR_IT_INIT) &&
3555-
(mrioc->shost->nr_hw_queues > mrioc->num_op_reply_q)) {
3556-
retval = -1;
3557-
ioc_err(mrioc,
3558-
"Cannot create minimum number of OpQueues expected:%d created:%d\n",
3559-
mrioc->shost->nr_hw_queues, mrioc->num_op_reply_q);
3560-
goto out_failed;
3561-
}
3562-
35633546
retval = mpi3mr_enable_events(mrioc);
35643547
if (retval) {
35653548
ioc_err(mrioc, "failed to enable events %d\n",
35663549
retval);
35673550
goto out_failed;
35683551
}
35693552

3570-
if (init_type != MPI3MR_IT_INIT) {
3571-
ioc_info(mrioc, "Issuing Port Enable\n");
3572-
retval = mpi3mr_issue_port_enable(mrioc, 0);
3573-
if (retval) {
3574-
ioc_err(mrioc, "Failed to issue port enable %d\n",
3575-
retval);
3576-
goto out_failed;
3577-
}
3578-
}
3553+
ioc_info(mrioc, "controller initialization completed successfully\n");
35793554
return retval;
3580-
35813555
out_failed:
3582-
if (init_type == MPI3MR_IT_INIT)
3583-
mpi3mr_cleanup_ioc(mrioc, MPI3MR_COMPLETE_CLEANUP);
3584-
else
3585-
mpi3mr_cleanup_ioc(mrioc, MPI3MR_REINIT_FAILURE);
3586-
out_nocleanup:
3556+
if (retry < 2) {
3557+
retry++;
3558+
ioc_warn(mrioc, "retrying controller initialization, retry_count:%d\n",
3559+
retry);
3560+
mpi3mr_memset_buffers(mrioc);
3561+
goto retry_init;
3562+
}
3563+
out_failed_noretry:
3564+
ioc_err(mrioc, "controller initialization failed\n");
3565+
mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
3566+
MPI3MR_RESET_FROM_CTLR_CLEANUP);
3567+
mrioc->unrecoverable = 1;
35873568
return retval;
35883569
}
35893570

3571+
int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
3572+
{
3573+
3574+
return 0;
3575+
}
3576+
35903577
/**
35913578
* mpi3mr_memset_op_reply_q_buffers - memset the operational reply queue's
35923579
* segments
@@ -3647,17 +3634,22 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
36473634
{
36483635
u16 i;
36493636

3650-
memset(mrioc->admin_req_base, 0, mrioc->admin_req_q_sz);
3651-
memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz);
3652-
3653-
memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply));
3654-
memset(mrioc->host_tm_cmds.reply, 0,
3655-
sizeof(*mrioc->host_tm_cmds.reply));
3656-
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++)
3657-
memset(mrioc->dev_rmhs_cmds[i].reply, 0,
3658-
sizeof(*mrioc->dev_rmhs_cmds[i].reply));
3659-
memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
3660-
memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
3637+
mrioc->change_count = 0;
3638+
if (mrioc->admin_req_base)
3639+
memset(mrioc->admin_req_base, 0, mrioc->admin_req_q_sz);
3640+
if (mrioc->admin_reply_base)
3641+
memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz);
3642+
3643+
if (mrioc->init_cmds.reply) {
3644+
memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply));
3645+
memset(mrioc->host_tm_cmds.reply, 0,
3646+
sizeof(*mrioc->host_tm_cmds.reply));
3647+
for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++)
3648+
memset(mrioc->dev_rmhs_cmds[i].reply, 0,
3649+
sizeof(*mrioc->dev_rmhs_cmds[i].reply));
3650+
memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
3651+
memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
3652+
}
36613653

36623654
for (i = 0; i < mrioc->num_queues; i++) {
36633655
mrioc->op_reply_qinfo[i].qid = 0;
@@ -3686,7 +3678,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
36863678
*
36873679
* Return: Nothing.
36883680
*/
3689-
static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
3681+
void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
36903682
{
36913683
u16 i;
36923684
struct mpi3mr_intr_info *intr_info;
@@ -3858,21 +3850,17 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
38583850
/**
38593851
* mpi3mr_cleanup_ioc - Cleanup controller
38603852
* @mrioc: Adapter instance reference
3861-
* @reason: Cleanup reason
3862-
*
3853+
38633854
* controller cleanup handler, Message unit reset or soft reset
3864-
* and shutdown notification is issued to the controller and the
3865-
* associated memory resources are freed.
3855+
* and shutdown notification is issued to the controller.
38663856
*
38673857
* Return: Nothing.
38683858
*/
3869-
void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 reason)
3859+
void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc)
38703860
{
38713861
enum mpi3mr_iocstate ioc_state;
38723862

3873-
if (reason == MPI3MR_COMPLETE_CLEANUP)
3874-
mpi3mr_stop_watchdog(mrioc);
3875-
3863+
dprint_exit(mrioc, "cleaning up the controller\n");
38763864
mpi3mr_ioc_disable_intr(mrioc);
38773865

38783866
ioc_state = mpi3mr_get_iocstate(mrioc);
@@ -3884,15 +3872,9 @@ void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc, u8 reason)
38843872
mpi3mr_issue_reset(mrioc,
38853873
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
38863874
MPI3MR_RESET_FROM_MUR_FAILURE);
3887-
3888-
if (reason != MPI3MR_REINIT_FAILURE)
3889-
mpi3mr_issue_ioc_shutdown(mrioc);
3890-
}
3891-
3892-
if (reason == MPI3MR_COMPLETE_CLEANUP) {
3893-
mpi3mr_free_mem(mrioc);
3894-
mpi3mr_cleanup_resources(mrioc);
3875+
mpi3mr_issue_ioc_shutdown(mrioc);
38953876
}
3877+
dprint_exit(mrioc, "controller cleanup completed\n");
38963878
}
38973879

38983880
/**
@@ -4071,7 +4053,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
40714053
mpi3mr_flush_host_io(mrioc);
40724054
mpi3mr_invalidate_devhandles(mrioc);
40734055
mpi3mr_memset_buffers(mrioc);
4074-
retval = mpi3mr_init_ioc(mrioc, MPI3MR_IT_RESET);
4056+
retval = mpi3mr_reinit_ioc(mrioc, 0);
40754057
if (retval) {
40764058
pr_err(IOCNAME "reinit after soft reset failed: reason %d\n",
40774059
mrioc->name, reset_reason);

0 commit comments

Comments
 (0)