diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2016-09-26 15:58:49 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-10-07 16:54:39 -0400 |
commit | 681cc3608355737c1effebc8145f95c8c3344bc3 (patch) | |
tree | 440c6dc95990989c80eaeac571a01c88efce3d7a | |
parent | 52bb8c626e0e5526c72b6ad17f1381f0bad283cc (diff) |
IB/srp: Fix infinite loop when FMR sg[0].offset != 0
Avoid that mapping an sg-list in which the first element has a
non-zero offset triggers an infinite loop when using FMR. This
patch makes the FMR mapping code similar to that of ib_sg_to_pages().
Note: older Mellanox HCAs do not support non-zero offsets for FMR.
See also commit 8c4037b501ac ("IB/srp: always avoid non-zero offsets
into an FMR").
Reported-by: Alex Estrin <alex.estrin@intel.com>
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 60031b9159d9..d980fb458ad4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -1402,7 +1402,9 @@ static int srp_map_sg_entry(struct srp_map_state *state, | |||
1402 | 1402 | ||
1403 | while (dma_len) { | 1403 | while (dma_len) { |
1404 | unsigned offset = dma_addr & ~dev->mr_page_mask; | 1404 | unsigned offset = dma_addr & ~dev->mr_page_mask; |
1405 | if (state->npages == dev->max_pages_per_mr || offset != 0) { | 1405 | |
1406 | if (state->npages == dev->max_pages_per_mr || | ||
1407 | (state->npages > 0 && offset != 0)) { | ||
1406 | ret = srp_map_finish_fmr(state, ch); | 1408 | ret = srp_map_finish_fmr(state, ch); |
1407 | if (ret) | 1409 | if (ret) |
1408 | return ret; | 1410 | return ret; |
@@ -1419,12 +1421,12 @@ static int srp_map_sg_entry(struct srp_map_state *state, | |||
1419 | } | 1421 | } |
1420 | 1422 | ||
1421 | /* | 1423 | /* |
1422 | * If the last entry of the MR wasn't a full page, then we need to | 1424 | * If the end of the MR is not on a page boundary then we need to |
1423 | * close it out and start a new one -- we can only merge at page | 1425 | * close it out and start a new one -- we can only merge at page |
1424 | * boundaries. | 1426 | * boundaries. |
1425 | */ | 1427 | */ |
1426 | ret = 0; | 1428 | ret = 0; |
1427 | if (len != dev->mr_page_size) | 1429 | if ((dma_addr & ~dev->mr_page_mask) != 0) |
1428 | ret = srp_map_finish_fmr(state, ch); | 1430 | ret = srp_map_finish_fmr(state, ch); |
1429 | return ret; | 1431 | return ret; |
1430 | } | 1432 | } |