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

Commit 2a022a0d authored by Tony Truong's avatar Tony Truong
Browse files

msm: pcie: update SMMU SID support on msm-4.9 kernel



On msm-4.9 kernel, PCIe host driver provides a SID to
endpoint BDF mapping in devicetree. SMMU driver uses
this mapping to link a SID to an endpoint making the
previous support obsolete. Update the way PCIe bus
driver supports SID.

Change-Id: Iab6b7f7944ef2515c6a4a111995722255a36a002
Signed-off-by: default avatarTony Truong <truong@codeaurora.org>
parent 7772e692
Loading
Loading
Loading
Loading
+24 −114
Original line number Diff line number Diff line
@@ -487,7 +487,6 @@ struct msm_pcie_dev_t {
	uint32_t			wr_halt_size;
	uint32_t			cpl_timeout;
	uint32_t			current_bdf;
	short				current_short_bdf;
	uint32_t			perst_delay_us_min;
	uint32_t			perst_delay_us_max;
	uint32_t			tlp_rd_size;
@@ -1134,8 +1133,6 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev)
		dev->msi_gicm_base);
	PCIE_DBG_FS(dev, "bus_client: %d\n",
		dev->bus_client);
	PCIE_DBG_FS(dev, "current short bdf: %d\n",
		dev->current_short_bdf);
	PCIE_DBG_FS(dev, "smmu does %s exist\n",
		dev->smmu_exist ? "" : "not");
	PCIE_DBG_FS(dev, "smmu_sid_base: 0x%x\n",
@@ -2987,8 +2984,6 @@ static void msm_pcie_iatu_config_all_ep(struct msm_pcie_dev_t *dev)

static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev)
{
	int i;

	PCIE_DBG(dev, "RC%d\n", dev->rc_idx);

	/*
@@ -3044,27 +3039,6 @@ static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev)
		PCIE_DBG(dev, "RC's PCIE20_CAP_DEVCTRLSTATUS:0x%x\n",
			readl_relaxed(dev->dm_core + PCIE20_CAP_DEVCTRLSTATUS));
	}

	/* configure SMMU registers */
	if (dev->smmu_exist) {
		msm_pcie_write_reg(dev->parf,
			PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
		msm_pcie_write_reg(dev->parf,
			PCIE20_PARF_SID_OFFSET, 0);

		if (dev->enumerated) {
			for (i = 0; i < MAX_DEVICE_NUM; i++) {
				if (dev->pcidev_table[i].dev &&
					dev->pcidev_table[i].short_bdf) {
					msm_pcie_write_reg(dev->parf,
						PCIE20_PARF_BDF_TRANSLATE_N +
						dev->pcidev_table[i].short_bdf
						* 4,
						dev->pcidev_table[i].bdf >> 16);
				}
			}
		}
	}
}

static void msm_pcie_config_link_state(struct msm_pcie_dev_t *dev)
@@ -4130,106 +4104,41 @@ static int msm_pcie_config_device_table(struct device *dev, void *pdev)
	return ret;
}

int msm_pcie_configure_sid(struct device *dev, u32 *sid, int *domain)
static void msm_pcie_configure_sid(struct msm_pcie_dev_t *pcie_dev,
				struct pci_dev *dev)
{
	struct pci_dev *pcidev;
	struct msm_pcie_dev_t *pcie_dev;
	struct pci_bus *bus;
	int i;
	u32 offset;
	u32 sid;
	u32 bdf;
	int ret;

	if (!dev) {
		pr_err("%s: PCIe: endpoint device passed in is NULL\n",
			__func__);
		return MSM_PCIE_ERROR;
	}

	pcidev = to_pci_dev(dev);
	if (!pcidev) {
		pr_err("%s: PCIe: PCI device of endpoint is NULL\n",
			__func__);
		return MSM_PCIE_ERROR;
	}

	bus = pcidev->bus;
	if (!bus) {
		pr_err("%s: PCIe: Bus of PCI device is NULL\n",
			__func__);
		return MSM_PCIE_ERROR;
	}

	while (!pci_is_root_bus(bus))
		bus = bus->parent;

	pcie_dev = (struct msm_pcie_dev_t *)(bus->sysdata);
	if (!pcie_dev) {
		pr_err("%s: PCIe: Could not get PCIe structure\n",
			__func__);
		return MSM_PCIE_ERROR;
	}

