diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_transport.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_transport.c | 196 |
1 files changed, 182 insertions, 14 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 3a82872bad44..789f9ee7f001 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
@@ -855,6 +855,17 @@ rphy_to_ioc(struct sas_rphy *rphy) | |||
855 | return shost_priv(shost); | 855 | return shost_priv(shost); |
856 | } | 856 | } |
857 | 857 | ||
858 | static struct _sas_phy * | ||
859 | _transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy) | ||
860 | { | ||
861 | int i; | ||
862 | |||
863 | for (i = 0; i < ioc->sas_hba.num_phys; i++) | ||
864 | if (ioc->sas_hba.phy[i].phy == phy) | ||
865 | return(&ioc->sas_hba.phy[i]); | ||
866 | return NULL; | ||
867 | } | ||
868 | |||
858 | /** | 869 | /** |
859 | * _transport_get_linkerrors - | 870 | * _transport_get_linkerrors - |
860 | * @phy: The sas phy object | 871 | * @phy: The sas phy object |
@@ -870,14 +881,8 @@ _transport_get_linkerrors(struct sas_phy *phy) | |||
870 | struct _sas_phy *mpt2sas_phy; | 881 | struct _sas_phy *mpt2sas_phy; |
871 | Mpi2ConfigReply_t mpi_reply; | 882 | Mpi2ConfigReply_t mpi_reply; |
872 | Mpi2SasPhyPage1_t phy_pg1; | 883 | Mpi2SasPhyPage1_t phy_pg1; |
873 | int i; | ||
874 | 884 | ||
875 | for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys && | 885 | mpt2sas_phy = _transport_find_local_phy(ioc, phy); |
876 | !mpt2sas_phy; i++) { | ||
877 | if (ioc->sas_hba.phy[i].phy != phy) | ||
878 | continue; | ||
879 | mpt2sas_phy = &ioc->sas_hba.phy[i]; | ||
880 | } | ||
881 | 886 | ||
882 | if (!mpt2sas_phy) /* this phy not on sas_host */ | 887 | if (!mpt2sas_phy) /* this phy not on sas_host */ |
883 | return -EINVAL; | 888 | return -EINVAL; |
@@ -971,14 +976,8 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset) | |||
971 | struct _sas_phy *mpt2sas_phy; | 976 | struct _sas_phy *mpt2sas_phy; |
972 | Mpi2SasIoUnitControlReply_t mpi_reply; | 977 | Mpi2SasIoUnitControlReply_t mpi_reply; |
973 | Mpi2SasIoUnitControlRequest_t mpi_request; | 978 | Mpi2SasIoUnitControlRequest_t mpi_request; |
974 | int i; | ||
975 | 979 | ||
976 | for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys && | 980 | mpt2sas_phy = _transport_find_local_phy(ioc, phy); |
977 | !mpt2sas_phy; i++) { | ||
978 | if (ioc->sas_hba.phy[i].phy != phy) | ||
979 | continue; | ||
980 | mpt2sas_phy = &ioc->sas_hba.phy[i]; | ||
981 | } | ||
982 | 981 | ||
983 | if (!mpt2sas_phy) /* this phy not on sas_host */ | 982 | if (!mpt2sas_phy) /* this phy not on sas_host */ |
984 | return -EINVAL; | 983 | return -EINVAL; |
@@ -1006,6 +1005,173 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset) | |||
1006 | } | 1005 | } |
1007 | 1006 | ||
1008 | /** | 1007 | /** |
1008 | * _transport_phy_enable - enable/disable phys | ||
1009 | * @phy: The sas phy object | ||
1010 | * @enable: enable phy when true | ||
1011 | * | ||
1012 | * Only support sas_host direct attached phys. | ||
1013 | * Returns 0 for success, non-zero for failure. | ||
1014 | */ | ||
1015 | static int | ||
1016 | _transport_phy_enable(struct sas_phy *phy, int enable) | ||
1017 | { | ||
1018 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
1019 | struct _sas_phy *mpt2sas_phy; | ||
1020 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
1021 | Mpi2ConfigReply_t mpi_reply; | ||
1022 | u16 ioc_status; | ||
1023 | u16 sz; | ||
1024 | int rc = 0; | ||
1025 | |||
1026 | mpt2sas_phy = _transport_find_local_phy(ioc, phy); | ||
1027 | |||
1028 | if (!mpt2sas_phy) /* this phy not on sas_host */ | ||
1029 | return -EINVAL; | ||
1030 | |||
1031 | /* sas_iounit page 1 */ | ||
1032 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | ||
1033 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
1034 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
1035 | if (!sas_iounit_pg1) { | ||
1036 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1037 | ioc->name, __FILE__, __LINE__, __func__); | ||
1038 | rc = -ENOMEM; | ||
1039 | goto out; | ||
1040 | } | ||
1041 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
1042 | sas_iounit_pg1, sz))) { | ||
1043 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1044 | ioc->name, __FILE__, __LINE__, __func__); | ||
1045 | rc = -ENXIO; | ||
1046 | goto out; | ||
1047 | } | ||
1048 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
1049 | MPI2_IOCSTATUS_MASK; | ||
1050 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
1051 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1052 | ioc->name, __FILE__, __LINE__, __func__); | ||
1053 | rc = -EIO; | ||
1054 | goto out; | ||
1055 | } | ||
1056 | |||
1057 | if (enable) | ||
1058 | sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags | ||
1059 | &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; | ||
1060 | else | ||
1061 | sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags | ||
1062 | |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; | ||
1063 | |||
1064 | mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); | ||
1065 | |||
1066 | out: | ||
1067 | kfree(sas_iounit_pg1); | ||
1068 | return rc; | ||
1069 | } | ||
1070 | |||
1071 | /** | ||
1072 | * _transport_phy_speed - set phy min/max link rates | ||
1073 | * @phy: The sas phy object | ||
1074 | * @rates: rates defined in sas_phy_linkrates | ||
1075 | * | ||
1076 | * Only support sas_host direct attached phys. | ||
1077 | * Returns 0 for success, non-zero for failure. | ||
1078 | */ | ||
1079 | static int | ||
1080 | _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) | ||
1081 | { | ||
1082 | struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy); | ||
1083 | struct _sas_phy *mpt2sas_phy; | ||
1084 | Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; | ||
1085 | Mpi2SasPhyPage0_t phy_pg0; | ||
1086 | Mpi2ConfigReply_t mpi_reply; | ||
1087 | u16 ioc_status; | ||
1088 | u16 sz; | ||
1089 | int i; | ||
1090 | int rc = 0; | ||
1091 | |||
1092 | mpt2sas_phy = _transport_find_local_phy(ioc, phy); | ||
1093 | |||
1094 | if (!mpt2sas_phy) /* this phy not on sas_host */ | ||
1095 | return -EINVAL; | ||
1096 | |||
1097 | if (!rates->minimum_linkrate) | ||
1098 | rates->minimum_linkrate = phy->minimum_linkrate; | ||
1099 | else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) | ||
1100 | rates->minimum_linkrate = phy->minimum_linkrate_hw; | ||
1101 | |||
1102 | if (!rates->maximum_linkrate) | ||
1103 | rates->maximum_linkrate = phy->maximum_linkrate; | ||
1104 | else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) | ||
1105 | rates->maximum_linkrate = phy->maximum_linkrate_hw; | ||
1106 | |||
1107 | /* sas_iounit page 1 */ | ||
1108 | sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * | ||
1109 | sizeof(Mpi2SasIOUnit1PhyData_t)); | ||
1110 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ||
1111 | if (!sas_iounit_pg1) { | ||
1112 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1113 | ioc->name, __FILE__, __LINE__, __func__); | ||
1114 | rc = -ENOMEM; | ||
1115 | goto out; | ||
1116 | } | ||
1117 | if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, | ||
1118 | sas_iounit_pg1, sz))) { | ||
1119 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1120 | ioc->name, __FILE__, __LINE__, __func__); | ||
1121 | rc = -ENXIO; | ||
1122 | goto out; | ||
1123 | } | ||
1124 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
1125 | MPI2_IOCSTATUS_MASK; | ||
1126 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
1127 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1128 | ioc->name, __FILE__, __LINE__, __func__); | ||
1129 | rc = -EIO; | ||
1130 | goto out; | ||
1131 | } | ||
1132 | |||
1133 | for (i = 0; i < ioc->sas_hba.num_phys; i++) { | ||
1134 | if (mpt2sas_phy->phy_id != i) { | ||
1135 | sas_iounit_pg1->PhyData[i].MaxMinLinkRate = | ||
1136 | (ioc->sas_hba.phy[i].phy->minimum_linkrate + | ||
1137 | (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); | ||
1138 | } else { | ||
1139 | sas_iounit_pg1->PhyData[i].MaxMinLinkRate = | ||
1140 | (rates->minimum_linkrate + | ||
1141 | (rates->maximum_linkrate << 4)); | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, | ||
1146 | sz)) { | ||
1147 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1148 | ioc->name, __FILE__, __LINE__, __func__); | ||
1149 | rc = -ENXIO; | ||
1150 | goto out; | ||
1151 | } | ||
1152 | |||
1153 | /* link reset */ | ||
1154 | _transport_phy_reset(phy, 0); | ||
1155 | |||
1156 | /* read phy page 0, then update the rates in the sas transport phy */ | ||
1157 | if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, | ||
1158 | mpt2sas_phy->phy_id)) { | ||
1159 | phy->minimum_linkrate = _transport_convert_phy_link_rate( | ||
1160 | phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); | ||
1161 | phy->maximum_linkrate = _transport_convert_phy_link_rate( | ||
1162 | phy_pg0.ProgrammedLinkRate >> 4); | ||
1163 | phy->negotiated_linkrate = _transport_convert_phy_link_rate( | ||
1164 | phy_pg0.NegotiatedLinkRate & | ||
1165 | MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); | ||
1166 | } | ||
1167 | |||
1168 | out: | ||
1169 | kfree(sas_iounit_pg1); | ||
1170 | return rc; | ||
1171 | } | ||
1172 | |||
1173 | |||
1174 | /** | ||
1009 | * _transport_smp_handler - transport portal for smp passthru | 1175 | * _transport_smp_handler - transport portal for smp passthru |
1010 | * @shost: shost object | 1176 | * @shost: shost object |
1011 | * @rphy: sas transport rphy object | 1177 | * @rphy: sas transport rphy object |
@@ -1207,6 +1373,8 @@ struct sas_function_template mpt2sas_transport_functions = { | |||
1207 | .get_enclosure_identifier = _transport_get_enclosure_identifier, | 1373 | .get_enclosure_identifier = _transport_get_enclosure_identifier, |
1208 | .get_bay_identifier = _transport_get_bay_identifier, | 1374 | .get_bay_identifier = _transport_get_bay_identifier, |
1209 | .phy_reset = _transport_phy_reset, | 1375 | .phy_reset = _transport_phy_reset, |
1376 | .phy_enable = _transport_phy_enable, | ||
1377 | .set_phy_speed = _transport_phy_speed, | ||
1210 | .smp_handler = _transport_smp_handler, | 1378 | .smp_handler = _transport_smp_handler, |
1211 | }; | 1379 | }; |
1212 | 1380 | ||