hinic3_queue_common.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
  3. #include <linux/device.h>
  4. #include "hinic3_hwdev.h"
  5. #include "hinic3_queue_common.h"
  6. void hinic3_queue_pages_init(struct hinic3_queue_pages *qpages, u32 q_depth,
  7. u32 page_size, u32 elem_size)
  8. {
  9. u32 elem_per_page;
  10. elem_per_page = min(page_size / elem_size, q_depth);
  11. qpages->pages = NULL;
  12. qpages->page_size = page_size;
  13. qpages->num_pages = max(q_depth / elem_per_page, 1);
  14. qpages->elem_size_shift = ilog2(elem_size);
  15. qpages->elem_per_pg_shift = ilog2(elem_per_page);
  16. }
  17. static void __queue_pages_free(struct hinic3_hwdev *hwdev,
  18. struct hinic3_queue_pages *qpages, u32 pg_cnt)
  19. {
  20. while (pg_cnt > 0) {
  21. pg_cnt--;
  22. hinic3_dma_free_coherent_align(hwdev->dev,
  23. qpages->pages + pg_cnt);
  24. }
  25. kfree(qpages->pages);
  26. qpages->pages = NULL;
  27. }
  28. void hinic3_queue_pages_free(struct hinic3_hwdev *hwdev,
  29. struct hinic3_queue_pages *qpages)
  30. {
  31. __queue_pages_free(hwdev, qpages, qpages->num_pages);
  32. }
  33. int hinic3_queue_pages_alloc(struct hinic3_hwdev *hwdev,
  34. struct hinic3_queue_pages *qpages, u32 align)
  35. {
  36. u32 pg_idx;
  37. int err;
  38. qpages->pages = kzalloc_objs(qpages->pages[0], qpages->num_pages);
  39. if (!qpages->pages)
  40. return -ENOMEM;
  41. if (align == 0)
  42. align = qpages->page_size;
  43. for (pg_idx = 0; pg_idx < qpages->num_pages; pg_idx++) {
  44. err = hinic3_dma_zalloc_coherent_align(hwdev->dev,
  45. qpages->page_size,
  46. align,
  47. GFP_KERNEL,
  48. qpages->pages + pg_idx);
  49. if (err) {
  50. __queue_pages_free(hwdev, qpages, pg_idx);
  51. return err;
  52. }
  53. }
  54. return 0;
  55. }