* [PATCH net-next 0/2] nfp: SR-IOV ndos support
From: Jakub Kicinski @ 2017-08-25 4:31 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Jakub Kicinski
Hi!
This set adds basic SR-IOV including setting/getting VF MAC addresses,
VLANs, link state and spoofcheck settings. It is wired up for both
vNICs and representors (note: ip link will not report VF settings on
VF/PF representors because they are not linked to the PF PCI device).
Pablo and team add the basic implementation, Simon and Dirk follow
up with the representor plumbing.
Pablo Cascón (1):
nfp: add basic SR-IOV ndo functions
Simon Horman (1):
nfp: add basic SR-IOV ndo functions to representors
drivers/net/ethernet/netronome/nfp/Makefile | 1 +
drivers/net/ethernet/netronome/nfp/nfp_main.h | 4 +
.../net/ethernet/netronome/nfp/nfp_net_common.c | 6 +
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 1 +
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 20 +-
drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 6 +
drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c | 243 +++++++++++++++++++++
drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h | 86 ++++++++
drivers/net/ethernet/netronome/nfp/nic/main.c | 12 +
9 files changed, 378 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
--
2.11.0
^ permalink raw reply
* [PATCH net-next 1/2] nfp: add basic SR-IOV ndo functions
From: Jakub Kicinski @ 2017-08-25 4:31 UTC (permalink / raw)
To: netdev
Cc: oss-drivers, Pablo Cascón, Jimmy Kizito, Rami Tomer,
Simon Horman, Jakub Kicinski
In-Reply-To: <20170825043150.375-1-jakub.kicinski@netronome.com>
From: Pablo Cascón <pablo.cascon@netronome.com>
Add basic ndo_set/get_vf to support SR-IOV.
VF to egress phy static mapping by now.
Use vfcfg ABI version 2 to write the info to the FW and collect
the return value from the mailbox.
Signed-off-by: Pablo Cascón <pablo.cascon@netronome.com>
Signed-off-by: Jimmy Kizito <jimmy.kizito@netronome.com>
Signed-off-by: Rami Tomer <rami.tomer@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/Makefile | 1 +
drivers/net/ethernet/netronome/nfp/nfp_main.h | 4 +
.../net/ethernet/netronome/nfp/nfp_net_common.c | 6 +
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 1 +
drivers/net/ethernet/netronome/nfp/nfp_net_main.c | 20 +-
drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c | 243 +++++++++++++++++++++
drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h | 86 ++++++++
drivers/net/ethernet/netronome/nfp/nic/main.c | 12 +
8 files changed, 372 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
create mode 100644 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
diff --git a/drivers/net/ethernet/netronome/nfp/Makefile b/drivers/net/ethernet/netronome/nfp/Makefile
index b8e1358868bd..96e579a15cbe 100644
--- a/drivers/net/ethernet/netronome/nfp/Makefile
+++ b/drivers/net/ethernet/netronome/nfp/Makefile
@@ -23,6 +23,7 @@ nfp-objs := \
nfp_net_ethtool.o \
nfp_net_main.o \
nfp_net_repr.o \
+ nfp_net_sriov.o \
nfp_netvf_main.o \
nfp_port.o \
bpf/main.o \
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h
index 6922410806db..be0ee59f2eb9 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h
@@ -73,6 +73,8 @@ struct nfp_rtsym_table;
* @mac_stats_mem: Pointer to mapped MAC stats area
* @vf_cfg_bar: Pointer to the CPP area for the VF configuration BAR
* @vf_cfg_mem: Pointer to mapped VF configuration area
+ * @vfcfg_tbl2_area: Pointer to the CPP area for the VF config table
+ * @vfcfg_tbl2: Pointer to mapped VF config table
* @irq_entries: Array of MSI-X entries for all vNICs
* @limit_vfs: Number of VFs supported by firmware (~0 for PCI limit)
* @num_vfs: Number of SR-IOV VFs enabled
@@ -107,6 +109,8 @@ struct nfp_pf {
u8 __iomem *mac_stats_mem;
struct nfp_cpp_area *vf_cfg_bar;
u8 __iomem *vf_cfg_mem;
+ struct nfp_cpp_area *vfcfg_tbl2_area;
+ u8 __iomem *vfcfg_tbl2;
struct msix_entry *irq_entries;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 1dbe9a3a02d1..2920889fa6d6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -71,6 +71,7 @@
#include "nfp_app.h"
#include "nfp_net_ctrl.h"
#include "nfp_net.h"
+#include "nfp_net_sriov.h"
#include "nfp_port.h"
/**
@@ -3421,6 +3422,11 @@ const struct net_device_ops nfp_net_netdev_ops = {
.ndo_get_stats64 = nfp_net_stat64,
.ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid,
+ .ndo_set_vf_mac = nfp_app_set_vf_mac,
+ .ndo_set_vf_vlan = nfp_app_set_vf_vlan,
+ .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
+ .ndo_get_vf_config = nfp_app_get_vf_config,
+ .ndo_set_vf_link_state = nfp_app_set_vf_link_state,
.ndo_setup_tc = nfp_port_setup_tc,
.ndo_tx_timeout = nfp_net_tx_timeout,
.ndo_set_rx_mode = nfp_net_set_rx_mode,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index e5e94e0746ec..b0a452ba9039 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -164,6 +164,7 @@
#define NFP_NET_CFG_UPDATE_BPF (0x1 << 10) /* BPF program load */
#define NFP_NET_CFG_UPDATE_MACADDR (0x1 << 11) /* MAC address change */
#define NFP_NET_CFG_UPDATE_MBOX (0x1 << 12) /* Mailbox update */
+#define NFP_NET_CFG_UPDATE_VF (0x1 << 13) /* VF settings change */
#define NFP_NET_CFG_UPDATE_ERR (0x1 << 31) /* A error occurred */
#define NFP_NET_CFG_TXRS_ENABLE 0x0008
#define NFP_NET_CFG_RXRS_ENABLE 0x0010
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
index 4c3be635f475..5a21e61662d6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_main.c
@@ -57,6 +57,7 @@
#include "nfpcore/nfp6000_pcie.h"
#include "nfp_app.h"
#include "nfp_net_ctrl.h"
+#include "nfp_net_sriov.h"
#include "nfp_net.h"
#include "nfp_main.h"
#include "nfp_port.h"
@@ -484,6 +485,8 @@ static void nfp_net_pf_app_stop(struct nfp_pf *pf)
static void nfp_net_pci_unmap_mem(struct nfp_pf *pf)
{
+ if (pf->vfcfg_tbl2_area)
+ nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);
if (pf->vf_cfg_bar)
nfp_cpp_area_release_free(pf->vf_cfg_bar);
if (pf->mac_stats_bar)
@@ -530,17 +533,32 @@ static int nfp_net_pci_map_mem(struct nfp_pf *pf)
pf->vf_cfg_mem = NULL;
}
+ min_size = NFP_NET_VF_CFG_SZ * pf->limit_vfs + NFP_NET_VF_CFG_MB_SZ;
+ pf->vfcfg_tbl2 = nfp_net_pf_map_rtsym(pf, "net.vfcfg_tbl2",
+ "_pf%d_net_vf_cfg2",
+ min_size, &pf->vfcfg_tbl2_area);
+ if (IS_ERR(pf->vfcfg_tbl2)) {
+ if (PTR_ERR(pf->vfcfg_tbl2) != -ENOENT) {
+ err = PTR_ERR(pf->vfcfg_tbl2);
+ goto err_unmap_vf_cfg;
+ }
+ pf->vfcfg_tbl2 = NULL;
+ }
+
mem = nfp_cpp_map_area(pf->cpp, "net.qc", 0, 0,
NFP_PCIE_QUEUE(0), NFP_QCP_QUEUE_AREA_SZ,
&pf->qc_area);
if (IS_ERR(mem)) {
nfp_err(pf->cpp, "Failed to map Queue Controller area.\n");
err = PTR_ERR(mem);
- goto err_unmap_vf_cfg;
+ goto err_unmap_vfcfg_tbl2;
}
return 0;
+err_unmap_vfcfg_tbl2:
+ if (pf->vfcfg_tbl2_area)
+ nfp_cpp_area_release_free(pf->vfcfg_tbl2_area);
err_unmap_vf_cfg:
if (pf->vf_cfg_bar)
nfp_cpp_area_release_free(pf->vf_cfg_bar);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
new file mode 100644
index 000000000000..e6d2e06b050c
--- /dev/null
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/if_link.h>
+#include <linux/if_ether.h>
+
+#include "nfpcore/nfp_cpp.h"
+#include "nfp_app.h"
+#include "nfp_main.h"
+#include "nfp_net_ctrl.h"
+#include "nfp_net.h"
+#include "nfp_net_sriov.h"
+
+static int
+nfp_net_sriov_check(struct nfp_app *app, int vf, u16 cap, const char *msg)
+{
+ u16 cap_vf;
+
+ if (!app || !app->pf->vfcfg_tbl2)
+ return -EOPNOTSUPP;
+
+ cap_vf = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_CAP);
+ if ((cap_vf & cap) != cap) {
+ nfp_warn(app->pf->cpp, "ndo_set_vf_%s not supported\n", msg);
+ return -EOPNOTSUPP;
+ }
+
+ if (vf < 0 || vf >= app->pf->num_vfs) {
+ nfp_warn(app->pf->cpp, "invalid VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+nfp_net_sriov_update(struct nfp_app *app, int vf, u16 update, const char *msg)
+{
+ struct nfp_net *nn;
+ int ret;
+
+ /* Write update info to mailbox in VF config symbol */
+ writeb(vf, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_VF_NUM);
+ writew(update, app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_UPD);
+
+ nn = list_first_entry(&app->pf->vnics, struct nfp_net, vnic_list);
+ /* Signal VF reconfiguration */
+ ret = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VF);
+ if (ret)
+ return ret;
+
+ ret = readw(app->pf->vfcfg_tbl2 + NFP_NET_VF_CFG_MB_RET);
+ if (ret)
+ nfp_warn(app->pf->cpp,
+ "FW refused VF %s update with errno: %d\n", msg, ret);
+ return -ret;
+}
+
+int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
+{
+ struct nfp_app *app = nfp_app_from_netdev(netdev);
+ unsigned int vf_offset;
+ int err;
+
+ err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_MAC, "mac");
+ if (err)
+ return err;
+
+ if (is_multicast_ether_addr(mac)) {
+ nfp_warn(app->pf->cpp,
+ "invalid Ethernet address %pM for VF id %d\n",
+ mac, vf);
+ return -EINVAL;
+ }
+
+ /* Write MAC to VF entry in VF config symbol */
+ vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
+ writel(get_unaligned_be32(mac), app->pf->vfcfg_tbl2 + vf_offset);
+ writew(get_unaligned_be16(mac + 4),
+ app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO);
+
+ return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_MAC, "MAC");
+}
+
+int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
+ __be16 vlan_proto)
+{
+ struct nfp_app *app = nfp_app_from_netdev(netdev);
+ unsigned int vf_offset;
+ u16 vlan_tci;
+ int err;
+
+ err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_VLAN, "vlan");
+ if (err)
+ return err;
+
+ if (vlan_proto != htons(ETH_P_8021Q))
+ return -EOPNOTSUPP;
+
+ if (vlan > 4095 || qos > 7) {
+ nfp_warn(app->pf->cpp,
+ "invalid vlan id or qos for VF id %d\n", vf);
+ return -EINVAL;
+ }
+
+ /* Write VLAN tag to VF entry in VF config symbol */
+ vlan_tci = FIELD_PREP(NFP_NET_VF_CFG_VLAN_VID, vlan) |
+ FIELD_PREP(NFP_NET_VF_CFG_VLAN_QOS, qos);
+ vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
+ writew(vlan_tci, app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN);
+
+ return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_VLAN,
+ "vlan");
+}
+
+int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
+{
+ struct nfp_app *app = nfp_app_from_netdev(netdev);
+ unsigned int vf_offset;
+ u8 vf_ctrl;
+ int err;
+
+ err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_SPOOF,
+ "spoofchk");
+ if (err)
+ return err;
+
+ /* Write spoof check control bit to VF entry in VF config symbol */
+ vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ +
+ NFP_NET_VF_CFG_CTRL;
+ vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset);
+ vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_SPOOF;
+ vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_SPOOF, enable);
+ writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset);
+
+ return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_SPOOF,
+ "spoofchk");
+}
+
+int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
+ int link_state)
+{
+ struct nfp_app *app = nfp_app_from_netdev(netdev);
+ unsigned int vf_offset;
+ u8 vf_ctrl;
+ int err;
+
+ err = nfp_net_sriov_check(app, vf, NFP_NET_VF_CFG_MB_CAP_LINK_STATE,
+ "link_state");
+ if (err)
+ return err;
+
+ switch (link_state) {
+ case IFLA_VF_LINK_STATE_AUTO:
+ case IFLA_VF_LINK_STATE_ENABLE:
+ case IFLA_VF_LINK_STATE_DISABLE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Write link state to VF entry in VF config symbol */
+ vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ +
+ NFP_NET_VF_CFG_CTRL;
+ vf_ctrl = readb(app->pf->vfcfg_tbl2 + vf_offset);
+ vf_ctrl &= ~NFP_NET_VF_CFG_CTRL_LINK_STATE;
+ vf_ctrl |= FIELD_PREP(NFP_NET_VF_CFG_CTRL_LINK_STATE, link_state);
+ writeb(vf_ctrl, app->pf->vfcfg_tbl2 + vf_offset);
+
+ return nfp_net_sriov_update(app, vf, NFP_NET_VF_CFG_MB_UPD_LINK_STATE,
+ "link state");
+}
+
+int nfp_app_get_vf_config(struct net_device *netdev, int vf,
+ struct ifla_vf_info *ivi)
+{
+ struct nfp_app *app = nfp_app_from_netdev(netdev);
+ unsigned int vf_offset;
+ u16 vlan_tci;
+ u32 mac_hi;
+ u16 mac_lo;
+ u8 flags;
+ int err;
+
+ err = nfp_net_sriov_check(app, vf, 0, "");
+ if (err)
+ return err;
+
+ vf_offset = NFP_NET_VF_CFG_MB_SZ + vf * NFP_NET_VF_CFG_SZ;
+
+ mac_hi = readl(app->pf->vfcfg_tbl2 + vf_offset);
+ mac_lo = readw(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_MAC_LO);
+
+ flags = readb(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_CTRL);
+ vlan_tci = readw(app->pf->vfcfg_tbl2 + vf_offset + NFP_NET_VF_CFG_VLAN);
+
+ memset(ivi, 0, sizeof(*ivi));
+ ivi->vf = vf;
+
+ put_unaligned_be32(mac_hi, &ivi->mac[0]);
+ put_unaligned_be16(mac_lo, &ivi->mac[4]);
+
+ ivi->vlan = FIELD_GET(NFP_NET_VF_CFG_VLAN_VID, vlan_tci);
+ ivi->qos = FIELD_GET(NFP_NET_VF_CFG_VLAN_QOS, vlan_tci);
+
+ ivi->spoofchk = FIELD_GET(NFP_NET_VF_CFG_CTRL_SPOOF, flags);
+ ivi->linkstate = FIELD_GET(NFP_NET_VF_CFG_CTRL_LINK_STATE, flags);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
new file mode 100644
index 000000000000..e9df9d1eab8e
--- /dev/null
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 Netronome Systems, Inc.
+ *
+ * This software is dual licensed under the GNU General License Version 2,
+ * June 1991 as shown in the file COPYING in the top-level directory of this
+ * source tree or the BSD 2-Clause License provided below. You have the
+ * option to license this software under the complete terms of either license.
+ *
+ * The BSD 2-Clause License:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _NFP_NET_SRIOV_H_
+#define _NFP_NET_SRIOV_H_
+
+/**
+ * SRIOV VF configuration.
+ * The configuration memory begins with a mailbox region for communication with
+ * the firmware followed by individual VF entries.
+ */
+#define NFP_NET_VF_CFG_SZ 16
+#define NFP_NET_VF_CFG_MB_SZ 16
+
+/* VF config mailbox */
+#define NFP_NET_VF_CFG_MB 0x0
+#define NFP_NET_VF_CFG_MB_CAP 0x0
+#define NFP_NET_VF_CFG_MB_CAP_MAC (0x1 << 0)
+#define NFP_NET_VF_CFG_MB_CAP_VLAN (0x1 << 1)
+#define NFP_NET_VF_CFG_MB_CAP_SPOOF (0x1 << 2)
+#define NFP_NET_VF_CFG_MB_CAP_LINK_STATE (0x1 << 3)
+#define NFP_NET_VF_CFG_MB_RET 0x2
+#define NFP_NET_VF_CFG_MB_UPD 0x4
+#define NFP_NET_VF_CFG_MB_UPD_MAC (0x1 << 0)
+#define NFP_NET_VF_CFG_MB_UPD_VLAN (0x1 << 1)
+#define NFP_NET_VF_CFG_MB_UPD_SPOOF (0x1 << 2)
+#define NFP_NET_VF_CFG_MB_UPD_LINK_STATE (0x1 << 3)
+#define NFP_NET_VF_CFG_MB_VF_NUM 0x7
+
+/* VF config entry
+ * MAC_LO is set that the MAC address can be read in a single 6 byte read
+ * by the NFP
+ */
+#define NFP_NET_VF_CFG_MAC 0x0
+#define NFP_NET_VF_CFG_MAC_HI 0x0
+#define NFP_NET_VF_CFG_MAC_LO 0x6
+#define NFP_NET_VF_CFG_CTRL 0x4
+#define NFP_NET_VF_CFG_CTRL_SPOOF 0x4
+#define NFP_NET_VF_CFG_CTRL_LINK_STATE 0x3
+#define NFP_NET_VF_CFG_LS_MODE_AUTO 0
+#define NFP_NET_VF_CFG_LS_MODE_ENABLE 1
+#define NFP_NET_VF_CFG_LS_MODE_DISABLE 2
+#define NFP_NET_VF_CFG_VLAN 0x8
+#define NFP_NET_VF_CFG_VLAN_QOS 0xe000
+#define NFP_NET_VF_CFG_VLAN_VID 0x0fff
+
+int nfp_app_set_vf_mac(struct net_device *netdev, int vf, u8 *mac);
+int nfp_app_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
+ __be16 vlan_proto);
+int nfp_app_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
+int nfp_app_set_vf_link_state(struct net_device *netdev, int vf,
+ int link_state);
+int nfp_app_get_vf_config(struct net_device *netdev, int vf,
+ struct ifla_vf_info *ivi);
+
+#endif /* _NFP_NET_SRIOV_H_ */
diff --git a/drivers/net/ethernet/netronome/nfp/nic/main.c b/drivers/net/ethernet/netronome/nfp/nic/main.c
index 520684242b7d..8287a85d22c1 100644
--- a/drivers/net/ethernet/netronome/nfp/nic/main.c
+++ b/drivers/net/ethernet/netronome/nfp/nic/main.c
@@ -49,10 +49,22 @@ static int nfp_nic_init(struct nfp_app *app)
return 0;
}
+static int nfp_nic_sriov_enable(struct nfp_app *app, int num_vfs)
+{
+ return 0;
+}
+
+static void nfp_nic_sriov_disable(struct nfp_app *app)
+{
+}
+
const struct nfp_app_type app_nic = {
.id = NFP_APP_CORE_NIC,
.name = "nic",
.init = nfp_nic_init,
.vnic_init = nfp_app_nic_vnic_init,
+
+ .sriov_enable = nfp_nic_sriov_enable,
+ .sriov_disable = nfp_nic_sriov_disable,
};
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 2/2] nfp: add basic SR-IOV ndo functions to representors
From: Jakub Kicinski @ 2017-08-25 4:31 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, Simon Horman, Dirk van der Merwe
In-Reply-To: <20170825043150.375-1-jakub.kicinski@netronome.com>
From: Simon Horman <simon.horman@netronome.com>
Add basic ndo_set/get_vf to support SR-IOV on all types
of port representors.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 0f9878d1bf40..d540a9dc77b3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -43,6 +43,7 @@
#include "nfp_main.h"
#include "nfp_net_ctrl.h"
#include "nfp_net_repr.h"
+#include "nfp_net_sriov.h"
#include "nfp_port.h"
static void
@@ -247,6 +248,11 @@ const struct net_device_ops nfp_repr_netdev_ops = {
.ndo_get_offload_stats = nfp_repr_get_offload_stats,
.ndo_get_phys_port_name = nfp_port_get_phys_port_name,
.ndo_setup_tc = nfp_port_setup_tc,
+ .ndo_set_vf_mac = nfp_app_set_vf_mac,
+ .ndo_set_vf_vlan = nfp_app_set_vf_vlan,
+ .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
+ .ndo_get_vf_config = nfp_app_get_vf_config,
+ .ndo_set_vf_link_state = nfp_app_set_vf_link_state,
};
static void nfp_repr_clean(struct nfp_repr *repr)
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next v2] net: mv643xx_eth: Be drop monitor friendly
From: Eric Dumazet @ 2017-08-25 4:34 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, davem, andrew, Sebastian Hesselbarth, open list
In-Reply-To: <20170825035540.26713-1-f.fainelli@gmail.com>
On Thu, 2017-08-24 at 20:55 -0700, Florian Fainelli wrote:
> txq_reclaim() does the normal transmit queue reclamation and
> rxq_deinit() does the RX ring cleanup, none of these are packet drops,
> so use dev_consume_skb() for both locations.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> drivers/net/ethernet/marvell/mv643xx_eth.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
> index fb2d533ae4ef..81c1fac00d33 100644
> --- a/drivers/net/ethernet/marvell/mv643xx_eth.c
> +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
> @@ -1121,7 +1121,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
> struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
>
> if (!WARN_ON(!skb))
> - dev_kfree_skb(skb);
> + dev_consume_skb_any(skb);
> }
>
> if (cmd_sts & ERROR_SUMMARY) {
> @@ -2024,7 +2024,7 @@ static void rxq_deinit(struct rx_queue *rxq)
>
> for (i = 0; i < rxq->rx_ring_size; i++) {
> if (rxq->rx_skb[i]) {
> - dev_kfree_skb(rxq->rx_skb[i]);
> + dev_consume_skb_any(rxq->rx_skb[i]);
> rxq->rx_desc_count--;
> }
> }
I do not believe this patch is needed.
dev_kfree_skb() is an alias of consume_skb(), which is already drop
monitor ready ;)
^ permalink raw reply
* [PATCH net-next 0/3 v9] Add support for rmnet driver
From: Subash Abhinov Kasiviswanathan @ 2017-08-25 4:39 UTC (permalink / raw)
To: netdev, davem, fengguang.wu, dcbw, jiri, stephen, David.Laight,
marcel, andrew
Cc: Subash Abhinov Kasiviswanathan
This patch adds support for the rmnet driver which is required to
support recent chipsets using Qualcomm Technologies, Inc. modems. The data
from hardware follows the multiplexing and aggregation protocol (MAP).
This driver can be used to register onto any physical network device in
IP mode. Physical transports include USB, HSIC, PCIe and IP accelerator.
rmnet driver helps to decode these packets and queue them to network
stack (and encode and transmit it to the physical device).
--
v1: Same as the RFC patch with some minor fixes for issues reported by
kbuild test robot.
v1->v2: Change datatypes and remove config IOCTL as mentioned by David.
Also fix checkpatch issues and remove some unused code.
v2->v3: Move location to drivers/net and rename to rmnet. Change the
userspace - netlink communication from custom netlink to rtnl_link_ops.
Refactor some code. Use a fixed config for ingress and egress.
v3->v4: Move location to drivers/net/ethernet/qualcomm/.
Fix comments from Stephen and Jiri -
Split the ether and arp type changes into seperate patches.
Remove debug and custom logging and switch to standard netdevice log.
Remove module parameters. Refactor and change some code style issues.
v4->v5: Rename some structs and variables. Move the initializer
before the for loop start. Put the arp type in correct sequence.
v5->v6: Fix comments from Dan -
Use the upper link API. As a result, remove all the refcounting logic.
Device refcount is explicitly held on real_dev on rx_handler
registration only. Modifiy the flow control struct. Remove the unused
ethernet mode handling.
v6->v7: Fix comments from David - Add newline to end of Makefile. Remove
inline from .c files. Move the module init/exit to rmnet config. Fix an
error reported by kbuild test robot for an unused file.
v7->v8: Use a smaller value for ETH_P_MAP as mentioned by David. Change
netdev_info to netdev_dbg as mentioned by Andew. Fix comments from
Stephen regarding netdev_priv and sparse related errors of using 0 as NULL
v8->v9: Fix comments from David - Remove the CFLAG rule. Change the way
rmnet devices are freed. Instead of using a workqueue to unregister devices
individually, go through the list and free all devices within the rtnl_lock().
Subash Abhinov Kasiviswanathan (3):
net: ether: Add support for multiplexing and aggregation type
net: arp: Add support for raw IP device
drivers: net: ethernet: qualcomm: rmnet: Initial implementation
Documentation/networking/rmnet.txt | 82 +++++
drivers/net/ethernet/qualcomm/Kconfig | 2 +
drivers/net/ethernet/qualcomm/Makefile | 2 +
drivers/net/ethernet/qualcomm/rmnet/Kconfig | 12 +
drivers/net/ethernet/qualcomm/rmnet/Makefile | 10 +
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 401 +++++++++++++++++++++
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h | 54 +++
.../net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 271 ++++++++++++++
.../net/ethernet/qualcomm/rmnet/rmnet_handlers.h | 26 ++
drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h | 88 +++++
.../ethernet/qualcomm/rmnet/rmnet_map_command.c | 107 ++++++
.../net/ethernet/qualcomm/rmnet/rmnet_map_data.c | 105 ++++++
.../net/ethernet/qualcomm/rmnet/rmnet_private.h | 45 +++
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 197 ++++++++++
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h | 30 ++
include/uapi/linux/if_arp.h | 1 +
include/uapi/linux/if_ether.h | 1 +
17 files changed, 1434 insertions(+)
create mode 100644 Documentation/networking/rmnet.txt
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/Kconfig
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/Makefile
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
--
1.9.1
^ permalink raw reply
* [PATCH net-next 1/3 v9] net: ether: Add support for multiplexing and aggregation type
From: Subash Abhinov Kasiviswanathan @ 2017-08-25 4:39 UTC (permalink / raw)
To: netdev, davem, fengguang.wu, dcbw, jiri, stephen, David.Laight,
marcel, andrew
Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1503635966-14076-1-git-send-email-subashab@codeaurora.org>
Define the multiplexing and aggregation (MAP) ether type 0x00F9. This
is needed for receiving data in the MAP protocol like RMNET. This is
not an officially registered ID.
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
include/uapi/linux/if_ether.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 5bc9bfd..0d73ecc 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -137,6 +137,7 @@
#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */
#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */
#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */
+#define ETH_P_MAP 0x00F9 /* Multiplex & aggregation proto*/
/*
* This is an Ethernet frame header.
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/3 v9] net: arp: Add support for raw IP device
From: Subash Abhinov Kasiviswanathan @ 2017-08-25 4:39 UTC (permalink / raw)
To: netdev, davem, fengguang.wu, dcbw, jiri, stephen, David.Laight,
marcel, andrew
Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1503635966-14076-1-git-send-email-subashab@codeaurora.org>
Define the raw IP type. This is needed for raw IP net devices
like rmnet.
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
include/uapi/linux/if_arp.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h
index cf73510..a2a6356 100644
--- a/include/uapi/linux/if_arp.h
+++ b/include/uapi/linux/if_arp.h
@@ -59,6 +59,7 @@
#define ARPHRD_LAPB 516 /* LAPB */
#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */
#define ARPHRD_RAWHDLC 518 /* Raw HDLC */
+#define ARPHRD_RAWIP 519 /* Raw IP */
#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 3/3 v9] drivers: net: ethernet: qualcomm: rmnet: Initial implementation
From: Subash Abhinov Kasiviswanathan @ 2017-08-25 4:39 UTC (permalink / raw)
To: netdev, davem, fengguang.wu, dcbw, jiri, stephen, David.Laight,
marcel, andrew
Cc: Subash Abhinov Kasiviswanathan
In-Reply-To: <1503635966-14076-1-git-send-email-subashab@codeaurora.org>
RmNet driver provides a transport agnostic MAP (multiplexing and
aggregation protocol) support in embedded module. Module provides
virtual network devices which can be attached to any IP-mode
physical device. This will be used to provide all MAP functionality
on future hardware in a single consistent location.
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
---
Documentation/networking/rmnet.txt | 82 +++++
drivers/net/ethernet/qualcomm/Kconfig | 2 +
drivers/net/ethernet/qualcomm/Makefile | 2 +
drivers/net/ethernet/qualcomm/rmnet/Kconfig | 12 +
drivers/net/ethernet/qualcomm/rmnet/Makefile | 10 +
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 401 +++++++++++++++++++++
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h | 54 +++
.../net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 271 ++++++++++++++
.../net/ethernet/qualcomm/rmnet/rmnet_handlers.h | 26 ++
drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h | 88 +++++
.../ethernet/qualcomm/rmnet/rmnet_map_command.c | 107 ++++++
.../net/ethernet/qualcomm/rmnet/rmnet_map_data.c | 105 ++++++
.../net/ethernet/qualcomm/rmnet/rmnet_private.h | 45 +++
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 197 ++++++++++
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h | 30 ++
15 files changed, 1432 insertions(+)
create mode 100644 Documentation/networking/rmnet.txt
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/Kconfig
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/Makefile
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
create mode 100644 drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
diff --git a/Documentation/networking/rmnet.txt b/Documentation/networking/rmnet.txt
new file mode 100644
index 0000000..6b341ea
--- /dev/null
+++ b/Documentation/networking/rmnet.txt
@@ -0,0 +1,82 @@
+1. Introduction
+
+rmnet driver is used for supporting the Multiplexing and aggregation
+Protocol (MAP). This protocol is used by all recent chipsets using Qualcomm
+Technologies, Inc. modems.
+
+This driver can be used to register onto any physical network device in
+IP mode. Physical transports include USB, HSIC, PCIe and IP accelerator.
+
+Multiplexing allows for creation of logical netdevices (rmnet devices) to
+handle multiple private data networks (PDN) like a default internet, tethering,
+multimedia messaging service (MMS) or IP media subsystem (IMS). Hardware sends
+packets with MAP headers to rmnet. Based on the multiplexer id, rmnet
+routes to the appropriate PDN after removing the MAP header.
+
+Aggregation is required to achieve high data rates. This involves hardware
+sending aggregated bunch of MAP frames. rmnet driver will de-aggregate
+these MAP frames and send them to appropriate PDN's.
+
+2. Packet format
+
+a. MAP packet (data / control)
+
+MAP header has the same endianness of the IP packet.
+
+Packet format -
+
+Bit 0 1 2-7 8 - 15 16 - 31
+Function Command / Data Reserved Pad Multiplexer ID Payload length
+Bit 32 - x
+Function Raw Bytes
+
+Command (1)/ Data (0) bit value is to indicate if the packet is a MAP command
+or data packet. Control packet is used for transport level flow control. Data
+packets are standard IP packets.
+
+Reserved bits are usually zeroed out and to be ignored by receiver.
+
+Padding is number of bytes to be added for 4 byte alignment if required by
+hardware.
+
+Multiplexer ID is to indicate the PDN on which data has to be sent.
+
+Payload length includes the padding length but does not include MAP header
+length.
+
+b. MAP packet (command specific)
+
+Bit 0 1 2-7 8 - 15 16 - 31
+Function Command Reserved Pad Multiplexer ID Payload length
+Bit 32 - 39 40 - 45 46 - 47 48 - 63
+Function Command name Reserved Command Type Reserved
+Bit 64 - 95
+Function Transaction ID
+Bit 96 - 127
+Function Command data
+
+Command 1 indicates disabling flow while 2 is enabling flow
+
+Command types -
+0 for MAP command request
+1 is to acknowledge the receipt of a command
+2 is for unsupported commands
+3 is for error during processing of commands
+
+c. Aggregation
+
+Aggregation is multiple MAP packets (can be data or command) delivered to
+rmnet in a single linear skb. rmnet will process the individual
+packets and either ACK the MAP command or deliver the IP packet to the
+network stack as needed
+
+MAP header|IP Packet|Optional padding|MAP header|IP Packet|Optional padding....
+MAP header|IP Packet|Optional padding|MAP header|Command Packet|Optional pad...
+
+3. Userspace configuration
+
+rmnet userspace configuration is done through netlink library librmnetctl
+and command line utility rmnetcli. Utility is hosted in codeaurora forum git.
+The driver uses rtnl_link_ops for communication.
+
+https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl
diff --git a/drivers/net/ethernet/qualcomm/Kconfig b/drivers/net/ethernet/qualcomm/Kconfig
index 877675a..f520071 100644
--- a/drivers/net/ethernet/qualcomm/Kconfig
+++ b/drivers/net/ethernet/qualcomm/Kconfig
@@ -59,4 +59,6 @@ config QCOM_EMAC
low power, Receive-Side Scaling (RSS), and IEEE 1588-2008
Precision Clock Synchronization Protocol.
+source "drivers/net/ethernet/qualcomm/rmnet/Kconfig"
+
endif # NET_VENDOR_QUALCOMM
diff --git a/drivers/net/ethernet/qualcomm/Makefile b/drivers/net/ethernet/qualcomm/Makefile
index 92fa7c4..1847350 100644
--- a/drivers/net/ethernet/qualcomm/Makefile
+++ b/drivers/net/ethernet/qualcomm/Makefile
@@ -9,3 +9,5 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o
qcauart-objs := qca_uart.o
obj-y += emac/
+
+obj-$(CONFIG_RMNET) += rmnet/
diff --git a/drivers/net/ethernet/qualcomm/rmnet/Kconfig b/drivers/net/ethernet/qualcomm/rmnet/Kconfig
new file mode 100644
index 0000000..4948f14
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/Kconfig
@@ -0,0 +1,12 @@
+#
+# RMNET MAP driver
+#
+
+menuconfig RMNET
+ depends on NETDEVICES
+ bool "RmNet MAP driver"
+ default n
+ ---help---
+ If you say Y here, then the rmnet module will be statically
+ compiled into the kernel. The rmnet module provides MAP
+ functionality for embedded and bridged traffic.
diff --git a/drivers/net/ethernet/qualcomm/rmnet/Makefile b/drivers/net/ethernet/qualcomm/rmnet/Makefile
new file mode 100644
index 0000000..01bddf2
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the RMNET module
+#
+
+rmnet-y := rmnet_config.o
+rmnet-y += rmnet_vnd.o
+rmnet-y += rmnet_handlers.o
+rmnet-y += rmnet_map_data.o
+rmnet-y += rmnet_map_command.o
+obj-$(CONFIG_RMNET) += rmnet.o
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
new file mode 100644
index 0000000..788074d
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -0,0 +1,401 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET configuration engine
+ *
+ */
+
+#include <net/sock.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netdevice.h>
+#include "rmnet_config.h"
+#include "rmnet_handlers.h"
+#include "rmnet_vnd.h"
+#include "rmnet_private.h"
+
+/* Local Definitions and Declarations */
+#define RMNET_LOCAL_LOGICAL_ENDPOINT -1
+
+struct rmnet_walk_data {
+ struct net_device *real_dev;
+ struct list_head *head;
+};
+
+static int rmnet_is_real_dev_registered(const struct net_device *real_dev)
+{
+ rx_handler_func_t *rx_handler;
+
+ rx_handler = rcu_dereference(real_dev->rx_handler);
+ return (rx_handler == rmnet_rx_handler);
+}
+
+static struct rmnet_real_dev_info*
+__rmnet_get_real_dev_info(const struct net_device *real_dev)
+{
+ if (rmnet_is_real_dev_registered(real_dev))
+ return (struct rmnet_real_dev_info *)
+ rcu_dereference(real_dev->rx_handler_data);
+ else
+ return NULL;
+}
+
+static struct rmnet_endpoint*
+rmnet_get_endpoint(struct net_device *dev, int config_id)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ struct rmnet_endpoint *ep;
+
+ if (!rmnet_is_real_dev_registered(dev)) {
+ ep = rmnet_vnd_get_endpoint(dev);
+ } else {
+ rdinfo = __rmnet_get_real_dev_info(dev);
+
+ if (!rdinfo)
+ return NULL;
+
+ if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
+ ep = &rdinfo->local_ep;
+ else
+ ep = &rdinfo->muxed_ep[config_id];
+ }
+
+ return ep;
+}
+
+static int rmnet_unregister_real_device(struct net_device *real_dev)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ struct list_head *iter;
+
+ if (!rmnet_is_real_dev_registered(real_dev) ||
+ netdev_lower_get_next(real_dev, &iter))
+ return -EINVAL;
+
+ rdinfo = __rmnet_get_real_dev_info(real_dev);
+ kfree(rdinfo);
+
+ netdev_rx_handler_unregister(real_dev);
+
+ /* release reference on real_dev */
+ dev_put(real_dev);
+
+ netdev_dbg(real_dev, "Removed from rmnet\n");
+ return 0;
+}
+
+static int rmnet_register_real_device(struct net_device *real_dev)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ int rc;
+
+ ASSERT_RTNL();
+
+ if (rmnet_is_real_dev_registered(real_dev))
+ return -EINVAL;
+
+ rdinfo = kzalloc(sizeof(*rdinfo), GFP_ATOMIC);
+ if (!rdinfo)
+ return -ENOMEM;
+
+ rdinfo->dev = real_dev;
+ rc = netdev_rx_handler_register(real_dev, rmnet_rx_handler, rdinfo);
+
+ if (rc) {
+ kfree(rdinfo);
+ return -EBUSY;
+ }
+
+ /* hold on to real dev for MAP data */
+ dev_hold(real_dev);
+
+ netdev_dbg(real_dev, "registered with rmnet\n");
+ return 0;
+}
+
+static int rmnet_set_ingress_data_format(struct net_device *dev, u32 idf)
+{
+ struct rmnet_real_dev_info *rdinfo;
+
+ netdev_dbg(dev, "Ingress format 0x%08X\n", idf);
+
+ rdinfo = __rmnet_get_real_dev_info(dev);
+ if (!rdinfo)
+ return -EINVAL;
+
+ rdinfo->ingress_data_format = idf;
+
+ return 0;
+}
+
+static int rmnet_set_egress_data_format(struct net_device *dev, u32 edf,
+ u16 agg_size, u16 agg_count)
+{
+ struct rmnet_real_dev_info *rdinfo;
+
+ netdev_dbg(dev, "Egress format 0x%08X agg size %d cnt %d\n",
+ edf, agg_size, agg_count);
+
+ rdinfo = __rmnet_get_real_dev_info(dev);
+ if (!rdinfo)
+ return -EINVAL;
+
+ rdinfo->egress_data_format = edf;
+
+ return 0;
+}
+
+static int __rmnet_set_endpoint_config(struct net_device *dev, int config_id,
+ struct rmnet_endpoint *ep)
+{
+ struct rmnet_endpoint *dev_ep;
+
+ dev_ep = rmnet_get_endpoint(dev, config_id);
+
+ if (!dev_ep)
+ return -EINVAL;
+
+ memcpy(dev_ep, ep, sizeof(struct rmnet_endpoint));
+ if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
+ dev_ep->mux_id = 0;
+ else
+ dev_ep->mux_id = config_id;
+
+ return 0;
+}
+
+static int __rmnet_unset_endpoint_config(struct net_device *dev, int config_id)
+{
+ struct rmnet_endpoint *ep;
+
+ ep = rmnet_get_endpoint(dev, config_id);
+ if (!ep)
+ return -EINVAL;
+
+ memset(ep, 0, sizeof(struct rmnet_endpoint));
+
+ return 0;
+}
+
+static int rmnet_set_endpoint_config(struct net_device *dev,
+ int config_id, u8 rmnet_mode,
+ struct net_device *egress_dev)
+{
+ struct rmnet_endpoint ep;
+
+ netdev_dbg(dev, "id %d mode %d dev %s\n",
+ config_id, rmnet_mode, egress_dev->name);
+
+ if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
+ config_id >= RMNET_MAX_LOGICAL_EP)
+ return -EINVAL;
+
+ memset(&ep, 0, sizeof(struct rmnet_endpoint));
+ ep.rmnet_mode = rmnet_mode;
+ ep.egress_dev = egress_dev;
+
+ return __rmnet_set_endpoint_config(dev, config_id, &ep);
+}
+
+static int rmnet_unset_endpoint_config(struct net_device *dev, int config_id)
+{
+ netdev_dbg(dev, "id %d\n", config_id);
+
+ if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
+ config_id >= RMNET_MAX_LOGICAL_EP)
+ return -EINVAL;
+
+ return __rmnet_unset_endpoint_config(dev, config_id);
+}
+
+static int rmnet_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ int ingress_format = RMNET_INGRESS_FORMAT_DEMUXING |
+ RMNET_INGRESS_FORMAT_DEAGGREGATION |
+ RMNET_INGRESS_FORMAT_MAP;
+ int egress_format = RMNET_EGRESS_FORMAT_MUXING |
+ RMNET_EGRESS_FORMAT_MAP;
+ struct net_device *real_dev;
+ int mode = RMNET_EPMODE_VND;
+ u16 mux_id;
+
+ real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+ if (!real_dev || !dev)
+ return -ENODEV;
+
+ if (!data[IFLA_VLAN_ID])
+ return -EINVAL;
+
+ mux_id = nla_get_u16(data[IFLA_VLAN_ID]);
+
+ rmnet_register_real_device(real_dev);
+
+ if (rmnet_vnd_newlink(real_dev, mux_id, dev))
+ return -EINVAL;
+
+ rmnet_set_egress_data_format(real_dev, egress_format, 0, 0);
+ rmnet_set_ingress_data_format(real_dev, ingress_format);
+ rmnet_set_endpoint_config(real_dev, mux_id, mode, dev);
+ rmnet_set_endpoint_config(dev, mux_id, mode, real_dev);
+ netdev_master_upper_dev_link(dev, real_dev, NULL, NULL);
+ return 0;
+}
+
+static void rmnet_delink(struct net_device *dev, struct list_head *head)
+{
+ struct net_device *real_dev;
+ int mux_id;
+
+ rcu_read_lock();
+ real_dev = netdev_master_upper_dev_get_rcu(dev);
+ if (real_dev) {
+ mux_id = rmnet_vnd_get_mux(real_dev, dev);
+
+ /* rmnet_vnd_get_mux() gives mux_id + 1,
+ * so subtract 1 to get the correct mux_id
+ */
+ mux_id--;
+ rmnet_unset_endpoint_config(real_dev, mux_id);
+ rmnet_unset_endpoint_config(dev, mux_id);
+ rmnet_vnd_remove_ref_dev(real_dev, mux_id);
+ netdev_upper_dev_unlink(dev, real_dev);
+ rmnet_unregister_real_device(real_dev);
+ }
+ rcu_read_unlock();
+
+ unregister_netdevice_queue(dev, head);
+}
+
+static int rmnet_dev_walk_unreg(struct net_device *lower_dev, void *data)
+{
+ struct rmnet_walk_data *d = data;
+
+ netdev_upper_dev_unlink(lower_dev, d->real_dev);
+ unregister_netdevice_queue(lower_dev, d->head);
+
+ return 0;
+}
+
+static void rmnet_force_unassociate_device(struct net_device *dev)
+{
+ struct net_device *real_dev = dev;
+ struct rmnet_walk_data d;
+ LIST_HEAD(list);
+
+ if (!rmnet_is_real_dev_registered(real_dev))
+ return;
+
+ ASSERT_RTNL();
+
+ d.real_dev = real_dev;
+ d.head = &list;
+
+ rcu_read_lock();
+ netdev_walk_all_lower_dev_rcu(real_dev, rmnet_dev_walk_unreg, &d);
+ synchronize_net();
+
+ unregister_netdevice_many(&list);
+ rcu_read_unlock();
+
+ rmnet_unregister_real_device(real_dev);
+}
+
+static int rmnet_config_notify_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(data);
+
+ if (!dev)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ netdev_dbg(dev, "Kernel unregister\n");
+ rmnet_force_unassociate_device(dev);
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rmnet_dev_notifier __read_mostly = {
+ .notifier_call = rmnet_config_notify_cb,
+};
+
+static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ u16 mux_id;
+
+ if (!data || !data[IFLA_VLAN_ID])
+ return -EINVAL;
+
+ mux_id = nla_get_u16(data[IFLA_VLAN_ID]);
+ if (!mux_id || mux_id > (RMNET_MAX_LOGICAL_EP - 1))
+ return -ERANGE;
+
+ return 0;
+}
+
+static size_t rmnet_get_size(const struct net_device *dev)
+{
+ return nla_total_size(2); /* IFLA_VLAN_ID */
+}
+
+struct rtnl_link_ops rmnet_link_ops __read_mostly = {
+ .kind = "rmnet",
+ .maxtype = __IFLA_VLAN_MAX,
+ .priv_size = sizeof(struct rmnet_priv),
+ .setup = rmnet_vnd_setup,
+ .validate = rmnet_rtnl_validate,
+ .newlink = rmnet_newlink,
+ .dellink = rmnet_delink,
+ .get_size = rmnet_get_size,
+};
+
+struct rmnet_real_dev_info*
+rmnet_get_real_dev_info(struct net_device *real_dev)
+{
+ return __rmnet_get_real_dev_info(real_dev);
+}
+
+/* Startup/Shutdown */
+
+static int __init rmnet_init(void)
+{
+ int rc;
+
+ rc = register_netdevice_notifier(&rmnet_dev_notifier);
+ if (rc != 0)
+ return rc;
+
+ rc = rtnl_link_register(&rmnet_link_ops);
+ if (rc != 0) {
+ unregister_netdevice_notifier(&rmnet_dev_notifier);
+ return rc;
+ }
+ return rc;
+}
+
+static void __exit rmnet_exit(void)
+{
+ unregister_netdevice_notifier(&rmnet_dev_notifier);
+ rtnl_link_unregister(&rmnet_link_ops);
+}
+
+module_init(rmnet_init)
+module_exit(rmnet_exit)
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
new file mode 100644
index 0000000..8f5a073
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET Data configuration engine
+ *
+ */
+
+#include <linux/skbuff.h>
+
+#ifndef _RMNET_CONFIG_H_
+#define _RMNET_CONFIG_H_
+
+#define RMNET_MAX_LOGICAL_EP 255
+#define RMNET_MAX_VND 32
+
+/* Information about the next device to deliver the packet to.
+ * Exact usage of this parameter depends on the rmnet_mode.
+ */
+struct rmnet_endpoint {
+ u8 rmnet_mode;
+ u8 mux_id;
+ struct net_device *egress_dev;
+};
+
+/* One instance of this structure is instantiated for each real_dev associated
+ * with rmnet.
+ */
+struct rmnet_real_dev_info {
+ struct net_device *dev;
+ struct rmnet_endpoint local_ep;
+ struct rmnet_endpoint muxed_ep[RMNET_MAX_LOGICAL_EP];
+ u32 ingress_data_format;
+ u32 egress_data_format;
+ struct net_device *rmnet_devices[RMNET_MAX_VND];
+};
+
+extern struct rtnl_link_ops rmnet_link_ops;
+
+struct rmnet_priv {
+ struct rmnet_endpoint local_ep;
+};
+
+struct rmnet_real_dev_info*
+rmnet_get_real_dev_info(struct net_device *real_dev);
+
+#endif /* _RMNET_CONFIG_H_ */
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
new file mode 100644
index 0000000..bef49ed
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -0,0 +1,271 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET Data ingress/egress handler
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/netdev_features.h>
+#include "rmnet_private.h"
+#include "rmnet_config.h"
+#include "rmnet_vnd.h"
+#include "rmnet_map.h"
+#include "rmnet_handlers.h"
+
+#define RMNET_IP_VERSION_4 0x40
+#define RMNET_IP_VERSION_6 0x60
+
+/* Helper Functions */
+
+static void rmnet_set_skb_proto(struct sk_buff *skb)
+{
+ switch (skb->data[0] & 0xF0) {
+ case RMNET_IP_VERSION_4:
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case RMNET_IP_VERSION_6:
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ default:
+ skb->protocol = htons(ETH_P_MAP);
+ break;
+ }
+}
+
+/* Generic handler */
+
+static rx_handler_result_t
+rmnet_bridge_handler(struct sk_buff *skb, struct rmnet_endpoint *ep)
+{
+ if (!ep->egress_dev)
+ kfree_skb(skb);
+ else
+ rmnet_egress_handler(skb, ep);
+
+ return RX_HANDLER_CONSUMED;
+}
+
+static rx_handler_result_t
+rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_endpoint *ep)
+{
+ switch (ep->rmnet_mode) {
+ case RMNET_EPMODE_NONE:
+ return RX_HANDLER_PASS;
+
+ case RMNET_EPMODE_BRIDGE:
+ return rmnet_bridge_handler(skb, ep);
+
+ case RMNET_EPMODE_VND:
+ skb_reset_transport_header(skb);
+ skb_reset_network_header(skb);
+ rmnet_vnd_rx_fixup(skb, skb->dev);
+
+ skb->pkt_type = PACKET_HOST;
+ skb_set_mac_header(skb, 0);
+ netif_receive_skb(skb);
+ return RX_HANDLER_CONSUMED;
+
+ default:
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+}
+
+static rx_handler_result_t
+rmnet_ingress_deliver_packet(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ if (!rdinfo) {
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+
+ skb->dev = rdinfo->local_ep.egress_dev;
+
+ return rmnet_deliver_skb(skb, &rdinfo->local_ep);
+}
+
+/* MAP handler */
+
+static rx_handler_result_t
+__rmnet_map_ingress_handler(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ struct rmnet_endpoint *ep;
+ u8 mux_id;
+ u16 len;
+
+ if (RMNET_MAP_GET_CD_BIT(skb)) {
+ if (rdinfo->ingress_data_format
+ & RMNET_INGRESS_FORMAT_MAP_COMMANDS)
+ return rmnet_map_command(skb, rdinfo);
+
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+
+ mux_id = RMNET_MAP_GET_MUX_ID(skb);
+ len = RMNET_MAP_GET_LENGTH(skb) - RMNET_MAP_GET_PAD(skb);
+
+ if (mux_id >= RMNET_MAX_LOGICAL_EP) {
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+
+ ep = &rdinfo->muxed_ep[mux_id];
+
+ if (rdinfo->ingress_data_format & RMNET_INGRESS_FORMAT_DEMUXING)
+ skb->dev = ep->egress_dev;
+
+ /* Subtract MAP header */
+ skb_pull(skb, sizeof(struct rmnet_map_header));
+ skb_trim(skb, len);
+ rmnet_set_skb_proto(skb);
+ return rmnet_deliver_skb(skb, ep);
+}
+
+static rx_handler_result_t
+rmnet_map_ingress_handler(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ struct sk_buff *skbn;
+ int rc;
+
+ if (rdinfo->ingress_data_format & RMNET_INGRESS_FORMAT_DEAGGREGATION) {
+ while ((skbn = rmnet_map_deaggregate(skb, rdinfo)) != NULL)
+ __rmnet_map_ingress_handler(skbn, rdinfo);
+
+ consume_skb(skb);
+ rc = RX_HANDLER_CONSUMED;
+ } else {
+ rc = __rmnet_map_ingress_handler(skb, rdinfo);
+ }
+
+ return rc;
+}
+
+static int rmnet_map_egress_handler(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo,
+ struct rmnet_endpoint *ep,
+ struct net_device *orig_dev)
+{
+ int required_headroom, additional_header_len;
+ struct rmnet_map_header *map_header;
+
+ additional_header_len = 0;
+ required_headroom = sizeof(struct rmnet_map_header);
+
+ if (skb_headroom(skb) < required_headroom) {
+ if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL))
+ return RMNET_MAP_CONSUMED;
+ }
+
+ map_header = rmnet_map_add_map_header(skb, additional_header_len, 0);
+ if (!map_header)
+ return RMNET_MAP_CONSUMED;
+
+ if (rdinfo->egress_data_format & RMNET_EGRESS_FORMAT_MUXING) {
+ if (ep->mux_id == 0xff)
+ map_header->mux_id = 0;
+ else
+ map_header->mux_id = ep->mux_id;
+ }
+
+ skb->protocol = htons(ETH_P_MAP);
+
+ return RMNET_MAP_SUCCESS;
+}
+
+/* Ingress / Egress Entry Points */
+
+/* Processes packet as per ingress data format for receiving device. Logical
+ * endpoint is determined from packet inspection. Packet is then sent to the
+ * egress device listed in the logical endpoint configuration.
+ */
+rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ struct sk_buff *skb = *pskb;
+ struct net_device *dev;
+ int rc;
+
+ if (!skb)
+ return RX_HANDLER_CONSUMED;
+
+ dev = skb->dev;
+ rdinfo = rmnet_get_real_dev_info(dev);
+
+ if (rdinfo->ingress_data_format & RMNET_INGRESS_FORMAT_MAP) {
+ rc = rmnet_map_ingress_handler(skb, rdinfo);
+ } else {
+ switch (ntohs(skb->protocol)) {
+ case ETH_P_MAP:
+ if (rdinfo->local_ep.rmnet_mode ==
+ RMNET_EPMODE_BRIDGE) {
+ rc = rmnet_ingress_deliver_packet(skb, rdinfo);
+ } else {
+ kfree_skb(skb);
+ rc = RX_HANDLER_CONSUMED;
+ }
+ break;
+
+ case ETH_P_IP:
+ case ETH_P_IPV6:
+ rc = rmnet_ingress_deliver_packet(skb, rdinfo);
+ break;
+
+ default:
+ rc = RX_HANDLER_PASS;
+ }
+ }
+
+ return rc;
+}
+
+/* Modifies packet as per logical endpoint configuration and egress data format
+ * for egress device configured in logical endpoint. Packet is then transmitted
+ * on the egress device.
+ */
+void rmnet_egress_handler(struct sk_buff *skb,
+ struct rmnet_endpoint *ep)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ struct net_device *orig_dev;
+
+ orig_dev = skb->dev;
+ skb->dev = ep->egress_dev;
+
+ rdinfo = rmnet_get_real_dev_info(skb->dev);
+ if (!rdinfo) {
+ kfree_skb(skb);
+ return;
+ }
+
+ if (rdinfo->egress_data_format & RMNET_EGRESS_FORMAT_MAP) {
+ switch (rmnet_map_egress_handler(skb, rdinfo, ep, orig_dev)) {
+ case RMNET_MAP_CONSUMED:
+ return;
+
+ case RMNET_MAP_SUCCESS:
+ break;
+
+ default:
+ kfree_skb(skb);
+ return;
+ }
+ }
+
+ if (ep->rmnet_mode == RMNET_EPMODE_VND)
+ rmnet_vnd_tx_fixup(skb, orig_dev);
+
+ dev_queue_xmit(skb);
+}
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h
new file mode 100644
index 0000000..f2638cf
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET Data ingress/egress handler
+ *
+ */
+
+#ifndef _RMNET_HANDLERS_H_
+#define _RMNET_HANDLERS_H_
+
+#include "rmnet_config.h"
+
+void rmnet_egress_handler(struct sk_buff *skb,
+ struct rmnet_endpoint *ep);
+
+rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb);
+
+#endif /* _RMNET_HANDLERS_H_ */
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
new file mode 100644
index 0000000..2aabad2
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _RMNET_MAP_H_
+#define _RMNET_MAP_H_
+
+struct rmnet_map_control_command {
+ u8 command_name;
+ u8 cmd_type:2;
+ u8 reserved:6;
+ u16 reserved2;
+ u32 transaction_id;
+ union {
+ struct {
+ u16 ip_family:2;
+ u16 reserved:14;
+ u16 flow_control_seq_num;
+ u32 qos_id;
+ } flow_control;
+ u8 data[0];
+ };
+} __aligned(1);
+
+enum rmnet_map_results {
+ RMNET_MAP_SUCCESS,
+ RMNET_MAP_CONSUMED,
+ RMNET_MAP_GENERAL_FAILURE,
+ RMNET_MAP_NOT_ENABLED,
+ RMNET_MAP_FAILED_AGGREGATION,
+ RMNET_MAP_FAILED_MUX
+};
+
+enum rmnet_map_commands {
+ RMNET_MAP_COMMAND_NONE,
+ RMNET_MAP_COMMAND_FLOW_DISABLE,
+ RMNET_MAP_COMMAND_FLOW_ENABLE,
+ /* These should always be the last 2 elements */
+ RMNET_MAP_COMMAND_UNKNOWN,
+ RMNET_MAP_COMMAND_ENUM_LENGTH
+};
+
+struct rmnet_map_header {
+ u8 pad_len:6;
+ u8 reserved_bit:1;
+ u8 cd_bit:1;
+ u8 mux_id;
+ u16 pkt_len;
+} __aligned(1);
+
+#define RMNET_MAP_GET_MUX_ID(Y) (((struct rmnet_map_header *) \
+ (Y)->data)->mux_id)
+#define RMNET_MAP_GET_CD_BIT(Y) (((struct rmnet_map_header *) \
+ (Y)->data)->cd_bit)
+#define RMNET_MAP_GET_PAD(Y) (((struct rmnet_map_header *) \
+ (Y)->data)->pad_len)
+#define RMNET_MAP_GET_CMD_START(Y) ((struct rmnet_map_control_command *) \
+ ((Y)->data + \
+ sizeof(struct rmnet_map_header)))
+#define RMNET_MAP_GET_LENGTH(Y) (ntohs(((struct rmnet_map_header *) \
+ (Y)->data)->pkt_len))
+
+#define RMNET_MAP_COMMAND_REQUEST 0
+#define RMNET_MAP_COMMAND_ACK 1
+#define RMNET_MAP_COMMAND_UNSUPPORTED 2
+#define RMNET_MAP_COMMAND_INVALID 3
+
+#define RMNET_MAP_NO_PAD_BYTES 0
+#define RMNET_MAP_ADD_PAD_BYTES 1
+
+u8 rmnet_map_demultiplex(struct sk_buff *skb);
+struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo);
+
+struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
+ int hdrlen, int pad);
+rx_handler_result_t rmnet_map_command(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo);
+
+#endif /* _RMNET_MAP_H_ */
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
new file mode 100644
index 0000000..ccded40
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c
@@ -0,0 +1,107 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/netdevice.h>
+#include "rmnet_config.h"
+#include "rmnet_map.h"
+#include "rmnet_private.h"
+#include "rmnet_vnd.h"
+
+static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo,
+ int enable)
+{
+ struct rmnet_map_control_command *cmd;
+ struct rmnet_endpoint *ep;
+ struct net_device *vnd;
+ u16 ip_family;
+ u16 fc_seq;
+ u32 qos_id;
+ u8 mux_id;
+ int r;
+
+ mux_id = RMNET_MAP_GET_MUX_ID(skb);
+ cmd = RMNET_MAP_GET_CMD_START(skb);
+
+ if (mux_id >= RMNET_MAX_LOGICAL_EP) {
+ kfree_skb(skb);
+ return RX_HANDLER_CONSUMED;
+ }
+
+ ep = &rdinfo->muxed_ep[mux_id];
+ vnd = ep->egress_dev;
+
+ ip_family = cmd->flow_control.ip_family;
+ fc_seq = ntohs(cmd->flow_control.flow_control_seq_num);
+ qos_id = ntohl(cmd->flow_control.qos_id);
+
+ /* Ignore the ip family and pass the sequence number for both v4 and v6
+ * sequence. User space does not support creating dedicated flows for
+ * the 2 protocols
+ */
+ r = rmnet_vnd_do_flow_control(vnd, enable);
+ if (r) {
+ kfree_skb(skb);
+ return RMNET_MAP_COMMAND_UNSUPPORTED;
+ } else {
+ return RMNET_MAP_COMMAND_ACK;
+ }
+}
+
+static void rmnet_map_send_ack(struct sk_buff *skb,
+ unsigned char type,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ struct rmnet_map_control_command *cmd;
+ int xmit_status;
+
+ skb->protocol = htons(ETH_P_MAP);
+
+ cmd = RMNET_MAP_GET_CMD_START(skb);
+ cmd->cmd_type = type & 0x03;
+
+ netif_tx_lock(skb->dev);
+ xmit_status = skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev);
+ netif_tx_unlock(skb->dev);
+}
+
+/* Process MAP command frame and send N/ACK message as appropriate. Message cmd
+ * name is decoded here and appropriate handler is called.
+ */
+rx_handler_result_t rmnet_map_command(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ struct rmnet_map_control_command *cmd;
+ unsigned char command_name;
+ unsigned char rc = 0;
+
+ cmd = RMNET_MAP_GET_CMD_START(skb);
+ command_name = cmd->command_name;
+
+ switch (command_name) {
+ case RMNET_MAP_COMMAND_FLOW_ENABLE:
+ rc = rmnet_map_do_flow_control(skb, rdinfo, 1);
+ break;
+
+ case RMNET_MAP_COMMAND_FLOW_DISABLE:
+ rc = rmnet_map_do_flow_control(skb, rdinfo, 0);
+ break;
+
+ default:
+ rc = RMNET_MAP_COMMAND_UNSUPPORTED;
+ kfree_skb(skb);
+ break;
+ }
+ if (rc == RMNET_MAP_COMMAND_ACK)
+ rmnet_map_send_ack(skb, rc, rdinfo);
+ return RX_HANDLER_CONSUMED;
+}
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
new file mode 100644
index 0000000..a29c476
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
@@ -0,0 +1,105 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET Data MAP protocol
+ *
+ */
+
+#include <linux/netdevice.h>
+#include "rmnet_config.h"
+#include "rmnet_map.h"
+#include "rmnet_private.h"
+
+#define RMNET_MAP_DEAGGR_SPACING 64
+#define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2)
+
+/* Adds MAP header to front of skb->data
+ * Padding is calculated and set appropriately in MAP header. Mux ID is
+ * initialized to 0.
+ */
+struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
+ int hdrlen, int pad)
+{
+ struct rmnet_map_header *map_header;
+ u32 padding, map_datalen;
+ u8 *padbytes;
+
+ if (skb_headroom(skb) < sizeof(struct rmnet_map_header))
+ return NULL;
+
+ map_datalen = skb->len - hdrlen;
+ map_header = (struct rmnet_map_header *)
+ skb_push(skb, sizeof(struct rmnet_map_header));
+ memset(map_header, 0, sizeof(struct rmnet_map_header));
+
+ if (pad == RMNET_MAP_NO_PAD_BYTES) {
+ map_header->pkt_len = htons(map_datalen);
+ return map_header;
+ }
+
+ padding = ALIGN(map_datalen, 4) - map_datalen;
+
+ if (padding == 0)
+ goto done;
+
+ if (skb_tailroom(skb) < padding)
+ return NULL;
+
+ padbytes = (u8 *)skb_put(skb, padding);
+ memset(padbytes, 0, padding);
+
+done:
+ map_header->pkt_len = htons(map_datalen + padding);
+ map_header->pad_len = padding & 0x3F;
+
+ return map_header;
+}
+
+/* Deaggregates a single packet
+ * A whole new buffer is allocated for each portion of an aggregated frame.
+ * Caller should keep calling deaggregate() on the source skb until 0 is
+ * returned, indicating that there are no more packets to deaggregate. Caller
+ * is responsible for freeing the original skb.
+ */
+struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
+ struct rmnet_real_dev_info *rdinfo)
+{
+ struct rmnet_map_header *maph;
+ struct sk_buff *skbn;
+ u32 packet_len;
+
+ if (skb->len == 0)
+ return NULL;
+
+ maph = (struct rmnet_map_header *)skb->data;
+ packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header);
+
+ if (((int)skb->len - (int)packet_len) < 0)
+ return NULL;
+
+ skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC);
+ if (!skbn)
+ return NULL;
+
+ skbn->dev = skb->dev;
+ skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
+ skb_put(skbn, packet_len);
+ memcpy(skbn->data, skb->data, packet_len);
+ skb_pull(skb, packet_len);
+
+ /* Some hardware can send us empty frames. Catch them */
+ if (ntohs(maph->pkt_len) == 0) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ return skbn;
+}
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
new file mode 100644
index 0000000..ed820b5
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_private.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _RMNET_PRIVATE_H_
+#define _RMNET_PRIVATE_H_
+
+#define RMNET_MAX_VND 32
+#define RMNET_MAX_PACKET_SIZE 16384
+#define RMNET_DFLT_PACKET_SIZE 1500
+#define RMNET_NEEDED_HEADROOM 16
+#define RMNET_TX_QUEUE_LEN 1000
+
+/* Constants */
+#define RMNET_EGRESS_FORMAT__RESERVED__ BIT(0)
+#define RMNET_EGRESS_FORMAT_MAP BIT(1)
+#define RMNET_EGRESS_FORMAT_AGGREGATION BIT(2)
+#define RMNET_EGRESS_FORMAT_MUXING BIT(3)
+#define RMNET_EGRESS_FORMAT_MAP_CKSUMV3 BIT(4)
+#define RMNET_EGRESS_FORMAT_MAP_CKSUMV4 BIT(5)
+
+#define RMNET_INGRESS_FIX_ETHERNET BIT(0)
+#define RMNET_INGRESS_FORMAT_MAP BIT(1)
+#define RMNET_INGRESS_FORMAT_DEAGGREGATION BIT(2)
+#define RMNET_INGRESS_FORMAT_DEMUXING BIT(3)
+#define RMNET_INGRESS_FORMAT_MAP_COMMANDS BIT(4)
+#define RMNET_INGRESS_FORMAT_MAP_CKSUMV3 BIT(5)
+#define RMNET_INGRESS_FORMAT_MAP_CKSUMV4 BIT(6)
+
+/* Pass the frame up the stack with no modifications to skb->dev */
+#define RMNET_EPMODE_NONE (0)
+/* Replace skb->dev to a virtual rmnet device and pass up the stack */
+#define RMNET_EPMODE_VND (1)
+/* Pass the frame directly to another device with dev_queue_xmit() */
+#define RMNET_EPMODE_BRIDGE (2)
+
+#endif /* _RMNET_PRIVATE_H_ */
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
new file mode 100644
index 0000000..f3f1014
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * RMNET Data virtual network driver
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/pkt_sched.h>
+#include "rmnet_config.h"
+#include "rmnet_handlers.h"
+#include "rmnet_private.h"
+#include "rmnet_map.h"
+#include "rmnet_vnd.h"
+
+/* RX/TX Fixup */
+
+void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev)
+{
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+}
+
+void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev)
+{
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+}
+
+/* Network Device Operations */
+
+static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct rmnet_priv *priv;
+
+ priv = netdev_priv(dev);
+ if (priv->local_ep.egress_dev) {
+ rmnet_egress_handler(skb, &priv->local_ep);
+ } else {
+ dev->stats.tx_dropped++;
+ kfree_skb(skb);
+ }
+ return NETDEV_TX_OK;
+}
+
+static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu)
+{
+ if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE)
+ return -EINVAL;
+
+ rmnet_dev->mtu = new_mtu;
+ return 0;
+}
+
+static const struct net_device_ops rmnet_vnd_ops = {
+ .ndo_start_xmit = rmnet_vnd_start_xmit,
+ .ndo_change_mtu = rmnet_vnd_change_mtu,
+};
+
+/* Called by kernel whenever a new rmnet<n> device is created. Sets MTU,
+ * flags, ARP type, needed headroom, etc...
+ */
+void rmnet_vnd_setup(struct net_device *rmnet_dev)
+{
+ struct rmnet_priv *priv;
+
+ priv = netdev_priv(rmnet_dev);
+ netdev_dbg(rmnet_dev, "Setting up device %s\n", rmnet_dev->name);
+
+ rmnet_dev->netdev_ops = &rmnet_vnd_ops;
+ rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE;
+ rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM;
+ random_ether_addr(rmnet_dev->dev_addr);
+ rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN;
+
+ /* Raw IP mode */
+ rmnet_dev->header_ops = NULL; /* No header */
+ rmnet_dev->type = ARPHRD_RAWIP;
+ rmnet_dev->hard_header_len = 0;
+ rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+
+ rmnet_dev->needs_free_netdev = true;
+}
+
+/* Exposed API */
+
+int rmnet_vnd_newlink(struct net_device *real_dev, int id,
+ struct net_device *rmnet_dev)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ int rc;
+
+ rdinfo = rmnet_get_real_dev_info(real_dev);
+
+ if (rdinfo->rmnet_devices[id])
+ return -EINVAL;
+
+ rc = register_netdevice(rmnet_dev);
+ if (!rc) {
+ rdinfo->rmnet_devices[id] = rmnet_dev;
+ rmnet_dev->rtnl_link_ops = &rmnet_link_ops;
+ }
+ return rc;
+}
+
+int rmnet_vnd_remove_ref_dev(struct net_device *real_dev, int id)
+{
+ struct rmnet_real_dev_info *rdinfo;
+ struct rmnet_endpoint *ep;
+
+ rdinfo = rmnet_get_real_dev_info(real_dev);
+ if (id < 0 || id >= RMNET_MAX_VND || !rdinfo->rmnet_devices[id])
+ return -EINVAL;
+
+ ep = rmnet_vnd_get_endpoint(rdinfo->rmnet_devices[id]);
+ rdinfo->rmnet_devices[id] = NULL;
+ return 0;
+}
+
+/* Searches through list of known RmNet virtual devices. This function is O(n)
+ * and should not be used in the data path.
+ *
+ * To get the read id, subtract this result by 1.
+ */
+int rmnet_vnd_get_mux(struct net_device *real_dev,
+ struct net_device *rmnet_dev)
+{
+ /* This is not an efficient search, but, this will only be called in
+ * a configuration context, and the list is small.
+ */
+ struct rmnet_real_dev_info *rdinfo;
+ int i;
+
+ rdinfo = rmnet_get_real_dev_info(real_dev);
+
+ if (!rmnet_dev)
+ return 0;
+
+ for (i = 0; i < RMNET_MAX_VND; i++)
+ if (rmnet_dev == rdinfo->rmnet_devices[i])
+ return i + 1;
+
+ return 0;
+}
+
+/* Gets the logical endpoint configuration for a RmNet virtual network device
+ * node. Caller should confirm that devices is a RmNet VND before calling.
+ */
+struct rmnet_endpoint *rmnet_vnd_get_endpoint(struct net_device *rmnet_dev)
+{
+ struct rmnet_priv *priv;
+
+ if (!rmnet_dev)
+ return NULL;
+
+ priv = netdev_priv(rmnet_dev);
+
+ return &priv->local_ep;
+}
+
+int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
+{
+ netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
+ /* Although we expect similar number of enable/disable
+ * commands, optimize for the disable. That is more
+ * latency sensitive than enable
+ */
+ if (unlikely(enable))
+ netif_wake_queue(rmnet_dev);
+ else
+ netif_stop_queue(rmnet_dev);
+
+ return 0;
+}
+
+struct net_device *rmnet_vnd_get_by_id(struct net_device *real_dev, int id)
+{
+ struct rmnet_real_dev_info *rdinfo;
+
+ rdinfo = rmnet_get_real_dev_info(real_dev);
+
+ if (id < 0 || id >= RMNET_MAX_VND)
+ return NULL;
+
+ return rdinfo->rmnet_devices[id];
+}
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
new file mode 100644
index 0000000..a4cdc41
--- /dev/null
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * RMNET Data Virtual Network Device APIs
+ *
+ */
+
+#ifndef _RMNET_VND_H_
+#define _RMNET_VND_H_
+
+int rmnet_vnd_do_flow_control(struct net_device *dev, int enable);
+struct rmnet_endpoint *rmnet_vnd_get_endpoint(struct net_device *dev);
+int rmnet_vnd_remove_ref_dev(struct net_device *real_dev, int id);
+void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev);
+void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev);
+int rmnet_vnd_get_mux(struct net_device *real_dev,
+ struct net_device *rmnet_dev);
+struct net_device *rmnet_vnd_get_by_id(struct net_device *real_dev, int id);
+void rmnet_vnd_setup(struct net_device *dev);
+int rmnet_vnd_newlink(struct net_device *real_dev, int id,
+ struct net_device *new_device);
+#endif /* _RMNET_VND_H_ */
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net-next 0/4] net: mvpp2: fix the mac address retrieval logic
From: David Miller @ 2017-08-25 4:46 UTC (permalink / raw)
To: antoine.tenart
Cc: thomas.petazzoni, andrew, gregory.clement, nadavh, linux,
linux-kernel, mw, stefanc, netdev
In-Reply-To: <20170824094658.1296-1-antoine.tenart@free-electrons.com>
From: Antoine Tenart <antoine.tenart@free-electrons.com>
Date: Thu, 24 Aug 2017 11:46:54 +0200
> The MAC address retrieval logic was broken and when using the PPv2
> driver on PPv2.2 engines I ended up using the same mac address on all
> ports. This series of patches fixes this, and also tackle a possible bug
> when defining the mac address in the device tree.
>
> To fix this in a nice way I ended up using a dedicated function to
> handle the mac retrieval logic. This can be hard to backport into stable
> kernels. This is why I also made a quick fix which is easy to backport
> (patch 1/14), to tackle down the PPv2.2 mac retrieval bug. Let me know
> if this approach is the proper way to handle this or if I should do
> something else.
This patch series doesn't apply to any of my trees, that is the first
thing.
Secondly, this is a bug fix, and the bug exists in the 'net' tree.
Therefore this patch series should target the 'net' tree.
Please always target legitimate bug fixes at the 'net' tree, rather
than 'net-next'.
Thank you.
^ permalink raw reply
* Re: [PATCH net-next] hinic: uninitialized variable in hinic_api_cmd_init()
From: David Miller @ 2017-08-25 4:48 UTC (permalink / raw)
To: dan.carpenter; +Cc: aviad.krawczyk, netdev, kernel-janitors
In-Reply-To: <20170824104739.gw422ufydwmiu4gi@mwanda>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Thu, 24 Aug 2017 13:47:39 +0300
> We never set the error code in this function.
>
> Fixes: eabf0fad81d5 ("net-next/hinic: Initialize api cmd resources")
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied, thanks.
^ permalink raw reply
* Re: [pull request][net-next 0/8] Mellanox, mlx5updates 2017-08-24
From: David Miller @ 2017-08-25 4:52 UTC (permalink / raw)
To: saeedm; +Cc: netdev, leonro
In-Reply-To: <20170824132152.29538-1-saeedm@mellanox.com>
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Thu, 24 Aug 2017 16:21:44 +0300
> The following changes provide updates to mlx5 core driver.
>
> For more details please see tag log message below.
> Please pull and let me know if there's any problem.
Pulled, thanks Saeed.
^ permalink raw reply
* Re: [PATCH net v1 0/3] tipc: buffer reassignment fixes
From: David Miller @ 2017-08-25 4:54 UTC (permalink / raw)
To: parthasarathy.bhuvaragan; +Cc: jon.maloy, netdev, tipc-discussion, ying.xue
In-Reply-To: <1503585084-14079-1-git-send-email-parthasarathy.bhuvaragan@ericsson.com>
From: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Date: Thu, 24 Aug 2017 16:31:21 +0200
> This series contains fixes for buffer reassignments and a context
> imbalance.
Series applied, thanks.
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply
* Re: [PATCH net-next] hv_netvsc: Fix rndis_filter_close error during netvsc_remove
From: David Miller @ 2017-08-25 4:58 UTC (permalink / raw)
To: haiyangz, haiyangz; +Cc: netdev, kys, olaf, vkuznets, linux-kernel
In-Reply-To: <20170824185002.10213-1-haiyangz@exchange.microsoft.com>
From: Haiyang Zhang <haiyangz@exchange.microsoft.com>
Date: Thu, 24 Aug 2017 11:50:02 -0700
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> We now remove rndis filter before unregister_netdev(), which calls
> device close. It involves closing rndis filter already removed.
>
> This patch fixes this error.
>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Applied.
^ permalink raw reply
* Re: [PATCH] strparser: initialize all callbacks
From: David Miller @ 2017-08-25 4:58 UTC (permalink / raw)
To: ebiggers3; +Cc: netdev, linux-kernel, ebiggers, dvyukov, tom
In-Reply-To: <20170824213851.57601-1-ebiggers3@gmail.com>
From: Eric Biggers <ebiggers3@gmail.com>
Date: Thu, 24 Aug 2017 14:38:51 -0700
> From: Eric Biggers <ebiggers@google.com>
>
> commit bbb03029a899 ("strparser: Generalize strparser") added more
> function pointers to 'struct strp_callbacks'; however, kcm_attach() was
> not updated to initialize them. This could cause the ->lock() and/or
> ->unlock() function pointers to be set to garbage values, causing a
> crash in strp_work().
>
> Fix the bug by moving the callback structs into static memory, so
> unspecified members are zeroed. Also constify them while we're at it.
>
> This bug was found by syzkaller, which encountered the following splat:
...
> Fixes: bbb03029a899 ("strparser: Generalize strparser")
> Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is only in net-next, so that is where I am applying
this patch.
Thanks.
^ permalink raw reply
* Re: [PATCH] netvsc: fix deadlock betwen link status and removal
From: David Miller @ 2017-08-25 4:59 UTC (permalink / raw)
To: stephen; +Cc: kys, haiyangz, sthemmin, netdev
In-Reply-To: <20170824234916.11490-1-sthemmin@microsoft.com>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Thu, 24 Aug 2017 16:49:16 -0700
> There is a deadlock possible when canceling the link status
> delayed work queue. The removal process is run with RTNL held,
> and the link status callback is acquring RTNL.
>
> Resolve the issue by using trylock and rescheduling.
> If cancel is in process, that block it from happening.
>
> Fixes: 122a5f6410f4 ("staging: hv: use delayed_work for netvsc_send_garp()")
> Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net] net: xfrm: don't double-hold dst when sk_policy in use.
From: Steffen Klassert @ 2017-08-25 5:16 UTC (permalink / raw)
To: Lorenzo Colitti; +Cc: netdev, weiwan, davem, misterikkit
In-Reply-To: <20170823081439.52796-1-lorenzo@google.com>
On Wed, Aug 23, 2017 at 05:14:39PM +0900, Lorenzo Colitti wrote:
> While removing dst_entry garbage collection, commit 52df157f17e5
> ("xfrm: take refcnt of dst when creating struct xfrm_dst bundle")
> changed xfrm_resolve_and_create_bundle so it returns an xdst with
> a refcount of 1 instead of 0.
>
> However, it did not delete the dst_hold performed by xfrm_lookup
> when a per-socket policy is in use. This means that when a
> socket policy is in use, dst entries returned by xfrm_lookup have
> a refcount of 2, and are not freed when no longer in use.
>
> Cc: Wei Wang <weiwan@google.com>
> Fixes: 52df157f17 ("xfrm: take refcnt of dst when creating struct xfrm_dst bundle")
> Tested: https://android-review.googlesource.com/417481
> Tested: https://android-review.googlesource.com/418659
> Tested: https://android-review.googlesource.com/424463
> Tested: https://android-review.googlesource.com/452776 passes on net-next
> Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Patch applied, thanks a lot!
^ permalink raw reply
* Re: nf_nat_pptp 4.12.3 kernel lockup/reboot
From: Florian Westphal @ 2017-08-25 5:21 UTC (permalink / raw)
To: Denys Fedoryshchenko; +Cc: Florian Westphal, Linux Kernel Network Developers
In-Reply-To: <f31c9ddfc1d4e02ff7fc16d3a0955841@nuclearcat.com>
Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
> >>> I am trying to upgrade kernel 4.11.8 to 4.12.3 (it is a nat/router, handling
> >>> approx 2gbps of pppoe users traffic) and noticed that after while server
> >>> rebooting(i have set reboot on panic and etc).
> >>> I can't run serial console, and in pstore / netconsole there is nothing.
> >>> Best i got is some very short message about softlockup in ipmi, but as
> >>> storage very limited there - it is near useless.
> >>>
> >>> By preliminary testing (can't do it much, as it's production) - it seems
> >>> following lines causing issue, they worked in 4.11.8 and no more in 4.12.3.
> >>
> >>Wild guess here, does this help?
> >>
> >>diff --git a/net/netfilter/nf_conntrack_helper.c
> >>b/net/netfilter/nf_conntrack_helper.c
> >>--- a/net/netfilter/nf_conntrack_helper.c
> >>+++ b/net/netfilter/nf_conntrack_helper.c
> >>@@ -266,6 +266,8 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct,
> >>struct nf_conn *tmpl,
> >> help = nf_ct_helper_ext_add(ct, helper, flags);
> >> if (help == NULL)
> >> return -ENOMEM;
> >>+ if (!nf_ct_ext_add(ct, NF_CT_EXT_NAT, flags));
> >
> >sigh, stupid typo, should be no ';' at the end above.
> Sorry, is there any plans to push this to 4.12 stable queue?
No, sorry, this patch adds the extension for all connections
that use a helper, but the nat extension is only used/required by pptp
helper (and masquerade).
Thing is that this patch should not be needed, I will have
to review pptp again, maybe i missed a case where the extension is not
added.
Do you happen to have an oops backtrace?
That might speed this up a bit.
^ permalink raw reply
* [PATCH] net: sxgbe: check memory allocation failure
From: Christophe JAILLET @ 2017-08-25 5:35 UTC (permalink / raw)
To: bh74.an, ks.giri, vipul.pandya
Cc: netdev, linux-kernel, kernel-janitors, Christophe JAILLET
Check memory allocation failure and return -ENOMEM in such a case, as
already done few lines below for another memory allocation.
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
---
drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
index 73427e29df2a..fbd00cb0cb7d 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
@@ -47,6 +47,8 @@ static int sxgbe_probe_config_dt(struct platform_device *pdev,
plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
sizeof(*plat->mdio_bus_data),
GFP_KERNEL);
+ if (!plat->mdio_bus_data)
+ return -ENOMEM;
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
if (!dma_cfg)
--
2.11.0
^ permalink raw reply related
* RE: [PATCH v3 0/7] Add RSS to DPAA 1.x Ethernet driver
From: Madalin-cristian Bucur @ 2017-08-25 5:50 UTC (permalink / raw)
To: David Miller
Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170824.114741.1529064786944246878.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Subject: Re: [PATCH v3 0/7] Add RSS to DPAA 1.x Ethernet driver
>
> From: David Miller <davem@davemloft.net>
> Date: Thu, 24 Aug 2017 09:42:20 -0700 (PDT)
>
> > From: Madalin Bucur <madalin.bucur@nxp.com>
> > Date: Thu, 24 Aug 2017 10:28:21 +0300
> >
> >> This patch set introduces Receive Side Scaling for the DPAA Ethernet
> >> driver. Documentation is updated with details related to the new
> >> feature and limitations that apply.
> >> Added also a small fix.
> >>
> >> v2: removed a C++ style comment
> >> v3: move struct fman to header file to avoid exporting a function
> >
> > Series applied, thanks.
>
> Actually I'm reverting, this doesn't even compile.
Hi,
Sorry for this blunder, I've only tested on PPC, where it works.
Will come back with a proper patch set.
Madalin
^ permalink raw reply
* [PATCH net-next v5] net: stmmac: Delete dead code for MDIO registration
From: Romain Perier @ 2017-08-25 6:49 UTC (permalink / raw)
To: Giuseppe Cavallaro, Alexandre Torgue, Andrew Lunn,
Florian Fainelli
Cc: David S. Miller, netdev, linux-kernel, Romain Perier
This code is no longer used, the logging function was changed by commit
fbca164776e4 ("net: stmmac: Use the right logging function in stmmac_mdio_register").
It was previously showing information about the type of the IRQ, if it's
polled, ignored or a normal interrupt. As we don't want information loss,
I have moved this code to phy_attached_print().
Fixes: fbca164776e4 ("net: stmmac: Use the right logging function in stmmac_mdio_register")
Signed-off-by: Romain Perier <romain.perier@collabora.com>
---
Hello,
This is the continuity of "[PATCH v2 0/2] net: stmmac: phy logging fixes",
see https://lkml.org/lkml/2017/8/21/288
Changes in v5:
- Don't truncater commit fbca164776e4 in the message of *this* commit
- Fixed typo
Changes in v4:
- Don't truncate the commit subject for "Fixes"
- Fixed invalid sizeof() used with snprintf
- Added "net-next" prefix to the title of the commit
Changes in v3:
- Removed patch 2/2: "net: phy: Don't use drv when it is NULL in phy_attached_print",
fixed upstream by fcd03e362b1c
("net: phy: Deal with unbound PHY driver in phy_attached_print()")
- Moved this code to phy_attached_print(), so we have more informations
about the IRQ (poll, ignore or normal irq) and no information are loss.
- Re-worded commit message
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 16 ----------------
drivers/net/phy/phy_device.c | 21 ++++++++++++++++++---
2 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 72ec711fcba2..f5f37bfa1d58 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -248,9 +248,6 @@ int stmmac_mdio_register(struct net_device *ndev)
found = 0;
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
- int act = 0;
- char irq_num[4];
- char *irq_str;
if (!phydev)
continue;
@@ -273,19 +270,6 @@ int stmmac_mdio_register(struct net_device *ndev)
if (priv->plat->phy_addr == -1)
priv->plat->phy_addr = addr;
- act = (priv->plat->phy_addr == addr);
- switch (phydev->irq) {
- case PHY_POLL:
- irq_str = "POLL";
- break;
- case PHY_IGNORE_INTERRUPT:
- irq_str = "IGNORE";
- break;
- default:
- sprintf(irq_num, "%d", phydev->irq);
- irq_str = irq_num;
- break;
- }
phy_attached_info(phydev);
found = 1;
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 2f742ae5b92e..4f67cafda2ef 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -861,21 +861,36 @@ void phy_attached_info(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_attached_info);
-#define ATTACHED_FMT "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)"
+#define ATTACHED_FMT "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%s)"
void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
{
const char *drv_name = phydev->drv ? phydev->drv->name : "unbound";
+ char *irq_str;
+ char irq_num[4];
+
+ switch(phydev->irq) {
+ case PHY_POLL:
+ irq_str = "POLL";
+ break;
+ case PHY_IGNORE_INTERRUPT:
+ irq_str = "IGNORE";
+ break;
+ default:
+ snprintf(irq_num, sizeof(irq_num), "%d", phydev->irq);
+ irq_str = irq_num;
+ break;
+ }
if (!fmt) {
dev_info(&phydev->mdio.dev, ATTACHED_FMT "\n",
drv_name, phydev_name(phydev),
- phydev->irq);
+ irq_str);
} else {
va_list ap;
dev_info(&phydev->mdio.dev, ATTACHED_FMT,
drv_name, phydev_name(phydev),
- phydev->irq);
+ irq_str);
va_start(ap, fmt);
vprintk(fmt, ap);
--
2.11.0
^ permalink raw reply related
* [PATCH net] ipv6: Fix may be used uninitialized warning in rt6_check
From: Steffen Klassert @ 2017-08-25 7:05 UTC (permalink / raw)
To: David S. Miller; +Cc: Wei Wang, Eric Dumazet, Martin KaFai Lau, netdev
rt_cookie might be used uninitialized, fix this by
initializing it.
Fixes: c5cff8561d2d ("ipv6: add rcu grace period before freeing fib6_node")
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv6/route.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a9d3564..48c8c92 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1289,7 +1289,7 @@ static void rt6_dst_from_metrics_check(struct rt6_info *rt)
static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
{
- u32 rt_cookie;
+ u32 rt_cookie = 0;
if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
return NULL;
--
2.7.4
^ permalink raw reply related
* Re: nf_nat_pptp 4.12.3 kernel lockup/reboot
From: Denys Fedoryshchenko @ 2017-08-25 7:15 UTC (permalink / raw)
To: Florian Westphal; +Cc: Linux Kernel Network Developers
In-Reply-To: <20170825052137.GF15739@breakpoint.cc>
On 2017-08-25 08:21, Florian Westphal wrote:
> Denys Fedoryshchenko <nuclearcat@nuclearcat.com> wrote:
>> >>> I am trying to upgrade kernel 4.11.8 to 4.12.3 (it is a nat/router, handling
>> >>> approx 2gbps of pppoe users traffic) and noticed that after while server
>> >>> rebooting(i have set reboot on panic and etc).
>> >>> I can't run serial console, and in pstore / netconsole there is nothing.
>> >>> Best i got is some very short message about softlockup in ipmi, but as
>> >>> storage very limited there - it is near useless.
>> >>>
>> >>> By preliminary testing (can't do it much, as it's production) - it seems
>> >>> following lines causing issue, they worked in 4.11.8 and no more in 4.12.3.
>> >>
>> >>Wild guess here, does this help?
>> >>
>> >>diff --git a/net/netfilter/nf_conntrack_helper.c
>> >>b/net/netfilter/nf_conntrack_helper.c
>> >>--- a/net/netfilter/nf_conntrack_helper.c
>> >>+++ b/net/netfilter/nf_conntrack_helper.c
>> >>@@ -266,6 +266,8 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct,
>> >>struct nf_conn *tmpl,
>> >> help = nf_ct_helper_ext_add(ct, helper, flags);
>> >> if (help == NULL)
>> >> return -ENOMEM;
>> >>+ if (!nf_ct_ext_add(ct, NF_CT_EXT_NAT, flags));
>> >
>> >sigh, stupid typo, should be no ';' at the end above.
>> Sorry, is there any plans to push this to 4.12 stable queue?
>
> No, sorry, this patch adds the extension for all connections
> that use a helper, but the nat extension is only used/required by pptp
> helper (and masquerade).
>
> Thing is that this patch should not be needed, I will have
> to review pptp again, maybe i missed a case where the extension is not
> added.
>
> Do you happen to have an oops backtrace?
>
> That might speed this up a bit.
There is nothing in netconsole, and also nothing ERST pstore, i found
reason just by guessing.
Its totally headless also (no screen, no serial console).
I can try to attach USB serial for serial console, but not sure it will
help.
If there is any other way to catch - i can try it, but as it's
production server, so i can't "crash it" more than once per day.
^ permalink raw reply
* Re: [net-next:master 1328/1341] drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c:77:3: error: 'devlink_dpipe_header_ethernet' undeclared here (not in a function)
From: Jiri Pirko @ 2017-08-25 7:28 UTC (permalink / raw)
To: David Miller; +Cc: fengguang.wu, arkadis, kbuild-all, netdev, jiri
In-Reply-To: <20170824.181150.1024909235376525254.davem@davemloft.net>
Fri, Aug 25, 2017 at 03:11:50AM CEST, davem@davemloft.net wrote:
>From: kbuild test robot <fengguang.wu@intel.com>
>Date: Fri, 25 Aug 2017 08:16:01 +0800
>
>> All error/warnings (new ones prefixed by >>):
>>
>>>> drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c:77:3: error: 'devlink_dpipe_header_ethernet' undeclared here (not in a function)
>> &devlink_dpipe_header_ethernet,
>> ^
>>>> drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c:78:3: error: 'devlink_dpipe_header_ipv4' undeclared here (not in a function)
>> &devlink_dpipe_header_ipv4,
>> ^
>> drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c: In function 'mlxsw_sp_dpipe_erif_table_init':
>> drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c:305:9: error: too few arguments to function 'devlink_dpipe_table_register'
>> return devlink_dpipe_table_register(devlink,
>
>Jiri and co., I think you'll need some ifdef'ery to deal with this
>properly.
Will fix this. Thanks.
^ permalink raw reply
* [PATCH net-next RESEND] sched: sfq: drop packets after root qdisc lock is released
From: gfree.wind @ 2017-08-25 7:43 UTC (permalink / raw)
To: jhs, xiyou.wangcong, jiri, davem, edumazet, netdev; +Cc: Gao Feng
From: Gao Feng <gfree.wind@vip.163.com>
The commit 520ac30f4551 ("net_sched: drop packets after root qdisc lock
is released) made a big change of tc for performance. But there are
some points which are not changed in SFQ enqueue operation.
1. Fail to find the SFQ hash slot;
2. When the queue is full;
Now use qdisc_drop instead free skb directly.
Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
---
net/sched/sch_sfq.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 82469ef..8841f4d 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -292,7 +292,7 @@ static inline void slot_queue_add(struct sfq_slot *slot, struct sk_buff *skb)
slot->skblist_prev = skb;
}
-static unsigned int sfq_drop(struct Qdisc *sch)
+static unsigned int sfq_drop(struct Qdisc *sch, struct sk_buff **to_free)
{
struct sfq_sched_data *q = qdisc_priv(sch);
sfq_index x, d = q->cur_depth;
@@ -310,9 +310,13 @@ static unsigned int sfq_drop(struct Qdisc *sch)
slot->backlog -= len;
sfq_dec(q, x);
sch->q.qlen--;
- qdisc_qstats_drop(sch);
qdisc_qstats_backlog_dec(sch, skb);
- kfree_skb(skb);
+ if (likely(to_free)) {
+ qdisc_drop(skb, sch, to_free);
+ } else {
+ qdisc_qstats_drop(sch);
+ kfree_skb(skb);
+ }
return len;
}
@@ -360,7 +364,7 @@ static int sfq_headdrop(const struct sfq_sched_data *q)
if (hash == 0) {
if (ret & __NET_XMIT_BYPASS)
qdisc_qstats_drop(sch);
- kfree_skb(skb);
+ __qdisc_drop(skb, to_free);
return ret;
}
hash--;
@@ -465,7 +469,7 @@ static int sfq_headdrop(const struct sfq_sched_data *q)
return NET_XMIT_SUCCESS;
qlen = slot->qlen;
- dropped = sfq_drop(sch);
+ dropped = sfq_drop(sch, to_free);
/* Return Congestion Notification only if we dropped a packet
* from this flow.
*/
@@ -675,7 +679,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
qlen = sch->q.qlen;
while (sch->q.qlen > q->limit)
- dropped += sfq_drop(sch);
+ dropped += sfq_drop(sch, NULL);
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
del_timer(&q->perturb_timer);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net] ipv6: Fix may be used uninitialized warning in rt6_check
From: Steffen Klassert @ 2017-08-25 7:52 UTC (permalink / raw)
To: David S. Miller; +Cc: Wei Wang, Eric Dumazet, Martin KaFai Lau, netdev
In-Reply-To: <20170825070542.GV31224@secunet.com>
On Fri, Aug 25, 2017 at 09:05:42AM +0200, Steffen Klassert wrote:
> rt_cookie might be used uninitialized, fix this by
> initializing it.
>
> Fixes: c5cff8561d2d ("ipv6: add rcu grace period before freeing fib6_node")
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
> net/ipv6/route.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index a9d3564..48c8c92 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1289,7 +1289,7 @@ static void rt6_dst_from_metrics_check(struct rt6_info *rt)
>
> static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
> {
> - u32 rt_cookie;
> + u32 rt_cookie = 0;
>
> if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie)
> return NULL;
The compiler warning seems to be a false positive, as
rt_cookie != cookie is only checked if rt6_get_cookie_safe
returns true in which case rt_cookie is initialized.
Please disregard this patch.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox