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

!14252 【OLK-5.10】backport some bugfix of hisi_sas module from upstream

Merge Pull Request from: @slim6882 
 
| commit(from upstream) | commit_message  |
|--------|---|
|e6702e3919328b24757872cbf7f02c51894624d7|scsi: hisi_sas: Adjust priority of registering and exiting debugfs for security|
|9f564f15f88490b484e02442dc4c4b11640ea172|scsi: hisi_sas: Create trigger_dump at the end of the debugfs initialization|
|2c335fa7e69c06d8932ae8bc0ec7145de2973cf5|scsi: hisi_sas: Add firmware information check|
|08a07dc71d7fc6f58c35c4fc0bcede2811c5aa4c|scsi: hisi_sas: Enable all PHYs that are not disabled by user during controller reset|
|64359afb7068e9fd1b3ffcf7b0fefb63d1a2ccdf|scsi: hisi_sas: Reset PHY again if phyup timeout|
|90b24856b311e7e2f4f1629fb315ee50a4914aa5|scsi: hisi_sas: Update disk locked timeout to 7 seconds|
|3c62791322e42d1afd65acfdb5b3a371bde21ede|scsi: hisi_sas: Add time interval between two H2D FIS following soft reset spec|
|90f17e3431d9c643558c3c343407ee37783d5e43|scsi: hisi_sas: Update v3 hw STP_LINK_TIMER setting|
|9f564f15f88490b484e02442dc4c4b11640ea172|scsi: hisi_sas: Create all dump files during debugfs initialization|
|cae668130c07f6873718b6f5b415d22e1008f2c9|scsi: hisi_sas: Add latest_dump for the debugfs dump|
|cd982c1a|scsi: hisi_sas: Enable force phy when SATA disk directly connected| 
 
Link:https://gitee.com/openeuler/kernel/pulls/14252

 

Reviewed-by: default avatarLi Nan <linan122@huawei.com>
Reviewed-by: default avatarYihang Li <liyihang9@huawei.com>
Signed-off-by: default avatarLi Nan <linan122@huawei.com>
parents f5a62ec8 2f70a025
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ enum {

struct hisi_sas_hw {
	int (*hw_init)(struct hisi_hba *hisi_hba);
	int (*fw_info_check)(struct hisi_hba *hisi_hba);
	int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
	void (*setup_itct)(struct hisi_hba *hisi_hba,
			   struct hisi_sas_device *device);
+27 −4
Original line number Diff line number Diff line
@@ -1397,6 +1397,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
	}

	if (rc == TMF_RESP_FUNC_COMPLETE) {
		usleep_range(900, 1000);
		ata_for_each_link(link, ap, EDGE) {
			int pmp = sata_srst_pmp(link);

@@ -1475,6 +1476,7 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)

static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
{
	u32 new_state = hisi_hba->hw->get_phys_state(hisi_hba);
	struct asd_sas_port *_sas_port = NULL;
	int phy_no;

@@ -1488,7 +1490,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
			continue;

		/* Report PHY state change to libsas */
		if (state & BIT(phy_no)) {
		if (new_state & BIT(phy_no)) {
			if (do_port_check && sas_port && sas_port->port_dev) {
				struct domain_device *dev = sas_port->port_dev;

@@ -1501,6 +1503,16 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
			}
		} else {
			hisi_sas_phy_down(hisi_hba, phy_no, 0, GFP_KERNEL);

			/*
			 * The new_state is not ready but old_state is ready,
			 * the two possible causes:
			 * 1. The connected device is removed
			 * 2. Device exists but phyup timed out
			 */
			if (state & BIT(phy_no))
				hisi_sas_notify_phy_event(phy,
							  HISI_PHYE_LINK_RESET);
		}
	}
}
@@ -1642,9 +1654,15 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba)
	/* Init and wait for PHYs to come up and all libsas event finished. */
	for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
		struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
		struct asd_sas_phy *sas_phy = &phy->sas_phy;

		if (!(hisi_hba->phy_state & BIT(phy_no)))
		if (!sas_phy->phy->enabled)
			continue;

		if (!(hisi_hba->phy_state & BIT(phy_no))) {
			hisi_sas_phy_enable(hisi_hba, phy_no, 1);
			continue;
		}

		async_schedule_domain(hisi_sas_async_init_wait_phyup,
				      phy, &async);
@@ -2760,6 +2778,11 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
	if (hisi_sas_get_fw_info(hisi_hba) < 0)
		goto err_out;

	if (hisi_hba->hw->fw_info_check) {
		if (hisi_hba->hw->fw_info_check(hisi_hba))
			goto err_out;
	}

	error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
	if (error)
		error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
@@ -2946,10 +2969,10 @@ static __init int hisi_sas_init(void)

static __exit void hisi_sas_exit(void)
{
	sas_release_transport(hisi_sas_stt);

	if (hisi_sas_debugfs_enable)
		debugfs_remove(hisi_sas_debugfs_dir);

	sas_release_transport(hisi_sas_stt);
}

module_init(hisi_sas_init);
+18 −0
Original line number Diff line number Diff line
@@ -1751,6 +1751,23 @@ static struct device_attribute *host_attrs_v1_hw[] = {
	NULL
};

static int check_fw_info_v1_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;

	if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
		dev_err(dev, "invalid phy number from FW\n");
		return -EINVAL;
	}

	if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 32) {
		dev_err(dev, "invalid queue count from FW\n");
		return -EINVAL;
	}

	return 0;
}

