Lines Matching +full:pci +full:- +full:domain
13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #define pr_fmt(fmt) "fsl-pamu-domain: %s: " fmt, __func__
52 return -ENOMEM; in iommu_init_mempool()
63 return -ENOMEM; in iommu_init_mempool()
71 u32 win_cnt = dma_domain->win_cnt; in get_phys_addr()
72 struct dma_window *win_ptr = &dma_domain->win_arr[0]; in get_phys_addr()
75 geom = &dma_domain->iommu_domain.geometry; in get_phys_addr()
77 if (!win_cnt || !dma_domain->geom_size) { in get_phys_addr()
78 pr_debug("Number of windows/geometry not configured for the domain\n"); in get_phys_addr()
87 subwin_size = dma_domain->geom_size >> ilog2(win_cnt); in get_phys_addr()
88 subwin_iova = iova & ~(subwin_size - 1); in get_phys_addr()
89 wnd = (subwin_iova - geom->aperture_start) >> ilog2(subwin_size); in get_phys_addr()
90 win_ptr = &dma_domain->win_arr[wnd]; in get_phys_addr()
93 if (win_ptr->valid) in get_phys_addr()
94 return win_ptr->paddr + (iova & (win_ptr->size - 1)); in get_phys_addr()
101 struct dma_window *sub_win_ptr = &dma_domain->win_arr[0]; in map_subwins()
105 for (i = 0; i < dma_domain->win_cnt; i++) { in map_subwins()
109 ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i, in map_subwins()
113 dma_domain->snoop_id, in map_subwins()
114 dma_domain->stash_id, in map_subwins()
132 struct dma_window *wnd = &dma_domain->win_arr[0]; in map_win()
133 phys_addr_t wnd_addr = dma_domain->iommu_domain.geometry.aperture_start; in map_win()
138 wnd->size, in map_win()
140 wnd->paddr >> PAMU_PAGE_SHIFT, in map_win()
141 dma_domain->snoop_id, dma_domain->stash_id, in map_win()
142 0, wnd->prot); in map_win()
153 if (dma_domain->win_cnt > 1) in map_liodn()
163 struct dma_window *wnd = &dma_domain->win_arr[wnd_nr]; in update_liodn()
167 if (dma_domain->win_cnt > 1) { in update_liodn()
168 ret = pamu_config_spaace(liodn, dma_domain->win_cnt, wnd_nr, in update_liodn()
169 wnd->size, in update_liodn()
171 wnd->paddr >> PAMU_PAGE_SHIFT, in update_liodn()
172 dma_domain->snoop_id, in update_liodn()
173 dma_domain->stash_id, in update_liodn()
175 wnd->prot); in update_liodn()
182 wnd_addr = dma_domain->iommu_domain.geometry.aperture_start; in update_liodn()
185 wnd->size, in update_liodn()
187 wnd->paddr >> PAMU_PAGE_SHIFT, in update_liodn()
188 dma_domain->snoop_id, dma_domain->stash_id, in update_liodn()
189 0, wnd->prot); in update_liodn()
207 if (!dma_domain->win_arr) { in update_liodn_stash()
211 return -EINVAL; in update_liodn_stash()
214 for (i = 0; i < dma_domain->win_cnt; i++) { in update_liodn_stash()
248 window_addr = geom_attr->aperture_start; in pamu_set_liodn()
249 window_size = dma_domain->geom_size; in pamu_set_liodn()
255 0, dma_domain->snoop_id, in pamu_set_liodn()
256 dma_domain->stash_id, win_cnt, 0); in pamu_set_liodn()
272 0, dma_domain->snoop_id, in pamu_set_liodn()
273 dma_domain->stash_id, in pamu_set_liodn()
293 if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) { in check_size()
295 return -EINVAL; in check_size()
299 if (iova & (size - 1)) { in check_size()
301 return -EINVAL; in check_size()
309 struct fsl_dma_domain *domain; in iommu_alloc_dma_domain() local
311 domain = kmem_cache_zalloc(fsl_pamu_domain_cache, GFP_KERNEL); in iommu_alloc_dma_domain()
312 if (!domain) in iommu_alloc_dma_domain()
315 domain->stash_id = ~(u32)0; in iommu_alloc_dma_domain()
316 domain->snoop_id = ~(u32)0; in iommu_alloc_dma_domain()
317 domain->win_cnt = pamu_get_max_subwin_cnt(); in iommu_alloc_dma_domain()
318 domain->geom_size = 0; in iommu_alloc_dma_domain()
320 INIT_LIST_HEAD(&domain->devices); in iommu_alloc_dma_domain()
322 spin_lock_init(&domain->domain_lock); in iommu_alloc_dma_domain()
324 return domain; in iommu_alloc_dma_domain()
331 list_del(&info->link); in remove_device_ref()
334 pamu_free_subwins(info->liodn); in remove_device_ref()
335 pamu_disable_liodn(info->liodn); in remove_device_ref()
338 info->dev->archdata.iommu_domain = NULL; in remove_device_ref()
348 spin_lock_irqsave(&dma_domain->domain_lock, flags); in detach_device()
349 /* Remove the device from the domain device list */ in detach_device()
350 list_for_each_entry_safe(info, tmp, &dma_domain->devices, link) { in detach_device()
351 if (!dev || (info->dev == dev)) in detach_device()
352 remove_device_ref(info, dma_domain->win_cnt); in detach_device()
354 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in detach_device()
364 * Check here if the device is already attached to domain or not. in attach_device()
365 * If the device is already attached to a domain detach it. in attach_device()
367 old_domain_info = dev->archdata.iommu_domain; in attach_device()
368 if (old_domain_info && old_domain_info->domain != dma_domain) { in attach_device()
370 detach_device(dev, old_domain_info->domain); in attach_device()
376 info->dev = dev; in attach_device()
377 info->liodn = liodn; in attach_device()
378 info->domain = dma_domain; in attach_device()
380 list_add(&info->link, &dma_domain->devices); in attach_device()
384 * LIODNs share the same domain in attach_device()
386 if (!dev->archdata.iommu_domain) in attach_device()
387 dev->archdata.iommu_domain = info; in attach_device()
391 static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain, in fsl_pamu_iova_to_phys() argument
394 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_iova_to_phys()
396 if (iova < domain->geometry.aperture_start || in fsl_pamu_iova_to_phys()
397 iova > domain->geometry.aperture_end) in fsl_pamu_iova_to_phys()
408 static void fsl_pamu_domain_free(struct iommu_domain *domain) in fsl_pamu_domain_free() argument
410 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_domain_free()
415 dma_domain->enabled = 0; in fsl_pamu_domain_free()
416 dma_domain->mapped = 0; in fsl_pamu_domain_free()
434 dma_domain->iommu_domain. geometry.aperture_start = 0; in fsl_pamu_domain_alloc()
435 dma_domain->iommu_domain.geometry.aperture_end = (1ULL << 36) - 1; in fsl_pamu_domain_alloc()
436 dma_domain->iommu_domain.geometry.force_aperture = true; in fsl_pamu_domain_alloc()
438 return &dma_domain->iommu_domain; in fsl_pamu_domain_alloc()
441 /* Configure geometry settings for all LIODNs associated with domain */
449 list_for_each_entry(info, &dma_domain->devices, link) { in pamu_set_domain_geometry()
450 ret = pamu_set_liodn(info->liodn, info->dev, dma_domain, in pamu_set_domain_geometry()
459 /* Update stash destination for all LIODNs associated with the domain */
465 list_for_each_entry(info, &dma_domain->devices, link) { in update_domain_stash()
466 ret = update_liodn_stash(info->liodn, dma_domain, val); in update_domain_stash()
474 /* Update domain mappings for all LIODNs associated with the domain */
480 list_for_each_entry(info, &dma_domain->devices, link) { in update_domain_mapping()
481 ret = update_liodn(info->liodn, dma_domain, wnd_nr); in update_domain_mapping()
493 list_for_each_entry(info, &dma_domain->devices, link) { in disable_domain_win()
494 if (dma_domain->win_cnt == 1 && dma_domain->enabled) { in disable_domain_win()
495 ret = pamu_disable_liodn(info->liodn); in disable_domain_win()
497 dma_domain->enabled = 0; in disable_domain_win()
499 ret = pamu_disable_spaace(info->liodn, wnd_nr); in disable_domain_win()
506 static void fsl_pamu_window_disable(struct iommu_domain *domain, u32 wnd_nr) in fsl_pamu_window_disable() argument
508 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_window_disable()
512 spin_lock_irqsave(&dma_domain->domain_lock, flags); in fsl_pamu_window_disable()
513 if (!dma_domain->win_arr) { in fsl_pamu_window_disable()
515 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_disable()
519 if (wnd_nr >= dma_domain->win_cnt) { in fsl_pamu_window_disable()
521 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_disable()
525 if (dma_domain->win_arr[wnd_nr].valid) { in fsl_pamu_window_disable()
528 dma_domain->win_arr[wnd_nr].valid = 0; in fsl_pamu_window_disable()
529 dma_domain->mapped--; in fsl_pamu_window_disable()
533 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_disable()
536 static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, in fsl_pamu_window_enable() argument
539 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_window_enable()
551 spin_lock_irqsave(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
552 if (!dma_domain->win_arr) { in fsl_pamu_window_enable()
554 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
555 return -ENODEV; in fsl_pamu_window_enable()
558 if (wnd_nr >= dma_domain->win_cnt) { in fsl_pamu_window_enable()
560 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
561 return -EINVAL; in fsl_pamu_window_enable()
564 win_size = dma_domain->geom_size >> ilog2(dma_domain->win_cnt); in fsl_pamu_window_enable()
567 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
568 return -EINVAL; in fsl_pamu_window_enable()
571 if (dma_domain->win_cnt == 1) { in fsl_pamu_window_enable()
572 if (dma_domain->enabled) { in fsl_pamu_window_enable()
574 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
575 return -EBUSY; in fsl_pamu_window_enable()
578 ret = check_size(size, domain->geometry.aperture_start); in fsl_pamu_window_enable()
581 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
582 return -EINVAL; in fsl_pamu_window_enable()
586 wnd = &dma_domain->win_arr[wnd_nr]; in fsl_pamu_window_enable()
587 if (!wnd->valid) { in fsl_pamu_window_enable()
588 wnd->paddr = paddr; in fsl_pamu_window_enable()
589 wnd->size = size; in fsl_pamu_window_enable()
590 wnd->prot = pamu_prot; in fsl_pamu_window_enable()
594 wnd->valid = 1; in fsl_pamu_window_enable()
595 dma_domain->mapped++; in fsl_pamu_window_enable()
599 ret = -EBUSY; in fsl_pamu_window_enable()
602 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_window_enable()
608 * Attach the LIODN to the DMA domain and configure the geometry
616 struct iommu_domain *domain = &dma_domain->iommu_domain; in handle_attach_device() local
620 spin_lock_irqsave(&dma_domain->domain_lock, flags); in handle_attach_device()
625 liodn[i], dev->of_node); in handle_attach_device()
626 ret = -EINVAL; in handle_attach_device()
633 * for the domain. If yes, set the geometry for in handle_attach_device()
636 if (dma_domain->win_arr) { in handle_attach_device()
637 u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0; in handle_attach_device()
640 &domain->geometry, win_cnt); in handle_attach_device()
643 if (dma_domain->mapped) { in handle_attach_device()
654 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in handle_attach_device()
659 static int fsl_pamu_attach_device(struct iommu_domain *domain, in fsl_pamu_attach_device() argument
662 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_attach_device()
670 * Use LIODN of the PCI controller while attaching a in fsl_pamu_attach_device()
671 * PCI device. in fsl_pamu_attach_device()
675 pci_ctl = pci_bus_to_host(pdev->bus); in fsl_pamu_attach_device()
677 * make dev point to pci controller device in fsl_pamu_attach_device()
679 * u-boot. in fsl_pamu_attach_device()
681 dev = pci_ctl->parent; in fsl_pamu_attach_device()
684 liodn = of_get_property(dev->of_node, "fsl,liodn", &len); in fsl_pamu_attach_device()
689 pr_debug("missing fsl,liodn property at %pOF\n", dev->of_node); in fsl_pamu_attach_device()
690 ret = -EINVAL; in fsl_pamu_attach_device()
696 static void fsl_pamu_detach_device(struct iommu_domain *domain, in fsl_pamu_detach_device() argument
699 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_detach_device()
706 * Use LIODN of the PCI controller while detaching a in fsl_pamu_detach_device()
707 * PCI device. in fsl_pamu_detach_device()
711 pci_ctl = pci_bus_to_host(pdev->bus); in fsl_pamu_detach_device()
713 * make dev point to pci controller device in fsl_pamu_detach_device()
715 * u-boot. in fsl_pamu_detach_device()
717 dev = pci_ctl->parent; in fsl_pamu_detach_device()
720 prop = of_get_property(dev->of_node, "fsl,liodn", &len); in fsl_pamu_detach_device()
724 pr_debug("missing fsl,liodn property at %pOF\n", dev->of_node); in fsl_pamu_detach_device()
727 static int configure_domain_geometry(struct iommu_domain *domain, void *data) in configure_domain_geometry() argument
730 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in configure_domain_geometry()
734 geom_size = geom_attr->aperture_end - geom_attr->aperture_start + 1; in configure_domain_geometry()
739 if (check_size(geom_size, geom_attr->aperture_start) || in configure_domain_geometry()
740 !geom_attr->force_aperture) { in configure_domain_geometry()
742 return -EINVAL; in configure_domain_geometry()
745 spin_lock_irqsave(&dma_domain->domain_lock, flags); in configure_domain_geometry()
746 if (dma_domain->enabled) { in configure_domain_geometry()
747 pr_debug("Can't set geometry attributes as domain is active\n"); in configure_domain_geometry()
748 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_geometry()
749 return -EBUSY; in configure_domain_geometry()
752 /* Copy the domain geometry information */ in configure_domain_geometry()
753 memcpy(&domain->geometry, geom_attr, in configure_domain_geometry()
755 dma_domain->geom_size = geom_size; in configure_domain_geometry()
757 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_geometry()
762 /* Set the domain stash attribute */
769 spin_lock_irqsave(&dma_domain->domain_lock, flags); in configure_domain_stash()
771 memcpy(&dma_domain->dma_stash, stash_attr, in configure_domain_stash()
774 dma_domain->stash_id = get_stash_id(stash_attr->cache, in configure_domain_stash()
775 stash_attr->cpu); in configure_domain_stash()
776 if (dma_domain->stash_id == ~(u32)0) { in configure_domain_stash()
778 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_stash()
779 return -EINVAL; in configure_domain_stash()
782 ret = update_domain_stash(dma_domain, dma_domain->stash_id); in configure_domain_stash()
784 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_stash()
789 /* Configure domain dma state i.e. enable/disable DMA */
796 spin_lock_irqsave(&dma_domain->domain_lock, flags); in configure_domain_dma_state()
798 if (enable && !dma_domain->mapped) { in configure_domain_dma_state()
799 pr_debug("Can't enable DMA domain without valid mapping\n"); in configure_domain_dma_state()
800 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_dma_state()
801 return -ENODEV; in configure_domain_dma_state()
804 dma_domain->enabled = enable; in configure_domain_dma_state()
805 list_for_each_entry(info, &dma_domain->devices, link) { in configure_domain_dma_state()
806 ret = (enable) ? pamu_enable_liodn(info->liodn) : in configure_domain_dma_state()
807 pamu_disable_liodn(info->liodn); in configure_domain_dma_state()
810 info->liodn); in configure_domain_dma_state()
812 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in configure_domain_dma_state()
817 static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, in fsl_pamu_set_domain_attr() argument
820 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_set_domain_attr()
825 ret = configure_domain_geometry(domain, data); in fsl_pamu_set_domain_attr()
835 ret = -EINVAL; in fsl_pamu_set_domain_attr()
842 static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, in fsl_pamu_get_domain_attr() argument
845 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_get_domain_attr()
850 memcpy(data, &dma_domain->dma_stash, in fsl_pamu_get_domain_attr()
854 *(int *)data = dma_domain->enabled; in fsl_pamu_get_domain_attr()
861 ret = -EINVAL; in fsl_pamu_get_domain_attr()
883 /* Check the PCI controller version number by readding BRR1 register */ in check_pci_ctl_endpt_part()
884 version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2)); in check_pci_ctl_endpt_part()
886 /* If PCI controller version is >= 0x204 we can partition endpoints */ in check_pci_ctl_endpt_part()
895 struct pci_bus *bus = pdev->bus; in get_shared_pci_device_group()
898 * Traverese the pci bus device list to get in get_shared_pci_device_group()
902 list_for_each_entry(tmp, &bus->devices, bus_list) { in get_shared_pci_device_group()
905 group = iommu_group_get(&tmp->dev); in get_shared_pci_device_group()
910 bus = bus->parent; in get_shared_pci_device_group()
922 pci_ctl = pci_bus_to_host(pdev->bus); in get_pci_device_group()
926 group = pci_device_group(&pdev->dev); in get_pci_device_group()
932 if (pci_ctl->parent->iommu_group) in get_pci_device_group()
933 iommu_group_remove_device(pci_ctl->parent); in get_pci_device_group()
937 * PCI controllers device group. If this is the first in get_pci_device_group()
938 * device to be probed for the pci controller, copy the in get_pci_device_group()
939 * device group information from the PCI controller device in get_pci_device_group()
940 * node and remove the PCI controller iommu group. in get_pci_device_group()
945 if (pci_ctl->parent->iommu_group) { in get_pci_device_group()
946 group = get_device_iommu_group(pci_ctl->parent); in get_pci_device_group()
947 iommu_group_remove_device(pci_ctl->parent); in get_pci_device_group()
954 group = ERR_PTR(-ENODEV); in get_pci_device_group()
961 struct iommu_group *group = ERR_PTR(-ENODEV); in fsl_pamu_device_group()
970 else if (of_get_property(dev->of_node, "fsl,liodn", &len)) in fsl_pamu_device_group()
997 static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count) in fsl_pamu_set_windows() argument
999 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_set_windows()
1003 spin_lock_irqsave(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1004 /* Ensure domain is inactive i.e. DMA should be disabled for the domain */ in fsl_pamu_set_windows()
1005 if (dma_domain->enabled) { in fsl_pamu_set_windows()
1006 pr_debug("Can't set geometry attributes as domain is active\n"); in fsl_pamu_set_windows()
1007 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1008 return -EBUSY; in fsl_pamu_set_windows()
1011 /* Ensure that the geometry has been set for the domain */ in fsl_pamu_set_windows()
1012 if (!dma_domain->geom_size) { in fsl_pamu_set_windows()
1014 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1015 return -EINVAL; in fsl_pamu_set_windows()
1024 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1025 return -EINVAL; in fsl_pamu_set_windows()
1028 ret = pamu_set_domain_geometry(dma_domain, &domain->geometry, in fsl_pamu_set_windows()
1031 kfree(dma_domain->win_arr); in fsl_pamu_set_windows()
1032 dma_domain->win_arr = kcalloc(w_count, in fsl_pamu_set_windows()
1033 sizeof(*dma_domain->win_arr), in fsl_pamu_set_windows()
1035 if (!dma_domain->win_arr) { in fsl_pamu_set_windows()
1036 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1037 return -ENOMEM; in fsl_pamu_set_windows()
1039 dma_domain->win_cnt = w_count; in fsl_pamu_set_windows()
1041 spin_unlock_irqrestore(&dma_domain->domain_lock, flags); in fsl_pamu_set_windows()
1046 static u32 fsl_pamu_get_windows(struct iommu_domain *domain) in fsl_pamu_get_windows() argument
1048 struct fsl_dma_domain *dma_domain = to_fsl_dma_domain(domain); in fsl_pamu_get_windows()
1050 return dma_domain->win_cnt; in fsl_pamu_get_windows()