[PATCH V2 12/16] drm/radeon: Make radeon card usable for Loongson.

2012-06-19 Thread j.glisse
On Tue, Jun 19, 2012 at 09:19:55AM +0200, Lucas Stach wrote:
> Hello Huacai,
> 
> Am Dienstag, den 19.06.2012, 14:50 +0800 schrieb Huacai Chen:
> > 1, Use 32-bit DMA as a workaround (Loongson has a hardware bug that it
> >doesn't support DMA address above 4GB).
> 
> This is a bug of your platform/CPU and should be fixed at a lower level,
> not in every driver. While radeon might be the only device using 40bit
> DMA right know, it is very well possible that other devices pop up in
> the future. So please fix your platform code to disallow >32bit DMA.
> 
> > 2, Read vga bios offered by system firmware.
> > 3, Handle io prot correctly for MIPS.
> 
> This seems good to me, but you should really split this out in a
> separate TTM patch.
> 
> > 4, Don't use swiotlb on Loongson machines (when use swiotlb, GPU reset
> >occurs at resume from suspend).
> > 
> While SWIOTLB might not be a common setup, simply ignoring it because it
> doesn't work on your platform is the wrong thing to do. Could you please
> try to root-cause the issue?
> 
> Thanks,
> Lucas

It's most likely because somehow with loongson and swiotlb you get bounce
page, radeon won't work with bounce pages.

Cheers,
Jerome

> 
> > Signed-off-by: Huacai Chen 
> > Signed-off-by: Hongliang Tao 
> > Signed-off-by: Hua Yan 
> > Cc: dri-devel at lists.freedesktop.org
> > ---
> >  drivers/gpu/drm/drm_vm.c   |2 +-
> >  drivers/gpu/drm/radeon/radeon_bios.c   |   32 
> > 
> >  drivers/gpu/drm/radeon/radeon_device.c |5 +
> >  drivers/gpu/drm/radeon/radeon_ttm.c|6 +++---
> >  drivers/gpu/drm/ttm/ttm_bo_util.c  |2 +-
> >  include/drm/drm_sarea.h|2 ++
> >  6 files changed, 44 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
> > index 961ee08..3f06166 100644
> > --- a/drivers/gpu/drm/drm_vm.c
> > +++ b/drivers/gpu/drm/drm_vm.c
> > @@ -62,7 +62,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct 
> > vm_area_struct *vma)
> > tmp = pgprot_writecombine(tmp);
> > else
> > tmp = pgprot_noncached(tmp);
> > -#elif defined(__sparc__) || defined(__arm__)
> > +#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
> > tmp = pgprot_noncached(tmp);
> >  #endif
> > return tmp;
> > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c 
> > b/drivers/gpu/drm/radeon/radeon_bios.c
> > index 501f488..2630e22 100644
> > --- a/drivers/gpu/drm/radeon/radeon_bios.c
> > +++ b/drivers/gpu/drm/radeon/radeon_bios.c
> > @@ -29,6 +29,7 @@
> >  #include "radeon_reg.h"
> >  #include "radeon.h"
> >  #include "atom.h"
> > +#include 
> >  
> >  #include 
> >  #include 
> > @@ -73,6 +74,32 @@ static bool igp_read_bios_from_vram(struct radeon_device 
> > *rdev)
> > return true;
> >  }
> >  
> > +#ifdef CONFIG_CPU_LOONGSON3
> > +extern u64 vgabios_addr;
> > +static bool loongson3_read_bios(struct radeon_device *rdev)
> > +{
> > +   u8 *bios;
> > +   resource_size_t size = 512 * 1024; /* ??? */
> > +
> > +   rdev->bios = NULL;
> > +
> > +   bios = (u8 *)vgabios_addr;
> > +   if (!bios) {
> > +   return false;
> > +   }
> > +
> > +   if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
> > +   return false;
> > +   }
> > +   rdev->bios = kmalloc(size, GFP_KERNEL);
> > +   if (rdev->bios == NULL) {
> > +   return false;
> > +   }
> > +   memcpy(rdev->bios, bios, size);
> > +   return true;
> > +}
> > +#endif
> > +
> >  static bool radeon_read_bios(struct radeon_device *rdev)
> >  {
> > uint8_t __iomem *bios;
> > @@ -490,6 +517,11 @@ bool radeon_get_bios(struct radeon_device *rdev)
> > if (r == false) {
> > r = radeon_read_disabled_bios(rdev);
> > }
> > +#ifdef CONFIG_CPU_LOONGSON3
> > +   if (r == false) {
> > +   r = loongson3_read_bios(rdev);
> > +   }
> > +#endif
> > if (r == false || rdev->bios == NULL) {
> > DRM_ERROR("Unable to locate a BIOS ROM\n");
> > rdev->bios = NULL;
> > diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> > b/drivers/gpu/drm/radeon/radeon_device.c
> > index 066c98b..8aac7ab 100644
> > --- a/drivers/gpu/drm/radeon/radeon_device.c
> > +++ b/drivers/gpu/drm/radeon/radeon_device.c
> > @@ -777,6 +777,11 @@ int radeon_device_init(struct radeon_device *rdev,
> > (rdev->family < CHIP_RS400))
> > rdev->need_dma32 = true;
> >  
> > +#ifdef CONFIG_CPU_LOONGSON3
> > +   /* Workaround: Loongson 3 doesn't support 40-bits DMA */
> > +   rdev->need_dma32 = true;
> > +#endif
> > +
> > dma_bits = rdev->need_dma32 ? 32 : 40;
> > r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
> > if (r) {
> > diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
> > b/drivers/gpu/drm/radeon/radeon_ttm.c
> > index c94a225..f49bdd1 100644
> > --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> > +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> > @@ -630,7 +630,7 @@ static int 

[PATCH V2 12/16] drm/radeon: Make radeon card usable for Loongson.

2012-06-19 Thread j.glisse
On Tue, Jun 19, 2012 at 02:50:20PM +0800, Huacai Chen wrote:
> 1, Use 32-bit DMA as a workaround (Loongson has a hardware bug that it
>doesn't support DMA address above 4GB).
> 2, Read vga bios offered by system firmware.
> 3, Handle io prot correctly for MIPS.
> 4, Don't use swiotlb on Loongson machines (when use swiotlb, GPU reset
>occurs at resume from suspend).
> 
> Signed-off-by: Huacai Chen 
> Signed-off-by: Hongliang Tao 
> Signed-off-by: Hua Yan 
> Cc: dri-devel at lists.freedesktop.org
> ---
>  drivers/gpu/drm/drm_vm.c   |2 +-
>  drivers/gpu/drm/radeon/radeon_bios.c   |   32 
> 
>  drivers/gpu/drm/radeon/radeon_device.c |5 +
>  drivers/gpu/drm/radeon/radeon_ttm.c|6 +++---
>  drivers/gpu/drm/ttm/ttm_bo_util.c  |2 +-
>  include/drm/drm_sarea.h|2 ++
>  6 files changed, 44 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
> index 961ee08..3f06166 100644
> --- a/drivers/gpu/drm/drm_vm.c
> +++ b/drivers/gpu/drm/drm_vm.c
> @@ -62,7 +62,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct 
> vm_area_struct *vma)
>   tmp = pgprot_writecombine(tmp);
>   else
>   tmp = pgprot_noncached(tmp);
> -#elif defined(__sparc__) || defined(__arm__)
> +#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>   tmp = pgprot_noncached(tmp);
>  #endif
>   return tmp;
> diff --git a/drivers/gpu/drm/radeon/radeon_bios.c 
> b/drivers/gpu/drm/radeon/radeon_bios.c
> index 501f488..2630e22 100644
> --- a/drivers/gpu/drm/radeon/radeon_bios.c
> +++ b/drivers/gpu/drm/radeon/radeon_bios.c
> @@ -29,6 +29,7 @@
>  #include "radeon_reg.h"
>  #include "radeon.h"
>  #include "atom.h"
> +#include 
>  
>  #include 
>  #include 
> @@ -73,6 +74,32 @@ static bool igp_read_bios_from_vram(struct radeon_device 
> *rdev)
>   return true;
>  }
>  
> +#ifdef CONFIG_CPU_LOONGSON3
> +extern u64 vgabios_addr;

Ugly, is this how platform specific stuff are handled usualy ? I hope not,
i would rather see a platform specific function such as loongson3_get_vga_bios.

Cheers,
Jerome

> +static bool loongson3_read_bios(struct radeon_device *rdev)
> +{
> + u8 *bios;
> + resource_size_t size = 512 * 1024; /* ??? */
> +
> + rdev->bios = NULL;
> +
> + bios = (u8 *)vgabios_addr;
> + if (!bios) {
> + return false;
> + }
> +
> + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
> + return false;
> + }
> + rdev->bios = kmalloc(size, GFP_KERNEL);
> + if (rdev->bios == NULL) {
> + return false;
> + }
> + memcpy(rdev->bios, bios, size);
> + return true;
> +}
> +#endif
> +
>  static bool radeon_read_bios(struct radeon_device *rdev)
>  {
>   uint8_t __iomem *bios;
> @@ -490,6 +517,11 @@ bool radeon_get_bios(struct radeon_device *rdev)
>   if (r == false) {
>   r = radeon_read_disabled_bios(rdev);
>   }
> +#ifdef CONFIG_CPU_LOONGSON3
> + if (r == false) {
> + r = loongson3_read_bios(rdev);
> + }
> +#endif
>   if (r == false || rdev->bios == NULL) {
>   DRM_ERROR("Unable to locate a BIOS ROM\n");
>   rdev->bios = NULL;
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index 066c98b..8aac7ab 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -777,6 +777,11 @@ int radeon_device_init(struct radeon_device *rdev,
>   (rdev->family < CHIP_RS400))
>   rdev->need_dma32 = true;
>  
> +#ifdef CONFIG_CPU_LOONGSON3
> + /* Workaround: Loongson 3 doesn't support 40-bits DMA */
> + rdev->need_dma32 = true;
> +#endif
> +
>   dma_bits = rdev->need_dma32 ? 32 : 40;
>   r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
>   if (r) {
> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
> b/drivers/gpu/drm/radeon/radeon_ttm.c
> index c94a225..f49bdd1 100644
> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> @@ -630,7 +630,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
>   }
>  #endif
>  
> -#ifdef CONFIG_SWIOTLB
> +#if defined(CONFIG_SWIOTLB) && !defined(CONFIG_CPU_LOONGSON3)
>   if (swiotlb_nr_tbl()) {
>   return ttm_dma_populate(>ttm, rdev->dev);
>   }
> @@ -676,7 +676,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm)
>   }
>  #endif
>  
> -#ifdef CONFIG_SWIOTLB
> +#if defined(CONFIG_SWIOTLB) && !defined(CONFIG_CPU_LOONGSON3)
>   if (swiotlb_nr_tbl()) {
>   ttm_dma_unpopulate(>ttm, rdev->dev);
>   return;
> @@ -906,7 +906,7 @@ static int radeon_ttm_debugfs_init(struct radeon_device 
> *rdev)
>   radeon_mem_types_list[i].show = _page_alloc_debugfs;
>   radeon_mem_types_list[i].driver_features = 0;
>   radeon_mem_types_list[i++].data = NULL;
> 

Re: [PATCH V2 12/16] drm/radeon: Make radeon card usable for Loongson.

2012-06-19 Thread j.glisse
On Tue, Jun 19, 2012 at 02:50:20PM +0800, Huacai Chen wrote:
 1, Use 32-bit DMA as a workaround (Loongson has a hardware bug that it
doesn't support DMA address above 4GB).
 2, Read vga bios offered by system firmware.
 3, Handle io prot correctly for MIPS.
 4, Don't use swiotlb on Loongson machines (when use swiotlb, GPU reset
occurs at resume from suspend).
 
 Signed-off-by: Huacai Chen che...@lemote.com
 Signed-off-by: Hongliang Tao ta...@lemote.com
 Signed-off-by: Hua Yan y...@lemote.com
 Cc: dri-devel@lists.freedesktop.org
 ---
  drivers/gpu/drm/drm_vm.c   |2 +-
  drivers/gpu/drm/radeon/radeon_bios.c   |   32 
 
  drivers/gpu/drm/radeon/radeon_device.c |5 +
  drivers/gpu/drm/radeon/radeon_ttm.c|6 +++---
  drivers/gpu/drm/ttm/ttm_bo_util.c  |2 +-
  include/drm/drm_sarea.h|2 ++
  6 files changed, 44 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
 index 961ee08..3f06166 100644
 --- a/drivers/gpu/drm/drm_vm.c
 +++ b/drivers/gpu/drm/drm_vm.c
 @@ -62,7 +62,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct 
 vm_area_struct *vma)
   tmp = pgprot_writecombine(tmp);
   else
   tmp = pgprot_noncached(tmp);
 -#elif defined(__sparc__) || defined(__arm__)
 +#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
   tmp = pgprot_noncached(tmp);
  #endif
   return tmp;
 diff --git a/drivers/gpu/drm/radeon/radeon_bios.c 
 b/drivers/gpu/drm/radeon/radeon_bios.c
 index 501f488..2630e22 100644
 --- a/drivers/gpu/drm/radeon/radeon_bios.c
 +++ b/drivers/gpu/drm/radeon/radeon_bios.c
 @@ -29,6 +29,7 @@
  #include radeon_reg.h
  #include radeon.h
  #include atom.h
 +#include asm/bootinfo.h
  
  #include linux/vga_switcheroo.h
  #include linux/slab.h
 @@ -73,6 +74,32 @@ static bool igp_read_bios_from_vram(struct radeon_device 
 *rdev)
   return true;
  }
  
 +#ifdef CONFIG_CPU_LOONGSON3
 +extern u64 vgabios_addr;

