Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c99afa25 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

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: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent b16137b1
Loading
Loading
Loading
Loading
+51 −0
Original line number Original line Diff line number Diff line
@@ -736,6 +736,22 @@ static void build_inv_iotlb_pasid(struct iommu_cmd *cmd, u16 devid, int pasid,
	CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
	CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
}
}


static void build_complete_ppr(struct iommu_cmd *cmd, u16 devid, int pasid,
			       int status, int tag, bool gn)
{
	memset(cmd, 0, sizeof(*cmd));

	cmd->data[0]  = devid;
	if (gn) {
		cmd->data[1]  = pasid & PASID_MASK;
		cmd->data[2]  = CMD_INV_IOMMU_PAGES_GN_MASK;
	}
	cmd->data[3]  = tag & 0x1ff;
	cmd->data[3] |= (status & PPR_STATUS_MASK) << PPR_STATUS_SHIFT;

	CMD_SET_TYPE(cmd, CMD_COMPLETE_PPR);
}

static void build_inv_all(struct iommu_cmd *cmd)
static void build_inv_all(struct iommu_cmd *cmd)
{
{
	memset(cmd, 0, sizeof(*cmd));
	memset(cmd, 0, sizeof(*cmd));
@@ -1950,6 +1966,23 @@ static int pdev_iommuv2_enable(struct pci_dev *pdev)
	return ret;
	return ret;
}
}


/* FIXME: Move this to PCI code */
#define PCI_PRI_TLP_OFF		(1 << 2)

bool pci_pri_tlp_required(struct pci_dev *pdev)
{
	u16 control;
	int pos;

	pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
	if (!pos)
		return false;

	pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);

	return (control & PCI_PRI_TLP_OFF) ? true : false;
}

/*
/*
 * If a device is not yet associated with a domain, this function does
 * If a device is not yet associated with a domain, this function does
 * assigns it visible for the hardware
 * assigns it visible for the hardware
@@ -1973,6 +2006,7 @@ static int attach_device(struct device *dev,


		dev_data->ats.enabled = true;
		dev_data->ats.enabled = true;
		dev_data->ats.qdep    = pci_ats_queue_depth(pdev);
		dev_data->ats.qdep    = pci_ats_queue_depth(pdev);
		dev_data->pri_tlp     = pci_pri_tlp_required(pdev);
	} else if (amd_iommu_iotlb_sup &&
	} else if (amd_iommu_iotlb_sup &&
		   pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
		   pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
		dev_data->ats.enabled = true;
		dev_data->ats.enabled = true;
@@ -3412,3 +3446,20 @@ int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid)
	return ret;
	return ret;
}
}
EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3);
EXPORT_SYMBOL(amd_iommu_domain_clear_gcr3);

int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid,
			   int status, int tag)
{
	struct iommu_dev_data *dev_data;
	struct amd_iommu *iommu;
	struct iommu_cmd cmd;

	dev_data = get_dev_data(&pdev->dev);
	iommu    = amd_iommu_rlookup_table[dev_data->devid];

	build_complete_ppr(&cmd, dev_data->devid, pasid, status,
			   tag, dev_data->pri_tlp);

	return iommu_queue_command(iommu, &cmd);
}
EXPORT_SYMBOL(amd_iommu_complete_ppr);
+6 −0
Original line number Original line Diff line number Diff line
@@ -47,6 +47,12 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
				     unsigned long cr3);
				     unsigned long cr3);
extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);
extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);


#define PPR_SUCCESS			0x0
#define PPR_INVALID			0x1
#define PPR_FAILURE			0xf

extern int amd_iommu_complete_ppr(struct pci_dev *pdev, int pasid,
				  int status, int tag);


#ifndef CONFIG_AMD_IOMMU_STATS
#ifndef CONFIG_AMD_IOMMU_STATS


+6 −0
Original line number Original line Diff line number Diff line
@@ -142,6 +142,7 @@
#define CMD_INV_DEV_ENTRY       0x02
#define CMD_INV_DEV_ENTRY       0x02
#define CMD_INV_IOMMU_PAGES	0x03
#define CMD_INV_IOMMU_PAGES	0x03
#define CMD_INV_IOTLB_PAGES	0x04
#define CMD_INV_IOTLB_PAGES	0x04
#define CMD_COMPLETE_PPR	0x07
#define CMD_INV_ALL		0x08
#define CMD_INV_ALL		0x08


#define CMD_COMPL_WAIT_STORE_MASK	0x01
#define CMD_COMPL_WAIT_STORE_MASK	0x01
@@ -150,6 +151,9 @@
#define CMD_INV_IOMMU_PAGES_PDE_MASK	0x02
#define CMD_INV_IOMMU_PAGES_PDE_MASK	0x02
#define CMD_INV_IOMMU_PAGES_GN_MASK	0x04
#define CMD_INV_IOMMU_PAGES_GN_MASK	0x04


#define PPR_STATUS_MASK			0xf
#define PPR_STATUS_SHIFT		12

#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS	0x7fffffffffffffffULL
#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS	0x7fffffffffffffffULL


/* macros and definitions for device table entries */
/* macros and definitions for device table entries */
@@ -394,6 +398,8 @@ struct iommu_dev_data {
		bool enabled;
		bool enabled;
		int qdep;
		int qdep;
	} ats;				  /* ATS state */
	} ats;				  /* ATS state */
	bool pri_tlp;			  /* PASID TLB required for
					     PPR completions */
};
};


/*
/*