diff options
author | David S. Miller <davem@davemloft.net> | 2016-03-14 12:19:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-14 12:19:47 -0400 |
commit | c9214f50a2b24f7de92752fd2c2358520bb84f9f (patch) | |
tree | 4b3579d7e2bd56b1c529fdd7620dd58826971997 /net | |
parent | d3bf9b19ff06bdcc4aacdd6eb395c742138a9dc9 (diff) | |
parent | baa11ebc0c7680861f74f8a11dca903e4b421262 (diff) | |
download | lwn-c9214f50a2b24f7de92752fd2c2358520bb84f9f.tar.gz lwn-c9214f50a2b24f7de92752fd2c2358520bb84f9f.zip |
Merge branch 'mvneta-hwbm'
Gregory CLEMENT says:
====================
API set for HW Buffer management
This is the sixth version of the API set for HW Buffer management (that was
initially submitted here:
http://thread.gmane.org/gmane.linux.kernel/2125152).
This version is just a rebasing onto the last net-next. I also added
the Tested-by flag from Sebastian Careba : "The patch set applies
successfully and it works well, no more Samba issues any longer".
For the record in the previous versions I made the following changes:
v4 -> v5:
- Add a field with the size of the buffer of the pool was added. It
then allow to fix some misused size in the mvneta_bm code when using
the new framework.
- Add a new patch from Marcin for sram allowing to require
non-bufferable access to the memory. It was needed for the hardware
buffer management of the mvneta.
- Fix the build issue notified by the 0-day builder when building the
drivers as module.
v3 -> v4
- Fix build issue when HWBM is not selected
v2 -> v3
- Make a HWBM and a SWBM version of the mvneta_rx() function in order
to reduce the the conditional code. Kept a condition inside the
mvneta_poll because specializing this function would have means
duplicating 95% of the code.
- Put back the register_netdev() call at the end of the mvneta_probe()
function. In order to have a unique ID for each port, just used a
global variable in the driver.
- Added a fix from Marcin in the "net: mvneta: bm: add support for
hardware buffer management" patch: "when dropping packets, only
buffer pointers passed from BM to descriptors have to be returned to
the pool. In submitted version after closing the port and
mvneta_rxq_deinit(), it was very likely that a lot of fake buffers
are added to the pool, because all descriptors took part in
iteration."
- Removed the select MVNETA_BM from the Kconfig, it will let the user
the choice to use not use it if they want.
v1 -> v2
- The hardware buffer management helpers are no more built by default
and now depend on a hidden config symbol which has to be selected
by the driver if needed
- The hwbm_pool_refill() and hwbm_pool_add() now receive a gfp_t as
argument allowing the caller to specify the flag it needs.
- buf_num is now tested to ensure there is no wrapping
- A spinlock has been added to protect the hwbm_pool_add() function in
SMP or irq context.
- used pr_warn instead of pr_debug in case of errors.
- fixed the mvneta implementation by returning the buffer to the pool
at various place instead of ignoring it.
- Squashed "bus: mvenus-mbus: Fix size test for
mvebu_mbus_get_dram_win_info" into bus: mvebu-mbus: provide api for
obtaining IO and DRAM window information.
- Added my signed-otf-by on all the patches as submitter of the series.
- Renamed the dts patches with the pattern "ARM: dts: platform:"
- Removed the patch "ARM: mvebu: enable SRAM support in
mvebu_v7_defconfig" of this series and already applied it
- Modified the order of the patches.
In order to ease the test the branch mvneta-BM-framework-v6 is
available at git@github.com:MISL-EBU-System-SW/mainline-public.git.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 3 | ||||
-rw-r--r-- | net/core/Makefile | 1 | ||||
-rw-r--r-- | net/core/hwbm.c | 87 |
3 files changed, 91 insertions, 0 deletions
diff --git a/net/Kconfig b/net/Kconfig index 10640d5f8bee..e13449870d06 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -253,6 +253,9 @@ config XPS depends on SMP default y +config HWBM + bool + config SOCK_CGROUP_DATA bool default n diff --git a/net/core/Makefile b/net/core/Makefile index 014422e2561f..d6508c2ddca5 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -25,4 +25,5 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o obj-$(CONFIG_LWTUNNEL) += lwtunnel.o obj-$(CONFIG_DST_CACHE) += dst_cache.o +obj-$(CONFIG_HWBM) += hwbm.o obj-$(CONFIG_NET_DEVLINK) += devlink.o diff --git a/net/core/hwbm.c b/net/core/hwbm.c new file mode 100644 index 000000000000..941c28486896 --- /dev/null +++ b/net/core/hwbm.c @@ -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); |