Commit 1ef0c327 authored by Ohad Sharabi's avatar Ohad Sharabi Committed by Oded Gabbay
Browse files

habanalabs: refactor dma asic-specific functions



This is a pre-requisite patch for adding tracepoints to the DMA memory
operations (allocation/free) in the driver.

The main purpose is to be able to cross data with the map operations and
determine whether memory violation occurred, for example free DMA
allocation before unmapping it from device memory.

To achieve this the DMA alloc/free code flows were refactored so that a
single DMA tracepoint will catch many flows.

Signed-off-by: default avatarOhad Sharabi <osharabi@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent c37d50e8
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -143,8 +143,7 @@ static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
		gen_pool_free(hdev->internal_cb_pool,
				(uintptr_t)cb->kernel_address, cb->size);
	else
		hdev->asic_funcs->asic_dma_free_coherent(hdev, cb->size,
				cb->kernel_address, cb->bus_address);
		hl_asic_dma_free_coherent(hdev, cb->size, cb->kernel_address, cb->bus_address);

	kfree(cb);
}
@@ -195,14 +194,11 @@ static struct hl_cb *hl_cb_alloc(struct hl_device *hdev, u32 cb_size,
		cb->is_internal = true;
		cb->bus_address =  hdev->internal_cb_va_base + cb_offset;
	} else if (ctx_id == HL_KERNEL_ASID_ID) {
		p = hdev->asic_funcs->asic_dma_alloc_coherent(hdev, cb_size,
						&cb->bus_address, GFP_ATOMIC);
		p = hl_asic_dma_alloc_coherent(hdev, cb_size, &cb->bus_address, GFP_ATOMIC);
		if (!p)
			p = hdev->asic_funcs->asic_dma_alloc_coherent(hdev,
					cb_size, &cb->bus_address, GFP_KERNEL);
			p = hl_asic_dma_alloc_coherent(hdev, cb_size, &cb->bus_address, GFP_KERNEL);
	} else {
		p = hdev->asic_funcs->asic_dma_alloc_coherent(hdev, cb_size,
						&cb->bus_address,
		p = hl_asic_dma_alloc_coherent(hdev, cb_size, &cb->bus_address,
						GFP_USER | __GFP_ZERO);
	}

+75 −0
Original line number Diff line number Diff line
@@ -17,6 +17,12 @@

#define MEM_SCRUB_DEFAULT_VAL 0x1122334455667788

enum dma_alloc_type {
	DMA_ALLOC_COHERENT,
	DMA_ALLOC_CPU_ACCESSIBLE,
	DMA_ALLOC_POOL,
};

/*
 * hl_set_dram_bar- sets the bar to allow later access to address
 *
@@ -90,6 +96,75 @@ static int hl_access_sram_dram_region(struct hl_device *hdev, u64 addr, u64 *val
	return 0;
}

static void *hl_dma_alloc_common(struct hl_device *hdev, size_t size, dma_addr_t *dma_handle,
		gfp_t flag, enum dma_alloc_type alloc_type)
{
	void *ptr;

	switch (alloc_type) {
	case DMA_ALLOC_COHERENT:
		ptr = hdev->asic_funcs->asic_dma_alloc_coherent(hdev, size, dma_handle, flag);
		break;
	case DMA_ALLOC_CPU_ACCESSIBLE:
		ptr = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, size, dma_handle);
		break;
	case DMA_ALLOC_POOL:
		ptr = hdev->asic_funcs->asic_dma_pool_zalloc(hdev, size, flag, dma_handle);
		break;
	}

	return ptr;
}

static void hl_asic_dma_free_common(struct hl_device *hdev, size_t size, void *cpu_addr,
					dma_addr_t dma_handle, enum dma_alloc_type alloc_type)
{
	switch (alloc_type) {
	case DMA_ALLOC_COHERENT:
		hdev->asic_funcs->asic_dma_free_coherent(hdev, size, cpu_addr, dma_handle);
		break;
	case DMA_ALLOC_CPU_ACCESSIBLE:
		hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, size, cpu_addr);
		break;
	case DMA_ALLOC_POOL:
		hdev->asic_funcs->asic_dma_pool_free(hdev, cpu_addr, dma_handle);
		break;
	}
}

void *hl_asic_dma_alloc_coherent(struct hl_device *hdev, size_t size, dma_addr_t *dma_handle,
					gfp_t flag)
{
	return hl_dma_alloc_common(hdev, size, dma_handle, flag, DMA_ALLOC_COHERENT);
}

void hl_asic_dma_free_coherent(struct hl_device *hdev, size_t size, void *cpu_addr,
					dma_addr_t dma_handle)
{
	hl_asic_dma_free_common(hdev, size, cpu_addr, dma_handle, DMA_ALLOC_COHERENT);
}

void *hl_cpu_accessible_dma_pool_alloc(struct hl_device *hdev, size_t size, dma_addr_t *dma_handle)
{
	return hl_dma_alloc_common(hdev, size, dma_handle, 0, DMA_ALLOC_CPU_ACCESSIBLE);
}

void hl_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void *vaddr)
{
	hl_asic_dma_free_common(hdev, size, vaddr, 0, DMA_ALLOC_CPU_ACCESSIBLE);
}

void *hl_asic_dma_pool_zalloc(struct hl_device *hdev, size_t size, gfp_t mem_flags,
					dma_addr_t *dma_handle)
{
	return hl_dma_alloc_common(hdev, size, dma_handle, mem_flags, DMA_ALLOC_POOL);
}

void hl_asic_dma_pool_free(struct hl_device *hdev, void *vaddr, dma_addr_t dma_addr)
{
	hl_asic_dma_free_common(hdev, 0, vaddr, dma_addr, DMA_ALLOC_POOL);
}

int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_data_direction dir)
{
	struct asic_fixed_properties *prop = &hdev->asic_prop;
+15 −24
Original line number Diff line number Diff line
@@ -218,8 +218,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
	u32 tmp, expected_ack_val, pi;
	int rc;

	pkt = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, len,
								&pkt_dma_addr);
	pkt = hl_cpu_accessible_dma_pool_alloc(hdev, len, &pkt_dma_addr);
	if (!pkt) {
		dev_err(hdev->dev,
			"Failed to allocate DMA memory for packet to CPU\n");
@@ -303,7 +302,7 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
out:
	mutex_unlock(&hdev->send_cpu_message_lock);

	hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, len, pkt);
	hl_cpu_accessible_dma_pool_free(hdev, len, pkt);

	return rc;
}
@@ -644,9 +643,7 @@ int hl_fw_cpucp_info_get(struct hl_device *hdev,
	u64 result;
	int rc;

	cpucp_info_cpu_addr =
			hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
					sizeof(struct cpucp_info),
	cpucp_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, sizeof(struct cpucp_info),
								&cpucp_info_dma_addr);
	if (!cpucp_info_cpu_addr) {
		dev_err(hdev->dev,
@@ -708,8 +705,7 @@ int hl_fw_cpucp_info_get(struct hl_device *hdev,
		prop->fw_app_cpu_boot_dev_sts1 = RREG32(sts_boot_dev_sts1_reg);

out:
	hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
			sizeof(struct cpucp_info), cpucp_info_cpu_addr);
	hl_cpu_accessible_dma_pool_free(hdev, sizeof(struct cpucp_info), cpucp_info_cpu_addr);

	return rc;
}
@@ -792,9 +788,8 @@ int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size)
	u64 result;
	int rc;

	eeprom_info_cpu_addr =
			hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
					max_size, &eeprom_info_dma_addr);
	eeprom_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, max_size,
									&eeprom_info_dma_addr);
	if (!eeprom_info_cpu_addr) {
		dev_err(hdev->dev,
			"Failed to allocate DMA memory for CPU-CP EEPROM packet\n");
@@ -822,8 +817,7 @@ int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size)
	memcpy(data, eeprom_info_cpu_addr, min((size_t)result, max_size));

out:
	hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, max_size,
			eeprom_info_cpu_addr);
	hl_cpu_accessible_dma_pool_free(hdev, max_size, eeprom_info_cpu_addr);

	return rc;
}
@@ -840,8 +834,7 @@ int hl_fw_get_monitor_dump(struct hl_device *hdev, void *data)
	int i, rc;

	data_size = sizeof(struct cpucp_monitor_dump);
	mon_dump_cpu_addr = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev, data_size,
										&mon_dump_dma_addr);
	mon_dump_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, data_size, &mon_dump_dma_addr);
	if (!mon_dump_cpu_addr) {
		dev_err(hdev->dev,
			"Failed to allocate DMA memory for CPU-CP monitor-dump packet\n");
@@ -871,7 +864,7 @@ int hl_fw_get_monitor_dump(struct hl_device *hdev, void *data)
	}

out:
	hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev, data_size, mon_dump_cpu_addr);
	hl_cpu_accessible_dma_pool_free(hdev, data_size, mon_dump_cpu_addr);

	return rc;
}
@@ -1064,8 +1057,7 @@ int hl_fw_dram_replaced_row_get(struct hl_device *hdev,
	u64 result;
	int rc;

	cpucp_repl_rows_info_cpu_addr =
			hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
	cpucp_repl_rows_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev,
							sizeof(struct cpucp_hbm_row_info),
							&cpucp_repl_rows_info_dma_addr);
	if (!cpucp_repl_rows_info_cpu_addr) {
@@ -1092,8 +1084,7 @@ int hl_fw_dram_replaced_row_get(struct hl_device *hdev,
	memcpy(info, cpucp_repl_rows_info_cpu_addr, sizeof(*info));

out:
	hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
					sizeof(struct cpucp_hbm_row_info),
	hl_cpu_accessible_dma_pool_free(hdev, sizeof(struct cpucp_hbm_row_info),
						cpucp_repl_rows_info_cpu_addr);

	return rc;
+9 −0
Original line number Diff line number Diff line
@@ -3121,6 +3121,15 @@ static inline bool hl_mem_area_crosses_range(u64 address, u32 size,
}

uint64_t hl_set_dram_bar_default(struct hl_device *hdev, u64 addr);
void *hl_asic_dma_alloc_coherent(struct hl_device *hdev, size_t size, dma_addr_t *dma_handle,
					gfp_t flag);
void hl_asic_dma_free_coherent(struct hl_device *hdev, size_t size, void *cpu_addr,
					dma_addr_t dma_handle);
void *hl_cpu_accessible_dma_pool_alloc(struct hl_device *hdev, size_t size, dma_addr_t *dma_handle);
void hl_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void *vaddr);
void *hl_asic_dma_pool_zalloc(struct hl_device *hdev, size_t size, gfp_t mem_flags,
					dma_addr_t *dma_handle);
void hl_asic_dma_pool_free(struct hl_device *hdev, void *vaddr, dma_addr_t dma_addr);
int hl_dma_map_sgtable(struct hl_device *hdev, struct sg_table *sgt, enum dma_data_direction dir);
void hl_dma_unmap_sgtable(struct hl_device *hdev, struct sg_table *sgt,
				enum dma_data_direction dir);
+10 −24
Original line number Diff line number Diff line
@@ -807,13 +807,9 @@ static int ext_and_cpu_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,
	int rc;

	if (is_cpu_queue)
		p = hdev->asic_funcs->cpu_accessible_dma_pool_alloc(hdev,
							HL_QUEUE_SIZE_IN_BYTES,
							&q->bus_address);
		p = hl_cpu_accessible_dma_pool_alloc(hdev, HL_QUEUE_SIZE_IN_BYTES, &q->bus_address);
	else
		p = hdev->asic_funcs->asic_dma_alloc_coherent(hdev,
						HL_QUEUE_SIZE_IN_BYTES,
						&q->bus_address,
		p = hl_asic_dma_alloc_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES, &q->bus_address,
						GFP_KERNEL | __GFP_ZERO);
	if (!p)
		return -ENOMEM;
@@ -839,13 +835,9 @@ static int ext_and_cpu_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,

free_queue:
	if (is_cpu_queue)
		hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
					HL_QUEUE_SIZE_IN_BYTES,
					q->kernel_address);
		hl_cpu_accessible_dma_pool_free(hdev, HL_QUEUE_SIZE_IN_BYTES, q->kernel_address);
	else
		hdev->asic_funcs->asic_dma_free_coherent(hdev,
					HL_QUEUE_SIZE_IN_BYTES,
					q->kernel_address,
		hl_asic_dma_free_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES, q->kernel_address,
						q->bus_address);

	return rc;
@@ -885,9 +877,7 @@ static int hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
{
	void *p;

	p = hdev->asic_funcs->asic_dma_alloc_coherent(hdev,
						HL_QUEUE_SIZE_IN_BYTES,
						&q->bus_address,
	p = hl_asic_dma_alloc_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES, &q->bus_address,
					GFP_KERNEL | __GFP_ZERO);
	if (!p)
		return -ENOMEM;
@@ -1061,13 +1051,9 @@ static void queue_fini(struct hl_device *hdev, struct hl_hw_queue *q)
	kfree(q->shadow_queue);

	if (q->queue_type == QUEUE_TYPE_CPU)
		hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
					HL_QUEUE_SIZE_IN_BYTES,
					q->kernel_address);
		hl_cpu_accessible_dma_pool_free(hdev, HL_QUEUE_SIZE_IN_BYTES, q->kernel_address);
	else
		hdev->asic_funcs->asic_dma_free_coherent(hdev,
					HL_QUEUE_SIZE_IN_BYTES,
					q->kernel_address,
		hl_asic_dma_free_coherent(hdev, HL_QUEUE_SIZE_IN_BYTES, q->kernel_address,
						q->bus_address);
}

Loading