Skip to content

Commit 1c342b0

Browse files
sumitsaxena11martinkpetersen
authored andcommitted
scsi: mpi3mr: Prevent PCI writes from driver during PCI error recovery
Prevent interaction with the hardware while the error recovery in progress. Co-developed-by: Sathya Prakash <[email protected]> Signed-off-by: Sathya Prakash <[email protected]> Co-developed-by: Ranjan Kumar <[email protected]> Signed-off-by: Ranjan Kumar <[email protected]> Signed-off-by: Sumit Saxena <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 30bafe1 commit 1c342b0

File tree

5 files changed

+104
-17
lines changed

5 files changed

+104
-17
lines changed

drivers/scsi/mpi3mr/mpi3mr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ struct mpi3mr_throttle_group_info {
519519

520520
/* HBA port flags */
521521
#define MPI3MR_HBA_PORT_FLAG_DIRTY 0x01
522+
#define MPI3MR_HBA_PORT_FLAG_NEW 0x02
522523

523524
/* IOCTL data transfer sge*/
524525
#define MPI3MR_NUM_IOCTL_SGE 256

drivers/scsi/mpi3mr/mpi3mr_app.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ static int mpi3mr_bsg_pel_abort(struct mpi3mr_ioc *mrioc)
846846
dprint_bsg_err(mrioc, "%s: reset in progress\n", __func__);
847847
return -1;
848848
}
849-
if (mrioc->stop_bsgs) {
849+
if (mrioc->stop_bsgs || mrioc->block_on_pci_err) {
850850
dprint_bsg_err(mrioc, "%s: bsgs are blocked\n", __func__);
851851
return -1;
852852
}
@@ -1492,6 +1492,9 @@ static long mpi3mr_bsg_adp_reset(struct mpi3mr_ioc *mrioc,
14921492
goto out;
14931493
}
14941494

1495+
if (mrioc->unrecoverable || mrioc->block_on_pci_err)
1496+
return -EINVAL;
1497+
14951498
sg_copy_to_buffer(job->request_payload.sg_list,
14961499
job->request_payload.sg_cnt,
14971500
&adpreset, sizeof(adpreset));
@@ -2575,7 +2578,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
25752578
mutex_unlock(&mrioc->bsg_cmds.mutex);
25762579
goto out;
25772580
}
2578-
if (mrioc->stop_bsgs) {
2581+
if (mrioc->stop_bsgs || mrioc->block_on_pci_err) {
25792582
dprint_bsg_err(mrioc, "%s: bsgs are blocked\n", __func__);
25802583
rval = -EAGAIN;
25812584
mutex_unlock(&mrioc->bsg_cmds.mutex);
@@ -3108,7 +3111,8 @@ adp_state_show(struct device *dev, struct device_attribute *attr,
31083111
ioc_state = mpi3mr_get_iocstate(mrioc);
31093112
if (ioc_state == MRIOC_STATE_UNRECOVERABLE)
31103113
adp_state = MPI3MR_BSG_ADPSTATE_UNRECOVERABLE;
3111-
else if ((mrioc->reset_in_progress) || (mrioc->stop_bsgs))
3114+
else if (mrioc->reset_in_progress || mrioc->stop_bsgs ||
3115+
mrioc->block_on_pci_err)
31123116
adp_state = MPI3MR_BSG_ADPSTATE_IN_RESET;
31133117
else if (ioc_state == MRIOC_STATE_FAULT)
31143118
adp_state = MPI3MR_BSG_ADPSTATE_FAULT;

drivers/scsi/mpi3mr/mpi3mr_fw.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ int mpi3mr_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
608608
mrioc = (struct mpi3mr_ioc *)shost->hostdata;
609609

610610
if ((mrioc->reset_in_progress || mrioc->prepare_for_reset ||
611-
mrioc->unrecoverable))
611+
mrioc->unrecoverable || mrioc->pci_err_recovery))
612612
return 0;
613613

614614
num_entries = mpi3mr_process_op_reply_q(mrioc,
@@ -1693,6 +1693,12 @@ int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req,
16931693
retval = -EAGAIN;
16941694
goto out;
16951695
}
1696+
if (mrioc->pci_err_recovery) {
1697+
ioc_err(mrioc, "admin request queue submission failed due to pci error recovery in progress\n");
1698+
retval = -EAGAIN;
1699+
goto out;
1700+
}
1701+
16961702
areq_entry = (u8 *)mrioc->admin_req_base +
16971703
(areq_pi * MPI3MR_ADMIN_REQ_FRAME_SZ);
16981704
memset(areq_entry, 0, MPI3MR_ADMIN_REQ_FRAME_SZ);
@@ -2363,6 +2369,11 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
23632369
retval = -EAGAIN;
23642370
goto out;
23652371
}
2372+
if (mrioc->pci_err_recovery) {
2373+
ioc_err(mrioc, "operational request queue submission failed due to pci error recovery in progress\n");
2374+
retval = -EAGAIN;
2375+
goto out;
2376+
}
23662377