Ugly, is this how platform specific stuff are handled usualy ? I hope not,
i would rather see a platform specific function such as loongson3_get_vga_bios.

Cheers,
Jerome

 +static bool loongson3_read_bios(struct radeon_device *rdev)
 +{
 + u8 *bios;
 + resource_size_t size = 512 * 1024; /* ??? */
 +
 + rdev-bios = NULL;
 +
 + bios = (u8 *)vgabios_addr;
 + if (!bios) {
 + return false;
 + }
 +
 + if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
 + return false;
 + }
 + rdev-bios = kmalloc(size, GFP_KERNEL);
 + if (rdev-bios == NULL) {
 + return false;
 + }
 + memcpy(rdev-bios, bios, size);
 + return true;
 +}
 +#endif
 +
  static bool radeon_read_bios(struct radeon_device *rdev)
  {
   uint8_t __iomem *bios;
 @@ -490,6 +517,11 @@ bool radeon_get_bios(struct radeon_device *rdev)
   if (r == false) {
   r = radeon_read_disabled_bios(rdev);
   }
 +#ifdef CONFIG_CPU_LOONGSON3
 + if (r == false) {
 + r = loongson3_read_bios(rdev);
 + }
 +#endif
   if (r == false || rdev-bios == NULL) {
   DRM_ERROR(Unable to locate a BIOS ROM\n);
   rdev-bios = NULL;
 diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
 b/drivers/gpu/drm/radeon/radeon_device.c
 index 066c98b..8aac7ab 100644
 --- a/drivers/gpu/drm/radeon/radeon_device.c
 +++ b/drivers/gpu/drm/radeon/radeon_device.c
 @@ -777,6 +777,11 @@ int radeon_device_init(struct radeon_device *rdev,
   (rdev-family  CHIP_RS400))
   rdev-need_dma32 = true;
  
 +#ifdef CONFIG_CPU_LOONGSON3
 + /* Workaround: Loongson 3 doesn't support 40-bits DMA */
 + rdev-need_dma32 = true;
 +#endif
 +
   dma_bits = rdev-need_dma32 ? 32 : 40;
   r = pci_set_dma_mask(rdev-pdev, DMA_BIT_MASK(dma_bits));
   if (r) {
 diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
 b/drivers/gpu/drm/radeon/radeon_ttm.c
 index c94a225..f49bdd1 100644
 --- a/drivers/gpu/drm/radeon/radeon_ttm.c
 +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
 @@ -630,7 +630,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
   }
  #endif
  
 -#ifdef CONFIG_SWIOTLB
 +#if defined(CONFIG_SWIOTLB)  !defined(CONFIG_CPU_LOONGSON3)
   if (swiotlb_nr_tbl()) {
   return ttm_dma_populate(gtt-ttm, rdev-dev);
   }
 @@ -676,7 +676,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm)
   }
  #endif
  
 -#ifdef CONFIG_SWIOTLB
 +#if defined(CONFIG_SWIOTLB)  !defined(CONFIG_CPU_LOONGSON3)
   if (swiotlb_nr_tbl()) {
   ttm_dma_unpopulate(gtt-ttm, rdev-dev);
   return;
 @@ -906,7 +906,7 @@ static int radeon_ttm_debugfs_init(struct radeon_device 
 *rdev)
   radeon_mem_types_list[i].show = ttm_page_alloc_debugfs;
   radeon_mem_types_list[i].driver_features = 0;
   radeon_mem_types_list[i++].data = NULL;
 -#ifdef CONFIG_SWIOTLB
 +#if defined(CONFIG_SWIOTLB)  

Re: [PATCH V2 12/16] drm/radeon: Make radeon card usable for Loongson.

2012-06-19 Thread j.glisse
On Tue, Jun 19, 2012 at 09:19:55AM +0200, Lucas Stach wrote:
 Hello Huacai,
 
 Am Dienstag, den 19.06.2012, 14:50 +0800 schrieb Huacai Chen:
  1, Use 32-bit DMA as a workaround (Loongson has a hardware bug that it
 doesn't support DMA address above 4GB).
 
 This is a bug of your platform/CPU and should be fixed at a lower level,
 not in every driver. While radeon might be the only device using 40bit
 DMA right know, it is very well possible that other devices pop up in
 the future. So please fix your platform code to disallow 32bit DMA.
 
  2, Read vga bios offered by system firmware.
  3, Handle io prot correctly for MIPS.
 
 This seems good to me, but you should really split this out in a
 separate TTM patch.
 
  4, Don't use swiotlb on Loongson machines (when use swiotlb, GPU reset
 occurs at resume from suspend).
  
 While SWIOTLB might not be a common setup, simply ignoring it because it
 doesn't work on your platform is the wrong thing to do. Could you please
 try to root-cause the issue?
 
 Thanks,
 Lucas

It's most likely because somehow with loongson and swiotlb you get bounce
page, radeon won't work with bounce pages.

Cheers,
Jerome

 
  Signed-off-by: Huacai Chen che...@lemote.com
  Signed-off-by: Hongliang Tao ta...@lemote.com
  Signed-off-by: Hua Yan y...@lemote.com
  Cc: dri-devel@lists.freedesktop.org
  ---
   drivers/gpu/drm/drm_vm.c   |2 +-
   drivers/gpu/drm/radeon/radeon_bios.c   |   32 
  
   drivers/gpu/drm/radeon/radeon_device.c |5 +
   drivers/gpu/drm/radeon/radeon_ttm.c|6 +++---
   drivers/gpu/drm/ttm/ttm_bo_util.c  |2 +-
   include/drm/drm_sarea.h|2 ++
   6 files changed, 44 insertions(+), 5 deletions(-)
  
  diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
  index 961ee08..3f06166 100644
  --- a/drivers/gpu/drm/drm_vm.c
  +++ b/drivers/gpu/drm/drm_vm.c
  @@ -62,7 +62,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct 
  vm_area_struct *vma)
  tmp = pgprot_writecombine(tmp);
  else
  tmp = pgprot_noncached(tmp);
  -#elif defined(__sparc__) || defined(__arm__)
  +#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
  tmp = pgprot_noncached(tmp);
   #endif
  return tmp;
  diff --git a/drivers/gpu/drm/radeon/radeon_bios.c 
  b/drivers/gpu/drm/radeon/radeon_bios.c
  index 501f488..2630e22 100644
  --- a/drivers/gpu/drm/radeon/radeon_bios.c
  +++ b/drivers/gpu/drm/radeon/radeon_bios.c
  @@ -29,6 +29,7 @@
   #include radeon_reg.h
   #include radeon.h
   #include atom.h
  +#include asm/bootinfo.h
   
   #include linux/vga_switcheroo.h
   #include linux/slab.h
  @@ -73,6 +74,32 @@ static bool igp_read_bios_from_vram(struct radeon_device 
  *rdev)
  return true;
   }
   
  +#ifdef CONFIG_CPU_LOONGSON3
  +extern u64 vgabios_addr;
  +static bool loongson3_read_bios(struct radeon_device *rdev)
  +{
  +   u8 *bios;
  +   resource_size_t size = 512 * 1024; /* ??? */
  +
  +   rdev-bios = NULL;
  +
  +   bios = (u8 *)vgabios_addr;
  +   if (!bios) {
  +   return false;
  +   }
  +
  +   if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
  +   return false;
  +   }
  +   rdev-bios = kmalloc(size, GFP_KERNEL);
  +   if (rdev-bios == NULL) {
  +   return false;
  +   }
  +   memcpy(rdev-bios, bios, size);
  +   return true;
  +}
  +#endif
  +
   static bool radeon_read_bios(struct radeon_device *rdev)
   {
  uint8_t __iomem *bios;
  @@ -490,6 +517,11 @@ bool radeon_get_bios(struct radeon_device *rdev)
  if (r == false) {
  r = radeon_read_disabled_bios(rdev);
  }
  +#ifdef CONFIG_CPU_LOONGSON3
  +   if (r == false) {
  +   r = loongson3_read_bios(rdev);
  +   }
  +#endif
  if (r == false || rdev-bios == NULL) {
  DRM_ERROR(Unable to locate a BIOS ROM\n);
  rdev-bios = NULL;
  diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
  b/drivers/gpu/drm/radeon/radeon_device.c
  index 066c98b..8aac7ab 100644
  --- a/drivers/gpu/drm/radeon/radeon_device.c
  +++ b/drivers/gpu/drm/radeon/radeon_device.c
  @@ -777,6 +777,11 @@ int radeon_device_init(struct radeon_device *rdev,
  (rdev-family  CHIP_RS400))
  rdev-need_dma32 = true;
   
  +#ifdef CONFIG_CPU_LOONGSON3
  +   /* Workaround: Loongson 3 doesn't support 40-bits DMA */
  +   rdev-need_dma32 = true;
  +#endif
  +
  dma_bits = rdev-need_dma32 ? 32 : 40;
  r = pci_set_dma_mask(rdev-pdev, DMA_BIT_MASK(dma_bits));
  if (r) {
  diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
  b/drivers/gpu/drm/radeon/radeon_ttm.c
  index c94a225..f49bdd1 100644
  --- a/drivers/gpu/drm/radeon/radeon_ttm.c
  +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
  @@ -630,7 +630,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
  }
   #endif
   
  -#ifdef CONFIG_SWIOTLB
  +#if defined(CONFIG_SWIOTLB)  !defined(CONFIG_CPU_LOONGSON3)
  if (swiotlb_nr_tbl()) {
  

[PATCH 06/10] drm/radeon: fix & improve ih ring handling

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:10AM +0200, Christian K?nig wrote:
> From: Christian Koenig 
> 
> The spinlock was actually there to protect the
> rptr, but rptr was read outside of the locked area.
> 
> Also we don't really need a spinlock here, an
> atomic should to quite fine since we only need to
> prevent it from being reentrant.
> 
> Signed-off-by: Christian Koenig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen.c |   29 -
>  drivers/gpu/drm/radeon/r600.c  |   30 +++---
>  drivers/gpu/drm/radeon/radeon.h|3 +--
>  drivers/gpu/drm/radeon/radeon_device.c |3 +--
>  drivers/gpu/drm/radeon/si.c|   30 --
>  5 files changed, 49 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> b/drivers/gpu/drm/radeon/evergreen.c
> index dd3cea4..bfcb39e 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -2943,7 +2943,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
>   u32 rptr;
>   u32 src_id, src_data;
>   u32 ring_index;
> - unsigned long flags;
>   bool queue_hotplug = false;
>   bool queue_hdmi = false;
>  
> @@ -2951,22 +2950,24 @@ int evergreen_irq_process(struct radeon_device *rdev)
>   return IRQ_NONE;
>  
>   wptr = evergreen_get_ih_wptr(rdev);
> +
> +restart_ih:
> + /* is somebody else already processing irqs? */
> + if (atomic_xchg(>ih.lock, 1))
> + return IRQ_NONE;
> +
>   rptr = rdev->ih.rptr;
> + if (rptr == wptr)
> + return IRQ_NONE;
> +
>   DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
>  
> - spin_lock_irqsave(>ih.lock, flags);
> - if (rptr == wptr) {
> - spin_unlock_irqrestore(>ih.lock, flags);
> - return IRQ_NONE;
> - }
> -restart_ih:
>   /* Order reading of wptr vs. reading of IH ring data */
>   rmb();
>  
>   /* display interrupts */
>   evergreen_irq_ack(rdev);
>  
> - rdev->ih.wptr = wptr;
>   while (rptr != wptr) {
>   /* wptr/rptr are in bytes! */
>   ring_index = rptr / 4;
> @@ -3265,17 +3266,19 @@ restart_ih:
>   rptr += 16;
>   rptr &= rdev->ih.ptr_mask;
>   }
> - /* make sure wptr hasn't changed while processing */
> - wptr = evergreen_get_ih_wptr(rdev);
> - if (wptr != rdev->ih.wptr)
> - goto restart_ih;
>   if (queue_hotplug)
>   schedule_work(>hotplug_work);
>   if (queue_hdmi)
>   schedule_work(>audio_work);
>   rdev->ih.rptr = rptr;
>   WREG32(IH_RB_RPTR, rdev->ih.rptr);
> - spin_unlock_irqrestore(>ih.lock, flags);
> + atomic_set(>ih.lock, 0);
> +
> + /* make sure wptr hasn't changed while processing */
> + wptr = evergreen_get_ih_wptr(rdev);
> + if (wptr != rptr)
> + goto restart_ih;
> +
>   return IRQ_HANDLED;
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index a8d8c44..eadbb06 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2921,7 +2921,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
>   WREG32(IH_RB_RPTR, 0);
>   WREG32(IH_RB_WPTR, 0);
>   rdev->ih.enabled = false;
> - rdev->ih.wptr = 0;
>   rdev->ih.rptr = 0;
>  }
>  
> @@ -3373,7 +3372,6 @@ int r600_irq_process(struct radeon_device *rdev)
>   u32 rptr;
>   u32 src_id, src_data;
>   u32 ring_index;
> - unsigned long flags;
>   bool queue_hotplug = false;
>   bool queue_hdmi = false;
>  
> @@ -3385,24 +3383,24 @@ int r600_irq_process(struct radeon_device *rdev)
>   RREG32(IH_RB_WPTR);
>  
>   wptr = r600_get_ih_wptr(rdev);
> - rptr = rdev->ih.rptr;
> - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
>  
> - spin_lock_irqsave(>ih.lock, flags);
> +restart_ih:
> + /* is somebody else already processing irqs? */
> + if (atomic_xchg(>ih.lock, 1))
> + return IRQ_NONE;
>  
> - if (rptr == wptr) {
> - spin_unlock_irqrestore(>ih.lock, flags);
> + rptr = rdev->ih.rptr;
> + if (rptr == wptr)
>   return IRQ_NONE;
> - }
>  
> -restart_ih:
> + DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
> +
>   /* Order reading of wptr vs. reading of IH ring data */
>   rmb();
>  
>   /* display interrupts */
>   r600_irq_ack(rdev);
>  
> - rdev->ih.wptr = wptr;
>   while (rptr != wptr) {
>   /* wptr/rptr are in bytes! */
>   ring_index = rptr / 4;
> @@ -3556,17 +3554,19 @@ restart_ih:
>   rptr += 16;
>   rptr &= rdev->ih.ptr_mask;
>   }
> - /* make sure wptr hasn't changed while processing */
> - wptr = r600_get_ih_wptr(rdev);
> - if (wptr != rdev->ih.wptr)

[PATCH 05/10] drm/radeon: remove some unneeded structure members

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:09AM +0200, Christian K?nig wrote:
> From: Christian Koenig 
> 
> Signed-off-by: Christian Koenig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h |2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 3e83480..618df9a 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -733,9 +733,7 @@ struct r600_ih {
>   struct radeon_bo*ring_obj;
>   volatile uint32_t   *ring;
>   unsignedrptr;
> - unsignedrptr_offs;
>   unsignedwptr;
> - unsignedwptr_old;
>   unsignedring_size;
>   uint64_tgpu_addr;
>   uint32_tptr_mask;
> -- 
> 1.7.9.5
> 


[PATCH 04/10] drm/radeon: replace vmram_mutex with mclk_lock v2

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:08AM +0200, Christian K?nig wrote:
> It is a rw_semaphore now and only write locked
> while changing the clock. Also the lock is renamed
> to better reflect what it is protecting.
> 
> v2: Keep the ttm_vm_ops on IGPs
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h|3 ++-
>  drivers/gpu/drm/radeon/radeon_device.c |2 +-
>  drivers/gpu/drm/radeon/radeon_object.c |8 
>  drivers/gpu/drm/radeon/radeon_pm.c |4 ++--
>  drivers/gpu/drm/radeon/radeon_ttm.c|4 ++--
>  5 files changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index aebaf28..3e83480 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -1055,6 +1055,8 @@ struct radeon_power_state {
>  
>  struct radeon_pm {
>   struct mutexmutex;
> + /* write locked while reprogramming mclk */
> + struct rw_semaphore mclk_lock;
>   u32 active_crtcs;
>   int active_crtc_count;
>   int req_vblank;
> @@ -1551,7 +1553,6 @@ struct radeon_device {
>   struct work_struct audio_work;
>   int num_crtc; /* number of crtcs */
>   struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
> - struct mutex vram_mutex;
>   bool audio_enabled;
>   struct r600_audio audio_status; /* audio stuff */
>   struct notifier_block acpi_nb;
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index 066c98b..7667184 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -735,7 +735,7 @@ int radeon_device_init(struct radeon_device *rdev,
>   spin_lock_init(>ih.lock);
>   mutex_init(>gem.mutex);
>   mutex_init(>pm.mutex);
> - mutex_init(>vram_mutex);
> + init_rwsem(>pm.mclk_lock);
>   init_waitqueue_head(>irq.vblank_queue);
>   init_waitqueue_head(>irq.idle_queue);
>   r = radeon_gem_init(rdev);
> diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
> b/drivers/gpu/drm/radeon/radeon_object.c
> index 830f1a7..6ecb200 100644
> --- a/drivers/gpu/drm/radeon/radeon_object.c
> +++ b/drivers/gpu/drm/radeon/radeon_object.c
> @@ -154,11 +154,11 @@ retry:
>   INIT_LIST_HEAD(>va);
>   radeon_ttm_placement_from_domain(bo, domain);
>   /* Kernel allocation are uninterruptible */
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   r = ttm_bo_init(>mman.bdev, >tbo, size, type,
>   >placement, page_align, 0, !kernel, NULL,
>   acc_size, sg, _ttm_bo_destroy);
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   if (unlikely(r != 0)) {
>   if (r != -ERESTARTSYS) {
>   if (domain == RADEON_GEM_DOMAIN_VRAM) {
> @@ -219,9 +219,9 @@ void radeon_bo_unref(struct radeon_bo **bo)
>   return;
>   rdev = (*bo)->rdev;
>   tbo = &((*bo)->tbo);
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   ttm_bo_unref();
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   if (tbo == NULL)
>   *bo = NULL;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
> b/drivers/gpu/drm/radeon/radeon_pm.c
> index 0882554..d13b6ae 100644
> --- a/drivers/gpu/drm/radeon/radeon_pm.c
> +++ b/drivers/gpu/drm/radeon/radeon_pm.c
> @@ -251,7 +251,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
> *rdev)
>   return;
>  
>   mutex_lock(>ddev->struct_mutex);
> - mutex_lock(>vram_mutex);
> + down_write(>pm.mclk_lock);
>   mutex_lock(>ring_lock);
>  
>   /* gui idle int has issues on older chips it seems */
> @@ -303,7 +303,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
> *rdev)
>   rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
>  
>   mutex_unlock(>ring_lock);
> - mutex_unlock(>vram_mutex);
> + up_write(>pm.mclk_lock);
>   mutex_unlock(>ddev->struct_mutex);
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
> b/drivers/gpu/drm/radeon/radeon_ttm.c
> index c43035c..0881131 100644
> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> @@ -797,9 +797,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, 
> struct vm_fault *vmf)
>   return VM_FAULT_NOPAGE;
>   }
>   rdev = radeon_get_rdev(bo->bdev);
> - mutex_lock(>vram_mutex);
> + down_read(>pm.mclk_lock);
>   r = ttm_vm_ops->fault(vma, vmf);
> - mutex_unlock(>vram_mutex);
> + up_read(>pm.mclk_lock);
>   return r;
>  }
>  
> -- 
> 1.7.9.5
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 03/10] drm/radeon: rework ring syncing code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:07AM +0200, Christian K?nig wrote:
> Move inter ring syncing with semaphores into the
> existing ring allocations, with that we need to
> lock the ring mutex only once.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen_blit_kms.c |3 +-
>  drivers/gpu/drm/radeon/r600.c   |5 +-
>  drivers/gpu/drm/radeon/r600_blit_kms.c  |   24 +++--
>  drivers/gpu/drm/radeon/radeon.h |6 +--
>  drivers/gpu/drm/radeon/radeon_asic.h|5 +-
>  drivers/gpu/drm/radeon/radeon_cs.c  |   38 +++---
>  drivers/gpu/drm/radeon/radeon_ring.c|   30 +--
>  drivers/gpu/drm/radeon/radeon_semaphore.c   |   71 
> ++-
>  drivers/gpu/drm/radeon/radeon_test.c|6 +--
>  drivers/gpu/drm/radeon/radeon_ttm.c |   20 
>  10 files changed, 92 insertions(+), 116 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c 
> b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> index 1e96bd4..e512560 100644
> --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
> @@ -622,7 +622,8 @@ int evergreen_blit_init(struct radeon_device *rdev)
>   rdev->r600_blit.primitives.draw_auto = draw_auto;
>   rdev->r600_blit.primitives.set_default_state = set_default_state;
>  
> - rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
> + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */
> + rdev->r600_blit.ring_size_common += 55; /* shaders + def state */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
>   rdev->r600_blit.ring_size_common += 5; /* done copy */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index e5279f9..a8d8c44 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2371,15 +2371,16 @@ int r600_copy_blit(struct radeon_device *rdev,
>  unsigned num_gpu_pages,
>  struct radeon_fence **fence)
>  {
> + struct radeon_semaphore *sem = NULL;
>   struct radeon_sa_bo *vb = NULL;
>   int r;
>  
> - r = r600_blit_prepare_copy(rdev, num_gpu_pages, );
> + r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, , );
>   if (r) {
>   return r;
>   }
>   r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb);
> - r600_blit_done_copy(rdev, fence, vb);
> + r600_blit_done_copy(rdev, fence, vb, sem);
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c 
> b/drivers/gpu/drm/radeon/r600_blit_kms.c
> index 02f4eeb..2b8d641 100644
> --- a/drivers/gpu/drm/radeon/r600_blit_kms.c
> +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
> @@ -512,7 +512,8 @@ int r600_blit_init(struct radeon_device *rdev)
>   rdev->r600_blit.primitives.draw_auto = draw_auto;
>   rdev->r600_blit.primitives.set_default_state = set_default_state;
>  
> - rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
> + rdev->r600_blit.ring_size_common = 8; /* sync semaphore */
> + rdev->r600_blit.ring_size_common += 40; /* shaders + def state */
>   rdev->r600_blit.ring_size_common += 5; /* done copy */
>   rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
>  
> @@ -666,7 +667,8 @@ static unsigned r600_blit_create_rect(unsigned 
> num_gpu_pages,
>  
>  
>  int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned 
> num_gpu_pages,
> -struct radeon_sa_bo **vb)
> +struct radeon_fence **fence, struct radeon_sa_bo 
> **vb,
> +struct radeon_semaphore **sem)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   int r;
> @@ -689,22 +691,37 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, 
> unsigned num_gpu_pages,
>   return r;
>   }
>  
> + r = radeon_semaphore_create(rdev, sem);
> + if (r) {
> + radeon_sa_bo_free(rdev, vb, NULL);
> + return r;
> + }
> +
>   /* calculate number of loops correctly */
>   ring_size = num_loops * dwords_per_loop;
>   ring_size += rdev->r600_blit.ring_size_common;
>   r = radeon_ring_lock(rdev, ring, ring_size);
>   if (r) {
>   radeon_sa_bo_free(rdev, vb, NULL);
> + radeon_semaphore_free(rdev, sem, NULL);
>   return r;
>   }
>  
> + if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) {
> + radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring,
> + RADEON_RING_TYPE_GFX_INDEX);
> + radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX);
> + } else {
> + radeon_semaphore_free(rdev, sem, NULL);
> + }
> +

