diff mbox

drivers/gpu/drm/ast: Fix infinite loop if read fails

Message ID 20161215051241.20815-1-ruscur@russell.cc (mailing list archive)
State New, archived
Headers show

Commit Message

Russell Currey Dec. 15, 2016, 5:12 a.m. UTC
ast_get_dram_info() configures a window in order to access BMC memory.
A BMC register can be configured to disallow this, and if so, causes
an infinite loop in the ast driver which renders the system unusable.

Fix this by erroring out if an error is detected.  On powerpc systems with
EEH, this leads to the device being fenced and the system continuing to
operate.

Cc: <stable@vger.kernel.org> # 3.10+
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
 drivers/gpu/drm/ast/ast_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Joel Stanley Dec. 16, 2016, 1:08 a.m. UTC | #1
On Thu, Dec 15, 2016 at 3:42 PM, Russell Currey <ruscur@russell.cc> wrote:
> ast_get_dram_info() configures a window in order to access BMC memory.
> A BMC register can be configured to disallow this, and if so, causes
> an infinite loop in the ast driver which renders the system unusable.
>
> Fix this by erroring out if an error is detected.  On powerpc systems with
> EEH, this leads to the device being fenced and the system continuing to
> operate.
>
> Cc: <stable@vger.kernel.org> # 3.10+
> Signed-off-by: Russell Currey <ruscur@russell.cc>

Reviewed-by: Joel Stanley <joel@jms.id.au>

Thanks Russel.

Cheers,

Joel


> ---
>  drivers/gpu/drm/ast/ast_main.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> index 904beaa..f75c642 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -223,7 +223,8 @@ static int ast_get_dram_info(struct drm_device *dev)
>         ast_write32(ast, 0x10000, 0xfc600309);
>
>         do {
> -               ;
> +               if (pci_channel_offline(dev->pdev))
> +                       return -EIO;
>         } while (ast_read32(ast, 0x10000) != 0x01);
>         data = ast_read32(ast, 0x10004);
>
> @@ -428,7 +429,9 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
>         ast_detect_chip(dev, &need_post);
>
>         if (ast->chip != AST1180) {
> -               ast_get_dram_info(dev);
> +               ret = ast_get_dram_info(dev);
> +               if (ret)
> +                       goto out_free;
>                 ast->vram_size = ast_get_vram_info(dev);
>                 DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
>         }
Daniel Vetter Dec. 18, 2016, 1:39 p.m. UTC | #2
On Fri, Dec 16, 2016 at 11:38:57AM +1030, Joel Stanley wrote:
> On Thu, Dec 15, 2016 at 3:42 PM, Russell Currey <ruscur@russell.cc> wrote:
> > ast_get_dram_info() configures a window in order to access BMC memory.
> > A BMC register can be configured to disallow this, and if so, causes
> > an infinite loop in the ast driver which renders the system unusable.
> >
> > Fix this by erroring out if an error is detected.  On powerpc systems with
> > EEH, this leads to the device being fenced and the system continuing to
> > operate.
> >
> > Cc: <stable@vger.kernel.org> # 3.10+
> > Signed-off-by: Russell Currey <ruscur@russell.cc>
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>

Applied to drm-misc-fixes.
-Daniel

> 
> Thanks Russel.
> 
> Cheers,
> 
> Joel
> 
> 
> > ---
> >  drivers/gpu/drm/ast/ast_main.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> > index 904beaa..f75c642 100644
> > --- a/drivers/gpu/drm/ast/ast_main.c
> > +++ b/drivers/gpu/drm/ast/ast_main.c
> > @@ -223,7 +223,8 @@ static int ast_get_dram_info(struct drm_device *dev)
> >         ast_write32(ast, 0x10000, 0xfc600309);
> >
> >         do {
> > -               ;
> > +               if (pci_channel_offline(dev->pdev))
> > +                       return -EIO;
> >         } while (ast_read32(ast, 0x10000) != 0x01);
> >         data = ast_read32(ast, 0x10004);
> >
> > @@ -428,7 +429,9 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
> >         ast_detect_chip(dev, &need_post);
> >
> >         if (ast->chip != AST1180) {
> > -               ast_get_dram_info(dev);
> > +               ret = ast_get_dram_info(dev);
> > +               if (ret)
> > +                       goto out_free;
> >                 ast->vram_size = ast_get_vram_info(dev);
> >                 DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
> >         }
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 904beaa..f75c642 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -223,7 +223,8 @@  static int ast_get_dram_info(struct drm_device *dev)
 	ast_write32(ast, 0x10000, 0xfc600309);
 
 	do {
-		;
+		if (pci_channel_offline(dev->pdev))
+			return -EIO;
 	} while (ast_read32(ast, 0x10000) != 0x01);
 	data = ast_read32(ast, 0x10004);
 
@@ -428,7 +429,9 @@  int ast_driver_load(struct drm_device *dev, unsigned long flags)
 	ast_detect_chip(dev, &need_post);
 
 	if (ast->chip != AST1180) {
-		ast_get_dram_info(dev);
+		ret = ast_get_dram_info(dev);
+		if (ret)
+			goto out_free;
 		ast->vram_size = ast_get_vram_info(dev);
 		DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
 	}