aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2009-05-08 00:35:13 -0400
committerRoland Dreier <rolandd@cisco.com>2009-05-08 00:35:13 -0400
commit2b6b7d4be487bada8c727df829c25068c7b5e5a3 (patch)
treed1fa04daa97cafe89f04b9f16c8a58925f364203 /drivers/infiniband/hw
parent56a50adda49b2020156616c4eb15353e0f9ad7de (diff)
IB/mlx4: Don't overwrite fast registration page list when posting work request
The low-level mlx4 driver modified the page-list addresses for fast register work requests post send to big-endian, and set a "present" bit. This caused problems later when the consumer attempted to unmap the pages using the page-list (using the list addresses which were assumed to be still in CPU-endian order). Fix the mlx4 driver to allocate two buffers and use a private buffer for the hardware-format bus addresses. This patch fixes <https://bugs.openfabrics.org/show_bug.cgi?id=1571>, an NFS/RDMA server crash. The cause of the crash was found by Vu Pham of Mellanox. The fix is along the lines suggested by Steve Wise in comment #21 in bug 1571. Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c10
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c2
3 files changed, 10 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 9974e886b8de..8a7dd6795fa0 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -86,6 +86,7 @@ struct mlx4_ib_mr {
86 86
87struct mlx4_ib_fast_reg_page_list { 87struct mlx4_ib_fast_reg_page_list {
88 struct ib_fast_reg_page_list ibfrpl; 88 struct ib_fast_reg_page_list ibfrpl;
89 __be64 *mapped_page_list;
89 dma_addr_t map; 90 dma_addr_t map;
90}; 91};
91 92
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 8e4d26d56a95..8f3666b20ea4 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -231,7 +231,11 @@ struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device
231 if (!mfrpl) 231 if (!mfrpl)
232 return ERR_PTR(-ENOMEM); 232 return ERR_PTR(-ENOMEM);
233 233
234 mfrpl->ibfrpl.page_list = dma_alloc_coherent(&dev->dev->pdev->dev, 234 mfrpl->ibfrpl.page_list = kmalloc(size, GFP_KERNEL);
235 if (!mfrpl->ibfrpl.page_list)
236 goto err_free;
237
238 mfrpl->mapped_page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
235 size, &mfrpl->map, 239 size, &mfrpl->map,
236 GFP_KERNEL); 240 GFP_KERNEL);
237 if (!mfrpl->ibfrpl.page_list) 241 if (!mfrpl->ibfrpl.page_list)
@@ -242,6 +246,7 @@ struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device
242 return &mfrpl->ibfrpl; 246 return &mfrpl->ibfrpl;
243 247
244err_free: 248err_free:
249 kfree(mfrpl->ibfrpl.page_list);
245 kfree(mfrpl); 250 kfree(mfrpl);
246 return ERR_PTR(-ENOMEM); 251 return ERR_PTR(-ENOMEM);
247} 252}
@@ -252,8 +257,9 @@ void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
252 struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list); 257 struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
253 int size = page_list->max_page_list_len * sizeof (u64); 258 int size = page_list->max_page_list_len * sizeof (u64);
254 259
255 dma_free_coherent(&dev->dev->pdev->dev, size, page_list->page_list, 260 dma_free_coherent(&dev->dev->pdev->dev, size, mfrpl->mapped_page_list,
256 mfrpl->map); 261 mfrpl->map);
262 kfree(mfrpl->ibfrpl.page_list);
257 kfree(mfrpl); 263 kfree(mfrpl);
258} 264}
259 265
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index f385a24d31d2..20724aee76f4 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1365,7 +1365,7 @@ static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
1365 int i; 1365 int i;
1366 1366
1367 for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i) 1367 for (i = 0; i < wr->wr.fast_reg.page_list_len; ++i)
1368 wr->wr.fast_reg.page_list->page_list[i] = 1368 mfrpl->mapped_page_list[i] =
1369 cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] | 1369 cpu_to_be64(wr->wr.fast_reg.page_list->page_list[i] |
1370 MLX4_MTT_FLAG_PRESENT); 1370 MLX4_MTT_FLAG_PRESENT);
1371 1371