⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iommu.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	tbl->it_base   = 0;	tbl->it_blocksize  = 16;	tbl->it_type = TCE_PCI;	tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;	tbl->it_size = size >> IOMMU_PAGE_SHIFT;}static void pci_dma_bus_setup_pSeries(struct pci_bus *bus){	struct device_node *dn;	struct iommu_table *tbl;	struct device_node *isa_dn, *isa_dn_orig;	struct device_node *tmp;	struct pci_dn *pci;	int children;	dn = pci_bus_to_OF_node(bus);	DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);	if (bus->self) {		/* This is not a root bus, any setup will be done for the		 * device-side of the bridge in iommu_dev_setup_pSeries().		 */		return;	}	pci = PCI_DN(dn);	/* Check if the ISA bus on the system is under	 * this PHB.	 */	isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");	while (isa_dn && isa_dn != dn)		isa_dn = isa_dn->parent;	if (isa_dn_orig)		of_node_put(isa_dn_orig);	/* Count number of direct PCI children of the PHB. */	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)		children++;	DBG("Children: %d\n", children);	/* Calculate amount of DMA window per slot. Each window must be	 * a power of two (due to pci_alloc_consistent requirements).	 *	 * Keep 256MB aside for PHBs with ISA.	 */	if (!isa_dn) {		/* No ISA/IDE - just set window size and return */		pci->phb->dma_window_size = 0x80000000ul; /* To be divided */		while (pci->phb->dma_window_size * children > 0x80000000ul)			pci->phb->dma_window_size >>= 1;		DBG("No ISA/IDE, window size is 0x%lx\n",			pci->phb->dma_window_size);		pci->phb->dma_window_base_cur = 0;		return;	}	/* If we have ISA, then we probably have an IDE	 * controller too. Allocate a 128MB table but	 * skip the first 128MB to avoid stepping on ISA	 * space.	 */	pci->phb->dma_window_size = 0x8000000ul;	pci->phb->dma_window_base_cur = 0x8000000ul;	tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,			   pci->phb->node);	iommu_table_setparms(pci->phb, dn, tbl);	pci->iommu_table = iommu_init_table(tbl, pci->phb->node);	/* Divide the rest (1.75GB) among the children */	pci->phb->dma_window_size = 0x80000000ul;	while (pci->phb->dma_window_size * children > 0x70000000ul)		pci->phb->dma_window_size >>= 1;	DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);}static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus){	struct iommu_table *tbl;	struct device_node *dn, *pdn;	struct pci_dn *ppci;	const void *dma_window = NULL;	dn = pci_bus_to_OF_node(bus);	DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);	/* Find nearest ibm,dma-window, walking up the device tree */	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {		dma_window = of_get_property(pdn, "ibm,dma-window", NULL);		if (dma_window != NULL)			break;	}	if (dma_window == NULL) {		DBG("  no ibm,dma-window property !\n");		return;	}	ppci = PCI_DN(pdn);	DBG("  parent is %s, iommu_table: 0x%p\n",	    pdn->full_name, ppci->iommu_table);	if (!ppci->iommu_table) {		/* Bussubno hasn't been copied yet.		 * Do it now because iommu_table_setparms_lpar needs it.		 */		ppci->bussubno = bus->number;		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,				   ppci->phb->node);		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);		DBG("  created table: %p\n", ppci->iommu_table);	}	if (pdn != dn)		PCI_DN(dn)->iommu_table = ppci->iommu_table;}static void pci_dma_dev_setup_pSeries(struct pci_dev *dev){	struct device_node *dn;	struct iommu_table *tbl;	DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));	dn = dev->dev.archdata.of_node;	/* If we're the direct child of a root bus, then we need to allocate	 * an iommu table ourselves. The bus setup code should have setup	 * the window sizes already.	 */	if (!dev->bus->self) {		struct pci_controller *phb = PCI_DN(dn)->phb;		DBG(" --> first child, no bridge. Allocating iommu table.\n");		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,				   phb->node);		iommu_table_setparms(phb, dn, tbl);		PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);		dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;		return;	}	/* If this device is further down the bus tree, search upwards until	 * an already allocated iommu table is found and use that.	 */	while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL)		dn = dn->parent;	if (dn && PCI_DN(dn))		dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;	else		printk(KERN_WARNING "iommu: Device %s has no iommu table\n",		       pci_name(dev));}static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev){	struct device_node *pdn, *dn;	struct iommu_table *tbl;	const void *dma_window = NULL;	struct pci_dn *pci;	DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));	/* dev setup for LPAR is a little tricky, since the device tree might	 * contain the dma-window properties per-device and not neccesarily	 * for the bus. So we need to search upwards in the tree until we	 * either hit a dma-window property, OR find a parent with a table	 * already allocated.	 */	dn = pci_device_to_OF_node(dev);	DBG("  node is %s\n", dn->full_name);	for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;	     pdn = pdn->parent) {		dma_window = of_get_property(pdn, "ibm,dma-window", NULL);		if (dma_window)			break;	}	if (!pdn || !PCI_DN(pdn)) {		printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "		       "no DMA window found for pci dev=%s dn=%s\n",				 pci_name(dev), dn? dn->full_name : "<null>");		return;	}	DBG("  parent is %s\n", pdn->full_name);	/* Check for parent == NULL so we don't try to setup the empty EADS	 * slots on POWER4 machines.	 */	if (dma_window == NULL || pdn->parent == NULL) {		DBG("  no dma window for device, linking to parent\n");		dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;		return;	}	pci = PCI_DN(pdn);	if (!pci->iommu_table) {		/* iommu_table_setparms_lpar needs bussubno. */		pci->bussubno = pci->phb->bus->number;		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,				   pci->phb->node);		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);		DBG("  created table: %p\n", pci->iommu_table);	} else {		DBG("  found DMA window, table: %p\n", pci->iommu_table);	}	dev->dev.archdata.dma_data = pci->iommu_table;}#else  /* CONFIG_PCI */#define pci_dma_bus_setup_pSeries	NULL#define pci_dma_dev_setup_pSeries	NULL#define pci_dma_bus_setup_pSeriesLP	NULL#define pci_dma_dev_setup_pSeriesLP	NULL#endif /* !CONFIG_PCI */static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node){	int err = NOTIFY_OK;	struct device_node *np = node;	struct pci_dn *pci = PCI_DN(np);	switch (action) {	case PSERIES_RECONFIG_REMOVE:		if (pci && pci->iommu_table &&		    of_get_property(np, "ibm,dma-window", NULL))			iommu_free_table(np);		break;	default:		err = NOTIFY_DONE;		break;	}	return err;}static struct notifier_block iommu_reconfig_nb = {	.notifier_call = iommu_reconfig_notifier,};/* These are called very early. */void iommu_init_early_pSeries(void){	if (of_chosen && of_get_property(of_chosen, "linux,iommu-off", NULL)) {		/* Direct I/O, IOMMU off */		ppc_md.pci_dma_dev_setup = NULL;		ppc_md.pci_dma_bus_setup = NULL;		set_pci_dma_ops(&dma_direct_ops);		return;	}	if (firmware_has_feature(FW_FEATURE_LPAR)) {		if (firmware_has_feature(FW_FEATURE_MULTITCE)) {			ppc_md.tce_build = tce_buildmulti_pSeriesLP;			ppc_md.tce_free	 = tce_freemulti_pSeriesLP;		} else {			ppc_md.tce_build = tce_build_pSeriesLP;			ppc_md.tce_free	 = tce_free_pSeriesLP;		}		ppc_md.tce_get   = tce_get_pSeriesLP;		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;	} else {		ppc_md.tce_build = tce_build_pSeries;		ppc_md.tce_free  = tce_free_pSeries;		ppc_md.tce_get   = tce_get_pseries;		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries;		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries;	}	pSeries_reconfig_notifier_register(&iommu_reconfig_nb);	set_pci_dma_ops(&dma_iommu_ops);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -