[PATCH 1/2] habanalabs: retrieve DMA mask indication from firmware

From: Oded Gabbay
Date: Tue Mar 31 2020 - 10:56:07 EST


Retrieve from the firmware the DMA mask value we need to set according to
the device's PCI controller configuration. This is needed when working on
POWER9 machines, as the device's PCI controller is configured in a
different way in those machines.

Signed-off-by: Oded Gabbay <oded.gabbay@xxxxxxxxx>
---
drivers/misc/habanalabs/goya/goya.c | 19 +++++-
drivers/misc/habanalabs/habanalabs.h | 9 ++-
drivers/misc/habanalabs/include/hl_boot_if.h | 1 +
drivers/misc/habanalabs/pci.c | 63 +++++++++-----------
4 files changed, 53 insertions(+), 39 deletions(-)

diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c
index a0a96ca31757..85f29cb7d67b 100644
--- a/drivers/misc/habanalabs/goya/goya.c
+++ b/drivers/misc/habanalabs/goya/goya.c
@@ -531,7 +531,7 @@ static int goya_early_init(struct hl_device *hdev)

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

- rc = hl_pci_init(hdev, 48);
+ rc = hl_pci_init(hdev);
if (rc)
return rc;

@@ -5185,6 +5185,20 @@ u32 goya_get_queue_id_for_cq(struct hl_device *hdev, u32 cq_idx)
return cq_idx;
}

+static void goya_set_dma_mask_from_fw(struct hl_device *hdev)
+{
+ if (RREG32(mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_0) ==
+ HL_POWER9_HOST_MAGIC) {
+ dev_dbg(hdev->dev, "Working in 64-bit DMA mode\n");
+ hdev->power9_64bit_dma_enable = 1;
+ hdev->dma_mask = 64;
+ } else {
+ dev_dbg(hdev->dev, "Working in 48-bit DMA mode\n");
+ hdev->power9_64bit_dma_enable = 0;
+ hdev->dma_mask = 48;
+ }
+}
+
static const struct hl_asic_funcs goya_funcs = {
.early_init = goya_early_init,
.early_fini = goya_early_fini,
@@ -5247,7 +5261,8 @@ static const struct hl_asic_funcs goya_funcs = {
.get_clk_rate = goya_get_clk_rate,
.get_queue_id_for_cq = goya_get_queue_id_for_cq,
.read_device_fw_version = goya_read_device_fw_version,
- .load_firmware_to_device = goya_load_firmware_to_device
+ .load_firmware_to_device = goya_load_firmware_to_device,
+ .set_dma_mask_from_fw = goya_set_dma_mask_from_fw
};

/*
diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h
index 6c54d0ba0a1d..29b9767387af 100644
--- a/drivers/misc/habanalabs/habanalabs.h
+++ b/drivers/misc/habanalabs/habanalabs.h
@@ -552,6 +552,8 @@ enum hl_pll_frequency {
* @read_device_fw_version: read the device's firmware versions that are
* contained in registers
* @load_firmware_to_device: load the firmware to the device's memory
+ * @set_dma_mask_from_fw: set the DMA mask in the driver according to the
+ * firmware configuration
*/
struct hl_asic_funcs {
int (*early_init)(struct hl_device *hdev);
@@ -642,6 +644,7 @@ struct hl_asic_funcs {
void (*read_device_fw_version)(struct hl_device *hdev,
enum hl_fw_component fwc);
int (*load_firmware_to_device)(struct hl_device *hdev);
+ void (*set_dma_mask_from_fw)(struct hl_device *hdev);
};


@@ -1321,6 +1324,8 @@ struct hl_device_idle_busy_ts {
* @dma_mask: the dma mask that was set for this device
* @in_debug: is device under debug. This, together with fpriv_list, enforces
* that only a single user is configuring the debug infrastructure.
+ * @power9_64bit_dma_enable: true to enable 64-bit DMA mask support. Relevant
+ * only to POWER9 machines.
* @cdev_sysfs_created: were char devices and sysfs nodes created.
* @stop_on_err: true if engines should stop on error.
*/
@@ -1402,6 +1407,7 @@ struct hl_device {
u8 device_cpu_disabled;
u8 dma_mask;
u8 in_debug;
+ u8 power9_64bit_dma_enable;
u8 cdev_sysfs_created;
u8 stop_on_err;

@@ -1632,9 +1638,8 @@ int hl_pci_set_dram_bar_base(struct hl_device *hdev, u8 inbound_region, u8 bar,
int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
u64 dram_base_address, u64 host_phys_base_address,
u64 host_phys_size);
-int hl_pci_init(struct hl_device *hdev, u8 dma_mask);
+int hl_pci_init(struct hl_device *hdev);
void hl_pci_fini(struct hl_device *hdev);
-int hl_pci_set_dma_mask(struct hl_device *hdev, u8 dma_mask);

long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr);
void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq);
diff --git a/drivers/misc/habanalabs/include/hl_boot_if.h b/drivers/misc/habanalabs/include/hl_boot_if.h
index 660550604362..7106315fc92e 100644
--- a/drivers/misc/habanalabs/include/hl_boot_if.h
+++ b/drivers/misc/habanalabs/include/hl_boot_if.h
@@ -9,6 +9,7 @@
#define HL_BOOT_IF_H

#define LKD_HARD_RESET_MAGIC 0xED7BD694
+#define HL_POWER9_HOST_MAGIC 0x1DA30009

/*
* CPU error bits in BOOT_ERROR registers
diff --git a/drivers/misc/habanalabs/pci.c b/drivers/misc/habanalabs/pci.c
index c98d88c7a5c6..0aef4af9f5ec 100644
--- a/drivers/misc/habanalabs/pci.c
+++ b/drivers/misc/habanalabs/pci.c
@@ -267,6 +267,12 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
/* Enable + Bar match + match enable */
rc |= hl_pci_iatu_write(hdev, 0x104, 0xC0080000);

+ /* Return the DBI window to the default location */
+ rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);
+ rc |= hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr + 4, 0);
+
+ hdev->asic_funcs->set_dma_mask_from_fw(hdev);
+
/* Point to DRAM */
if (!hdev->asic_funcs->set_dram_bar_base)
return -EINVAL;
@@ -274,7 +280,6 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
U64_MAX)
return -EIO;

-
/* Outbound Region 0 - Point to Host */
host_phys_end_addr = host_phys_base_address + host_phys_size - 1;
rc |= hl_pci_iatu_write(hdev, 0x008,
@@ -283,7 +288,12 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
upper_32_bits(host_phys_base_address));
rc |= hl_pci_iatu_write(hdev, 0x010, lower_32_bits(host_phys_end_addr));
rc |= hl_pci_iatu_write(hdev, 0x014, 0);
- rc |= hl_pci_iatu_write(hdev, 0x018, 0);
+
+ if ((hdev->power9_64bit_dma_enable) && (hdev->dma_mask == 64))
+ rc |= hl_pci_iatu_write(hdev, 0x018, 0x08000000);
+ else
+ rc |= hl_pci_iatu_write(hdev, 0x018, 0);
+
rc |= hl_pci_iatu_write(hdev, 0x020, upper_32_bits(host_phys_end_addr));
/* Increase region size */
rc |= hl_pci_iatu_write(hdev, 0x000, 0x00002000);
@@ -310,41 +320,25 @@ int hl_pci_init_iatu(struct hl_device *hdev, u64 sram_base_address,
*
* Return: 0 on success, non-zero for failure.
*/
-int hl_pci_set_dma_mask(struct hl_device *hdev, u8 dma_mask)
+int hl_pci_set_dma_mask(struct hl_device *hdev)
{
struct pci_dev *pdev = hdev->pdev;
int rc;

/* set DMA mask */
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_mask));
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(hdev->dma_mask));
if (rc) {
- dev_warn(hdev->dev,
+ dev_err(hdev->dev,
"Failed to set pci dma mask to %d bits, error %d\n",
- dma_mask, rc);
-
- dma_mask = hdev->dma_mask;
-
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_mask));
- if (rc) {
- dev_err(hdev->dev,
- "Failed to set pci dma mask to %d bits, error %d\n",
- dma_mask, rc);
- return rc;
- }
+ hdev->dma_mask, rc);
+ return rc;
}

- /*
- * We managed to set the dma mask, so update the dma mask field. If
- * the set to the coherent mask will fail with that mask, we will
- * fail the entire function
- */
- hdev->dma_mask = dma_mask;
-
- rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_mask));
+ rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(hdev->dma_mask));
if (rc) {
dev_err(hdev->dev,
"Failed to set pci consistent dma mask to %d bits, error %d\n",
- dma_mask, rc);
+ hdev->dma_mask, rc);
return rc;
}

@@ -354,21 +348,16 @@ int hl_pci_set_dma_mask(struct hl_device *hdev, u8 dma_mask)
/**
* hl_pci_init() - PCI initialization code.
* @hdev: Pointer to hl_device structure.
- * @dma_mask: number of bits for the requested dma mask.
*
* Set DMA masks, initialize the PCI controller and map the PCI BARs.
*
* Return: 0 on success, non-zero for failure.
*/
-int hl_pci_init(struct hl_device *hdev, u8 dma_mask)
+int hl_pci_init(struct hl_device *hdev)
{
struct pci_dev *pdev = hdev->pdev;
int rc;

- rc = hl_pci_set_dma_mask(hdev, dma_mask);
- if (rc)
- return rc;
-
if (hdev->reset_pcilink)
hl_pci_reset_link_through_bridge(hdev);

@@ -380,18 +369,22 @@ int hl_pci_init(struct hl_device *hdev, u8 dma_mask)

pci_set_master(pdev);

- rc = hdev->asic_funcs->init_iatu(hdev);
+ rc = hdev->asic_funcs->pci_bars_map(hdev);
if (rc) {
- dev_err(hdev->dev, "Failed to initialize iATU\n");
+ dev_err(hdev->dev, "Failed to initialize PCI BARs\n");
goto disable_device;
}

- rc = hdev->asic_funcs->pci_bars_map(hdev);
+ rc = hdev->asic_funcs->init_iatu(hdev);
if (rc) {
- dev_err(hdev->dev, "Failed to initialize PCI BARs\n");
+ dev_err(hdev->dev, "Failed to initialize iATU\n");
goto disable_device;
}

+ rc = hl_pci_set_dma_mask(hdev);
+ if (rc)
+ goto disable_device;
+
return 0;

disable_device:
--
2.17.1