diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-09-06 19:28:07 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-07 15:20:23 -0500 |
commit | a01e70e570a72b8a8c9a58062e4f5bdcd3986222 (patch) | |
tree | d2b8b5e0e69d14805ac98033561597de6e24d5c6 /drivers/scsi/libsas/sas_init.c | |
parent | d24e1eeb3a16e4944288c2f3bf082e1513f4b425 (diff) |
[SCSI] aci94xx: implement link rate setting
This patch implements the ability to set the minimum and maximum
linkrates for both libsas (for expanders) and aic94xx (for the host
phys). It also tidies up the setting of the hardware min and max to
make sure they're updated when the expander emits a change broadcast.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_init.c')
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index b961664b810..c836a237fb7 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -159,17 +159,57 @@ static int sas_phy_reset(struct sas_phy *phy, int hard_reset) struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); - ret = i->dft->lldd_control_phy(asd_phy, reset_type); + ret = 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); - ret = sas_smp_phy_control(ddev, phy->number, reset_type); + ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL); } return ret; } +static int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates) +{ + int ret; + + if ((rates->minimum_linkrate && + rates->minimum_linkrate > phy->maximum_linkrate) || + (rates->maximum_linkrate && + rates->maximum_linkrate < phy->minimum_linkrate)) + return -EINVAL; + + if (rates->minimum_linkrate && + rates->minimum_linkrate < phy->minimum_linkrate_hw) + rates->minimum_linkrate = phy->minimum_linkrate_hw; + + if (rates->maximum_linkrate && + rates->maximum_linkrate > phy->maximum_linkrate_hw) + rates->maximum_linkrate = phy->maximum_linkrate_hw; + + if (scsi_is_sas_phy_local(phy)) { + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); + struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; + struct sas_internal *i = + to_sas_internal(sas_ha->core.shost->transportt); + + ret = i->dft->lldd_control_phy(asd_phy, PHY_FUNC_SET_LINK_RATE, + rates); + } else { + struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); + struct domain_device *ddev = sas_find_dev_by_rphy(rphy); + ret = sas_smp_phy_control(ddev, phy->number, + PHY_FUNC_LINK_RESET, rates); + + } + + return ret; +} + static struct sas_function_template sft = { .phy_reset = sas_phy_reset, + .set_phy_speed = sas_set_phy_speed, .get_linkerrors = sas_get_linkerrors, }; |