Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab526633 authored by Dan Williams's avatar Dan Williams Committed by James Bottomley
Browse files

[SCSI] libsas: route local link resets through ata-eh



Similar to the conversion of the transport-class reset we want bsg
initiated resets to be managed by libata.

Reported-by: default avatarJacek Danecki <jacek.danecki@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent d230ce69
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -187,11 +187,14 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
	struct sas_internal *i =
		to_sas_internal(sas_ha->core.shost->transportt);
	struct sas_phy_linkrates rates;
	struct asd_sas_phy *asd_phy;

	if (phy_id >= sas_ha->num_phys) {
		resp_data[2] = SMP_RESP_NO_PHY;
		return;
	}

	asd_phy = sas_ha->sas_phy[phy_id];
	switch (phy_op) {
	case PHY_FUNC_NOP:
	case PHY_FUNC_LINK_RESET:
@@ -210,7 +213,13 @@ static void sas_phy_control(struct sas_ha_struct *sas_ha, u8 phy_id,
	rates.minimum_linkrate = min;
	rates.maximum_linkrate = max;

	if (i->dft->lldd_control_phy(sas_ha->sas_phy[phy_id], phy_op, &rates))
	/* filter reset requests through libata eh */
	if (phy_op == PHY_FUNC_LINK_RESET && sas_try_ata_reset(asd_phy) == 0) {
		resp_data[2] = SMP_RESP_FUNC_ACC;
		return;
	}

	if (i->dft->lldd_control_phy(asd_phy, phy_op, &rates))
		resp_data[2] = SMP_RESP_FUNC_FAILED;
	else
		resp_data[2] = SMP_RESP_FUNC_ACC;
+26 −19
Original line number Diff line number Diff line
@@ -196,6 +196,27 @@ static int sas_get_linkerrors(struct sas_phy *phy)
	return sas_smp_get_phy_events(phy);
}

int sas_try_ata_reset(struct asd_sas_phy *asd_phy)
{
	struct domain_device *dev = NULL;

	/* try to route user requested link resets through libata */
	if (asd_phy->port)
		dev = asd_phy->port->port_dev;

	/* validate that dev has been probed */
	if (dev)
		dev = sas_find_dev_by_rphy(dev->rphy);

	if (dev && dev_is_sata(dev)) {
		sas_ata_schedule_reset(dev);
		sas_ata_wait_eh(dev);
		return 0;
	}

	return -ENODEV;
}

/**
 * transport_sas_phy_reset - reset a phy and permit libata to manage the link
 *
@@ -204,7 +225,6 @@ static int sas_get_linkerrors(struct sas_phy *phy)
 */
static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
{
	int ret;
	enum phy_func reset_type;

	if (hard_reset)
@@ -218,21 +238,10 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
		struct sas_internal *i =
			to_sas_internal(sas_ha->core.shost->transportt);
		struct domain_device *dev = NULL;

		if (asd_phy->port)
			dev = asd_phy->port->port_dev;

		/* validate that dev has been probed */
		if (dev)
			dev = sas_find_dev_by_rphy(dev->rphy);

		if (dev && dev_is_sata(dev) && !hard_reset) {
			sas_ata_schedule_reset(dev);
			sas_ata_wait_eh(dev);
			ret = 0;
		} else
			ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
		if (!hard_reset && sas_try_ata_reset(asd_phy) == 0)
			return 0;
		return i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
	} else {
		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
@@ -241,12 +250,10 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
		if (ata_dev && !hard_reset) {
			sas_ata_schedule_reset(ata_dev);
			sas_ata_wait_eh(ata_dev);
			ret = 0;
			return 0;
		} else
			ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
			return sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
	}

	return ret;
}

static int sas_phy_enable(struct sas_phy *phy, int enable)
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
int sas_get_phy_attached_sas_addr(struct domain_device *dev, int phy_id,
				  u8 *attached_sas_addr);
int sas_try_ata_reset(struct asd_sas_phy *phy);
void sas_hae_reset(struct work_struct *work);

void sas_free_device(struct kref *kref);