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

!3203 Some fixes and optimizations for hisi_sas

Merge Pull Request from: @xia-bing1 
 
This patchset includes some changes for hisi_sas:
- Fix NULL pointer issue when removing debugfs.
- Directly calling register snapshot instead of workqueue.
- Allocate debugfs memory during triggering debugfs dump.
- Fix issue that device is not found because .phy_attached is not set.
- Replace with standard error code return value.
- Check the variable slot before use it.
- Clear HISI_SAS_RESET_BIT, release hisi_hba semaphore, unblock the
  scsi host, clear HISI_SAS_REJECT_CMD_BIT if FLR failed.
- Use the correct number of registers when reading register information.
- Fix warnings detected by sparse
- Handle the NCQ error returned by D2H frame
 
 
Link:https://gitee.com/openeuler/kernel/pulls/3203

 

Reviewed-by: default avatarYihang Li <liyihang9@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents d90cff02 bf870808
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -351,7 +351,7 @@ struct hisi_sas_hw {
				u8 reg_index, u8 reg_count, u8 *write_data);
	void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba,
					   int delay_ms, int timeout_ms);
	void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
	int (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
	int complete_hdr_size;
	struct scsi_host_template *sht;
};
@@ -459,7 +459,6 @@ struct hisi_hba {
	const struct hisi_sas_hw *hw;	/* Low level hw interface */
	unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)];
	struct work_struct rst_work;
	struct work_struct debugfs_work;
	u32 phy_state;
	u32 intr_coal_ticks;	/* Time of interrupt coalesce in us */
	u32 intr_coal_count;	/* Interrupt count to coalesce */
+24 −13
Original line number Diff line number Diff line
@@ -1531,16 +1531,11 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
	struct device *dev = hisi_hba->dev;
	int s = sizeof(struct host_to_dev_fis);
	int rc = TMF_RESP_FUNC_FAILED;
	struct asd_sas_phy *sas_phy;
	struct ata_link *link;
	u8 fis[20] = {0};
	u32 state;
	int i;

	state = hisi_hba->hw->get_phys_state(hisi_hba);
	for (i = 0; i < hisi_hba->n_phy; i++) {
		if (!(state & BIT(sas_phy->id)))
			continue;
		if (!(sas_port->phy_mask & BIT(i)))
			continue;

@@ -1669,15 +1664,15 @@ EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done);
static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)
{
	if (!hisi_hba->hw->soft_reset)
		return -1;
		return -ENOENT;

	down(&hisi_hba->sem);
	if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
		up(&hisi_hba->sem);
		return -1;
		return -EPERM;
	}

	if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
	if (hisi_sas_debugfs_enable)
		hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);

	return 0;
@@ -1746,7 +1741,10 @@ static int hisi_sas_abort_task(struct sas_task *task)
	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	if (slot && task->task_proto & SAS_PROTOCOL_SSP) {
	if (!slot)
		goto out;

	if (task->task_proto & SAS_PROTOCOL_SSP) {
		struct scsi_cmnd *cmnd = task->uldd_task;
		u16 tag = slot->idx;
		int rc2;
@@ -1803,7 +1801,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
				rc = hisi_sas_softreset_ata_disk(device);
			}
		}
	} else if (slot && task->task_proto & SAS_PROTOCOL_SMP) {
	} else if (task->task_proto & SAS_PROTOCOL_SMP) {
		/* SMP */
		u32 tag = slot->idx;
		struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
@@ -2215,8 +2213,20 @@ _hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,

	/* Internal abort timed out */
	if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
		if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
			queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
		if (hisi_sas_debugfs_enable) {
			/*
			 * If timeout occurs in device gone scenario, to avoid
			 * circular dependency like:
			 * hisi_sas_dev_gone() -> down() -> ... ->
			 * hisi_sas_internal_abort_timeout() -> down().
			 */
			if (!rst_to_recover)
				down(&hisi_hba->sem);

			hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
			if (!rst_to_recover)
				up(&hisi_hba->sem);
		}

		if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
			struct hisi_sas_slot *slot = task->lldd_task;
@@ -2932,6 +2942,7 @@ static __exit void hisi_sas_exit(void)
{
	sas_release_transport(hisi_sas_stt);

	if (hisi_sas_debugfs_enable)
		debugfs_remove(hisi_sas_debugfs_dir);
}

+9 −2
Original line number Diff line number Diff line
@@ -2026,6 +2026,11 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
	u16 dma_tx_err_type = le16_to_cpu(err_record->dma_tx_err_type);
	u16 sipc_rx_err_type = le16_to_cpu(err_record->sipc_rx_err_type);
	u32 dma_rx_err_type = le32_to_cpu(err_record->dma_rx_err_type);
	struct hisi_sas_complete_v2_hdr *complete_queue =
			hisi_hba->complete_hdr[slot->cmplt_queue];
	struct hisi_sas_complete_v2_hdr *complete_hdr =
			&complete_queue[slot->cmplt_queue_slot];
	u32 dw0 = le32_to_cpu(complete_hdr->dw0);
	int error = -1;

	if (err_phase == 1) {
@@ -2310,6 +2315,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
			break;
		}
		}
		if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
			hisi_sas_sata_done(task, slot);
	}
		break;
