arch/powerpc/kernel/eeh_cache.c

Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/eeh_cache.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kernel/eeh_cache.c
Extension
.c
Size
8003 bytes
Lines
289
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source 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

struct pci_io_addr_range {
	struct rb_node rb_node;
	resource_size_t addr_lo;
	resource_size_t addr_hi;
	struct eeh_dev *edev;
	struct pci_dev *pcidev;
	unsigned long flags;
};

static struct pci_io_addr_cache {
	struct rb_root rb_root;
	spinlock_t piar_lock;
} pci_io_addr_cache_root;

static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr)
{
	struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;

	while (n) {
		struct pci_io_addr_range *piar;
		piar = rb_entry(n, struct pci_io_addr_range, rb_node);

		if (addr < piar->addr_lo)
			n = n->rb_left;
		else if (addr > piar->addr_hi)
			n = n->rb_right;
		else
			return piar->edev;
	}

	return NULL;
}

/**
 * eeh_addr_cache_get_dev - Get device, given only address
 * @addr: mmio (PIO) phys address or i/o port number
 *
 * Given an mmio phys address, or a port number, find a pci device
 * that implements this address.  I/O port numbers are assumed to be offset
 * from zero (that is, they do *not* have pci_io_addr added in).
 * It is safe to call this function within an interrupt.
 */
struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr)
{
	struct eeh_dev *edev;
	unsigned long flags;

	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
	edev = __eeh_addr_cache_get_device(addr);
	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
	return edev;
}

#ifdef DEBUG
/*
 * Handy-dandy debug print routine, does nothing more
 * than print out the contents of our addr cache.
 */
static void eeh_addr_cache_print(struct pci_io_addr_cache *cache)
{
	struct rb_node *n;
	int cnt = 0;

	n = rb_first(&cache->rb_root);
	while (n) {
		struct pci_io_addr_range *piar;
		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
		pr_info("PCI: %s addr range %d [%pap-%pap]: %s\n",
		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
		       &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
		cnt++;
		n = rb_next(n);
	}
}
#endif

/* Insert address range into the rb tree. */
static struct pci_io_addr_range *
eeh_addr_cache_insert(struct pci_dev *dev, resource_size_t alo,
		      resource_size_t ahi, unsigned long flags)
{
	struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
	struct rb_node *parent = NULL;
	struct pci_io_addr_range *piar;

	/* Walk tree, find a place to insert into tree */
	while (*p) {
		parent = *p;
		piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
		if (ahi < piar->addr_lo) {

Annotation

Implementation Notes