/* * PASID zero is used for requests from the I/O device without * a PASID
*/
dev_data = dev_iommu_priv_get(&pdev->dev); if (event.fault.prm.pasid == 0 ||
event.fault.prm.pasid >= dev_data->max_pasids) {
pr_info_ratelimited("Invalid PASID : 0x%x, device : 0x%x\n",
event.fault.prm.pasid, pdev->dev.id); goto out;
}
head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);
while (head != tail) { volatile u64 *raw;
u64 entry[2]; int i;
raw = (u64 *)(iommu->ppr_log + head);
/* * Hardware bug: Interrupt may arrive before the entry is * written to memory. If this happens we need to wait for the * entry to arrive.
*/ for (i = 0; i < LOOP_TIMEOUT; ++i) { if (PPR_REQ_TYPE(raw[0]) != 0) break;
udelay(1);
}
/* * To detect the hardware errata 733 we need to clear the * entry back to zero. This issue does not exist on SNP * enabled system. Also this buffer is not writeable on * SNP enabled system.
*/ if (!amd_iommu_snp_en)
raw[0] = raw[1] = 0UL;
/* Update head pointer of hardware ring-buffer */
head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE;
writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
int amd_iommu_iopf_add_device(struct amd_iommu *iommu, struct iommu_dev_data *dev_data)
{ int ret = 0;
if (!dev_data->pri_enabled) return ret;
if (!iommu->iopf_queue) return -EINVAL;
ret = iopf_queue_add_device(iommu->iopf_queue, dev_data->dev); if (ret) return ret;
dev_data->ppr = true; return 0;
}
/* Its assumed that caller has verified that device was added to iopf queue */ void amd_iommu_iopf_remove_device(struct amd_iommu *iommu, struct iommu_dev_data *dev_data)
{
iopf_queue_remove_device(iommu->iopf_queue, dev_data->dev);
dev_data->ppr = false;
}
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.