-
Notifications
You must be signed in to change notification settings - Fork 93
ve2: added support to allocate cma bo from multiple cma regions #887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,8 @@ | |
| #include <linux/device.h> | ||
| #include <linux/firmware.h> | ||
| #include <linux/xlnx-ai-engine.h> | ||
| #include <linux/firmware.h> | ||
| #include <linux/of_reserved_mem.h> | ||
| #include <linux/of_address.h> | ||
|
|
||
| #include "ve2_of.h" | ||
| #include "ve2_mgmt.h" | ||
|
|
@@ -84,6 +85,94 @@ static int ve2_load_fw(struct amdxdna_dev_hdl *xdna_hdl) | |
| return ret; | ||
| } | ||
|
|
||
| static void ve2_cma_device_release(struct device *dev) | ||
| { | ||
| /* | ||
| * All DMA and reserved memory resources are released by | ||
| * of_reserved_mem_device_release() before this function is called. | ||
| * This release function only needs to free the device structure itself. | ||
| */ | ||
| kfree(dev); | ||
| } | ||
|
|
||
| static void ve2_cma_mem_region_remove(struct amdxdna_dev *xdna) | ||
| { | ||
| int i; | ||
|
|
||
| for (i = 0; i < MAX_MEM_REGIONS; i++) { | ||
| struct amdxdna_cma_mem_region *region; | ||
|
|
||
| region = &xdna->cma_mem_regions[i]; | ||
| if (region->initialized) { | ||
| of_reserved_mem_device_release(region->dev); | ||
| put_device(region->dev); | ||
| region->dev = NULL; | ||
| region->initialized = false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static int | ||
| ve2_cma_mem_region_init(struct amdxdna_dev *xdna, | ||
| struct platform_device *pdev) | ||
| { | ||
| int num_regions; | ||
| int ret = 0; | ||
| int i; | ||
|
|
||
| xdna->num_cma_regions = 0; | ||
|
|
||
| num_regions = of_count_phandle_with_args(pdev->dev.of_node, | ||
| "memory-region", NULL); | ||
| if (num_regions <= 0) | ||
| return -EINVAL; | ||
|
|
||
| for (i = 0; i < num_regions && i < MAX_MEM_REGIONS; i++) { | ||
| struct device *child_dev; | ||
|
|
||
| child_dev = kzalloc(sizeof(*child_dev), GFP_KERNEL); | ||
| if (!child_dev) { | ||
| XDNA_ERR(xdna, | ||
| "Failed to alloc child_dev for cma region %d\n", | ||
| i); | ||
| ve2_cma_mem_region_remove(xdna); | ||
| return -ENOMEM; | ||
| } | ||
|
|
||
| device_initialize(child_dev); | ||
| child_dev->parent = &pdev->dev; | ||
| child_dev->of_node = pdev->dev.of_node; | ||
| child_dev->coherent_dma_mask = DMA_BIT_MASK(64); | ||
| child_dev->release = ve2_cma_device_release; | ||
|
|
||
| ret = dev_set_name(child_dev, "amdxdna-mem%d", i); | ||
| if (ret) { | ||
| XDNA_DBG(xdna, | ||
| "Failed to set name for cma region %d\n", i); | ||
| put_device(child_dev); | ||
| continue; | ||
| } | ||
|
|
||
| ret = of_reserved_mem_device_init_by_idx(child_dev, | ||
| pdev->dev.of_node, i); | ||
| if (ret) { | ||
| XDNA_DBG(xdna, | ||
| "Failed to init reserved cma region %d\n", i); | ||
| put_device(child_dev); | ||
| continue; | ||
|
Comment on lines
+156
to
+162
|
||
| } | ||
|
|
||
| xdna->cma_mem_regions[i].dev = child_dev; | ||
| xdna->cma_mem_regions[i].initialized = true; | ||
| xdna->num_cma_regions++; | ||
| } | ||
|
|
||
| if (xdna->num_cma_regions == 0) | ||
| return -EINVAL; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int ve2_init(struct amdxdna_dev *xdna) | ||
| { | ||
| struct platform_device *pdev = to_platform_device(xdna->ddev.dev); | ||
|
|
@@ -133,6 +222,12 @@ static int ve2_init(struct amdxdna_dev *xdna) | |
| xdna->dev_handle->fw_slots[col] = fw_slots; | ||
| } | ||
|
|
||
| ret = ve2_cma_mem_region_init(xdna, pdev); | ||
| if (ret < 0) { | ||
| /* CMA region initialization is optional - system will fall back to default CMA */ | ||
| XDNA_DBG(xdna, "Failed to initialize the cma memories\n"); | ||
| } | ||
|
|
||
| return 0; | ||
| done: | ||
| ve2_free_firmware_slots(xdna_hdl, VE2_MAX_COL); | ||
|
|
@@ -143,6 +238,7 @@ static int ve2_init(struct amdxdna_dev *xdna) | |
| static void ve2_fini(struct amdxdna_dev *xdna) | ||
| { | ||
| ve2_free_firmware_slots(xdna->dev_handle, VE2_MAX_COL); | ||
| ve2_cma_mem_region_remove(xdna); | ||
| } | ||
|
|
||
| const struct amdxdna_dev_ops ve2_ops = { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On
dev_set_name()failure, the device is freed butve2_cma_mem_region_remove()is not called to clean up any previously initialized regions before returning. This leaves partially initialized state. Consider callingve2_cma_mem_region_remove(xdna)before continuing or ensure proper cleanup on any failure path.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
continuestatement implements intentional fallback behavior. If one CMA regionfails to initialize, the driver tries remaining regions. The
put_device()callproperly cleans up the failed region. Only if all regions fail the function
returns -EINVAL (line 170).