static struct scsi_host_template sht_v1_hw = {
	.name			= DRV_NAME,
	.proc_name		= DRV_NAME,
@@ -1780,6 +1797,7 @@ static struct scsi_host_template sht_v1_hw = {

static const struct hisi_sas_hw hisi_sas_v1_hw = {
	.hw_init = hisi_sas_v1_init,
	.fw_info_check = check_fw_info_v1_hw,
	.setup_itct = setup_itct_v1_hw,
	.sl_notify_ssp = sl_notify_ssp_v1_hw,
	.clear_itct = clear_itct_v1_hw,
+25 −2
Original line number Diff line number Diff line
@@ -2511,10 +2511,15 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
	/* create header */
	/* dw0 */
	dw0 = port->id << CMD_HDR_PORT_OFF;
	if (parent_dev && dev_is_expander(parent_dev->dev_type))
	if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
		dw0 |= 3 << CMD_HDR_CMD_OFF;
	else
	} else {
		int phy_id = device->phy->identify.phy_identifier;

		dw0 |= (1U << phy_id) << CMD_HDR_PHY_ID_OFF;
		dw0 |= CMD_HDR_FORCE_PHY_MSK;
		dw0 |= 4 << CMD_HDR_CMD_OFF;
	}

	if (tmf && tmf->force_phy) {
		dw0 |= CMD_HDR_FORCE_PHY_MSK;
@@ -3567,6 +3572,23 @@ static int map_queues_v2_hw(struct Scsi_Host *shost)

}

static int check_fw_info_v2_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;

	if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
		dev_err(dev, "invalid phy number from FW\n");
		return -EINVAL;
	}

	if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
		dev_err(dev, "invalid queue count from FW\n");
		return -EINVAL;
	}

	return 0;
}

