diff options
author | Noa Osherovich <noaos@mellanox.com> | 2016-10-25 11:36:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-10-29 12:00:39 -0400 |
commit | 6b276190c50a12511d889d9079ffb901ff94a822 (patch) | |
tree | 2fbd8a81031683406fa5fbd8a50f310aea4be4fc | |
parent | 04c0c1ab38e95105d950db5b84e727637e149ce7 (diff) |
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: bf0bf77f6519 ('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>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index cc4fd61914d3..a57d5a81eb05 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | |||
@@ -209,6 +209,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr) | |||
209 | static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id) | 209 | static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id) |
210 | { | 210 | { |
211 | struct page *page; | 211 | struct page *page; |
212 | u64 zero_addr = 1; | ||
212 | u64 addr; | 213 | u64 addr; |
213 | int err; | 214 | int err; |
214 | int nid = dev_to_node(&dev->pdev->dev); | 215 | 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) | |||
218 | mlx5_core_warn(dev, "failed to allocate page\n"); | 219 | mlx5_core_warn(dev, "failed to allocate page\n"); |
219 | return -ENOMEM; | 220 | return -ENOMEM; |
220 | } | 221 | } |
222 | map: | ||
221 | addr = dma_map_page(&dev->pdev->dev, page, 0, | 223 | addr = dma_map_page(&dev->pdev->dev, page, 0, |
222 | PAGE_SIZE, DMA_BIDIRECTIONAL); | 224 | PAGE_SIZE, DMA_BIDIRECTIONAL); |
223 | if (dma_mapping_error(&dev->pdev->dev, addr)) { | 225 | if (dma_mapping_error(&dev->pdev->dev, addr)) { |
224 | mlx5_core_warn(dev, "failed dma mapping page\n"); | 226 | mlx5_core_warn(dev, "failed dma mapping page\n"); |
225 | err = -ENOMEM; | 227 | err = -ENOMEM; |
226 | goto out_alloc; | 228 | goto err_mapping; |
227 | } | 229 | } |
230 | |||
231 | /* Firmware doesn't support page with physical address 0 */ | ||
232 | if (addr == 0) { | ||
233 | zero_addr = addr; | ||
234 | goto map; | ||
235 | } | ||
236 | |||
228 | err = insert_page(dev, addr, page, func_id); | 237 | err = insert_page(dev, addr, page, func_id); |
229 | if (err) { | 238 | if (err) { |
230 | mlx5_core_err(dev, "failed to track allocated page\n"); | 239 | mlx5_core_err(dev, "failed to track allocated page\n"); |
231 | goto out_mapping; | 240 | dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, |
241 | DMA_BIDIRECTIONAL); | ||
232 | } | 242 | } |
233 | 243 | ||
234 | return 0; | 244 | err_mapping: |
235 | 245 | if (err) | |
236 | out_mapping: | 246 | __free_page(page); |
237 | dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); | ||
238 | 247 | ||
239 | out_alloc: | 248 | if (zero_addr == 0) |
240 | __free_page(page); | 249 | dma_unmap_page(&dev->pdev->dev, zero_addr, PAGE_SIZE, |
250 | DMA_BIDIRECTIONAL); | ||
241 | 251 | ||
242 | return err; | 252 | return err; |
243 | } | 253 | } |