1. 13 Mar, 2009 15 commits
    • David Miller's avatar
      drm: Preserve SHMLBA bits in hash key for _DRM_SHM mappings. · f1a2a9b6
      David Miller authored
      Platforms such as sparc64 have D-cache aliasing issues.  We
      cannot allow virtual mappings in different contexts to be such
      that two cache lines can be loaded for the same backing data.
      Updates to one cache line won't be seen by accesses to the other
      cache line.
      
      Code in sparc64 and other architectures solve this problem by
      making sure that all userland mappings of MAP_SHARED objects have
      the same virtual address base.  They implement this by keying
      off of the page offset, and using that to choose a suitably
      consistent virtual address for mmap() requests.
      
      Making things even worse, getting this wrong on sparc64 can result
      in hangs during DRM lock acquisition.  This is because, at least on
      UltraSPARC-III, normal loads consult the D-cache but atomics such
      as 'cas' (which is what cmpxchg() is implement using) only consult
      the L2 cache.  So if a D-cache alias is inserted, the load can
      see different data than the atomic, and we'll loop forever because
      the atomic compare-and-exchange will never complete successfully.
      
      So to make this all work properly, we need to make sure that the
      hash address computed by drm_map_handle() preserves the SHMLBA
      relevant bits, and that's what this patch does for _DRM_SHM mappings.
      
      As a historical note, many years ago this bug didn't exist because we
      used to just use the low 32-bits of the address as the hash and just
      hope for the best.  This preserved the SHMLBA bits properly.  But when
      the hashtab code was added to DRM, this was no longer the case.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
      f1a2a9b6
    • David Miller's avatar
      drm: ati_pcigart: Fix limit check in drm_ati_pcigart_init(). · d30333bb
      David Miller authored
      The variable 'max_pages' is ambiguous.  There are two concepts
      of "pages" being used in this function.
      
      First, we have ATI GART pages which are always 4096 bytes.
      Then, we have system pages which are of size PAGE_SIZE.
      
      Eliminate the confusion by creating max_ati_pages and
      max_real_pages.  Calculate and use them as appropriate.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      d30333bb
    • David Miller's avatar
      drm: radeon: Use surface for PCI GART table. · 6abf6bb0
      David Miller authored
      This allocates a physical surface for the PCI GART table, this way no
      matter what other surface configurations exist the GART table will
      always be seen by the hardware properly.
      
      We encode the file pointer of the virtual surface allocate using a
      special cookie value, called PCIGART_FILE_PRIV.  On the last close, we
      release that surface.
      
      Just to be doubly safe, we run the pcigart table setup with the main
      surface control register clear.
      
      Based upon ideas from David Airlie and Ben Benjamin Herrenschmidt.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      6abf6bb0
    • David Miller's avatar
      drm: radeon: Fix calculation of RB_RPTR_ADDR in non-AGP case. · e8a89437
      David Miller authored
      The address needs to be a GART relative address, rather than a PCI
      DMA address.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      e8a89437
    • David Miller's avatar
      drm: radeon: Fix RADEON_*_EMITED defines. · b2665030
      David Miller authored
      These are not supposed to be booleans, they are
      supposed to be bit masks.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      b2665030
    • David Miller's avatar
      drm: radeon: Fix ring_rptr accesses. · b07fa022
      David Miller authored
      The memory behind ring_rptr can either be in ioremapped memory
      or a vmalloc() normal kernel memory buffer.
      
      However, the code unconditionally uses DRM_{READ,WRITE}32() (and thus
      readl() and writel()) to access it.
      
      Basically, if RADEON_IS_AGP then it's ioremap()'d memory else it's
      vmalloc'd memory.
      
      Adjust all of the ring_rptr access code as needed.
      
      While we're here, kill the 'scratch' pointer in drm_radeon_private.
      It's only used in the one place where it is initialized.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      b07fa022
    • David Miller's avatar
      drm: ati_pcigart: Need to use PCI_DMA_BIDIRECTIONAL. · 296c6ae0
      David Miller authored
      The buffers mapped by the PCI GART can be written to by the device,
      not just read.
      
      For example, this happens via the RB_RPTR writeback on Radeon.
      
      So we can't use PCI_DMA_TODEVICE else we'll get protection faults
      on IOMMU platforms.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      296c6ae0
    • David Miller's avatar
      drm: ati_pcigart: Do not access I/O MEM space using pointer derefs. · 5a7aad9a
      David Miller authored
      The PCI GART table initialization code treats the GART table mapping
      unconditionally as a kernel virtual address.
      
      But it could be in the framebuffer, for example, and thus we're
      dealing with a PCI MEM space ioremap() cookie.  Treating that as a
      virtual address is illegal and will crash some system types (such as
      sparc64 where the ioremap() return value is actually a physical I/O
      address).
      
      So access the area correctly, using gart_info->gart_table_location as
      our guide.
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      5a7aad9a
    • Kristian Høgsberg's avatar
      drm: Drop unused and broken dri_library_name sysfs attribute. · 8e100458
      Kristian Høgsberg authored
      The kernel shouldn't be in the business of telling user space which
      driver to load.  The kernel defers mapping PCI IDs to module names
      to user space and we should do the same for DRI drivers.
      
      And in fact, that's how it does work today.  Nothing uses the
      dri_library_name attribute, and the attribute is in fact broken.
      For intel devices, it falls back to the default behaviour of returning
      the kernel module name as the DRI driver name, which doesn't work for
      i965 devices.  Nobody has ever hit this problem or filed a bug about this.
      Signed-off-by: default avatarKristian Høgsberg <krh@redhat.com>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      8e100458
    • Kristian Høgsberg's avatar
      drm: claim PCI device when running in modesetting mode. · 112b715e
      Kristian Høgsberg authored
      Under kernel modesetting, we manage the device at all times, regardless
      of VT switching and X servers, so the only decent thing to do is to
      claim the PCI device.  In that case, we call the suspend/resume hooks
      directly from the pci driver hooks instead of the current class device detour.
      Signed-off-by: default avatarKristian Høgsberg <krh@redhat.com>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      112b715e
    • Benjamin Herrenschmidt's avatar
      drm: Make drm_local_map use a resource_size_t offset · 41c2e75e
      Benjamin Herrenschmidt authored
      This changes drm_local_map to use a resource_size for its "offset"
      member instead of an unsigned long, thus allowing 32-bit machines
      with a >32-bit physical address space to be able to store there
      their register or framebuffer addresses when those are above 4G,
      such as when using a PCI video card on a recent AMCC 440 SoC.
      
      This patch isn't as "trivial" as it sounds: A few functions needed
      to have some unsigned long/int changed to resource_size_t and a few
      printk's had to be adjusted.
      
      But also, because userspace isn't capable of passing such offsets,
      I had to modify drm_find_matching_map() to ignore the offset passed
      in for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
      
      If we ever support multiple _DRM_FRAMEBUFFER or _DRM_REGISTERS maps
      for a given device, we might have to change that trick, but I don't
      think that happens on any current driver.
      Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      41c2e75e
    • Benjamin Herrenschmidt's avatar
      drm: Split drm_map and drm_local_map · f77d390c
      Benjamin Herrenschmidt authored
      Once upon a time, the DRM made the distinction between the drm_map
      data structure exchanged with user space and the drm_local_map used
      in the kernel.
      
      For some reasons, while the BSD port still has that "feature", the
      linux part abused drm_map for kernel internal usage as the local
      map only existed as a typedef of the struct drm_map.
      
      This patch fixes it by declaring struct drm_local_map separately
      (though its content is currently identical to the userspace variant),
      and changing the kernel code to only use that, except when it's a
      user<->kernel interface (ie. ioctl).
      
      This allows subsequent changes to the in-kernel format
      
      I've also replaced the use of drm_local_map_t with struct drm_local_map
      in a couple of places. Mostly by accident but they are the same (the
      former is a typedef of the later) and I have some remote plans and
      half finished patch to completely kill the drm_local_map_t typedef
      so I left those bits in.
      Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Acked-by: default avatarEric Anholt <eric@anholt.net>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      f77d390c
    • Benjamin Herrenschmidt's avatar
      drm: Use resource_size_t for drm_get_resource_{start, len} · d883f7f1
      Benjamin Herrenschmidt authored
      The DRM uses its own wrappers to obtain resources from PCI devices,
      which currently convert the resource_size_t into an unsigned long.
      
      This is broken on 32-bit platforms with >32-bit physical address
      space.
      
      This fixes them, along with a few occurences of unsigned long used
      to store such a resource in drivers.
      Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
      d883f7f1
    • Linus Torvalds's avatar
      Linus 2.6.29-rc8 · 041b6237
      Linus Torvalds authored
      041b6237
    • Linus Torvalds's avatar
      bitmap: fix end condition in bitmap_find_free_region · aa8e4fc6
      Linus Torvalds authored
      Guennadi Liakhovetski noticed that the end condition for the loop in
      bitmap_find_free_region() is wrong, and the "return if error" was also
      using the wrong conditional that would only trigger if the bitmap was an
      exact multiple of the allocation size, which is not necessarily the case
      with dma_alloc_from_coherent().
      
      Such a failure would end up in bitmap_find_free_region() accessing
      beyond the end of the bitmap.
      Reported-by: default avatarGuennadi Liakhovetski <lg@denx.de>
      Cc: Andrew Morton <akpm@linux-foundation.org>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      aa8e4fc6
  2. 12 Mar, 2009 25 commits