Skip to content

Commit 8cb2d8b

Browse files
gclementdavem330
authored andcommitted
net: add a hardware buffer management helper API
This basic implementation allows to share code between driver using hardware buffer management. As the code is hardware agnostic, there is few helpers, most of the optimization brought by the an HW BM has to be done at driver level. Tested-by: Sebastian Careba <[email protected]> Signed-off-by: Gregory CLEMENT <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent dc35a10 commit 8cb2d8b

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

include/net/hwbm.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef _HWBM_H
2+
#define _HWBM_H
3+
4+
struct hwbm_pool {
5+
/* Capacity of the pool */
6+
int size;
7+
/* Size of the buffers managed */
8+
int frag_size;
9+
/* Number of buffers currently used by this pool */
10+
int buf_num;
11+
/* constructor called during alocation */
12+
int (*construct)(struct hwbm_pool *bm_pool, void *buf);
13+
/* protect acces to the buffer counter*/
14+
spinlock_t lock;
15+
/* private data */
16+
void *priv;
17+
};
18+
#ifdef CONFIG_HWBM
19+
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf);
20+
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp);
21+
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp);
22+
#else
23+
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
24+
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; }
25+
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
26+
{ return 0; }
27+
#endif /* CONFIG_HWBM */
28+
#endif /* _HWBM_H */

net/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ config XPS
253253
depends on SMP
254254
default y
255255

256+
config HWBM
257+
bool
258+
256259
config SOCK_CGROUP_DATA
257260
bool
258261
default n

net/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
2525
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
2626
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
2727
obj-$(CONFIG_DST_CACHE) += dst_cache.o
28+
obj-$(CONFIG_HWBM) += hwbm.o
2829
obj-$(CONFIG_NET_DEVLINK) += devlink.o

net/core/hwbm.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* Support for hardware buffer manager.
2+
*
3+
* Copyright (C) 2016 Marvell
4+
*
5+
* Gregory CLEMENT <[email protected]>
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*/
12+
#include <linux/kernel.h>
13+
#include <linux/printk.h>
14+
#include <linux/skbuff.h>
15+
#include <net/hwbm.h>
16+
17+
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf)
18+
{
19+
if (likely(bm_pool->frag_size <= PAGE_SIZE))
20+
skb_free_frag(buf);
21+
else
22+
kfree(buf);
23+
}
24+
EXPORT_SYMBOL_GPL(hwbm_buf_free);
25+
26+
/* Refill processing for HW buffer management */
27+
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp)
28+
{
29+
int frag_size = bm_pool->frag_size;
30+
void *buf;
31+
32+
if (likely(frag_size <= PAGE_SIZE))
33+
buf = netdev_alloc_frag(frag_size);
34+
else
35+
buf = kmalloc(frag_size, gfp);
36+
37+
if (!buf)
38+
return -ENOMEM;
39+
40+
if (bm_pool->construct)
41+
if (bm_pool->construct(bm_pool, buf)) {
42+
hwbm_buf_free(bm_pool, buf);
43+
return -ENOMEM;
44+
}
45+
46+
return 0;
47+
}
48+
EXPORT_SYMBOL_GPL(hwbm_pool_refill);
49+
50+
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
51+
{
52+
int err, i;
53+
unsigned long flags;
54+
55+
spin_lock_irqsave(&bm_pool->lock, flags);
56+
if (bm_pool->buf_num == bm_pool->size) {
57+
pr_warn("pool already filled\n");
58+
return bm_pool->buf_num;
59+
}
60+
61+
if (buf_num + bm_pool->buf_num > bm_pool->size) {
62+
pr_warn("cannot allocate %d buffers for pool\n",
63+
buf_num);
64+
return 0;
65+
}
66+
67+
if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
68+
pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
69+
buf_num, bm_pool->buf_num);
70+
return 0;
71+
}
72+
73+
for (i = 0; i < buf_num; i++) {
74+
err = hwbm_pool_refill(bm_pool, gfp);
75+
if (err < 0)
76+
break;
77+
}
78+
79+
/* Update BM driver with number of buffers added to pool */
80+
bm_pool->buf_num += i;
81+
82+
pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num);
83+
spin_unlock_irqrestore(&bm_pool->lock, flags);
84+
85+
return i;
86+
}
87+
EXPORT_SYMBOL_GPL(hwbm_pool_add);

0 commit comments

Comments
 (0)