aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-11-21 12:19:25 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2011-12-12 09:19:05 -0500
commitc99afa25b67339b5fa7ef3767398878be9f60e1f (patch)
tree6743ac16764459cbdf519f0c83ca4d0c2d923dfb /drivers
parentb16137b11b4b4d4bb27b61bba7e05f5fda5968f4 (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.c51
-rw-r--r--drivers/iommu/amd_iommu_proto.h6
-rw-r--r--drivers/iommu/amd_iommu_types.h6
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
739static 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
739static void build_inv_all(struct iommu_cmd *cmd) 755static 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
1972bool 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}
3414EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3); 3448EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3);
3449
3450int 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}
3465EXPORT_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);
48extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid); 48extern 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
54extern 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/*