Skip to content

Commit

Permalink
dma-direct: improve addressability error reporting
Browse files Browse the repository at this point in the history
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: Christoph Hellwig <hch@lst.de>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Tested-by: Jesper Dangaard Brouer <brouer@redhat.com>
Tested-by: Tony Luck <tony.luck@intel.com>
  • Loading branch information
Christoph Hellwig committed Dec 13, 2018
1 parent 68c6083 commit 58dfd4a
Showing 1 changed file with 15 additions and 21 deletions.
36 changes: 15 additions & 21 deletions kernel/dma/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,16 @@ static inline bool force_dma_unencrypted(void)
return sev_active();
}

static bool
check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
const char *caller)
static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
{
if (unlikely(dev && !dma_capable(dev, dma_addr, size))) {
if (!dev->dma_mask) {
dev_err(dev,
"%s: call on device without dma_mask\n",
caller);
return false;
}

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;
if (!dev->dma_mask) {
dev_err_once(dev, "DMA map on device without dma_mask\n");
} else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_mask) {
dev_err_once(dev,
"overflow %pad+%zu of DMA mask %llx bus mask %llx\n",
&dma_addr, size, *dev->dma_mask, dev->bus_dma_mask);
}
return true;
WARN_ON_ONCE(1);
}

static inline dma_addr_t phys_to_dma_direct(struct device *dev,
Expand Down Expand Up @@ -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;
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;
}

if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
dma_direct_sync_single_for_device(dev, dma_addr, size, dir);
Expand All @@ -306,8 +297,11 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
BUG_ON(!sg_page(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;
}
sg_dma_len(sg) = sg->length;
}

Expand Down

0 comments on commit 58dfd4a

Please sign in to comment.