static struct scsi_host_template sht_v2_hw = {
	.name			= DRV_NAME,
	.proc_name		= DRV_NAME,
@@ -3598,6 +3620,7 @@ static struct scsi_host_template sht_v2_hw = {

static const struct hisi_sas_hw hisi_sas_v2_hw = {
	.hw_init = hisi_sas_v2_init,
	.fw_info_check = check_fw_info_v2_hw,
	.interrupt_preinit = hisi_sas_v2_interrupt_preinit,
	.setup_itct = setup_itct_v2_hw,
	.slot_index_alloc = slot_index_alloc_quirk_v2_hw,
+143 −44
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#define CQ_INT_CONVERGE_EN		0xb0
#define CFG_AGING_TIME			0xbc
#define HGC_DFX_CFG2			0xc0
#define CFG_ICT_TIMER_STEP_TRSH		0xc8
#define CFG_ABT_SET_QUERY_IPTT	0xd4
#define CFG_SET_ABORTED_IPTT_OFF	0
#define CFG_SET_ABORTED_IPTT_MSK	(0xfff << CFG_SET_ABORTED_IPTT_OFF)
@@ -357,6 +358,10 @@
#define CMD_HDR_RESP_REPORT_MSK		(0x1 << CMD_HDR_RESP_REPORT_OFF)
#define CMD_HDR_TLR_CTRL_OFF		6
#define CMD_HDR_TLR_CTRL_MSK		(0x3 << CMD_HDR_TLR_CTRL_OFF)
#define CMD_HDR_PHY_ID_OFF		8
#define CMD_HDR_PHY_ID_MSK		(0x1ff << CMD_HDR_PHY_ID_OFF)
#define CMD_HDR_FORCE_PHY_OFF		17
#define CMD_HDR_FORCE_PHY_MSK		(0x1U << CMD_HDR_FORCE_PHY_OFF)
#define CMD_HDR_PORT_OFF		18
#define CMD_HDR_PORT_MSK		(0xf << CMD_HDR_PORT_OFF)
#define CMD_HDR_PRIORITY_OFF		27
@@ -630,6 +635,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
	hisi_sas_write32(hisi_hba, TRANS_LOCK_ICT_TIME, 0x4A817C80);
	hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
	hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1);
	hisi_sas_write32(hisi_hba, CFG_ICT_TIMER_STEP_TRSH, 0xf4240);
	hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x3);
	hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0xa);
	hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0xa);
@@ -674,7 +680,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
		hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
		hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0);
		hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1);
		hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
		hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7ffffff);
		hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER, 0x2a0a01);
		hisi_sas_phy_write32(hisi_hba, i, SAS_EC_INT_COAL_TIME,
				     0x30f4240);
@@ -1422,10 +1428,16 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
	u32 dw1 = 0, dw2 = 0;

	hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
	if (parent_dev && dev_is_expander(parent_dev->dev_type))
	if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
		hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
	else
	} else {
		int phy_id = device->phy->identify.phy_identifier;

		hdr->dw0 |= cpu_to_le32((1U << phy_id)
				<< CMD_HDR_PHY_ID_OFF);
		hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
		hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF);
	}

	switch (task->data_dir) {
	case DMA_TO_DEVICE:
@@ -3327,6 +3339,23 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
	.debugfs_snapshot_regs = debugfs_snapshot_regs_v3_hw,
};

static int check_fw_info_v3_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;

	if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 8) {
		dev_err(dev, "invalid phy number from FW\n");
		return -EINVAL;
	}

	if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
		dev_err(dev, "invalid queue count from FW\n");
		return -EINVAL;
	}

	return 0;
}

