[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1543880097-7106-5-git-send-email-Tristram.Ha@microchip.com>
Date: Mon, 3 Dec 2018 15:34:55 -0800
From: <Tristram.Ha@...rochip.com>
To: Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>,
Pavel Machek <pavel@....cz>
CC: Tristram Ha <Tristram.Ha@...rochip.com>,
<UNGLinuxDriver@...rochip.com>, <netdev@...r.kernel.org>
Subject: [PATCH RFC 4/6] net: dsa: microchip: Each switch driver has its own tail tagging operations
From: Tristram Ha <Tristram.Ha@...rochip.com>
The tail tagging operations are implemented in each switch driver so that
the main tail tagging code tag_ksz.c does not need to be changed after
modification to support that mechanism is made.
Signed-off-by: Tristram Ha <Tristram.Ha@...rochip.com>
---
drivers/net/dsa/microchip/ksz9477.c | 78 +++++++++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 4 +-
drivers/net/dsa/microchip/ksz_priv.h | 3 +-
include/linux/dsa/ksz_dsa.h | 9 ++++
4 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index bd1ca33..c690c2b2 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -21,6 +21,14 @@
#include "ksz_common.h"
#include "ksz9477_reg.h"
+/* features flags */
+#define GBIT_SUPPORT BIT(0)
+#define NEW_XMII BIT(1)
+#define IS_9893 BIT(2)
+
+/* overrides flags */
+#define PTP_TAG BIT(0)
+
static const struct {
int index;
char string[ETH_GSTRING_LEN];
@@ -1356,9 +1364,77 @@ static void ksz9477_switch_exit(struct ksz_device *dev)
.exit = ksz9477_switch_exit,
};
+/* For Ingress (Host -> KSZ), 2 bytes are added before FCS.
+ * ---------------------------------------------------------------------------
+ * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
+ * ---------------------------------------------------------------------------
+ * tag0 : Prioritization (not used now)
+ * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
+ *
+ * For switch with 3 ports only one byte is needed.
+ * When PTP function is enabled additional 4 bytes are needed.
+ *
+ * For Egress (KSZ -> Host), 1 byte is added before FCS.
+ * ---------------------------------------------------------------------------
+ * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---------------------------------------------------------------------------
+ * tag0 : zero-based value represents port
+ * (eg, 0x00=port1, 0x02=port3, 0x06=port7)
+ *
+ * When PTP function is enabled BIT 7 indicates the received frame is a PTP
+ * message and so there are 4 additional bytes for the receive timestamp.
+ */
+
+static int ksz9477_get_len(struct ksz_device *dev)
+{
+ int len = 1;
+
+ if (!(dev->features & IS_9893))
+ len += 1;
+ if (dev->overrides & PTP_TAG)
+ len += 4;
+ return len;
+}
+
+static int ksz9477_get_tag(struct ksz_device *dev, u8 *tag, int *port)
+{
+ int len = 1;
+
+ if (tag[0] & BIT(7))
+ len += 4;
+ *port = tag[0] & 7;
+ return len;
+}
+
+static void ksz9477_set_tag(struct ksz_device *dev, void *ptr, u8 *addr, int p)
+{
+ if (dev->overrides & PTP_TAG) {
+ u32 *timestamp = (u32 *)ptr;
+
+ *timestamp = 0;
+ ptr = timestamp + 1;
+ }
+ if (dev->features & IS_9893) {
+ u8 *tag = (u8 *)ptr;
+
+ *tag = 1 << p;
+ } else {
+ u16 *tag = (u16 *)ptr;
+
+ *tag = 1 << p;
+ *tag = cpu_to_be16(*tag);
+ }
+}
+
+static const struct ksz_tag_ops ksz9477_tag_ops = {
+ .get_len = ksz9477_get_len,
+ .get_tag = ksz9477_get_tag,
+ .set_tag = ksz9477_set_tag,
+};
+
int ksz9477_switch_register(struct ksz_device *dev)
{
- return ksz_switch_register(dev, &ksz9477_dev_ops);
+ return ksz_switch_register(dev, &ksz9477_dev_ops, &ksz9477_tag_ops);
}
EXPORT_SYMBOL(ksz9477_switch_register);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 7b8f57b..a72659b 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -399,7 +399,8 @@ struct ksz_device *ksz_switch_alloc(struct device *base,
EXPORT_SYMBOL(ksz_switch_alloc);
int ksz_switch_register(struct ksz_device *dev,
- const struct ksz_dev_ops *ops)
+ const struct ksz_dev_ops *ops,
+ const struct ksz_tag_ops *tag_ops)
{
int ret;
@@ -412,6 +413,7 @@ int ksz_switch_register(struct ksz_device *dev,
mutex_init(&dev->vlan_mutex);
dev->dev_ops = ops;
+ dev->tag_ops = tag_ops;
if (dev->dev_ops->detect(dev))
return -EINVAL;
diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
index 5d93822..d020c1e 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -78,7 +78,8 @@ struct ksz_dev_ops {
struct ksz_device *ksz_switch_alloc(struct device *base,
const struct ksz_io_ops *ops, void *priv);
int ksz_switch_register(struct ksz_device *dev,
- const struct ksz_dev_ops *ops);
+ const struct ksz_dev_ops *ops,
+ const struct ksz_tag_ops *tag_ops);
void ksz_switch_remove(struct ksz_device *dev);
int ksz9477_switch_register(struct ksz_device *dev);
diff --git a/include/linux/dsa/ksz_dsa.h b/include/linux/dsa/ksz_dsa.h
index 3148cae..3fb2713 100644
--- a/include/linux/dsa/ksz_dsa.h
+++ b/include/linux/dsa/ksz_dsa.h
@@ -7,6 +7,14 @@
#include <linux/phy.h>
+struct ksz_device;
+
+struct ksz_tag_ops {
+ int (*get_len)(struct ksz_device *dev);
+ int (*get_tag)(struct ksz_device *dev, u8 *tag, int *port);
+ void (*set_tag)(struct ksz_device *dev, void *ptr, u8 *addr, int p);
+};
+
struct vlan_table {
u32 table[3];
};
@@ -45,6 +53,7 @@ struct ksz_device {
struct mutex vlan_mutex; /* vlan access */
const struct ksz_io_ops *ops;
const struct ksz_dev_ops *dev_ops;
+ const struct ksz_tag_ops *tag_ops;
struct device *dev;
--
1.9.1
Powered by blists - more mailing lists