[PATCH 02/10] drm/radeon: add infrastructure for advanced ring synchronization

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:06AM +0200, Christian K?nig wrote:
> Signed-off-by: Christian K?nig 

Need a small improvement see below, otherwise

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/radeon.h   |   23 ++-
>  drivers/gpu/drm/radeon/radeon_fence.c |   73 
> +
>  2 files changed, 85 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 5e259b4..4e232c3 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -257,8 +257,8 @@ struct radeon_fence_driver {
>   uint32_tscratch_reg;
>   uint64_tgpu_addr;
>   volatile uint32_t   *cpu_addr;
> - /* seq is protected by ring emission lock */
> - uint64_tseq;
> + /* sync_seq is protected by ring emission lock */
> + uint64_tsync_seq[RADEON_NUM_RINGS];
>   atomic64_t  last_seq;
>   unsigned long   last_activity;
>   boolinitialized;
> @@ -288,6 +288,25 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
>  struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
>  void radeon_fence_unref(struct radeon_fence **fence);
>  unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
> +bool radeon_fence_need_sync(struct radeon_fence *fence, int ring);
> +void radeon_fence_note_sync(struct radeon_fence *fence, int ring);
> +static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a,
> +   struct radeon_fence *b)
> +{
> + if (!a) {
> + return b;
> + }
> +
> + if (!b) {
> + return a;
> + }

Please add :
BUG_ON(a->ring != b->ring);

So we can catch if someone badly use this function.

> +
> + if (a->seq > b->seq) {
> + return a;
> + } else {
> + return b;
> + }
> +}
>  
>  /*
>   * Tiling registers
> diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
> b/drivers/gpu/drm/radeon/radeon_fence.c
> index 401d346..7b55625 100644
> --- a/drivers/gpu/drm/radeon/radeon_fence.c
> +++ b/drivers/gpu/drm/radeon/radeon_fence.c
> @@ -72,7 +72,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
>   }
>   kref_init(&((*fence)->kref));
>   (*fence)->rdev = rdev;
> - (*fence)->seq = ++rdev->fence_drv[ring].seq;
> + (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
>   (*fence)->ring = ring;
>   radeon_fence_ring_emit(rdev, ring, *fence);
>   trace_radeon_fence_emit(rdev->ddev, (*fence)->seq);
> @@ -449,7 +449,7 @@ int radeon_fence_wait_next_locked(struct radeon_device 
> *rdev, int ring)
>* wait.
>*/
>   seq = atomic64_read(>fence_drv[ring].last_seq) + 1ULL;
> - if (seq >= rdev->fence_drv[ring].seq) {
> + if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
>   /* nothing to wait for, last_seq is
>  already the last emited fence */
>   return -ENOENT;
> @@ -464,7 +464,7 @@ int radeon_fence_wait_empty_locked(struct radeon_device 
> *rdev, int ring)
>* activity can be scheduled so there won't be concurrent access
>* to seq value.
>*/
> - return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
> + return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].sync_seq[ring],
>ring, false, false);
>  }
>  
> @@ -492,7 +492,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
> *rdev, int ring)
>* but it's ok to report slightly wrong fence count here.
>*/
>   radeon_fence_process(rdev, ring);
> - emitted = rdev->fence_drv[ring].seq - 
> atomic64_read(>fence_drv[ring].last_seq);
> + emitted = rdev->fence_drv[ring].sync_seq[ring]
> + - atomic64_read(>fence_drv[ring].last_seq);
>   /* to avoid 32bits warp around */
>   if (emitted > 0x1000) {
>   emitted = 0x1000;
> @@ -500,6 +501,51 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
> *rdev, int ring)
>   return (unsigned)emitted;
>  }
>  
> +bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
> +{
> + struct radeon_fence_driver *fdrv;
> +
> + if (!fence) {
> + return false;
> + }
> +
> + if (fence->ring == dst_ring) {
> + return false;
> + }
> +
> + /* we are protected by the ring mutex */
> + fdrv = >rdev->fence_drv[dst_ring];
> + if (fence->seq <= fdrv->sync_seq[fence->ring]) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> +void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
> +{
> + struct radeon_fence_driver *dst, *src;
> + unsigned i;
> +
> + if (!fence) {
> + return;
> + }
> +
> + if 

[PATCH 01/10] drm/radeon: remove radeon_fence_create

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:05AM +0200, Christian K?nig wrote:
> It is completely unnecessary to create fences
> before they are emitted, so remove it and a bunch
> of checks if fences are emitted or not.
> 
> Signed-off-by: Christian K?nig 

Reviewed-by: Jerome Glisse 

> ---
>  drivers/gpu/drm/radeon/evergreen.c|2 +-
>  drivers/gpu/drm/radeon/ni.c   |2 +-
>  drivers/gpu/drm/radeon/r100.c |4 +-
>  drivers/gpu/drm/radeon/r200.c |4 +-
>  drivers/gpu/drm/radeon/r600.c |4 +-
>  drivers/gpu/drm/radeon/r600_blit_kms.c|6 +--
>  drivers/gpu/drm/radeon/radeon.h   |   11 +++--
>  drivers/gpu/drm/radeon/radeon_asic.h  |8 ++--
>  drivers/gpu/drm/radeon/radeon_benchmark.c |   10 +
>  drivers/gpu/drm/radeon/radeon_fence.c |   42 ++
>  drivers/gpu/drm/radeon/radeon_ring.c  |   19 +
>  drivers/gpu/drm/radeon/radeon_sa.c|2 +-
>  drivers/gpu/drm/radeon/radeon_test.c  |   66 
> -
>  drivers/gpu/drm/radeon/radeon_ttm.c   |   30 +
>  drivers/gpu/drm/radeon/si.c   |6 +--
>  15 files changed, 86 insertions(+), 130 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> b/drivers/gpu/drm/radeon/evergreen.c
> index 58991af..dd3cea4 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1366,7 +1366,7 @@ void evergreen_mc_program(struct radeon_device *rdev)
>   */
>  void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib 
> *ib)
>  {
> - struct radeon_ring *ring = >ring[ib->fence->ring];
> + struct radeon_ring *ring = >ring[ib->ring];
>  
>   /* set to DX10/11 mode */
>   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
> diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
> index b01c2dd..9d9f5ac 100644
> --- a/drivers/gpu/drm/radeon/ni.c
> +++ b/drivers/gpu/drm/radeon/ni.c
> @@ -1127,7 +1127,7 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
>  
>  void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
>  {
> - struct radeon_ring *ring = >ring[ib->fence->ring];
> + struct radeon_ring *ring = >ring[ib->ring];
>  
>   /* set to DX10/11 mode */
>   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index fb44e7e..415b7d8 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -883,7 +883,7 @@ int r100_copy_blit(struct radeon_device *rdev,
>  uint64_t src_offset,
>  uint64_t dst_offset,
>  unsigned num_gpu_pages,
> -struct radeon_fence *fence)
> +struct radeon_fence **fence)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   uint32_t cur_pages;
> @@ -947,7 +947,7 @@ int r100_copy_blit(struct radeon_device *rdev,
> RADEON_WAIT_HOST_IDLECLEAN |
> RADEON_WAIT_DMA_GUI_IDLE);
>   if (fence) {
> - r = radeon_fence_emit(rdev, fence);
> + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
>   }
>   radeon_ring_unlock_commit(rdev, ring);
>   return r;
> diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
> index a26144d..f088925 100644
> --- a/drivers/gpu/drm/radeon/r200.c
> +++ b/drivers/gpu/drm/radeon/r200.c
> @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev,
> uint64_t src_offset,
> uint64_t dst_offset,
> unsigned num_gpu_pages,
> -   struct radeon_fence *fence)
> +   struct radeon_fence **fence)
>  {
>   struct radeon_ring *ring = >ring[RADEON_RING_TYPE_GFX_INDEX];
>   uint32_t size;
> @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev,
>   radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
>   radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
>   if (fence) {
> - r = radeon_fence_emit(rdev, fence);
> + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
>   }
>   radeon_ring_unlock_commit(rdev, ring);
>   return r;
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index f388a1d..e5279f9 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -2369,7 +2369,7 @@ int r600_copy_blit(struct radeon_device *rdev,
>  uint64_t src_offset,
>  uint64_t dst_offset,
>  unsigned num_gpu_pages,
> -struct radeon_fence *fence)
> +struct radeon_fence **fence)
>  {
>   struct radeon_sa_bo *vb = NULL;
>   int r;
> @@ -2670,7 +2670,7 @@ void r600_fini(struct radeon_device *rdev)
>   */
>  void 

[PATCH 07/10] drm/radeon: apply Murphy's law to the kms irq code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 11:35:15AM -0400, Alex Deucher wrote:
> On Thu, May 24, 2012 at 3:49 AM, Christian K?nig
>  wrote:
> > From: Christian Koenig 
> >
> > 1. It is really dangerous to have more than one
> > ? spinlock protecting the same information.
> >
> > 2. radeon_irq_set sometimes wasn't called with lock
> > ? protection, so it can happen that more than one
> > ? CPU would tamper with the irq regs at the same
> > ? time.
> >
> > 3. The pm.gui_idle variable was assuming that the 3D
> > ? engine wasn't becoming idle between testing the
> > ? register and setting the variable. So just remove
> > ? it and test the register directly.
> >
> > Signed-off-by: Christian Koenig 
> > ---
> > ?drivers/gpu/drm/radeon/evergreen.c ? ? ?| ? ?1 -
> > ?drivers/gpu/drm/radeon/r100.c ? ? ? ? ? | ? ?1 -
> > ?drivers/gpu/drm/radeon/r600.c ? ? ? ? ? | ? ?1 -
> > ?drivers/gpu/drm/radeon/r600_hdmi.c ? ? ?| ? ?6 +--
> > ?drivers/gpu/drm/radeon/radeon.h ? ? ? ? | ? 33 +++---
> > ?drivers/gpu/drm/radeon/radeon_irq_kms.c | ? 72 
> > +--
> > ?drivers/gpu/drm/radeon/radeon_kms.c ? ? | ? 12 --
> > ?drivers/gpu/drm/radeon/radeon_pm.c ? ? ?| ? 12 +-
> > ?drivers/gpu/drm/radeon/rs600.c ? ? ? ? ?| ? ?1 -
> > ?drivers/gpu/drm/radeon/si.c ? ? ? ? ? ? | ? ?1 -
> > ?10 files changed, 90 insertions(+), 50 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/radeon/evergreen.c 
> > b/drivers/gpu/drm/radeon/evergreen.c
> > index bfcb39e..9e9b3bb 100644
> > --- a/drivers/gpu/drm/radeon/evergreen.c
> > +++ b/drivers/gpu/drm/radeon/evergreen.c
> > @@ -3254,7 +3254,6 @@ restart_ih:
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> > ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?default:
> > diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> > index 415b7d8..2587426 100644
> > --- a/drivers/gpu/drm/radeon/r100.c
> > +++ b/drivers/gpu/drm/radeon/r100.c
> > @@ -782,7 +782,6 @@ int r100_irq_process(struct radeon_device *rdev)
> > ? ? ? ? ? ? ? ?/* gui idle interrupt */
> > ? ? ? ? ? ? ? ?if (status & RADEON_GUI_IDLE_STAT) {
> > ? ? ? ? ? ? ? ? ? ? ? ?rdev->irq.gui_idle_acked = true;
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ?}
> > ? ? ? ? ? ? ? ?/* Vertical blank interrupts */
> > diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> > index eadbb06..90c6639 100644
> > --- a/drivers/gpu/drm/radeon/r600.c
> > +++ b/drivers/gpu/drm/radeon/r600.c
> > @@ -3542,7 +3542,6 @@ restart_ih:
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?case 233: /* GUI IDLE */
> > ? ? ? ? ? ? ? ? ? ? ? ?DRM_DEBUG("IH: GUI idle\n");
> > - ? ? ? ? ? ? ? ? ? ? ? rdev->pm.gui_idle = true;
> > ? ? ? ? ? ? ? ? ? ? ? ?wake_up(>irq.idle_queue);
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?default:
> > diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c 
> > b/drivers/gpu/drm/radeon/r600_hdmi.c
> > index 226379e..b76c0f2 100644
> > --- a/drivers/gpu/drm/radeon/r600_hdmi.c
> > +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
> > @@ -523,8 +523,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
> >
> > ? ? ? ?if (rdev->irq.installed) {
> > ? ? ? ? ? ? ? ?/* if irq is available use it */
> > - ? ? ? ? ? ? ? rdev->irq.afmt[dig->afmt->id] = true;
> > - ? ? ? ? ? ? ? radeon_irq_set(rdev);
> > + ? ? ? ? ? ? ? radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
> > ? ? ? ?}
> >
> > ? ? ? ?dig->afmt->enabled = true;
> > @@ -560,8 +559,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
> > ? ? ? ? ? ? ? ? ?offset, radeon_encoder->encoder_id);
> >
> > ? ? ? ?/* disable irq */
> > - ? ? ? rdev->irq.afmt[dig->afmt->id] = false;
> > - ? ? ? radeon_irq_set(rdev);
> > + ? ? ? radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
> >
> > ? ? ? ?/* Older chipsets not handled by AtomBIOS */
> > ? ? ? ?if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
> > diff --git a/drivers/gpu/drm/radeon/radeon.h 
> > b/drivers/gpu/drm/radeon/radeon.h
> > index 8479096..23552b4 100644
> > --- a/drivers/gpu/drm/radeon/radeon.h
> > +++ b/drivers/gpu/drm/radeon/radeon.h
> > @@ -610,21 +610,20 @@ union radeon_irq_stat_regs {
> > ?#define RADEON_MAX_AFMT_BLOCKS 6
> >
> > ?struct radeon_irq {
> > - ? ? ? bool ? ? ? ? ? ?installed;
> > - ? ? ? bool ? ? ? ? ? ?sw_int[RADEON_NUM_RINGS];
> > - ? ? ? bool ? ? ? ? ? ?crtc_vblank_int[RADEON_MAX_CRTCS];
> > - ? ? ? bool ? ? ? ? ? ?pflip[RADEON_MAX_CRTCS];
> > - ? ? ? wait_queue_head_t ? ? ? vblank_queue;
> > - ? ? ? bool ? ? ? ? ? ?hpd[RADEON_MAX_HPD_PINS];
> > - ? ? ? bool ? ? ? ? ? ?gui_idle;
> > - ? ? ? bool ? ? ? ? ? ?gui_idle_acked;
> > - ? ? ? wait_queue_head_t ? ? ? idle_queue;
> > - ? ? ? bool ? ? ? ? ? ?afmt[RADEON_MAX_AFMT_BLOCKS];
> > - ? ? ? spinlock_t sw_lock;
> > - ? ? ? int 

Re: [PATCH 07/10] drm/radeon: apply Murphy's law to the kms irq code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 11:35:15AM -0400, Alex Deucher wrote:
 On Thu, May 24, 2012 at 3:49 AM, Christian König
 deathsim...@vodafone.de wrote:
  From: Christian Koenig christian.koe...@amd.com
 
  1. It is really dangerous to have more than one
    spinlock protecting the same information.
 
  2. radeon_irq_set sometimes wasn't called with lock
    protection, so it can happen that more than one
    CPU would tamper with the irq regs at the same
    time.
 
  3. The pm.gui_idle variable was assuming that the 3D
    engine wasn't becoming idle between testing the
    register and setting the variable. So just remove
    it and test the register directly.
 
  Signed-off-by: Christian Koenig christian.koe...@amd.com
  ---
   drivers/gpu/drm/radeon/evergreen.c      |    1 -
   drivers/gpu/drm/radeon/r100.c           |    1 -
   drivers/gpu/drm/radeon/r600.c           |    1 -
   drivers/gpu/drm/radeon/r600_hdmi.c      |    6 +--
   drivers/gpu/drm/radeon/radeon.h         |   33 +++---
   drivers/gpu/drm/radeon/radeon_irq_kms.c |   72 
  +--
   drivers/gpu/drm/radeon/radeon_kms.c     |   12 --
   drivers/gpu/drm/radeon/radeon_pm.c      |   12 +-
   drivers/gpu/drm/radeon/rs600.c          |    1 -
   drivers/gpu/drm/radeon/si.c             |    1 -
   10 files changed, 90 insertions(+), 50 deletions(-)
 
  diff --git a/drivers/gpu/drm/radeon/evergreen.c 
  b/drivers/gpu/drm/radeon/evergreen.c
  index bfcb39e..9e9b3bb 100644
  --- a/drivers/gpu/drm/radeon/evergreen.c
  +++ b/drivers/gpu/drm/radeon/evergreen.c
  @@ -3254,7 +3254,6 @@ restart_ih:
                         break;
                 case 233: /* GUI IDLE */
                         DRM_DEBUG(IH: GUI idle\n);
  -                       rdev-pm.gui_idle = true;
                         wake_up(rdev-irq.idle_queue);
                         break;
                 default:
  diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
  index 415b7d8..2587426 100644
  --- a/drivers/gpu/drm/radeon/r100.c
  +++ b/drivers/gpu/drm/radeon/r100.c
  @@ -782,7 +782,6 @@ int r100_irq_process(struct radeon_device *rdev)
                 /* gui idle interrupt */
                 if (status  RADEON_GUI_IDLE_STAT) {
                         rdev-irq.gui_idle_acked = true;
  -                       rdev-pm.gui_idle = true;
                         wake_up(rdev-irq.idle_queue);
                 }
                 /* Vertical blank interrupts */
  diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
  index eadbb06..90c6639 100644
  --- a/drivers/gpu/drm/radeon/r600.c
  +++ b/drivers/gpu/drm/radeon/r600.c
  @@ -3542,7 +3542,6 @@ restart_ih:
                         break;
                 case 233: /* GUI IDLE */
                         DRM_DEBUG(IH: GUI idle\n);
  -                       rdev-pm.gui_idle = true;
                         wake_up(rdev-irq.idle_queue);
                         break;
                 default:
  diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c 
  b/drivers/gpu/drm/radeon/r600_hdmi.c
  index 226379e..b76c0f2 100644
  --- a/drivers/gpu/drm/radeon/r600_hdmi.c
  +++ b/drivers/gpu/drm/radeon/r600_hdmi.c
  @@ -523,8 +523,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
 
         if (rdev-irq.installed) {
                 /* if irq is available use it */
  -               rdev-irq.afmt[dig-afmt-id] = true;
  -               radeon_irq_set(rdev);
  +               radeon_irq_kms_enable_afmt(rdev, dig-afmt-id);
         }
 
         dig-afmt-enabled = true;
  @@ -560,8 +559,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
                   offset, radeon_encoder-encoder_id);
 
         /* disable irq */
  -       rdev-irq.afmt[dig-afmt-id] = false;
  -       radeon_irq_set(rdev);
  +       radeon_irq_kms_disable_afmt(rdev, dig-afmt-id);
 
         /* Older chipsets not handled by AtomBIOS */
         if (rdev-family = CHIP_R600  !ASIC_IS_DCE3(rdev)) {
  diff --git a/drivers/gpu/drm/radeon/radeon.h 
  b/drivers/gpu/drm/radeon/radeon.h
  index 8479096..23552b4 100644
  --- a/drivers/gpu/drm/radeon/radeon.h
  +++ b/drivers/gpu/drm/radeon/radeon.h
  @@ -610,21 +610,20 @@ union radeon_irq_stat_regs {
   #define RADEON_MAX_AFMT_BLOCKS 6
 
   struct radeon_irq {
  -       bool            installed;
  -       bool            sw_int[RADEON_NUM_RINGS];
  -       bool            crtc_vblank_int[RADEON_MAX_CRTCS];
  -       bool            pflip[RADEON_MAX_CRTCS];
  -       wait_queue_head_t       vblank_queue;
  -       bool            hpd[RADEON_MAX_HPD_PINS];
  -       bool            gui_idle;
  -       bool            gui_idle_acked;
  -       wait_queue_head_t       idle_queue;
  -       bool            afmt[RADEON_MAX_AFMT_BLOCKS];
  -       spinlock_t sw_lock;
  -       int sw_refcount[RADEON_NUM_RINGS];
  -       union radeon_irq_stat_regs stat_regs;
  -       spinlock_t pflip_lock[RADEON_MAX_CRTCS];
  -       int pflip_refcount[RADEON_MAX_CRTCS];
  +       

Re: [PATCH 01/10] drm/radeon: remove radeon_fence_create

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:05AM +0200, Christian König wrote:
 It is completely unnecessary to create fences
 before they are emitted, so remove it and a bunch
 of checks if fences are emitted or not.
 
 Signed-off-by: Christian König deathsim...@vodafone.de

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/evergreen.c|2 +-
  drivers/gpu/drm/radeon/ni.c   |2 +-
  drivers/gpu/drm/radeon/r100.c |4 +-
  drivers/gpu/drm/radeon/r200.c |4 +-
  drivers/gpu/drm/radeon/r600.c |4 +-
  drivers/gpu/drm/radeon/r600_blit_kms.c|6 +--
  drivers/gpu/drm/radeon/radeon.h   |   11 +++--
  drivers/gpu/drm/radeon/radeon_asic.h  |8 ++--
  drivers/gpu/drm/radeon/radeon_benchmark.c |   10 +
  drivers/gpu/drm/radeon/radeon_fence.c |   42 ++
  drivers/gpu/drm/radeon/radeon_ring.c  |   19 +
  drivers/gpu/drm/radeon/radeon_sa.c|2 +-
  drivers/gpu/drm/radeon/radeon_test.c  |   66 
 -
  drivers/gpu/drm/radeon/radeon_ttm.c   |   30 +
  drivers/gpu/drm/radeon/si.c   |6 +--
  15 files changed, 86 insertions(+), 130 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/evergreen.c 
 b/drivers/gpu/drm/radeon/evergreen.c
 index 58991af..dd3cea4 100644
 --- a/drivers/gpu/drm/radeon/evergreen.c
 +++ b/drivers/gpu/drm/radeon/evergreen.c
 @@ -1366,7 +1366,7 @@ void evergreen_mc_program(struct radeon_device *rdev)
   */
  void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib 
 *ib)
  {
 - struct radeon_ring *ring = rdev-ring[ib-fence-ring];
 + struct radeon_ring *ring = rdev-ring[ib-ring];
  
   /* set to DX10/11 mode */
   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
 index b01c2dd..9d9f5ac 100644
 --- a/drivers/gpu/drm/radeon/ni.c
 +++ b/drivers/gpu/drm/radeon/ni.c
 @@ -1127,7 +1127,7 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
  
  void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
  {
 - struct radeon_ring *ring = rdev-ring[ib-fence-ring];
 + struct radeon_ring *ring = rdev-ring[ib-ring];
  
   /* set to DX10/11 mode */
   radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
 index fb44e7e..415b7d8 100644
 --- a/drivers/gpu/drm/radeon/r100.c
 +++ b/drivers/gpu/drm/radeon/r100.c
 @@ -883,7 +883,7 @@ int r100_copy_blit(struct radeon_device *rdev,
  uint64_t src_offset,
  uint64_t dst_offset,
  unsigned num_gpu_pages,
 -struct radeon_fence *fence)
 +struct radeon_fence **fence)
  {
   struct radeon_ring *ring = rdev-ring[RADEON_RING_TYPE_GFX_INDEX];
   uint32_t cur_pages;
 @@ -947,7 +947,7 @@ int r100_copy_blit(struct radeon_device *rdev,
 RADEON_WAIT_HOST_IDLECLEAN |
 RADEON_WAIT_DMA_GUI_IDLE);
   if (fence) {
 - r = radeon_fence_emit(rdev, fence);
 + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
   }
   radeon_ring_unlock_commit(rdev, ring);
   return r;
 diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
 index a26144d..f088925 100644
 --- a/drivers/gpu/drm/radeon/r200.c
 +++ b/drivers/gpu/drm/radeon/r200.c
 @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev,
 uint64_t src_offset,
 uint64_t dst_offset,
 unsigned num_gpu_pages,
 -   struct radeon_fence *fence)
 +   struct radeon_fence **fence)
  {
   struct radeon_ring *ring = rdev-ring[RADEON_RING_TYPE_GFX_INDEX];
   uint32_t size;
 @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev,
   radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
   radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
   if (fence) {
 - r = radeon_fence_emit(rdev, fence);
 + r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
   }
   radeon_ring_unlock_commit(rdev, ring);
   return r;
 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
 index f388a1d..e5279f9 100644
 --- a/drivers/gpu/drm/radeon/r600.c
 +++ b/drivers/gpu/drm/radeon/r600.c
 @@ -2369,7 +2369,7 @@ int r600_copy_blit(struct radeon_device *rdev,
  uint64_t src_offset,
  uint64_t dst_offset,
  unsigned num_gpu_pages,
 -struct radeon_fence *fence)
 +struct radeon_fence **fence)
  {
   struct radeon_sa_bo *vb = NULL;
   int r;
 @@ -2670,7 +2670,7 @@ void r600_fini(struct radeon_device *rdev)
   */
  void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
  

Re: [PATCH 02/10] drm/radeon: add infrastructure for advanced ring synchronization

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:06AM +0200, Christian König wrote:
 Signed-off-by: Christian König deathsim...@vodafone.de

Need a small improvement see below, otherwise

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/radeon.h   |   23 ++-
  drivers/gpu/drm/radeon/radeon_fence.c |   73 
 +
  2 files changed, 85 insertions(+), 11 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
 index 5e259b4..4e232c3 100644
 --- a/drivers/gpu/drm/radeon/radeon.h
 +++ b/drivers/gpu/drm/radeon/radeon.h
 @@ -257,8 +257,8 @@ struct radeon_fence_driver {
   uint32_tscratch_reg;
   uint64_tgpu_addr;
   volatile uint32_t   *cpu_addr;
 - /* seq is protected by ring emission lock */
 - uint64_tseq;
 + /* sync_seq is protected by ring emission lock */
 + uint64_tsync_seq[RADEON_NUM_RINGS];
   atomic64_t  last_seq;
   unsigned long   last_activity;
   boolinitialized;
 @@ -288,6 +288,25 @@ int radeon_fence_wait_any(struct radeon_device *rdev,
  struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
  void radeon_fence_unref(struct radeon_fence **fence);
  unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
 +bool radeon_fence_need_sync(struct radeon_fence *fence, int ring);
 +void radeon_fence_note_sync(struct radeon_fence *fence, int ring);
 +static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a,
 +   struct radeon_fence *b)
 +{
 + if (!a) {
 + return b;
 + }
 +
 + if (!b) {
 + return a;
 + }

Please add :
BUG_ON(a-ring != b-ring);

So we can catch if someone badly use this function.

 +
 + if (a-seq  b-seq) {
 + return a;
 + } else {
 + return b;
 + }
 +}
  
  /*
   * Tiling registers
 diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
 b/drivers/gpu/drm/radeon/radeon_fence.c
 index 401d346..7b55625 100644
 --- a/drivers/gpu/drm/radeon/radeon_fence.c
 +++ b/drivers/gpu/drm/radeon/radeon_fence.c
 @@ -72,7 +72,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
   }
   kref_init(((*fence)-kref));
   (*fence)-rdev = rdev;
 - (*fence)-seq = ++rdev-fence_drv[ring].seq;
 + (*fence)-seq = ++rdev-fence_drv[ring].sync_seq[ring];
   (*fence)-ring = ring;
   radeon_fence_ring_emit(rdev, ring, *fence);
   trace_radeon_fence_emit(rdev-ddev, (*fence)-seq);
 @@ -449,7 +449,7 @@ int radeon_fence_wait_next_locked(struct radeon_device 
 *rdev, int ring)
* wait.
*/
   seq = atomic64_read(rdev-fence_drv[ring].last_seq) + 1ULL;
 - if (seq = rdev-fence_drv[ring].seq) {
 + if (seq = rdev-fence_drv[ring].sync_seq[ring]) {
   /* nothing to wait for, last_seq is
  already the last emited fence */
   return -ENOENT;
 @@ -464,7 +464,7 @@ int radeon_fence_wait_empty_locked(struct radeon_device 
 *rdev, int ring)
* activity can be scheduled so there won't be concurrent access
* to seq value.
*/
 - return radeon_fence_wait_seq(rdev, rdev-fence_drv[ring].seq,
 + return radeon_fence_wait_seq(rdev, rdev-fence_drv[ring].sync_seq[ring],
ring, false, false);
  }
  
 @@ -492,7 +492,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
 *rdev, int ring)
* but it's ok to report slightly wrong fence count here.
*/
   radeon_fence_process(rdev, ring);
 - emitted = rdev-fence_drv[ring].seq - 
 atomic64_read(rdev-fence_drv[ring].last_seq);
 + emitted = rdev-fence_drv[ring].sync_seq[ring]
 + - atomic64_read(rdev-fence_drv[ring].last_seq);
   /* to avoid 32bits warp around */
   if (emitted  0x1000) {
   emitted = 0x1000;
 @@ -500,6 +501,51 @@ unsigned radeon_fence_count_emitted(struct radeon_device 
 *rdev, int ring)
   return (unsigned)emitted;
  }
  
 +bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
 +{
 + struct radeon_fence_driver *fdrv;
 +
 + if (!fence) {
 + return false;
 + }
 +
 + if (fence-ring == dst_ring) {
 + return false;
 + }
 +
 + /* we are protected by the ring mutex */
 + fdrv = fence-rdev-fence_drv[dst_ring];
 + if (fence-seq = fdrv-sync_seq[fence-ring]) {
 + return false;
 + }
 +
 + return true;
 +}
 +
 +void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
 +{
 + struct radeon_fence_driver *dst, *src;
 + unsigned i;
 +
 + if (!fence) {
 + return;
 + }
 +
 + if (fence-ring == dst_ring) {
 + return;
 + }
 +
 + /* we are protected by the ring 

Re: [PATCH 03/10] drm/radeon: rework ring syncing code

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:07AM +0200, Christian König wrote:
 Move inter ring syncing with semaphores into the
 existing ring allocations, with that we need to
 lock the ring mutex only once.
 
 Signed-off-by: Christian König deathsim...@vodafone.de

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/evergreen_blit_kms.c |3 +-
  drivers/gpu/drm/radeon/r600.c   |5 +-
  drivers/gpu/drm/radeon/r600_blit_kms.c  |   24 +++--
  drivers/gpu/drm/radeon/radeon.h |6 +--
  drivers/gpu/drm/radeon/radeon_asic.h|5 +-
  drivers/gpu/drm/radeon/radeon_cs.c  |   38 +++---
  drivers/gpu/drm/radeon/radeon_ring.c|   30 +--
  drivers/gpu/drm/radeon/radeon_semaphore.c   |   71 
 ++-
  drivers/gpu/drm/radeon/radeon_test.c|6 +--
  drivers/gpu/drm/radeon/radeon_ttm.c |   20 
  10 files changed, 92 insertions(+), 116 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c 
 b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
 index 1e96bd4..e512560 100644
 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c
 +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
 @@ -622,7 +622,8 @@ int evergreen_blit_init(struct radeon_device *rdev)
   rdev-r600_blit.primitives.draw_auto = draw_auto;
   rdev-r600_blit.primitives.set_default_state = set_default_state;
  
 - rdev-r600_blit.ring_size_common = 55; /* shaders + def state */
 + rdev-r600_blit.ring_size_common = 8; /* sync semaphore */
 + rdev-r600_blit.ring_size_common += 55; /* shaders + def state */
   rdev-r600_blit.ring_size_common += 16; /* fence emit for VB IB */
   rdev-r600_blit.ring_size_common += 5; /* done copy */
   rdev-r600_blit.ring_size_common += 16; /* fence emit for done copy */
 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
 index e5279f9..a8d8c44 100644
 --- a/drivers/gpu/drm/radeon/r600.c
 +++ b/drivers/gpu/drm/radeon/r600.c
 @@ -2371,15 +2371,16 @@ int r600_copy_blit(struct radeon_device *rdev,
  unsigned num_gpu_pages,
  struct radeon_fence **fence)
  {
 + struct radeon_semaphore *sem = NULL;
   struct radeon_sa_bo *vb = NULL;
   int r;
  
 - r = r600_blit_prepare_copy(rdev, num_gpu_pages, vb);
 + r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, vb, sem);
   if (r) {
   return r;
   }
   r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb);
 - r600_blit_done_copy(rdev, fence, vb);
 + r600_blit_done_copy(rdev, fence, vb, sem);
   return 0;
  }
  
 diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c 
 b/drivers/gpu/drm/radeon/r600_blit_kms.c
 index 02f4eeb..2b8d641 100644
 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c
 +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
 @@ -512,7 +512,8 @@ int r600_blit_init(struct radeon_device *rdev)
   rdev-r600_blit.primitives.draw_auto = draw_auto;
   rdev-r600_blit.primitives.set_default_state = set_default_state;
  
 - rdev-r600_blit.ring_size_common = 40; /* shaders + def state */
 + rdev-r600_blit.ring_size_common = 8; /* sync semaphore */
 + rdev-r600_blit.ring_size_common += 40; /* shaders + def state */
   rdev-r600_blit.ring_size_common += 5; /* done copy */
   rdev-r600_blit.ring_size_common += 16; /* fence emit for done copy */
  
 @@ -666,7 +667,8 @@ static unsigned r600_blit_create_rect(unsigned 
 num_gpu_pages,
  
  
  int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned 
 num_gpu_pages,
 -struct radeon_sa_bo **vb)
 +struct radeon_fence **fence, struct radeon_sa_bo 
 **vb,
 +struct radeon_semaphore **sem)
  {
   struct radeon_ring *ring = rdev-ring[RADEON_RING_TYPE_GFX_INDEX];
   int r;
 @@ -689,22 +691,37 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, 
 unsigned num_gpu_pages,
   return r;
   }
  
 + r = radeon_semaphore_create(rdev, sem);
 + if (r) {
 + radeon_sa_bo_free(rdev, vb, NULL);
 + return r;
 + }
 +
   /* calculate number of loops correctly */
   ring_size = num_loops * dwords_per_loop;
   ring_size += rdev-r600_blit.ring_size_common;
   r = radeon_ring_lock(rdev, ring, ring_size);
   if (r) {
   radeon_sa_bo_free(rdev, vb, NULL);
 + radeon_semaphore_free(rdev, sem, NULL);
   return r;
   }
  
 + if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) {
 + radeon_semaphore_sync_rings(rdev, *sem, (*fence)-ring,
 + RADEON_RING_TYPE_GFX_INDEX);
 + radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX);
 + } else {
 + radeon_semaphore_free(rdev, sem, NULL);
 + }
 +
   rdev-r600_blit.primitives.set_default_state(rdev);
   

Re: [PATCH 04/10] drm/radeon: replace vmram_mutex with mclk_lock v2

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:08AM +0200, Christian König wrote:
 It is a rw_semaphore now and only write locked
 while changing the clock. Also the lock is renamed
 to better reflect what it is protecting.
 
 v2: Keep the ttm_vm_ops on IGPs
 
 Signed-off-by: Christian König deathsim...@vodafone.de

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/radeon.h|3 ++-
  drivers/gpu/drm/radeon/radeon_device.c |2 +-
  drivers/gpu/drm/radeon/radeon_object.c |8 
  drivers/gpu/drm/radeon/radeon_pm.c |4 ++--
  drivers/gpu/drm/radeon/radeon_ttm.c|4 ++--
  5 files changed, 11 insertions(+), 10 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
 index aebaf28..3e83480 100644
 --- a/drivers/gpu/drm/radeon/radeon.h
 +++ b/drivers/gpu/drm/radeon/radeon.h
 @@ -1055,6 +1055,8 @@ struct radeon_power_state {
  
  struct radeon_pm {
   struct mutexmutex;
 + /* write locked while reprogramming mclk */
 + struct rw_semaphore mclk_lock;
   u32 active_crtcs;
   int active_crtc_count;
   int req_vblank;
 @@ -1551,7 +1553,6 @@ struct radeon_device {
   struct work_struct audio_work;
   int num_crtc; /* number of crtcs */
   struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
 - struct mutex vram_mutex;
   bool audio_enabled;
   struct r600_audio audio_status; /* audio stuff */
   struct notifier_block acpi_nb;
 diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
 b/drivers/gpu/drm/radeon/radeon_device.c
 index 066c98b..7667184 100644
 --- a/drivers/gpu/drm/radeon/radeon_device.c
 +++ b/drivers/gpu/drm/radeon/radeon_device.c
 @@ -735,7 +735,7 @@ int radeon_device_init(struct radeon_device *rdev,
   spin_lock_init(rdev-ih.lock);
   mutex_init(rdev-gem.mutex);
   mutex_init(rdev-pm.mutex);
 - mutex_init(rdev-vram_mutex);
 + init_rwsem(rdev-pm.mclk_lock);
   init_waitqueue_head(rdev-irq.vblank_queue);
   init_waitqueue_head(rdev-irq.idle_queue);
   r = radeon_gem_init(rdev);
 diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
 b/drivers/gpu/drm/radeon/radeon_object.c
 index 830f1a7..6ecb200 100644
 --- a/drivers/gpu/drm/radeon/radeon_object.c
 +++ b/drivers/gpu/drm/radeon/radeon_object.c
 @@ -154,11 +154,11 @@ retry:
   INIT_LIST_HEAD(bo-va);
   radeon_ttm_placement_from_domain(bo, domain);
   /* Kernel allocation are uninterruptible */
 - mutex_lock(rdev-vram_mutex);
 + down_read(rdev-pm.mclk_lock);
   r = ttm_bo_init(rdev-mman.bdev, bo-tbo, size, type,
   bo-placement, page_align, 0, !kernel, NULL,
   acc_size, sg, radeon_ttm_bo_destroy);
 - mutex_unlock(rdev-vram_mutex);
 + up_read(rdev-pm.mclk_lock);
   if (unlikely(r != 0)) {
   if (r != -ERESTARTSYS) {
   if (domain == RADEON_GEM_DOMAIN_VRAM) {
 @@ -219,9 +219,9 @@ void radeon_bo_unref(struct radeon_bo **bo)
   return;
   rdev = (*bo)-rdev;
   tbo = ((*bo)-tbo);
 - mutex_lock(rdev-vram_mutex);
 + down_read(rdev-pm.mclk_lock);
   ttm_bo_unref(tbo);
 - mutex_unlock(rdev-vram_mutex);
 + up_read(rdev-pm.mclk_lock);
   if (tbo == NULL)
   *bo = NULL;
  }
 diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
 b/drivers/gpu/drm/radeon/radeon_pm.c
 index 0882554..d13b6ae 100644
 --- a/drivers/gpu/drm/radeon/radeon_pm.c
 +++ b/drivers/gpu/drm/radeon/radeon_pm.c
 @@ -251,7 +251,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
 *rdev)
   return;
  
   mutex_lock(rdev-ddev-struct_mutex);
 - mutex_lock(rdev-vram_mutex);
 + down_write(rdev-pm.mclk_lock);
   mutex_lock(rdev-ring_lock);
  
   /* gui idle int has issues on older chips it seems */
 @@ -303,7 +303,7 @@ static void radeon_pm_set_clocks(struct radeon_device 
 *rdev)
   rdev-pm.dynpm_planned_action = DYNPM_ACTION_NONE;
  
   mutex_unlock(rdev-ring_lock);
 - mutex_unlock(rdev-vram_mutex);
 + up_write(rdev-pm.mclk_lock);
   mutex_unlock(rdev-ddev-struct_mutex);
  }
  
 diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
 b/drivers/gpu/drm/radeon/radeon_ttm.c
 index c43035c..0881131 100644
 --- a/drivers/gpu/drm/radeon/radeon_ttm.c
 +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
 @@ -797,9 +797,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, 
 struct vm_fault *vmf)
   return VM_FAULT_NOPAGE;
   }
   rdev = radeon_get_rdev(bo-bdev);
 - mutex_lock(rdev-vram_mutex);
 + down_read(rdev-pm.mclk_lock);
   r = ttm_vm_ops-fault(vma, vmf);
 - mutex_unlock(rdev-vram_mutex);
 + up_read(rdev-pm.mclk_lock);
   return r;
  }
  
 -- 
 1.7.9.5
 
 ___
 dri-devel mailing list
 dri-devel@lists.freedesktop.org
 

Re: [PATCH 05/10] drm/radeon: remove some unneeded structure members

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:09AM +0200, Christian König wrote:
 From: Christian Koenig christian.koe...@amd.com
 
 Signed-off-by: Christian Koenig christian.koe...@amd.com

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/radeon.h |2 --
  1 file changed, 2 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
 index 3e83480..618df9a 100644
 --- a/drivers/gpu/drm/radeon/radeon.h
 +++ b/drivers/gpu/drm/radeon/radeon.h
 @@ -733,9 +733,7 @@ struct r600_ih {
   struct radeon_bo*ring_obj;
   volatile uint32_t   *ring;
   unsignedrptr;
 - unsignedrptr_offs;
   unsignedwptr;
 - unsignedwptr_old;
   unsignedring_size;
   uint64_tgpu_addr;
   uint32_tptr_mask;
 -- 
 1.7.9.5
 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 06/10] drm/radeon: fix improve ih ring handling

2012-05-24 Thread j.glisse
On Thu, May 24, 2012 at 09:49:10AM +0200, Christian König wrote:
 From: Christian Koenig christian.koe...@amd.com
 
 The spinlock was actually there to protect the
 rptr, but rptr was read outside of the locked area.
 
 Also we don't really need a spinlock here, an
 atomic should to quite fine since we only need to
 prevent it from being reentrant.
 
 Signed-off-by: Christian Koenig christian.koe...@amd.com

Reviewed-by: Jerome Glisse jgli...@redhat.com

 ---
  drivers/gpu/drm/radeon/evergreen.c |   29 -
  drivers/gpu/drm/radeon/r600.c  |   30 +++---
  drivers/gpu/drm/radeon/radeon.h|3 +--
  drivers/gpu/drm/radeon/radeon_device.c |3 +--
  drivers/gpu/drm/radeon/si.c|   30 --
  5 files changed, 49 insertions(+), 46 deletions(-)
 
 diff --git a/drivers/gpu/drm/radeon/evergreen.c 
 b/drivers/gpu/drm/radeon/evergreen.c
 index dd3cea4..bfcb39e 100644
 --- a/drivers/gpu/drm/radeon/evergreen.c
 +++ b/drivers/gpu/drm/radeon/evergreen.c
 @@ -2943,7 +2943,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
   u32 rptr;
   u32 src_id, src_data;
   u32 ring_index;
 - unsigned long flags;
   bool queue_hotplug = false;
   bool queue_hdmi = false;
  
 @@ -2951,22 +2950,24 @@ int evergreen_irq_process(struct radeon_device *rdev)
   return IRQ_NONE;
  
   wptr = evergreen_get_ih_wptr(rdev);
 +
 +restart_ih:
 + /* is somebody else already processing irqs? */
 + if (atomic_xchg(rdev-ih.lock, 1))
 + return IRQ_NONE;
 +
   rptr = rdev-ih.rptr;
 + if (rptr == wptr)
 + return IRQ_NONE;
 +
   DRM_DEBUG(r600_irq_process start: rptr %d, wptr %d\n, rptr, wptr);
  
 - spin_lock_irqsave(rdev-ih.lock, flags);
 - if (rptr == wptr) {
 - spin_unlock_irqrestore(rdev-ih.lock, flags);
 - return IRQ_NONE;
 - }
 -restart_ih:
   /* Order reading of wptr vs. reading of IH ring data */
   rmb();
  
   /* display interrupts */
   evergreen_irq_ack(rdev);
  
 - rdev-ih.wptr = wptr;
   while (rptr != wptr) {
   /* wptr/rptr are in bytes! */
   ring_index = rptr / 4;
 @@ -3265,17 +3266,19 @@ restart_ih:
   rptr += 16;
   rptr = rdev-ih.ptr_mask;
   }
 - /* make sure wptr hasn't changed while processing */
 - wptr = evergreen_get_ih_wptr(rdev);
 - if (wptr != rdev-ih.wptr)
 - goto restart_ih;
   if (queue_hotplug)
   schedule_work(rdev-hotplug_work);
   if (queue_hdmi)
   schedule_work(rdev-audio_work);
   rdev-ih.rptr = rptr;
   WREG32(IH_RB_RPTR, rdev-ih.rptr);
 - spin_unlock_irqrestore(rdev-ih.lock, flags);
 + atomic_set(rdev-ih.lock, 0);
 +
 + /* make sure wptr hasn't changed while processing */
 + wptr = evergreen_get_ih_wptr(rdev);
 + if (wptr != rptr)
 + goto restart_ih;
 +
   return IRQ_HANDLED;
  }
  
 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
 index a8d8c44..eadbb06 100644
 --- a/drivers/gpu/drm/radeon/r600.c
 +++ b/drivers/gpu/drm/radeon/r600.c
 @@ -2921,7 +2921,6 @@ void r600_disable_interrupts(struct radeon_device *rdev)
   WREG32(IH_RB_RPTR, 0);
   WREG32(IH_RB_WPTR, 0);
   rdev-ih.enabled = false;
 - rdev-ih.wptr = 0;
   rdev-ih.rptr = 0;
  }
  
 @@ -3373,7 +3372,6 @@ int r600_irq_process(struct radeon_device *rdev)
   u32 rptr;
   u32 src_id, src_data;
   u32 ring_index;
 - unsigned long flags;
   bool queue_hotplug = false;
   bool queue_hdmi = false;
  
 @@ -3385,24 +3383,24 @@ int r600_irq_process(struct radeon_device *rdev)
   RREG32(IH_RB_WPTR);
  
   wptr = r600_get_ih_wptr(rdev);
 - rptr = rdev-ih.rptr;
 - DRM_DEBUG(r600_irq_process start: rptr %d, wptr %d\n, rptr, wptr);
  
 - spin_lock_irqsave(rdev-ih.lock, flags);
 +restart_ih:
 + /* is somebody else already processing irqs? */
 + if (atomic_xchg(rdev-ih.lock, 1))
 + return IRQ_NONE;
  
 - if (rptr == wptr) {
 - spin_unlock_irqrestore(rdev-ih.lock, flags);
 + rptr = rdev-ih.rptr;
 + if (rptr == wptr)
   return IRQ_NONE;
 - }
  
 -restart_ih:
 + DRM_DEBUG(r600_irq_process start: rptr %d, wptr %d\n, rptr, wptr);
 +
   /* Order reading of wptr vs. reading of IH ring data */
   rmb();
  
   /* display interrupts */
   r600_irq_ack(rdev);
  
 - rdev-ih.wptr = wptr;
   while (rptr != wptr) {
   /* wptr/rptr are in bytes! */
   ring_index = rptr / 4;
 @@ -3556,17 +3554,19 @@ restart_ih:
   rptr += 16;
   rptr = rdev-ih.ptr_mask;
   }
 - /* make sure wptr hasn't changed while processing */
 - wptr = r600_get_ih_wptr(rdev);
 - if (wptr != rdev-ih.wptr)
 - goto restart_ih;
   if (queue_hotplug)