Skip to content

Commit

Permalink
drm/nv50: punt hotplug irq handling out to workqueue
Browse files Browse the repository at this point in the history
On DP outputs we'll likely end up running vbios init tables here, which
may sleep.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Apr 9, 2010
1 parent 6f335a7 commit a5acac6
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 5 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ struct drm_nouveau_private {

struct workqueue_struct *wq;
struct work_struct irq_work;
struct work_struct hpd_work;

struct list_head vbl_waiting;

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ nouveau_irq_preinstall(struct drm_device *dev)

if (dev_priv->card_type == NV_50) {
INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
INIT_LIST_HEAD(&dev_priv->vbl_waiting);
}
}
Expand Down
14 changes: 9 additions & 5 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,10 +887,12 @@ nv50_display_error_handler(struct drm_device *dev)
nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
}

static void
nv50_display_irq_hotplug(struct drm_device *dev)
void
nv50_display_irq_hotplug_bh(struct work_struct *work)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_private *dev_priv =
container_of(work, struct drm_nouveau_private, hpd_work);
struct drm_device *dev = dev_priv->dev;
struct drm_connector *connector;
const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
uint32_t unplug_mask, plug_mask, change_mask;
Expand Down Expand Up @@ -951,8 +953,10 @@ nv50_display_irq_handler(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t delayed = 0;

while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG)
nv50_display_irq_hotplug(dev);
if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) {
if (!work_pending(&dev_priv->hpd_work))
queue_work(dev_priv->wq, &dev_priv->hpd_work);
}

while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nv50_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

void nv50_display_irq_handler(struct drm_device *dev);
void nv50_display_irq_handler_bh(struct work_struct *work);
void nv50_display_irq_hotplug_bh(struct work_struct *work);
int nv50_display_init(struct drm_device *dev);
int nv50_display_create(struct drm_device *dev);
int nv50_display_destroy(struct drm_device *dev);
Expand Down

0 comments on commit a5acac6

Please sign in to comment.