044-net-add-a-hardware-buffer-management-helper-API.patch 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. From: Gregory CLEMENT <gregory.clement@free-electrons.com>
  2. Date: Mon, 14 Mar 2016 09:39:04 +0100
  3. Subject: [PATCH] net: add a hardware buffer management helper API
  4. This basic implementation allows to share code between driver using
  5. hardware buffer management. As the code is hardware agnostic, there is
  6. few helpers, most of the optimization brought by the an HW BM has to be
  7. done at driver level.
  8. Tested-by: Sebastian Careba <nitroshift@yahoo.com>
  9. Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
  10. Signed-off-by: David S. Miller <davem@davemloft.net>
  11. ---
  12. create mode 100644 include/net/hwbm.h
  13. create mode 100644 net/core/hwbm.c
  14. --- /dev/null
  15. +++ b/include/net/hwbm.h
  16. @@ -0,0 +1,28 @@
  17. +#ifndef _HWBM_H
  18. +#define _HWBM_H
  19. +
  20. +struct hwbm_pool {
  21. + /* Capacity of the pool */
  22. + int size;
  23. + /* Size of the buffers managed */
  24. + int frag_size;
  25. + /* Number of buffers currently used by this pool */
  26. + int buf_num;
  27. + /* constructor called during alocation */
  28. + int (*construct)(struct hwbm_pool *bm_pool, void *buf);
  29. + /* protect acces to the buffer counter*/
  30. + spinlock_t lock;
  31. + /* private data */
  32. + void *priv;
  33. +};
  34. +#ifdef CONFIG_HWBM
  35. +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf);
  36. +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp);
  37. +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp);
  38. +#else
  39. +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
  40. +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; }
  41. +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
  42. +{ return 0; }
  43. +#endif /* CONFIG_HWBM */
  44. +#endif /* _HWBM_H */
  45. --- a/net/Kconfig
  46. +++ b/net/Kconfig
  47. @@ -259,6 +259,9 @@ config XPS
  48. depends on SMP
  49. default y
  50. +config HWBM
  51. + bool
  52. +
  53. config CGROUP_NET_PRIO
  54. bool "Network priority cgroup"
  55. depends on CGROUPS
  56. --- a/net/core/Makefile
  57. +++ b/net/core/Makefile
  58. @@ -14,6 +14,7 @@ obj-y += dev.o ethtool.o dev_addr_
  59. obj-$(CONFIG_SOCK_DIAG) += sock_diag.o
  60. obj-$(CONFIG_XFRM) += flow.o
  61. obj-y += net-sysfs.o
  62. +obj-$(CONFIG_HWBM) += hwbm.o
  63. obj-$(CONFIG_PROC_FS) += net-procfs.o
  64. obj-$(CONFIG_NET_PKTGEN) += pktgen.o
  65. obj-$(CONFIG_NETPOLL) += netpoll.o
  66. --- /dev/null
  67. +++ b/net/core/hwbm.c
  68. @@ -0,0 +1,87 @@
  69. +/* Support for hardware buffer manager.
  70. + *
  71. + * Copyright (C) 2016 Marvell
  72. + *
  73. + * Gregory CLEMENT <gregory.clement@free-electrons.com>
  74. + *
  75. + * This program is free software; you can redistribute it and/or modify
  76. + * it under the terms of the GNU General Public License as published by
  77. + * the Free Software Foundation; either version 2 of the License, or
  78. + * (at your option) any later version.
  79. + */
  80. +#include <linux/kernel.h>
  81. +#include <linux/printk.h>
  82. +#include <linux/skbuff.h>
  83. +#include <net/hwbm.h>
  84. +
  85. +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf)
  86. +{
  87. + if (likely(bm_pool->frag_size <= PAGE_SIZE))
  88. + skb_free_frag(buf);
  89. + else
  90. + kfree(buf);
  91. +}
  92. +EXPORT_SYMBOL_GPL(hwbm_buf_free);
  93. +
  94. +/* Refill processing for HW buffer management */
  95. +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp)
  96. +{
  97. + int frag_size = bm_pool->frag_size;
  98. + void *buf;
  99. +
  100. + if (likely(frag_size <= PAGE_SIZE))
  101. + buf = netdev_alloc_frag(frag_size);
  102. + else
  103. + buf = kmalloc(frag_size, gfp);
  104. +
  105. + if (!buf)
  106. + return -ENOMEM;
  107. +
  108. + if (bm_pool->construct)
  109. + if (bm_pool->construct(bm_pool, buf)) {
  110. + hwbm_buf_free(bm_pool, buf);
  111. + return -ENOMEM;
  112. + }
  113. +
  114. + return 0;
  115. +}
  116. +EXPORT_SYMBOL_GPL(hwbm_pool_refill);
  117. +
  118. +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
  119. +{
  120. + int err, i;
  121. + unsigned long flags;
  122. +
  123. + spin_lock_irqsave(&bm_pool->lock, flags);
  124. + if (bm_pool->buf_num == bm_pool->size) {
  125. + pr_warn("pool already filled\n");
  126. + return bm_pool->buf_num;
  127. + }
  128. +
  129. + if (buf_num + bm_pool->buf_num > bm_pool->size) {
  130. + pr_warn("cannot allocate %d buffers for pool\n",
  131. + buf_num);
  132. + return 0;
  133. + }
  134. +
  135. + if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
  136. + pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
  137. + buf_num, bm_pool->buf_num);
  138. + return 0;
  139. + }
  140. +
  141. + for (i = 0; i < buf_num; i++) {
  142. + err = hwbm_pool_refill(bm_pool, gfp);
  143. + if (err < 0)
  144. + break;
  145. + }
  146. +
  147. + /* Update BM driver with number of buffers added to pool */
  148. + bm_pool->buf_num += i;
  149. +
  150. + pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num);
  151. + spin_unlock_irqrestore(&bm_pool->lock, flags);
  152. +
  153. + return i;
  154. +}
  155. +EXPORT_SYMBOL_GPL(hwbm_pool_add);