Skip to content

Commit

Permalink
drm/gma500: Move asle interrupt work into a work task
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrik Jakobsson committed Mar 17, 2014
1 parent c7829b2 commit 778e26d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
25 changes: 21 additions & 4 deletions drivers/gpu/drm/gma500/opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/gma500/psb_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 778e26d

Please sign in to comment.