|
@@ -1286,6 +1286,32 @@ out:
|
|
|
put_hash_bucket(bucket, &flags);
|
|
|
}
|
|
|
|
|
|
+static void check_sg_segment(struct device *dev, struct scatterlist *sg)
|
|
|
+{
|
|
|
+#ifdef CONFIG_DMA_API_DEBUG_SG
|
|
|
+ unsigned int max_seg = dma_get_max_seg_size(dev);
|
|
|
+ u64 start, end, boundary = dma_get_seg_boundary(dev);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Either the driver forgot to set dma_parms appropriately, or
|
|
|
+ * whoever generated the list forgot to check them.
|
|
|
+ */
|
|
|
+ if (sg->length > max_seg)
|
|
|
+ err_printk(dev, NULL, "DMA-API: mapping sg segment longer than device claims to support [len=%u] [max=%u]\n",
|
|
|
+ sg->length, max_seg);
|
|
|
+ /*
|
|
|
+ * In some cases this could potentially be the DMA API
|
|
|
+ * implementation's fault, but it would usually imply that
|
|
|
+ * the scatterlist was built inappropriately to begin with.
|
|
|
+ */
|
|
|
+ start = sg_dma_address(sg);
|
|
|
+ end = start + sg_dma_len(sg) - 1;
|
|
|
+ if ((start ^ end) & ~boundary)
|
|
|
+ err_printk(dev, NULL, "DMA-API: mapping sg segment across boundary [start=0x%016llx] [end=0x%016llx] [boundary=0x%016llx]\n",
|
|
|
+ start, end, boundary);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
|
|
|
size_t size, int direction, dma_addr_t dma_addr,
|
|
|
bool map_single)
|
|
@@ -1416,6 +1442,8 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
|
|
check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
|
|
|
}
|
|
|
|
|
|
+ check_sg_segment(dev, s);
|
|
|
+
|
|
|
add_dma_entry(entry);
|
|
|
}
|
|
|
}
|