@@ -2446,6 +2452,7 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba,
	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
	{
		ts->stat = SAS_SAM_STAT_GOOD;
		if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
			hisi_sas_sata_done(task, slot);
		break;
	}
+86 −78
Original line number Diff line number Diff line
@@ -550,8 +550,7 @@ static int prot_mask;
module_param(prot_mask, int, 0444);
MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 ");

static void debugfs_work_handler_v3_hw(struct work_struct *work);
static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);

static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
{
@@ -1598,6 +1597,11 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
	}

	phy->port_id = port_id;
	spin_lock(&phy->lock);
	/* Delete timer and set phy_attached atomically */
	del_timer(&phy->timer);
	phy->phy_attached = 1;
	spin_unlock(&phy->lock);

	/*
	 * Call pm_runtime_get_noresume() which pairs with
@@ -1611,11 +1615,6 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)

	res = IRQ_HANDLED;

	spin_lock(&phy->lock);
	/* Delete timer and set phy_attached atomically */
	del_timer(&phy->timer);
	phy->phy_attached = 1;
	spin_unlock(&phy->lock);
end:
	if (phy->reset_completion)
		complete(phy->reset_completion);
@@ -2211,6 +2210,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
	u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type);
	u16 sipc_rx_err_type = le16_to_cpu(record->sipc_rx_err_type);
	u32 dw3 = le32_to_cpu(complete_hdr->dw3);
	u32 dw0 = le32_to_cpu(complete_hdr->dw0);

	switch (task->task_proto) {
	case SAS_PROTOCOL_SSP:
@@ -2220,8 +2220,8 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
			 * but I/O information has been written to the host memory, we examine
			 * response IU.
			 */
			if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) &&
				(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))
			if (!(dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) &&
			    (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))
				return false;

			ts->residual = trans_tx_fail_type;
@@ -2237,9 +2237,17 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
	case SAS_PROTOCOL_SATA:
	case SAS_PROTOCOL_STP:
	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
		if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
		if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
		    (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) {
			if (task->ata_task.use_ncq) {
				struct domain_device *device = task->dev;
				struct hisi_sas_device *sas_dev =
						device->lldd_dev;
				sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR;
				slot->abort = 1;
			} else {
				ts->stat = SAS_PROTO_RESPONSE;
			}
		} else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
			ts->residual = trans_tx_fail_type;
			ts->stat = SAS_DATA_UNDERRUN;
@@ -2251,6 +2259,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
			ts->stat = SAS_OPEN_REJECT;
			ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
		}
		if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
			hisi_sas_sata_done(task, slot);
		break;
	case SAS_PROTOCOL_SMP:
@@ -2381,6 +2390,7 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
	case SAS_PROTOCOL_STP:
	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
		ts->stat = SAS_SAM_STAT_GOOD;
		if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
			hisi_sas_sata_done(task, slot);
		break;
	default:
@@ -3333,7 +3343,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
	hisi_hba = shost_priv(shost);

	INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
	INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw);
	hisi_hba->hw = &hisi_sas_v3_hw;
	hisi_hba->pci_dev = pdev;
	hisi_hba->dev = dev;
@@ -3416,7 +3425,7 @@ static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba)
	u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
	int i;

	for (i = 0; i < debugfs_axi_reg.count; i++, databuf++)
	for (i = 0; i < debugfs_global_reg.count; i++, databuf++)
		*databuf = hisi_sas_read32(hisi_hba, 4 * i);
}

@@ -3798,37 +3807,6 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
			    &debugfs_ras_v3_hw_fops);
}

static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
{
	int debugfs_dump_index = hisi_hba->debugfs_dump_index;
	struct device *dev = hisi_hba->dev;
	u64 timestamp = local_clock();

	if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
		dev_warn(dev, "dump count exceeded!\n");
		return;
	}

	do_div(timestamp, NSEC_PER_MSEC);
	hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;

	debugfs_snapshot_prepare_v3_hw(hisi_hba);

	debugfs_snapshot_global_reg_v3_hw(hisi_hba);
	debugfs_snapshot_port_reg_v3_hw(hisi_hba);
	debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
	debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
	debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
	debugfs_snapshot_dq_reg_v3_hw(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++;
}

