NetBSD Problem Report #48796

From www@NetBSD.org  Fri May  9 14:15:24 2014
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 594E1A5675
	for <gnats-bugs@gnats.NetBSD.org>; Fri,  9 May 2014 14:15:24 +0000 (UTC)
Message-Id: <20140509141522.D17FEA5856@mollari.NetBSD.org>
Date: Fri,  9 May 2014 14:15:22 +0000 (UTC)
From: vs@nifelheim.info
Reply-To: vs@nifelheim.info
To: gnats-bugs@NetBSD.org
Subject: xf86-video-mga: bug with dual-head operations
X-Send-Pr-Version: www-1.0

>Number:         48796
>Category:       xsrc
>Synopsis:       xf86-video-mga: bug with dual-head operations
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    mrg
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 09 14:20:00 +0000 2014
>Closed-Date:    Fri Aug 08 11:01:15 +0000 2014
>Last-Modified:  Fri Aug 08 11:01:15 +0000 2014
>Originator:     Volkmar Seifert
>Release:        NetBSD 6.1_STABLE
>Organization:
>Environment:
NetBSD SnowLion.home.nifelheim.info 6.1_STABLE NetBSD 6.1_STABLE (GENERIC) #1: Fri May  9 12:48:47 CEST 2014  mjoellnir@cheetah:/work/netbsd/v6/work/i386/GENERIC/obj/work/netbsd/v6/src/sys/arch/i386/compile/GENERIC i386

>Description:
The mga driver fails on dual head configurations with this error:

[  1099.472] (WW) MGA(0): Direct rendering disabled
[  1099.473] (EE) MGA(1): Unable to map BAR 0.  Invalid argument (22)
[  1099.473]
Fatal server error:
[  1099.473] AddScreen/ScreenInit failed for driver 1

This happens, because it tries to map the same PCI memory region twice.

The xorg.config looks like this (shortened to the relevant sections): 

Section "Monitor"
        Identifier "Monitor0"
        VendorName "Acer"
        ModelName  "V223HQ"
EndSection

Section "Monitor"
        Identifier "Monitor1"
        VendorName "Asus"
        ModelName  "V278"
EndSection

Section "Device"
        Identifier "Card0"
        Driver     "mga"
        #BusId      "PCI:1:0:0"
        Screen     0
EndSection

Section "Device"
        Identifier "Card1"
        Driver     "mga"
        #BusID      "PCI:1:0:0"
        Screen     1
EndSection

Section "Screen"
        Identifier   "Screen0"
        Device       "Card0"
        Monitor      "Monitor0"
        DefaultDepth 24
EndSection

Section "Screen"
        Identifier   "Screen1"
        Device       "Card1"
        Monitor      "Monitor1"
        DefaultDepth 24
EndSection

Section "ServerLayout"
        Identifier     "X.org Configured"
        InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Keyboard0" "CoreKeyboard"
        Screen         "Screen0"
        Screen         "Screen1" RightOf "Screen0"
EndSection

Section "ServerFlags"
        Option "Xinerama"
EndSection

>How-To-Repeat:
Use a xorg.conf like the one above and an MGA card, call "startx" on cli, and there you go.
>Fix:
Following a few leads found via google, I found a patch that helped on Linux to get rid of the problem. I have applied that patch to our sources, and tested them on my system successfully. Using the xorg.conf above and the mga-driver starts a nice dual-headed system on which both screens are used for an extended display (meaning the output is not mirrored :) ). I have created this xsrc-specific patch, and would like to ask you to apply it to the repository, so that everyone can benefit from this:

? xf86-video-mga.patch
Index: mga.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-video-mga/dist/src/mga.h,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 mga.h
--- mga.h	22 May 2010 10:09:00 -0000	1.1.1.4
+++ mga.h	9 May 2014 13:46:45 -0000
@@ -337,6 +337,10 @@
     int			mastervideoRam;
     int			slavevideoRam;
     Bool		directRenderingEnabled;
+    void  *		mappedIOBase;
+    int			mappedIOUsage;
+    void  *		mappedILOADBase;
+    int			mappedILOADUsage; 
     ScrnInfoPtr 	pScrn_1;
     ScrnInfoPtr 	pScrn_2;
 } MGAEntRec, *MGAEntPtr;
Index: mga_driver.c
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-video-mga/dist/src/mga_driver.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 mga_driver.c
--- mga_driver.c	14 Aug 2010 08:33:53 -0000	1.1.1.5
+++ mga_driver.c	9 May 2014 13:46:45 -0000
@@ -2822,23 +2822,46 @@

     if (!pMga->FBDev) {
 #ifdef XSERVER_LIBPCIACCESS
-        memory[pMga->io_bar] = &pMga->IOBase;
-        memory[pMga->framebuffer_bar] = &pMga->FbBase;
+	pciaddr_t fbaddr = pMga->FbAddress;
+	pciaddr_t fbsize = pMga->FbMapSize;
+	err = pci_device_map_range(dev,
+				   fbaddr, fbsize,
+				   PCI_DEV_MAP_FLAG_WRITABLE,
+				   (void **)&pMga->FbBase);
+	if (err) {
+	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		"Unable to map Framebuffer %08llX %llx.  %s (%d)\n", (long long)fbaddr, (long long)fbsize,
+		strerror(err), err);
+	  return FALSE;
+	}
+	else
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			"MAPPED Framebuffer %08llX %llx to %08llX.\n", 
+			(long long)fbaddr, (long long)fbsize, (long long)pMga->FbBase);
+
+	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
+	  region = &dev->regions[pMga->io_bar];
+	  err = pci_device_map_range(dev,
+	    region->base_addr, region->size,
+	    PCI_DEV_MAP_FLAG_WRITABLE,
+	    &pMga->IOBase);
+    
+	  if (err) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	      "Unable to map IO Region %i.  %s (%d)\n",
+	    pMga->io_bar, strerror(err), err);
+	    return FALSE;
+	  }

