mmconfig.c 6.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
 * 
 * This is an 64bit optimized version that always keeps the full mmconfig
 * space mapped. This allows lockless config space operation.
 */

#include <linux/pci.h>
#include <linux/init.h>
10
#include <linux/acpi.h>
11
#include <linux/bitmap.h>
12 13
#include <asm/e820.h>

L
Linus Torvalds 已提交
14 15
#include "pci.h"

16 17 18 19
/* aperture is up to 256MB but BIOS may reserve less */
#define MMCONFIG_APER_MIN	(2 * 1024*1024)
#define MMCONFIG_APER_MAX	(256 * 1024*1024)

20 21 22
/* Verify the first 16 busses. We assume that systems with more busses
   get MCFG right. */
#define MAX_CHECK_BUS 16
L
Linus Torvalds 已提交
23

24
static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
25

L
Linus Torvalds 已提交
26
/* Static virtual mapping of the MMCONFIG aperture */
27 28
struct mmcfg_virt {
	struct acpi_table_mcfg_config *cfg;
29
	char __iomem *virt;
30 31
};
static struct mmcfg_virt *pci_mmcfg_virt;
L
Linus Torvalds 已提交
32

33
static char __iomem *get_virt(unsigned int seg, unsigned bus)
L
Linus Torvalds 已提交
34
{
35 36 37 38 39
	int cfg_num = -1;
	struct acpi_table_mcfg_config *cfg;

	while (1) {
		++cfg_num;
40 41
		if (cfg_num >= pci_mmcfg_config_num)
			break;
42 43 44 45 46 47 48
		cfg = pci_mmcfg_virt[cfg_num].cfg;
		if (cfg->pci_segment_group_number != seg)
			continue;
		if ((cfg->start_bus_number <= bus) &&
		    (cfg->end_bus_number >= bus))
			return pci_mmcfg_virt[cfg_num].virt;
	}
49 50 51 52 53 54 55 56

	/* Handle more broken MCFG tables on Asus etc.
	   They only contain a single entry for bus 0-0. Assume
 	   this applies to all busses. */
	cfg = &pci_mmcfg_config[0];
	if (pci_mmcfg_config_num == 1 &&
		cfg->pci_segment_group_number == 0 &&
		(cfg->start_bus_number | cfg->end_bus_number) == 0)
57
		return pci_mmcfg_virt[0].virt;
58 59

	/* Fall back to type 0 */
60
	return NULL;
61 62
}

63
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
64
{
65
	char __iomem *addr;
66 67
	if (seg == 0 && bus < MAX_CHECK_BUS &&
		test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
68 69
		return NULL;
	addr = get_virt(seg, bus);
70 71 72
	if (!addr)
		return NULL;
 	return addr + ((bus << 20) | (devfn << 12));
L
Linus Torvalds 已提交
73 74 75 76 77
}

static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
			  unsigned int devfn, int reg, int len, u32 *value)
{
78
	char __iomem *addr;
L
Linus Torvalds 已提交
79

80
	/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
81
	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
82
		*value = -1;
L
Linus Torvalds 已提交
83
		return -EINVAL;
84
	}
L
Linus Torvalds 已提交
85

86 87 88 89
	addr = pci_dev_base(seg, bus, devfn);
	if (!addr)
		return pci_conf1_read(seg,bus,devfn,reg,len,value);

L
Linus Torvalds 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	switch (len) {
	case 1:
		*value = readb(addr + reg);
		break;
	case 2:
		*value = readw(addr + reg);
		break;
	case 4:
		*value = readl(addr + reg);
		break;
	}

	return 0;
}

static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
			   unsigned int devfn, int reg, int len, u32 value)
{
108
	char __iomem *addr;
L
Linus Torvalds 已提交
109

110
	/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
L
Linus Torvalds 已提交
111 112 113
	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
		return -EINVAL;

114 115 116 117
	addr = pci_dev_base(seg, bus, devfn);
	if (!addr)
		return pci_conf1_write(seg,bus,devfn,reg,len,value);

L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
	switch (len) {
	case 1:
		writeb(value, addr + reg);
		break;
	case 2:
		writew(value, addr + reg);
		break;
	case 4:
		writel(value, addr + reg);
		break;
	}

	return 0;
}

static struct pci_raw_ops pci_mmcfg = {
	.read =		pci_mmcfg_read,
	.write =	pci_mmcfg_write,
};

138 139 140 141 142
/* K8 systems have some devices (typically in the builtin northbridge)
   that are only accessible using type1
   Normally this can be expressed in the MCFG by not listing them
   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
   Instead try to discover all devices on bus 0 that are unreachable using MM
143
   and fallback for them. */
144 145
static __init void unreachable_devices(void)
{
146 147
	int i, k;
	/* Use the max bus number from ACPI here? */
148
	for (k = 0; k < MAX_CHECK_BUS; k++) {
149 150 151 152 153 154 155 156 157 158
		for (i = 0; i < 32; i++) {
			u32 val1;
			char __iomem *addr;

			pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
			if (val1 == 0xffffffff)
				continue;
			addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
			if (addr == NULL|| readl(addr) != val1) {
				set_bit(i + 32*k, fallback_slots);
159 160
				printk(KERN_NOTICE "PCI: No mmconfig possible"
				       " on device %02x:%02x\n", k, i);
161
			}
162 163 164 165
		}
	}
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
static __init void pci_mmcfg_insert_resources(void)
{
#define PCI_MMCFG_RESOURCE_NAME_LEN 19
	int i;
	struct resource *res;
	char *names;
	unsigned num_buses;

	res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
			pci_mmcfg_config_num, GFP_KERNEL);

	if (!res) {
		printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
		return;
	}

	names = (void *)&res[pci_mmcfg_config_num];
	for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
		num_buses = pci_mmcfg_config[i].end_bus_number -
		    pci_mmcfg_config[i].start_bus_number + 1;
		res->name = names;
		snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
			pci_mmcfg_config[i].pci_segment_group_number);
		res->start = pci_mmcfg_config[i].base_address;
		res->end = res->start + (num_buses << 20) - 1;
		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
		insert_resource(&iomem_resource, res);
		names += PCI_MMCFG_RESOURCE_NAME_LEN;
	}
}

197
void __init pci_mmcfg_init(int type)
L
Linus Torvalds 已提交
198
{
199 200
	int i;

201
	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
202
		return;
203 204 205 206 207

	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
	if ((pci_mmcfg_config_num == 0) ||
	    (pci_mmcfg_config == NULL) ||
	    (pci_mmcfg_config[0].base_address == 0))
208
		return;
L
Linus Torvalds 已提交
209

210 211 212
	/* Only do this check when type 1 works. If it doesn't work
           assume we run on a Mac and always use MCFG */
	if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address,
213 214 215 216 217 218 219 220
			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
			E820_RESERVED)) {
		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
				pci_mmcfg_config[0].base_address);
		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
		return;
	}

221 222
	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
	if (pci_mmcfg_virt == NULL) {
223
		printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
224
		return;
225 226 227
	}
	for (i = 0; i < pci_mmcfg_config_num; ++i) {
		pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
228 229
		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
							 MMCONFIG_APER_MAX);
230
		if (!pci_mmcfg_virt[i].virt) {
231 232
			printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
					"segment %d\n",
233
			       pci_mmcfg_config[i].pci_segment_group_number);
234
			return;
235 236 237
		}
		printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
	}
L
Linus Torvalds 已提交
238

239
	unreachable_devices();
240
	pci_mmcfg_insert_resources();
241

L
Linus Torvalds 已提交
242 243 244
	raw_pci_ops = &pci_mmcfg;
	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
}