diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-11-21 12:19:25 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-12 09:19:05 -0500 |
commit | c99afa25b67339b5fa7ef3767398878be9f60e1f (patch) | |
tree | 6743ac16764459cbdf519f0c83ca4d0c2d923dfb /drivers | |
parent | b16137b11b4b4d4bb27b61bba7e05f5fda5968f4 (diff) |
iommu/amd: Implement function to send PPR completions
To send completions for PPR requests this patch adds a
function which can be used by the IOMMUv2 driver.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 51 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_proto.h | 6 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 6 |
3 files changed, 63 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 65a118ce626e..9a7e64b245a7 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -736,6 +736,22 @@ static void build_inv_iotlb_pasid(struct iommu_cmd *cmd, u16 devid, int pasid, | |||
736 | CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES); | 736 | CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES); |
737 | } | 737 | } |
738 | 738 | ||
739 | static void build_complete_ppr(struct iommu_cmd *cmd, u16 devid, int pasid, | ||
740 | int status, int tag, bool gn) | ||
741 | { | ||
742 | memset(cmd, 0, sizeof(*cmd)); | ||
743 | |||
744 | cmd->data[0] = devid; | ||
745 | if (gn) { | ||
746 | cmd->data[1] = pasid & PASID_MASK; | ||
747 | cmd->data[2] = CMD_INV_IOMMU_PAGES_GN_MASK; | ||
748 | } | ||
749 | cmd->data[3] = tag & 0x1ff; | ||
750 | cmd->data[3] |= (status & PPR_STATUS_MASK) << PPR_STATUS_SHIFT; | ||
751 | |||
752 | CMD_SET_TYPE(cmd, CMD_COMPLETE_PPR); | ||
753 | } | ||
754 | |||
739 | static void build_inv_all(struct iommu_cmd *cmd) | 755 | static void build_inv_all(struct iommu_cmd *cmd) |
740 | { | 756 | { |
741 | memset(cmd, 0, sizeof(*cmd)); | 757 | memset(cmd, 0, sizeof(*cmd)); |
@@ -1950,6 +1966,23 @@ out_err: | |||
1950 | return ret; | 1966 | return ret; |
1951 | } | 1967 | } |
1952 | 1968 | ||
1969 | /* FIXME: Move this to PCI code */ | ||
1970 | #define PCI_PRI_TLP_OFF (1 << 2) | ||
1971 | |||
1972 | bool pci_pri_tlp_required(struct pci_dev *pdev) | ||
1973 | { | ||
1974 | u16 control; | ||
1975 | int pos; | ||
1976 | |||
1977 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | ||
1978 | if (!pos) | ||
1979 | return false; | ||
1980 | |||
1981 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | ||
1982 | |||
1983 | return (control & PCI_PRI_TLP_OFF) ? true : false; | ||
1984 | } | ||
1985 | |||
1953 | /* | 1986 | /* |
1954 | * If a device is not yet associated with a domain, this function does | 1987 | * If a device is not yet associated with a domain, this function does |
1955 | * assigns it visible for the hardware | 1988 | * assigns it visible for the hardware |
@@ -1973,6 +2006,7 @@ static int attach_device(struct device *dev, | |||
1973 | 2006 | ||
1974 | dev_data->ats.enabled = true; | 2007 | dev_data->ats.enabled = true; |
1975 | dev_data->ats.qdep = pci_ats_queue_depth(pdev); | 2008 | dev_data->ats.qdep = pci_ats_queue_depth(pdev); |
2009 | dev_data->pri_tlp = pci_pri_tlp_required(pdev); | ||
1976 | } else if (amd_iommu_iotlb_sup && | 2010 | } else if (amd_iommu_iotlb_sup && |
1977 | pci_enable_ats(pdev, PAGE_SHIFT) == 0) { | 2011 | pci_enable_ats(pdev, PAGE_SHIFT) == 0) { |
1978 | dev_data->ats.enabled = true; | 2012 | dev_data->ats.enabled = true; |
@@ -3412,3 +3446,20 @@ int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid) | |||
3412 | return ret; | 3446 | return ret; |
3413 | } | 3447 | } |
3414 | EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3); | 3448 | EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3); |
3449 | |||
3450 | int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid, | ||
3451 | int status, int tag) | ||
3452 | { | ||
3453 | struct iommu_dev_data *dev_data; | ||
3454 | struct amd_iommu *iommu; | ||
3455 | struct iommu_cmd cmd; | ||
3456 | |||
3457 | dev_data = get_dev_data(&pdev->dev); | ||
3458 | iommu = amd_iommu_rlookup_table[dev_data->devid]; | ||
3459 | |||
3460 | build_complete_ppr(&cmd, dev_data->devid, pasid, status, | ||
3461 | tag, dev_data->pri_tlp); | ||
3462 | |||
3463 | return iommu_queue_command(iommu, &cmd); | ||
3464 | } | ||
3465 | EXPORT_SYMBOL(amd_iommu_complete_ppr); | ||
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index a951a7090e35..bb5ecfecfa44 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h | |||
@@ -47,6 +47,12 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid, | |||
47 | unsigned long cr3); | 47 | unsigned long cr3); |
48 | extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); | 48 | extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); |
49 | 49 | ||
50 | #define PPR_SUCCESS 0x0 | ||
51 | #define PPR_INVALID 0x1 | ||
52 | #define PPR_FAILURE 0xf | ||
53 | |||
54 | extern int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid, | ||
55 | int status, int tag); | ||
50 | 56 | ||
51 | #ifndef CONFIG_AMD_IOMMU_STATS | 57 | #ifndef CONFIG_AMD_IOMMU_STATS |
52 | 58 | ||
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 060724e02e9f..8e1a6460f683 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
@@ -142,6 +142,7 @@ | |||
142 | #define CMD_INV_DEV_ENTRY 0x02 | 142 | #define CMD_INV_DEV_ENTRY 0x02 |
143 | #define CMD_INV_IOMMU_PAGES 0x03 | 143 | #define CMD_INV_IOMMU_PAGES 0x03 |
144 | #define CMD_INV_IOTLB_PAGES 0x04 | 144 | #define CMD_INV_IOTLB_PAGES 0x04 |
145 | #define CMD_COMPLETE_PPR 0x07 | ||
145 | #define CMD_INV_ALL 0x08 | 146 | #define CMD_INV_ALL 0x08 |
146 | 147 | ||
147 | #define CMD_COMPL_WAIT_STORE_MASK 0x01 | 148 | #define CMD_COMPL_WAIT_STORE_MASK 0x01 |
@@ -150,6 +151,9 @@ | |||
150 | #define CMD_INV_IOMMU_PAGES_PDE_MASK 0x02 | 151 | #define CMD_INV_IOMMU_PAGES_PDE_MASK 0x02 |
151 | #define CMD_INV_IOMMU_PAGES_GN_MASK 0x04 | 152 | #define CMD_INV_IOMMU_PAGES_GN_MASK 0x04 |
152 | 153 | ||
154 | #define PPR_STATUS_MASK 0xf | ||
155 | #define PPR_STATUS_SHIFT 12 | ||
156 | |||
153 | #define CMD_INV_IOMMU_ALL_PAGES_ADDRESS 0x7fffffffffffffffULL | 157 | #define CMD_INV_IOMMU_ALL_PAGES_ADDRESS 0x7fffffffffffffffULL |
154 | 158 | ||
155 | /* macros and definitions for device table entries */ | 159 | /* macros and definitions for device table entries */ |
@@ -394,6 +398,8 @@ struct iommu_dev_data { | |||
394 | bool enabled; | 398 | bool enabled; |
395 | int qdep; | 399 | int qdep; |
396 | } ats; /* ATS state */ | 400 | } ats; /* ATS state */ |
401 | bool pri_tlp; /* PASID TLB required for | ||
402 | PPR completions */ | ||
397 | }; | 403 | }; |
398 | 404 | ||
399 | /* | 405 | /* |