Unverified Commit ae344b95 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!508 SCSI: SSSRAID: Fix the bug that system automatically reboot when issue a...

!508 SCSI: SSSRAID: Fix the bug that system automatically reboot when issue a 'pcie-linkdown' command

Merge Pull Request from: @steven-song3 
 

[steps to reproduce the bug]
1. Create classic RAID1 and RAID5
2. Issue read & write mixed I/O to the drive letters corresponding to
RAID1 and RAID5
3. In the process of reading and writing I/O,issue a 'pcie-linkdown'
command by a serial port
[Expected results]
The I/O rate is 0 temporarily, and after a period of time the IO is
interrupted, the system will not automatically restart, and the RAID
card will not be unhealthy after manual restart.
[Root cause]
'pcie-linkdown' will trigger I/O timeout and firmware hang dead, and driver
will try to access firmware when it dead, Multiple accesses cause this
bug.
[Solution]
Remove communication with firmware in I/O timeout process when firmware
hang dead. 
 
Link:https://gitee.com/openeuler/kernel/pulls/508

 

Reviewed-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 38138a0b 1d48701c
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -58,7 +58,8 @@
#define SSSRAID_ADM_QUEUE_NUM 1
#define SSSRAID_ADM_QUEUE_NUM 1
#define SSSRAID_PTCMDS_PERQ 1
#define SSSRAID_PTCMDS_PERQ 1
#define SSSRAID_IO_BLK_MQ_DEPTH (sdioc->scsi_qd)
#define SSSRAID_IO_BLK_MQ_DEPTH (sdioc->scsi_qd)
#define SSSRAID_NR_IOQ_PTCMDS (SSSRAID_PTCMDS_PERQ * sdioc->shost->nr_hw_queues)
#define SSSRAID_NR_HW_QUEUES (sdioc->init_done_queue_cnt - 1)
#define SSSRAID_NR_IOQ_PTCMDS (SSSRAID_PTCMDS_PERQ * SSSRAID_NR_HW_QUEUES)


