diff options
| author | Joachim Fenkes <fenkes@de.ibm.com> | 2009-09-05 23:22:55 -0400 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2009-09-05 23:22:55 -0400 |
| commit | d706834d995939c96b4952bf042918879b4db18b (patch) | |
| tree | 68dcb2f6075f155e0c47cb9f61160df9442dcb3d | |
| parent | 50d40b8e53fab58b0141a75f7448eb28f9e21338 (diff) | |
IB/ehca: Construct MAD redirect replies from request MAD
The old code used a lot of hard-coded values, which might not be valid
in all environments (especially routed fabrics or partitioned
subnets). Copy as much information as possible from the incoming
request to correct that.
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
| -rw-r--r-- | drivers/infiniband/hw/ehca/ehca_sqp.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index c568b28f4e20..8c1213f8916a 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c | |||
| @@ -125,14 +125,30 @@ struct ib_perf { | |||
| 125 | u8 data[192]; | 125 | u8 data[192]; |
| 126 | } __attribute__ ((packed)); | 126 | } __attribute__ ((packed)); |
| 127 | 127 | ||
| 128 | /* TC/SL/FL packed into 32 bits, as in ClassPortInfo */ | ||
| 129 | struct tcslfl { | ||
| 130 | u32 tc:8; | ||
| 131 | u32 sl:4; | ||
| 132 | u32 fl:20; | ||
| 133 | } __attribute__ ((packed)); | ||
| 134 | |||
| 135 | /* IP Version/TC/FL packed into 32 bits, as in GRH */ | ||
| 136 | struct vertcfl { | ||
| 137 | u32 ver:4; | ||
| 138 | u32 tc:8; | ||
| 139 | u32 fl:20; | ||
| 140 | } __attribute__ ((packed)); | ||
| 128 | 141 | ||
| 129 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | 142 | static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, |
| 143 | struct ib_wc *in_wc, struct ib_grh *in_grh, | ||
| 130 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 144 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 131 | { | 145 | { |
| 132 | struct ib_perf *in_perf = (struct ib_perf *)in_mad; | 146 | struct ib_perf *in_perf = (struct ib_perf *)in_mad; |
| 133 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; | 147 | struct ib_perf *out_perf = (struct ib_perf *)out_mad; |
| 134 | struct ib_class_port_info *poi = | 148 | struct ib_class_port_info *poi = |
| 135 | (struct ib_class_port_info *)out_perf->data; | 149 | (struct ib_class_port_info *)out_perf->data; |
| 150 | struct tcslfl *tcslfl = | ||
| 151 | (struct tcslfl *)&poi->redirect_tcslfl; | ||
| 136 | struct ehca_shca *shca = | 152 | struct ehca_shca *shca = |
| 137 | container_of(ibdev, struct ehca_shca, ib_device); | 153 | container_of(ibdev, struct ehca_shca, ib_device); |
| 138 | struct ehca_sport *sport = &shca->sport[port_num - 1]; | 154 | struct ehca_sport *sport = &shca->sport[port_num - 1]; |
| @@ -158,10 +174,29 @@ static int ehca_process_perf(struct ib_device *ibdev, u8 port_num, | |||
| 158 | poi->base_version = 1; | 174 | poi->base_version = 1; |
| 159 | poi->class_version = 1; | 175 | poi->class_version = 1; |
| 160 | poi->resp_time_value = 18; | 176 | poi->resp_time_value = 18; |
| 161 | poi->redirect_lid = sport->saved_attr.lid; | 177 | |
| 162 | poi->redirect_qp = sport->pma_qp_nr; | 178 | /* copy local routing information from WC where applicable */ |
| 179 | tcslfl->sl = in_wc->sl; | ||
| 180 | poi->redirect_lid = | ||
| 181 | sport->saved_attr.lid | in_wc->dlid_path_bits; | ||
| 182 | poi->redirect_qp = sport->pma_qp_nr; | ||
| 163 | poi->redirect_qkey = IB_QP1_QKEY; | 183 | poi->redirect_qkey = IB_QP1_QKEY; |
| 164 | poi->redirect_pkey = IB_DEFAULT_PKEY_FULL; | 184 | |
| 185 | ehca_query_pkey(ibdev, port_num, in_wc->pkey_index, | ||
| 186 | &poi->redirect_pkey); | ||
| 187 | |||
| 188 | /* if request was globally routed, copy route info */ | ||
| 189 | if (in_grh) { | ||
| 190 | struct vertcfl *vertcfl = | ||
| 191 | (struct vertcfl *)&in_grh->version_tclass_flow; | ||
| 192 | memcpy(poi->redirect_gid, in_grh->dgid.raw, | ||
| 193 | sizeof(poi->redirect_gid)); | ||
| 194 | tcslfl->tc = vertcfl->tc; | ||
| 195 | tcslfl->fl = vertcfl->fl; | ||
| 196 | } else | ||
| 197 | /* else only fill in default GID */ | ||
| 198 | ehca_query_gid(ibdev, port_num, 0, | ||
| 199 | (union ib_gid *)&poi->redirect_gid); | ||
| 165 | 200 | ||
| 166 | ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x", | 201 | ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x", |
| 167 | sport->saved_attr.lid, sport->pma_qp_nr); | 202 | sport->saved_attr.lid, sport->pma_qp_nr); |
| @@ -183,8 +218,7 @@ perf_reply: | |||
| 183 | 218 | ||
| 184 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | 219 | int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, |
| 185 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 220 | struct ib_wc *in_wc, struct ib_grh *in_grh, |
| 186 | struct ib_mad *in_mad, | 221 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
| 187 | struct ib_mad *out_mad) | ||
| 188 | { | 222 | { |
| 189 | int ret; | 223 | int ret; |
| 190 | 224 | ||
| @@ -196,7 +230,8 @@ int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
| 196 | return IB_MAD_RESULT_SUCCESS; | 230 | return IB_MAD_RESULT_SUCCESS; |
| 197 | 231 | ||
| 198 | ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp); | 232 | ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp); |
| 199 | ret = ehca_process_perf(ibdev, port_num, in_mad, out_mad); | 233 | ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh, |
| 234 | in_mad, out_mad); | ||
| 200 | 235 | ||
| 201 | return ret; | 236 | return ret; |
| 202 | } | 237 | } |
