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

!5922 Some fixes and cleanups for SAS

Merge Pull Request from: @ci-robot 
 
PR sync from: Yihang Li <liyihang9@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/R2OGYPYLOL4CWT7XLNO5SD742EXEVJWF/ 
From: Bing Xia <xiabing12@h-partners.com>

This series contains some fixes and cleanups including:
- Add slave_destroy interface for v3 hw;
- Remove hisi_hba->timer for v3 hw;
- Handle the NCQ error returned by D2H frame;
- Fix disk not being scanned in after being removed;
- Add a helper sas_get_sas_addr_and_dev_type();
- Directly call register snapshot instead of using workqueue;
- Allocate DFX memory during dump trigger;
- Fix a deadlock issue related to automatic debugfs;
- Check whether debugfs is enabled before removing or releasing it;
- Check usage count only when the runtime PM status is RPM_SUSPENDING
- Remove redundant checks for automatic debugfs dump;
- Allocation SMP request is aligned to ARCH_DMA_MINALIGN;
- Modify the deadline for ata_wait_after_reset();
- Revert "scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus reset
  failure"

Qi Liu (1):
  scsi: hisi_sas: Add slave_destroy interface for v3 hw

Xiang Chen (1):
  scsi: hisi_sas: Remove hisi_hba->timer for v3 hw

Xingui Yang (3):
  scsi: hisi_sas: Handle the NCQ error returned by D2H frame
  scsi: libsas: Fix disk not being scanned in after being removed
  scsi: libsas: Add a helper sas_get_sas_addr_and_dev_type()

Yihang Li (8):
  scsi: hisi_sas: Directly call register snapshot instead of using
    workqueue
  scsi: hisi_sas: Allocate DFX memory during dump trigger
  scsi: hisi_sas: Fix a deadlock issue related to automatic dump
  scsi: hisi_sas: Check whether debugfs is enabled before removing or
    releasing it
  scsi: hisi_sas: Check usage count only when the runtime PM status is
    RPM_SUSPENDING
  scsi: hisi_sas: Remove redundant checks for automatic debugfs dump
  scsi: libsas: Allocation SMP request is aligned to ARCH_DMA_MINALIGN
  scsi: hisi_sas: Modify the deadline for ata_wait_after_reset()

xiabing (1):
  Revert "scsi: hisi_sas: Disable SATA disk phy for severe I_T nexus
    reset failure"


-- 
2.30.0
 
https://gitee.com/openeuler/kernel/issues/I96KNQ 
 
Link:https://gitee.com/openeuler/kernel/pulls/5922

 

Reviewed-by: default avatarYihang Li <liyihang9@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents d6d89d55 7065aeae
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -343,7 +343,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;
	const struct scsi_host_template *sht;
};
@@ -451,7 +451,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 */
+30 −30
Original line number Diff line number Diff line
@@ -1507,6 +1507,11 @@ void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba)
	scsi_block_requests(shost);
	hisi_hba->hw->wait_cmds_complete_timeout(hisi_hba, 100, 5000);

	/*
	 * hisi_hba->timer is only used for v1/v2 hw, and check hw->sht
	 * which is also only used for v1/v2 hw to skip it for v3 hw
	 */
	if (hisi_hba->hw->sht)
		del_timer_sync(&hisi_hba->timer);

	set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@@ -1573,7 +1578,7 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)
		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;
