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@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@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@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@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);