static struct Scsi_Host *
hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
{
@@ -3357,6 +3386,9 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
	if (hisi_sas_get_fw_info(hisi_hba) < 0)
		goto err_out;

	if (check_fw_info_v3_hw(hisi_hba) < 0)
		goto err_out;

	if (hisi_sas_alloc(hisi_hba)) {
		hisi_sas_free(hisi_hba);
		goto err_out;
@@ -3499,6 +3531,11 @@ debugfs_to_reg_name_v3_hw(int off, int base_off,
	return NULL;
}

static bool debugfs_dump_is_generated_v3_hw(void *p)
{
	return p ? true : false;
}

static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s,
				    const struct hisi_sas_debugfs_reg *reg)
{
@@ -3524,6 +3561,9 @@ static int debugfs_global_v3_hw_show(struct seq_file *s, void *p)
{
	struct hisi_sas_debugfs_regs *global = s->private;

	if (!debugfs_dump_is_generated_v3_hw(global->data))
		return -EPERM;

	debugfs_print_reg_v3_hw(global->data, s,
				&debugfs_global_reg);

@@ -3535,6 +3575,9 @@ static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p)
{
	struct hisi_sas_debugfs_regs *axi = s->private;

	if (!debugfs_dump_is_generated_v3_hw(axi->data))
		return -EPERM;

	debugfs_print_reg_v3_hw(axi->data, s,
				&debugfs_axi_reg);

@@ -3546,6 +3589,9 @@ static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p)
{
	struct hisi_sas_debugfs_regs *ras = s->private;

	if (!debugfs_dump_is_generated_v3_hw(ras->data))
		return -EPERM;

	debugfs_print_reg_v3_hw(ras->data, s,
				&debugfs_ras_reg);

@@ -3558,6 +3604,9 @@ static int debugfs_port_v3_hw_show(struct seq_file *s, void *p)
	struct hisi_sas_debugfs_port *port = s->private;
	const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg;

	if (!debugfs_dump_is_generated_v3_hw(port->data))
		return -EPERM;

	debugfs_print_reg_v3_hw(port->data, s, reg_port);

	return 0;
@@ -3613,6 +3662,9 @@ static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p)
	struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
	int slot;

	if (!debugfs_dump_is_generated_v3_hw(debugfs_cq->complete_hdr))
		return -EPERM;

	for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
		debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq);

@@ -3634,8 +3686,12 @@ static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot,

static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p)
{
	struct hisi_sas_debugfs_dq *debugfs_dq = s->private;
	int slot;

	if (!debugfs_dump_is_generated_v3_hw(debugfs_dq->hdr))
		return -EPERM;

	for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
		debugfs_dq_show_slot_v3_hw(s, slot, s->private);

@@ -3649,6 +3705,9 @@ static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p)
	struct hisi_sas_iost *iost = debugfs_iost->iost;
	int i, max_command_entries = HISI_SAS_MAX_COMMANDS;

	if (!debugfs_dump_is_generated_v3_hw(iost))
		return -EPERM;

	for (i = 0; i < max_command_entries; i++, iost++) {
		__le64 *data = &iost->qw0;

@@ -3668,6 +3727,9 @@ static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p)
	int i, tab_idx;
	__le64 *iost;

	if (!debugfs_dump_is_generated_v3_hw(iost_cache))
		return -EPERM;

	for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
		/*
		 * Data struct of IOST cache:
@@ -3691,6 +3753,9 @@ static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p)
	struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
	struct hisi_sas_itct *itct = debugfs_itct->itct;

	if (!debugfs_dump_is_generated_v3_hw(itct))
		return -EPERM;

	for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
		__le64 *data = &itct->qw0;

@@ -3710,6 +3775,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
	int i, tab_idx;
	__le64 *itct;

	if (!debugfs_dump_is_generated_v3_hw(itct_cache))
		return -EPERM;

	for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
		/*
		 * Data struct of ITCT cache:
@@ -3727,10 +3795,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
}
DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw);

static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba, int index)
{
	u64 *debugfs_timestamp;
	int dump_index = hisi_hba->debugfs_dump_index;
	struct dentry *dump_dentry;
	struct dentry *dentry;
	char name[256];
@@ -3738,17 +3805,17 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
	int c;
	int d;

	snprintf(name, 256, "%d", dump_index);
	snprintf(name, 256, "%d", index);

	dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);

	debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
	debugfs_timestamp = &hisi_hba->debugfs_timestamp[index];

	debugfs_create_u64("timestamp", 0400, dump_dentry,
			   debugfs_timestamp);

	debugfs_create_file("global", 0400, dump_dentry,
			    &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
			    &hisi_hba->debugfs_regs[index][DEBUGFS_GLOBAL],
			    &debugfs_global_v3_hw_fops);

	/* Create port dir and files */
@@ -3757,7 +3824,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
		snprintf(name, 256, "%d", p);

		debugfs_create_file(name, 0400, dentry,
				    &hisi_hba->debugfs_port_reg[dump_index][p],
				    &hisi_hba->debugfs_port_reg[index][p],
				    &debugfs_port_v3_hw_fops);
	}

@@ -3767,7 +3834,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
		snprintf(name, 256, "%d", c);

		debugfs_create_file(name, 0400, dentry,
				    &hisi_hba->debugfs_cq[dump_index][c],
				    &hisi_hba->debugfs_cq[index][c],
				    &debugfs_cq_v3_hw_fops);
	}

