Exemple #1
0
/* 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
   and fallback for them. */
static __init void unreachable_devices(void)
{
	int i, k;
	unsigned long flags;

	for (k = 0; k < MAX_CHECK_BUS; k++) {
		for (i = 0; i < 32; i++) {
			u32 val1;
			u32 addr;

			pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
			if (val1 == 0xffffffff)
				continue;

			/* Locking probably not needed, but safer */
			spin_lock_irqsave(&pci_config_lock, flags);
			addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
			if (addr != 0)
				pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
			if (addr == 0 ||
			    readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
				set_bit(i + 32*k, fallback_slots);
				printk(KERN_NOTICE
			"PCI: No mmconfig possible on %x:%x\n", k, i);
			}
			spin_unlock_irqrestore(&pci_config_lock, flags);
		}
	}
}
Exemple #2
0
static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
			  unsigned int devfn, int reg, int len, u32 *value)
{
	char __iomem *addr;

	/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
	if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
		return -EINVAL;

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

	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;
}
Exemple #3
0
static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
			  unsigned int devfn, int reg, int len, u32 *value)
{
	unsigned long flags;
	u32 base;

	if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
		return -EINVAL;

	base = get_base_addr(seg, bus, devfn);
	if (!base)
		return pci_conf1_read(seg,bus,devfn,reg,len,value);

	spin_lock_irqsave(&pci_config_lock, flags);

	pci_exp_set_dev_base(base, bus, devfn);

	switch (len) {
	case 1:
		*value = readb(mmcfg_virt_addr + reg);
		break;
	case 2:
		*value = readw(mmcfg_virt_addr + reg);
		break;
	case 4:
		*value = readl(mmcfg_virt_addr + reg);
		break;
	}

	spin_unlock_irqrestore(&pci_config_lock, flags);

	return 0;
}
Exemple #4
0
static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
	if (!value) 
		return -EINVAL;

	return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 4, value);
}
Exemple #5
0
static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
	int result; 
	u32 data;

	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 2, &data);

	*value = (u16)data;

	return result;
}
Exemple #6
0
static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
	int result; 
	u32 data;

	if (!value) 
		return -EINVAL;

	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 1, &data);

	*value = (u8)data;

	return result;
}
Exemple #7
0
/* 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
   and fallback for them.
   We only do this for bus 0/seg 0 */
static __init void unreachable_devices(void)
{
	int i;
	for (i = 0; i < 32; i++) {
		u32 val1;
		char __iomem *addr;

		pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
		if (val1 == 0xffffffff)
			continue;
		addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
		if (addr == NULL|| readl(addr) != val1) {
			set_bit(i, &fallback_slots);
		}
	}
}
Exemple #8
0
/* 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
   and fallback for them.
   We only do this for bus 0/seg 0 */
static __init void unreachable_devices(void)
{
	int i;
	unsigned long flags;

	for (i = 0; i < 32; i++) {
		u32 val1;
		u32 addr;

		pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
		if (val1 == 0xffffffff)
			continue;

		/* Locking probably not needed, but safer */
		spin_lock_irqsave(&pci_config_lock, flags);
		addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
		if (addr != 0)
			pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
		if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
			set_bit(i, fallback_slots);
		spin_unlock_irqrestore(&pci_config_lock, flags);
	}
}
Exemple #9
0
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
	return pci_conf1_read(pci_domain_nr(bus), bus->number,
	                      devfn, where, size, value);
}