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

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
...@@ -445,6 +445,7 @@ struct hl_mmu_properties { ...@@ -445,6 +445,7 @@ struct hl_mmu_properties {
* @dram_supports_virtual_memory: is there an MMU towards the DRAM * @dram_supports_virtual_memory: is there an MMU towards the DRAM
* @hard_reset_done_by_fw: true if firmware is handling hard reset flow * @hard_reset_done_by_fw: true if firmware is handling hard reset flow
* @num_functional_hbms: number of functional HBMs in each DCORE. * @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 asic_fixed_properties {
struct hw_queue_properties *hw_queues_props; struct hw_queue_properties *hw_queues_props;
...@@ -508,6 +509,7 @@ struct asic_fixed_properties { ...@@ -508,6 +509,7 @@ struct asic_fixed_properties {
u8 dram_supports_virtual_memory; u8 dram_supports_virtual_memory;
u8 hard_reset_done_by_fw; u8 hard_reset_done_by_fw;
u8 num_functional_hbms; 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, ...@@ -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], int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3],
bool is_wc[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_iatu_write(struct hl_device *hdev, u32 addr, u32 data);
int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region, int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
struct hl_inbound_pci_region *pci_region); struct hl_inbound_pci_region *pci_region);
......
...@@ -85,6 +85,58 @@ static void hl_pci_bars_unmap(struct hl_device *hdev) ...@@ -85,6 +85,58 @@ static void hl_pci_bars_unmap(struct hl_device *hdev)
pci_release_regions(pdev); 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. * hl_pci_elbi_write() - Write through the ELBI interface.
* @hdev: Pointer to hl_device structure. * @hdev: Pointer to hl_device structure.
......
...@@ -629,6 +629,11 @@ static int gaudi_init_iatu(struct hl_device *hdev) ...@@ -629,6 +629,11 @@ static int gaudi_init_iatu(struct hl_device *hdev)
struct hl_outbound_pci_region outbound_region; struct hl_outbound_pci_region outbound_region;
int rc; 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 0 - Bar 0 - Point to SRAM + CFG */
inbound_region.mode = PCI_BAR_MATCH_MODE; inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = SRAM_BAR_ID; inbound_region.bar = SRAM_BAR_ID;
...@@ -673,6 +678,7 @@ static int gaudi_early_init(struct hl_device *hdev) ...@@ -673,6 +678,7 @@ static int gaudi_early_init(struct hl_device *hdev)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
struct pci_dev *pdev = hdev->pdev; struct pci_dev *pdev = hdev->pdev;
u32 fw_boot_status;
int rc; int rc;
rc = gaudi_get_fixed_properties(hdev); rc = gaudi_get_fixed_properties(hdev);
...@@ -706,6 +712,23 @@ static int gaudi_early_init(struct hl_device *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); 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); rc = hl_pci_init(hdev);
if (rc) if (rc)
goto free_queue_props; goto free_queue_props;
......
...@@ -555,6 +555,11 @@ static int goya_init_iatu(struct hl_device *hdev) ...@@ -555,6 +555,11 @@ static int goya_init_iatu(struct hl_device *hdev)
struct hl_outbound_pci_region outbound_region; struct hl_outbound_pci_region outbound_region;
int rc; 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 0 - Bar 0 - Point to SRAM and CFG */
inbound_region.mode = PCI_BAR_MATCH_MODE; inbound_region.mode = PCI_BAR_MATCH_MODE;
inbound_region.bar = SRAM_CFG_BAR_ID; inbound_region.bar = SRAM_CFG_BAR_ID;
...@@ -602,7 +607,7 @@ static int goya_early_init(struct hl_device *hdev) ...@@ -602,7 +607,7 @@ static int goya_early_init(struct hl_device *hdev)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
struct pci_dev *pdev = hdev->pdev; struct pci_dev *pdev = hdev->pdev;
u32 val; u32 fw_boot_status, val;
int rc; int rc;
rc = goya_get_fixed_properties(hdev); rc = goya_get_fixed_properties(hdev);
...@@ -636,6 +641,23 @@ static int goya_early_init(struct hl_device *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); 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); rc = hl_pci_init(hdev);
if (rc) if (rc)
goto free_queue_props; goto free_queue_props;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment