/*
 * AMD K8 NUMA support.
 * Discover the memory map and associated nodes.
 *
 * This version reads it directly from the K8 northbridge.
 *
 * Copyright 2002,2003 Andi Kleen, SuSE Labs.
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/nodemask.h>
#include <asm/io.h>
#include <linux/pci_ids.h>
#include <linux/acpi.h>
#include <asm/types.h>
#include <asm/mmzone.h>
#include <asm/proto.h>
#include <asm/e820.h>
#include <asm/pci-direct.h>
#include <asm/numa.h>
#include <asm/mpspec.h>
#include <asm/apic.h>
#include <asm/k8.h>

static __init int find_northbridge(void)
{
	int num;

	for (num = 0; num < 32; num++) {
		u32 header;

		header = read_pci_config(0, num, 0, 0x00);
		if (header != (PCI_VENDOR_ID_AMD | (0x1100<<16)) &&
			header != (PCI_VENDOR_ID_AMD | (0x1200<<16)) &&
			header != (PCI_VENDOR_ID_AMD | (0x1300<<16)))
			continue;

		header = read_pci_config(0, num, 1, 0x00);
		if (header != (PCI_VENDOR_ID_AMD | (0x1101<<16)) &&
			header != (PCI_VENDOR_ID_AMD | (0x1201<<16)) &&
			header != (PCI_VENDOR_ID_AMD | (0x1301<<16)))
			continue;
		return num;
	}

	return -1;
}

static __init void early_get_boot_cpu_id(void)
{
	/*
	 * need to get boot_cpu_id so can use that to create apicid_to_node
	 * in k8_scan_nodes()
	 */
	/*
	 * Find possible boot-time SMP configuration:
	 */
	early_find_smp_config();
#ifdef CONFIG_ACPI
	/*
	 * Read APIC information from ACPI tables.
	 */
	early_acpi_boot_init();
#endif
	/*
	 * get boot-time SMP configuration:
	 */
	if (smp_found_config)
		early_get_smp_config();
	early_init_lapic_mapping();
}

int __init k8_scan_nodes(unsigned long start, unsigned long end)
{
	unsigned long prevbase;
	struct bootnode nodes[8];
	int nodeid, i, nb;
	unsigned char nodeids[8];
	int found = 0;
	u32 reg;
	unsigned numnodes;
	unsigned cores;
	unsigned bits;
	int j;
	unsigned apicid_base;

	if (!early_pci_allowed())
		return -1;

	nb = find_northbridge();
	if (nb < 0)
		return nb;

	printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb);

	reg = read_pci_config(0, nb, 0, 0x60);
	numnodes = ((reg >> 4) & 0xF) + 1;
	if (numnodes <= 1)
		return -1;

	printk(KERN_INFO "Number of nodes %d\n", numnodes);

	memset(&nodes, 0, sizeof(nodes));
	prevbase = 0;
	for (i = 0; i < 8; i++) {
		unsigned long base, limit;
		u32 nodeid;

		base = read_pci_config(0, nb, 1, 0x40 + i*8);
		limit = read_pci_config(0, nb, 1, 0x44 + i*8);

		nodeid = limit & 7;
		nodeids[i] = nodeid;
		if ((base & 3) == 0) {
			if (i < numnodes)
				printk("Skipping disabled node %d\n", i);
			continue;
		}
		if (nodeid >= numnodes) {
			printk("Ignoring excess node %d (%lx:%lx)\n", nodeid,
			       base, limit);
			continue;
		}

		if (!limit) {
			printk(KERN_INFO "Skipping node entry %d (base %lx)\n",
			       i, base);
			continue;
		}
		if ((base >> 8) & 3 || (limit >> 8) & 3) {
			printk(KERN_ERR "Node %d using interleaving mode %lx/%lx\n",
			       nodeid, (base>>8)&3, (limit>>8) & 3);
			return -1;
		}
		if (node_isset(nodeid, node_possible_map)) {
			printk(KERN_INFO "Node %d already present. Skipping\n",
			       nodeid);
			continue;
		}

		limit >>= 16;
		limit <<= 24;
		limit |= (1<<24)-1;
		limit++;

		if (limit > end_pfn << PAGE_SHIFT)
			limit = end_pfn << PAGE_SHIFT;
		if (limit <= base)
			continue;

		base >>= 16;
		base <<= 24;

		if (base < start)
			base = start;
		if (limit > end)
			limit = end;
		if (limit == base) {
			printk(KERN_ERR "Empty node %d\n", nodeid);
			continue;
		}
		if (limit < base) {
			printk(KERN_ERR "Node %d bogus settings %lx-%lx.\n",
			       nodeid, base, limit);
			continue;
		}

		/* Could sort here, but pun for now. Should not happen anyroads. */
		if (prevbase > base) {
			printk(KERN_ERR "Node map not sorted %lx,%lx\n",
			       prevbase, base);
			return -1;
		}

		printk(KERN_INFO "Node %d MemBase %016lx Limit %016lx\n",
		       nodeid, base, limit);

		found++;

		nodes[nodeid].start = base;
		nodes[nodeid].end = limit;
		e820_register_active_regions(nodeid,
				nodes[nodeid].start >> PAGE_SHIFT,
				nodes[nodeid].end >> PAGE_SHIFT);

		prevbase = base;

		node_set(nodeid, node_possible_map);
	}

	if (!found)
		return -1;

	memnode_shift = compute_hash_shift(nodes, 8, NULL);
	if (memnode_shift < 0) {
		printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
		return -1;
	}
	printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift);

	/* use the coreid bits from early_identify_cpu */
	bits = boot_cpu_data.x86_coreid_bits;
	cores = (1<<bits);
	apicid_base = 0;
	/* need to get boot_cpu_id early for system with apicid lifting */
	early_get_boot_cpu_id();
	if (boot_cpu_physical_apicid > 0) {
		printk(KERN_INFO "BSP APIC ID: %02x\n",
				 boot_cpu_physical_apicid);
		apicid_base = boot_cpu_physical_apicid;
	}

	for (i = 0; i < 8; i++) {
		if (nodes[i].start != nodes[i].end) {
			nodeid = nodeids[i];
			for (j = apicid_base; j < cores + apicid_base; j++)
				apicid_to_node[(nodeid << bits) + j] = i;
			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
		}
	}

	numa_init_array();
	return 0;
}