@@ -3777,32 +3844,32 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
		snprintf(name, 256, "%d", d);

		debugfs_create_file(name, 0400, dentry,
				    &hisi_hba->debugfs_dq[dump_index][d],
				    &hisi_hba->debugfs_dq[index][d],
				    &debugfs_dq_v3_hw_fops);
	}

	debugfs_create_file("iost", 0400, dump_dentry,
			    &hisi_hba->debugfs_iost[dump_index],
			    &hisi_hba->debugfs_iost[index],
			    &debugfs_iost_v3_hw_fops);

	debugfs_create_file("iost_cache", 0400, dump_dentry,
			    &hisi_hba->debugfs_iost_cache[dump_index],
			    &hisi_hba->debugfs_iost_cache[index],
			    &debugfs_iost_cache_v3_hw_fops);

	debugfs_create_file("itct", 0400, dump_dentry,
			    &hisi_hba->debugfs_itct[dump_index],
			    &hisi_hba->debugfs_itct[index],
			    &debugfs_itct_v3_hw_fops);

	debugfs_create_file("itct_cache", 0400, dump_dentry,
			    &hisi_hba->debugfs_itct_cache[dump_index],
			    &hisi_hba->debugfs_itct_cache[index],
			    &debugfs_itct_cache_v3_hw_fops);

	debugfs_create_file("axi", 0400, dump_dentry,
			    &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
			    &hisi_hba->debugfs_regs[index][DEBUGFS_AXI],
			    &debugfs_axi_v3_hw_fops);

	debugfs_create_file("ras", 0400, dump_dentry,
			    &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
			    &hisi_hba->debugfs_regs[index][DEBUGFS_RAS],
			    &debugfs_ras_v3_hw_fops);
}

@@ -4584,22 +4651,34 @@ static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
	int i;

	devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
	hisi_hba->debugfs_iost_cache[dump_index].cache = NULL;
	devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
	hisi_hba->debugfs_itct_cache[dump_index].cache = NULL;
	devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
	hisi_hba->debugfs_iost[dump_index].iost = NULL;
	devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
	hisi_hba->debugfs_itct[dump_index].itct = NULL;

	for (i = 0; i < hisi_hba->queue_count; i++)
	for (i = 0; i < hisi_hba->queue_count; i++) {
		devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
		hisi_hba->debugfs_dq[dump_index][i].hdr = NULL;
	}

	for (i = 0; i < hisi_hba->queue_count; i++)
	for (i = 0; i < hisi_hba->queue_count; i++) {
		devm_kfree(dev,
			   hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
		hisi_hba->debugfs_cq[dump_index][i].complete_hdr = NULL;
	}

	for (i = 0; i < DEBUGFS_REGS_NUM; i++)
	for (i = 0; i < DEBUGFS_REGS_NUM; i++) {
		devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
		hisi_hba->debugfs_regs[dump_index][i].data = NULL;
	}

	for (i = 0; i < hisi_hba->n_phy; i++)
	for (i = 0; i < hisi_hba->n_phy; i++) {
		devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
		hisi_hba->debugfs_port_reg[dump_index][i].data = NULL;
	}
}

static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = {
@@ -4726,8 +4805,6 @@ static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
	debugfs_snapshot_itct_reg_v3_hw(hisi_hba);
	debugfs_snapshot_iost_reg_v3_hw(hisi_hba);

	debugfs_create_files_v3_hw(hisi_hba);

	debugfs_snapshot_restore_v3_hw(hisi_hba);
	hisi_hba->debugfs_dump_index++;

@@ -4811,6 +4888,34 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba)
	hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
}

static int debugfs_dump_index_v3_hw_show(struct seq_file *s, void *p)
{
	int *debugfs_dump_index = s->private;

	if (*debugfs_dump_index > 0)
		seq_printf(s, "%d\n", *debugfs_dump_index - 1);
	else
		seq_puts(s, "dump not triggered\n");

	return 0;
}
DEFINE_SHOW_ATTRIBUTE(debugfs_dump_index_v3_hw);

