Commit 41f458f2 authored by Ofir Bitton's avatar Ofir Bitton Committed by Oded Gabbay
Browse files

habanalabs/gaudi: skip iATU if F/W security is enabled



As part of the securing GAUDI, the F/W will configure the PCI iATU
regions. If the driver identifies a secured PCI ID, it will know to
skip iATU configuration in a very early stage.

Signed-off-by: default avatarOfir Bitton <obitton@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent e5042a6f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -445,6 +445,7 @@ struct hl_mmu_properties {
 * @dram_supports_virtual_memory: is there an MMU towards the DRAM
 * @hard_reset_done_by_fw: true if firmware is handling hard reset flow
 * @num_functional_hbms: number of functional HBMs in each DCORE.
 * @iatu_done_by_fw: true if iATU configuration is being done by FW.
 */
struct asic_fixed_properties {
	struct hw_queue_properties	*hw_queues_props;
@@ -508,6 +509,7 @@ struct asic_fixed_properties {
	u8				dram_supports_virtual_memory;
	u8				hard_reset_done_by_fw;
	u8				num_functional_hbms;
	u8				iatu_done_by_fw;
};

/**
@@ -2400,6 +2402,7 @@ int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg,

int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3],
			bool is_wc[3]);
int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data);
int hl_pci_iatu_write(struct hl_device *hdev, u32 addr, u32 data);
int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
		struct hl_inbound_pci_region *pci_region);
+52 −0
Original line number Diff line number Diff line
@@ -85,6 +85,58 @@ static void hl_pci_bars_unmap(struct hl_device *hdev)
	pci_release_regions(pdev);
}

int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data)
{
	struct pci_dev *pdev = hdev->pdev;
	ktime_t timeout;
	u64 msec;
	u32 val;

	if (hdev->pldm)
		msec = HL_PLDM_PCI_ELBI_TIMEOUT_MSEC;
	else
		msec = HL_PCI_ELBI_TIMEOUT_MSEC;

	/* Clear previous status */
	pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, 0);

	pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_ADDR, (u32) addr);
	pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_CTRL, 0);

	timeout = ktime_add_ms(ktime_get(), msec);
	for (;;) {
		pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, &val);
		if (val & PCI_CONFIG_ELBI_STS_MASK)
			break;
		if (ktime_compare(ktime_get(), timeout) > 0) {
			pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS,
						&val);
			break;
		}

		usleep_range(300, 500);
	}

	if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) {
		pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_DATA, data);

		return 0;
	}

	if (val & PCI_CONFIG_ELBI_STS_ERR) {
		dev_err(hdev->dev, "Error reading from ELBI\n");
		return -EIO;
	}

	if (!(val & PCI_CONFIG_ELBI_STS_MASK)) {
		dev_err(hdev->dev, "ELBI read didn't finish in time\n");
		return -EIO;
	}

	dev_err(hdev->dev, "ELBI read has undefined bits in status\n");
	return -EIO;
}

/**
 * hl_pci_elbi_write() - Write through the ELBI interface.
 * @hdev: Pointer to hl_device structure.
+23 −0
Original line number Diff line number Diff line
@@ -629,6 +629,11 @@ static int gaudi_init_iatu(struct hl_device *hdev)
	struct hl_outbound_pci_region outbound_region;
	int rc;

	if (hdev->asic_prop.iatu_done_by_fw) {
		hdev->asic_funcs->set_dma_mask_from_fw(hdev);
		return 0;
	}

	/* Inbound Region 0 - Bar 0 - Point to SRAM + CFG */
	inbound_region.mode = PCI_BAR_MATCH_MODE;
	inbound_region.bar = SRAM_BAR_ID;
@@ -673,6 +678,7 @@ static int gaudi_early_init(struct hl_device *hdev)
{
	struct asic_fixed_properties *prop = &hdev->asic_prop;
	struct pci_dev *pdev = hdev->pdev;
	u32 fw_boot_status;
	int rc;

	rc = gaudi_get_fixed_properties(hdev);
@@ -706,6 +712,23 @@ static int gaudi_early_init(struct hl_device *hdev)

	prop->dram_pci_bar_size = pci_resource_len(pdev, HBM_BAR_ID);

	/* If FW security is enabled at this point it means no access to ELBI */
	if (!hdev->asic_prop.fw_security_disabled) {
		hdev->asic_prop.iatu_done_by_fw = true;
		goto pci_init;
	}

	rc = hl_pci_elbi_read(hdev, CFG_BASE + mmCPU_BOOT_DEV_STS0,
				&fw_boot_status);
	if (rc)
		goto free_queue_props;

	/* Check whether FW is configuring iATU */
	if ((fw_boot_status & CPU_BOOT_DEV_STS0_ENABLED) &&
			(fw_boot_status & CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN))
		hdev->asic_prop.iatu_done_by_fw = true;

pci_init:
	rc = hl_pci_init(hdev);
	if (rc)
		goto free_queue_props;
+23 −1
Original line number Diff line number Diff line
@@ -555,6 +555,11 @@ static int goya_init_iatu(struct hl_device *hdev)
	struct hl_outbound_pci_region outbound_region;
	int rc;

	if (hdev->asic_prop.iatu_done_by_fw) {
		hdev->asic_funcs->set_dma_mask_from_fw(hdev);
		return 0;
	}

	/* Inbound Region 0 - Bar 0 - Point to SRAM and CFG */
	inbound_region.mode = PCI_BAR_MATCH_MODE;
	inbound_region.bar = SRAM_CFG_BAR_ID;
@@ -602,7 +607,7 @@ static int goya_early_init(struct hl_device *hdev)
{
	struct asic_fixed_properties *prop = &hdev->asic_prop;
	struct pci_dev *pdev = hdev->pdev;
	u32 val;
	u32 fw_boot_status, val;
	int rc;

	rc = goya_get_fixed_properties(hdev);
@@ -636,6 +641,23 @@ static int goya_early_init(struct hl_device *hdev)

	prop->dram_pci_bar_size = pci_resource_len(pdev, DDR_BAR_ID);

	/* If FW security is enabled at this point it means no access to ELBI */
	if (!hdev->asic_prop.fw_security_disabled) {
		hdev->asic_prop.iatu_done_by_fw = true;
		goto pci_init;
	}

	rc = hl_pci_elbi_read(hdev, CFG_BASE + mmCPU_BOOT_DEV_STS0,
				&fw_boot_status);
	if (rc)
		goto free_queue_props;

	/* Check whether FW is configuring iATU */
	if ((fw_boot_status & CPU_BOOT_DEV_STS0_ENABLED) &&
			(fw_boot_status & CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN))
		hdev->asic_prop.iatu_done_by_fw = true;

pci_init:
	rc = hl_pci_init(hdev);
	if (rc)
		goto free_queue_props;