aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-09-06 20:28:07 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-07 16:20:23 -0400
commita01e70e570a72b8a8c9a58062e4f5bdcd3986222 (patch)
treed2b8b5e0e69d14805ac98033561597de6e24d5c6 /drivers/scsi/aic94xx
parentd24e1eeb3a16e4944288c2f3bf082e1513f4b425 (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/aic94xx')
-rw-r--r--drivers/scsi/aic94xx/aic94xx.h2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c30
2 files changed, 29 insertions, 3 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index cb7caf1c9ce1..1bd5b4ecf3d5 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -109,6 +109,6 @@ int asd_clear_nexus_port(struct asd_sas_port *port);
109int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha); 109int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha);
110 110
111/* ---------- Phy Management ---------- */ 111/* ---------- Phy Management ---------- */
112int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func); 112int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg);
113 113
114#endif 114#endif
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index ef8ca08b545f..7ee49b51b724 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -52,6 +52,8 @@
52 52
53static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode) 53static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
54{ 54{
55 struct sas_phy *sas_phy = phy->sas_phy.phy;
56
55 switch (oob_mode & 7) { 57 switch (oob_mode & 7) {
56 case PHY_SPEED_60: 58 case PHY_SPEED_60:
57 /* FIXME: sas transport class doesn't have this */ 59 /* FIXME: sas transport class doesn't have this */
@@ -67,6 +69,12 @@ static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
67 phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; 69 phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
68 break; 70 break;
69 } 71 }
72 sas_phy->negotiated_linkrate = phy->sas_phy.linkrate;
73 sas_phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
74 sas_phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
75 sas_phy->maximum_linkrate = phy->phy_desc->max_sas_lrate;
76 sas_phy->minimum_linkrate = phy->phy_desc->min_sas_lrate;
77
70 if (oob_mode & SAS_MODE) 78 if (oob_mode & SAS_MODE)
71 phy->sas_phy.oob_mode = SAS_OOB_MODE; 79 phy->sas_phy.oob_mode = SAS_OOB_MODE;
72 else if (oob_mode & SATA_MODE) 80 else if (oob_mode & SATA_MODE)
@@ -710,14 +718,32 @@ static const int phy_func_table[] = {
710 [PHY_FUNC_RELEASE_SPINUP_HOLD] = RELEASE_SPINUP_HOLD, 718 [PHY_FUNC_RELEASE_SPINUP_HOLD] = RELEASE_SPINUP_HOLD,
711}; 719};
712 720
713int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func) 721int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
714{ 722{
715 struct asd_ha_struct *asd_ha = phy->ha->lldd_ha; 723 struct asd_ha_struct *asd_ha = phy->ha->lldd_ha;
724 struct asd_phy_desc *pd = asd_ha->phys[phy->id].phy_desc;
716 struct asd_ascb *ascb; 725 struct asd_ascb *ascb;
726 struct sas_phy_linkrates *rates;
717 int res = 1; 727 int res = 1;
718 728
719 if (func == PHY_FUNC_CLEAR_ERROR_LOG) 729 switch (func) {
730 case PHY_FUNC_CLEAR_ERROR_LOG:
720 return -ENOSYS; 731 return -ENOSYS;
732 case PHY_FUNC_SET_LINK_RATE:
733 rates = arg;
734 if (rates->minimum_linkrate) {
735 pd->min_sas_lrate = rates->minimum_linkrate;
736 pd->min_sata_lrate = rates->minimum_linkrate;
737 }
738 if (rates->maximum_linkrate) {
739 pd->max_sas_lrate = rates->maximum_linkrate;
740 pd->max_sata_lrate = rates->maximum_linkrate;
741 }
742 func = PHY_FUNC_LINK_RESET;
743 break;
744 default:
745 break;
746 }
721 747
722 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); 748 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
723 if (!ascb) 749 if (!ascb)