-        for (i = 0; i < 2; i++) {
-            region = &dev->regions[i];
-            err = pci_device_map_range(dev,
-                                       region->base_addr, region->size,
-                                       PCI_DEV_MAP_FLAG_WRITABLE,
-                                       memory[i]);
+	  if(pMga->entityPrivate != NULL) {
+	    pMga->entityPrivate->mappedIOBase = pMga->IOBase;
+	  }
+	}
+	else
+	  pMga->IOBase = pMga->entityPrivate->mappedIOBase;

-            if (err) {
-                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                           "Unable to map BAR %i.  %s (%d)\n",
-                           i, strerror(err), err);
-                return FALSE;
-            }
-        }
+	if(pMga->entityPrivate != NULL)		
+	  pMga->entityPrivate->mappedIOUsage ++;
 #else
 	/*
 	 * For Alpha, we need to map SPARSE memory, since we need
@@ -2880,16 +2903,26 @@
     if (pMga->iload_bar != -1) {
 #ifdef XSERVER_LIBPCIACCESS
         region = &dev->regions[pMga->iload_bar];
-        err = pci_device_map_range(dev,
+        if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) { 
+		err = pci_device_map_range(dev,
                                    region->base_addr, region->size,
                                    PCI_DEV_MAP_FLAG_WRITABLE,
                                    (void *) &pMga->ILOADBase);
-	if (err) {
+	  if (err) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Unable to map BAR 2 (ILOAD region).  %s (%d)\n",
 		       strerror(err), err);
 	    return FALSE;
+	  }
+
+	  if(pMga->entityPrivate != NULL)
+		pMga->entityPrivate->mappedILOADBase = pMga->ILOADBase;
 	}
+	else
+	  pMga->ILOADBase = pMga->entityPrivate->mappedILOADBase;
+
+	if(pMga->entityPrivate != NULL)
+	  pMga->entityPrivate->mappedILOADUsage ++;
 #else
 	pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
 					VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
@@ -2919,10 +2952,19 @@

     if (!pMga->FBDev) {
 #ifdef XSERVER_LIBPCIACCESS
-        pci_device_unmap_range(dev, pMga->IOBase, 
-			       dev->regions[pMga->io_bar].size);
-        pci_device_unmap_range(dev, pMga->FbBase, 
-			       dev->regions[pMga->framebuffer_bar].size);
+	if(pMga->entityPrivate != NULL)
+	  pMga->entityPrivate->mappedIOUsage --;
+	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedIOUsage == 0) {
+	  pci_device_unmap_range(dev, pMga->IOBase,
+		dev->regions[pMga->io_bar].size);
+	  if(pMga->entityPrivate != NULL)
+	    pMga->entityPrivate->mappedIOBase = NULL;
+	}
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UNMAPPING framebuffer 0x%08llX, 0x%llX.\n", 
+		(long long)pMga->FbBase, (long long)pMga->FbMapSize);
+	
+	pci_device_unmap_range(dev, pMga->FbBase, 
+			       pMga->FbMapSize);
 #else
 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase, pMga->FbMapSize);
@@ -2935,8 +2977,14 @@

     if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
 #ifdef XSERVER_LIBPCIACCESS
-        pci_device_unmap_range(dev, pMga->ILOADBase,
+        if(pMga->entityPrivate != NULL) 
+	  pMga->entityPrivate->mappedILOADUsage --;
+	if(pMga->entityPrivate == NULL || pMga->entityPrivate->mappedILOADUsage == 0) {
+	  pci_device_unmap_range(dev, pMga->ILOADBase,
 			       dev->regions[pMga->iload_bar].size);
+	  if(pMga->entityPrivate != NULL)
+	    pMga->entityPrivate->mappedILOADBase = NULL;
+	}
 #else
 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
 #endif

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: xsrc-manager->mrg
Responsible-Changed-By: mrg@NetBSD.org
Responsible-Changed-When: Fri, 16 May 2014 10:22:22 +0000
Responsible-Changed-Why:
i'll handle this.


State-Changed-From-To: open->pending-pullups
State-Changed-By: mrg@NetBSD.org
State-Changed-When: Tue, 05 Aug 2014 07:35:13 +0000
State-Changed-Why:
pullups to update to the latest mga driver are pending.  (it includes
the patch from this PR as well.)


State-Changed-From-To: pending-pullups->closed
State-Changed-By: mrg@NetBSD.org
State-Changed-When: Fri, 08 Aug 2014 11:01:15 +0000
State-Changed-Why:
latest mga driver has been pulled up to netbsd-6.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.