All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
	Andrew Lunn <andrew@lunn.ch>,
	Florian Fainelli <f.fainelli@gmail.com>,
	linux-kernel@vger.kernel.org, Guenter Roeck <linux@roeck-us.net>
Subject: [PATCH v2 11/16] net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext
Date: Thu, 26 Mar 2015 18:36:38 -0700	[thread overview]
Message-ID: <1427420203-27685-12-git-send-email-linux@roeck-us.net> (raw)
In-Reply-To: <1427420203-27685-1-git-send-email-linux@roeck-us.net>

No vlan support at this time.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.h |  16 ++++++
 2 files changed, 152 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 17aa74f64233..038802229e32 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
@@ -953,6 +954,141 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
 	return 0;
 }
 
+static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
+				  const unsigned char *addr)
+{
+	int i, ret;
+
+	for (i = 0; i < 3; i++) {
+		ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0d + i,
+					(addr[i * 2] << 8) | addr[i * 2 + 1]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
+{
+	int i, ret;
+
+	for (i = 0; i < 3; i++) {
+		ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0d + i);
+		if (ret < 0)
+			return ret;
+		addr[i * 2] = ret >> 8;
+		addr[i * 2 + 1] = ret & 0xff;
+	}
+
+	return 0;
+}
+
+static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
+				    const unsigned char *addr, int state)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid = ps->fid[port];
+	int ret;
+
+	ret = _mv88e6xxx_atu_wait(ds);
+	if (ret < 0)
+		return ret;
+
+	ret = __mv88e6xxx_write_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0c,
+				   (0x10 << port) | state);
+	if (ret)
+		return ret;
+
+	ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_LOAD_FID);
+
+	return ret;
+}
+
+int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	int state = is_multicast_ether_addr(addr) ?
+					FDB_STATE_MC_STATIC : FDB_STATE_STATIC;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, FDB_STATE_UNUSED);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
+				    unsigned char *addr, bool *is_static)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid = ps->fid[port];
+	int ret, state;
+
+	ret = _mv88e6xxx_atu_wait(ds);
+	if (ret < 0)
+		return ret;
+
+	ret = __mv88e6xxx_write_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	do {
+		ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_GETNEXT_FID);
+		if (ret < 0)
+			return ret;
+
+		ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0c);
+		if (ret < 0)
+			return ret;
+		state = ret & FDB_STATE_MASK;
+		if (state == FDB_STATE_UNUSED)
+			return -ENOENT;
+	} while (!(((ret >> 4) & 0xff) & (1 << port)));
+
+	ret = __mv88e6xxx_read_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	*is_static = state == (is_multicast_ether_addr(addr) ?
+			       FDB_STATE_MC_STATIC : FDB_STATE_STATIC);
+
+	return 0;
+}
+
+/* get next entry for port */
+int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
+			       unsigned char *addr, bool *is_static)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
 static void mv88e6xxx_bridge_work(struct work_struct *work)
 {
 	struct mv88e6xxx_priv_state *ps;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8e215ebc8d34..aaf239aba726 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -19,6 +19,8 @@
 
 #define ATU_BUSY			0x8000
 
+#define ATU_CMD_LOAD_FID		(ATU_BUSY | 0x3000)
+#define ATU_CMD_GETNEXT_FID		(ATU_BUSY | 0x4000)
 #define ATU_CMD_FLUSH_NONSTATIC_FID	(ATU_BUSY | 0x6000)
 
 /* port states */
@@ -29,6 +31,14 @@
 #define PSTATE_LEARNING		0x02
 #define PSTATE_FORWARDING	0x03
 
+/* FDB states */
+
+#define FDB_STATE_MASK			0x0f
+
+#define FDB_STATE_UNUSED		0x00
+#define FDB_STATE_MC_STATIC		0x07	/* static multicast */
+#define FDB_STATE_STATIC		0x0e	/* static unicast */
+
 struct mv88e6xxx_priv_state {
 	/* When using multi-chip addressing, this mutex protects
 	 * access to the indirect access registers.  (In single-chip
@@ -121,6 +131,12 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
 int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
 int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
+int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
+			       unsigned char *addr, bool *is_static);
 
 extern struct dsa_switch_driver mv88e6131_switch_driver;
 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
-- 
2.1.0


  parent reply	other threads:[~2015-03-27  1:39 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 02/16] net: dsa: mv88e6xxx: Provide function for common port initialization Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 03/16] net: dsa: mv88e6xxx: Disable Message Port bit for CPU port Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 04/16] net: dsa: mv88e6xxx: Split mv88e6xxx_reg_read and mv88e6xxx_reg_write Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 05/16] net: dsa: mv88e6352: Use common port initialization code Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 06/16] net: dsa: mv88e6123_61_65: Use common port configuration Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 07/16] net: dsa: mv88e6171: " Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 08/16] net: dsa: mv88e6xxx: Add Hardware bridging support Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 09/16] net: dsa: mv88e6352: Add support for hardware bridging Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 10/16] net: dsa: Add basic framework to support ndo_fdb functions Guenter Roeck
2015-03-27  1:36 ` Guenter Roeck [this message]
2015-03-27  1:36 ` [PATCH v2 12/16] net: dsa: mv88e6352: Add support for " Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 13/16] net: dsa: Centralise getting switch id Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 14/16] net: dsa: mv88e6171: Add defines for switch product IDs Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 15/16] net: dsa: mv88e6171: Add EEE support to the mv88e6172 Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 16/16] net: dsa: mv88e6171: Add support for hardware bridging Guenter Roeck
2015-03-27  6:01 ` [PATCH v2 00/16] net: dsa: HW bridging, EEE support Florian Fainelli
2015-03-27 15:54 ` Andrew Lunn
2015-03-29 20:24 ` David Miller

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=1427420203-27685-12-git-send-email-linux@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.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.