23672378
segment_base_addr = segments[pi / op_req_q->segment_qd].segment;
23682379
req_entry = (u8 *)segment_base_addr +
@@ -2627,7 +2638,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
26272638
union mpi3mr_trigger_data trigger_data;
26282639
u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH;
26292640

2630-
if (mrioc->reset_in_progress)
2641+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
26312642
return;
26322643

26332644
if (!mrioc->unrecoverable && !pci_device_is_present(mrioc->pdev)) {
@@ -4268,7 +4279,7 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
42684279
goto out_failed_noretry;
42694280
}
42704281

4271-
if (is_resume) {
4282+
if (is_resume || mrioc->block_on_pci_err) {
42724283
dprint_reset(mrioc, "setting up single ISR\n");
42734284
retval = mpi3mr_setup_isr(mrioc, 1);
42744285
if (retval) {
@@ -4319,7 +4330,7 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
43194330
goto out_failed;
43204331
}
43214332

4322-
if (is_resume) {
4333+
if (is_resume || mrioc->block_on_pci_err) {
43234334
dprint_reset(mrioc, "setting up multiple ISR\n");
43244335
retval = mpi3mr_setup_isr(mrioc, 0);
43254336
if (retval) {
@@ -4807,7 +4818,8 @@ void mpi3mr_cleanup_ioc(struct mpi3mr_ioc *mrioc)
48074818

48084819
ioc_state = mpi3mr_get_iocstate(mrioc);
48094820

4810-
if ((!mrioc->unrecoverable) && (!mrioc->reset_in_progress) &&
4821+
if (!mrioc->unrecoverable && !mrioc->reset_in_progress &&
4822+
!mrioc->pci_err_recovery &&
48114823
(ioc_state == MRIOC_STATE_READY)) {
48124824
if (mpi3mr_issue_and_process_mur(mrioc,
48134825
MPI3MR_RESET_FROM_CTLR_CLEANUP))

drivers/scsi/mpi3mr/mpi3mr_os.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
956956
int retval = 0;
957957
struct mpi3mr_tgt_dev *tgtdev;
958958

959-
if (mrioc->reset_in_progress)
959+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
960960
return -1;
961961

962962
tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id);
@@ -2007,6 +2007,7 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
20072007
struct mpi3_device_page0 *dev_pg0 = NULL;
20082008
u16 perst_id, handle, dev_info;
20092009
struct mpi3_device0_sas_sata_format *sasinf = NULL;
2010+
unsigned int timeout;
20102011

20112012
mpi3mr_fwevt_del_from_list(mrioc, fwevt);
20122013
mrioc->current_event = fwevt;
@@ -2097,8 +2098,18 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
20972098
}
20982099
case MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH:
20992100
{
2100-
while (mrioc->device_refresh_on)
2101+
timeout = MPI3MR_RESET_TIMEOUT * 2;
2102+
while ((mrioc->device_refresh_on || mrioc->block_on_pci_err) &&
2103+
!mrioc->unrecoverable && !mrioc->pci_err_recovery) {
21012104
msleep(500);
2105+
if (!timeout--) {
2106+
mrioc->unrecoverable = 1;
2107+
break;
2108+
}
2109+
}
2110+
2111+
if (mrioc->unrecoverable || mrioc->pci_err_recovery)
2112+
break;
21022113

21032114
dprint_event_bh(mrioc,
21042115
"scan for non responding and newly added devices after soft reset started\n");
@@ -3796,6 +3807,13 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
37963807
mutex_unlock(&drv_cmd->mutex);
37973808
goto out;
37983809
}
3810+
if (mrioc->block_on_pci_err) {
3811+
retval = -1;
3812+
dprint_tm(mrioc, "sending task management failed due to\n"
3813+
"pci error recovery in progress\n");
3814+
mutex_unlock(&drv_cmd->mutex);
3815+
goto out;
3816+
}
37993817

38003818
drv_cmd->state = MPI3MR_CMD_PENDING;
38013819
drv_cmd->is_waiting = 1;
@@ -4181,6 +4199,7 @@ static int mpi3mr_eh_bus_reset(struct scsi_cmnd *scmd)
41814199
struct mpi3mr_sdev_priv_data *sdev_priv_data;
41824200
u8 dev_type = MPI3_DEVICE_DEVFORM_VD;
41834201
int retval = FAILED;
4202+
unsigned int timeout = MPI3MR_RESET_TIMEOUT;
41844203

41854204
sdev_priv_data = scmd->device->hostdata;
41864205
if (sdev_priv_data && sdev_priv_data->tgt_priv_data) {
@@ -4191,12 +4210,24 @@ static int mpi3mr_eh_bus_reset(struct scsi_cmnd *scmd)
41914210
if (dev_type == MPI3_DEVICE_DEVFORM_VD) {
41924211
mpi3mr_wait_for_host_io(mrioc,
41934212
MPI3MR_RAID_ERRREC_RESET_TIMEOUT);
4194-
if (!mpi3mr_get_fw_pending_ios(mrioc))
4213+
if (!mpi3mr_get_fw_pending_ios(mrioc)) {
4214+
while (mrioc->reset_in_progress ||
4215+
mrioc->prepare_for_reset ||
4216+
mrioc->block_on_pci_err) {
4217+
ssleep(1);
4218+
if (!timeout--) {
4219+
retval = FAILED;
4220+
goto out;
4221+
}
4222+
}
41954223
retval = SUCCESS;
4224+
goto out;
4225+
}
41964226
}
41974227
if (retval == FAILED)
41984228
mpi3mr_print_pending_host_io(mrioc);
41994229

4230+
out:
42004231
sdev_printk(KERN_INFO, scmd->device,
42014232
"Bus reset is %s for scmd(%p)\n",
42024233
((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
@@ -4879,7 +4910,8 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
48794910
goto out;
48804911
}
48814912

4882-
if (mrioc->reset_in_progress) {
4913+
if (mrioc->reset_in_progress || mrioc->prepare_for_reset
4914+
|| mrioc->block_on_pci_err) {
48834915
retval = SCSI_MLQUEUE_HOST_BUSY;
48844916
goto out;
48854917
}
@@ -5362,7 +5394,14 @@ static void mpi3mr_remove(struct pci_dev *pdev)
53625394
while (mrioc->reset_in_progress || mrioc->is_driver_loading)
53635395
ssleep(1);
53645396

5365-
if (!pci_device_is_present(mrioc->pdev)) {
5397+
if (mrioc->block_on_pci_err) {
5398+
mrioc->block_on_pci_err = false;
5399+
scsi_unblock_requests(shost);
5400+
mrioc->unrecoverable = 1;
5401+
}
5402+
5403+
if (!pci_device_is_present(mrioc->pdev) ||
5404+
mrioc->pci_err_recovery) {
53665405
mrioc->unrecoverable = 1;
53675406
mpi3mr_flush_cmds_for_unrecovered_controller(mrioc);
53685407
}

drivers/scsi/mpi3mr/mpi3mr_transport.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
151151
return -EFAULT;
152152
}
153153

154+
if (mrioc->pci_err_recovery) {
155+
ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
156+
return -EFAULT;
157+
}
158+
154159
data_out_sz = sizeof(struct rep_manu_request);
155160
data_in_sz = sizeof(struct rep_manu_reply);
156161
data_out = dma_alloc_coherent(&mrioc->pdev->dev,
@@ -790,6 +795,12 @@ static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
790795
return -EFAULT;
791796
}
792797

798+
if (mrioc->pci_err_recovery) {
799+
ioc_err(mrioc, "%s: pci error recovery in progress!\n",
800+
__func__);
801+
return -EFAULT;
802+
}
803+
793804
if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
794805
sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
795806
ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
@@ -1007,6 +1018,9 @@ mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
10071018
hba_port->port_id = port_id;
10081019
ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
10091020
hba_port, hba_port->port_id);
1021+
if (mrioc->reset_in_progress ||
1022+
mrioc->pci_err_recovery)
1023+
hba_port->flags = MPI3MR_HBA_PORT_FLAG_NEW;
10101024
list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
10111025
return hba_port;
10121026
}
@@ -1055,7 +1069,7 @@ void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
10551069
struct mpi3mr_sas_node *mr_sas_node;
10561070
struct mpi3mr_sas_phy *mr_sas_phy;
10571071

1058-
if (mrioc->reset_in_progress)
1072+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
10591073
return;
10601074

10611075
spin_lock_irqsave(&mrioc->sas_node_lock, flags);
@@ -1978,7 +1992,7 @@ int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
19781992
if (!handle)
19791993
return -1;
19801994

1981-
if (mrioc->reset_in_progress)
1995+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
19821996
return -1;
19831997

19841998
if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
@@ -2184,7 +2198,7 @@ void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
21842198
/* remove sibling ports attached to this expander */
21852199
list_for_each_entry_safe(mr_sas_port, next,
21862200
&sas_expander->sas_port_list, port_list) {
2187-
if (mrioc->reset_in_progress)
2201+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
21882202
return;
21892203
if (mr_sas_port->remote_identify.device_type ==
21902204
SAS_END_DEVICE)
@@ -2234,7 +2248,7 @@ void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
22342248
struct mpi3mr_sas_node *sas_expander;
22352249
unsigned long flags;
22362250

2237-
if (mrioc->reset_in_progress)
2251+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
22382252
return;
22392253

22402254
if (!hba_port)
@@ -2545,6 +2559,11 @@ static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
25452559
return -EFAULT;
25462560
}
25472561

2562+
if (mrioc->pci_err_recovery) {
2563+
ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
2564+
return -EFAULT;
2565+
}
2566+
25482567
data_out_sz = sizeof(struct phy_error_log_request);
25492568
data_in_sz = sizeof(struct phy_error_log_reply);
25502569
sz = data_out_sz + data_in_sz;
@@ -2804,6 +2823,12 @@ mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
28042823
return -EFAULT;
28052824
}
28062825

2826+
if (mrioc->pci_err_recovery) {
2827+
ioc_err(mrioc, "%s: pci error recovery in progress!\n",
2828+
__func__);
2829+
return -EFAULT;
2830+
}
2831+
28072832
data_out_sz = sizeof(struct phy_control_request);
28082833
data_in_sz = sizeof(struct phy_control_reply);
28092834
sz = data_out_sz + data_in_sz;
@@ -3227,6 +3252,12 @@ mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
32273252
goto out;
32283253
}
32293254

3255+
if (mrioc->pci_err_recovery) {
3256+
ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
3257+
rc = -EFAULT;
3258+
goto out;
3259+
}
3260+
32303261
rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
32313262
&dma_addr_out, &dma_len_out, &addr_out);
32323263
if (rc)

0 commit comments

Comments
 (0)