i915_driver_irq_handler: irq 42: nobody cared

Marcin Slusarz marcin.slusarz at gmail.com
Tue Apr 10 09:50:44 PDT 2012


On Tue, Apr 10, 2012 at 10:52:06AM +0200, Jiri Slaby wrote:
> On 04/06/2012 11:31 PM, Jiri Slaby wrote:
> > On 03/30/2012 02:24 PM, Chris Wilson wrote:
> >> On Fri, 30 Mar 2012 14:11:47 +0200, Jiri Slaby <jslaby at suse.cz> wrote:
> >>> On 03/30/2012 12:45 PM, Chris Wilson wrote:
> >>>> On Fri, 30 Mar 2012 11:59:28 +0200, Jiri Slaby <jslaby at suse.cz> wrote:
> >>>>> I don't know what to dump more, because iir is obviously zero too. What
> >>>>> other sources of interrupts are on the (G33) chip?
> >>>>
> >>>> IIR is the master interrupt, with chained secondary interrupt statuses.
> >>>> If IIR is 0, the interrupt wasn't raised by the GPU.
> >>>
> >>> This does not make sense, the handler does something different. Even if
> >>> IIR is 0, it still takes a look at pipe stats.
> >>
> >> That was introduced in 05eff845a28499762075d3a72e238a31f4d2407c to close
> >> a race where the pipestat triggered an interrupt after we processed the
> >> secondary registers and before reseting the primary.
> >>
> >> But the basic premise that we should only enter the interrupt handler
> >> with IIR!=0 holds (presuming non-shared interrupt lines such as MSI).
> > 
> > Ok, this behavior is definitely new. I get several "nobody cared" about
> > this interrupt a week. This never used to happen. And something weird
> > emerges in /proc/interrupts when this happens:
> >  42:    1003292    1212890   PCI-MSI-edge      �s����:0000:00:02.0
> > instead of
> >  42:    1006715    1218472   PCI-MSI-edge      i915 at pci:0000:00:02.0
> 
> See the difference of drm_device->devname:
> 
> Before:
> 20 34 32 3a 20 20 20 20  31 34 30 35 34 36 32 20  | 42:    1405462 |
> 20 20 20 31 37 32 38 33  30 32 20 20 20 50 43 49  |   1728302   PCI|
> 2d 4d 53 49 2d 65 64 67  65 20 20 20 20 20 20 69  |-MSI-edge      i|
> 39 31 35 40 70 63 69 3a  30 30 30 30 3a 30 30 3a  |915 at pci:0000:00:|
> 30 32 2e 30 0a                                    |02.0.|
> 
> After:
> 20 34 32 3a 20 20 20 20  31 30 30 33 32 39 32 20  | 42:    1003292 |
> 20 20 20 31 32 31 32 38  39 30 20 20 20 50 43 49  |   1212890   PCI|
> 2d 4d 53 49 2d 65 64 67  65 20 20 20 20 20 20 ef  |-MSI-edge      .|
> bf bd 73 ef bf bd ef bf  bd ef bf bd ef bf bd 3a  |..s............:|
> 30 30 30 30 3a 30 30 3a  30 32 2e 30 0a           |0000:00:02.0.|
> 
> Any idea what "ef bf bd" pattern could be? And who *shifts* the
> "0000:00:02.0" string?
> 

Maybe this patch will help catch it:

---
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index cf85155..2f9717c 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -69,7 +69,7 @@ static void
 drm_unset_busid(struct drm_device *dev,
 		struct drm_master *master)
 {
-	kfree(dev->devname);
+	free_pages((unsigned long)dev->devname, 0);
 	dev->devname = NULL;
 
 	kfree(master->unique);
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index 13f3d93..d788b78 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -177,9 +177,7 @@ int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
 	} else
 		master->unique_len = len;
 
-	dev->devname =
-		kmalloc(strlen(pdriver->name) +
-			master->unique_len + 2, GFP_KERNEL);
+	dev->devname = (void *)__get_free_pages(GFP_KERNEL, 0);
 
 	if (dev->devname == NULL) {
 		ret = -ENOMEM;
@@ -188,6 +186,7 @@ int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
 
 	sprintf(dev->devname, "%s@%s", pdriver->name,
 		master->unique);
+	set_memory_ro((unsigned long)dev->devname, 1);
 
 	return 0;
 err:
@@ -217,8 +216,7 @@ int drm_pci_set_unique(struct drm_device *dev,
 	master->unique[master->unique_len] = '\0';
 
 	bus_name = dev->driver->bus->get_name(dev);
-	dev->devname = kmalloc(strlen(bus_name) +
-			       strlen(master->unique) + 2, GFP_KERNEL);
+	dev->devname = (void *)__get_free_pages(GFP_KERNEL, 0);
 	if (!dev->devname) {
 		ret = -ENOMEM;
 		goto err;
@@ -226,6 +224,7 @@ int drm_pci_set_unique(struct drm_device *dev,
 
 	sprintf(dev->devname, "%s@%s", bus_name,
 		master->unique);
+	set_memory_ro((unsigned long)dev->devname, 1);
 
 	/* Return error if the busid submitted doesn't match the device's actual
 	 * busid.
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 82431dc..aa0acec 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -148,9 +148,7 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas
 		goto err;
 	}
 
-	dev->devname =
-		kmalloc(strlen(dev->platformdev->name) +
-			master->unique_len + 2, GFP_KERNEL);
+	dev->devname = (void *)__get_free_pages(GFP_KERNEL, 0);
 
 	if (dev->devname == NULL) {
 		ret = -ENOMEM;
@@ -159,6 +157,8 @@ static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *mas
 
 	sprintf(dev->devname, "%s@%s", dev->platformdev->name,
 		master->unique);
+	set_memory_ro((unsigned long)dev->devname, 1);
+
 	return 0;
 err:
 	return ret;
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index aa454f8..4f53c0f 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -187,7 +187,7 @@ static void drm_master_destroy(struct kref *kref)
 		master->unique_len = 0;
 	}
 
-	kfree(dev->devname);
+	free_pages((unsigned long)dev->devname, 0);
 	dev->devname = NULL;
 
 	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
@@ -494,7 +494,7 @@ void drm_put_dev(struct drm_device *dev)
 
 	list_del(&dev->driver_item);
 	if (dev->devname) {
-		kfree(dev->devname);
+		free_pages((unsigned long)dev->devname, 0);
 		dev->devname = NULL;
 	}
 	kfree(dev);


More information about the dri-devel mailing list