12 Dec, 2015

1 commit

  • When using the Promise TX2+ SATA controller on PA-RISC, the system often
    crashes with kernel panic, for example just writing data with the dd
    utility will make it crash.

    Kernel panic - not syncing: drivers/parisc/sba_iommu.c: I/O MMU @ 000000000000a000 is out of mapping resources

    CPU: 0 PID: 18442 Comm: mkspadfs Not tainted 4.4.0-rc2 #2
    Backtrace:
    [] show_stack+0x14/0x20
    [] dump_stack+0x88/0x100
    [] panic+0x124/0x360
    [] sba_alloc_range+0x698/0x6a0
    [] sba_map_sg+0x260/0x5b8
    [] ata_qc_issue+0x264/0x4a8 [libata]
    [] ata_scsi_translate+0xe4/0x220 [libata]
    [] ata_scsi_queuecmd+0xbc/0x320 [libata]
    [] scsi_dispatch_cmd+0xfc/0x130
    [] scsi_request_fn+0x6e4/0x970
    [] __blk_run_queue+0x40/0x60
    [] blk_run_queue+0x3c/0x68
    [] scsi_run_queue+0x2a4/0x360
    [] scsi_end_request+0x1a8/0x238
    [] scsi_io_completion+0xfc/0x688
    [] scsi_finish_command+0x17c/0x1d0

    The cause of the crash is not exhaustion of the IOMMU space, there is
    plenty of free pages. The function sba_alloc_range is called with size
    0x11000, thus the pages_needed variable is 0x11. The function
    sba_search_bitmap is called with bits_wanted 0x11 and boundary size is
    0x10 (because dma_get_seg_boundary(dev) returns 0xffff).

    The function sba_search_bitmap attempts to allocate 17 pages that must not
    cross 16-page boundary - it can't satisfy this requirement
    (iommu_is_span_boundary always returns true) and fails even if there are
    many free entries in the IOMMU space.

    How did it happen that we try to allocate 17 pages that don't cross
    16-page boundary? The cause is in the function iommu_coalesce_chunks. This
    function tries to coalesce adjacent entries in the scatterlist. The
    function does several checks if it may coalesce one entry with the next,
    one of those checks is this:

    if (startsg->length + dma_len > max_seg_size)
    break;

    When it finishes coalescing adjacent entries, it allocates the mapping:

    sg_dma_len(contig_sg) = dma_len;
    dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
    sg_dma_address(contig_sg) =
    PIDE_FLAG
    | (iommu_alloc_range(ioc, dev, dma_len) << IOVP_SHIFT)
    | dma_offset;

    It is possible that (startsg->length + dma_len > max_seg_size) is false
    (we are just near the 0x10000 max_seg_size boundary), so the funcion
    decides to coalesce this entry with the next entry. When the coalescing
    succeeds, the function performs
    dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
    And now, because of non-zero dma_offset, dma_len is greater than 0x10000.
    iommu_alloc_range (a pointer to sba_alloc_range) is called and it attempts
    to allocate 17 pages for a device that must not cross 16-page boundary.

    To fix the bug, we must make sure that dma_len after addition of
    dma_offset and alignment doesn't cross the segment boundary. I.e. change
    if (startsg->length + dma_len > max_seg_size)
    break;
    to
    if (ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) > max_seg_size)
    break;

    This patch makes this change (it precalculates max_seg_boundary at the
    beginning of the function iommu_coalesce_chunks). I also added a check
    that the mapping length doesn't exceed dma_get_seg_boundary(dev) (it is
    not needed for Promise TX2+ SATA, but it may be needed for other devices
    that have dma_get_seg_boundary lower than dma_get_max_seg_size).

    Signed-off-by: Mikulas Patocka
    Cc: stable@vger.kernel.org
    Signed-off-by: Helge Deller

    Mikulas Patocka
     

22 Apr, 2015

1 commit

  • The only reason to keep parisc's private asm/scatterlist.h was that it
    had the macro sg_virt_addr(). Convert all callers to use something else
    (sometimes just sg->offset was enough, others should use sg_virt()), and
    we can just use the asm-generic scatterlist.h instead.

    Signed-off-by: Matthew Wilcox
    Signed-off-by: Dave Anglin
    Signed-off-by: Helge Deller

    Matthew Wilcox
     

27 Feb, 2012

1 commit


05 Mar, 2008

1 commit

  • This adds struct device argument to sba_alloc_range and ccio_alloc_range, a
    preparation for modifications to fix the IOMMU segment boundary problem. This
    change enables ccio_alloc_range to access to LLD's segment boundary limits.

    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: FUJITA Tomonori
    Cc: Kyle McMartin
    Cc: Matthew Wilcox
    Cc: Grant Grundler
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    FUJITA Tomonori
     

06 Feb, 2008

1 commit


23 May, 2007

1 commit


17 Apr, 2005

1 commit

  • Initial git repository build. I'm not bothering with the full history,
    even though we have it. We can create a separate "historical" git
    archive of that later if we want to, and in the meantime it's about
    3.2GB when imported into git - space that would just make the early
    git days unnecessarily complicated, when we don't have a lot of good
    infrastructure for it.

    Let it rip!

    Linus Torvalds