static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
						const char __user *user_buf,
						size_t count, loff_t *ppos)
@@ -3836,9 +3814,6 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
	struct hisi_hba *hisi_hba = file->f_inode->i_private;
	char buf[8];

	if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
		return -EFAULT;

	if (count > 8)
		return -EFAULT;

@@ -3848,7 +3823,12 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
	if (buf[0] != '1')
		return -EFAULT;

	queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
	down(&hisi_hba->sem);
	if (debugfs_snapshot_regs_v3_hw(hisi_hba)) {
		up(&hisi_hba->sem);
		return -EFAULT;
	}
	up(&hisi_hba->sem);

	return count;
}
@@ -4599,14 +4579,6 @@ static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba)
	}
}

static void debugfs_work_handler_v3_hw(struct work_struct *work)
{
	struct hisi_hba *hisi_hba =
		container_of(work, struct hisi_hba, debugfs_work);

	debugfs_snapshot_regs_v3_hw(hisi_hba);
}

static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
{
	struct device *dev = hisi_hba->dev;
@@ -4641,7 +4613,7 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
{
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	struct device *dev = hisi_hba->dev;
	int p, c, d, r, i;
	int p, c, d, r;
	size_t sz;

	for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
@@ -4721,11 +4693,48 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)

	return 0;
fail:
	for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
		debugfs_release_v3_hw(hisi_hba, i);
	debugfs_release_v3_hw(hisi_hba, dump_index);
	return -ENOMEM;
}

static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
{
	int debugfs_dump_index = hisi_hba->debugfs_dump_index;
	struct device *dev = hisi_hba->dev;
	u64 timestamp = local_clock();

	if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
		dev_warn(dev, "dump count exceeded!\n");
		return -EINVAL;
	}

	if (debugfs_alloc_v3_hw(hisi_hba, debugfs_dump_index)) {
		dev_warn(dev, "failed to alloc memory\n");
		return -ENOMEM;
	}

	do_div(timestamp, NSEC_PER_MSEC);
	hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;

	debugfs_snapshot_prepare_v3_hw(hisi_hba);

	debugfs_snapshot_global_reg_v3_hw(hisi_hba);
	debugfs_snapshot_port_reg_v3_hw(hisi_hba);
	debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
	debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
	debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
	debugfs_snapshot_dq_reg_v3_hw(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++;

	return 0;
}

static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba)
{
	struct dentry *dir = debugfs_create_dir("phy_down_cnt",
@@ -4803,10 +4812,15 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba)
	hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
}

static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
{
	debugfs_remove_recursive(hisi_hba->debugfs_dir);
	hisi_hba->debugfs_dir = NULL;
}

static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;
	int i;

	hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
						   hisi_sas_debugfs_dir);
@@ -4823,19 +4837,6 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)

	debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
	debugfs_fifo_init_v3_hw(hisi_hba);

	for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
		if (debugfs_alloc_v3_hw(hisi_hba, i)) {
			debugfs_remove_recursive(hisi_hba->debugfs_dir);
			dev_dbg(dev, "failed to init debugfs!\n");
			break;
		}
	}
}

static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
{
	debugfs_remove_recursive(hisi_hba->debugfs_dir);
}

static int
@@ -4968,6 +4969,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
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:
	hisi_sas_free(hisi_hba);
@@ -5015,6 +5017,7 @@ 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);
}
@@ -5041,6 +5044,7 @@ static void hisi_sas_reset_done_v3_hw(struct pci_dev *pdev)
{
	struct sas_ha_struct *sha = pci_get_drvdata(pdev);
	struct hisi_hba *hisi_hba = sha->lldd_ha;
	struct Scsi_Host *shost = hisi_hba->shost;
	struct device *dev = hisi_hba->dev;
	int rc;

@@ -5049,6 +5053,10 @@ static void hisi_sas_reset_done_v3_hw(struct pci_dev *pdev)
	rc = hw_init_v3_hw(hisi_hba);
	if (rc) {
		dev_err(dev, "FLR: hw init failed rc=%d\n", rc);
		clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
		scsi_unblock_requests(shost);
		clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
		up(&hisi_hba->sem);
		return;
	}

@@ -5091,7 +5099,7 @@ static int _suspend_v3_hw(struct device *device)
	}

	if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
		return -1;
		return -EPERM;

	dev_warn(dev, "entering suspend state\n");