arch/x86/events/intel/uncore_snbep.c

Source file repositories/reference/linux-study-clean/arch/x86/events/intel/uncore_snbep.c

File Facts

System
Linux kernel
Corpus path
arch/x86/events/intel/uncore_snbep.c
Extension
.c
Size
208164 bytes
Lines
6995
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static struct pci_driver snbep_uncore_pci_driver = {
	.name		= "snbep_uncore",
	.id_table	= snbep_uncore_pci_ids,
};

#define NODE_ID_MASK	0x7

/* Each three bits from 0 to 23 of GIDNIDMAP register correspond Node ID. */
#define GIDNIDMAP(config, id)	(((config) >> (3 * (id))) & 0x7)

static int upi_nodeid_groupid(struct pci_dev *ubox_dev, int nodeid_loc, int idmap_loc,
			      int *nodeid, int *groupid)
{
	int ret;

	/* get the Node ID of the local register */
	ret = pci_read_config_dword(ubox_dev, nodeid_loc, nodeid);
	if (ret)
		goto err;

	*nodeid = *nodeid & NODE_ID_MASK;
	/* get the Node ID mapping */
	ret = pci_read_config_dword(ubox_dev, idmap_loc, groupid);
	if (ret)
		goto err;
err:
	return ret;
}

static int topology_gidnid_map(int nodeid, u32 gidnid)
{
	int i, die_id = -1;

	/*
	 * every three bits in the Node ID mapping register maps
	 * to a particular node.
	 */
	for (i = 0; i < 8; i++) {
		if (nodeid == GIDNIDMAP(gidnid, i)) {
			if (topology_max_dies_per_package() > 1)
				die_id = i;
			else
				die_id = topology_phys_to_logical_pkg(i);
			if (die_id < 0)
				die_id = -ENODEV;
			break;
		}
	}

	return die_id;
}

/*
 * build pci bus to socket mapping
 */
static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool reverse)
{
	struct pci_dev *ubox_dev = NULL;
	int i, bus, nodeid, segment, die_id;
	struct pci2phy_map *map;
	int err = 0;
	u32 config = 0;

	while (1) {
		/* find the UBOX device */
		ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, ubox_dev);
		if (!ubox_dev)
			break;
		bus = ubox_dev->bus->number;
		/*
		 * The nodeid and idmap registers only contain enough
		 * information to handle 8 nodes.  On systems with more
		 * than 8 nodes, we need to rely on NUMA information,
		 * filled in from BIOS supplied information, to determine
		 * the topology.
		 */
		if (nr_node_ids <= 8) {
			err = upi_nodeid_groupid(ubox_dev, nodeid_loc, idmap_loc,
						 &nodeid, &config);
			if (err)
				break;

			segment = pci_domain_nr(ubox_dev->bus);
			raw_spin_lock(&pci2phy_map_lock);
			map = __find_pci2phy_map(segment);
			if (!map) {
				raw_spin_unlock(&pci2phy_map_lock);
				err = -ENOMEM;
				break;
			}

Annotation

Implementation Notes