diff options
author | Joachim Fenkes <fenkes@de.ibm.com> | 2007-10-16 11:31:14 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-10-18 00:47:24 -0400 |
commit | abc39d3672d8af4bf6c943faf85fa8877caccf7e (patch) | |
tree | c90456ddae53b1ce39cd604404d3810e3b499a27 /drivers/infiniband/hw | |
parent | 8c08d50d4fc52a9367c356ebbeb194c30fbc7ac8 (diff) |
IB/ehca: Change meaning of hca_cap_mr_pgsize
ehca_shca.hca_cap_mr_pgsize now contains all supported page sizes ORed
together. This makes some checks easier to code and understand, plus
we can return this value verbatim in query_hca(), fixing a problem
with SRP (reported by Anton Blanchard -- thanks!).
Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_hca.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 18 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_mrmw.c | 38 |
4 files changed, 36 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0f7a55d35ea7..365bc5dfcc88 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -323,7 +323,6 @@ extern int ehca_static_rate; | |||
323 | extern int ehca_port_act_time; | 323 | extern int ehca_port_act_time; |
324 | extern int ehca_use_hp_mr; | 324 | extern int ehca_use_hp_mr; |
325 | extern int ehca_scaling_code; | 325 | extern int ehca_scaling_code; |
326 | extern int ehca_mr_largepage; | ||
327 | 326 | ||
328 | struct ipzu_queue_resp { | 327 | struct ipzu_queue_resp { |
329 | u32 qe_size; /* queue entry size */ | 328 | u32 qe_size; /* queue entry size */ |
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 4aa3ffa6a19f..15806d140461 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c | |||
@@ -77,6 +77,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | memset(props, 0, sizeof(struct ib_device_attr)); | 79 | memset(props, 0, sizeof(struct ib_device_attr)); |
80 | props->page_size_cap = shca->hca_cap_mr_pgsize; | ||
80 | props->fw_ver = rblock->hw_ver; | 81 | props->fw_ver = rblock->hw_ver; |
81 | props->max_mr_size = rblock->max_mr_size; | 82 | props->max_mr_size = rblock->max_mr_size; |
82 | props->vendor_id = rblock->vendor_id >> 8; | 83 | props->vendor_id = rblock->vendor_id >> 8; |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 403467f66fe6..d477dc3b4760 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -260,13 +260,20 @@ static struct cap_descr { | |||
260 | { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" }, | 260 | { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" }, |
261 | }; | 261 | }; |
262 | 262 | ||
263 | int ehca_sense_attributes(struct ehca_shca *shca) | 263 | static int ehca_sense_attributes(struct ehca_shca *shca) |
264 | { | 264 | { |
265 | int i, ret = 0; | 265 | int i, ret = 0; |
266 | u64 h_ret; | 266 | u64 h_ret; |
267 | struct hipz_query_hca *rblock; | 267 | struct hipz_query_hca *rblock; |
268 | struct hipz_query_port *port; | 268 | struct hipz_query_port *port; |
269 | 269 | ||
270 | static const u32 pgsize_map[] = { | ||
271 | HCA_CAP_MR_PGSIZE_4K, 0x1000, | ||
272 | HCA_CAP_MR_PGSIZE_64K, 0x10000, | ||
273 | HCA_CAP_MR_PGSIZE_1M, 0x100000, | ||
274 | HCA_CAP_MR_PGSIZE_16M, 0x1000000, | ||
275 | }; | ||
276 | |||
270 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 277 | rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); |
271 | if (!rblock) { | 278 | if (!rblock) { |
272 | ehca_gen_err("Cannot allocate rblock memory."); | 279 | ehca_gen_err("Cannot allocate rblock memory."); |
@@ -329,8 +336,15 @@ int ehca_sense_attributes(struct ehca_shca *shca) | |||
329 | if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap)) | 336 | if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap)) |
330 | ehca_gen_dbg(" %s", hca_cap_descr[i].descr); | 337 | ehca_gen_dbg(" %s", hca_cap_descr[i].descr); |
331 | 338 | ||
332 | shca->hca_cap_mr_pgsize = rblock->memory_page_size_supported; | 339 | /* translate supported MR page sizes; always support 4K */ |
340 | shca->hca_cap_mr_pgsize = EHCA_PAGESIZE; | ||
341 | if (ehca_mr_largepage) { /* support extra sizes only if enabled */ | ||
342 | for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2) | ||
343 | if (rblock->memory_page_size_supported & pgsize_map[i]) | ||
344 | shca->hca_cap_mr_pgsize |= pgsize_map[i + 1]; | ||
345 | } | ||
333 | 346 | ||
347 | /* query max MTU from first port -- it's the same for all ports */ | ||
334 | port = (struct hipz_query_port *)rblock; | 348 | port = (struct hipz_query_port *)rblock; |
335 | h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port); | 349 | h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port); |
336 | if (h_ret != H_SUCCESS) { | 350 | if (h_ret != H_SUCCESS) { |
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c index b9a788c4fdd1..bb9791555f49 100644 --- a/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c | |||
@@ -79,9 +79,7 @@ static u32 ehca_encode_hwpage_size(u32 pgsize) | |||
79 | 79 | ||
80 | static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca) | 80 | static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca) |
81 | { | 81 | { |
82 | if (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M) | 82 | return 1UL << ilog2(shca->hca_cap_mr_pgsize); |
83 | return EHCA_MR_PGSIZE16M; | ||
84 | return EHCA_MR_PGSIZE4K; | ||
85 | } | 83 | } |
86 | 84 | ||
87 | static struct ehca_mr *ehca_mr_new(void) | 85 | static struct ehca_mr *ehca_mr_new(void) |
@@ -288,7 +286,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | |||
288 | container_of(pd->device, struct ehca_shca, ib_device); | 286 | container_of(pd->device, struct ehca_shca, ib_device); |
289 | struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); | 287 | struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); |
290 | struct ehca_mr_pginfo pginfo; | 288 | struct ehca_mr_pginfo pginfo; |
291 | int ret; | 289 | int ret, page_shift; |
292 | u32 num_kpages; | 290 | u32 num_kpages; |
293 | u32 num_hwpages; | 291 | u32 num_hwpages; |
294 | u64 hwpage_size; | 292 | u64 hwpage_size; |
@@ -343,19 +341,20 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, | |||
343 | /* determine number of MR pages */ | 341 | /* determine number of MR pages */ |
344 | num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE); | 342 | num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE); |
345 | /* select proper hw_pgsize */ | 343 | /* select proper hw_pgsize */ |
346 | if (ehca_mr_largepage && | 344 | page_shift = PAGE_SHIFT; |
347 | (shca->hca_cap_mr_pgsize & HCA_CAP_MR_PGSIZE_16M)) { | 345 | if (e_mr->umem->hugetlb) { |
348 | int page_shift = PAGE_SHIFT; | 346 | /* determine page_shift, clamp between 4K and 16M */ |
349 | if (e_mr->umem->hugetlb) { | 347 | page_shift = (fls64(length - 1) + 3) & ~3; |
350 | /* determine page_shift, clamp between 4K and 16M */ | 348 | page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K), |
351 | page_shift = (fls64(length - 1) + 3) & ~3; | 349 | EHCA_MR_PGSHIFT16M); |
352 | page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K), | 350 | } |
353 | EHCA_MR_PGSHIFT16M); | 351 | hwpage_size = 1UL << page_shift; |
354 | } | 352 | |
355 | hwpage_size = 1UL << page_shift; | 353 | /* now that we have the desired page size, shift until it's |
356 | } else | 354 | * supported, too. 4K is always supported, so this terminates. |
357 | hwpage_size = EHCA_MR_PGSIZE4K; /* ehca1 only supports 4k */ | 355 | */ |
358 | ehca_dbg(pd->device, "hwpage_size=%lx", hwpage_size); | 356 | while (!(hwpage_size & shca->hca_cap_mr_pgsize)) |
357 | hwpage_size >>= 4; | ||
359 | 358 | ||
360 | reg_user_mr_fallback: | 359 | reg_user_mr_fallback: |
361 | num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size); | 360 | num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size); |
@@ -801,8 +800,9 @@ struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, | |||
801 | ib_fmr = ERR_PTR(-EINVAL); | 800 | ib_fmr = ERR_PTR(-EINVAL); |
802 | goto alloc_fmr_exit0; | 801 | goto alloc_fmr_exit0; |
803 | } | 802 | } |
804 | hw_pgsize = ehca_get_max_hwpage_size(shca); | 803 | |
805 | if ((1 << fmr_attr->page_shift) != hw_pgsize) { | 804 | hw_pgsize = 1 << fmr_attr->page_shift; |
805 | if (!(hw_pgsize & shca->hca_cap_mr_pgsize)) { | ||
806 | ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x", | 806 | ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x", |
807 | fmr_attr->page_shift); | 807 | fmr_attr->page_shift); |
808 | ib_fmr = ERR_PTR(-EINVAL); | 808 | ib_fmr = ERR_PTR(-EINVAL); |