	if (!pcie_dev->smmu_exist) {
	ret = iommu_fwspec_get_id(&dev->dev, &sid);
	if (ret) {
		PCIE_DBG(pcie_dev,
			"PCIe: RC:%d: smmu does not exist\n",
			"PCIe: RC%d: Device does not have a SID\n",
			pcie_dev->rc_idx);
		return MSM_PCIE_ERROR;
		return;
	}

	PCIE_DBG(pcie_dev, "PCIe: RC%d: device address is: %p\n",
		pcie_dev->rc_idx, dev);
	PCIE_DBG(pcie_dev, "PCIe: RC%d: PCI device address is: %p\n",
		pcie_dev->rc_idx, pcidev);
	PCIE_DBG(pcie_dev,
		"PCIe: RC%d: Device SID: 0x%x\n",
		pcie_dev->rc_idx, sid);

	*domain = pcie_dev->rc_idx;
	bdf = BDF_OFFSET(dev->bus->number, dev->devfn);
	offset = (sid - pcie_dev->smmu_sid_base) * 4;

	if (pcie_dev->current_short_bdf < (MAX_SHORT_BDF_NUM - 1)) {
		pcie_dev->current_short_bdf++;
	} else {
	if (offset >= MAX_SHORT_BDF_NUM * 4) {
		PCIE_ERR(pcie_dev,
			"PCIe: RC%d: No more short BDF left\n",
			pcie_dev->rc_idx);
		return MSM_PCIE_ERROR;
			"PCIe: RC%d: Invalid SID offset: 0x%x. Should be less than 0x%x\n",
			pcie_dev->rc_idx, offset, MAX_SHORT_BDF_NUM * 4);
		return;
	}

	bdf = BDF_OFFSET(pcidev->bus->number, pcidev->devfn);

	for (i = 0; i < MAX_DEVICE_NUM; i++) {
		if (pcie_dev->pcidev_table[i].bdf == bdf) {
			*sid = pcie_dev->smmu_sid_base +
				((pcie_dev->rc_idx << 4) |
				pcie_dev->current_short_bdf);

	msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_BDF_TRANSLATE_CFG, 0);
	msm_pcie_write_reg(pcie_dev->parf, PCIE20_PARF_SID_OFFSET, 0);
	msm_pcie_write_reg(pcie_dev->parf,
				PCIE20_PARF_BDF_TRANSLATE_N +
				pcie_dev->current_short_bdf * 4,
				bdf >> 16);

			pcie_dev->pcidev_table[i].sid = *sid;
			pcie_dev->pcidev_table[i].short_bdf =
				pcie_dev->current_short_bdf;
			break;
		}
	}

	if (i == MAX_DEVICE_NUM) {
		pcie_dev->current_short_bdf--;
		PCIE_ERR(pcie_dev,
			"PCIe: RC%d could not find BDF:%d\n",
			pcie_dev->rc_idx, bdf);
		return MSM_PCIE_ERROR;
	}

	PCIE_DBG(pcie_dev,
		"PCIe: RC%d: Device: %02x:%02x.%01x received SID %d\n",
		pcie_dev->rc_idx,
		bdf >> 24,
		bdf >> 19 & 0x1f,
		bdf >> 16 & 0x07,
		*sid);

	return 0;
		PCIE20_PARF_BDF_TRANSLATE_N + offset, bdf >> 16);
}
EXPORT_SYMBOL(msm_pcie_configure_sid);

int msm_pcie_enumerate(u32 rc_idx)
{
@@ -5343,6 +5252,8 @@ static int msm_pcie_config_device(struct pci_dev *dev, void *pdev)
	PCIE_DBG(pcie_dev, "PCIe: RC%d: configure PCI device %02x:%02x.%01x\n",
		pcie_dev->rc_idx, busnr, slot, func);

	msm_pcie_configure_sid(pcie_dev, dev);

	return 0;
}

@@ -5628,7 +5539,6 @@ static int msm_pcie_probe(struct platform_device *pdev)
	msm_pcie_dev[rc_idx].wake_counter = 0;
	msm_pcie_dev[rc_idx].aer_enable = true;
	msm_pcie_dev[rc_idx].power_on = false;
	msm_pcie_dev[rc_idx].current_short_bdf = 0;
	msm_pcie_dev[rc_idx].use_msi = false;
	msm_pcie_dev[rc_idx].use_pinctrl = false;
	msm_pcie_dev[rc_idx].linkdown_panic = false;
+0 −18
Original line number Diff line number Diff line
@@ -157,18 +157,6 @@ int msm_pcie_shadow_control(struct pci_dev *dev, bool enable);
int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
			u32 offset, u32 mask, u32 value);

/*
 * msm_pcie_configure_sid - calculates the SID for a PCIe endpoint.
 * @dev:	device structure
 * @sid:	the calculated SID
 * @domain:	the domain number of the Root Complex
 *
 * This function calculates the SID for a PCIe endpoint device.
 *
 * Return: 0 on success, negative value on error
 */
int msm_pcie_configure_sid(struct device *dev, u32 *sid,
			int *domain);
#else /* !CONFIG_PCI_MSM */
static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr,
			void *user, void *data, u32 options)
@@ -206,12 +194,6 @@ static inline int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
{
	return -ENODEV;
}

static inline int msm_pcie_configure_sid(struct device *dev, u32 *sid,
			int *domain)
{
	return -ENODEV;
}
#endif /* CONFIG_PCI_MSM */

#endif /* __MSM_PCIE_H */