From: Dennis Dalessandro <dennis.dalessandro-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
To: dledford-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Niranjana Vishwanathapura
<niranjana.vishwanathapura-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Scott Franco <safranco-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Sudeep Dutt <sudeep.dutt-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: [PATCH for-next 1/2] IB/opa_vnic: Add debugfs support to OPA VNIC
Date: Tue, 26 Sep 2017 07:08:44 -0700 [thread overview]
Message-ID: <20170926140842.18110.55132.stgit@scvm10.sc.intel.com> (raw)
In-Reply-To: <20170926140714.18110.74689.stgit-9QXIwq+3FY+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
From: Niranjana Vishwanathapura <niranjana.vishwanathapura-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Add debugfs support to view/modify the VESW port configuration information
including MAC to DLID translation table.
Reviewed-by: Sudeep Dutt <sudeep.dutt-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Scott Franco <safranco-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/infiniband/ulp/opa_vnic/Makefile | 1
drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.c | 620 ++++++++++++++++++++
drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.h | 66 ++
.../infiniband/ulp/opa_vnic/opa_vnic_internal.h | 6
drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c | 11
5 files changed, 700 insertions(+), 4 deletions(-)
create mode 100644 drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.c
create mode 100644 drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.h
diff --git a/drivers/infiniband/ulp/opa_vnic/Makefile b/drivers/infiniband/ulp/opa_vnic/Makefile
index 8061b28..8d1929c 100644
--- a/drivers/infiniband/ulp/opa_vnic/Makefile
+++ b/drivers/infiniband/ulp/opa_vnic/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_INFINIBAND_OPA_VNIC) += opa_vnic.o
opa_vnic-y := opa_vnic_netdev.o opa_vnic_encap.o opa_vnic_ethtool.o \
opa_vnic_vema.o opa_vnic_vema_iface.o
+opa_vnic-$(CONFIG_DEBUG_FS) += opa_vnic_debugfs.o
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.c
new file mode 100644
index 0000000..f5565bd
--- /dev/null
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright(c) 2017 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * This file contains HFI VNIC debug interface
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/list_sort.h>
+#include <linux/module.h>
+
+#include "opa_vnic_internal.h"
+#include "opa_vnic_debugfs.h"
+
+/* MAC table string size; 64K is enough for the whole table */
+#define OPA_VNIC_MACTBL_STR_SIZE SZ_64K
+
+/* EEPH string size */
+#define OPA_VNIC_EEPH_STR_SIZE SZ_1K
+
+/* Vnic stats string size */
+#define OPA_VNIC_STATS_STR_SIZE SZ_1K
+
+enum {
+ OPA_VNIC_DBG_FABRIC_ID,
+ OPA_VNIC_DBG_VESW_ID,
+ OPA_VNIC_DBG_PKEY,
+ OPA_VNIC_DBG_ETH_LINK_STATUS,
+ OPA_VNIC_DBG_BASE_MAC_ADDR,
+ OPA_VNIC_DBG_CFG_STATE,
+ OPA_VNIC_DBG_OPER_STATE,
+ OPA_VNIC_DBG_ENCAP_SLID,
+ OPA_VNIC_DBG_DEF_PORT_MASK,
+ OPA_VNIC_DBG_UC_DLID,
+ OPA_VNIC_DBG_MC_DLID,
+ OPA_VNIC_DBG_SC_UC,
+ OPA_VNIC_DBG_SC_MC,
+ OPA_VNIC_DBG_PCP_SC_UC,
+ OPA_VNIC_DBG_PCP_SC_MC,
+ OPA_VNIC_DBG_VL_UC,
+ OPA_VNIC_DBG_VL_MC,
+ OPA_VNIC_DBG_PCP_VL_UC,
+ OPA_VNIC_DBG_PCP_VL_MC,
+ OPA_VNIC_DBG_ETH_MTU,
+ OPA_VNIC_DBG_ENCAP_RC,
+ OPA_VNIC_DBG_RESET,
+ OPA_VNIC_DBG_MACTBL_DIGEST,
+ OPA_VNIC_DBG_NUM_ATTR,
+};
+
+static struct dentry *opa_vnic_dbg_root;
+
+#define DEBUGFS_SEQ_FILE_OPS(name) \
+static const struct seq_operations _##name##_seq_ops = { \
+ .start = _##name##_seq_start, \
+ .next = _##name##_seq_next, \
+ .stop = _##name##_seq_stop, \
+ .show = _##name##_seq_show \
+}
+
+#define DEBUGFS_SEQ_FILE_OPEN(name) \
+static int _##name##_open(struct inode *inode, struct file *file) \
+{ \
+ struct seq_file *seq; \
+ int ret; \
+ ret = seq_open(file, &_##name##_seq_ops); \
+ if (ret) \
+ return ret; \
+ seq = file->private_data; \
+ seq->private = inode->i_private; \
+ return 0; \
+}
+
+#define DEBUGFS_FILE_OPS(name) \
+static const struct file_operations _##name##_file_ops = { \
+ .owner = THIS_MODULE, \
+ .open = _##name##_open, \
+ .write = _##name##_write, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = seq_release \
+}
+
+#define DEBUGFS_FILE_CREATE(name, parent, data, ops, mode) \
+do { \
+ struct dentry *ent; \
+ ent = debugfs_create_file(name, mode, parent, data, ops); \
+ if (!ent) \
+ pr_warn("create of %s failed\n", name); \
+} while (0)
+
+#define DEBUGFS_SEQ_FILE_CREATE(name, parent, data) \
+ DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, 0644)
+
+static void *_vport_state_seq_start(struct seq_file *s, loff_t *pos)
+__acquires(RCU)
+{
+ rcu_read_lock();
+ if (*pos >= OPA_VNIC_DBG_NUM_ATTR)
+ return NULL;
+ return pos;
+}
+
+static void *_vport_state_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos >= OPA_VNIC_DBG_NUM_ATTR)
+ return NULL;
+ return pos;
+}
+
+static void _vport_state_seq_stop(struct seq_file *s, void *v)
+__releases(RCU)
+{
+ rcu_read_unlock();
+}
+
+static int _vport_state_seq_show(struct seq_file *s, void *v)
+{
+ struct opa_vnic_adapter *adapter =
+ (struct opa_vnic_adapter *)s->private;
+ struct __opa_veswport_info *info = &adapter->info;
+ loff_t *spos = v;
+ int stat;
+ char *str;
+ u8 i, *val;
+
+ if (v == SEQ_START_TOKEN)
+ return 0;
+
+ stat = *spos;
+ switch (stat) {
+ case OPA_VNIC_DBG_FABRIC_ID:
+ seq_printf(s, "fabric_id (fabric id): 0x%x\n",
+ info->vesw.fabric_id);
+ break;
+ case OPA_VNIC_DBG_VESW_ID:
+ seq_printf(s, "vesw_id (virtual eth switch id): 0x%x\n",
+ info->vesw.vesw_id);
+ break;
+ case OPA_VNIC_DBG_PKEY:
+ seq_printf(s, "pkey (partition key): 0x%x\n",
+ info->vesw.pkey);
+ break;
+ case OPA_VNIC_DBG_ETH_LINK_STATUS:
+ seq_printf(s, "eth_link_status (0=unknown 1=up 2=down): %u\n",
+ info->vport.eth_link_status);
+ break;
+ case OPA_VNIC_DBG_BASE_MAC_ADDR:
+ val = info->vport.base_mac_addr;
+ str = "%s: %02x:%02x:%02x:%02x:%02x:%02x\n";
+ seq_printf(s, str, "base_mac_addr (mac address)",
+ val[0], val[1], val[2], val[3], val[4], val[5]);
+ break;
+ case OPA_VNIC_DBG_CFG_STATE:
+ seq_printf(s, "config_state (0=nop 1=drop 2=init 3=fwd): %u\n",
+ info->vport.config_state);
+ break;
+ case OPA_VNIC_DBG_OPER_STATE:
+ seq_printf(s, "oper_state (0=nop 1=drop 2=init 3=fwd): %u\n",
+ info->vport.oper_state);
+ break;
+ case OPA_VNIC_DBG_ENCAP_SLID:
+ seq_printf(s, "encap_slid (source lid): 0x%x\n",
+ info->vport.encap_slid);
+ break;
+ case OPA_VNIC_DBG_DEF_PORT_MASK:
+ seq_printf(s, "def_port_mask (default port mask): 0x%04x\n",
+ info->vesw.def_port_mask);
+ break;
+ case OPA_VNIC_DBG_UC_DLID:
+ seq_puts(s, "u_ucast_dlid (unknown ucast dlid):");
+ for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++)
+ seq_printf(s, " 0x%x", info->vesw.u_ucast_dlid[i]);
+ seq_puts(s, "\n");
+ break;
+ case OPA_VNIC_DBG_MC_DLID:
+ seq_printf(s, "u_mcast_dlid (unknown mcast dlid): 0x%x\n",
+ info->vesw.u_mcast_dlid);
+ break;
+ case OPA_VNIC_DBG_ETH_MTU:
+ seq_printf(s, "eth_mtu (ethernet mtu): %u\n",
+ info->vesw.eth_mtu);
+ break;
+ case OPA_VNIC_DBG_SC_UC:
+ seq_printf(s, "non_vlan_sc_uc (non-vlan ucast sc): 0x%x\n",
+ info->vport.non_vlan_sc_uc);
+ break;
+ case OPA_VNIC_DBG_SC_MC:
+ seq_printf(s, "non_vlan_sc_mc (non-vlan mcast sc): 0x%x\n",
+ info->vport.non_vlan_sc_mc);
+ break;
+ case OPA_VNIC_DBG_PCP_SC_UC:
+ val = info->vport.pcp_to_sc_uc;
+ str = "%s: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n";
+ seq_printf(s, str, "pcp_to_sc_uc (vlan ucast sc)",
+ val[0], val[1], val[2], val[3],
+ val[4], val[5], val[6], val[7]);
+ break;
+ case OPA_VNIC_DBG_PCP_SC_MC:
+ val = info->vport.pcp_to_sc_mc;
+ str = "%s: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n";
+ seq_printf(s, str, "pcp_to_sc_mc (vlan mcast sc)",
+ val[0], val[1], val[2], val[3],
+ val[4], val[5], val[6], val[7]);
+ break;
+ case OPA_VNIC_DBG_VL_UC:
+ seq_printf(s, "non_vlan_vl_uc (non-vlan ucast vl): 0x%x\n",
+ info->vport.non_vlan_vl_uc);
+ break;
+ case OPA_VNIC_DBG_VL_MC:
+ seq_printf(s, "non_vlan_vl_mc (non-vlan mcast vl): 0x%x\n",
+ info->vport.non_vlan_vl_mc);
+ break;
+ case OPA_VNIC_DBG_PCP_VL_UC:
+ val = info->vport.pcp_to_vl_uc;
+ str = "%s: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n";
+ seq_printf(s, str, "pcp_to_vl_uc (vlan ucast vl)",
+ val[0], val[1], val[2], val[3],
+ val[4], val[5], val[6], val[7]);
+ break;
+ case OPA_VNIC_DBG_PCP_VL_MC:
+ val = info->vport.pcp_to_vl_mc;
+ str = "%s: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n";
+ seq_printf(s, str, "pcp_to_vl_mc (vlan mcast vl)",
+ val[0], val[1], val[2], val[3],
+ val[4], val[5], val[6], val[7]);
+ break;
+ case OPA_VNIC_DBG_ENCAP_RC:
+ seq_printf(s, "encap_rc (routing control): 0x%08x\n",
+ info->vesw.rc);
+ break;
+ case OPA_VNIC_DBG_MACTBL_DIGEST:
+ seq_printf(s, "MAC Table Digest: %u\n",
+ info->vport.mac_tbl_digest);
+ break;
+ default:
+ return SEQ_SKIP;
+ }
+
+ return 0;
+}
+
+static ssize_t _vport_state_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *s = (struct seq_file *)file->private_data;
+ struct opa_vnic_adapter *adapter =
+ (struct opa_vnic_adapter *)s->private;
+ struct __opa_veswport_info *info = &adapter->info;
+ char debug_buf[256];
+ ssize_t len;
+ u32 value;
+ int cnt;
+
+ if (*ppos != 0)
+ return 0;
+
+ if (count >= sizeof(debug_buf))
+ return -ENOSPC;
+
+ len = simple_write_to_buffer(debug_buf, sizeof(debug_buf) - 1,
+ ppos, buf, count);
+ if (len < 0)
+ return len;
+
+ debug_buf[len] = '\0';
+ if (strncmp(debug_buf, "fabric_id", 9) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[9]), 0, &value);
+ if (!cnt)
+ info->vesw.fabric_id = value;
+ } else if (strncmp(debug_buf, "vesw_id", 7) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[7]), 0, &value);
+ if (!cnt)
+ info->vesw.vesw_id = value;
+ } else if (strncmp(debug_buf, "pkey", 4) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[4]), 0, &value);
+ if (!cnt)
+ info->vesw.pkey = value;
+ } else if (strncmp(debug_buf, "base_mac_addr", 13) == 0) {
+ u8 i, mac[6];
+
+ cnt = sscanf(&debug_buf[13], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &mac[0], &mac[1], &mac[2],
+ &mac[3], &mac[4], &mac[5]);
+ if (cnt == 6)
+ for (i = 0; i < 6; i++)
+ info->vport.base_mac_addr[i] = mac[i];
+ } else if (strncmp(debug_buf, "config_state", 12) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[12]), 0, &value);
+ if (!cnt)
+ info->vport.config_state = value;
+ } else if (strncmp(debug_buf, "encap_slid", 10) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[10]), 0, &value);
+ if (!cnt)
+ info->vport.encap_slid = value;
+ } else if (strncmp(debug_buf, "def_port_mask", 13) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[13]), 16, &value);
+ if (!cnt)
+ info->vesw.def_port_mask = value;
+ } else if (strncmp(debug_buf, "u_ucast_dlid", 12) == 0) {
+ u32 idx;
+ int val;
+
+ cnt = sscanf(&debug_buf[12], "%u %i", &idx, &val);
+ if ((cnt == 2) && (idx < OPA_VESW_MAX_NUM_DEF_PORT))
+ info->vesw.u_ucast_dlid[idx] = (u32)val;
+ } else if (strncmp(debug_buf, "u_mcast_dlid", 12) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[12]), 0, &value);
+ if (!cnt)
+ info->vesw.u_mcast_dlid = value;
+ } else if (strncmp(debug_buf, "eth_mtu", 7) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[7]), 0, &value);
+ if (!cnt)
+ info->vesw.eth_mtu = value;
+ } else if (strncmp(debug_buf, "non_vlan_sc_uc", 14) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[14]), 0, &value);
+ if (!cnt)
+ info->vport.non_vlan_sc_uc = value;
+ } else if (strncmp(debug_buf, "non_vlan_sc_mc", 14) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[14]), 0, &value);
+ if (!cnt)
+ info->vport.non_vlan_sc_mc = value;
+ } else if (strncmp(debug_buf, "pcp_to_sc_uc", 12) == 0) {
+ int i, sc[8];
+
+ cnt = sscanf(&debug_buf[12], "%i %i %i %i %i %i %i %i",
+ &sc[0], &sc[1], &sc[2], &sc[3],
+ &sc[4], &sc[5], &sc[6], &sc[7]);
+ if (cnt == 8)
+ for (i = 0; i < 8; i++)
+ info->vport.pcp_to_sc_uc[i] = sc[i];
+ } else if (strncmp(debug_buf, "pcp_to_sc_mc", 12) == 0) {
+ int i, sc[8];
+
+ cnt = sscanf(&debug_buf[12], "%i %i %i %i %i %i %i %i",
+ &sc[0], &sc[1], &sc[2], &sc[3],
+ &sc[4], &sc[5], &sc[6], &sc[7]);
+ if (cnt == 8)
+ for (i = 0; i < 8; i++)
+ info->vport.pcp_to_sc_mc[i] = sc[i];
+ } else if (strncmp(debug_buf, "non_vlan_vl_uc", 14) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[14]), 0, &value);
+ if (!cnt)
+ info->vport.non_vlan_vl_uc = value;
+ } else if (strncmp(debug_buf, "non_vlan_vl_mc", 14) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[14]), 0, &value);
+ if (!cnt)
+ info->vport.non_vlan_vl_mc = value;
+ } else if (strncmp(debug_buf, "pcp_to_vl_uc", 12) == 0) {
+ int i, vl[8];
+
+ cnt = sscanf(&debug_buf[12], "%i %i %i %i %i %i %i %i",
+ &vl[0], &vl[1], &vl[2], &vl[3],
+ &vl[4], &vl[5], &vl[6], &vl[7]);
+ if (cnt == 8)
+ for (i = 0; i < 8; i++)
+ info->vport.pcp_to_vl_uc[i] = vl[i];
+ } else if (strncmp(debug_buf, "pcp_to_vl_mc", 12) == 0) {
+ int i, vl[8];
+
+ cnt = sscanf(&debug_buf[12], "%i %i %i %i %i %i %i %i",
+ &vl[0], &vl[1], &vl[2], &vl[3],
+ &vl[4], &vl[5], &vl[6], &vl[7]);
+ if (cnt == 8)
+ for (i = 0; i < 8; i++)
+ info->vport.pcp_to_vl_mc[i] = vl[i];
+ } else if (strncmp(debug_buf, "encap_rc", 8) == 0) {
+ cnt = kstrtouint(strim(&debug_buf[8]), 16, &value);
+ if (!cnt)
+ info->vesw.rc = value;
+ } else if (strncmp(debug_buf, "reset", 5) == 0) {
+ struct opa_veswport_info port_info;
+
+ vema_get_pod_values(&port_info);
+ opa_vnic_set_vesw_info(adapter, &port_info.vesw);
+ opa_vnic_set_per_veswport_info(adapter, &port_info.vport);
+ opa_vnic_release_mac_tbl(adapter);
+ }
+
+ /* process the new config settings */
+ opa_vnic_process_vema_config(adapter);
+ return count;
+}
+
+DEBUGFS_SEQ_FILE_OPS(vport_state);
+DEBUGFS_SEQ_FILE_OPEN(vport_state)
+DEBUGFS_FILE_OPS(vport_state);
+
+static ssize_t mac_tbl_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct opa_vnic_adapter *adapter = file_inode(file)->i_private;
+ struct opa_veswport_mactable *tbl;
+ char *debug_buf;
+ ssize_t len = 0;
+ int i, extra, rc = 0;
+
+ if (*ppos != 0)
+ return 0;
+
+ if (count < OPA_VNIC_MACTBL_STR_SIZE)
+ return -ENOSPC;
+
+ debug_buf = kmalloc(OPA_VNIC_MACTBL_STR_SIZE, GFP_KERNEL);
+ if (!debug_buf)
+ return -ENOMEM;
+
+ /* allocate veswport mac table */
+ extra = sizeof(struct opa_veswport_mactable_entry) *
+ OPA_VNIC_MAC_TBL_MAX_ENTRIES;
+ tbl = kzalloc(sizeof(*tbl) + extra, GFP_KERNEL);
+ if (!tbl) {
+ rc = -ENOMEM;
+ goto read_done;
+ }
+
+ /* get the whole table */
+ tbl->offset = cpu_to_be16(0);
+ tbl->num_entries = cpu_to_be16(OPA_VNIC_MAC_TBL_MAX_ENTRIES);
+
+ opa_vnic_query_mac_tbl(adapter, tbl);
+ len += scnprintf(debug_buf + len, OPA_VNIC_MACTBL_STR_SIZE - len,
+ "Mac Table Digest: %u\n",
+ be32_to_cpu(tbl->mac_tbl_digest));
+ for (i = 0; i < OPA_VNIC_MAC_TBL_MAX_ENTRIES; i++) {
+ struct opa_veswport_mactable_entry *entry =
+ &tbl->tbl_entries[i];
+ u8 *mac_addr = entry->mac_addr;
+ u8 empty_mac[ETH_ALEN] = { 0 };
+
+ /* if the entry is not there (null), skip */
+ if (!memcmp(mac_addr, empty_mac, ARRAY_SIZE(empty_mac)))
+ continue;
+
+ len += scnprintf(debug_buf + len,
+ OPA_VNIC_MACTBL_STR_SIZE - len,
+ "%4d: %02x:%02x:%02x:%02x:%02x:%02x 0x%x\n",
+ i, mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5],
+ be32_to_cpu(entry->dlid_sd));
+ }
+ kfree(tbl);
+
+ rc = simple_read_from_buffer(buf, count, ppos, debug_buf, len);
+read_done:
+ kfree(debug_buf);
+ return rc;
+}
+
+static ssize_t mac_tbl_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct opa_vnic_adapter *adapter = file_inode(file)->i_private;
+ struct opa_veswport_mactable *tbl;
+ int i, extra, cnt, rc, num_bytes;
+ u32 offset, num_entries, digest;
+ char *debug_buf, *buf_ptr;
+ ssize_t len;
+
+ if (*ppos != 0)
+ return 0;
+
+ if (count >= OPA_VNIC_MACTBL_STR_SIZE)
+ return -ENOSPC;
+
+ debug_buf = kmalloc(count + 1, GFP_KERNEL);
+ if (!debug_buf)
+ return -ENOMEM;
+
+ rc = simple_write_to_buffer(debug_buf, count, ppos, buf, count);
+ if (rc < 0)
+ goto write_err;
+
+ len = rc;
+ debug_buf[len] = '\0';
+
+ /* read offset and number of entries */
+ buf_ptr = debug_buf;
+ cnt = sscanf(buf_ptr, "%u %u %u %n", &digest, &offset, &num_entries,
+ &num_bytes);
+ if ((cnt != 3) || !num_entries ||
+ ((offset + num_entries) > OPA_VNIC_MAC_TBL_MAX_ENTRIES)) {
+ v_err("Invalid input\n");
+ rc = -EINVAL;
+ goto write_err;
+ }
+
+ /* allocate veswport mac table */
+ extra = sizeof(struct opa_veswport_mactable_entry) * num_entries;
+ tbl = kzalloc(sizeof(*tbl) + extra, GFP_KERNEL);
+ if (!tbl) {
+ rc = -ENOMEM;
+ goto write_err;
+ }
+
+ /* build the veswport mac table */
+ tbl->mac_tbl_digest = cpu_to_be32(digest);
+ tbl->offset = cpu_to_be16(offset);
+ tbl->num_entries = cpu_to_be16(num_entries);
+ for (i = 0; i < num_entries; i++) {
+ struct opa_veswport_mactable_entry *entry =
+ &tbl->tbl_entries[i];
+ u8 *mac_addr = entry->mac_addr;
+ u32 dlid_sd;
+
+ buf_ptr += num_bytes;
+ cnt = sscanf(buf_ptr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %x%n",
+ &mac_addr[0], &mac_addr[1], &mac_addr[2],
+ &mac_addr[3], &mac_addr[4], &mac_addr[5],
+ &dlid_sd, &num_bytes);
+ if (cnt != 7) {
+ v_err("Invalid input\n");
+ rc = -EINVAL;
+ goto write_invalid;
+ }
+ entry->dlid_sd = cpu_to_be32(dlid_sd);
+ }
+
+ /* update mac table */
+ rc = opa_vnic_update_mac_tbl(adapter, tbl);
+write_invalid:
+ kfree(tbl);
+ rc = rc ? : count;
+write_err:
+ kfree(debug_buf);
+ return rc;
+}
+
+static const struct file_operations mac_tbl_file_ops = {
+ .owner = THIS_MODULE,
+ .write = mac_tbl_write,
+ .read = mac_tbl_read,
+};
+
+void opa_vnic_dbg_vport_init(struct opa_vnic_adapter *adapter)
+{
+ struct net_device *dev = adapter->netdev;
+
+ if (!opa_vnic_dbg_root)
+ return;
+
+ adapter->dentry = debugfs_create_dir(dev->name,
+ opa_vnic_dbg_root);
+ if (!adapter->dentry) {
+ pr_warn("init of opa vnic debugfs failed\n");
+ return;
+ }
+
+ DEBUGFS_SEQ_FILE_CREATE(vport_state, adapter->dentry, adapter);
+ DEBUGFS_FILE_CREATE("mac_tbl", adapter->dentry, adapter,
+ &mac_tbl_file_ops, 0644);
+}
+
+void opa_vnic_dbg_vport_exit(struct opa_vnic_adapter *adapter)
+{
+ debugfs_remove_recursive(adapter->dentry);
+}
+
+void opa_vnic_dbg_init(void)
+{
+ opa_vnic_dbg_root = debugfs_create_dir(opa_vnic_driver_name, NULL);
+ if (IS_ERR(opa_vnic_dbg_root))
+ opa_vnic_dbg_root = NULL;
+ if (!opa_vnic_dbg_root)
+ pr_warn("init of hfi vnic debugfs failed\n");
+}
+
+void opa_vnic_dbg_exit(void)
+{
+ debugfs_remove_recursive(opa_vnic_dbg_root);
+ opa_vnic_dbg_root = NULL;
+}
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.h b/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.h
new file mode 100644
index 0000000..9583a34
--- /dev/null
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_debugfs.h
@@ -0,0 +1,66 @@
+#ifndef _OPA_VNIC_DEBUGFS_H
+#define _OPA_VNIC_DEBUGFS_H
+/*
+ * Copyright(c) 2017 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * This file contains OPA VNIC Debug interface declarations
+ */
+
+#ifdef CONFIG_DEBUG_FS
+void opa_vnic_dbg_vport_init(struct opa_vnic_adapter *adapter);
+void opa_vnic_dbg_vport_exit(struct opa_vnic_adapter *adapter);
+void opa_vnic_dbg_init(void);
+void opa_vnic_dbg_exit(void);
+#else
+static inline void opa_vnic_dbg_vport_init(struct opa_vnic_adapter *adapter) {}
+static inline void opa_vnic_dbg_vport_exit(struct opa_vnic_adapter *adapter) {}
+static inline void opa_vnic_dbg_init(void) {}
+static inline void opa_vnic_dbg_exit(void) {}
+#endif
+
+#endif /* _OPA_VNIC_DEBUGFS_H */
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h b/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h
index afd95f4..4c82c55 100644
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_internal.h
@@ -219,8 +219,9 @@ struct opa_vnic_adapter {
u8 flow_tbl[OPA_VNIC_FLOW_TBL_SIZE];
- unsigned long trap_timeout;
- u8 trap_count;
+ unsigned long trap_timeout;
+ u8 trap_count;
+ struct dentry *dentry;
};
/* Same as opa_veswport_mactable_entry, but without bitwise attribute */
@@ -326,5 +327,6 @@ void opa_vnic_set_per_veswport_info(struct opa_vnic_adapter *adapter,
void opa_vnic_set_ethtool_ops(struct net_device *netdev);
void opa_vnic_vema_send_trap(struct opa_vnic_adapter *adapter,
struct __opa_veswport_trap *data, u32 lid);
+void vema_get_pod_values(struct opa_veswport_info *port_info);
#endif /* _OPA_VNIC_INTERNAL_H */
diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
index 4b615c1..c6cccbb 100644
--- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
+++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c
@@ -57,6 +57,7 @@
#include <rdma/opa_port_info.h>
#include "opa_vnic_internal.h"
+#include "opa_vnic_debugfs.h"
#define DRV_VERSION "1.0"
char opa_vnic_driver_name[] = "opa_vnic";
@@ -177,7 +178,7 @@ static inline bool vema_mac_tbl_req_ok(struct opa_veswport_mactable *mac_tbl)
* Return the power on default values in the port info structure
* in big endian format as required by MAD.
*/
-static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
+void vema_get_pod_values(struct opa_veswport_info *port_info)
{
memset(port_info, 0, sizeof(*port_info));
port_info->vport.max_mac_tbl_ent =
@@ -213,6 +214,7 @@ static inline void vema_get_pod_values(struct opa_veswport_info *port_info)
opa_vnic_rem_netdev(adapter);
adapter = ERR_PTR(rc);
}
+ opa_vnic_dbg_vport_init(adapter);
}
return adapter;
@@ -857,6 +859,7 @@ static int vema_rem_vport(int id, void *p, void *data)
{
struct opa_vnic_adapter *adapter = p;
+ opa_vnic_dbg_vport_exit(adapter);
opa_vnic_rem_netdev(adapter);
return 0;
}
@@ -1057,9 +1060,12 @@ static int __init opa_vnic_init(void)
pr_info("OPA Virtual Network Driver - v%s\n",
opa_vnic_driver_version);
+ opa_vnic_dbg_init();
rc = ib_register_client(&opa_vnic_client);
- if (rc)
+ if (rc) {
pr_err("VNIC driver register failed %d\n", rc);
+ opa_vnic_dbg_exit();
+ }
return rc;
}
@@ -1068,6 +1074,7 @@ static int __init opa_vnic_init(void)
static void opa_vnic_deinit(void)
{
ib_unregister_client(&opa_vnic_client);
+ opa_vnic_dbg_exit();
}
module_exit(opa_vnic_deinit);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2017-09-26 14:08 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-26 14:08 [PATCH for-next 0/2] IB/opa_vnic: Add debugfs interface Dennis Dalessandro
[not found] ` <20170926140714.18110.74689.stgit-9QXIwq+3FY+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
2017-09-26 14:08 ` Dennis Dalessandro [this message]
2017-09-26 14:08 ` [PATCH for-next 2/2] IB/opa_vnic: Support adding OPA VNIC vports through debug interface Dennis Dalessandro
2017-09-26 17:49 ` [PATCH for-next 0/2] IB/opa_vnic: Add debugfs interface Leon Romanovsky
[not found] ` <20170926174946.GA1218-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-26 17:55 ` Leon Romanovsky
[not found] ` <20170926175524.GA2297-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-26 18:12 ` Vishwanathapura, Niranjana
[not found] ` <20170926181214.GA41364-wPcXA7LoDC+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
2017-09-27 6:20 ` Leon Romanovsky
2017-09-27 15:26 ` Doug Ledford
[not found] ` <1506525977.33755.3.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2017-09-28 18:47 ` Vishwanathapura, Niranjana
[not found] ` <20170928184727.GA33282-wPcXA7LoDC+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
2017-09-28 18:57 ` Leon Romanovsky
[not found] ` <20170928185753.GG2297-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-28 19:05 ` Vishwanathapura, Niranjana
[not found] ` <20170928190502.GA33289-wPcXA7LoDC+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
2017-09-28 19:37 ` Leon Romanovsky
[not found] ` <20170928193740.GH2297-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-28 20:02 ` Jason Gunthorpe
[not found] ` <20170928200258.GA27343-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2017-09-29 5:49 ` Leon Romanovsky
[not found] ` <20170929054959.GJ2297-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-29 14:46 ` Dennis Dalessandro
[not found] ` <cbb65789-2d1e-779e-77f8-55b435511069-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2017-09-29 14:59 ` Leon Romanovsky
[not found] ` <20170929145950.GC2965-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-09-29 15:27 ` Vishwanathapura, Niranjana
[not found] ` <20170929152707.GA34521-wPcXA7LoDC+1XWohqUldA0EOCMrvLtNR@public.gmane.org>
2017-10-02 4:23 ` Leon Romanovsky
[not found] ` <20171002042323.GG2031-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-10-03 0:47 ` Dennis Dalessandro
[not found] ` <68a08a10-5b8d-4fd7-ad06-8add423bd3cd-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2017-10-03 5:15 ` Leon Romanovsky
[not found] ` <20171003051521.GA26055-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-10-03 17:05 ` Vishwanathapura, Niranjana
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170926140842.18110.55132.stgit@scvm10.sc.intel.com \
--to=dennis.dalessandro-ral2jqcrhueavxtiumwx3w@public.gmane.org \
--cc=dledford-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=niranjana.vishwanathapura-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=safranco-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=sudeep.dutt-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.