struct mlx5_vhca_qp *host_qp;
        struct mlx5_vhca_qp *fw_qp;
        struct mlx5_core_dev *mdev;
-       u32 max_msg_size = PAGE_SIZE;
+       u32 log_max_msg_size;
+       u32 max_msg_size;
        u64 rq_size = SZ_2M;
        u32 max_recv_wr;
        int err;
        }
 
        mdev = mvdev->mdev;
+       log_max_msg_size = MLX5_CAP_ADV_VIRTUALIZATION(mdev, pg_track_log_max_msg_size);
+       max_msg_size = (1ULL << log_max_msg_size);
+       /* The RQ must hold at least 4 WQEs/messages for successful QP creation */
+       if (rq_size < 4 * max_msg_size)
+               rq_size = 4 * max_msg_size;
+
        memset(tracker, 0, sizeof(*tracker));
        tracker->uar = mlx5_get_uars_page(mdev);
        if (IS_ERR(tracker->uar)) {
 {
        u32 entry_size = MLX5_ST_SZ_BYTES(page_track_report_entry);
        u32 nent = size / entry_size;
+       u32 nent_in_page;
+       u32 nent_to_set;
        struct page *page;
+       u32 page_offset;
+       u32 page_index;
+       u32 buf_offset;
+       void *kaddr;
        u64 addr;
        u64 *buf;
        int i;
 
-       if (WARN_ON(index >= qp->recv_buf.npages ||
+       buf_offset = index * qp->max_msg_size;
+       if (WARN_ON(buf_offset + size >= qp->recv_buf.npages * PAGE_SIZE ||
                    (nent > qp->max_msg_size / entry_size)))
                return;
 
-       page = qp->recv_buf.page_list[index];
-       buf = kmap_local_page(page);
-       for (i = 0; i < nent; i++) {
-               addr = MLX5_GET(page_track_report_entry, buf + i,
-                               dirty_address_low);
-               addr |= (u64)MLX5_GET(page_track_report_entry, buf + i,
-                                     dirty_address_high) << 32;
-               iova_bitmap_set(dirty, addr, qp->tracked_page_size);
-       }
-       kunmap_local(buf);
+       do {
+               page_index = buf_offset / PAGE_SIZE;
+               page_offset = buf_offset % PAGE_SIZE;
+               nent_in_page = (PAGE_SIZE - page_offset) / entry_size;
+               page = qp->recv_buf.page_list[page_index];
+               kaddr = kmap_local_page(page);
+               buf = kaddr + page_offset;
+               nent_to_set = min(nent, nent_in_page);
+               for (i = 0; i < nent_to_set; i++) {
+                       addr = MLX5_GET(page_track_report_entry, buf + i,
+                                       dirty_address_low);
+                       addr |= (u64)MLX5_GET(page_track_report_entry, buf + i,
+                                             dirty_address_high) << 32;
+                       iova_bitmap_set(dirty, addr, qp->tracked_page_size);
+               }
+               kunmap_local(kaddr);
+               buf_offset += (nent_to_set * entry_size);
+               nent -= nent_to_set;
+       } while (nent);
 }
 
 static void