arch/powerpc/platforms/powernv/pci-ioda.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powernv/pci-ioda.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/powernv/pci-ioda.c
Extension
.c
Size
75067 bytes
Lines
2750
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

if (!strncmp(str, "nobypass", 8)) {
			pnv_iommu_bypass_disabled = true;
			pr_info("PowerNV: IOMMU bypass window disabled.\n");
			break;
		}
		str += strcspn(str, ",");
		if (*str == ',')
			str++;
	}

	return 0;
}
early_param("iommu", iommu_setup);

static int __init pci_reset_phbs_setup(char *str)
{
	pci_reset_phbs = true;
	return 0;
}

early_param("ppc_pci_reset_phbs", pci_reset_phbs_setup);

static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
{
	s64 rc;

	phb->ioda.pe_array[pe_no].phb = phb;
	phb->ioda.pe_array[pe_no].pe_number = pe_no;
	phb->ioda.pe_array[pe_no].dma_setup_done = false;

	/*
	 * Clear the PE frozen state as it might be put into frozen state
	 * in the last PCI remove path. It's not harmful to do so when the
	 * PE is already in unfrozen state.
	 */
	rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
				       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
	if (rc != OPAL_SUCCESS && rc != OPAL_UNSUPPORTED)
		pr_warn("%s: Error %lld unfreezing PHB#%x-PE#%x\n",
			__func__, rc, phb->hose->global_number, pe_no);

	return &phb->ioda.pe_array[pe_no];
}

static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
{
	if (!(pe_no >= 0 && pe_no < phb->ioda.total_pe_num)) {
		pr_warn("%s: Invalid PE %x on PHB#%x\n",
			__func__, pe_no, phb->hose->global_number);
		return;
	}

	mutex_lock(&phb->ioda.pe_alloc_mutex);
	if (test_and_set_bit(pe_no, phb->ioda.pe_alloc))
		pr_debug("%s: PE %x was reserved on PHB#%x\n",
			 __func__, pe_no, phb->hose->global_number);
	mutex_unlock(&phb->ioda.pe_alloc_mutex);

	pnv_ioda_init_pe(phb, pe_no);
}

struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb, int count)
{
	struct pnv_ioda_pe *ret = NULL;
	int run = 0, pe, i;

	mutex_lock(&phb->ioda.pe_alloc_mutex);

	/* scan backwards for a run of @count cleared bits */
	for (pe = phb->ioda.total_pe_num - 1; pe >= 0; pe--) {
		if (test_bit(pe, phb->ioda.pe_alloc)) {
			run = 0;
			continue;
		}

		run++;
		if (run == count)
			break;
	}
	if (run != count)
		goto out;

	for (i = pe; i < pe + count; i++) {
		set_bit(i, phb->ioda.pe_alloc);
		pnv_ioda_init_pe(phb, i);
	}
	ret = &phb->ioda.pe_array[pe];

out:
	mutex_unlock(&phb->ioda.pe_alloc_mutex);

Annotation

Implementation Notes