pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); if (!pos) return;
dev->ats_cap = pos;
}
/** * pci_ats_supported - check if the device can use ATS * @dev: the PCI device * * Returns true if the device supports ATS and is allowed to use it, false * otherwise.
*/ bool pci_ats_supported(struct pci_dev *dev)
{ if (!dev->ats_cap) returnfalse;
/** * pci_prepare_ats - Setup the PS for ATS * @dev: the PCI device * @ps: the IOMMU page shift * * This must be done by the IOMMU driver on the PF before any VFs are created to * ensure that the VF can have ATS enabled. * * Returns 0 on success, or negative on failure.
*/ int pci_prepare_ats(struct pci_dev *dev, int ps)
{
u16 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)
{
u16 ctrl; struct pci_dev *pdev;
if (!pci_ats_supported(dev)) 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;
} 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);
/** * pci_ats_queue_depth - query the ATS Invalidate Queue Depth * @dev: the PCI device * * Returns the queue depth on success, or negative on failure. * * The ATS spec uses 0 in the Invalidate Queue Depth field to * indicate that the function can accept 32 Invalidate Request. * But here we use the `real' values (i.e. 1~32) for the Queue * Depth; and 0 indicates the function shares the Queue with * other functions (doesn't exclusively own a Queue).
*/ int pci_ats_queue_depth(struct pci_dev *dev)
{
u16 cap;
/** * pci_ats_page_aligned - Return Page Aligned Request bit status. * @pdev: the PCI device * * Returns 1, if the Untranslated Addresses generated by the device * are always aligned or 0 otherwise. * * Per PCIe spec r4.0, sec 10.5.1.2, if the Page Aligned Request bit * is set, it indicates the Untranslated Addresses generated by the * device are always aligned to a 4096 byte boundary.
*/ int pci_ats_page_aligned(struct pci_dev *pdev)
{
u16 cap;
/** * pci_enable_pri - Enable PRI capability * @pdev: PCI device structure * @reqs: outstanding requests * * Returns 0 on success, negative value on error
*/ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
{
u16 control, status;
u32 max_requests; int pri = pdev->pri_cap;
/* * VFs must not implement the PRI Capability. If their PF * implements PRI, it is shared by the VFs, so if the PF PRI is * enabled, it is also enabled for the VF.
*/ if (pdev->is_virtfn) { if (pci_physfn(pdev)->pri_enabled) return 0; return -EINVAL;
}
if (WARN_ON(pdev->pri_enabled)) return -EBUSY;
if (!pri) return -EINVAL;
pci_read_config_word(pdev, pri + PCI_PRI_STATUS, &status); if (!(status & PCI_PRI_STATUS_STOPPED)) return -EBUSY;
pci_read_config_dword(pdev, pri + PCI_PRI_MAX_REQ, &max_requests);
reqs = min(max_requests, reqs);
pdev->pri_reqs_alloc = reqs;
pci_write_config_dword(pdev, pri + PCI_PRI_ALLOC_REQ, reqs);
control = PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pri + PCI_PRI_CTRL, control);
pdev->pri_enabled = 1;
return 0;
}
/** * pci_disable_pri - Disable PRI capability * @pdev: PCI device structure * * Only clears the enabled-bit, regardless of its former value
*/ void pci_disable_pri(struct pci_dev *pdev)
{
u16 control; int pri = pdev->pri_cap;
/* VFs share the PF PRI */ if (pdev->is_virtfn) return;
if (WARN_ON(!pdev->pri_enabled)) return;
if (!pri) return;
pci_read_config_word(pdev, pri + PCI_PRI_CTRL, &control);
control &= ~PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pri + PCI_PRI_CTRL, control);
/** * pci_restore_pri_state - Restore PRI * @pdev: PCI device structure
*/ void pci_restore_pri_state(struct pci_dev *pdev)
{
u16 control = PCI_PRI_CTRL_ENABLE;
u32 reqs = pdev->pri_reqs_alloc; int pri = pdev->pri_cap;
if (pdev->is_virtfn) return;
if (!pdev->pri_enabled) return;
if (!pri) return;
pci_write_config_dword(pdev, pri + PCI_PRI_ALLOC_REQ, reqs);
pci_write_config_word(pdev, pri + PCI_PRI_CTRL, control);
}
/** * pci_reset_pri - Resets device's PRI state * @pdev: PCI device structure * * The PRI capability must be disabled before this function is called. * Returns 0 on success, negative value on error.
*/ int pci_reset_pri(struct pci_dev *pdev)
{
u16 control; int pri = pdev->pri_cap;
if (pdev->is_virtfn) return 0;
if (WARN_ON(pdev->pri_enabled)) return -EBUSY;
if (!pri) return -EINVAL;
control = PCI_PRI_CTRL_RESET;
pci_write_config_word(pdev, pri + PCI_PRI_CTRL, control);
return 0;
}
/** * pci_prg_resp_pasid_required - Return PRG Response PASID Required bit * status. * @pdev: PCI device structure * * Returns 1 if PASID is required in PRG Response Message, 0 otherwise.
*/ int pci_prg_resp_pasid_required(struct pci_dev *pdev)
{ if (pdev->is_virtfn)
pdev = pci_physfn(pdev);
return pdev->pasid_required;
}
/** * pci_pri_supported - Check if PRI is supported. * @pdev: PCI device structure * * Returns true if PRI capability is present, false otherwise.
*/ bool pci_pri_supported(struct pci_dev *pdev)
{ /* VFs share the PF PRI */ if (pci_physfn(pdev)->pri_cap) returntrue; returnfalse;
}
EXPORT_SYMBOL_GPL(pci_pri_supported); #endif/* CONFIG_PCI_PRI */
/** * pci_enable_pasid - Enable the PASID capability * @pdev: PCI device structure * @features: Features to enable * * Returns 0 on success, negative value on error. This function checks * whether the features are actually supported by the device and returns * an error if not.
*/ int pci_enable_pasid(struct pci_dev *pdev, int features)
{
u16 control, supported; int pasid = pdev->pasid_cap;
/* * VFs must not implement the PASID Capability, but if a PF * supports PASID, its VFs share the PF PASID configuration.
*/ if (pdev->is_virtfn) { if (pci_physfn(pdev)->pasid_enabled) return 0; return -EINVAL;
}
if (WARN_ON(pdev->pasid_enabled)) return -EBUSY;
if (!pdev->eetlp_prefix_max && !pdev->pasid_no_tlp) return -EINVAL;
if (!pasid) return -EINVAL;
if (!pci_acs_path_enabled(pdev, NULL, PCI_ACS_RR | PCI_ACS_UF)) return -EINVAL;
/** * pci_pasid_features - Check which PASID features are supported * @pdev: PCI device structure * * Return a negative value when no PASID capability is present. * Otherwise return a bitmask with supported features. Current * features reported are: * PCI_PASID_CAP_EXEC - Execute permission supported * PCI_PASID_CAP_PRIV - Privileged mode supported
*/ int pci_pasid_features(struct pci_dev *pdev)
{
u16 supported; int pasid;
if (pdev->is_virtfn)
pdev = pci_physfn(pdev);
pasid = pdev->pasid_cap; if (!pasid) return -EINVAL;
/** * pci_max_pasids - Get maximum number of PASIDs supported by device * @pdev: PCI device structure * * Returns negative value when PASID capability is not present. * Otherwise it returns the number of supported PASIDs.
*/ int pci_max_pasids(struct pci_dev *pdev)
{
u16 supported; int pasid;
if (pdev->is_virtfn)
pdev = pci_physfn(pdev);
pasid = pdev->pasid_cap; if (!pasid) return -EINVAL;
/** * pci_pasid_status - Check the PASID status * @pdev: PCI device structure * * Returns a negative value when no PASID capability is present. * Otherwise the value of the control register is returned. * Status reported are: * * PCI_PASID_CTRL_ENABLE - PASID enabled * PCI_PASID_CTRL_EXEC - Execute permission enabled * PCI_PASID_CTRL_PRIV - Privileged mode enabled
*/ int pci_pasid_status(struct pci_dev *pdev)
{ int pasid;
u16 ctrl;
if (pdev->is_virtfn)
pdev = pci_physfn(pdev);
pasid = pdev->pasid_cap; if (!pasid) return -EINVAL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.