diff mbox

drm/nouveau: Ack interrupts for some fuc engines

Message ID 5150175D.3070808@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Maarten Lankhorst March 25, 2013, 9:22 a.m. UTC
Fixes 100% cpu usage when the exit interrupt never got acked.

Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
---

Comments

Marcin Ślusarz March 25, 2013, 6:14 p.m. UTC | #1
On Mon, Mar 25, 2013 at 10:22:37AM +0100, Maarten Lankhorst wrote:
> Fixes 100% cpu usage when the exit interrupt never got acked.
> 
> Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
> ---
> diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c
> index e05c157..b11c5f3 100644
> --- a/drivers/gpu/drm/nouveau/core/core/falcon.c
> +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c
> @@ -229,6 +229,24 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
>  	return nouveau_engine_fini(&falcon->base, suspend);
>  }
>  
> +void
> +nouveau_falcon_intr(struct nouveau_subdev *subdev)
> +{
> +	struct nouveau_falcon *falcon = (void*)subdev;
> +	u32 intr = nv_ro32(falcon, 0x008);
> +
> +	nv_wo32(falcon, 0x004, intr);
> +
> +	if (intr & 0x10) {
> +		intr &= ~0x10;
> +
> +		nv_info(falcon, "Exit interrupt called\n");

Do you really want to print it at "info" level? How frequent it is?

> +	}
> +
> +	if (intr)
> +		nv_error(falcon, "Unhandled interrupt %08x\n", intr);
> +}
> +
>  int
>  nouveau_falcon_create_(struct nouveau_object *parent,
>  		       struct nouveau_object *engine,
Maarten Lankhorst March 26, 2013, 6:29 a.m. UTC | #2
Op 25-03-13 19:14, Marcin Slusarz schreef:
> On Mon, Mar 25, 2013 at 10:22:37AM +0100, Maarten Lankhorst wrote:
>> Fixes 100% cpu usage when the exit interrupt never got acked.
>>
>> Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
>> ---
>> diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c
>> index e05c157..b11c5f3 100644
>> --- a/drivers/gpu/drm/nouveau/core/core/falcon.c
>> +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c
>> @@ -229,6 +229,24 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
>>  	return nouveau_engine_fini(&falcon->base, suspend);
>>  }
>>  
>> +void
>> +nouveau_falcon_intr(struct nouveau_subdev *subdev)
>> +{
>> +	struct nouveau_falcon *falcon = (void*)subdev;
>> +	u32 intr = nv_ro32(falcon, 0x008);
>> +
>> +	nv_wo32(falcon, 0x004, intr);
>> +
>> +	if (intr & 0x10) {
>> +		intr &= ~0x10;
>> +
>> +		nv_info(falcon, "Exit interrupt called\n");
> Do you really want to print it at "info" level? How frequent it is?
It shouldn't be often, I want it to run at the error level since that usually means the firmware exited prematurely/crashed and things go bad, but it happens with the secret scrubber finishing on initialization too. That one is harmless though.
>> +	}
>> +
>> +	if (intr)
>> +		nv_error(falcon, "Unhandled interrupt %08x\n", intr);
>> +}
>> +
>>  int
>>  nouveau_falcon_create_(struct nouveau_object *parent,
>>  		       struct nouveau_object *engine,
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
Marcin Ślusarz March 26, 2013, 8:29 p.m. UTC | #3
On Tue, Mar 26, 2013 at 07:29:24AM +0100, Maarten Lankhorst wrote:
> Op 25-03-13 19:14, Marcin Slusarz schreef:
> > On Mon, Mar 25, 2013 at 10:22:37AM +0100, Maarten Lankhorst wrote:
> >> Fixes 100% cpu usage when the exit interrupt never got acked.
> >>
> >> Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
> >> ---
> >> diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c
> >> index e05c157..b11c5f3 100644
> >> --- a/drivers/gpu/drm/nouveau/core/core/falcon.c
> >> +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c
> >> @@ -229,6 +229,24 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
> >>  	return nouveau_engine_fini(&falcon->base, suspend);
> >>  }
> >>  
> >> +void
> >> +nouveau_falcon_intr(struct nouveau_subdev *subdev)
> >> +{
> >> +	struct nouveau_falcon *falcon = (void*)subdev;
> >> +	u32 intr = nv_ro32(falcon, 0x008);
> >> +
> >> +	nv_wo32(falcon, 0x004, intr);
> >> +
> >> +	if (intr & 0x10) {
> >> +		intr &= ~0x10;
> >> +
> >> +		nv_info(falcon, "Exit interrupt called\n");
> > Do you really want to print it at "info" level? How frequent it is?
> It shouldn't be often, I want it to run at the error level since that usually
> means the firmware exited prematurely/crashed and things go bad, but it
> happens with the secret scrubber finishing on initialization too. That one
> is harmless though.

Maybe it should say:
nv_error(falcon, "firmware exited prematurely\n");
?

> >> +	}
> >> +
> >> +	if (intr)
> >> +		nv_error(falcon, "Unhandled interrupt %08x\n", intr);
> >> +}
> >> +
> >>  int
> >>  nouveau_falcon_create_(struct nouveau_object *parent,
> >>  		       struct nouveau_object *engine,
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/dri-devel
> >
>
Maarten Lankhorst March 27, 2013, 6:21 a.m. UTC | #4
Op 26-03-13 21:29, Marcin Slusarz schreef:
> On Tue, Mar 26, 2013 at 07:29:24AM +0100, Maarten Lankhorst wrote:
>> Op 25-03-13 19:14, Marcin Slusarz schreef:
>>> On Mon, Mar 25, 2013 at 10:22:37AM +0100, Maarten Lankhorst wrote:
>>>> Fixes 100% cpu usage when the exit interrupt never got acked.
>>>>
>>>> Signed-off-by: Maarten Lankhorst <m.b.lankhorst@gmail.com>
>>>> ---
>>>> diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c
>>>> index e05c157..b11c5f3 100644
>>>> --- a/drivers/gpu/drm/nouveau/core/core/falcon.c
>>>> +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c
>>>> @@ -229,6 +229,24 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
>>>>  	return nouveau_engine_fini(&falcon->base, suspend);
>>>>  }
>>>>  
>>>> +void
>>>> +nouveau_falcon_intr(struct nouveau_subdev *subdev)
>>>> +{
>>>> +	struct nouveau_falcon *falcon = (void*)subdev;
>>>> +	u32 intr = nv_ro32(falcon, 0x008);
>>>> +
>>>> +	nv_wo32(falcon, 0x004, intr);
>>>> +
>>>> +	if (intr & 0x10) {
>>>> +		intr &= ~0x10;
>>>> +
>>>> +		nv_info(falcon, "Exit interrupt called\n");
>>> Do you really want to print it at "info" level? How frequent it is?
>> It shouldn't be often, I want it to run at the error level since that usually
>> means the firmware exited prematurely/crashed and things go bad, but it
>> happens with the secret scrubber finishing on initialization too. That one
>> is harmless though.
> Maybe it should say:
> nv_error(falcon, "firmware exited prematurely\n");
> ?
>
That is only 1 of the 2 causes, the other is when it's a secret engine (CRYPT/BSP/VP for <nvd0) and the scrubber finished running. In that case it's not an error.

~Maarten
diff mbox

Patch

diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c
index e05c157..b11c5f3 100644
--- a/drivers/gpu/drm/nouveau/core/core/falcon.c
+++ b/drivers/gpu/drm/nouveau/core/core/falcon.c
@@ -229,6 +229,24 @@  _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
 	return nouveau_engine_fini(&falcon->base, suspend);
 }
 
+void
+nouveau_falcon_intr(struct nouveau_subdev *subdev)
+{
+	struct nouveau_falcon *falcon = (void*)subdev;
+	u32 intr = nv_ro32(falcon, 0x008);
+
+	nv_wo32(falcon, 0x004, intr);
+
+	if (intr & 0x10) {
+		intr &= ~0x10;
+
+		nv_info(falcon, "Exit interrupt called\n");
+	}
+
+	if (intr)
+		nv_error(falcon, "Unhandled interrupt %08x\n", intr);
+}
+
 int
 nouveau_falcon_create_(struct nouveau_object *parent,
 		       struct nouveau_object *engine,
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
index 0a5aa6b..2201c96 100644
--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
@@ -91,6 +91,7 @@  nvc0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	nv_subdev(priv)->unit = 0x00008000;
+	nv_subdev(priv)->intr = nouveau_falcon_intr;
 	nv_engine(priv)->cclass = &nvc0_bsp_cclass;
 	nv_engine(priv)->sclass = nvc0_bsp_sclass;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
index d4f23bb..4e7f79b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
@@ -91,6 +91,7 @@  nve0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	nv_subdev(priv)->unit = 0x00008000;
+	nv_subdev(priv)->intr = nouveau_falcon_intr;
 	nv_engine(priv)->cclass = &nve0_bsp_cclass;
 	nv_engine(priv)->sclass = nve0_bsp_sclass;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c
index ebf0d86..4557c3b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c
@@ -91,6 +91,7 @@  nvc0_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	nv_subdev(priv)->unit = 0x00000002;
+	nv_subdev(priv)->intr = nouveau_falcon_intr;
 	nv_engine(priv)->cclass = &nvc0_ppp_cclass;
 	nv_engine(priv)->sclass = nvc0_ppp_sclass;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c
index f761949..cc2c8cc 100644
--- a/drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c
@@ -91,6 +91,7 @@  nvc0_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	nv_subdev(priv)->unit = 0x00020000;
+	nv_subdev(priv)->intr = nouveau_falcon_intr;
 	nv_engine(priv)->cclass = &nvc0_vp_cclass;
 	nv_engine(priv)->sclass = nvc0_vp_sclass;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/vp/nve0.c
index 2384ce5..774ec16 100644
--- a/drivers/gpu/drm/nouveau/core/engine/vp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/vp/nve0.c
@@ -91,6 +91,7 @@  nve0_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	nv_subdev(priv)->unit = 0x00020000;
+	nv_subdev(priv)->intr = nouveau_falcon_intr;
 	nv_engine(priv)->cclass = &nve0_vp_cclass;
 	nv_engine(priv)->sclass = nve0_vp_sclass;
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/falcon.h b/drivers/gpu/drm/nouveau/core/include/core/falcon.h
index 1edec38..181aa7d 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/falcon.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/falcon.h
@@ -72,6 +72,8 @@  int nouveau_falcon_create_(struct nouveau_object *, struct nouveau_object *,
 			   struct nouveau_oclass *, u32, bool, const char *,
 			   const char *, int, void **);
 
+void nouveau_falcon_intr(struct nouveau_subdev *subdev);
+
 #define _nouveau_falcon_dtor _nouveau_engine_dtor
 int  _nouveau_falcon_init(struct nouveau_object *);
 int  _nouveau_falcon_fini(struct nouveau_object *, bool);