This is a bit tricky, since AMD laid off the team who were maintaining this, but I added to the cc' one of the original maintainers in the hopes they can take a look. James On Tue, 2013-02-19 at 18:30 -0800, Eddie Wai wrote: > Hello, > > For a 64-bit DMA capable PCIe storage HBA running under the 64-bit > AMD-VI IOMMU environment, the amd_iommu code was observed to hit an > overflow when it tries to page align the dma_parms->segment_boundary_mask. > This overflow would eventually trigger the BUG_ON in the iommu-helper's > iommu_is_span_boundary is_power_of_2 check. > > A little back tracking shows that since the device is 64-bit DMA capable, > the pcidev->dma_mask was correctly set to DMA_BIT_MASK(64). This dma_mask > was then transferred to the SCSI host's dma_boundary param (by the iSCSI > driver) and was eventually used to populate the q->limits.seg_boundary_mask > (via blk_queue_segment_boundary) and the dma_parms->segment_boundary_mask > (via dma_set_seg_boundary) during the scsi queue allocation. > > The code seems correct as it make sense to impose the same hardware > segment boundary limit on both the blk queue and the DMA code. It would > be an easy alternative to simply prevent the shost->dma_boundary from > being set to DMA_BIT_MASK(64), but it seems more correct to fix the > amd_iommu code itself to detect and handle this max 64-bit mask condition. > > Please let me know your comments. > > Thanks, > Eddie > > Signed-off-by: Eddie Wai <eddie.wai@xxxxxxxxxxxx> > --- > drivers/iommu/amd_iommu.c | 7 +++++-- > 1 files changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index d90a421..63185a1 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -1526,11 +1526,14 @@ static unsigned long dma_ops_area_alloc(struct device *dev, > unsigned long boundary_size; > unsigned long address = -1; > unsigned long limit; > + unsigned long mask; > > next_bit >>= PAGE_SHIFT; > > - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, > - PAGE_SIZE) >> PAGE_SHIFT; > + mask = dma_get_seg_boundary(dev); > + boundary_size = mask + 1 ? > + ALIGN(mask + 1, PAGE_SIZE) >> PAGE_SHIFT : > + 1UL << (BITS_PER_LONG - PAGE_SHIFT); > > for (;i < max_index; ++i) { > unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html