#define FUA_MASK 0x08
#define FUA_MASK 0x08
#define SSSRAID_MINORS BIT(MINORBITS)
#define SSSRAID_MINORS BIT(MINORBITS)
+27 −15
Original line number Original line Diff line number Diff line
@@ -1316,7 +1316,7 @@ int sssraid_init_ioc(struct sssraid_ioc *sdioc, u8 re_init)
	/* num_vecs no sense, abandon */
	/* num_vecs no sense, abandon */


	if (!re_init) {
	if (!re_init) {
		for (i = sdioc->init_done_queue_cnt; i <= sdioc->intr_info_count; i++) {
		for (i = sdioc->init_done_queue_cnt; i < sdioc->intr_info_count; i++) {
			retval = sssraid_alloc_qpair(sdioc, i, sdioc->ioq_depth);
			retval = sssraid_alloc_qpair(sdioc, i, sdioc->ioq_depth);
			if (retval) {
			if (retval) {
				ioc_err(sdioc, "Failed to alloc io queue:error %d\n",
				ioc_err(sdioc, "Failed to alloc io queue:error %d\n",
@@ -1631,27 +1631,30 @@ void sssraid_complete_cqes(struct sssraid_ioc *sdioc, u16 midx, u16 start, u16 e
	}
	}
}
}


static void sssraid_disable_admin_queue(struct sssraid_ioc *sdioc, bool shutdown)
static int sssraid_disable_admin_queue(struct sssraid_ioc *sdioc, bool shutdown)
{
{
	struct sssraid_cqueue *adm_cqinfo = &sdioc->cqinfo[0];
	struct sssraid_cqueue *adm_cqinfo = &sdioc->cqinfo[0];
	u16 start, end;
	u16 start, end;
	int ret = 0;


	if (pci_device_is_present(sdioc->pdev)) {
	if (pci_device_is_present(sdioc->pdev)) {
		if (shutdown)
		if (shutdown)
			sssraid_shutdown_ctrl(sdioc);
			sssraid_shutdown_ctrl(sdioc);
		else
		else
			sssraid_disable_ctrl(sdioc);
			ret = sssraid_disable_ctrl(sdioc);
	}
	}


	if (sdioc->init_done_queue_cnt == 0) {
	if (sdioc->init_done_queue_cnt == 0) {
		ioc_err(sdioc, "err: admin queue has been delete\n");
		ioc_err(sdioc, "err: admin queue has been delete\n");
		return;
		return -ENODEV;
	}
	}


	spin_lock_irq(&adm_cqinfo->cq_lock);
	spin_lock_irq(&adm_cqinfo->cq_lock);
	sssraid_process_cq(sdioc, 0, &start, &end, -1);
	sssraid_process_cq(sdioc, 0, &start, &end, -1);
	spin_unlock_irq(&adm_cqinfo->cq_lock);
	spin_unlock_irq(&adm_cqinfo->cq_lock);
	sssraid_complete_cqes(sdioc, 0, start, end);
	sssraid_complete_cqes(sdioc, 0, start, end);

	return ret;
}
}


static void sssraid_free_all_queues(struct sssraid_ioc *sdioc)
static void sssraid_free_all_queues(struct sssraid_ioc *sdioc)
@@ -1722,29 +1725,38 @@ int sssraid_soft_reset_handler(struct sssraid_ioc *sdioc)


	ioc_info(sdioc, "host reset entry\n");
	ioc_info(sdioc, "host reset entry\n");


	sssraid_ioc_disable_intr(sdioc);
	sssraid_cleanup_fwevt_list(sdioc);
	sssraid_cleanup_fwevt_list(sdioc);


	/* realize above here:
	 * sssraid_dev_disable -> sssraid_back_all_io
	 */
	sssraid_back_all_io(sdioc);
	/*
	/*
	 * realize sssraid_dev_disable,
	 * realize sssraid_dev_disable,
	 * i.e. sssraid_cleanup_ioc(1)
	 * i.e. sssraid_cleanup_ioc(1)
	 */
	 */
	if (sdioc->ctrl_config & SSSRAID_CC_ENABLE) {
	if (sdioc->ctrl_config & SSSRAID_CC_ENABLE) {
		ioc_info(sdioc, "start cleanup ioc\n");
		ioc_info(sdioc, "start disable admin queue\n");
		sssraid_cleanup_ioc(sdioc, 1);
		retval = sssraid_disable_admin_queue(sdioc, 0);
	}
	}


	sssraid_cleanup_resources(sdioc);

	/* realize above here:
	 * sssraid_dev_disable -> sssraid_back_all_io
	 */
	sssraid_back_all_io(sdioc);

	if (retval)
		goto host_reset_failed;

	retval = sssraid_init_ioc(sdioc, 1);
	retval = sssraid_init_ioc(sdioc, 1);
	if (retval) {
	if (retval)
		ioc_err(sdioc, "err: init ioc fail.\n");
		goto cleanup_resources;
		return retval;
	}


	sssraid_change_host_state(sdioc, SSSRAID_LIVE);
	sssraid_change_host_state(sdioc, SSSRAID_LIVE);
	return 0;


cleanup_resources:
	sssraid_cleanup_resources(sdioc);
host_reset_failed:
	sssraid_change_host_state(sdioc, SSSRAID_DEAD);
	ioc_err(sdioc, "err, host reset failed\n");
	return retval;
	return retval;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -566,7 +566,7 @@ static void sssraid_shost_init(struct sssraid_ioc *sdioc)
	bus = pdev->bus->number;
	bus = pdev->bus->number;
	dev_func = pdev->devfn;
	dev_func = pdev->devfn;


	sdioc->shost->nr_hw_queues = sdioc->init_done_queue_cnt - 1;
	sdioc->shost->nr_hw_queues = SSSRAID_NR_HW_QUEUES;
	sdioc->shost->can_queue = (sdioc->ioq_depth - SSSRAID_PTCMDS_PERQ);
	sdioc->shost->can_queue = (sdioc->ioq_depth - SSSRAID_PTCMDS_PERQ);


	sdioc->shost->sg_tablesize = le16_to_cpu(sdioc->ctrl_info->max_num_sge);
	sdioc->shost->sg_tablesize = le16_to_cpu(sdioc->ctrl_info->max_num_sge);