Skip to content

Commit 235fdbc

Browse files
jwrdegoedepatjak
authored andcommitted
drm/gma500: Fix (vblank) IRQs not working after suspend/resume
Fix gnome-shell (and other page-flip users) hanging after suspend/resume because of the gma500's IRQs not working. This fixes 2 problems with the IRQ handling: 1. gma_power_off() calls gma_irq_uninstall() which does a free_irq(), but gma_power_on() called gma_irq_preinstall() + gma_irq_postinstall() which do not call request_irq. Replace the pre- + post-install calls with gma_irq_install() which does prep + request + post. 2. After fixing 1. IRQs still do not work on a Packard Bell Dot SC (Intel Atom N2600, cedarview) netbook. Cederview uses MSI interrupts and it seems that the BIOS re-configures things back to normal APIC based interrupts during S3 suspend. There is some MSI PCI-config registers save/restore code which tries to deal with this, but on the Packard Bell Dot SC this is not sufficient to restore MSI IRQ functionality after a suspend/resume. Replace the PCI-config registers save/restore with pci_disable_msi() on suspend + pci_enable_msi() on resume. Fixing e.g. gnome-shell hanging. Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Patrik Jakobsson <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b6f25c3 commit 235fdbc

File tree

7 files changed

+18
-23
lines changed

7 files changed

+18
-23
lines changed

drivers/gpu/drm/gma500/cdv_device.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,9 @@ static const struct psb_offset cdv_regmap[2] = {
581581
static int cdv_chip_setup(struct drm_device *dev)
582582
{
583583
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
584-
struct pci_dev *pdev = to_pci_dev(dev->dev);
585584
INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func);
586585

587-
if (pci_enable_msi(pdev))
588-
dev_warn(dev->dev, "Enabling MSI failed!\n");
586+
dev_priv->use_msi = true;
589587
dev_priv->regmap = cdv_regmap;
590588
gma_get_core_freq(dev);
591589
psb_intel_opregion_init(dev);

drivers/gpu/drm/gma500/oaktrail_device.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,12 +501,9 @@ static const struct psb_offset oaktrail_regmap[2] = {
501501
static int oaktrail_chip_setup(struct drm_device *dev)
502502
{
503503
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
504-
struct pci_dev *pdev = to_pci_dev(dev->dev);
505504
int ret;
506505

507-
if (pci_enable_msi(pdev))
508-
dev_warn(dev->dev, "Enabling MSI failed!\n");
509-
506+
dev_priv->use_msi = true;
510507
dev_priv->regmap = oaktrail_regmap;
511508

512509
ret = mid_chip_setup(dev);

drivers/gpu/drm/gma500/power.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,6 @@ static void gma_suspend_pci(struct pci_dev *pdev)
139139
dev_priv->regs.saveBSM = bsm;
140140
pci_read_config_dword(pdev, 0xFC, &vbt);
141141
dev_priv->regs.saveVBT = vbt;
142-
pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
143-
pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
144142

145143
pci_disable_device(pdev);
146144
pci_set_power_state(pdev, PCI_D3hot);
@@ -168,9 +166,6 @@ static bool gma_resume_pci(struct pci_dev *pdev)
168166
pci_restore_state(pdev);
169167
pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM);
170168
pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT);
171-
/* restoring MSI address and data in PCIx space */
172-
pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
173-
pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
174169
ret = pci_enable_device(pdev);
175170

176171
if (ret != 0)
@@ -223,8 +218,7 @@ int gma_power_resume(struct device *_dev)
223218
mutex_lock(&power_mutex);
224219
gma_resume_pci(pdev);
225220
gma_resume_display(pdev);
226-
gma_irq_preinstall(dev);
227-
gma_irq_postinstall(dev);
221+
gma_irq_install(dev);
228222
mutex_unlock(&power_mutex);
229223
return 0;
230224
}

drivers/gpu/drm/gma500/psb_drv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
383383
PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
384384
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
385385

386-
gma_irq_install(dev, pdev->irq);
386+
gma_irq_install(dev);
387387

388388
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
389389

drivers/gpu/drm/gma500/psb_drv.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ struct drm_psb_private {
490490
int rpm_enabled;
491491

492492
/* MID specific */
493+
bool use_msi;
493494
bool has_gct;
494495
struct oaktrail_gct_data gct_data;
495496

@@ -499,10 +500,6 @@ struct drm_psb_private {
499500
/* Register state */
500501
struct psb_save_area regs;
501502

502-
/* MSI reg save */
503-
uint32_t msi_addr;
504-
uint32_t msi_data;
505-
506503
/* Hotplug handling */
507504
struct work_struct hotplug_work;
508505

drivers/gpu/drm/gma500/psb_irq.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,17 +316,24 @@ void gma_irq_postinstall(struct drm_device *dev)
316316
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
317317
}
318318

319-
int gma_irq_install(struct drm_device *dev, unsigned int irq)
319+
int gma_irq_install(struct drm_device *dev)
320320
{
321+
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
322+
struct pci_dev *pdev = to_pci_dev(dev->dev);
321323
int ret;
322324

323-
if (irq == IRQ_NOTCONNECTED)
325+
if (dev_priv->use_msi && pci_enable_msi(pdev)) {
326+
dev_warn(dev->dev, "Enabling MSI failed!\n");
327+
dev_priv->use_msi = false;
328+
}
329+
330+
if (pdev->irq == IRQ_NOTCONNECTED)
324331
return -ENOTCONN;
325332

326333
gma_irq_preinstall(dev);
327334

328335
/* PCI devices require shared interrupts. */
329-
ret = request_irq(irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev);
336+
ret = request_irq(pdev->irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev);
330337
if (ret)
331338
return ret;
332339

@@ -369,6 +376,8 @@ void gma_irq_uninstall(struct drm_device *dev)
369376
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
370377

371378
free_irq(pdev->irq, dev);
379+
if (dev_priv->use_msi)
380+
pci_disable_msi(pdev);
372381
}
373382

374383
int gma_crtc_enable_vblank(struct drm_crtc *crtc)

drivers/gpu/drm/gma500/psb_irq.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct drm_device;
1717

1818
void gma_irq_preinstall(struct drm_device *dev);
1919
void gma_irq_postinstall(struct drm_device *dev);
20-
int gma_irq_install(struct drm_device *dev, unsigned int irq);
20+
int gma_irq_install(struct drm_device *dev);
2121
void gma_irq_uninstall(struct drm_device *dev);
2222

2323
int gma_crtc_enable_vblank(struct drm_crtc *crtc);

0 commit comments

Comments
 (0)