* [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code @ 2010-07-21 13:37 Mike Frysinger 2010-07-21 13:37 ` [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support Mike Frysinger 2010-07-21 15:02 ` [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Lennert Buytenhek 0 siblings, 2 replies; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 13:37 UTC (permalink / raw) To: netdev, David S. Miller Cc: uclinux-dist-devel, Karl Beldan, Lennert Buytenhek, Graf Yang, Bryan Wu From: Graf Yang <graf.yang@analog.com> Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org> --- include/linux/if_ether.h | 1 + include/linux/netdevice.h | 10 +++ include/net/dsa.h | 2 +- net/dsa/Kconfig | 3 + net/dsa/Makefile | 1 + net/dsa/dsa.c | 6 ++ net/dsa/dsa_priv.h | 2 + net/dsa/slave.c | 18 ++++++ net/dsa/tag_stpid.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ net/ethernet/eth.c | 2 + 10 files changed, 191 insertions(+), 1 deletions(-) create mode 100644 net/dsa/tag_stpid.c diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index c831467..cb9e2be 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -107,6 +107,7 @@ #define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ #define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ #define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ +#define ETH_P_STPID 0x001D /* STPID switch tagging */ #define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ #define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ #define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b626289..a13dca4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1140,6 +1140,16 @@ static inline bool netdev_uses_trailer_tags(struct net_device *dev) return 0; } +static inline bool netdev_uses_stpid_tags(struct net_device *dev) +{ +#ifdef CONFIG_NET_DSA_TAG_STPID + if (dev->dsa_ptr != NULL) + return dsa_uses_stpid_tags(dev->dsa_ptr); +#endif + + return 0; +} + /** * netdev_priv - access network device private data * @dev: network device diff --git a/include/net/dsa.h b/include/net/dsa.h index 839f768..21a5e2e 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -56,6 +56,6 @@ struct dsa_platform_data { extern bool dsa_uses_dsa_tags(void *dsa_ptr); extern bool dsa_uses_trailer_tags(void *dsa_ptr); - +extern bool dsa_uses_stpid_tags(void *dsa_ptr); #endif diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 1120178..ee8d705 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -23,6 +23,9 @@ config NET_DSA_TAG_TRAILER bool default n +config NET_DSA_TAG_STPID + bool + default n # switch drivers config NET_DSA_MV88E6XXX diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 2374faf..4881577 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o +obj-$(CONFIG_NET_DSA_TAG_STPID) += tag_stpid.o # switch drivers obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 6112a12..8cb4dfa 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -220,6 +220,12 @@ bool dsa_uses_trailer_tags(void *dsa_ptr) return !!(dst->tag_protocol == htons(ETH_P_TRAILER)); } +bool dsa_uses_stpid_tags(void *dsa_ptr) +{ + struct dsa_switch_tree *dst = dsa_ptr; + + return !!(dst->tag_protocol == htons(ETH_P_STPID)); +} /* link polling *************************************************************/ static void dsa_link_poll_work(struct work_struct *ugly) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 4b0ea05..be76ded 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -177,5 +177,7 @@ netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev); /* tag_trailer.c */ netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev); +/* tag_stpid.c */ +int stpid_xmit(struct sk_buff *skb, struct net_device *dev); #endif diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 64ca2a6..a1b30a7 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -333,6 +333,19 @@ static const struct net_device_ops trailer_netdev_ops = { .ndo_do_ioctl = dsa_slave_ioctl, }; #endif +#ifdef CONFIG_NET_DSA_TAG_STPID +static const struct net_device_ops stpid_netdev_ops = { + .ndo_init = dsa_slave_init, + .ndo_open = dsa_slave_open, + .ndo_stop = dsa_slave_close, + .ndo_start_xmit = stpid_xmit, + .ndo_change_rx_flags = dsa_slave_change_rx_flags, + .ndo_set_rx_mode = dsa_slave_set_rx_mode, + .ndo_set_multicast_list = dsa_slave_set_rx_mode, + .ndo_set_mac_address = dsa_slave_set_mac_address, + .ndo_do_ioctl = dsa_slave_ioctl, +}; +#endif /* slave device setup *******************************************************/ struct net_device * @@ -370,6 +383,11 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent, slave_dev->netdev_ops = &trailer_netdev_ops; break; #endif +#ifdef CONFIG_NET_DSA_TAG_STPID + case htons(ETH_P_STPID): + slave_dev->netdev_ops = &stpid_netdev_ops; + break; +#endif default: BUG(); } diff --git a/net/dsa/tag_stpid.c b/net/dsa/tag_stpid.c new file mode 100644 index 0000000..b5d9829 --- /dev/null +++ b/net/dsa/tag_stpid.c @@ -0,0 +1,147 @@ +/* + * net/dsa/tag_stpid.c - special tag identifier, + * 0x810 + 4 bit "port mask" + 3 bit 8021p + 1 bit CFI + 12 bit VLAN ID + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/etherdevice.h> +#include <linux/list.h> +#include <linux/netdevice.h> +#include "dsa_priv.h" + +#define ETH_P_8021QH (ETH_P_8021Q >> 8) +#define ETH_P_8021QL (ETH_P_8021Q & 0xFF) +#define STPID_HLEN 4 + +#define ZERO_VID 0 +#define RESERVED_VID 0xFFF +#define STPID_VID ZERO_VID + +int stpid_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct dsa_slave_priv *p = netdev_priv(dev); + u8 *dsa_header; + + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + + /* + * For 802.1Q frames, convert to STPID tagged frames, + * do nothing for common frames. + */ + if (skb->protocol == htons(ETH_P_8021Q)) { + if (skb_cow_head(skb, 0) < 0) + goto out_free; + + dsa_header = skb->data + 2 * ETH_ALEN; + dsa_header[1] = p->port & 0x03; + } + + skb->protocol = htons(ETH_P_STPID); + + skb->dev = p->parent->dst->master_netdev; + dev_queue_xmit(skb); + + return NETDEV_TX_OK; + +out_free: + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static int stpid_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) +{ + struct dsa_switch_tree *dst = dev->dsa_ptr; + struct dsa_switch *ds = dst->ds[0]; + u8 *dsa_header; + int source_port; + int vid; + + if (unlikely(ds == NULL)) + goto out_drop; + + skb = skb_unshare(skb, GFP_ATOMIC); + if (skb == NULL) + goto out; + + /* The ether_head has been pulled by master driver */ + dsa_header = skb->data - 2; + + vid = ((dsa_header[2] & 0x0f)<<8 | dsa_header[3]); + + source_port = dsa_header[1] & 0x03; + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) + goto out_drop; + + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && + (vid != STPID_VID)) { + u8 new_header[STPID_HLEN]; + + /* Convert STPID tag to 802.1q tag */ + new_header[0] = ETH_P_8021QH; + new_header[1] = ETH_P_8021QL; + + if (skb->ip_summed == CHECKSUM_COMPLETE) { + __wsum c = skb->csum; + c = csum_add(c, csum_partial(new_header, 2, 0)); + c = csum_sub(c, csum_partial(dsa_header, 2, 0)); + skb->csum = c; + } + memcpy(dsa_header, new_header, STPID_HLEN / 2); + + } else if ((dsa_header[0] & ETH_P_8021QH) && + (vid == STPID_VID)) { + + if (unlikely(!pskb_may_pull(skb, STPID_HLEN))) + goto out_drop; + + /* Remove STPID tag and update checksum. */ + if (skb->ip_summed == CHECKSUM_COMPLETE) { + __wsum c = skb->csum; + c = csum_sub(c, csum_partial(dsa_header, STPID_HLEN, 0)); + skb->csum = c; + } + memmove(skb->data - ETH_HLEN + STPID_HLEN, + skb->data - ETH_HLEN, 2 * ETH_ALEN); + skb_pull(skb, STPID_HLEN); + } + + skb->dev = ds->ports[source_port]; + skb_push(skb, ETH_HLEN); + skb->pkt_type = PACKET_HOST; + skb->protocol = eth_type_trans(skb, skb->dev); + skb->dev->last_rx = jiffies; + skb->dev->stats.rx_packets++; + skb->dev->stats.rx_bytes += skb->len; + netif_receive_skb(skb); + + return 0; + +out_drop: + kfree_skb(skb); +out: + return 0; +} + +static struct packet_type stpid_packet_type = { + .type = __constant_htons(ETH_P_STPID), + .func = stpid_rcv, +}; + +static int __init stpid_init_module(void) +{ + dev_add_pack(&stpid_packet_type); + return 0; +} +module_init(stpid_init_module); + +static void __exit stpid_cleanup_module(void) +{ + dev_remove_pack(&stpid_packet_type); +} +module_exit(stpid_cleanup_module); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 215c839..964f9d2 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -194,6 +194,8 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_DSA); if (netdev_uses_trailer_tags(dev)) return htons(ETH_P_TRAILER); + if (netdev_uses_stpid_tags(dev)) + return htons(ETH_P_STPID); if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; -- 1.7.1.1 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 13:37 [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Mike Frysinger @ 2010-07-21 13:37 ` Mike Frysinger 2010-07-21 15:16 ` Lennert Buytenhek 2010-07-21 16:29 ` [PATCH 2/2 v2] " Mike Frysinger 2010-07-21 15:02 ` [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Lennert Buytenhek 1 sibling, 2 replies; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 13:37 UTC (permalink / raw) To: netdev, David S. Miller Cc: uclinux-dist-devel, Karl Beldan, Lennert Buytenhek, Graf Yang, Bryan Wu From: Graf Yang <graf.yang@analog.com> Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org> --- net/dsa/Kconfig | 7 + net/dsa/Makefile | 1 + net/dsa/ksz8893m.c | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/ksz8893m.h | 223 ++++++++++++++++++++++++++++++++ 4 files changed, 590 insertions(+), 0 deletions(-) create mode 100644 net/dsa/ksz8893m.c create mode 100644 net/dsa/ksz8893m.h diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index ee8d705..4a87436 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -60,4 +60,11 @@ config NET_DSA_MV88E6123_61_65 This enables support for the Marvell 88E6123/6161/6165 ethernet switch chips. +config NET_DSA_KSZ8893M + bool "MICREL KSZ8893MQL/BL ethernet switch chip support" + select NET_DSA_TAG_STPID + ---help--- + This enables support for the Micrel KSZ8893MQL/BL + ethernet switch chips. + endif diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 4881577..c4295e3 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o +obj-$(CONFIG_NET_DSA_KSZ8893M) += ksz8893m.o # the core obj-$(CONFIG_NET_DSA) += dsa.o slave.o diff --git a/net/dsa/ksz8893m.c b/net/dsa/ksz8893m.c new file mode 100644 index 0000000..98cce04 --- /dev/null +++ b/net/dsa/ksz8893m.c @@ -0,0 +1,359 @@ +/* + * Integrated 3-Port 10/100 Managed Switch with PHYs + * + * - KSZ8893M support + * + * Copyright 2008-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#define pr_fmt(fmt) "ksz8893m: " fmt + +#include <linux/list.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/spi/spi.h> +#include "dsa_priv.h" +#include "ksz8893m.h" + +#define BUF_LEN 6 + +static struct _spi_switch { + struct spi_transfer xfer; + struct spi_device *dev; +} sw; + +static int ksz8893m_read(unsigned char *din, unsigned char reg, int len) +{ + int i, ret; + struct spi_message message; + unsigned char dout[BUF_LEN]; + struct spi_transfer *t = &sw.xfer; + + t->len = len; + t->tx_buf = dout; + t->rx_buf = din; + dout[0] = SPI_READ; + dout[1] = reg; + for (i = 2; i < len; i++) + dout[i] = 0; + + spi_message_init(&message); + spi_message_add_tail(t, &message); + ret = spi_sync(sw.dev, &message); + if (!ret) + return message.status; + + pr_err("read reg%d failed, ret=%d\n", reg, ret); + return ret; +} + +static int ksz8893m_write(unsigned char *dout, unsigned char reg, int len) +{ + int ret; + struct spi_message message; + unsigned char din[BUF_LEN]; + struct spi_transfer *t = &sw.xfer; + + t->len = len; + t->tx_buf = dout; + t->rx_buf = din; + dout[0] = SPI_WRITE; + dout[1] = reg; + + spi_message_init(&message); + spi_message_add_tail(t, &message); + ret = spi_sync(sw.dev, &message); + if (!ret) + return message.status; + + pr_err("write reg%d failed, ret=%d\n", reg, ret); + return ret; +} + +static char *ksz8893m_probe(struct mii_bus *bus, int sw_addr) +{ + int ret, phyid_low, phyid_high; + unsigned char din[BUF_LEN]; + + phyid_high = mdiobus_read(bus, KSZ8893M_CPU_PORT, MII_PHYSID1); + phyid_low = mdiobus_read(bus, KSZ8893M_CPU_PORT, MII_PHYSID2); + if (phyid_high != PHYID_HIGH || phyid_low != PHYID_LOW) + return NULL; + + ret = ksz8893m_read(din, ChipID0, 3); + + if (!ret && FAMILY_ID == din[2]) + return "KSZ8893M"; + + return NULL; +} + +static int ksz8893m_switch_reset(struct dsa_switch *ds) +{ + return 0; +} + +static int ksz8893m_setup_global(struct dsa_switch *ds) +{ + int ret; + unsigned char dout[BUF_LEN]; + unsigned char din[BUF_LEN]; + + /* Set VLAN VID of port1 */ + ret = ksz8893m_read(din, Port1Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port1Control3, 4); + if (ret) + return ret; + + /* Set VLAN VID of port2 */ + ret = ksz8893m_read(din, Port2Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port2Control3, 4); + if (ret) + return ret; + + /* Set VLAN VID of port3 */ + ret = ksz8893m_read(din, Port3Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port3Control3, 4); + if (ret) + return ret; + + /* Insert VLAN tag that egress Port3 */ + ret = ksz8893m_read(din, Port3Control0, 3); + if (ret) + return ret; + dout[2] = TAG_INSERTION | din[2]; + ret = ksz8893m_write(dout, Port3Control0, 3); + if (ret) + return ret; + + /* Enable STPID Mode */ + ret = ksz8893m_read(din, GlobalControl9, 3); + if (ret) + return ret; + dout[2] = SPECIAL_TPID_MODE | din[2]; + ret = ksz8893m_write(dout, GlobalControl9, 3); + if (ret) + return ret; + + /* Start switch */ + dout[2] = START_SWITCH; + ret = ksz8893m_write(dout, ChipID1_StartSwitch, 3); + if (ret) + return ret; + + return 0; +} + +static int ksz8893m_setup_port(struct dsa_switch *ds, int p) +{ + int val, ret; + val = mdiobus_read(ds->master_mii_bus, p, MII_BMCR); + if (val < 0) + return val; + val |= AN_ENABLE | FORCE_100 | FORCE_FULL_DUPLEX; + val &= ~(POWER_DOWN | DISABLE_MDIX | DIS_FAR_END_FAULT |\ + DISABLE_TRANSMIT | DISABLE_LED); + ret = mdiobus_write(ds->master_mii_bus, p, MII_BMCR, val); + if (ret < 0) + return ret; + + val = mdiobus_read(ds->master_mii_bus, p, MII_ADVERTISE); + if (val < 0) + return val; + val |= ADV_10_HALF | ADV_10_FULL | ADV_100_HALF | ADV_100_FULL; + ret = mdiobus_write(ds->master_mii_bus, p, MII_ADVERTISE, val); + if (ret < 0) + return ret; + return 0; +} + +static int ksz8893m_setup(struct dsa_switch *ds) +{ + int i; + int ret; + + ret = ksz8893m_switch_reset(ds); + if (ret < 0) + return ret; + + ret = ksz8893m_setup_global(ds); + if (ret < 0) + return ret; + + for (i = 1; i < KSZ8893M_PORT_NUM; i++) { + ret = ksz8893m_setup_port(ds, i); + if (ret < 0) + return ret; + } + + return 0; +} + +static int ksz8893m_set_addr(struct dsa_switch *ds, u8 *addr) +{ + return 0; +} + +static int ksz8893m_port_to_phy_addr(int port) +{ + if (port >= 1 && port <= KSZ8893M_PORT_NUM) + return port; + + pr_warning("use default phy addr 3\n"); + return 3; +} + +static int +ksz8893m_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + int phy_addr = ksz8893m_port_to_phy_addr(port); + return mdiobus_read(ds->master_mii_bus, phy_addr, regnum); +} + +static int +ksz8893m_phy_write(struct dsa_switch *ds, + int port, int regnum, u16 val) +{ + int phy_addr = ksz8893m_port_to_phy_addr(port); + return mdiobus_write(ds->master_mii_bus, phy_addr, regnum, val); +} + +static void ksz8893m_poll_link(struct dsa_switch *ds) +{ + int i; + + for (i = 1; i < KSZ8893M_PORT_NUM; i++) { + struct net_device *dev; + int val; + int link; + int speed; + int duplex; + int anc; + + dev = ds->ports[i]; + if (dev == NULL) + continue; + + link = 0; + if (dev->flags & IFF_UP) { + val = mdiobus_read(ds->master_mii_bus, i, MII_BMSR); + if (val < 0) + continue; + + link = !!(val & LINK_STATUS); + anc = !!(val & AN_COMPLETE); + } + + if (!link) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link down\n", dev->name); + netif_carrier_off(dev); + } + continue; + } + + speed = 10; + duplex = 0; + val = mdiobus_read(ds->master_mii_bus, i, MII_BMSR); + if (val < 0) + continue; + val &= HALF_10_CAPABLE | FULL_10_CAPABLE |\ + HALF_100_CAPABLE | FULL_100_CAPABLE; + if (val & FULL_100_CAPABLE) { + speed = 100; + duplex = 1; + } else if (val & HALF_100_CAPABLE) { + speed = 100; + duplex = 0; + } else if (val & FULL_10_CAPABLE) { + speed = 10; + duplex = 1; + } + + if (!netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex\n", + dev->name, speed, duplex ? "full" : "half"); + netif_carrier_on(dev); + } + } +} + +static int __devinit spi_switch_probe(struct spi_device *spi) +{ + if (sw.dev) { + pr_err("only one instance supported at a time\n"); + return 1; + } + memset(&sw.xfer, 0, sizeof(sw.xfer)); + sw.dev = spi; + return 0; +} + +static int __devexit spi_switch_remove(struct spi_device *spi) +{ + sw.dev = NULL; + return 0; +} + +static struct spi_driver spi_switch_driver = { + .driver = { + .name = "ksz8893m", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = spi_switch_probe, + .remove = __devexit_p(spi_switch_remove), +}; + +static struct dsa_switch_driver ksz8893m_switch_driver = { + .tag_protocol = __constant_htons(ETH_P_STPID), + .probe = ksz8893m_probe, + .setup = ksz8893m_setup, + .set_addr = ksz8893m_set_addr, + .phy_read = ksz8893m_phy_read, + .phy_write = ksz8893m_phy_write, + .poll_link = ksz8893m_poll_link, +}; + +static int __init ksz8893m_init(void) +{ + int ret; + + ret = spi_register_driver(&spi_switch_driver); + if (ret) { + pr_err("can't register driver\n"); + return ret; + } + + register_switch_driver(&ksz8893m_switch_driver); + return 0; +} +module_init(ksz8893m_init); + +static void __exit ksz8893m_cleanup(void) +{ + spi_unregister_driver(&spi_switch_driver); + unregister_switch_driver(&ksz8893m_switch_driver); +} +module_exit(ksz8893m_cleanup); + +MODULE_AUTHOR("Graf Yang <graf.yang@analog.com>"); +MODULE_DESCRIPTION("KSZ8893M driver for DSA"); +MODULE_LICENSE("GPL"); diff --git a/net/dsa/ksz8893m.h b/net/dsa/ksz8893m.h new file mode 100644 index 0000000..84f44e9 --- /dev/null +++ b/net/dsa/ksz8893m.h @@ -0,0 +1,223 @@ +/* + * Integrated 3-Port 10/100 Managed Switch with PHYs + * + * - KSZ8893M support + * + * Copyright 2008-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __KSZ8893M_H__ +#define __KSZ8893M_H__ + +#include <linux/netdevice.h> + +#define KSZ8893M_PORT_NUM 3 +#define KSZ8893M_CPU_PORT 3 + +#define DEFAULT_PORT_VID 0 + +#define SPI_READ 3 +#define SPI_WRITE 2 + +/* PHYID High */ +#define PHYID_HIGH 0x22 +/* PHYID Low */ +#define PHYID_LOW 0x1430 + +/* MII Basic Control */ +#define SOFT_RESET 0x8000 +#define LOOPBACK 0x4000 +#define FORCE_100 0x2000 +#define AN_ENABLE 0x1000 +#define POWER_DOWN 0x0800 +#define ISOLATE 0x0400 +#define RESTART_AN 0x0200 +#define FORCE_FULL_DUPLEX 0x0100 +#define COLLISION_TEST 0x0080 +/* Bit Reserved */ +#define HP_MDIX 0x0020 +#define Force_MDI 0x0010 +#define DISABLE_MDIX 0x0008 +#define DIS_FAR_END_FAULT 0x0004 +#define DISABLE_TRANSMIT 0x0002 +#define DISABLE_LED 0x0001 + +/* MII Basic Status */ +#define T4_CAPABLE 0x8000 +#define FULL_100_CAPABLE 0x4000 +#define HALF_100_CAPABLE 0x2000 +#define FULL_10_CAPABLE 0x1000 +#define HALF_10_CAPABLE 0x0800 +/* 4 Bits Reserved */ +#define PREAMBLE_SUPPRESS 0x0040 +#define AN_COMPLETE 0x0020 +#define FAR_END_FAULT 0x0010 +#define AN_CAPABLE 0x0008 +#define LINK_STATUS 0x0004 +#define JABBER_TEST 0x0002 +#define EXTENDED_CAPABLE 0x0001 + +/* Auto-Negotiation Advertisement Ability */ +#define NEXT_PAGE 0x8000 +/* Bit Reserved */ +#define REMOTE_FAULT 0x2000 +/* 2 Bits Reserved */ +#define PAUSE 0x0400 +/* Bit Reserved */ +#define ADV_100_FULL 0x0100 +#define ADV_100_HALF 0x0080 +#define ADV_10_FULL 0x0040 +#define ADV_10_HALF 0x0020 +#define SELECTOR_FIELD 0x001F + +/* Auto-Negotiation Link Partner Ability */ +#define NEXT_PAGE 0x8000 +#define LP_ACK 0x4000 +#define REMOTE_FAULT 0x2000 +/* 2 Bits Reserved */ +#define PAUSE 0x0400 +/* Bit Reserved */ +#define ADV_100_FULL 0x0100 +#define ADV_100_HALF 0x0080 +#define ADV_10_FULL 0x0040 +#define ADV_10_HALF 0x0020 +/* 5 Bits Reserved */ + +/* LinkMD Control/Status */ +#define VCT_ENABLE 0x8000 +#define VCT_RESULT 0x6000 +#define VCT_10M_SHORT 0x1000 +/* 3 Bits Reserved */ +#define VCT_FAULT_COUNT 0x01FF + +/* PHY Special Control/Status */ +/* 10 Bits Reserved */ +#define POLRVS 0x0020 +#define MDI_X_STATUS 0x0010 +#define FORCE_LNK 0x0008 +#define PWRSAVE 0x0004 +#define REMOTE_LOOPBACK 0x0002 +/* Bit Reserved */ + + +#define FAMILY_ID 0x88 +#define START_SWITCH 0x01 +#define TAG_INSERTION 0x04 +#define SPECIAL_TPID_MODE 0x01 + + +enum switch_phy_reg { + /* Global Registers: 0-15 */ + ChipID0 = 0, + ChipID1_StartSwitch, + GlobalControl0, + GlobalControl1, + GlobalControl2, /* 4 */ + GlobalControl3, + GlobalControl4, + GlobalControl5, + GlobalControl6, /* 8 */ + GlobalControl7, + GlobalControl8, + GlobalControl9, + GlobalControl10, /* 12 */ + GlobalControl11, + GlobalControl12, + GlobalControl13, + /* Port Registers: 16-95 */ + Port1Control0 = 16, + Port1Control1, + Port1Control2, + Port1Control3, + Port1Control4, /* 20 */ + Port1Control5, + Port1Control6, + Port1Control7, + Port1Control8, /* 24 */ + Port1Control9, + Port1PHYSpecialControl_Status, + Port1LinkMDResult, + Port1Control12, /* 28 */ + Port1Control13, + Port1Status0, + Port1Status1, + Port2Control0, /* 32 */ + Port2Control1, + Port2Control2, + Port2Control3, + Port2Control4, /* 36 */ + Port2Control5, + Port2Control6, + Port2Control7, + Port2Control8, /* 40 */ + Port2Control9, + Port2PHYSpecialControl_Status, + Port2LinkMDResult, + Port2Control12, /* 44 */ + Port2Control13, + Port2Status0, + Port2Status1, + Port3Control0, /* 48 */ + Port3Control1, + Port3Control2, + Port3Control3, + Port3Control4, /* 52 */ + Port3Control5, + Port3Control6, + Port3Control7, + Port3Control8, /* 56 */ + Port3Control9, + Reservednotappliedtoport3, /* 58-62 */ + Port3Status1 = 63, + /* Advanced Control Registers: 96-141 */ + TOSPriorityControlRegister0 = 96, + TOSPriorityControlRegister1, + TOSPriorityControlRegister2, + TOSPriorityControlRegister3, + TOSPriorityControlRegister4, /* 100 */ + TOSPriorityControlRegister5, + TOSPriorityControlRegister6, + TOSPriorityControlRegister7, + TOSPriorityControlRegister8, /* 104 */ + TOSPriorityControlRegister9, + TOSPriorityControlRegister10, + TOSPriorityControlRegister11, + TOSPriorityControlRegister12, /* 108 */ + TOSPriorityControlRegister13, + TOSPriorityControlRegister14, + TOSPriorityControlRegister15, + MACAddressRegister0 = 112, + MACAddressRegister1, + MACAddressRegister2, + MACAddressRegister3, + MACAddressRegister4, + MACAddressRegister5, + UserDefinedRegister1 = 118, + UserDefinedRegister2, + UserDefinedRegister3, + IndirectAccessControl0 = 121, + IndirectAccessControl1, + IndirectDataRegister8 = 123, + IndirectDataRegister7, + IndirectDataRegister6, + IndirectDataRegister5, + IndirectDataRegister4, + IndirectDataRegister3, + IndirectDataRegister2, + IndirectDataRegister1, + IndirectDataRegister0, + DigitalTestingStatus0 = 132, + DigitalTestingControl0, + AnalogTestingControl0, + AnalogTestingControl1, + AnalogTestingControl2, + AnalogTestingControl3, + AnalogTestingStatus, + AnalogTestingControl4, + QMDebug1, + QMDebug2, +}; + +#endif -- 1.7.1.1 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 13:37 ` [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support Mike Frysinger @ 2010-07-21 15:16 ` Lennert Buytenhek 2010-07-21 15:33 ` Eric Dumazet ` (2 more replies) 2010-07-21 16:29 ` [PATCH 2/2 v2] " Mike Frysinger 1 sibling, 3 replies; 21+ messages in thread From: Lennert Buytenhek @ 2010-07-21 15:16 UTC (permalink / raw) To: Mike Frysinger Cc: netdev, David S. Miller, uclinux-dist-devel, Karl Beldan, Graf Yang, Bryan Wu On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: > From: Graf Yang <graf.yang@analog.com> Hurray for the first non-Marvell switch chip support in net/dsa! > +#define pr_fmt(fmt) "ksz8893m: " fmt This has no users. > +static int ksz8893m_setup(struct dsa_switch *ds) > +{ > + int i; > + int ret; > + > + ret = ksz8893m_switch_reset(ds); > + if (ret < 0) > + return ret; It's pretty ugly that the mdiobus is passed in via the normal means, but a reference to the SPI bus to use is just stuffed into some global variable. Can you not access all registers via MII? (If not, struct dsa_chip_data will need go be extended with another struct device pointer that we can use to find the spi bus with.) > +static int ksz8893m_port_to_phy_addr(int port) > +{ > + if (port >= 1 && port <= KSZ8893M_PORT_NUM) > + return port; > + > + pr_warning("use default phy addr 3\n"); > + return 3; Does this ever happen? You should just be able to return -1 here, IMHO. > +static int __devinit spi_switch_probe(struct spi_device *spi) > +{ > + if (sw.dev) { > + pr_err("only one instance supported at a time\n"); > + return 1; > + } > + memset(&sw.xfer, 0, sizeof(sw.xfer)); > + sw.dev = spi; > + return 0; > +} > + > +static int __devexit spi_switch_remove(struct spi_device *spi) > +{ > + sw.dev = NULL; > + return 0; > +} > + > +static struct spi_driver spi_switch_driver = { > + .driver = { > + .name = "ksz8893m", > + .bus = &spi_bus_type, > + .owner = THIS_MODULE, > + }, > + .probe = spi_switch_probe, > + .remove = __devexit_p(spi_switch_remove), > +}; I'm not entirely happy with this. Then again, there isn't really a clean way to deal with devices that have multiple different host interfaces as far as I know.. > +#define KSZ8893M_PORT_NUM 3 > +#define KSZ8893M_CPU_PORT 3 > + > +#define DEFAULT_PORT_VID 0 > + > +#define SPI_READ 3 > +#define SPI_WRITE 2 > > [snip] Something tells me that half the defines (and register index definitions) in this file aren't used. Also: > +/* MII Basic Control */ > +#define SOFT_RESET 0x8000 > +#define LOOPBACK 0x4000 > +#define FORCE_100 0x2000 > +#define AN_ENABLE 0x1000 > +#define POWER_DOWN 0x0800 > +#define ISOLATE 0x0400 > +#define RESTART_AN 0x0200 > +#define FORCE_FULL_DUPLEX 0x0100 > +#define COLLISION_TEST 0x0080 This part of the MII register is standard, and there are BMCR_* definitions for this in mii.h, no need to duplicate them. > +#define Force_MDI 0x0010 And please don't use mixed case. > +#define FAMILY_ID 0x88 > +#define START_SWITCH 0x01 > +#define TAG_INSERTION 0x04 > +#define SPECIAL_TPID_MODE 0x01 It would be nice to mention what registers these bitfields are part of. > +enum switch_phy_reg { > + /* Global Registers: 0-15 */ > + ChipID0 = 0, > + ChipID1_StartSwitch, > + GlobalControl0, And here, just define the registers you need only. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 15:16 ` Lennert Buytenhek @ 2010-07-21 15:33 ` Eric Dumazet 2010-07-21 15:36 ` Lennert Buytenhek 2010-07-21 16:40 ` Joe Perches 2010-07-21 16:05 ` [Uclinux-dist-devel] " Mike Frysinger [not found] ` <20100721151608.GM21121-SHk0+jKqY/D5VnbZ9m/NDkB+6BGkLq7r@public.gmane.org> 2 siblings, 2 replies; 21+ messages in thread From: Eric Dumazet @ 2010-07-21 15:33 UTC (permalink / raw) To: Lennert Buytenhek Cc: Mike Frysinger, netdev, David S. Miller, uclinux-dist-devel, Karl Beldan, Graf Yang, Bryan Wu Le mercredi 21 juillet 2010 à 17:16 +0200, Lennert Buytenhek a écrit : > > +#define pr_fmt(fmt) "ksz8893m: " fmt > > This has no users. > Dont tell this to Joe Perches ;) It is used by all pr_err() friends #define pr_emerg(fmt, ...) \ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) #define pr_alert(fmt, ...) \ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) #define pr_crit(fmt, ...) \ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) #define pr_err(fmt, ...) \ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 15:33 ` Eric Dumazet @ 2010-07-21 15:36 ` Lennert Buytenhek 2010-07-21 16:40 ` Joe Perches 1 sibling, 0 replies; 21+ messages in thread From: Lennert Buytenhek @ 2010-07-21 15:36 UTC (permalink / raw) To: Eric Dumazet Cc: Mike Frysinger, netdev, David S. Miller, uclinux-dist-devel, Karl Beldan, Graf Yang, Bryan Wu On Wed, Jul 21, 2010 at 05:33:13PM +0200, Eric Dumazet wrote: > > > +#define pr_fmt(fmt) "ksz8893m: " fmt > > > > This has no users. > > Dont tell this to Joe Perches ;) > > It is used by all pr_err() friends Oops, my bad! ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 15:33 ` Eric Dumazet 2010-07-21 15:36 ` Lennert Buytenhek @ 2010-07-21 16:40 ` Joe Perches 1 sibling, 0 replies; 21+ messages in thread From: Joe Perches @ 2010-07-21 16:40 UTC (permalink / raw) To: Eric Dumazet Cc: Lennert Buytenhek, Mike Frysinger, netdev, David S. Miller, uclinux-dist-devel, Karl Beldan, Graf Yang, Bryan Wu On Wed, 2010-07-21 at 17:33 +0200, Eric Dumazet wrote: > It is used by all pr_err() friends Shouldn't these drivers be moved into something like drivers/net/dsa/ rather than be kept in net? The #define pr_fmt would be more standard as #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt The printks could be netdev_<level> Suggested patches: diff --git a/net/dsa/ksz8893m.c b/net/dsa/ksz8893m.c index 98cce04..80fb0ac 100644 --- a/net/dsa/ksz8893m.c +++ b/net/dsa/ksz8893m.c @@ -8,7 +8,7 @@ * Licensed under the GPL-2 or later. */ -#define pr_fmt(fmt) "ksz8893m: " fmt +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/list.h> #include <linux/netdevice.h> @@ -42,11 +42,14 @@ static int ksz8893m_read(unsigned char *din, unsigned char reg, int len) spi_message_init(&message); spi_message_add_tail(t, &message); ret = spi_sync(sw.dev, &message); - if (!ret) - return message.status; + if (ret) { + pr_err("read reg%d failed, ret=%d\n", reg, ret); + return ret; + } + if (message.status) + pr_err("read reg%d failed, status=%d\n", reg, message.status); - pr_err("read reg%d failed, ret=%d\n", reg, ret); - return ret; + return message.status; } static int ksz8893m_write(unsigned char *dout, unsigned char reg, int len) @@ -65,11 +68,14 @@ static int ksz8893m_write(unsigned char *dout, unsigned char reg, int len) spi_message_init(&message); spi_message_add_tail(t, &message); ret = spi_sync(sw.dev, &message); - if (!ret) - return message.status; + if (ret) { + pr_err("write reg%d failed, ret=%d\n", reg, ret); + return ret; + } + if (message.status) + pr_err("write reg%d failed, status=%d\n", reg, message.status); - pr_err("write reg%d failed, ret=%d\n", reg, ret); - return ret; + return message.status; } static char *ksz8893m_probe(struct mii_bus *bus, int sw_addr) @@ -168,8 +174,8 @@ static int ksz8893m_setup_port(struct dsa_switch *ds, int p) if (val < 0) return val; val |= AN_ENABLE | FORCE_100 | FORCE_FULL_DUPLEX; - val &= ~(POWER_DOWN | DISABLE_MDIX | DIS_FAR_END_FAULT |\ - DISABLE_TRANSMIT | DISABLE_LED); + val &= ~(POWER_DOWN | DISABLE_MDIX | DIS_FAR_END_FAULT | + DISABLE_TRANSMIT | DISABLE_LED); ret = mdiobus_write(ds->master_mii_bus, p, MII_BMCR, val); if (ret < 0) return ret; @@ -228,8 +234,7 @@ ksz8893m_phy_read(struct dsa_switch *ds, int port, int regnum) } static int -ksz8893m_phy_write(struct dsa_switch *ds, - int port, int regnum, u16 val) +ksz8893m_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) { int phy_addr = ksz8893m_port_to_phy_addr(port); return mdiobus_write(ds->master_mii_bus, phy_addr, regnum, val); @@ -263,7 +268,7 @@ static void ksz8893m_poll_link(struct dsa_switch *ds) if (!link) { if (netif_carrier_ok(dev)) { - printk(KERN_INFO "%s: link down\n", dev->name); + netdev_info(dev, "link down\n"); netif_carrier_off(dev); } continue; @@ -274,8 +279,8 @@ static void ksz8893m_poll_link(struct dsa_switch *ds) val = mdiobus_read(ds->master_mii_bus, i, MII_BMSR); if (val < 0) continue; - val &= HALF_10_CAPABLE | FULL_10_CAPABLE |\ - HALF_100_CAPABLE | FULL_100_CAPABLE; + val &= (HALF_10_CAPABLE | FULL_10_CAPABLE | + HALF_100_CAPABLE | FULL_100_CAPABLE); if (val & FULL_100_CAPABLE) { speed = 100; duplex = 1; @@ -288,8 +293,8 @@ static void ksz8893m_poll_link(struct dsa_switch *ds) } if (!netif_carrier_ok(dev)) { - printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex\n", - dev->name, speed, duplex ? "full" : "half"); + netdev_info(dev, "link up, %d Mb/s, %s duplex\n", + speed, duplex ? "full" : "half"); netif_carrier_on(dev); } } ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 15:16 ` Lennert Buytenhek 2010-07-21 15:33 ` Eric Dumazet @ 2010-07-21 16:05 ` Mike Frysinger 2010-07-21 20:31 ` Karl Beldan [not found] ` <20100721151608.GM21121-SHk0+jKqY/D5VnbZ9m/NDkB+6BGkLq7r@public.gmane.org> 2 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 16:05 UTC (permalink / raw) To: Lennert Buytenhek Cc: Karl Beldan, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 11:16, Lennert Buytenhek wrote: > On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: >> +static int ksz8893m_setup(struct dsa_switch *ds) >> +{ >> + int i; >> + int ret; >> + >> + ret = ksz8893m_switch_reset(ds); >> + if (ret < 0) >> + return ret; > > It's pretty ugly that the mdiobus is passed in via the normal means, > but a reference to the SPI bus to use is just stuffed into some global > variable. > > Can you not access all registers via MII? it depends on the host mdio bus. if it supports the semi-standard behavior of toggling the OP field of MDIO frames, then yes, you can do it via MII. but i dont think the current mdio framework in the kernel keeps track of that functionality, so there isnt a way in the driver to say "is this possible, else fall back to SPI". certainly the part that was used to develop this driver does not support this behavior thus SPI is the only way of accessing the extended registers. i guess the driver could be extended so that people could pick which mode they want to program the registers via platform resources, but we have no way of testing that, so i say let the person who actually can use & wants that functionality implement it. > (If not, struct dsa_chip_data will need go be extended with another > struct device pointer that we can use to find the spi bus with.) if the framework supports, i can convert the driver to it, but i'm not sure we have the time atm to tackle reworking common frameworks. >> +static int ksz8893m_port_to_phy_addr(int port) >> +{ >> + if (port >= 1 && port <= KSZ8893M_PORT_NUM) >> + return port; >> + >> + pr_warning("use default phy addr 3\n"); >> + return 3; > > Does this ever happen? You should just be able to return -1 here, IMHO. i dont recall seeing a warning, but presumably if it it did occur, something else needs fixing. so -1 is OK. >> +/* MII Basic Control */ >> +#define SOFT_RESET 0x8000 >> +#define LOOPBACK 0x4000 >> +#define FORCE_100 0x2000 >> +#define AN_ENABLE 0x1000 >> +#define POWER_DOWN 0x0800 >> +#define ISOLATE 0x0400 >> +#define RESTART_AN 0x0200 >> +#define FORCE_FULL_DUPLEX 0x0100 >> +#define COLLISION_TEST 0x0080 > > This part of the MII register is standard, and there are BMCR_* > definitions for this in mii.h, no need to duplicate them. most are copies of the MII headers, so i just converted them all and punted the rest >> +#define FAMILY_ID 0x88 >> +#define START_SWITCH 0x01 >> +#define TAG_INSERTION 0x04 >> +#define SPECIAL_TPID_MODE 0x01 > > It would be nice to mention what registers these bitfields are part of. done >> +enum switch_phy_reg { >> + /* Global Registers: 0-15 */ >> + ChipID0 = 0, >> + ChipID1_StartSwitch, >> + GlobalControl0, > > And here, just define the registers you need only. i'm not sure that's necessary ... having the complete register layout is useful for people who want to extend in the future -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 16:05 ` [Uclinux-dist-devel] " Mike Frysinger @ 2010-07-21 20:31 ` Karl Beldan 2010-07-21 21:00 ` Mike Frysinger 0 siblings, 1 reply; 21+ messages in thread From: Karl Beldan @ 2010-07-21 20:31 UTC (permalink / raw) To: Mike Frysinger Cc: Lennert Buytenhek, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 6:05 PM, Mike Frysinger <vapier.adi@gmail.com> wrote: > On Wed, Jul 21, 2010 at 11:16, Lennert Buytenhek wrote: >> On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: >>> +static int ksz8893m_setup(struct dsa_switch *ds) >>> +{ >>> + int i; >>> + int ret; >>> + >>> + ret = ksz8893m_switch_reset(ds); >>> + if (ret < 0) >>> + return ret; >> >> It's pretty ugly that the mdiobus is passed in via the normal means, >> but a reference to the SPI bus to use is just stuffed into some global >> variable. >> >> Can you not access all registers via MII? > > it depends on the host mdio bus. if it supports the semi-standard > behavior of toggling the OP field of MDIO frames, then yes, you can do > it via MII. but i dont think the current mdio framework in the kernel > keeps track of that functionality, so there isnt a way in the driver > to say "is this possible, else fall back to SPI". > Are you referring to SMI ? > certainly the part that was used to develop this driver does not > support this behavior thus SPI is the only way of accessing the > extended registers. i guess the driver could be extended so that > people could pick which mode they want to program the registers via > platform resources, but we have no way of testing that, so i say let > the person who actually can use & wants that functionality implement > it. > >> (If not, struct dsa_chip_data will need go be extended with another >> struct device pointer that we can use to find the spi bus with.) > > if the framework supports, i can convert the driver to it, but i'm not > sure we have the time atm to tackle reworking common frameworks. > If someone tackles this, it would be nice that they bear in mind that phylib's drivers also need spi/smi/i2c register access. >>> +static int ksz8893m_port_to_phy_addr(int port) >>> +{ >>> + if (port >= 1 && port <= KSZ8893M_PORT_NUM) >>> + return port; >>> + >>> + pr_warning("use default phy addr 3\n"); >>> + return 3; >> >> Does this ever happen? You should just be able to return -1 here, IMHO. > > i dont recall seeing a warning, but presumably if it it did occur, > something else needs fixing. so -1 is OK. > I would remove this. -- Karl ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 20:31 ` Karl Beldan @ 2010-07-21 21:00 ` Mike Frysinger 2010-07-22 19:27 ` Karl Beldan 0 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 21:00 UTC (permalink / raw) To: Karl Beldan Cc: Lennert Buytenhek, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 16:31, Karl Beldan wrote: > On Wed, Jul 21, 2010 at 6:05 PM, Mike Frysinger wrote: >> On Wed, Jul 21, 2010 at 11:16, Lennert Buytenhek wrote: >>> On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: >>>> +static int ksz8893m_setup(struct dsa_switch *ds) >>>> +{ >>>> + int i; >>>> + int ret; >>>> + >>>> + ret = ksz8893m_switch_reset(ds); >>>> + if (ret < 0) >>>> + return ret; >>> >>> It's pretty ugly that the mdiobus is passed in via the normal means, >>> but a reference to the SPI bus to use is just stuffed into some global >>> variable. >>> >>> Can you not access all registers via MII? >> >> it depends on the host mdio bus. if it supports the semi-standard >> behavior of toggling the OP field of MDIO frames, then yes, you can do >> it via MII. but i dont think the current mdio framework in the kernel >> keeps track of that functionality, so there isnt a way in the driver >> to say "is this possible, else fall back to SPI". > > Are you referring to SMI ? that is the term the ksz datasheet uses (Serial Management Interface), but i'm not aware of it being a standardized term. even the ksz datasheet admits that its behavior is a bit non-standard. the Blackfin MAC doesnt support it so we have no way of testing the it as that is the MAC on the board with the ksz switch. -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 21:00 ` Mike Frysinger @ 2010-07-22 19:27 ` Karl Beldan 0 siblings, 0 replies; 21+ messages in thread From: Karl Beldan @ 2010-07-22 19:27 UTC (permalink / raw) To: Mike Frysinger Cc: Lennert Buytenhek, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 11:00 PM, Mike Frysinger <vapier.adi@gmail.com> wrote: > On Wed, Jul 21, 2010 at 16:31, Karl Beldan wrote: >> On Wed, Jul 21, 2010 at 6:05 PM, Mike Frysinger wrote: >>> On Wed, Jul 21, 2010 at 11:16, Lennert Buytenhek wrote: >>>> On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: >>>>> +static int ksz8893m_setup(struct dsa_switch *ds) >>>>> +{ >>>>> + int i; >>>>> + int ret; >>>>> + >>>>> + ret = ksz8893m_switch_reset(ds); >>>>> + if (ret < 0) >>>>> + return ret; >>>> >>>> It's pretty ugly that the mdiobus is passed in via the normal means, >>>> but a reference to the SPI bus to use is just stuffed into some global >>>> variable. >>>> >>>> Can you not access all registers via MII? >>> >>> it depends on the host mdio bus. if it supports the semi-standard >>> behavior of toggling the OP field of MDIO frames, then yes, you can do >>> it via MII. but i dont think the current mdio framework in the kernel >>> keeps track of that functionality, so there isnt a way in the driver >>> to say "is this possible, else fall back to SPI". >> >> Are you referring to SMI ? > > that is the term the ksz datasheet uses (Serial Management Interface), > but i'm not aware of it being a standardized term. even the ksz > datasheet admits that its behavior is a bit non-standard. the > Blackfin MAC doesnt support it so we have no way of testing the it as > that is the MAC on the board with the ksz switch. > Can't either, we don't even have mdio, only spi. Speaking of which, maybe you can replace this while you are at it : --- net/dsa/slave.c 2010-05-22 09:58:34.000000000 +0200 void dsa_slave_mii_bus_init(struct dsa_switch *ds) { ds->slave_mii_bus->priv = (void *)ds; - ds->slave_mii_bus->name = "dsa slave smi"; -- Karl ^ permalink raw reply [flat|nested] 21+ messages in thread
[parent not found: <20100721151608.GM21121-SHk0+jKqY/D5VnbZ9m/NDkB+6BGkLq7r@public.gmane.org>]
* Re: [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support [not found] ` <20100721151608.GM21121-SHk0+jKqY/D5VnbZ9m/NDkB+6BGkLq7r@public.gmane.org> @ 2010-07-21 17:23 ` David Miller 0 siblings, 0 replies; 21+ messages in thread From: David Miller @ 2010-07-21 17:23 UTC (permalink / raw) To: buytenh-OLH4Qvv75CYX/NnBR394Jw Cc: karl.beldan-Re5JQEeQqe8AvxtiuMwx3w, vapier-aBrp7R+bbdUdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA, graf.yang-OyLXuOCK7orQT0dZR+AlfA, uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b From: Lennert Buytenhek <buytenh-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org> Date: Wed, 21 Jul 2010 17:16:08 +0200 > On Wed, Jul 21, 2010 at 09:37:22AM -0400, Mike Frysinger wrote: > >> +#define pr_fmt(fmt) "ksz8893m: " fmt > > This has no users. egrep pr_fmt include/linux/kernel.h It feeds into all of the various kernel logging interfaces. ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 2/2 v2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 13:37 ` [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support Mike Frysinger 2010-07-21 15:16 ` Lennert Buytenhek @ 2010-07-21 16:29 ` Mike Frysinger 2010-07-21 20:45 ` Karl Beldan 1 sibling, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 16:29 UTC (permalink / raw) To: netdev, David S. Miller Cc: uclinux-dist-devel, Karl Beldan, Lennert Buytenhek, Graf Yang, Bryan Wu From: Graf Yang <graf.yang@analog.com> Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org> --- v2 - clean up header duplication net/dsa/Kconfig | 7 + net/dsa/Makefile | 1 + net/dsa/ksz8893m.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/ksz8893m.h | 163 +++++++++++++++++++++++++ 4 files changed, 512 insertions(+), 0 deletions(-) create mode 100644 net/dsa/ksz8893m.c create mode 100644 net/dsa/ksz8893m.h diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index ee8d705..4a87436 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -60,4 +60,11 @@ config NET_DSA_MV88E6123_61_65 This enables support for the Marvell 88E6123/6161/6165 ethernet switch chips. +config NET_DSA_KSZ8893M + bool "MICREL KSZ8893MQL/BL ethernet switch chip support" + select NET_DSA_TAG_STPID + ---help--- + This enables support for the Micrel KSZ8893MQL/BL + ethernet switch chips. + endif diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 4881577..c4295e3 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o +obj-$(CONFIG_NET_DSA_KSZ8893M) += ksz8893m.o # the core obj-$(CONFIG_NET_DSA) += dsa.o slave.o diff --git a/net/dsa/ksz8893m.c b/net/dsa/ksz8893m.c new file mode 100644 index 0000000..0bfa193 --- /dev/null +++ b/net/dsa/ksz8893m.c @@ -0,0 +1,341 @@ +/* + * Integrated 3-Port 10/100 Managed Switch with PHYs + * + * - KSZ8893M support + * + * Copyright 2008-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#define pr_fmt(fmt) "ksz8893m: " fmt + +#include <linux/list.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/spi/spi.h> +#include "dsa_priv.h" +#include "ksz8893m.h" + +#define BUF_LEN 6 + +static struct _spi_switch { + struct spi_transfer xfer; + struct spi_device *dev; +} sw; + +static int ksz8893m_read(unsigned char *din, unsigned char reg, int len) +{ + int i, ret; + struct spi_message message; + unsigned char dout[BUF_LEN]; + struct spi_transfer *t = &sw.xfer; + + t->len = len; + t->tx_buf = dout; + t->rx_buf = din; + dout[0] = SPI_READ; + dout[1] = reg; + for (i = 2; i < len; i++) + dout[i] = 0; + + spi_message_init(&message); + spi_message_add_tail(t, &message); + ret = spi_sync(sw.dev, &message); + if (!ret) + return message.status; + + pr_err("read reg%d failed, ret=%d\n", reg, ret); + return ret; +} + +static int ksz8893m_write(unsigned char *dout, unsigned char reg, int len) +{ + int ret; + struct spi_message message; + unsigned char din[BUF_LEN]; + struct spi_transfer *t = &sw.xfer; + + t->len = len; + t->tx_buf = dout; + t->rx_buf = din; + dout[0] = SPI_WRITE; + dout[1] = reg; + + spi_message_init(&message); + spi_message_add_tail(t, &message); + ret = spi_sync(sw.dev, &message); + if (!ret) + return message.status; + + pr_err("write reg%d failed, ret=%d\n", reg, ret); + return ret; +} + +static char *ksz8893m_probe(struct mii_bus *bus, int sw_addr) +{ + int ret, phyid_low, phyid_high; + unsigned char din[BUF_LEN]; + + phyid_high = mdiobus_read(bus, KSZ8893M_CPU_PORT, MII_PHYSID1); + phyid_low = mdiobus_read(bus, KSZ8893M_CPU_PORT, MII_PHYSID2); + if (phyid_high != PHYID_HIGH || phyid_low != PHYID_LOW) + return NULL; + + ret = ksz8893m_read(din, ChipID0, 3); + + if (!ret && FAMILY_ID == din[2]) + return "KSZ8893M"; + + return NULL; +} + +static int ksz8893m_switch_reset(struct dsa_switch *ds) +{ + return 0; +} + +static int ksz8893m_setup_global(struct dsa_switch *ds) +{ + int ret; + unsigned char dout[BUF_LEN]; + unsigned char din[BUF_LEN]; + + /* Set VLAN VID of port1 */ + ret = ksz8893m_read(din, Port1Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port1Control3, 4); + if (ret) + return ret; + + /* Set VLAN VID of port2 */ + ret = ksz8893m_read(din, Port2Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port2Control3, 4); + if (ret) + return ret; + + /* Set VLAN VID of port3 */ + ret = ksz8893m_read(din, Port3Control3, 3); + if (ret) + return ret; + din[2] &= 0xf0; + dout[2] = (DEFAULT_PORT_VID & 0xfff) >> 8 | din[2]; + dout[3] = DEFAULT_PORT_VID & 0xff; + ret = ksz8893m_write(dout, Port3Control3, 4); + if (ret) + return ret; + + /* Insert VLAN tag that egress Port3 */ + ret = ksz8893m_read(din, Port3Control0, 3); + if (ret) + return ret; + dout[2] = TAG_INSERTION | din[2]; + ret = ksz8893m_write(dout, Port3Control0, 3); + if (ret) + return ret; + + /* Enable STPID Mode */ + ret = ksz8893m_read(din, GlobalControl9, 3); + if (ret) + return ret; + dout[2] = SPECIAL_TPID_MODE | din[2]; + ret = ksz8893m_write(dout, GlobalControl9, 3); + if (ret) + return ret; + + /* Start switch */ + dout[2] = START_SWITCH; + ret = ksz8893m_write(dout, ChipID1_StartSwitch, 3); + if (ret) + return ret; + + return 0; +} + +static int ksz8893m_setup_port(struct dsa_switch *ds, int p) +{ + int val, ret; + val = mdiobus_read(ds->master_mii_bus, p, MII_BMCR); + if (val < 0) + return val; + val |= BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX; + val &= ~(BMCR_PDOWN | DISABLE_MDIX | DIS_FAR_END_FAULT | + DISABLE_TRANSMIT | DISABLE_LED); + ret = mdiobus_write(ds->master_mii_bus, p, MII_BMCR, val); + if (ret < 0) + return ret; + + val = mdiobus_read(ds->master_mii_bus, p, MII_ADVERTISE); + if (val < 0) + return val; + val |= ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL; + ret = mdiobus_write(ds->master_mii_bus, p, MII_ADVERTISE, val); + if (ret < 0) + return ret; + return 0; +} + +static int ksz8893m_setup(struct dsa_switch *ds) +{ + int i; + int ret; + + ret = ksz8893m_switch_reset(ds); + if (ret < 0) + return ret; + + ret = ksz8893m_setup_global(ds); + if (ret < 0) + return ret; + + for (i = 1; i < KSZ8893M_PORT_NUM; i++) { + ret = ksz8893m_setup_port(ds, i); + if (ret < 0) + return ret; + } + + return 0; +} + +static int ksz8893m_set_addr(struct dsa_switch *ds, u8 *addr) +{ + return 0; +} + +static int ksz8893m_port_to_phy_addr(int port) +{ + if (port >= 1 && port <= KSZ8893M_PORT_NUM) + return port; + return -1; +} + +static int +ksz8893m_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + int phy_addr = ksz8893m_port_to_phy_addr(port); + return mdiobus_read(ds->master_mii_bus, phy_addr, regnum); +} + +static int +ksz8893m_phy_write(struct dsa_switch *ds, + int port, int regnum, u16 val) +{ + int phy_addr = ksz8893m_port_to_phy_addr(port); + return mdiobus_write(ds->master_mii_bus, phy_addr, regnum, val); +} + +static void ksz8893m_poll_link(struct dsa_switch *ds) +{ + int i; + + for (i = 1; i < KSZ8893M_PORT_NUM; i++) { + struct net_device *dev; + int val, link; + + dev = ds->ports[i]; + if (dev == NULL) + continue; + + link = 0; + if (dev->flags & IFF_UP) { + val = mdiobus_read(ds->master_mii_bus, i, MII_BMSR); + if (val < 0) + continue; + + link = val & BMSR_LSTATUS; + } + + if (!link) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link down\n", dev->name); + netif_carrier_off(dev); + } + continue; + } + + val = mdiobus_read(ds->master_mii_bus, i, MII_BMSR); + if (val < 0) + continue; + + if (!netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex\n", + dev->name, + (val & LPA_100) ? 100 : 10, + (val & LPA_DUPLEX) ? "half" : "full"); + netif_carrier_on(dev); + } + } +} + +static int __devinit spi_switch_probe(struct spi_device *spi) +{ + if (sw.dev) { + pr_err("only one instance supported at a time\n"); + return 1; + } + memset(&sw.xfer, 0, sizeof(sw.xfer)); + sw.dev = spi; + return 0; +} + +static int __devexit spi_switch_remove(struct spi_device *spi) +{ + sw.dev = NULL; + return 0; +} + +static struct spi_driver spi_switch_driver = { + .driver = { + .name = "ksz8893m", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = spi_switch_probe, + .remove = __devexit_p(spi_switch_remove), +}; + +static struct dsa_switch_driver ksz8893m_switch_driver = { + .tag_protocol = __constant_htons(ETH_P_STPID), + .probe = ksz8893m_probe, + .setup = ksz8893m_setup, + .set_addr = ksz8893m_set_addr, + .phy_read = ksz8893m_phy_read, + .phy_write = ksz8893m_phy_write, + .poll_link = ksz8893m_poll_link, +}; + +static int __init ksz8893m_init(void) +{ + int ret; + + ret = spi_register_driver(&spi_switch_driver); + if (ret) { + pr_err("can't register driver\n"); + return ret; + } + + register_switch_driver(&ksz8893m_switch_driver); + return 0; +} +module_init(ksz8893m_init); + +static void __exit ksz8893m_cleanup(void) +{ + spi_unregister_driver(&spi_switch_driver); + unregister_switch_driver(&ksz8893m_switch_driver); +} +module_exit(ksz8893m_cleanup); + +MODULE_AUTHOR("Graf Yang <graf.yang@analog.com>"); +MODULE_DESCRIPTION("KSZ8893M driver for DSA"); +MODULE_LICENSE("GPL"); diff --git a/net/dsa/ksz8893m.h b/net/dsa/ksz8893m.h new file mode 100644 index 0000000..30e0df0 --- /dev/null +++ b/net/dsa/ksz8893m.h @@ -0,0 +1,163 @@ +/* + * Integrated 3-Port 10/100 Managed Switch with PHYs + * + * - KSZ8893M support + * + * Copyright 2008-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __KSZ8893M_H__ +#define __KSZ8893M_H__ + +#define KSZ8893M_PORT_NUM 3 +#define KSZ8893M_CPU_PORT 3 + +#define DEFAULT_PORT_VID 0 + +/* Simple SPI command set for poking registers */ +#define SPI_READ 3 +#define SPI_WRITE 2 + +/* Expected value for MII_PHYSID1 */ +#define PHYID_HIGH 0x22 +/* Expected value for MII_PHYSID2 */ +#define PHYID_LOW 0x1430 + +/* ChipID0 defines */ +#define FAMILY_ID 0x88 + +/* ChipID1_StartSwitch defines */ +#define START_SWITCH 0x01 + +/* Port3Control0 defines */ +#define TAG_INSERTION 0x04 + +/* GlobalControl9 defines */ +#define SPECIAL_TPID_MODE 0x01 + +/* BMCR Reserved Bits */ +#define HP_MDIX 0x0020 +#define FORCE_MDI 0x0010 +#define DISABLE_MDIX 0x0008 +#define DIS_FAR_END_FAULT 0x0004 +#define DISABLE_TRANSMIT 0x0002 +#define DISABLE_LED 0x0001 + +/* BMSCR Reserved Bits */ +#define PREAMBLE_SUPPRESS 0x0040 + +enum switch_phy_reg { + /* Global Registers: 0-15 */ + ChipID0 = 0, + ChipID1_StartSwitch, + GlobalControl0, + GlobalControl1, + GlobalControl2, /* 4 */ + GlobalControl3, + GlobalControl4, + GlobalControl5, + GlobalControl6, /* 8 */ + GlobalControl7, + GlobalControl8, + GlobalControl9, + GlobalControl10, /* 12 */ + GlobalControl11, + GlobalControl12, + GlobalControl13, + /* Port Registers: 16-95 */ + Port1Control0 = 16, + Port1Control1, + Port1Control2, + Port1Control3, + Port1Control4, /* 20 */ + Port1Control5, + Port1Control6, + Port1Control7, + Port1Control8, /* 24 */ + Port1Control9, + Port1PHYSpecialControl_Status, + Port1LinkMDResult, + Port1Control12, /* 28 */ + Port1Control13, + Port1Status0, + Port1Status1, + Port2Control0, /* 32 */ + Port2Control1, + Port2Control2, + Port2Control3, + Port2Control4, /* 36 */ + Port2Control5, + Port2Control6, + Port2Control7, + Port2Control8, /* 40 */ + Port2Control9, + Port2PHYSpecialControl_Status, + Port2LinkMDResult, + Port2Control12, /* 44 */ + Port2Control13, + Port2Status0, + Port2Status1, + Port3Control0, /* 48 */ + Port3Control1, + Port3Control2, + Port3Control3, + Port3Control4, /* 52 */ + Port3Control5, + Port3Control6, + Port3Control7, + Port3Control8, /* 56 */ + Port3Control9, + Reservednotappliedtoport3, /* 58-62 */ + Port3Status1 = 63, + /* Advanced Control Registers: 96-141 */ + TOSPriorityControlRegister0 = 96, + TOSPriorityControlRegister1, + TOSPriorityControlRegister2, + TOSPriorityControlRegister3, + TOSPriorityControlRegister4, /* 100 */ + TOSPriorityControlRegister5, + TOSPriorityControlRegister6, + TOSPriorityControlRegister7, + TOSPriorityControlRegister8, /* 104 */ + TOSPriorityControlRegister9, + TOSPriorityControlRegister10, + TOSPriorityControlRegister11, + TOSPriorityControlRegister12, /* 108 */ + TOSPriorityControlRegister13, + TOSPriorityControlRegister14, + TOSPriorityControlRegister15, + MACAddressRegister0 = 112, + MACAddressRegister1, + MACAddressRegister2, + MACAddressRegister3, + MACAddressRegister4, + MACAddressRegister5, + UserDefinedRegister1 = 118, + UserDefinedRegister2, + UserDefinedRegister3, + IndirectAccessControl0 = 121, + IndirectAccessControl1, + IndirectDataRegister8 = 123, + IndirectDataRegister7, + IndirectDataRegister6, + IndirectDataRegister5, + IndirectDataRegister4, + IndirectDataRegister3, + IndirectDataRegister2, + IndirectDataRegister1, + IndirectDataRegister0, + DigitalTestingStatus0 = 132, + DigitalTestingControl0, + AnalogTestingControl0, + AnalogTestingControl1, + AnalogTestingControl2, + AnalogTestingControl3, + AnalogTestingStatus, + AnalogTestingControl4, + QMDebug1, + QMDebug2, +}; + +#endif -- 1.7.1.1 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2 v2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support 2010-07-21 16:29 ` [PATCH 2/2 v2] " Mike Frysinger @ 2010-07-21 20:45 ` Karl Beldan 0 siblings, 0 replies; 21+ messages in thread From: Karl Beldan @ 2010-07-21 20:45 UTC (permalink / raw) To: Mike Frysinger Cc: netdev, David S. Miller, uclinux-dist-devel, Lennert Buytenhek, Graf Yang, Bryan Wu On 7/21/10, Mike Frysinger <vapier@gentoo.org> wrote: [...] > net/dsa/Kconfig | 7 + > net/dsa/Makefile | 1 + > net/dsa/ksz8893m.c | 341 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/dsa/ksz8893m.h | 163 +++++++++++++++++++++++++ > 4 files changed, 512 insertions(+), 0 deletions(-) > create mode 100644 net/dsa/ksz8893m.c > create mode 100644 net/dsa/ksz8893m.h > [...] > +/* Port3Control0 defines */ > +#define TAG_INSERTION 0x04 > + > +/* GlobalControl9 defines */ > +#define SPECIAL_TPID_MODE 0x01 > + How about prefixes like 'PC0_' (PortControl0) ? -- Karl ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-21 13:37 [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Mike Frysinger 2010-07-21 13:37 ` [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support Mike Frysinger @ 2010-07-21 15:02 ` Lennert Buytenhek 2010-07-21 15:29 ` [Uclinux-dist-devel] " Mike Frysinger 1 sibling, 1 reply; 21+ messages in thread From: Lennert Buytenhek @ 2010-07-21 15:02 UTC (permalink / raw) To: Mike Frysinger Cc: netdev, David S. Miller, uclinux-dist-devel, Karl Beldan, Graf Yang, Bryan Wu On Wed, Jul 21, 2010 at 09:37:21AM -0400, Mike Frysinger wrote: > diff --git a/net/dsa/tag_stpid.c b/net/dsa/tag_stpid.c > new file mode 100644 > index 0000000..b5d9829 > --- /dev/null > +++ b/net/dsa/tag_stpid.c > @@ -0,0 +1,147 @@ > +/* > + * net/dsa/tag_stpid.c - special tag identifier, > + * 0x810 + 4 bit "port mask" + 3 bit 8021p + 1 bit CFI + 12 bit VLAN ID > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > + > +#include <linux/etherdevice.h> > +#include <linux/list.h> > +#include <linux/netdevice.h> > +#include "dsa_priv.h" > + > +#define ETH_P_8021QH (ETH_P_8021Q >> 8) > +#define ETH_P_8021QL (ETH_P_8021Q & 0xFF) > +#define STPID_HLEN 4 > + > +#define ZERO_VID 0 > +#define RESERVED_VID 0xFFF > +#define STPID_VID ZERO_VID > + > +int stpid_xmit(struct sk_buff *skb, struct net_device *dev) > +{ > + struct dsa_slave_priv *p = netdev_priv(dev); > + u8 *dsa_header; > + > + dev->stats.tx_packets++; > + dev->stats.tx_bytes += skb->len; Everything up to this point looks OK, but.. > + /* > + * For 802.1Q frames, convert to STPID tagged frames, > + * do nothing for common frames. > + */ > + if (skb->protocol == htons(ETH_P_8021Q)) { > + if (skb_cow_head(skb, 0) < 0) > + goto out_free; > + > + dsa_header = skb->data + 2 * ETH_ALEN; > + dsa_header[1] = p->port & 0x03; > + } This is almost certainly wrong -- according to the KSZ8893ML datasheet, this means that VLAN tagged frames will be switched explicitly (by sending them to p->port), but non-VLAN tagged frames will be switched according to the switch's MAC address database. You want explicit (i.e. host kernel-side MAC address database lookup) switching in both cases. > +{ > + struct dsa_switch_tree *dst = dev->dsa_ptr; > + struct dsa_switch *ds = dst->ds[0]; > + u8 *dsa_header; > + int source_port; > + int vid; > + > + if (unlikely(ds == NULL)) > + goto out_drop; > + > + skb = skb_unshare(skb, GFP_ATOMIC); > + if (skb == NULL) > + goto out; > + > + /* The ether_head has been pulled by master driver */ > + dsa_header = skb->data - 2; > + > + vid = ((dsa_header[2] & 0x0f)<<8 | dsa_header[3]); Coding style (need spaces around '<<'). > + > + source_port = dsa_header[1] & 0x03; > + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) > + goto out_drop; > + > + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && This is bogus -- what it does is: if ((dsa_header[0] & 0x81) == 0x81) It doesn't look like you need to mask here at all. ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-21 15:02 ` [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Lennert Buytenhek @ 2010-07-21 15:29 ` Mike Frysinger 2010-07-21 15:35 ` Lennert Buytenhek 0 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 15:29 UTC (permalink / raw) To: Lennert Buytenhek Cc: Karl Beldan, netdev, Graf Yang, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 11:02, Lennert Buytenhek wrote: > On Wed, Jul 21, 2010 at 09:37:21AM -0400, Mike Frysinger wrote: >> + source_port = dsa_header[1] & 0x03; >> + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) >> + goto out_drop; >> + >> + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && > > This is bogus -- what it does is: > > if ((dsa_header[0] & 0x81) == 0x81) > > It doesn't look like you need to mask here at all. where does it say dsa_header[0] will always have 0x81 set ? -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-21 15:29 ` [Uclinux-dist-devel] " Mike Frysinger @ 2010-07-21 15:35 ` Lennert Buytenhek 2010-07-21 16:08 ` Mike Frysinger 0 siblings, 1 reply; 21+ messages in thread From: Lennert Buytenhek @ 2010-07-21 15:35 UTC (permalink / raw) To: Mike Frysinger Cc: Karl Beldan, netdev, Graf Yang, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 11:29:30AM -0400, Mike Frysinger wrote: > >> + source_port = dsa_header[1] & 0x03; > >> + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) > >> + goto out_drop; > >> + > >> + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && > > > > This is bogus -- what it does is: > > > > if ((dsa_header[0] & 0x81) == 0x81) > > > > It doesn't look like you need to mask here at all. > > where does it say dsa_header[0] will always have 0x81 set ? Eh? This code is checking whether the packet has a STPID tag on it or not. A STPID tag exists if the first 12 nibbles are 0x810. You are checking whether the first 8 nibbles of this are equal to 0x81 by doing: if ((byte & 0x81) == 0x81) What if the first byte is 0x93? Or 0xc5? ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-21 15:35 ` Lennert Buytenhek @ 2010-07-21 16:08 ` Mike Frysinger 2010-07-29 17:50 ` Mike Frysinger 0 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-21 16:08 UTC (permalink / raw) To: Lennert Buytenhek Cc: Karl Beldan, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 11:35, Lennert Buytenhek wrote: > On Wed, Jul 21, 2010 at 11:29:30AM -0400, Mike Frysinger wrote: >> >> + source_port = dsa_header[1] & 0x03; >> >> + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) >> >> + goto out_drop; >> >> + >> >> + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && >> > >> > This is bogus -- what it does is: >> > >> > if ((dsa_header[0] & 0x81) == 0x81) >> > >> > It doesn't look like you need to mask here at all. >> >> where does it say dsa_header[0] will always have 0x81 set ? > > Eh? > > This code is checking whether the packet has a STPID tag on it or not. > A STPID tag exists if the first 12 nibbles are 0x810. > > You are checking whether the first 8 nibbles of this are equal to 0x81 > by doing: > > if ((byte & 0x81) == 0x81) > > What if the first byte is 0x93? Or 0xc5? that was my point. should it be masking or doing a raw compare ? i have nfc as i had nothing to do with the creation of this code. i dont know the first thing about VLAN tags or anything else at that level. -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-21 16:08 ` Mike Frysinger @ 2010-07-29 17:50 ` Mike Frysinger 2010-08-10 14:05 ` Lennert Buytenhek 0 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-07-29 17:50 UTC (permalink / raw) To: Lennert Buytenhek Cc: Karl Beldan, netdev, uclinux-dist-devel, David S. Miller On Wed, Jul 21, 2010 at 12:08, Mike Frysinger wrote: > On Wed, Jul 21, 2010 at 11:35, Lennert Buytenhek wrote: >> On Wed, Jul 21, 2010 at 11:29:30AM -0400, Mike Frysinger wrote: >>> >> + source_port = dsa_header[1] & 0x03; >>> >> + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) >>> >> + goto out_drop; >>> >> + >>> >> + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && >>> > >>> > This is bogus -- what it does is: >>> > >>> > if ((dsa_header[0] & 0x81) == 0x81) >>> > >>> > It doesn't look like you need to mask here at all. >>> >>> where does it say dsa_header[0] will always have 0x81 set ? >> >> Eh? >> >> This code is checking whether the packet has a STPID tag on it or not. >> A STPID tag exists if the first 12 nibbles are 0x810. >> >> You are checking whether the first 8 nibbles of this are equal to 0x81 >> by doing: >> >> if ((byte & 0x81) == 0x81) >> >> What if the first byte is 0x93? Or 0xc5? > > that was my point. should it be masking or doing a raw compare ? and the answer is ... ? so i can send an updated patch ;) -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-07-29 17:50 ` Mike Frysinger @ 2010-08-10 14:05 ` Lennert Buytenhek 2010-08-10 17:04 ` Mike Frysinger 0 siblings, 1 reply; 21+ messages in thread From: Lennert Buytenhek @ 2010-08-10 14:05 UTC (permalink / raw) To: Mike Frysinger; +Cc: Karl Beldan, netdev, uclinux-dist-devel On Thu, Jul 29, 2010 at 01:50:45PM -0400, Mike Frysinger wrote: > >>> >> + source_port = dsa_header[1] & 0x03; > >>> >> + if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) > >>> >> + goto out_drop; > >>> >> + > >>> >> + if (((dsa_header[0] & ETH_P_8021QH) == ETH_P_8021QH) && > >>> > > >>> > This is bogus -- what it does is: > >>> > > >>> > if ((dsa_header[0] & 0x81) == 0x81) > >>> > > >>> > It doesn't look like you need to mask here at all. > >>> > >>> where does it say dsa_header[0] will always have 0x81 set ? > >> > >> Eh? > >> > >> This code is checking whether the packet has a STPID tag on it or not. > >> A STPID tag exists if the first 12 nibbles are 0x810. > >> > >> You are checking whether the first 8 nibbles of this are equal to 0x81 > >> by doing: > >> > >> if ((byte & 0x81) == 0x81) > >> > >> What if the first byte is 0x93? Or 0xc5? > > > > that was my point. should it be masking or doing a raw compare ? > > and the answer is ... ? so i can send an updated patch ;) From what I understand, you should just be checking for equality with 0x81 in the first byte, as that is what indicates presence of the STPID tag. Is the hardware you're doing this on available somewhere for me to try things out on? ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-08-10 14:05 ` Lennert Buytenhek @ 2010-08-10 17:04 ` Mike Frysinger 2010-08-12 22:38 ` Mike Frysinger 0 siblings, 1 reply; 21+ messages in thread From: Mike Frysinger @ 2010-08-10 17:04 UTC (permalink / raw) To: Lennert Buytenhek; +Cc: Karl Beldan, netdev, uclinux-dist-devel On Tue, Aug 10, 2010 at 10:05, Lennert Buytenhek wrote: > Is the hardware you're doing this on available somewhere for me to > try things out on? yes & no. the board in question is here (that picture has two ethernet ports): http://www.analog.com/en/embedded-processing-dsp/blackfin/BF518-EZBRD/processors/product.html but that was the first few revs of the board ... later ones have dropped the switch because it didnt support PTP packets. i dont think you can specify "give me an older rev" when ordering from ADI. if you're interested, i can probably find you an older one laying around if you're interested in testing things. -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [Uclinux-dist-devel] [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code 2010-08-10 17:04 ` Mike Frysinger @ 2010-08-12 22:38 ` Mike Frysinger 0 siblings, 0 replies; 21+ messages in thread From: Mike Frysinger @ 2010-08-12 22:38 UTC (permalink / raw) To: Lennert Buytenhek; +Cc: Karl Beldan, netdev, uclinux-dist-devel On Tue, Aug 10, 2010 at 13:04, Mike Frysinger wrote: > On Tue, Aug 10, 2010 at 10:05, Lennert Buytenhek wrote: >> Is the hardware you're doing this on available somewhere for me to >> try things out on? > > if you're interested, i can probably find you an older one laying > around if you're interested in testing things. hrm, too many "interested" in that sentence ... at any rate, i'm implying you'd get the board for free if that makes a difference to you -mike ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2010-08-12 22:39 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-07-21 13:37 [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Mike Frysinger 2010-07-21 13:37 ` [PATCH 2/2] net: dsa: introduce MICREL KSZ8893MQL/BL ethernet switch chip support Mike Frysinger 2010-07-21 15:16 ` Lennert Buytenhek 2010-07-21 15:33 ` Eric Dumazet 2010-07-21 15:36 ` Lennert Buytenhek 2010-07-21 16:40 ` Joe Perches 2010-07-21 16:05 ` [Uclinux-dist-devel] " Mike Frysinger 2010-07-21 20:31 ` Karl Beldan 2010-07-21 21:00 ` Mike Frysinger 2010-07-22 19:27 ` Karl Beldan [not found] ` <20100721151608.GM21121-SHk0+jKqY/D5VnbZ9m/NDkB+6BGkLq7r@public.gmane.org> 2010-07-21 17:23 ` David Miller 2010-07-21 16:29 ` [PATCH 2/2 v2] " Mike Frysinger 2010-07-21 20:45 ` Karl Beldan 2010-07-21 15:02 ` [PATCH 1/2] net: dsa: introduce STPID switch tagging handling code Lennert Buytenhek 2010-07-21 15:29 ` [Uclinux-dist-devel] " Mike Frysinger 2010-07-21 15:35 ` Lennert Buytenhek 2010-07-21 16:08 ` Mike Frysinger 2010-07-29 17:50 ` Mike Frysinger 2010-08-10 14:05 ` Lennert Buytenhek 2010-08-10 17:04 ` Mike Frysinger 2010-08-12 22:38 ` Mike Frysinger
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).