summaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch')
-rw-r--r--target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch159
1 files changed, 159 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch b/target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch
new file mode 100644
index 0000000000..d4bc6a0088
--- /dev/null
+++ b/target/linux/mvebu/patches-4.4/044-net-add-a-hardware-buffer-management-helper-API.patch
@@ -0,0 +1,159 @@
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Mon, 14 Mar 2016 09:39:04 +0100
+Subject: [PATCH] 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>
+---
+ create mode 100644 include/net/hwbm.h
+ create mode 100644 net/core/hwbm.c
+
+--- /dev/null
++++ b/include/net/hwbm.h
+@@ -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 */
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -259,6 +259,9 @@ config XPS
+ depends on SMP
+ default y
+
++config HWBM
++ bool
++
+ config CGROUP_NET_PRIO
+ bool "Network priority cgroup"
+ depends on CGROUPS
+--- a/net/core/Makefile
++++ b/net/core/Makefile
+@@ -14,6 +14,7 @@ obj-y += dev.o ethtool.o dev_addr_
+ obj-$(CONFIG_SOCK_DIAG) += sock_diag.o
+ obj-$(CONFIG_XFRM) += flow.o
+ obj-y += net-sysfs.o
++obj-$(CONFIG_HWBM) += hwbm.o
+ obj-$(CONFIG_PROC_FS) += net-procfs.o
+ obj-$(CONFIG_NET_PKTGEN) += pktgen.o
+ obj-$(CONFIG_NETPOLL) += netpoll.o
+--- /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);