{
struct iommu *iommu = dev->archdata.iommu;
u64 dma_addr_mask = iommu->dma_addr_mask;
+ unsigned long err;
if (device_mask > DMA_BIT_MASK(32)) {
- if (iommu->atu)
+ if (iommu->atu && dev_is_pci(dev)) {
+ /* bind this pci device to ATU IOTSB */
+ err = iommu->atu->iotsb->bind(dev);
+ /* if binding fails, ATU cannot be used and hence
+ * no 64bit DMA.
+ */
+ if (err)
+ return 0;
+
dma_addr_mask = iommu->atu->dma_addr_mask;
- else
+ } else {
return 0;
+ }
}
if ((device_mask & dma_addr_mask) == dma_addr_mask)
return NULL;
}
-unsigned long dma_4v_iotsb_bind(unsigned long devhandle,
- unsigned long iotsb_num,
- struct pci_bus *bus_dev)
+unsigned long dma_4v_iotsb_bind(struct device *dev)
{
- struct pci_dev *pdev;
- unsigned long err;
+ struct pci_pbm_info *pbm = dev->archdata.host_controller;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ unsigned long iotsb_num;
+ unsigned long err = 0;
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;
+ iotsb_num = pbm->iommu->atu->iotsb->iotsb_num;
+ bus = pdev->bus->number;
+ device = PCI_SLOT(pdev->devfn);
+ fun = PCI_FUNC(pdev->devfn);
+
+ err = pci_sun4v_iotsb_bind(pbm->devhandle, iotsb_num,
+ HV_PCI_DEVICE_BUILD(bus,
+ device,
+ fun));
+
+ /* If bind fails, device will no longer be able to
+ * use ATU because hypervisor will reject any access
+ * to IOTSB until device is successfully bound to IOTSB.
+ * However, device still can continue using legacy IOMMU
+ * with 32bit DMA.
+ */
+ return err;
}
static void dma_4v_iommu_demap(struct device *dev, unsigned long devhandle,
goto iotsb_conf_failed;
}
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;
- }
+ iotsb->bind = dma_4v_iotsb_bind;
return 0;