Commit 778e26de authored by Patrik Jakobsson's avatar Patrik Jakobsson

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=64221Signed-off-by: default avatarPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
parent c7829b29
...@@ -173,10 +173,13 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) ...@@ -173,10 +173,13 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
return 0; 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 psb_intel_opregion *opregion =
struct opregion_asle *asle = dev_priv->opregion.asle; 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_stat = 0;
u32 asle_req; u32 asle_req;
...@@ -190,9 +193,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev) ...@@ -190,9 +193,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev)
} }
if (asle_req & ASLE_SET_BACKLIGHT) 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; 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) #define ASLE_ALS_EN (1<<0)
...@@ -282,6 +294,8 @@ void psb_intel_opregion_fini(struct drm_device *dev) ...@@ -282,6 +294,8 @@ void psb_intel_opregion_fini(struct drm_device *dev)
unregister_acpi_notifier(&psb_intel_opregion_notifier); unregister_acpi_notifier(&psb_intel_opregion_notifier);
} }
cancel_work_sync(&opregion->asle_work);
/* just clear all opregion memory pointers now */ /* just clear all opregion memory pointers now */
iounmap(opregion->header); iounmap(opregion->header);
opregion->header = NULL; opregion->header = NULL;
...@@ -304,6 +318,9 @@ int psb_intel_opregion_setup(struct drm_device *dev) ...@@ -304,6 +318,9 @@ int psb_intel_opregion_setup(struct drm_device *dev)
DRM_DEBUG_DRIVER("ACPI Opregion not supported\n"); DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
return -ENOTSUPP; return -ENOTSUPP;
} }
INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);
DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy); DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
base = acpi_os_ioremap(opregion_phy, 8*1024); base = acpi_os_ioremap(opregion_phy, 8*1024);
if (!base) if (!base)
......
...@@ -266,6 +266,7 @@ struct psb_intel_opregion { ...@@ -266,6 +266,7 @@ struct psb_intel_opregion {
struct opregion_asle *asle; struct opregion_asle *asle;
void *vbt; void *vbt;
u32 __iomem *lid_state; u32 __iomem *lid_state;
struct work_struct asle_work;
}; };
struct sdvo_device_mapping { struct sdvo_device_mapping {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment