The following reply was made to PR i386/6540; it has been noted by GNATS.

From: Mark Kettenis <[email protected]>
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: i386/6540: panic on boot in pci_make_tag
Date: Sun, 9 Jan 2011 12:41:55 +0100 (CET)

 Just committed the patch below which should fix this.
 
 Index: i386/pci/pci_machdep.c
 ===================================================================
 RCS file: /cvs/src/sys/arch/i386/pci/pci_machdep.c,v
 retrieving revision 1.56
 diff -u -p -r1.56 pci_machdep.c
 --- i386/pci/pci_machdep.c     4 Jan 2011 21:17:49 -0000       1.56
 +++ i386/pci/pci_machdep.c     9 Jan 2011 11:10:28 -0000
 @@ -126,6 +126,7 @@ bus_addr_t pci_mcfg_addr;
  int pci_mcfg_min_bus, pci_mcfg_max_bus;
  bus_space_tag_t pci_mcfgt = I386_BUS_SPACE_MEM;
  bus_space_handle_t pci_mcfgh[256];
 +void pci_mcfg_map_bus(int);
  
  struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
  
 @@ -224,15 +225,6 @@ pci_make_tag(pci_chipset_tag_t pc, int b
  {
        pcitag_t tag;
  
 -      if (pci_mcfg_addr) {
 -              if (bus < pci_mcfg_min_bus  || bus > pci_mcfg_max_bus ||
 -                  device >= 32 || function >= 8)
 -                      panic("pci_make_tag: bad request");
 -
 -              tag.mode1 = (bus << 20) | (device << 15) | (function << 12);
 -              return tag;
 -      }
 -
        switch (pci_mode) {
        case 1:
                if (bus >= 256 || device >= 32 || function >= 8)
 @@ -259,16 +251,6 @@ pci_make_tag(pci_chipset_tag_t pc, int b
  void
  pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int 
*fp)
  {
 -      if (pci_mcfg_addr) {
 -              if (bp != NULL)
 -                      *bp = (tag.mode1 >> 20) & 0xff;
 -              if (dp != NULL)
 -                      *dp = (tag.mode1 >> 15) & 0x1f;
 -              if (fp != NULL)
 -                      *fp = (tag.mode1 >> 12) & 0x7;
 -              return;
 -      }
 -
        switch (pci_mode) {
        case 1:
                if (bp != NULL)
 @@ -294,12 +276,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, 
  int
  pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
  {
 -      if (pci_mcfg_addr)
 -              return PCIE_CONFIG_SPACE_SIZE;
 +      int bus;
 +
 +      if (pci_mcfg_addr) {
 +              pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
 +                      return PCIE_CONFIG_SPACE_SIZE;
 +      }
  
        return PCI_CONFIG_SPACE_SIZE;
  }
  
 +void
 +pci_mcfg_map_bus(int bus)
 +{
 +      if (pci_mcfgh[bus])
 +              return;
 +
 +      if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
 +          0, &pci_mcfgh[bus]))
 +              panic("pci_conf_read: cannot map mcfg space");
 +}
 +
  pcireg_t
  pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
  {
 @@ -308,13 +306,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcit
  
        if (pci_mcfg_addr) {
                pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 -              if (pci_mcfgh[bus] == 0 &&
 -                  bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
 -                  1 << 20, 0, &pci_mcfgh[bus]))
 -                      panic("pci_conf_read: cannot map mcfg space");
 -              data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
 -                  (tag.mode1 & 0x000ff000) | reg);
 -              return data;
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
 +                      pci_mcfg_map_bus(bus);
 +                      data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
 +                          (tag.mode1 & 0x000ff00) << 4 | reg);
 +                      return data;
 +              }
        }
  
        PCI_CONF_LOCK();
 @@ -345,13 +342,12 @@ pci_conf_write(pci_chipset_tag_t pc, pci
  
        if (pci_mcfg_addr) {
                pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 -              if (pci_mcfgh[bus] == 0 &&
 -                  bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
 -                  1 << 20, 0, &pci_mcfgh[bus]))
 -                      panic("pci_conf_write: cannot map mcfg space");
 -              bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
 -                  (tag.mode1 & 0x000ff000) | reg, data);
 -              return;
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
 +                      pci_mcfg_map_bus(bus);
 +                      bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
 +                          (tag.mode1 & 0x000ff00) << 4 | reg, data);
 +                      return;
 +              }
        }
  
        PCI_CONF_LOCK();
 Index: amd64/pci/pci_machdep.c
 ===================================================================
 RCS file: /cvs/src/sys/arch/amd64/pci/pci_machdep.c,v
 retrieving revision 1.38
 diff -u -p -r1.38 pci_machdep.c
 --- amd64/pci/pci_machdep.c    4 Jan 2011 21:17:49 -0000       1.38
 +++ amd64/pci/pci_machdep.c    9 Jan 2011 11:10:28 -0000
 @@ -108,6 +108,7 @@ bus_addr_t pci_mcfg_addr;
  int pci_mcfg_min_bus, pci_mcfg_max_bus;
  bus_space_tag_t pci_mcfgt = X86_BUS_SPACE_MEM;
  bus_space_handle_t pci_mcfgh[256];
 +void pci_mcfg_map_bus(int);
  
  struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
  
 @@ -170,14 +171,6 @@ pci_make_tag(pci_chipset_tag_t pc, int b
        if (bus >= 256 || device >= 32 || function >= 8)
                panic("pci_make_tag: bad request");
  
 -      if (pci_mcfg_addr) {
 -              if (bus < pci_mcfg_min_bus  || bus > pci_mcfg_max_bus ||
 -                  device >= 32 || function >= 8)
 -                      panic("pci_make_tag: bad request");
 -
 -              return (bus << 20) | (device << 15) | (function << 12);
 -      }
 -
        return (PCI_MODE1_ENABLE |
            (bus << 16) | (device << 11) | (function << 8));
  }
 @@ -185,16 +178,6 @@ pci_make_tag(pci_chipset_tag_t pc, int b
  void
  pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int 
*fp)
  {
 -      if (pci_mcfg_addr) {
 -              if (bp != NULL)
 -                      *bp = (tag >> 20) & 0xff;
 -              if (dp != NULL)
 -                      *dp = (tag >> 15) & 0x1f;
 -              if (fp != NULL)
 -                      *fp = (tag >> 12) & 0x7;
 -              return;
 -      }
 -
        if (bp != NULL)
                *bp = (tag >> 16) & 0xff;
        if (dp != NULL)
 @@ -206,12 +189,28 @@ pci_decompose_tag(pci_chipset_tag_t pc, 
  int
  pci_conf_size(pci_chipset_tag_t pc, pcitag_t tag)
  {
 -      if (pci_mcfg_addr)
 -              return PCIE_CONFIG_SPACE_SIZE;
 +      int bus;
 +
 +      if (pci_mcfg_addr) {
 +              pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus)
 +                      return PCIE_CONFIG_SPACE_SIZE;
 +      }
  
        return PCI_CONFIG_SPACE_SIZE;
  }
  
 +void
 +pci_mcfg_map_bus(int bus)
 +{
 +      if (pci_mcfgh[bus])
 +              return;
 +
 +      if (bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20), 1 << 20,
 +          0, &pci_mcfgh[bus]))
 +              panic("pci_conf_read: cannot map mcfg space");
 +}
 +
  pcireg_t
  pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
  {
 @@ -220,12 +219,12 @@ pci_conf_read(pci_chipset_tag_t pc, pcit
  
        if (pci_mcfg_addr) {
                pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 -              if (pci_mcfgh[bus] == 0 &&
 -                  bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
 -                  1 << 20, 0, &pci_mcfgh[bus]))
 -                      panic("pci_conf_read: cannot map mcfg space");
 -              return  bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
 -                  (tag & 0x000ff000) | reg);
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
 +                      pci_mcfg_map_bus(bus);
 +                      data = bus_space_read_4(pci_mcfgt, pci_mcfgh[bus],
 +                          (tag & 0x000ff00) << 4 | reg);
 +                      return data;
 +              }
        }
  
        PCI_CONF_LOCK();
 @@ -244,13 +243,12 @@ pci_conf_write(pci_chipset_tag_t pc, pci
  
        if (pci_mcfg_addr) {
                pci_decompose_tag(pc, tag, &bus, NULL, NULL);
 -              if (pci_mcfgh[bus] == 0 &&
 -                  bus_space_map(pci_mcfgt, pci_mcfg_addr + (bus << 20),
 -                  1 << 20, 0, &pci_mcfgh[bus]))
 -                      panic("pci_conf_write: cannot map mcfg space");
 -              bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
 -                  (tag & 0x000ff000) | reg, data);
 -              return;
 +              if (bus >= pci_mcfg_min_bus && bus <= pci_mcfg_max_bus) {
 +                      pci_mcfg_map_bus(bus);
 +                      bus_space_write_4(pci_mcfgt, pci_mcfgh[bus],
 +                          (tag & 0x000ff00) << 4 | reg, data);
 +                      return;
 +              }
        }
  
        PCI_CONF_LOCK();

Reply via email to