summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-04-03 12:41:21 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-04-03 12:41:21 +0000
commita42bafa7a7c496b51d0003dec48fcd7f0a78c6ac (patch)
treec1aa8ec5ccb5a355e708b41c90f0b77ba384425a /sys
parent945edc728f8c2b49653ec54af3cae1e8af64d04c (diff)
Same as just done for radeon. Add and use a lock for procecting against
races when waiting on fences, and use that in preference to irq_lock. Don't use drm_irq_handler_wrap() anymore for irq handler, just the mgadrm main irq handler. knf while here.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/drm/mga_drv.c1
-rw-r--r--sys/dev/pci/drm/mga_drv.h10
-rw-r--r--sys/dev/pci/drm/mga_irq.c42
-rw-r--r--sys/dev/pci/drm/mga_state.c11
4 files changed, 34 insertions, 30 deletions
diff --git a/sys/dev/pci/drm/mga_drv.c b/sys/dev/pci/drm/mga_drv.c
index 278249746d7..5e5464b4532 100644
--- a/sys/dev/pci/drm/mga_drv.c
+++ b/sys/dev/pci/drm/mga_drv.c
@@ -173,6 +173,7 @@ mgadrm_attach(struct device *parent, struct device *self, void *aux)
return;
}
printf(": %s\n", pci_intr_string(pa->pa_pc, dev_priv->ih));
+ mtx_init(&dev_priv->fence_lock, IPL_BIO);
/* XXX pcie */
is_agp = pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
diff --git a/sys/dev/pci/drm/mga_drv.h b/sys/dev/pci/drm/mga_drv.h
index 8ca1d7cca3a..0c979ce9b55 100644
--- a/sys/dev/pci/drm/mga_drv.h
+++ b/sys/dev/pci/drm/mga_drv.h
@@ -119,9 +119,10 @@ typedef struct drm_mga_private {
u32 clear_cmd;
u32 maccess;
- atomic_t vbl_received; /**< Number of vblanks received. */
- atomic_t last_fence_retired;
- u32 next_fence_to_post;
+ atomic_t vbl_received; /**< Number of vblanks received. */
+ struct mutex fence_lock;
+ u_int32_t last_fence_retired;
+ u_int32_t next_fence_to_post;
unsigned int fb_cpp;
unsigned int front_offset;
@@ -186,8 +187,7 @@ extern int mga_warp_init(drm_mga_private_t * dev_priv);
extern int mga_enable_vblank(struct drm_device *dev, int crtc);
extern void mga_disable_vblank(struct drm_device *dev, int crtc);
extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
-extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device * dev, u_int32_t *sequence);
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
extern int mga_driver_irq_install(struct drm_device * dev);
extern void mga_driver_irq_uninstall(struct drm_device * dev);
diff --git a/sys/dev/pci/drm/mga_irq.c b/sys/dev/pci/drm/mga_irq.c
index 0d3bdac8730..6e0a736f84d 100644
--- a/sys/dev/pci/drm/mga_irq.c
+++ b/sys/dev/pci/drm/mga_irq.c
@@ -45,7 +45,6 @@ mga_get_vblank_counter(struct drm_device *dev, int crtc)
return (0);
}
-
return (atomic_read(&dev_priv->vbl_received));
}
@@ -69,8 +68,8 @@ mga_driver_irq_handler(DRM_IRQ_ARGS)
/* SOFTRAP interrupt */
if (status & MGA_SOFTRAPEN) {
- const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
- const u32 prim_end = MGA_READ(MGA_PRIMEND);
+ const u_int32_t prim_start = MGA_READ(MGA_PRIMADDRESS);
+ const u_int32_t prim_end = MGA_READ(MGA_PRIMEND);
MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
@@ -82,8 +81,10 @@ mga_driver_irq_handler(DRM_IRQ_ARGS)
MGA_WRITE(MGA_PRIMEND, prim_end);
}
- atomic_inc(&dev_priv->last_fence_retired);
+ mtx_enter(&dev_priv->fence_lock);
+ dev_priv->last_fence_retired++;
wakeup(dev_priv);
+ mtx_leave(&dev_priv->fence_lock);
handled = 1;
}
@@ -92,22 +93,24 @@ mga_driver_irq_handler(DRM_IRQ_ARGS)
return (IRQ_NONE);
}
-int mga_enable_vblank(struct drm_device *dev, int crtc)
+int
+mga_enable_vblank(struct drm_device *dev, int crtc)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_mga_private_t *dev_priv = dev->dev_private;
if (crtc != 0) {
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
crtc);
- return 0;
+ return (0);
}
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
- return 0;
+ return (0);
}
-void mga_disable_vblank(struct drm_device *dev, int crtc)
+void
+mga_disable_vblank(struct drm_device *dev, int crtc)
{
if (crtc != 0) {
DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
@@ -122,29 +125,30 @@ void mga_disable_vblank(struct drm_device *dev, int crtc)
/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
}
-int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
+int
+mga_driver_fence_wait(struct drm_device * dev, u_int32_t *sequence)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
- unsigned int cur_fence;
- int ret = 0;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u_int32_t cur_fence;
+ int ret = 0;
/* Assume that the user has missed the current sequence number
* by about a day rather than she wants to wait for years
* using fences.
*/
- DRM_WAIT_ON(ret, dev_priv, &dev->irq_lock, 3 * hz, "mgawt",
- (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) -
+ DRM_WAIT_ON(ret, dev_priv, &dev_priv->fence_lock, 3 * hz, "mgawt",
+ (((cur_fence = dev_priv->last_fence_retired) -
*sequence) <= (1 << 23)));
*sequence = cur_fence;
- return ret;
+ return (ret);
}
int
mga_driver_irq_install(struct drm_device * dev)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_mga_private_t *dev_priv = dev->dev_private;
/* Disable *all* interrupts */
MGA_WRITE(MGA_IEN, 0);
@@ -152,7 +156,7 @@ mga_driver_irq_install(struct drm_device * dev)
MGA_WRITE(MGA_ICLEAR, ~0);
dev_priv->irqh = pci_intr_establish(dev_priv->pc, dev_priv->ih, IPL_BIO,
- drm_irq_handler_wrap, dev, dev_priv->dev.dv_xname);
+ mga_driver_irq_handler, dev, dev_priv->dev.dv_xname);
if (dev_priv->irqh == NULL)
return (ENOENT);
@@ -166,7 +170,7 @@ mga_driver_irq_install(struct drm_device * dev)
void
mga_driver_irq_uninstall(struct drm_device * dev)
{
- drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+ drm_mga_private_t *dev_priv = dev->dev_private;
/* Disable *all* interrupts */
MGA_WRITE(MGA_IEN, 0);
diff --git a/sys/dev/pci/drm/mga_state.c b/sys/dev/pci/drm/mga_state.c
index f13c60fcdaa..3db6c44415d 100644
--- a/sys/dev/pci/drm/mga_state.c
+++ b/sys/dev/pci/drm/mga_state.c
@@ -1102,19 +1102,18 @@ int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv
return 0;
}
-int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int
+mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
- drm_mga_private_t *dev_priv = dev->dev_private;
- u32 *fence = data;
+ drm_mga_private_t *dev_priv = dev->dev_private;
+ u_int32_t *fence = data;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return EINVAL;
}
- DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
mga_driver_fence_wait(dev, fence);
- return 0;
+ return (0);
}