arch/powerpc/sysdev/mpic_u3msi.c

Source file repositories/reference/linux-study-clean/arch/powerpc/sysdev/mpic_u3msi.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/sysdev/mpic_u3msi.c
Extension
.c
Size
5180 bytes
Lines
197
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

find_u4_magic_addr(pdev, 0) == 0) {
		pr_debug("u3msi: no magic address found for %s\n",
			 pci_name(pdev));
		return -ENXIO;
	}

	msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
		if (hwirq < 0) {
			pr_debug("u3msi: failed allocating hwirq\n");
			return hwirq;
		}

		addr = find_ht_magic_addr(pdev, hwirq);
		if (addr == 0)
			addr = find_u4_magic_addr(pdev, hwirq);
		msg.address_lo = addr & 0xFFFFFFFF;
		msg.address_hi = addr >> 32;

		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
		if (!virq) {
			pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
			msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
			return -ENOSPC;
		}

		irq_set_msi_desc(virq, entry);
		irq_set_chip(virq, &mpic_u3msi_chip);
		irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);

		pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
			  virq, hwirq, (unsigned long)addr);

		printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
			  virq, hwirq, (unsigned long)addr);
		msg.data = hwirq;
		pci_write_msi_msg(virq, &msg);

		hwirq++;
	}

	return 0;
}

int __init mpic_u3msi_init(struct mpic *mpic)
{
	int rc;
	struct pci_controller *phb;

	rc = mpic_msi_init_allocator(mpic);
	if (rc) {
		pr_debug("u3msi: Error allocating bitmap!\n");
		return rc;
	}

	pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");

	BUG_ON(msi_mpic);
	msi_mpic = mpic;

	list_for_each_entry(phb, &hose_list, list_node) {
		WARN_ON(phb->controller_ops.setup_msi_irqs);
		phb->controller_ops.setup_msi_irqs = u3msi_setup_msi_irqs;
		phb->controller_ops.teardown_msi_irqs = u3msi_teardown_msi_irqs;
	}

	return 0;
}

Annotation

Implementation Notes