CTC++ Coverage Report - Execution Profile    #92/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: arch/x86_64/pci/mmconfig.c
Instrumentation mode: function-decision-multicondition
TER: 5 % ( 5/ 96)

Start/ End/    
True False - Line Source

  1 /*
  2  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
  3  * 
  4  * This is an 64bit optimized version that always keeps the full mmconfig
  5  * space mapped. This allows lockless config space operation.
  6  */
  7 
  8 #include <linux/pci.h>
  9 #include <linux/init.h>
  10 #include <linux/acpi.h>
  11 #include <linux/bitmap.h>
  12 #include "pci.h"
  13 
  14 #define MMCONFIG_APER_SIZE (256*1024*1024)
  15 
  16 static DECLARE_BITMAP(fallback_slots, 32);
  17 
  18 /* Static virtual mapping of the MMCONFIG aperture */
  19 struct mmcfg_virt {
  20    struct acpi_table_mcfg_config *cfg;
  21    char __iomem *virt;
  22 };
  23 static struct mmcfg_virt *pci_mmcfg_virt;
  24 
 
- 25 static char __iomem *get_virt(unsigned int seg, unsigned bus)
  26 {
  27    int cfg_num = -1;
  28    struct acpi_table_mcfg_config *cfg;
  29 
- 30    while (1) {
  31       ++cfg_num;
- 32       if (cfg_num >= pci_mmcfg_config_num)
 - 33          break;
  34       cfg = pci_mmcfg_virt[cfg_num].cfg;
- 35       if (cfg->pci_segment_group_number != seg)
 - 36          continue;
  37       if ((cfg->start_bus_number <= bus) &&
- 38           (cfg->end_bus_number >= bus))
 - 38     (T) && (T)
 - 38     (T) && (F)
 - 38     (F) && (_)
 - 39          return pci_mmcfg_virt[cfg_num].virt;
  40    }
  41 
  42    /* Handle more broken MCFG tables on Asus etc.
  43       They only contain a single entry for bus 0-0. Assume
  44        this applies to all busses. */
  45    cfg = &pci_mmcfg_config[0];
  46    if (pci_mmcfg_config_num == 1 &&
  47       cfg->pci_segment_group_number == 0 &&
- 48       (cfg->start_bus_number | cfg->end_bus_number) == 0)
 - 48   T && T && T
 - 48   T && T && F
 - 48   T && F && _
 - 48   F && _ && _
 - 49       return pci_mmcfg_virt[0].virt;
  50 
  51    /* Fall back to type 0 */
 - 52    return NULL;
  53 }
  54 
 
- 55 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
  56 {
  57    char __iomem *addr;
- 58    if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
 - 58   T && T && (T)
 - 58   T && T && (F)
 - 58   T && F && (_)
 - 58   F && _ && (_)
- 58 ternary-?: __builtin_constant_p ( ( ( ( devfn ..
 - 59       return NULL;
  60    addr = get_virt(seg, bus);
- 61    if (!addr)
 - 62       return NULL;
 - 63     return addr + ((bus << 20) | (devfn << 12));
  64 }
  65 
 
- 66 static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
  67            unsigned int devfn, int reg, int len, u32 *value)
  68 {
  69    char __iomem *addr;
  70 
  71    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
- 72    if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
 - 73       return -EINVAL;
  74 
  75    addr = pci_dev_base(seg, bus, devfn);
- 76    if (!addr)
 - 77       return pci_conf1_read(seg,bus,devfn,reg,len,value);
  78 
    79    switch (len) {
 - 80    case 1:
  81       *value = readb(addr + reg);
 - 82       break;
 - 83    case 2:
  84       *value = readw(addr + reg);
 - 85       break;
 - 86    case 4:
  87       *value = readl(addr + reg);
 - 88       break;
  89    }
  90 
 - 91    return 0;
  92 }
  93 
 
- 94 static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
  95             unsigned int devfn, int reg, int len, u32 value)
  96 {
  97    char __iomem *addr;
  98 
  99    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
- 100    if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
 - 101       return -EINVAL;
  102 
  103    addr = pci_dev_base(seg, bus, devfn);
- 104    if (!addr)
 - 105       return pci_conf1_write(seg,bus,devfn,reg,len,value);
  106 
    107    switch (len) {
 - 108    case 1:
  109       writeb(value, addr + reg);
 - 110       break;
 - 111    case 2:
  112       writew(value, addr + reg);
 - 113       break;
 - 114    case 4:
  115       writel(value, addr + reg);
 - 116       break;
  117    }
  118 
 - 119    return 0;
  120 }
  121 
  122 static struct pci_raw_ops pci_mmcfg = {
  123    .read =      pci_mmcfg_read,
  124    .write =   pci_mmcfg_write,
  125 };
  126 
  127 /* K8 systems have some devices (typically in the builtin northbridge)
  128    that are only accessible using type1
  129    Normally this can be expressed in the MCFG by not listing them
  130    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
  131    Instead try to discover all devices on bus 0 that are unreachable using MM
  132    and fallback for them.
  133    We only do this for bus 0/seg 0 */
 
- 134 static __init void unreachable_devices(void)
  135 {
  136    int i;
- 137    for (i = 0; i < 32; i++) {
  138       u32 val1;
  139       char __iomem *addr;
  140 
  141       pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
- 142       if (val1 == 0xffffffff)
 - 143          continue;
  144       addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
- 145       if (addr == NULL|| readl(addr) != val1) {
 - 145     T || _
 - 145     F || T
 - 145     F || F
  146          set_bit(i, &fallback_slots);
  147       }
  148    }
  149 }
  150 
 
  151 static int __init pci_mmcfg_init(void)
  152 {
  153    int i;
  154 
- 155    if ((pci_probe & PCI_PROBE_MMCONF) == 0)
 - 156       return 0;
  157 
  158    acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
  159    if ((pci_mmcfg_config_num == 0) ||
  160        (pci_mmcfg_config == NULL) ||
- 161        (pci_mmcfg_config[0].base_address == 0))
   161   (T) || (_) || (_)
 - 161   (F) || (T) || (_)
 - 161   (F) || (F) || (T)
 - 161   (F) || (F) || (F)
   162       return 0;
  163 
  164    /* RED-PEN i386 doesn't do _nocache right now */
  165    pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
- 166    if (pci_mmcfg_virt == NULL) {
  167       printk("PCI: Can not allocate memory for mmconfig structures\n");
 - 168       return 0;
  169    }
- 170    for (i = 0; i < pci_mmcfg_config_num; ++i) {
  171       pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
  172       pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
- 173       if (!pci_mmcfg_virt[i].virt) {
  174          printk("PCI: Cannot map mmconfig aperture for segment %d\n",
  175                 pci_mmcfg_config[i].pci_segment_group_number);
 - 176          return 0;
  177       }
  178       printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
  179    }
  180 
  181    unreachable_devices();
  182 
  183    raw_pci_ops = &pci_mmcfg;
  184    pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
  185 
 - 186    return 0;
  187 }
  188 
  189 arch_initcall(pci_mmcfg_init);
***TER 5% (5/96) of SOURCE FILE mmconfig.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top