diff mbox series

[1/2] scsi: libsas: Add sas_update_linkrate()

Message ID 20221020141635.2479412-2-liyihang9@huawei.com (mailing list archive)
State Not Applicable
Headers show
Series Check and update the device link rate during discovery | expand

Commit Message

Yihang Li Oct. 20, 2022, 2:16 p.m. UTC
Add support for updates the link rate of all expander devices and
expander SATA PHYs connected to the port and triggers revalidation.

Signed-off-by: Yihang Li <liyihang9@huawei.com>
---
 drivers/scsi/libsas/sas_expander.c | 40 ++++++++++++++++++++++++++++++
 drivers/scsi/libsas/sas_internal.h |  1 +
 2 files changed, 41 insertions(+)
diff mbox series

Patch

diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index a18259f68c40..0cfb98c791c9 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -2029,6 +2029,46 @@  static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old)
 	return false;
 }
 
+void sas_update_linkrate(struct asd_sas_port *port)
+{
+	struct domain_device *parent, *dev, *n;
+	struct sas_phy *local_phy;
+	struct ex_phy *ex_phy;
+	int phy_id;
+
+	list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) {
+		if (dev_is_expander(dev->dev_type)) {
+			dev->linkrate = port->linkrate;
+			dev->min_linkrate = port->linkrate;
+			dev->max_linkrate = port->linkrate;
+			dev->ex_dev.ex_change_count = -1;
+		}
+
+		local_phy = sas_get_local_phy(dev);
+		if (scsi_is_sas_phy_local(local_phy)) {
+			sas_put_local_phy(local_phy);
+			continue;
+		}
+
+		parent = dev->parent;
+		phy_id = local_phy->number;
+		ex_phy = &parent->ex_dev.ex_phy[phy_id];
+		if (dev_is_sata(dev)) {
+			if (dev->linkrate > parent->min_linkrate) {
+				struct sas_phy_linkrates rates = {
+					.maximum_linkrate = parent->min_linkrate,
+					.minimum_linkrate = parent->min_linkrate,
+				};
+
+				sas_smp_phy_control(parent, phy_id,
+						    PHY_FUNC_LINK_RESET, &rates);
+				ex_phy->phy_change_count = -1;
+			}
+		}
+		sas_put_local_phy(local_phy);
+	}
+}
+
 void async_sas_ex_phy_refresh_linkrate(void *data, async_cookie_t cookie)
 {
 	struct domain_device *dev = data;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 591b217b0813..fc976043a523 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -36,6 +36,7 @@  int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf);
 
 int  sas_register_phys(struct sas_ha_struct *sas_ha);
 void sas_unregister_phys(struct sas_ha_struct *sas_ha);
+void sas_update_linkrate(struct asd_sas_port *port);
 void async_sas_ex_phy_refresh_linkrate(void *data, async_cookie_t cookie);
 
 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, gfp_t gfp_flags);