1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #define VCMD_CMD_ALLOC 0x1 #define VCMD_CMD_FREE 0x2 #define VCMD_VRSP_IP 0x1 #define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1) #define VCMD_VRSP_SC_SUCCESS 0 #define VCMD_VRSP_SC_NO_PASID_AVAIL 16 #define VCMD_VRSP_SC_INVALID_PASID 16 #define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff) #define VCMD_CMD_OPERAND(e) ((e) << 16)
int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid) { unsigned long flags; u8 status_code; int ret = 0; u64 res;
raw_spin_lock_irqsave(&iommu->register_lock, flags); dmar_writeq(iommu->reg + DMAR_VCMD_REG, VCMD_CMD_ALLOC); IOMMU_WAIT_OP(iommu, DMAR_VCRSP_REG, dmar_readq, !(res & VCMD_VRSP_IP), res); raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
status_code = VCMD_VRSP_SC(res); switch (status_code) { case VCMD_VRSP_SC_SUCCESS: *pasid = VCMD_VRSP_RESULT_PASID(res); break; case VCMD_VRSP_SC_NO_PASID_AVAIL: pr_info("IOMMU: %s: No PASID available\n", iommu->name); ret = -ENOSPC; break; default: ret = -ENODEV; pr_warn("IOMMU: %s: Unexpected error code %d\n", iommu->name, status_code); }
return ret; }
void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid) { unsigned long flags; u8 status_code; u64 res;
raw_spin_lock_irqsave(&iommu->register_lock, flags); dmar_writeq(iommu->reg + DMAR_VCMD_REG, VCMD_CMD_OPERAND(pasid) | VCMD_CMD_FREE); IOMMU_WAIT_OP(iommu, DMAR_VCRSP_REG, dmar_readq, !(res & VCMD_VRSP_IP), res); raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
status_code = VCMD_VRSP_SC(res); switch (status_code) { case VCMD_VRSP_SC_SUCCESS: break; case VCMD_VRSP_SC_INVALID_PASID: pr_info("IOMMU: %s: Invalid PASID\n", iommu->name); break; default: pr_warn("IOMMU: %s: Unexpected error code %d\n", iommu->name, status_code); } }
|