Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5116ab4e authored by Tushar Dave's avatar Tushar Dave Committed by David S. Miller
Browse files

sparc64: Bind PCIe devices to use IOMMU v2 service



In order to use Hypervisor (HV) IOMMU v2 API for map/demap, each PCIe
device has to be bound to IOTSB using HV API pci_iotsb_bind().

Signed-off-by: default avatarTushar Dave <tushar.n.dave@oracle.com>
Reviewed-by: default avatarchris hyser <chris.hyser@oracle.com>
Acked-by: default avatarSowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31f077dc
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -216,6 +216,43 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
	return NULL;
}

unsigned long dma_4v_iotsb_bind(unsigned long devhandle,
				unsigned long iotsb_num,
				struct pci_bus *bus_dev)
{
	struct pci_dev *pdev;
	unsigned long err;
	unsigned int bus;
	unsigned int device;
	unsigned int fun;

	list_for_each_entry(pdev, &bus_dev->devices, bus_list) {
		if (pdev->subordinate) {
			/* No need to bind pci bridge */
			dma_4v_iotsb_bind(devhandle, iotsb_num,
					  pdev->subordinate);
		} else {
			bus = bus_dev->number;
			device = PCI_SLOT(pdev->devfn);
			fun = PCI_FUNC(pdev->devfn);
			err = pci_sun4v_iotsb_bind(devhandle, iotsb_num,
						   HV_PCI_DEVICE_BUILD(bus,
								       device,
								       fun));

			/* If bind fails for one device it is going to fail
			 * for rest of the devices because we are sharing
			 * IOTSB. So in case of failure simply return with
			 * error.
			 */
			if (err)
				return err;
		}
	}

	return 0;
}

static void dma_4v_iommu_demap(void *demap_arg, unsigned long entry,
			       unsigned long npages)
{
@@ -629,6 +666,12 @@ static int pci_sun4v_atu_alloc_iotsb(struct pci_pbm_info *pbm)
	}
	iotsb->iotsb_num = iotsb_num;

	err = dma_4v_iotsb_bind(pbm->devhandle, iotsb_num, pbm->pci_bus);
	if (err) {
		pr_err(PFX "pci_iotsb_bind failed error: %ld\n", err);
		goto iotsb_conf_failed;
	}

	return 0;

iotsb_conf_failed:
+3 −0
Original line number Diff line number Diff line
@@ -96,4 +96,7 @@ unsigned long pci_sun4v_iotsb_conf(unsigned long devhandle,
				   unsigned long page_size,
				   unsigned long dvma_base,
				   u64 *iotsb_num);
unsigned long pci_sun4v_iotsb_bind(unsigned long devhandle,
				   unsigned long iotsb_num,
				   unsigned int pci_device);
#endif /* !(_PCI_SUN4V_H) */
+14 −0
Original line number Diff line number Diff line
@@ -378,3 +378,17 @@ ENTRY(pci_sun4v_iotsb_conf)
	retl
	 stx	%o1, [%g1]
ENDPROC(pci_sun4v_iotsb_conf)

	/*
	 * %o0:	devhandle
	 * %o1:	iotsb_num/iotsb_handle
	 * %o2:	pci_device
	 *
	 * returns %o0:	status
	 */
ENTRY(pci_sun4v_iotsb_bind)
	mov	HV_FAST_PCI_IOTSB_BIND, %o5
	ta	HV_FAST_TRAP
	retl
	 nop
ENDPROC(pci_sun4v_iotsb_bind)