hwbm.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Support for hardware buffer manager.
  3. *
  4. * Copyright (C) 2016 Marvell
  5. *
  6. * Gregory CLEMENT <gregory.clement@free-electrons.com>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/printk.h>
  10. #include <linux/skbuff.h>
  11. #include <net/hwbm.h>
  12. void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf)
  13. {
  14. if (likely(bm_pool->frag_size <= PAGE_SIZE))
  15. skb_free_frag(buf);
  16. else
  17. kfree(buf);
  18. }
  19. EXPORT_SYMBOL_GPL(hwbm_buf_free);
  20. /* Refill processing for HW buffer management */
  21. int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp)
  22. {
  23. int frag_size = bm_pool->frag_size;
  24. void *buf;
  25. if (likely(frag_size <= PAGE_SIZE))
  26. buf = netdev_alloc_frag(frag_size);
  27. else
  28. buf = kmalloc(frag_size, gfp);
  29. if (!buf)
  30. return -ENOMEM;
  31. if (bm_pool->construct)
  32. if (bm_pool->construct(bm_pool, buf)) {
  33. hwbm_buf_free(bm_pool, buf);
  34. return -ENOMEM;
  35. }
  36. return 0;
  37. }
  38. EXPORT_SYMBOL_GPL(hwbm_pool_refill);
  39. int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num)
  40. {
  41. int err, i;
  42. mutex_lock(&bm_pool->buf_lock);
  43. if (bm_pool->buf_num == bm_pool->size) {
  44. pr_warn("pool already filled\n");
  45. mutex_unlock(&bm_pool->buf_lock);
  46. return bm_pool->buf_num;
  47. }
  48. if (buf_num + bm_pool->buf_num > bm_pool->size) {
  49. pr_warn("cannot allocate %d buffers for pool\n",
  50. buf_num);
  51. mutex_unlock(&bm_pool->buf_lock);
  52. return 0;
  53. }
  54. if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
  55. pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
  56. buf_num, bm_pool->buf_num);
  57. mutex_unlock(&bm_pool->buf_lock);
  58. return 0;
  59. }
  60. for (i = 0; i < buf_num; i++) {
  61. err = hwbm_pool_refill(bm_pool, GFP_KERNEL);
  62. if (err < 0)
  63. break;
  64. }
  65. /* Update BM driver with number of buffers added to pool */
  66. bm_pool->buf_num += i;
  67. pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num);
  68. mutex_unlock(&bm_pool->buf_lock);
  69. return i;
  70. }
  71. EXPORT_SYMBOL_GPL(hwbm_pool_add);