]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
IB/srp: Fix infinite loop when FMR sg[0].offset != 0
authorBart Van Assche <bart.vanassche@sandisk.com>
Mon, 26 Sep 2016 19:58:49 +0000 (12:58 -0700)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 23 Feb 2017 03:54:10 +0000 (03:54 +0000)
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>
drivers/infiniband/ulp/srp/ib_srp.c

index 36876960f97e04432cec2beeff8f749c139b324d..6311fd448c3616423169fe97863fd51cb924333d 100644 (file)
@@ -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);