]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mlx4_core: fix FMR unmapping to allow remapping afterward
authorMoshe Lazer <moshel@mellanox.com>
Sun, 8 Sep 2013 06:59:09 +0000 (08:59 +0200)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 21:45:12 +0000 (14:45 -0700)
The FMR common use flow (as implemented in fmr_pool) is:
 - Allocate FMR (ib_alloc_fmr)
 - Use the FMR to remap DMA memory until remaps limit
   exceeded (ib_map_phys_fmr)
 - Unmap the FMR (ib_unmap_fmr)
 - Use the FMR to remap DMA memory until remaps limit
   exceeded (ib_map_phys_fmr)
 - ...

The current implementation of mlx4_fmr_unmap is not following
this use flow since it is using the HW2SW MPT command.
The HW2SW MPT command notifies the FW that the MPT entry is
not used by HW anymore. The FW may act according to this information,
therefore it is not safe for the driver to manipulate the MPT
directly.  The patch fixes this by manipulating the MPT directly
to unmap the memory instead of using the HW2SW MPT command.

Signed-off-by: Moshe Lazer <moshel@mellanox.com>
(Ported from Mellanox OFED 2.4)

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
drivers/net/ethernet/mellanox/mlx4/mr.c

index c8dc251ea569341985d00fcb11d440238ea289b2..bc7fd3282b4fe5b1fe14d25891bf627a0e4408b0 100644 (file)
@@ -1110,30 +1110,34 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
 void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
                    u32 *lkey, u32 *rkey)
 {
-       struct mlx4_cmd_mailbox *mailbox;
-       int err;
+       u32 key;
 
        if (!fmr->maps)
                return;
 
-       fmr->maps = 0;
+       key = key_to_hw_index(fmr->mr.key) & (dev->caps.num_mpts - 1);
 
-       mailbox = mlx4_alloc_cmd_mailbox(dev);
-       if (IS_ERR(mailbox)) {
-               err = PTR_ERR(mailbox);
-               pr_warn("mlx4_ib: mlx4_alloc_cmd_mailbox failed (%d)\n", err);
-               return;
-       }
+       *(u8 *)fmr->mpt = MLX4_MPT_STATUS_SW;
 
-       err = mlx4_HW2SW_MPT(dev, NULL,
-                            key_to_hw_index(fmr->mr.key) &
-                            (dev->caps.num_mpts - 1));
-       mlx4_free_cmd_mailbox(dev, mailbox);
-       if (err) {
-               pr_warn("mlx4_ib: mlx4_HW2SW_MPT failed (%d)\n", err);
-               return;
-       }
-       fmr->mr.enabled = MLX4_MPT_EN_SW;
+       /* Make sure MPT status is visible before changing MPT fields */
+       wmb();
+
+       fmr->mr.key = hw_index_to_key(key);
+
+       fmr->mpt->key    = cpu_to_be32(key);
+       fmr->mpt->lkey   = cpu_to_be32(key);
+       fmr->mpt->length = 0;
+       fmr->mpt->start  = 0;
+
+       /* Make sure MPT data is visible before changing MPT status */
+       wmb();
+
+       *(u8 *)fmr->mpt = MLX4_MPT_STATUS_HW;
+
+       /* Make sure MPT satus is visible */
+       wmb();
+
+       fmr->maps = 0;
 }
 EXPORT_SYMBOL_GPL(mlx4_fmr_unmap);