diff options
author | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2014-03-11 21:51:20 +0400 |
---|---|---|
committer | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2014-03-17 23:12:04 +0400 |
commit | 778e26dee5e6b3be4611b1f99f8359cb64b27ce9 (patch) | |
tree | b2776e555ac3588a97952d281a7c09db7b978203 /drivers/gpu/drm/gma500 | |
parent | c7829b29e9fd66f4e5cdd411feb28a22acdd1936 (diff) | |
download | linux-778e26dee5e6b3be4611b1f99f8359cb64b27ce9.tar.xz |
drm/gma500: Move asle interrupt work into a work task
Previously the backlight code was called from IRQ context which isn't
allowed. This patch moves all the asle work into a work task which takes
care of the locking bug reported by users.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=64221
Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/gma500')
-rw-r--r-- | drivers/gpu/drm/gma500/opregion.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.h | 1 |
2 files changed, 22 insertions, 4 deletions
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index 13ec6283bf59..ab696ca7eeec 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -173,10 +173,13 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) return 0; } -void psb_intel_opregion_asle_intr(struct drm_device *dev) +static void psb_intel_opregion_asle_work(struct work_struct *work) { - struct drm_psb_private *dev_priv = dev->dev_private; - struct opregion_asle *asle = dev_priv->opregion.asle; + struct psb_intel_opregion *opregion = + container_of(work, struct psb_intel_opregion, asle_work); + struct drm_psb_private *dev_priv = + container_of(opregion, struct drm_psb_private, opregion); + struct opregion_asle *asle = opregion->asle; u32 asle_stat = 0; u32 asle_req; @@ -190,9 +193,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev) } if (asle_req & ASLE_SET_BACKLIGHT) - asle_stat |= asle_set_backlight(dev, asle->bclp); + asle_stat |= asle_set_backlight(dev_priv->dev, asle->bclp); asle->aslc = asle_stat; + +} + +void psb_intel_opregion_asle_intr(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + + if (dev_priv->opregion.asle) + schedule_work(&dev_priv->opregion.asle_work); } #define ASLE_ALS_EN (1<<0) @@ -282,6 +294,8 @@ void psb_intel_opregion_fini(struct drm_device *dev) unregister_acpi_notifier(&psb_intel_opregion_notifier); } + cancel_work_sync(&opregion->asle_work); + /* just clear all opregion memory pointers now */ iounmap(opregion->header); opregion->header = NULL; @@ -304,6 +318,9 @@ int psb_intel_opregion_setup(struct drm_device *dev) DRM_DEBUG_DRIVER("ACPI Opregion not supported\n"); return -ENOTSUPP; } + + INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work); + DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy); base = acpi_os_ioremap(opregion_phy, 8*1024); if (!base) diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 77bd7aba8298..d5421c072b6b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -266,6 +266,7 @@ struct psb_intel_opregion { struct opregion_asle *asle; void *vbt; u32 __iomem *lid_state; + struct work_struct asle_work; }; struct sdvo_device_mapping { |