summaryrefslogtreecommitdiff
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@sandisk.com>2016-09-26 22:58:49 +0300
committerBen Hutchings <ben@decadent.org.uk>2017-02-23 06:54:10 +0300
commit00a05de9ae402f3408fe7fb43fb5654c435831ed (patch)
tree0de30e2a48c215d17cf3efac8f60f664e707b9e7 /drivers/infiniband/ulp
parent3c54629c642f3b11dd33e412b9519091b5bb3ede (diff)
downloadlinux-00a05de9ae402f3408fe7fb43fb5654c435831ed.tar.xz
IB/srp: Fix infinite loop when FMR sg[0].offset != 0
commit 681cc3608355737c1effebc8145f95c8c3344bc3 upstream. 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> Signed-off-by: Doug Ledford <dledford@redhat.com> [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c8
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 36876960f97e..6311fd448c36 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1310,7 +1310,9 @@ static int srp_map_sg_entry(struct srp_map_state *state,
while (dma_len) {
unsigned offset = dma_addr & ~dev->mr_page_mask;
- if (state->npages == dev->max_pages_per_mr || offset != 0) {
+
+ if (state->npages == dev->max_pages_per_mr ||
+ (state->npages > 0 && offset != 0)) {
ret = srp_finish_mapping(state, target);
if (ret)
return ret;
@@ -1329,12 +1331,12 @@ static int srp_map_sg_entry(struct srp_map_state *state,
}
/*
- * If the last entry of the MR wasn't a full page, then we need to
+ * If the end of the MR is not on a page boundary then we need to
* close it out and start a new one -- we can only merge at page
* boundries.
*/
ret = 0;
- if (len != dev->mr_page_size) {
+ if ((dma_addr & ~dev->mr_page_mask) != 0) {
ret = srp_finish_mapping(state, target);
if (!ret)
srp_map_update_start(state, NULL, 0, 0);