mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 12:10:38 -04:00
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: Ofir Bitton <obitton@habana.ai> Reviewed-by: Oded Gabbay <ogabbay@kernel.org> Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
This commit is contained in:
@@ -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 {
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user