static void debugfs_dump_init_v3_hw(struct hisi_hba *hisi_hba)
{
	int i;

	hisi_hba->debugfs_dump_dentry =
			debugfs_create_dir("dump", hisi_hba->debugfs_dir);

	debugfs_create_file("latest_dump", 0400, hisi_hba->debugfs_dump_dentry,
			    &hisi_hba->debugfs_dump_index,
			    &debugfs_dump_index_v3_hw_fops);

	for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
		debugfs_create_files_v3_hw(hisi_hba, i);
}

static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
{
	debugfs_remove_recursive(hisi_hba->debugfs_dir);
@@ -4823,19 +4928,17 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)

	hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
						   hisi_sas_debugfs_dir);
	debugfs_create_file("trigger_dump", 0200,
			    hisi_hba->debugfs_dir,
			    hisi_hba,
			    &debugfs_trigger_dump_v3_hw_fops);

	/* create bist structures */
	debugfs_bist_init_v3_hw(hisi_hba);

	hisi_hba->debugfs_dump_dentry =
			debugfs_create_dir("dump", hisi_hba->debugfs_dir);
	debugfs_dump_init_v3_hw(hisi_hba);

	debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
	debugfs_fifo_init_v3_hw(hisi_hba);
	debugfs_create_file("trigger_dump", 0200,
			    hisi_hba->debugfs_dir,
			    hisi_hba,
			    &debugfs_trigger_dump_v3_hw_fops);
}

static int
@@ -4882,7 +4985,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	if (!hisi_hba->regs) {
		dev_err(dev, "cannot map register\n");
		rc = -ENOMEM;
		goto err_out_ha;
		goto err_out_free_host;
	}

	phy_nr = port_nr = hisi_hba->n_phy;
@@ -4891,7 +4994,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
	if (!arr_phy || !arr_port) {
		rc = -ENOMEM;
		goto err_out_ha;
		goto err_out_free_host;
	}

	sha->sas_phy = arr_phy;
@@ -4927,16 +5030,13 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
					    SHOST_DIX_GUARD_CRC);
	}

	if (hisi_sas_debugfs_enable)
		debugfs_init_v3_hw(hisi_hba);

	rc = interrupt_preinit_v3_hw(hisi_hba);
	if (rc)
		goto err_out_debugfs;
	dev_err(dev, "%d hw queues\n", shost->nr_hw_queues);
		goto err_out_free_host;

	rc = scsi_add_host(shost, dev);
	if (rc)
		goto err_out_debugfs;
		goto err_out_free_host;

	rc = sas_register_ha(sha);
	if (rc)
@@ -4947,6 +5047,8 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
		goto err_out_hw_init;

	scsi_scan_host(shost);
	if (hisi_sas_debugfs_enable)
		debugfs_init_v3_hw(hisi_hba);

	pm_runtime_set_autosuspend_delay(dev, 5000);
	pm_runtime_use_autosuspend(dev);
@@ -4967,10 +5069,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	sas_unregister_ha(sha);
err_out_register_ha:
	scsi_remove_host(shost);
err_out_debugfs:
	if (hisi_sas_debugfs_enable)
		debugfs_exit_v3_hw(hisi_hba);
err_out_ha:
err_out_free_host:
	hisi_sas_free(hisi_hba);
	scsi_host_put(shost);
err_out_regions:
@@ -5005,6 +5104,8 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
	struct Scsi_Host *shost = sha->core.shost;

	pm_runtime_get_noresume(dev);
	if (hisi_sas_debugfs_enable)
		debugfs_exit_v3_hw(hisi_hba);

	sas_unregister_ha(sha);
	flush_workqueue(hisi_hba->wq);
@@ -5014,8 +5115,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	hisi_sas_free(hisi_hba);
	if (hisi_sas_debugfs_enable)
		debugfs_exit_v3_hw(hisi_hba);
	scsi_host_put(shost);
}