@@ -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;
@@ -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);
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(+)