aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Wood <donald.e.wood@intel.com>2009-04-20 17:53:00 -0400
committerRoland Dreier <rolandd@cisco.com>2009-04-20 17:53:00 -0400
commit3f32eb1185170524a81dadff2e67521585943a53 (patch)
tree3c44461bed14392563c06b611ccff7e78f80a1cb
parent1af9222b5223a7b04102dc8c403fa55fa15d5184 (diff)
RDMA/nes: Fix bugs in nes_reg_phys_mr()
The code incorrectly failed memory registration if the buffer was not page aligned. Also, the length field is mangled causing the hardware to think the registration is much larger than it really is. The fix is to remove the page alignment restriction as well the incorrect length adjustment. Also make sure that all buffers after the first start at a page boundary, and all buffers except the last end on a page boundary. Signed-off-by: Don Wood <donald.e.wood@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 9279d0561853..f04bb1a5da45 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -2122,6 +2122,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2122 struct nes_root_vpbl root_vpbl; 2122 struct nes_root_vpbl root_vpbl;
2123 u32 stag; 2123 u32 stag;
2124 u32 i; 2124 u32 i;
2125 unsigned long mask;
2125 u32 stag_index = 0; 2126 u32 stag_index = 0;
2126 u32 next_stag_index = 0; 2127 u32 next_stag_index = 0;
2127 u32 driver_key = 0; 2128 u32 driver_key = 0;
@@ -2150,6 +2151,9 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2150 return ERR_PTR(-E2BIG); 2151 return ERR_PTR(-E2BIG);
2151 } 2152 }
2152 2153
2154 if ((buffer_list[0].addr ^ *iova_start) & ~PAGE_MASK)
2155 return ERR_PTR(-EINVAL);
2156
2153 err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr, 2157 err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,
2154 &stag_index, &next_stag_index); 2158 &stag_index, &next_stag_index);
2155 if (err) { 2159 if (err) {
@@ -2215,19 +2219,16 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2215 root_pbl_index++; 2219 root_pbl_index++;
2216 cur_pbl_index = 0; 2220 cur_pbl_index = 0;
2217 } 2221 }
2218 if (buffer_list[i].addr & ~PAGE_MASK) {
2219 /* TODO: Unwind allocated buffers */
2220 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2221 nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
2222 (unsigned int) buffer_list[i].addr);
2223 ibmr = ERR_PTR(-EINVAL);
2224 kfree(nesmr);
2225 goto reg_phys_err;
2226 }
2227 2222
2228 if (!buffer_list[i].size) { 2223 mask = !buffer_list[i].size;
2224 if (i != 0)
2225 mask |= buffer_list[i].addr;
2226 if (i != num_phys_buf - 1)
2227 mask |= buffer_list[i].addr + buffer_list[i].size;
2228
2229 if (mask & ~PAGE_MASK) {
2229 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index); 2230 nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
2230 nes_debug(NES_DBG_MR, "Invalid Buffer Size\n"); 2231 nes_debug(NES_DBG_MR, "Invalid buffer addr or size\n");
2231 ibmr = ERR_PTR(-EINVAL); 2232 ibmr = ERR_PTR(-EINVAL);
2232 kfree(nesmr); 2233 kfree(nesmr);
2233 goto reg_phys_err; 2234 goto reg_phys_err;
@@ -2238,7 +2239,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2238 if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr) 2239 if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr)
2239 single_page = 0; 2240 single_page = 0;
2240 } 2241 }
2241 vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr); 2242 vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr & PAGE_MASK);
2242 vpbl.pbl_vbase[cur_pbl_index++].pa_high = 2243 vpbl.pbl_vbase[cur_pbl_index++].pa_high =
2243 cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32))); 2244 cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32)));
2244 } 2245 }
@@ -2251,8 +2252,6 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
2251 " length = 0x%016lX, index = 0x%08X\n", 2252 " length = 0x%016lX, index = 0x%08X\n",
2252 stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index); 2253 stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index);
2253 2254
2254 region_length -= (*iova_start)&PAGE_MASK;
2255
2256 /* Make the leaf PBL the root if only one PBL */ 2255 /* Make the leaf PBL the root if only one PBL */
2257 if (root_pbl_index == 1) { 2256 if (root_pbl_index == 1) {
2258 root_vpbl.pbl_pbase = vpbl.pbl_pbase; 2257 root_vpbl.pbl_pbase = vpbl.pbl_pbase;