Commit 58dfd4ac authored by Christoph Hellwig's avatar Christoph Hellwig

dma-direct: improve addressability error reporting

Only report report a DMA addressability report once to avoid spewing the
kernel log with repeated message.  Also provide a stack trace to make it
easy to find the actual caller that caused the problem.

Last but not least move the actual check into the fast path and only
leave the error reporting in a helper.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
Tested-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
Tested-by: default avatarTony Luck <tony.luck@intel.com>
parent 68c60834
...@@ -30,27 +30,16 @@ static inline bool force_dma_unencrypted(void) ...@@ -30,27 +30,16 @@ static inline bool force_dma_unencrypted(void)
return sev_active(); return sev_active();
} }
static bool static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
const char *caller)
{ {
if (unlikely(dev && !dma_capable(dev, dma_addr, size))) { if (!dev->dma_mask) {
if (!dev->dma_mask) { dev_err_once(dev, "DMA map on device without dma_mask\n");
dev_err(dev, } else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_mask) {
"%s: call on device without dma_mask\n", dev_err_once(dev,
caller); "overflow %pad+%zu of DMA mask %llx bus mask %llx\n",
return false; &dma_addr, size, *dev->dma_mask, dev->bus_dma_mask);
}
if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_mask) {
dev_err(dev,
"%s: overflow %pad+%zu of device mask %llx bus mask %llx\n",
caller, &dma_addr, size,
*dev->dma_mask, dev->bus_dma_mask);
}
return false;
} }
return true; WARN_ON_ONCE(1);
} }
static inline dma_addr_t phys_to_dma_direct(struct device *dev, static inline dma_addr_t phys_to_dma_direct(struct device *dev,
...@@ -288,8 +277,10 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct page *page, ...@@ -288,8 +277,10 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
phys_addr_t phys = page_to_phys(page) + offset; phys_addr_t phys = page_to_phys(page) + offset;
dma_addr_t dma_addr = phys_to_dma(dev, phys); dma_addr_t dma_addr = phys_to_dma(dev, phys);
if (!check_addr(dev, dma_addr, size, __func__)) if (unlikely(dev && !dma_capable(dev, dma_addr, size))) {
report_addr(dev, dma_addr, size);
return DMA_MAPPING_ERROR; return DMA_MAPPING_ERROR;
}
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
dma_direct_sync_single_for_device(dev, dma_addr, size, dir); dma_direct_sync_single_for_device(dev, dma_addr, size, dir);
...@@ -306,8 +297,11 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, ...@@ -306,8 +297,11 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
BUG_ON(!sg_page(sg)); BUG_ON(!sg_page(sg));
sg_dma_address(sg) = phys_to_dma(dev, sg_phys(sg)); sg_dma_address(sg) = phys_to_dma(dev, sg_phys(sg));
if (!check_addr(dev, sg_dma_address(sg), sg->length, __func__)) if (unlikely(dev && !dma_capable(dev, sg_dma_address(sg),
sg->length))) {
report_addr(dev, sg_dma_address(sg), sg->length);
return 0; return 0;
}
sg_dma_len(sg) = sg->length; sg_dma_len(sg) = sg->length;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment