Certainly can't see any immediate problem David.

We can always cut a 4.3.1 if issues are found anyway.

Alan.

On Fri, Feb 14, 2003 at 04:17:16 -0500, David Dawes wrote:
> Egbert and I have been looking into the issues that are preventing a second
> X server to be started for i810/830M platforms when DRI is enabled.  Several
> issues were found:
> 
>   1. The i810 support doesn't unbind/release the agpgart module when VT
>      switching away, and this prevents a second X server from acquiring
>      it.  Since the i810 driver requires agpgart access even for 2D
>      operation, this is prevents a second X server from running.  A fix
>      for this is to add the unbind/release calls at LeaveVT, and
>      acquire/rebind at EnterVT.  The attached patch does this.  It also
>      makes a small change to the unbind code in the DRM kernel modules
>      to handle this.
> 
>   2. The 830M support does unbind/release the agpgart module, but code
>      in DRM(release) called when closing a /dev/dri/* device blocks
>      until it can obtain the lock.  Since the first server holds the
>      lock while switched away, the second one can never get it, so it
>      ends up blocking in close().  The second server opens/closes the
>      devices to find out whether DRI can be enabled.  DRI can't be
>      enabled on the second server (which isn't a problem), but this
>      blocking behaviour is preventing it from starting up at all.  I've
>      found that this can be solved by keeping track of whether the opener
>      has ever tried to acquire the lock, and not try to acquire it at
>      close/release when it had never previously been acquired.  The patch
>      below implements this.
> 
>   3. The drm module AGP support code keeps track of a "handle" for
>      allocated AGP regions.  It uses the memory address returned from
>      the allocation for this purpose.  This would normally be unique,
>      but for the i810 driver case where "DCACHE" memory is "allocated".
>      In the DCACHE case, the allocated memory is freed immediately (since
>      DCACHE doesn't come from the system memory pool), and the next
>      allocation often ends up getting the same memory address, and thus
>      the same "handle".  This showed up as a problem when the unbind/rebind
>      code was added.
> 
>      The user-level agpgart interfaces use a "key" value to uniquely
>      identify allocated AGP regions.  I don't know why the DRM module
>      doesn't do the same, since the key is guaranteed to be unique.
>      The patch below changes the handle to be the "key" value.
> 
> I'm wary of making changes like this so close to the 4.3 release, but
> I would like to see this problem fixed in 4.3.  Does anyone see any
> potential problems with the attached patch?
> 
> David
> -- 
> David Dawes
> Release Engineer/Architect                      The XFree86 Project
> www.XFree86.org/~dawes

> Index: drivers/i810/i810.h
> ===================================================================
> RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/drivers/i810/i810.h,v
> retrieving revision 1.37
> diff -u -r1.37 i810.h
> --- drivers/i810/i810.h       2002/12/10 01:27:04     1.37
> +++ drivers/i810/i810.h       2003/02/14 20:00:33
> @@ -264,6 +264,9 @@
>  extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen);
>  extern Bool I810InitDma(ScrnInfoPtr pScrn);
>  extern Bool I810CleanupDma(ScrnInfoPtr pScrn);
> +extern Bool I810DRILeave(ScrnInfoPtr pScrn);
> +extern Bool I810DRIEnter(ScrnInfoPtr pScrn);
> +
>  
>  #define I810PTR(p) ((I810Ptr)((p)->driverPrivate))
>  #define I810REGPTR(p) (&(I810PTR(p)->ModeReg))
> Index: drivers/i810/i810_dri.c
> ===================================================================
> RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v
> retrieving revision 1.33
> diff -u -r1.33 i810_dri.c
> --- drivers/i810/i810_dri.c   2002/12/10 01:27:04     1.33
> +++ drivers/i810/i810_dri.c   2003/02/14 20:00:33
> @@ -1218,3 +1218,84 @@
>  
>     pI810->AccelInfoRec->NeedToSync = TRUE;
>  }
> +
> +Bool
> +I810DRILeave(ScrnInfoPtr pScrn)
> +{
> +    I810Ptr pI810 = I810PTR(pScrn);
> +    
> +    if (pI810->directRenderingEnabled) {
> +     if (pI810->dcacheHandle != 0) 
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->backHandle != 0) 
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->zHandle != 0)
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->sysmemHandle != 0)
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->xvmcHandle != 0)
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->cursorHandle != 0)
> +         if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
> +             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
> +             return FALSE;
> +         }
> +     if (pI810->agpAcquired == TRUE)
> +         drmAgpRelease(pI810->drmSubFD);
> +     pI810->agpAcquired = FALSE;
> +    }
> +    return TRUE;
> +}
> +
> +Bool
> +I810DRIEnter(ScrnInfoPtr pScrn)
> +{
> +    I810Ptr pI810 = I810PTR(pScrn);
> +
> +    if (pI810->directRenderingEnabled) {
> +
> +     if (pI810->agpAcquired == FALSE)
> +         drmAgpAcquire(pI810->drmSubFD);
> +     pI810->agpAcquired = TRUE;
> +     if (pI810->dcacheHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
> +                        pI810->DepthOffset) != 0)
> +             return FALSE;
> +     if (pI810->backHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
> +                        pI810->BackOffset) != 0)
> +             return FALSE;
> +     if (pI810->zHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
> +                        pI810->DepthOffset) != 0)
> +             return FALSE;
> +     if (pI810->sysmemHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle,
> +                        0) != 0)
> +             return FALSE;
> +     if (pI810->xvmcHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
> +                        pI810->MC.Start) != 0)
> +             return FALSE;
> +     if (pI810->cursorHandle != 0)
> +         if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
> +                        pI810->CursorStart) != 0)
> +             return FALSE;
> +    }
> +    return TRUE;
> +}
> Index: drivers/i810/i810_driver.c
> ===================================================================
> RCS file: /home/x-cvs/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_driver.c,v
> retrieving revision 1.79
> diff -u -r1.79 i810_driver.c
> --- drivers/i810/i810_driver.c        2003/02/14 17:12:42     1.79
> +++ drivers/i810/i810_driver.c        2003/02/14 20:00:21
> @@ -2218,6 +2218,9 @@
>        return FALSE;
>  
>  #ifdef XF86DRI
> +   if (!I810DRIEnter(pScrn))
> +      return FALSE;
> +
>     if (pI810->directRenderingEnabled) {
>        if (I810_DEBUG & DEBUG_VERBOSE_DRI)
>        ErrorF("calling dri unlock\n");
> @@ -2260,6 +2263,11 @@
>  
>     if (!I810UnbindGARTMemory(pScrn))
>        return;
> +
> +#ifdef XF86DRI
> +   if (!I810DRILeave(pScrn))
> +      return;
> +#endif
>  
>     vgaHWLock(hwp);
>  }
> Index: os-support/linux/drm/kernel/drmP.h
> ===================================================================
> RCS file: 
>/home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v
> retrieving revision 1.27
> diff -u -r1.27 drmP.h
> --- os-support/linux/drm/kernel/drmP.h        2003/01/29 23:00:43     1.27
> +++ os-support/linux/drm/kernel/drmP.h        2003/02/14 19:53:44
> @@ -418,6 +418,7 @@
>       struct drm_file   *prev;
>       struct drm_device *dev;
>       int               remove_auth_on_close;
> +     unsigned long     lock_count;
>  } drm_file_t;
>  
>  
> @@ -484,7 +485,7 @@
>  
>  #if __REALLY_HAVE_AGP
>  typedef struct drm_agp_mem {
> -     unsigned long      handle;
> +     int                key;
>       agp_memory         *memory;
>       unsigned long      bound; /* address */
>       int                pages;
> Index: os-support/linux/drm/kernel/drm_agpsupport.h
> ===================================================================
> RCS file: 
>/home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h,v
> retrieving revision 1.7
> diff -u -r1.7 drm_agpsupport.h
> --- os-support/linux/drm/kernel/drm_agpsupport.h      2002/12/16 16:19:28     1.7
> +++ os-support/linux/drm/kernel/drm_agpsupport.h      2003/02/14 20:01:18
> @@ -147,7 +147,7 @@
>               return -ENOMEM;
>       }
>  
> -     entry->handle    = (unsigned long)memory->memory;
> +     entry->key       = memory->key;
>       entry->memory    = memory;
>       entry->bound     = 0;
>       entry->pages     = pages;
> @@ -156,7 +156,7 @@
>       if (dev->agp->memory) dev->agp->memory->prev = entry;
>       dev->agp->memory = entry;
>  
> -     request.handle   = entry->handle;
> +     request.handle   = entry->key;
>          request.physical = memory->physical;
>  
>       if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) {
> @@ -175,7 +175,7 @@
>       drm_agp_mem_t *entry;
>  
>       for (entry = dev->agp->memory; entry; entry = entry->next) {
> -             if (entry->handle == handle) return entry;
> +             if (entry->key == handle) return entry;
>       }
>       return NULL;
>  }
> @@ -187,6 +187,7 @@
>       drm_device_t      *dev   = priv->dev;
>       drm_agp_binding_t request;
>       drm_agp_mem_t     *entry;
> +     int               ret;
>  
>       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
>       if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
> @@ -194,7 +195,10 @@
>       if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
>               return -EINVAL;
>       if (!entry->bound) return -EINVAL;
> -     return DRM(unbind_agp)(entry->memory);
> +     ret = DRM(unbind_agp)(entry->memory);
> +     if (ret == 0)
> +         entry->bound = 0;
> +     return ret;
>  }
>  
>  int DRM(agp_bind)(struct inode *inode, struct file *filp,
> Index: os-support/linux/drm/kernel/drm_drv.h
> ===================================================================
> RCS file: 
>/home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h,v
> retrieving revision 1.10
> diff -u -r1.10 drm_drv.h
> --- os-support/linux/drm/kernel/drm_drv.h     2002/11/25 14:05:04     1.10
> +++ os-support/linux/drm/kernel/drm_drv.h     2003/02/14 17:32:02
> @@ -768,7 +768,7 @@
>       DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
>                  current->pid, (long)dev->device, dev->open_count );
>  
> -     if ( dev->lock.hw_lock &&
> +     if ( priv->lock_count && dev->lock.hw_lock &&
>            _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
>            dev->lock.pid == current->pid ) {
>               DRM_DEBUG( "Process %d dead, freeing lock for context %d\n",
> @@ -786,7 +786,7 @@
>                                     server. */
>       }
>  #if __HAVE_RELEASE
> -     else if ( dev->lock.hw_lock ) {
> +     else if ( priv->lock_count && dev->lock.hw_lock ) {
>               /* The lock is required to reclaim buffers */
>               DECLARE_WAITQUEUE( entry, current );
>               add_wait_queue( &dev->lock.lock_queue, &entry );
> @@ -932,6 +932,8 @@
>  
>          dev->lck_start = start = get_cycles();
>  #endif
> +
> +     ++priv->lock_count;
>  
>          if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
>               return -EFAULT;
> Index: os-support/linux/drm/kernel/drm_fops.h
> ===================================================================
> RCS file: 
>/home/x-cvs/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_fops.h,v
> retrieving revision 1.7
> diff -u -r1.7 drm_fops.h
> --- os-support/linux/drm/kernel/drm_fops.h    2002/11/25 14:05:04     1.7
> +++ os-support/linux/drm/kernel/drm_fops.h    2003/02/14 17:32:26
> @@ -57,6 +57,7 @@
>       priv->dev           = dev;
>       priv->ioctl_count   = 0;
>       priv->authenticated = capable(CAP_SYS_ADMIN);
> +     priv->lock_count    = 0;
>  
>       down(&dev->struct_sem);
>       if (!dev->file_last) {



-------------------------------------------------------
This SF.NET email is sponsored by: FREE  SSL Guide from Thawte
are you planning your Web Server Security? Click here to get a FREE
Thawte SSL guide and find the answers to all your  SSL security issues.
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0026en
_______________________________________________
Dri-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to