Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / mellanox / mlx4 / resource_tracker.c
index 0efc1368e5a8c4d25b4c95edf049fcae1bec0efb..1089367fed22632e087b2da0bcd150cd1dce6f48 100644 (file)
@@ -2613,12 +2613,34 @@ int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
        if (err)
                return err;
 
-       if (mpt->com.from_state != RES_MPT_HW) {
+       if (mpt->com.from_state == RES_MPT_MAPPED) {
+               /* In order to allow rereg in SRIOV, we need to alter the MPT entry. To do
+                * that, the VF must read the MPT. But since the MPT entry memory is not
+                * in the VF's virtual memory space, it must use QUERY_MPT to obtain the
+                * entry contents. To guarantee that the MPT cannot be changed, the driver
+                * must perform HW2SW_MPT before this query and return the MPT entry to HW
+                * ownership fofollowing the change. The change here allows the VF to
+                * perform QUERY_MPT also when the entry is in SW ownership.
+                */
+               struct mlx4_mpt_entry *mpt_entry = mlx4_table_find(
+                                       &mlx4_priv(dev)->mr_table.dmpt_table,
+                                       mpt->key, NULL);
+
+               if (NULL == mpt_entry || NULL == outbox->buf) {
+                       err = -EINVAL;
+                       goto out;
+               }
+
+               memcpy(outbox->buf, mpt_entry, sizeof(*mpt_entry));
+
+               err = 0;
+       } else if (mpt->com.from_state == RES_MPT_HW) {
+               err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+       } else {
                err = -EBUSY;
                goto out;
        }
 
-       err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
 
 out:
        put_res(dev, slave, id, RES_MPT);