net/mlx5: Avoid passing dma address 0 to firmware

Currently the firmware can't work with a page with dma address 0.
Passing such an address to the firmware will cause the give_pages
command to fail.

To avoid this, in case we get a 0 dma address of a page from the
dma engine, we avoid passing it to FW by remapping to get an address
other than 0.

Fixes: bf0bf77f65 ('mlx5: Support communicating arbitrary host...')
Signed-off-by: Noa Osherovich <noaos@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Noa Osherovich 2016-10-25 18:36:35 +03:00 committed by David S. Miller
parent 04c0c1ab38
commit 6b276190c5
1 changed files with 18 additions and 8 deletions

View File

@ -209,6 +209,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr)
static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id) static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id)
{ {
struct page *page; struct page *page;
u64 zero_addr = 1;
u64 addr; u64 addr;
int err; int err;
int nid = dev_to_node(&dev->pdev->dev); int nid = dev_to_node(&dev->pdev->dev);
@ -218,26 +219,35 @@ static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id)
mlx5_core_warn(dev, "failed to allocate page\n"); mlx5_core_warn(dev, "failed to allocate page\n");
return -ENOMEM; return -ENOMEM;
} }
map:
addr = dma_map_page(&dev->pdev->dev, page, 0, addr = dma_map_page(&dev->pdev->dev, page, 0,
PAGE_SIZE, DMA_BIDIRECTIONAL); PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(&dev->pdev->dev, addr)) { if (dma_mapping_error(&dev->pdev->dev, addr)) {
mlx5_core_warn(dev, "failed dma mapping page\n"); mlx5_core_warn(dev, "failed dma mapping page\n");
err = -ENOMEM; err = -ENOMEM;
goto out_alloc; goto err_mapping;
} }
/* Firmware doesn't support page with physical address 0 */
if (addr == 0) {
zero_addr = addr;
goto map;
}
err = insert_page(dev, addr, page, func_id); err = insert_page(dev, addr, page, func_id);
if (err) { if (err) {
mlx5_core_err(dev, "failed to track allocated page\n"); mlx5_core_err(dev, "failed to track allocated page\n");
goto out_mapping; dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE,
DMA_BIDIRECTIONAL);
} }
return 0; err_mapping:
if (err)
__free_page(page);
out_mapping: if (zero_addr == 0)
dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); dma_unmap_page(&dev->pdev->dev, zero_addr, PAGE_SIZE,
DMA_BIDIRECTIONAL);
out_alloc:
__free_page(page);
return err; return err;
} }