@@ -1791,8 +1796,10 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)

	if (dev_is_sata(device)) {
		struct ata_link *link = &device->sata_dev.ap->link;
		unsigned long deadline = ata_deadline(jiffies,
				HISI_SAS_WAIT_PHYUP_TIMEOUT / HZ * 1000);

		rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT,
		rc = ata_wait_after_reset(link, deadline,
					  smp_ata_check_ready_type);
	} else {
		msleep(2000);
@@ -1818,33 +1825,14 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
	}
	hisi_sas_dereg_device(hisi_hba, device);

	rc = hisi_sas_debug_I_T_nexus_reset(device);
	if (rc == TMF_RESP_FUNC_COMPLETE && dev_is_sata(device)) {
		struct sas_phy *local_phy;

	if (dev_is_sata(device)) {
		rc = hisi_sas_softreset_ata_disk(device);
		switch (rc) {
		case -ECOMM:
			rc = -ENODEV;
			break;
		case TMF_RESP_FUNC_FAILED:
		case -EMSGSIZE:
		case -EIO:
			local_phy = sas_get_local_phy(device);
			rc = sas_phy_enable(local_phy, 0);
			if (!rc) {
				local_phy->enabled = 0;
				dev_err(dev, "Disabled local phy of ATA disk %016llx due to softreset fail (%d)\n",
		if (rc == TMF_RESP_FUNC_FAILED)
			dev_err(dev, "ata disk %016llx reset (%d)\n",
				SAS_ADDR(device->sas_addr), rc);
				rc = -ENODEV;
			}
			sas_put_local_phy(local_phy);
			break;
		default:
			break;
		}
	}

	rc = hisi_sas_debug_I_T_nexus_reset(device);
	if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
		hisi_sas_release_task(hisi_hba, device);

@@ -1961,8 +1949,19 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct hisi_sas_internal_abort_data *timeout = data;

	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 (!timeout->rst_ha_timeout)
			down(&hisi_hba->sem);
		hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
		if (!timeout->rst_ha_timeout)
			up(&hisi_hba->sem);
	}

	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
		pr_err("Internal abort: timeout %016llx\n",
@@ -2614,6 +2613,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);
}

+74 −64
Original line number Diff line number Diff line
@@ -558,8 +558,7 @@ static int experimental_iopoll_q_cnt;
module_param(experimental_iopoll_q_cnt, int, 0444);
MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0");

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)
{
@@ -2245,7 +2244,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
		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;
@@ -2909,7 +2916,7 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
		return 0;

	if (!device_link_add(&sdev->sdev_gendev, dev,
			     DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) {
			     DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) {
		if (pm_runtime_enabled(dev)) {
			dev_info(dev, "add device link failed, disable runtime PM for the host\n");
			pm_runtime_disable(dev);
@@ -2919,6 +2926,15 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
	return 0;
}

static void slave_destroy_v3_hw(struct scsi_device *sdev)
{
	struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev);
	struct hisi_hba *hisi_hba = shost_priv(shost);
	struct device *dev = hisi_hba->dev;

	device_link_remove(&sdev->sdev_gendev, dev);
}

static struct attribute *host_v3_hw_attrs[] = {
	&dev_attr_phy_event_threshold.attr,
	&dev_attr_intr_conv_v3_hw.attr,
@@ -3335,6 +3351,7 @@ static const struct scsi_host_template sht_v3_hw = {
	.eh_device_reset_handler = sas_eh_device_reset_handler,
	.eh_target_reset_handler = sas_eh_target_reset_handler,
	.slave_alloc		= hisi_sas_slave_alloc,
	.slave_destroy		= slave_destroy_v3_hw,
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
#ifdef CONFIG_COMPAT
@@ -3388,7 +3405,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;
@@ -3860,37 +3876,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)
@@ -3898,9 +3883,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;

@@ -3910,7 +3892,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;
}
@@ -4661,14 +4648,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;
@@ -4703,7 +4682,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++) {
@@ -4783,11 +4762,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",
@@ -4874,7 +4890,6 @@ static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
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);
@@ -4891,14 +4906,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_exit_v3_hw(hisi_hba);
			dev_dbg(dev, "failed to init debugfs!\n");
			break;
		}
	}
}

static int
@@ -5032,6 +5039,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_out_remove_host:
	scsi_remove_host(shost);
err_out_undo_debugfs:
	if (hisi_sas_debugfs_enable)
		debugfs_exit_v3_hw(hisi_hba);
err_out_free_host:
	hisi_sas_free(hisi_hba);
@@ -5064,7 +5072,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
	struct Scsi_Host *shost = sha->shost;

	pm_runtime_get_noresume(dev);
	del_timer_sync(&hisi_hba->timer);

	sas_unregister_ha(sha);
	flush_workqueue(hisi_hba->wq);
@@ -5072,7 +5079,9 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)

	hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
	hisi_sas_free(hisi_hba);
	if (hisi_sas_debugfs_enable)
		debugfs_exit_v3_hw(hisi_hba);

	scsi_host_put(shost);
}

@@ -5163,7 +5172,8 @@ static int _suspend_v3_hw(struct device *device)
	interrupt_disable_v3_hw(hisi_hba);

