-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <nitroshift@yahoo.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Gregory CLEMENT
authored and
David S. Miller
committed
Mar 14, 2016
1 parent
dc35a10
commit 8cb2d8b
Showing
4 changed files
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#ifndef _HWBM_H | ||
#define _HWBM_H | ||
|
||
struct hwbm_pool { | ||
/* Capacity of the pool */ | ||
int size; | ||
/* Size of the buffers managed */ | ||
int frag_size; | ||
/* Number of buffers currently used by this pool */ | ||
int buf_num; | ||
/* constructor called during alocation */ | ||
int (*construct)(struct hwbm_pool *bm_pool, void *buf); | ||
/* protect acces to the buffer counter*/ | ||
spinlock_t lock; | ||
/* private data */ | ||
void *priv; | ||
}; | ||
#ifdef CONFIG_HWBM | ||
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf); | ||
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp); | ||
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp); | ||
#else | ||
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {} | ||
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; } | ||
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp) | ||
{ return 0; } | ||
#endif /* CONFIG_HWBM */ | ||
#endif /* _HWBM_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -253,6 +253,9 @@ config XPS | |
depends on SMP | ||
default y | ||
|
||
config HWBM | ||
bool | ||
|
||
config SOCK_CGROUP_DATA | ||
bool | ||
default n | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* Support for hardware buffer manager. | ||
* | ||
* Copyright (C) 2016 Marvell | ||
* | ||
* Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/printk.h> | ||
#include <linux/skbuff.h> | ||
#include <net/hwbm.h> | ||
|
||
void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) | ||
{ | ||
if (likely(bm_pool->frag_size <= PAGE_SIZE)) | ||
skb_free_frag(buf); | ||
else | ||
kfree(buf); | ||
} | ||
EXPORT_SYMBOL_GPL(hwbm_buf_free); | ||
|
||
/* Refill processing for HW buffer management */ | ||
int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) | ||
{ | ||
int frag_size = bm_pool->frag_size; | ||
void *buf; | ||
|
||
if (likely(frag_size <= PAGE_SIZE)) | ||
buf = netdev_alloc_frag(frag_size); | ||
else | ||
buf = kmalloc(frag_size, gfp); | ||
|
||
if (!buf) | ||
return -ENOMEM; | ||
|
||
if (bm_pool->construct) | ||
if (bm_pool->construct(bm_pool, buf)) { | ||
hwbm_buf_free(bm_pool, buf); | ||
return -ENOMEM; | ||
} | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(hwbm_pool_refill); | ||
|
||
int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp) | ||
{ | ||
int err, i; | ||
unsigned long flags; | ||
|
||
spin_lock_irqsave(&bm_pool->lock, flags); | ||
if (bm_pool->buf_num == bm_pool->size) { | ||
pr_warn("pool already filled\n"); | ||
return bm_pool->buf_num; | ||
} | ||
|
||
if (buf_num + bm_pool->buf_num > bm_pool->size) { | ||
pr_warn("cannot allocate %d buffers for pool\n", | ||
buf_num); | ||
return 0; | ||
} | ||
|
||
if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) { | ||
pr_warn("Adding %d buffers to the %d current buffers will overflow\n", | ||
buf_num, bm_pool->buf_num); | ||
return 0; | ||
} | ||
|
||
for (i = 0; i < buf_num; i++) { | ||
err = hwbm_pool_refill(bm_pool, gfp); | ||
if (err < 0) | ||
break; | ||
} | ||
|
||
/* Update BM driver with number of buffers added to pool */ | ||
bm_pool->buf_num += i; | ||
|
||
pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num); | ||
spin_unlock_irqrestore(&bm_pool->lock, flags); | ||
|
||
return i; | ||
} | ||
EXPORT_SYMBOL_GPL(hwbm_pool_add); |