/** * pci_enable_ats - enable the ATS capability * @dev: the PCI device * @ps: the IOMMU page shift * * Returns 0 on success, or negative on failure. */ int pci_enable_ats(struct pci_dev *dev, int ps) { u16 ctrl; struct pci_dev *pdev; if (!dev->ats_cap) return -EINVAL; if (WARN_ON(dev->ats_enabled)) return -EBUSY; if (ps < PCI_ATS_MIN_STU) return -EINVAL; /* * Note that enabling ATS on a VF fails unless it's already enabled * with the same STU on the PF. */ ctrl = PCI_ATS_CTRL_ENABLE; if (dev->is_virtfn) { pdev = pci_physfn(dev); if (pdev->ats_stu != ps) return -EINVAL; atomic_inc(&pdev->ats_ref_cnt); /* count enabled VFs */ } else { dev->ats_stu = ps; ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); } pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); dev->ats_enabled = 1; return 0; }
void pci_restore_ats_state(struct pci_dev *dev) { u16 ctrl; if (!dev->ats_enabled) return; ctrl = PCI_ATS_CTRL_ENABLE; if (!dev->is_virtfn) ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU); pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl); }
void pci_restore_ats_state(struct pci_dev *dev) { u16 ctrl; if (!pci_ats_enabled(dev)) return; if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS)) BUG(); ctrl = PCI_ATS_CTRL_ENABLE; if (!dev->is_virtfn) ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU); pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); }
/** * pci_enable_ats - enable the ATS capability * @dev: the PCI device * @ps: the IOMMU page shift * * Returns 0 on success, or negative on failure. */ int pci_enable_ats(struct pci_dev *dev, int ps) { int rc; u16 ctrl; BUG_ON(dev->ats && dev->ats->is_enabled); if (ps < PCI_ATS_MIN_STU) return -EINVAL; if (dev->is_physfn || dev->is_virtfn) { struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn; mutex_lock(&pdev->sriov->lock); if (pdev->ats) rc = pdev->ats->stu == ps ? 0 : -EINVAL; else rc = ats_alloc_one(pdev, ps); if (!rc) pdev->ats->ref_cnt++; mutex_unlock(&pdev->sriov->lock); if (rc) return rc; } if (!dev->is_physfn) { rc = ats_alloc_one(dev, ps); if (rc) return rc; } ctrl = PCI_ATS_CTRL_ENABLE; if (!dev->is_virtfn) ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU); pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl); dev->ats->is_enabled = 1; return 0; }