Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Nov 2005 07:00:56 GMT
From:      Arthur Hartwig <arthur.hartwig@nokia.com>
To:        freebsd-i386@FreeBSD.org
Subject:   Re: i386/89296: Spurious atapci1: failed to enable memory mapping! on ICH7
Message-ID:  <200511220700.jAM70uHP068304@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR i386/89296; it has been noted by GNATS.

From: Arthur Hartwig <arthur.hartwig@nokia.com>
To: bug-followup@FreeBSD.org, Francis.Dupont@enst-bretagne.fr
Cc:  
Subject: Re: i386/89296: Spurious atapci1: failed to enable memory mapping!
 on ICH7
Date: Tue, 22 Nov 2005 16:51:40 +1000

 I also saw this on my Gigabyte GA-*i945P-G motherboard which has an ICH7.
 
 The message is printed as a result of a bus_alloc_resource_any() call in 
 ata_intel_chipinit() in ata-chipset.c. The offending call is
 
 /* SATA parts can be either compat or AHCI */
     else {
         /* if we have BAR(5) as a memory resource we should use AHCI mode */
         ctlr->r_type2 = SYS_RES_MEMORY;
         ctlr->r_rid2 =PCIR_BAR(5);
         if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
                                                    &ctlr->r_rid2, 
 RF_ACTIVE))) {
 
 The bus_alloc_resource_any() call winds up in pci_alloc_resource() in 
 dev/pci/pci.c which sees the RF_ACTIVE flag is set and triies to enable 
 memory space access by calling PCI_ENABLE_IO() to set the appropriate 
 bit in the PCIR_COMMAND  register of the ATA controller. Unfortunately 
 the memory space enable bit in the ICH7 ATA controller on my motherboard 
 is hardwired to 0 unless the SCRAE bit is one. So the ATA driver could 
 be changed to stop this message appearing but I think the logic in 
 pci_alloc_resource() is flawed - it should not be attempting to enable 
 memory or i/o access UNTIL it has successfully allocated the requested 
 resource. Suggested fix:
 
 change pci_alloc_resource() to read as follows:
 struct resource *
 pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
                    u_long start, u_long end, u_long count, u_int flags)
 {
         struct pci_devinfo *dinfo = device_get_ivars(child);
         struct resource_list *rl = &dinfo->resources;
         struct resource_list_entry *rle;
         pcicfgregs *cfg = &dinfo->cfg;
 
         /*
          * Perform lazy resource allocation
          */
         if (device_get_parent(child) == dev) {
                 switch (type) {
                 case SYS_RES_IRQ:
                         /*
                          * If the child device doesn't have an
                          * interrupt routed and is deserving of an
                          * interrupt, try to assign it one.
                          */
                         if (!PCI_INTERRUPT_VALID(cfg->intline) &&
                             (cfg->intpin != 0))
                                 pci_assign_interrupt(dev, child, 0);
                         break;
                 case SYS_RES_IOPORT:
                 case SYS_RES_MEMORY:
                         rle = resource_list_find(rl, type, *rid);
                         if (rle == NULL)
                                 return (pci_alloc_map(dev, child, type, rid,
                                     start, end, count, flags));
                         break;
                 }
                 /*
                  * If we've already allocated the resource, then
                  * return it now.  But first we may need to activate
                  * it, since we don't allocate the resource as active
                  * above.  Normally this would be done down in the
                  * nexus, but since we short-circuit that path we have
                  * to do its job here.  Not sure if we should free the
                  * resource if it fails to activate.
                  */
                 rle = resource_list_find(rl, type, *rid);
                 if (rle != NULL && rle->res != NULL) {
                         if (bootverbose)
                                 device_printf(child,
                             "Reserved %#lx bytes for rid %#x type %d at 
 %#lx\n",
                                     rman_get_size(rle->res), *rid, type,
                                     rman_get_start(rle->res));
                         /*
                          * Enable IO mode only if the matching resource is
                          * successfully activated else the PCI_ENABLE_IO 
 might
                          * fail and report the failre when it doesn't 
 matter.
                          */
                         if (flags & RF_ACTIVE) {
                             if (bus_generic_activate_resource(dev, 
 child, type,
                                  *rid, rle->res) != 0)
                                 return NULL;
                             else
                                 PCI_ENABLE_IO(dev, child, type);
                         }
                         return (rle->res);
                 }
         }
         return (resource_list_alloc(rl, dev, child, type, rid,
             start, end, count, flags));
 }
 
 I built a kernel with this change, booted it and the memory mapping 
 failure message was gone. All devices seemed to work but I was left 
 wondering if the return in the SYS_RES_MEMORY and SYS_RES_IOPORT case 
 also needs a call to bus_generic_activate_resource() and PCI_ENABLE_IO().
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200511220700.jAM70uHP068304>