diff options
author | Joachim Fenkes <fenkes@de.ibm.com> | 2007-07-09 09:21:45 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-07-09 23:12:27 -0400 |
commit | 91f13aa3fc22e357b494c5b8270e94543870928d (patch) | |
tree | e8f78c2549945f5e3bc42e33ce81a18a9292f746 | |
parent | b8a3ba551369982180917a999d32fcedbba34115 (diff) |
IB/ehca: HW level, HW caps and MTU autodetection
In preparation for support of new eHCA2 features, change adapter probing:
- Hardware level is changed to encode major and minor chip version
- Hardware capabilities are queried from the firmware
- The maximum MTU is queried from the firmware instead of assuming a
fixed value
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_av.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_hca.c | 27 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 62 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/hipz_hw.h | 18 |
5 files changed, 104 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c index 0d6e2c4bb245..3cd6bf3402d1 100644 --- a/drivers/infiniband/hw/ehca/ehca_av.c +++ b/drivers/infiniband/hw/ehca/ehca_av.c | |||
@@ -118,7 +118,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) | |||
118 | } | 118 | } |
119 | memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); | 119 | memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); |
120 | } | 120 | } |
121 | av->av.pmtu = EHCA_MAX_MTU; | 121 | av->av.pmtu = shca->max_mtu; |
122 | 122 | ||
123 | /* dgid comes in grh.word_3 */ | 123 | /* dgid comes in grh.word_3 */ |
124 | memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, | 124 | memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, |
@@ -137,6 +137,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) | |||
137 | struct ehca_av *av; | 137 | struct ehca_av *av; |
138 | struct ehca_ud_av new_ehca_av; | 138 | struct ehca_ud_av new_ehca_av; |
139 | struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); | 139 | struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); |
140 | struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca, | ||
141 | ib_device); | ||
140 | u32 cur_pid = current->tgid; | 142 | u32 cur_pid = current->tgid; |
141 | 143 | ||
142 | if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && | 144 | if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && |
@@ -192,7 +194,7 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) | |||
192 | memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); | 194 | memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); |
193 | } | 195 | } |
194 | 196 | ||
195 | new_ehca_av.pmtu = EHCA_MAX_MTU; | 197 | new_ehca_av.pmtu = shca->max_mtu; |
196 | 198 | ||
197 | memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, | 199 | memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, |
198 | sizeof(ah_attr->grh.dgid)); | 200 | sizeof(ah_attr->grh.dgid)); |
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 1d286d3cc2d5..35d948f2502c 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -107,6 +107,8 @@ struct ehca_shca { | |||
107 | struct ehca_pd *pd; | 107 | struct ehca_pd *pd; |
108 | struct h_galpas galpas; | 108 | struct h_galpas galpas; |
109 | struct mutex modify_mutex; | 109 | struct mutex modify_mutex; |
110 | u64 hca_cap; | ||
111 | int max_mtu; | ||
110 | }; | 112 | }; |
111 | 113 | ||
112 | struct ehca_pd { | 114 | struct ehca_pd { |
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 32b55a4f0e5b..b310de5c94ae 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c | |||
@@ -45,11 +45,25 @@ | |||
45 | 45 | ||
46 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | 46 | int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) |
47 | { | 47 | { |
48 | int ret = 0; | 48 | int i, ret = 0; |
49 | struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, | 49 | struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, |
50 | ib_device); | 50 | ib_device); |
51 | struct hipz_query_hca *rblock; | 51 | struct hipz_query_hca *rblock; |
52 | 52 | ||
53 | static const u32 cap_mapping[] = { | ||
54 | IB_DEVICE_RESIZE_MAX_WR, HCA_CAP_WQE_RESIZE, | ||
55 | IB_DEVICE_BAD_PKEY_CNTR, HCA_CAP_BAD_P_KEY_CTR, | ||
56 | IB_DEVICE_BAD_QKEY_CNTR, HCA_CAP_Q_KEY_VIOL_CTR, | ||
57 | IB_DEVICE_RAW_MULTI, HCA_CAP_RAW_PACKET_MCAST, | ||
58 | IB_DEVICE_AUTO_PATH_MIG, HCA_CAP_AUTO_PATH_MIG, | ||
59 | IB_DEVICE_CHANGE_PHY_PORT, HCA_CAP_SQD_RTS_PORT_CHANGE, | ||
60 | IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK, | ||
61 | IB_DEVICE_CURR_QP_STATE_MOD, HCA_CAP_CUR_QP_STATE_MOD, | ||
62 | IB_DEVICE_SHUTDOWN_PORT, HCA_CAP_SHUTDOWN_PORT, | ||
63 | IB_DEVICE_INIT_TYPE, HCA_CAP_INIT_TYPE, | ||
64 | IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT, | ||
65 | }; | ||
66 | |||
53 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 67 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); |
54 | if (!rblock) { | 68 | if (!rblock) { |
55 | ehca_err(&shca->ib_device, "Can't allocate rblock memory."); | 69 | ehca_err(&shca->ib_device, "Can't allocate rblock memory."); |
@@ -96,6 +110,13 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | |||
96 | props->max_total_mcast_qp_attach | 110 | props->max_total_mcast_qp_attach |
97 | = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); | 111 | = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); |
98 | 112 | ||
113 | /* translate device capabilities */ | ||
114 | props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID | | ||
115 | IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ; | ||
116 | for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2) | ||
117 | if (rblock->hca_cap_indicators & cap_mapping[i + 1]) | ||
118 | props->device_cap_flags |= cap_mapping[i]; | ||
119 | |||
99 | query_device1: | 120 | query_device1: |
100 | ehca_free_fw_ctrlblock(rblock); | 121 | ehca_free_fw_ctrlblock(rblock); |
101 | 122 | ||
@@ -261,7 +282,7 @@ int ehca_modify_port(struct ib_device *ibdev, | |||
261 | } | 282 | } |
262 | 283 | ||
263 | if (mutex_lock_interruptible(&shca->modify_mutex)) | 284 | if (mutex_lock_interruptible(&shca->modify_mutex)) |
264 | return -ERESTARTSYS; | 285 | return -ERESTARTSYS; |
265 | 286 | ||
266 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 287 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); |
267 | if (!rblock) { | 288 | if (!rblock) { |
@@ -290,7 +311,7 @@ modify_port2: | |||
290 | ehca_free_fw_ctrlblock(rblock); | 311 | ehca_free_fw_ctrlblock(rblock); |
291 | 312 | ||
292 | modify_port1: | 313 | modify_port1: |
293 | mutex_unlock(&shca->modify_mutex); | 314 | mutex_unlock(&shca->modify_mutex); |
294 | 315 | ||
295 | return ret; | 316 | return ret; |
296 | } | 317 | } |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index fea199f01eaa..eb22a6b296d9 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -205,11 +205,35 @@ static void ehca_destroy_slab_caches(void) | |||
205 | #define EHCA_HCAAVER EHCA_BMASK_IBM(32,39) | 205 | #define EHCA_HCAAVER EHCA_BMASK_IBM(32,39) |
206 | #define EHCA_REVID EHCA_BMASK_IBM(40,63) | 206 | #define EHCA_REVID EHCA_BMASK_IBM(40,63) |
207 | 207 | ||
208 | static struct cap_descr { | ||
209 | u64 mask; | ||
210 | char *descr; | ||
211 | } hca_cap_descr[] = { | ||
212 | { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" }, | ||
213 | { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" }, | ||
214 | { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" }, | ||
215 | { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" }, | ||
216 | { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" }, | ||
217 | { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" }, | ||
218 | { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" }, | ||
219 | { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" }, | ||
220 | { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" }, | ||
221 | { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" }, | ||
222 | { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" }, | ||
223 | { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" }, | ||
224 | { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" }, | ||
225 | { HCA_CAP_SRQ, "HCA_CAP_SRQ" }, | ||
226 | { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" }, | ||
227 | { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" }, | ||
228 | { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" }, | ||
229 | }; | ||
230 | |||
208 | int ehca_sense_attributes(struct ehca_shca *shca) | 231 | int ehca_sense_attributes(struct ehca_shca *shca) |
209 | { | 232 | { |
210 | int ret = 0; | 233 | int i, ret = 0; |
211 | u64 h_ret; | 234 | u64 h_ret; |
212 | struct hipz_query_hca *rblock; | 235 | struct hipz_query_hca *rblock; |
236 | struct hipz_query_port *port; | ||
213 | 237 | ||
214 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 238 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); |
215 | if (!rblock) { | 239 | if (!rblock) { |
@@ -222,7 +246,7 @@ int ehca_sense_attributes(struct ehca_shca *shca) | |||
222 | ehca_gen_err("Cannot query device properties. h_ret=%lx", | 246 | ehca_gen_err("Cannot query device properties. h_ret=%lx", |
223 | h_ret); | 247 | h_ret); |
224 | ret = -EPERM; | 248 | ret = -EPERM; |
225 | goto num_ports1; | 249 | goto sense_attributes1; |
226 | } | 250 | } |
227 | 251 | ||
228 | if (ehca_nr_ports == 1) | 252 | if (ehca_nr_ports == 1) |
@@ -242,18 +266,44 @@ int ehca_sense_attributes(struct ehca_shca *shca) | |||
242 | ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid); | 266 | ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid); |
243 | 267 | ||
244 | if ((hcaaver == 1) && (revid == 0)) | 268 | if ((hcaaver == 1) && (revid == 0)) |
245 | shca->hw_level = 0; | 269 | shca->hw_level = 0x11; |
246 | else if ((hcaaver == 1) && (revid == 1)) | 270 | else if ((hcaaver == 1) && (revid == 1)) |
247 | shca->hw_level = 1; | 271 | shca->hw_level = 0x12; |
248 | else if ((hcaaver == 1) && (revid == 2)) | 272 | else if ((hcaaver == 1) && (revid == 2)) |
249 | shca->hw_level = 2; | 273 | shca->hw_level = 0x13; |
274 | else if ((hcaaver == 2) && (revid == 0)) | ||
275 | shca->hw_level = 0x21; | ||
276 | else if ((hcaaver == 2) && (revid == 0x10)) | ||
277 | shca->hw_level = 0x22; | ||
278 | else { | ||
279 | ehca_gen_warn("unknown hardware version" | ||
280 | " - assuming default level"); | ||
281 | shca->hw_level = 0x22; | ||
282 | } | ||
250 | } | 283 | } |
251 | ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); | 284 | ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); |
252 | 285 | ||
253 | shca->sport[0].rate = IB_RATE_30_GBPS; | 286 | shca->sport[0].rate = IB_RATE_30_GBPS; |
254 | shca->sport[1].rate = IB_RATE_30_GBPS; | 287 | shca->sport[1].rate = IB_RATE_30_GBPS; |
255 | 288 | ||
256 | num_ports1: | 289 | shca->hca_cap = rblock->hca_cap_indicators; |
290 | ehca_gen_dbg(" ... HCA capabilities:"); | ||
291 | for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++) | ||
292 | if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap)) | ||
293 | ehca_gen_dbg(" %s", hca_cap_descr[i].descr); | ||
294 | |||
295 | port = (struct hipz_query_port *) rblock; | ||
296 | h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port); | ||
297 | if (h_ret != H_SUCCESS) { | ||
298 | ehca_gen_err("Cannot query port properties. h_ret=%lx", | ||
299 | h_ret); | ||
300 | ret = -EPERM; | ||
301 | goto sense_attributes1; | ||
302 | } | ||
303 | |||
304 | shca->max_mtu = port->max_mtu; | ||
305 | |||
306 | sense_attributes1: | ||
257 | ehca_free_fw_ctrlblock(rblock); | 307 | ehca_free_fw_ctrlblock(rblock); |
258 | return ret; | 308 | return ret; |
259 | } | 309 | } |
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h index fad91368dc5a..9116fc943fee 100644 --- a/drivers/infiniband/hw/ehca/hipz_hw.h +++ b/drivers/infiniband/hw/ehca/hipz_hw.h | |||
@@ -360,6 +360,24 @@ struct hipz_query_hca { | |||
360 | u32 max_neq; | 360 | u32 max_neq; |
361 | } __attribute__ ((packed)); | 361 | } __attribute__ ((packed)); |
362 | 362 | ||
363 | #define HCA_CAP_AH_PORT_NR_CHECK EHCA_BMASK_IBM( 0, 0) | ||
364 | #define HCA_CAP_ATOMIC EHCA_BMASK_IBM( 1, 1) | ||
365 | #define HCA_CAP_AUTO_PATH_MIG EHCA_BMASK_IBM( 2, 2) | ||
366 | #define HCA_CAP_BAD_P_KEY_CTR EHCA_BMASK_IBM( 3, 3) | ||
367 | #define HCA_CAP_SQD_RTS_PORT_CHANGE EHCA_BMASK_IBM( 4, 4) | ||
368 | #define HCA_CAP_CUR_QP_STATE_MOD EHCA_BMASK_IBM( 5, 5) | ||
369 | #define HCA_CAP_INIT_TYPE EHCA_BMASK_IBM( 6, 6) | ||
370 | #define HCA_CAP_PORT_ACTIVE_EVENT EHCA_BMASK_IBM( 7, 7) | ||
371 | #define HCA_CAP_Q_KEY_VIOL_CTR EHCA_BMASK_IBM( 8, 8) | ||
372 | #define HCA_CAP_WQE_RESIZE EHCA_BMASK_IBM( 9, 9) | ||
373 | #define HCA_CAP_RAW_PACKET_MCAST EHCA_BMASK_IBM(10, 10) | ||
374 | #define HCA_CAP_SHUTDOWN_PORT EHCA_BMASK_IBM(11, 11) | ||
375 | #define HCA_CAP_RC_LL_QP EHCA_BMASK_IBM(12, 12) | ||
376 | #define HCA_CAP_SRQ EHCA_BMASK_IBM(13, 13) | ||
377 | #define HCA_CAP_UD_LL_QP EHCA_BMASK_IBM(16, 16) | ||
378 | #define HCA_CAP_RESIZE_MR EHCA_BMASK_IBM(17, 17) | ||
379 | #define HCA_CAP_MINI_QP EHCA_BMASK_IBM(18, 18) | ||
380 | |||
363 | /* query port response block */ | 381 | /* query port response block */ |
364 | struct hipz_query_port { | 382 | struct hipz_query_port { |
365 | u32 state; | 383 | u32 state; |