linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Satha Koteswara Rao <satha.rao@caviumnetworks.com>
To: <linux-kernel@vger.kernel.org>
Cc: <sgoutham@cavium.com>, <rric@kernel.org>, <davem@davemloft.net>,
	<david.daney@cavium.com>, <rvatsavayi@caviumnetworks.com>,
	<derek.chickles@caviumnetworks.com>,
	<satha.rao@caviumnetworks.com>, <philip.romanov@cavium.com>,
	<netdev@vger.kernel.org>, <linux-arm-kernel@lists.infradead.org>
Subject: [RFC PATCH 6/7] HW Filter Table access API's
Date: Wed, 21 Dec 2016 14:16:50 +0530	[thread overview]
Message-ID: <1482310011-1862-7-git-send-email-satha.rao@caviumnetworks.com> (raw)
In-Reply-To: <1482310011-1862-1-git-send-email-satha.rao@caviumnetworks.com>

---
 drivers/net/ethernet/cavium/thunder/tbl_access.c | 262 +++++++++++++++++++++++
 drivers/net/ethernet/cavium/thunder/tbl_access.h |  61 ++++++
 2 files changed, 323 insertions(+)
 create mode 100644 drivers/net/ethernet/cavium/thunder/tbl_access.c
 create mode 100644 drivers/net/ethernet/cavium/thunder/tbl_access.h

diff --git a/drivers/net/ethernet/cavium/thunder/tbl_access.c b/drivers/net/ethernet/cavium/thunder/tbl_access.c
new file mode 100644
index 0000000..6be31eb
--- /dev/null
+++ b/drivers/net/ethernet/cavium/thunder/tbl_access.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2015 Cavium, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/uaccess.h>
+#include "pf_globals.h"
+#include "pf_locals.h"
+#include "tbl_access.h"
+
+struct tns_table_s *get_table_information(int table_id)
+{
+	int i;
+
+	for (i = 0; i < TNS_MAX_TABLE; i++) {
+		if (!tbl_info[i].sdata.valid)
+			continue;
+
+		if (tbl_info[i].sdata.tbl_id == table_id)
+			return &tbl_info[i];
+	}
+
+	return NULL;
+}
+
+int tbl_write(int node, int table_id, int tbl_index, void *key, void *mask,
+	      void *data)
+{
+	int i;
+	struct tns_table_s *tbl = get_table_information(table_id);
+	int bck_cnt, data_index, data_offset;
+	u64 data_entry[4];
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	bck_cnt = tbl->sdata.data_width / tbl->sdata.data_size;
+	data_index = (tbl_index / bck_cnt);
+	data_offset = (tbl_index % bck_cnt);
+	//TCAM Table, we need to parse key & mask into single array
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		struct filter_keymask_s *tk = (struct filter_keymask_s *)key;
+		struct filter_keymask_s *tm = (struct filter_keymask_s *)mask;
+		u8 km[32];
+		u64 mod_key, mod_mask, temp_mask;
+		int index = 0, offset = 0;
+
+		memset(km, 0x0, 32);
+
+/* TCAM truth table data creation. Translation from data/mask to following
+ * truth table:
+ *
+ *         Mask   Data     Content
+ *          0     0         X
+ *          0     1         1
+ *          1     0         0
+ *          1     1         Always Mismatch
+ *
+ */
+		mod_mask = ~tk->key_value;
+		temp_mask = tm->key_value;
+		mod_key = tk->key_value;
+		mod_key = mod_key & (~temp_mask);
+		mod_mask = mod_mask & (~temp_mask);
+
+		for (i = 0; i < 64; i++) {
+			km[index] = km[index] | (((mod_mask >> i) & 0x1) <<
+						 offset);
+			km[index] = km[index] | (((mod_key >> i) & 0x1) <<
+						 (offset + 1));
+			offset += 2;
+			if (offset == 8) {
+				offset = 0;
+				index += 1;
+			}
+		}
+		km[index] = 0x2;
+		if (tns_write_register_indirect(node,
+						(tbl->sdata.key_base_addr +
+						 (tbl_index * 32)), 32,
+						(void *)&km[0])) {
+			filter_dbg(FERR, "key write failed node %d tbl ID %d",
+				   node, table_id);
+			filter_dbg(FERR, " index %d\n", tbl_index);
+			return TNS_ERR_DRIVER_WRITE;
+		}
+	}
+
+	/* Data Writes are ReadModifyWrite */
+	if (tns_read_register_indirect(node, (tbl->sdata.data_base_addr +
+					      (data_index * 32)), 32,
+				       (void *)&data_entry[0])) {
+		filter_dbg(FERR, "data read failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_READ;
+	}
+	memcpy(&data_entry[data_offset], data, tbl->sdata.data_size / 8);
+	if (tns_write_register_indirect(node, (tbl->sdata.data_base_addr +
+					       (data_index * 32)), 32,
+					(void *)&data_entry[0])) {
+		filter_dbg(FERR, "data write failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_WRITE;
+	}
+
+	return TNS_NO_ERR;
+}
+
+int tbl_read(int node, int table_id, int tbl_index, void *key, void *mask,
+	     void *data)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+	int i, bck_cnt, data_index, data_offset;
+	u64 data_entry[4];
+	u8 km[32];
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	bck_cnt = tbl->sdata.data_width / tbl->sdata.data_size;
+	data_index = (tbl_index / bck_cnt);
+	data_offset = (tbl_index % bck_cnt);
+
+	//TCAM Table, we need to parse key & mask into single array
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		memset(km, 0x0, 32);
+
+		if (tns_read_register_indirect(node, (tbl->sdata.key_base_addr +
+						      (tbl_index * 32)), 32,
+					       (void *)&km[0])) {
+			filter_dbg(FERR, "key read failed node %d tbl ID %d",
+				   node, table_id);
+			filter_dbg(FERR, " idx %d\n", tbl_index);
+			return TNS_ERR_DRIVER_READ;
+		}
+		if (!(km[((tbl->sdata.key_size * 2) / 8)] == 0x2))
+			return TNS_ERR_MAC_FILTER_INVALID_ENTRY;
+	}
+
+	if (tns_read_register_indirect(node, (tbl->sdata.data_base_addr +
+					      (data_index * 32)), 32,
+				       (void *)&data_entry[0])) {
+		filter_dbg(FERR, "data read failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_READ;
+	}
+	memcpy(data, (void *)(&data_entry[data_offset]),
+	       (tbl->sdata.data_size / 8));
+
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		struct filter_keymask_s *tk = (struct filter_keymask_s *)key;
+		struct filter_keymask_s *tm = (struct filter_keymask_s *)mask;
+		u8 temp_km;
+		int index = 0, offset = 0;
+
+		tk->key_value = 0x0ull;
+		tm->key_value = 0x0ull;
+		temp_km = km[0];
+		for (i = 0; i < 64; i++) {
+			tm->key_value = tm->key_value |
+					 ((temp_km & 0x1ull) << i);
+			temp_km >>= 1;
+			tk->key_value = tk->key_value |
+					 ((temp_km & 0x1ull) << i);
+			temp_km >>= 1;
+			offset += 2;
+			if (offset == 8) {
+				offset = 0;
+				index += 1;
+				temp_km = km[index];
+			}
+		}
+		tm->key_value = ~tm->key_value & ~tk->key_value;
+		tk->is_valid = 1;
+		tm->is_valid = 0;
+	}
+
+	return TNS_NO_ERR;
+}
+
+int invalidate_table_entry(int node, int table_id, int tbl_idx)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		u8 km[32];
+
+		memset(km, 0x0, 32);
+		km[((tbl->sdata.key_size * 2) / 8)] = 0x1;
+
+		if (tns_write_register_indirect(node,
+						(tbl->sdata.key_base_addr +
+						 (tbl_idx * 32)), 32,
+						(void *)&km[0])) {
+			filter_dbg(FERR, "%s failed node %d tbl ID %d idx %d\n",
+				   __func__, node, table_id, tbl_idx);
+			return TNS_ERR_DRIVER_WRITE;
+		}
+	}
+
+	return TNS_NO_ERR;
+}
+
+int alloc_table_index(int node, int table_id, int *index)
+{
+	int err = 0;
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "%s Invalid TableID %d\n", __func__, table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	if (*index == -1) {
+		*index = find_first_zero_bit(tbl->ddata[node].bitmap,
+					     tbl->sdata.depth);
+
+		if (*index < 0 || *index >= tbl->sdata.depth)
+			err = -ENOSPC;
+		else
+			__set_bit(*index, tbl->ddata[node].bitmap);
+
+		return err;
+	} else if (*index < 0 || *index >= tbl->sdata.depth) {
+		filter_dbg(FERR, "%s Out of bound index %d requested[0...%d]\n",
+			   __func__, *index, tbl->sdata.depth);
+		return TNS_ERR_MAC_FILTER_INVALID_ENTRY;
+	}
+	if (test_and_set_bit(*index, tbl->ddata[node].bitmap))
+		filter_dbg(FDEBUG, "%s Entry Already exists\n", __func__);
+
+	return err;
+}
+
+void free_table_index(int node, int table_id, int index)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "%s Invalid TableID %d\n", __func__, table_id);
+		return;
+	}
+	if (index < 0 || index >= tbl->sdata.depth) {
+		filter_dbg(FERR, "%s Invalid Index %d Max Limit %d\n",
+			   __func__, index, tbl->sdata.depth);
+		return;
+	}
+
+	__clear_bit(index, tbl->ddata[node].bitmap);
+}
diff --git a/drivers/net/ethernet/cavium/thunder/tbl_access.h b/drivers/net/ethernet/cavium/thunder/tbl_access.h
new file mode 100644
index 0000000..c098410
--- /dev/null
+++ b/drivers/net/ethernet/cavium/thunder/tbl_access.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Cavium, Inc.
+ *
+ * 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.
+ */
+
+#ifndef __TBL_ACCESS_H__
+#define __TBL_ACCESS_H__
+
+#define TNS_MAX_TABLE	8
+
+enum {
+	TNS_TBL_TYPE_DT,
+	TNS_TBL_TYPE_HT,
+	TNS_TBL_TYPE_TT,
+	TNS_TBL_TYPE_MAX
+};
+
+struct table_static_s {
+	u8 tbl_type;
+	u8 tbl_id;
+	u8 valid;
+	u8 rsvd;
+	u16 key_size;
+	u16 data_size;
+	u16 data_width;
+	u16 key_width;
+	u32 depth;
+	u64 key_base_addr;
+	u64 data_base_addr;
+	u8 tbl_name[32];
+};
+
+struct table_dynamic_s {
+	unsigned long *bitmap;
+};
+
+struct tns_table_s {
+	struct table_static_s sdata;
+	struct table_dynamic_s ddata[MAX_NUMNODES];
+};
+
+enum {
+	MAC_FILTER_TABLE = 102,
+	VLAN_FILTER_TABLE = 103,
+	MAC_EVIF_TABLE = 140,
+	VLAN_EVIF_TABLE = 201,
+	PORT_CONFIG_TABLE = 202,
+	TABLE_ID_END
+};
+
+extern struct tns_table_s	tbl_info[TNS_MAX_TABLE];
+
+struct filter_keymask_s {
+	u8 is_valid;
+	u64 key_value;
+};
+
+#endif /* __TBL_ACCESS_H__ */
-- 
1.8.3.1

  parent reply	other threads:[~2016-12-21  9:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-21  8:46 [RFC PATCH 0/7] ThunderX Embedded switch support Satha Koteswara Rao
2016-12-21  8:46 ` [RFC PATCH 1/7] PF driver modified to enable HW filter support, changes works in backward compatibility mode Enable required things in Makefile Enable LZ4 dependecy inside config file Satha Koteswara Rao
2016-12-21 13:05   ` Sunil Kovvuri
2016-12-26 14:20     ` Koteshwar Rao, Satha
2016-12-27  4:19       ` Sunil Kovvuri
2016-12-21  8:46 ` [RFC PATCH 2/7] VF driver changes to enable hooks to get kernel notifications Satha Koteswara Rao
2016-12-21  8:46 ` [RFC PATCH 3/7] Enable pause frame support Satha Koteswara Rao
     [not found]   ` <DM5PR07MB2889471E0668C95BD2A266709E930@DM5PR07MB2889.namprd07.prod.outlook.com>
2016-12-26 14:21     ` Koteshwar Rao, Satha
2016-12-21  8:46 ` [RFC PATCH 4/7] HW Filter Initialization code and register access APIs Satha Koteswara Rao
2016-12-21 12:36   ` Sunil Kovvuri
2016-12-26 14:13     ` Koteshwar Rao, Satha
2016-12-21  8:46 ` [RFC PATCH 5/7] Multiple VF's grouped together under single physical port called PF group PF Group maintainance API's Satha Koteswara Rao
2016-12-21 12:43   ` Sunil Kovvuri
2016-12-26 14:16     ` Koteshwar Rao, Satha
2016-12-21  8:46 ` Satha Koteswara Rao [this message]
2016-12-21  8:46 ` [RFC PATCH 7/7] Get notifications from PF driver and configure filter block based on request data Satha Koteswara Rao
2016-12-21 12:03 ` [RFC PATCH 0/7] ThunderX Embedded switch support Sunil Kovvuri
2016-12-26 14:04   ` Koteshwar Rao, Satha
2016-12-26 14:55     ` Andrew Lunn

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=1482310011-1862-7-git-send-email-satha.rao@caviumnetworks.com \
    --to=satha.rao@caviumnetworks.com \
    --cc=davem@davemloft.net \
    --cc=david.daney@cavium.com \
    --cc=derek.chickles@caviumnetworks.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=philip.romanov@cavium.com \
    --cc=rric@kernel.org \
    --cc=rvatsavayi@caviumnetworks.com \
    --cc=sgoutham@cavium.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).