#ifdef CONFIG_PM
	if (atomic_read(&device->power.usage_count)) {
	if ((device->power.runtime_status == RPM_SUSPENDING) &&
	    atomic_read(&device->power.usage_count)) {
		dev_err(dev, "PM suspend: host status cannot be suspended\n");
		rc = -EBUSY;
		goto err_out;
+35 −18
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,

static inline void *alloc_smp_req(int size)
{
	u8 *p = kzalloc(size, GFP_KERNEL);
	u8 *p = kzalloc(ALIGN(size, ARCH_DMA_MINALIGN), GFP_KERNEL);
	if (p)
		p[0] = SMP_REQUEST;
	return p;
@@ -1621,6 +1621,16 @@ int sas_discover_root_expander(struct domain_device *dev)

/* ---------- Domain revalidation ---------- */

static void sas_get_sas_addr_and_dev_type(struct smp_disc_resp *disc_resp,
					  u8 *sas_addr,
					  enum sas_device_type *type)
{
	memcpy(sas_addr, disc_resp->disc.attached_sas_addr, SAS_ADDR_SIZE);
	*type = to_dev_type(&disc_resp->disc);
	if (*type == SAS_PHY_UNUSED)
		memset(sas_addr, 0, SAS_ADDR_SIZE);
}

static int sas_get_phy_discover(struct domain_device *dev,
				int phy_id, struct smp_disc_resp *disc_resp)
{
@@ -1674,13 +1684,8 @@ int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
		return -ENOMEM;

	res = sas_get_phy_discover(dev, phy_id, disc_resp);
	if (res == 0) {
		memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
		       SAS_ADDR_SIZE);
		*type = to_dev_type(&disc_resp->disc);
		if (*type == 0)
			memset(sas_addr, 0, SAS_ADDR_SIZE);
	}
	if (res == 0)
		sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, type);
	kfree(disc_resp);
	return res;
}
@@ -1940,6 +1945,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
	struct expander_device *ex = &dev->ex_dev;
	struct ex_phy *phy = &ex->ex_phy[phy_id];
	enum sas_device_type type = SAS_PHY_UNUSED;
	struct smp_disc_resp *disc_resp;
	u8 sas_addr[SAS_ADDR_SIZE];
	char msg[80] = "";
	int res;
@@ -1951,33 +1957,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
		 SAS_ADDR(dev->sas_addr), phy_id, msg);

	memset(sas_addr, 0, SAS_ADDR_SIZE);
	res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
	disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
	if (!disc_resp)
		return -ENOMEM;

	res = sas_get_phy_discover(dev, phy_id, disc_resp);
	switch (res) {
	case SMP_RESP_NO_PHY:
		phy->phy_state = PHY_NOT_PRESENT;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		return res;
		goto out_free_resp;
	case SMP_RESP_PHY_VACANT:
		phy->phy_state = PHY_VACANT;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		return res;
		goto out_free_resp;
	case SMP_RESP_FUNC_ACC:
		break;
	case -ECOMM:
		break;
	default:
		return res;
		goto out_free_resp;
	}

	if (res == 0)
		sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);

	if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
		phy->phy_state = PHY_EMPTY;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		/*
		 * Even though the PHY is empty, for convenience we discover
		 * the PHY to update the PHY info, like negotiated linkrate.
		 * Even though the PHY is empty, for convenience we update
		 * the PHY info, like negotiated linkrate.
		 */
		sas_ex_phy_discover(dev, phy_id);
		return res;
		if (res == 0)
			sas_set_ex_phy(dev, phy_id, disc_resp);
		goto out_free_resp;
	} else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
		   dev_type_flutter(type, phy->attached_dev_type)) {
		struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
@@ -1989,7 +2003,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
			action = ", needs recovery";
		pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
			 SAS_ADDR(dev->sas_addr), phy_id, action);
		return res;
		goto out_free_resp;
	}

	/* we always have to delete the old device when we went here */
@@ -1998,7 +2012,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
		SAS_ADDR(phy->attached_sas_addr));
	sas_unregister_devs_sas_addr(dev, phy_id, last);

	return sas_discover_new(dev, phy_id);
	res = sas_discover_new(dev, phy_id);
out_free_resp:
	kfree(disc_resp);
	return res;
}

/**