Commit 1222e069 authored by Lizhi Hou's avatar Lizhi Hou
Browse files

accel/amdxdna: Update message DMA buffer allocation



The latest firmware requires the message DMA buffer to
  - have a minimum size of 8K
  - use a power-of-two size
  - be aligned to the buffer size
  - not cross 64M boundary

Update the buffer allocation logic to meet these requirements and support
the latest firmware.

Reviewed-by: default avatarMario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: default avatarLizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20251219014356.2234241-1-lizhi.hou@amd.com
parent adca0ad9
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -338,8 +338,7 @@ void aie2_error_async_events_free(struct amdxdna_dev_hdl *ndev)
	destroy_workqueue(events->wq);
	mutex_lock(&xdna->dev_lock);

	dma_free_noncoherent(xdna->ddev.dev, events->size, events->buf,
			     events->addr, DMA_FROM_DEVICE);
	aie2_free_msg_buffer(ndev, events->size, events->buf, events->addr);
	kfree(events);
}

@@ -355,8 +354,8 @@ int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev)
	if (!events)
		return -ENOMEM;

	events->buf = dma_alloc_noncoherent(xdna->ddev.dev, total_size, &events->addr,
					    DMA_FROM_DEVICE, GFP_KERNEL);
	events->buf = aie2_alloc_msg_buffer(ndev, &total_size, &events->addr);

	if (!events->buf) {
		ret = -ENOMEM;
		goto free_events;
@@ -396,8 +395,7 @@ int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev)
free_wq:
	destroy_workqueue(events->wq);
free_buf:
	dma_free_noncoherent(xdna->ddev.dev, events->size, events->buf,
			     events->addr, DMA_FROM_DEVICE);
	aie2_free_msg_buffer(ndev, events->size, events->buf, events->addr);
free_events:
	kfree(events);
	return ret;
+24 −9
Original line number Diff line number Diff line
@@ -55,6 +55,22 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev,
	return ret;
}

void *aie2_alloc_msg_buffer(struct amdxdna_dev_hdl *ndev, u32 *size,
			    dma_addr_t *dma_addr)
{
	struct amdxdna_dev *xdna = ndev->xdna;
	int order;

	*size = max(*size, SZ_8K);
	order = get_order(*size);
	if (order > MAX_PAGE_ORDER)
		return NULL;
	*size = PAGE_SIZE << order;

	return dma_alloc_noncoherent(xdna->ddev.dev, *size, dma_addr,
				     DMA_FROM_DEVICE, GFP_KERNEL);
}

int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)
{
	DECLARE_AIE2_MSG(suspend, MSG_OP_SUSPEND);
@@ -346,14 +362,13 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
{
	DECLARE_AIE2_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS);
	struct amdxdna_dev *xdna = ndev->xdna;
	u32 buf_sz = size, aie_bitmap = 0;
	struct amdxdna_client *client;
	dma_addr_t dma_addr;
	u32 aie_bitmap = 0;
	u8 *buff_addr;
	int ret;

	buff_addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr,
					  DMA_FROM_DEVICE, GFP_KERNEL);
	buff_addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
	if (!buff_addr)
		return -ENOMEM;

@@ -363,7 +378,7 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,

	*cols_filled = 0;
	req.dump_buff_addr = dma_addr;
	req.dump_buff_size = size;
	req.dump_buff_size = buf_sz;
	req.num_cols = hweight32(aie_bitmap);
	req.aie_bitmap = aie_bitmap;

@@ -391,7 +406,7 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
	*cols_filled = aie_bitmap;

fail:
	dma_free_noncoherent(xdna->ddev.dev, size, buff_addr, dma_addr, DMA_FROM_DEVICE);
	aie2_free_msg_buffer(ndev, buf_sz, buff_addr, dma_addr);
	return ret;
}

@@ -402,19 +417,19 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
	DECLARE_AIE2_MSG(get_telemetry, MSG_OP_GET_TELEMETRY);
	struct amdxdna_dev *xdna = ndev->xdna;
	dma_addr_t dma_addr;
	u32 buf_sz = size;
	u8 *addr;
	int ret;

	if (header->type >= MAX_TELEMETRY_TYPE)
		return -EINVAL;

	addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr,
				     DMA_FROM_DEVICE, GFP_KERNEL);
	addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
	if (!addr)
		return -ENOMEM;

	req.buf_addr = dma_addr;
	req.buf_size = size;
	req.buf_size = buf_sz;
	req.type = header->type;

	drm_clflush_virt_range(addr, size); /* device can access */
@@ -440,7 +455,7 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl *ndev,
	header->minor = resp.minor;

free_buf:
	dma_free_noncoherent(xdna->ddev.dev, size, addr, dma_addr, DMA_FROM_DEVICE);
	aie2_free_msg_buffer(ndev, buf_sz, addr, dma_addr);
	return ret;
}

+5 −0
Original line number Diff line number Diff line
@@ -336,6 +336,11 @@ int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
		 int (*notify_cb)(void *, void __iomem *, size_t));
int aie2_config_debug_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
			 int (*notify_cb)(void *, void __iomem *, size_t));
void *aie2_alloc_msg_buffer(struct amdxdna_dev_hdl *ndev, u32 *size,
			    dma_addr_t *dma_addr);
#define aie2_free_msg_buffer(ndev, size, buff_addr, dma_addr)		\
	dma_free_noncoherent((ndev)->xdna->ddev.dev, size, buff_addr,	\
			     dma_addr, DMA_FROM_DEVICE)

/* aie2_hwctx.c */
int aie2_hwctx_init(struct amdxdna_hwctx *hwctx);