From: Tristram Ha <tristram...@microchip.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...@microchip.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