[OpenWrt-Devel] [PATCH 3/3] b53: create slave devices for ports

Charlie Smurthwaite charlie at atechmedia.com
Thu Feb 26 15:02:27 EST 2015


I'm also very interested in implementing a switchdev driver (seems to be 
a good direction for this type of work), so I'd like to see any efforts 
in this direction so far which I can use as a base for my driver. I was 
waiting for the switch to Linux 3.19 for the initial code be be easily 
available.

Charlie


On 26/02/15 19:58, Alexandru Ardelean wrote:
> Fully agree on converging.
> I missed Rafal's switchdev effort.
>
> Before starting on this work, I first tried to look into net/dsa in 
> the Linux kernel.
> I did notice your patches there and started on that.
> I got to a decent point, but then I was stuck at some issues.
> I later found out that I needed to adjust the MTU and manually pad 
> potential runt packets.
>
> I also found out the switchdev API, which seems like it's in an rather 
> infant state.
>
> In any case, I think DSA is the better approach, so my vote is for b53 
> + DSA (or DSA-like) in the kernel.
>
> For this swconfig effort, the reasoning is that our current firmware 
> is @ kernel 3.10, and most of our current target setup logic relies on 
> swconfig; I backported DSA, but because of time/effort constraints to 
> also port, test & validate any b53 PHY setup logic in DSA, we decided 
> that it's easier to adapt the current b53 driver, and later re-visit DSA.
> And because we have time constraints, there's no telling if we'll have 
> the time to port b53 to DSA, so this patchset is at least meant to 
> share our effort/findings regarding the b53 + LAN ports + Broadcom tag.
> If things get settled/more calm, I might try to do an effort to do b53 
> + DSA (if nobody does that before me).
>
> Regarding this patchset, I have no objections regarding whether it 
> gets accepted/dropped.
> Either way, we'll keep it in our tree for a while, and re-evaluate any 
> other DSA (or DSA-like) frameworks later.
>
> Thanks
> Alex
>
> On Thu, Feb 26, 2015 at 8:24 PM, Florian Fainelli 
> <f.fainelli at gmail.com <mailto:f.fainelli at gmail.com>> wrote:
>
>     On 25/02/15 07:24, Alexandru Ardelean wrote:
>     > Feature implemented and tested on BCM53128.
>     >
>     > Slave devices logic copied from the Linux kernel from Marvell's DSA
>     > driver ( linux/net/dsa/ ).
>     > Also the logic for the Broadcom tag processing has been copied
>     from there.
>
>     There are different efforts here going on, and I would like to at
>     least
>     3 different people (you, Rafal and myself) can converge to an
>     identical
>     solution that fits everybody here.
>
>     What net-next supports today is:
>
>     - broadcom tags in net/dsa/tag_brcm.c, 4-bytes format, identical to
>     yours AFAICT
>     - HW bridging support for bcm_sf2 (roboswitch successor)
>
>     What's missing:
>     - adding VLAN configuration, which is what Rafal has been doing using
>     here: http://thread.gmane.org/gmane.linux.network/351503
>
>     There are a number of things that I want to rework in DSA such that we
>     can almost immediately leverage OpenWrt's switch drivers, where the
>     entry point is a phy_driver, and have them register as switches
>     (DSA or
>     something wider) eventually [1], such that DSA handles the slave
>     devices
>     creation, and also handles the transmission/reception of Broadcom tags
>     for us. This is work in progress, but I expect the patches would be
>     ready by the end of this week.
>
>     [1]: http://www.spinics.net/lists/netdev/msg295942.html
>
>     >
>     > OpenWRT's eth_mangle_rx/tx() patch/code is being used to tap into
>     > the packets to/from the ethernet chip since it's convenient.
>     >
>     > This code will create lanX (X = 1..B53_N_PORTS) devices.
>     > All traffic from the ethX device will be forwarded the proper
>     lanX device.
>     > So, sw_port0_traffic == lan1_traffic and so on.
>     >
>     > The slave devices logic has been put into it's own file.
>     > Should this logic be desired to be extended to swconfig or other
>     > switch chips, it should be convenient to just move the slave.c/h
>     files.
>     >
>     > Note: if enable_vlan == 1, be sure to configure VLAN per lanX device
>     >       in '/etc/config/network'
>     >
>     > Signed-off-by: Alexandru Ardelean <ardeleanalex at gmail.com
>     <mailto:ardeleanalex at gmail.com>>
>     > ---
>     >  .../generic/files/drivers/net/phy/b53/Makefile    |   2 +-
>     > .../generic/files/drivers/net/phy/b53/b53_common.c |  3 +
>     >  .../generic/files/drivers/net/phy/b53/b53_hdr.c   | 114
>     +++++++++++-
>     > .../generic/files/drivers/net/phy/b53/b53_priv.h   |  2 +
>     >  .../generic/files/drivers/net/phy/b53/slave.c   | 196
>     +++++++++++++++++++++
>     >  .../generic/files/drivers/net/phy/b53/slave.h   |  38 ++++
>     >  6 files changed, 352 insertions(+), 3 deletions(-)
>     >  create mode 100644
>     target/linux/generic/files/drivers/net/phy/b53/slave.c
>     >  create mode 100644
>     target/linux/generic/files/drivers/net/phy/b53/slave.h
>     >
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/Makefile
>     b/target/linux/generic/files/drivers/net/phy/b53/Makefile
>     > index 6c809f9..c74f82b 100644
>     > --- a/target/linux/generic/files/drivers/net/phy/b53/Makefile
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/Makefile
>     > @@ -1,5 +1,5 @@
>     >  obj-$(CONFIG_B53)            += b53_common.o
>     > -obj-$(CONFIG_B53_HDR)                += b53_hdr.o
>     > +obj-$(CONFIG_B53_HDR)                += b53_hdr.o slave.o
>     >
>     >  obj-$(CONFIG_B53_PHY_FIXUP)  += b53_phy_fixup.o
>     >
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
>     b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
>     > index 9459b22..3da9efe 100644
>     > --- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
>     > @@ -1377,6 +1377,9 @@ static int b53_global_reset_switch(struct
>     switch_dev *dev)
>     >       priv->enable_management = 0;
>     >  #ifdef CONFIG_B53_HDR
>     >       priv->enable_brcm_hdr = 0;
>     > +     /* Call this function before the memset on the priv->ports,
>     > +      * otherwise we may leak devices */
>     > +     b53_unregister_netdevs(priv);
>     >  #endif
>     >
>     >       memset(priv->vlans, 0, sizeof(priv->vlans) * dev->vlans);
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/b53_hdr.c
>     b/target/linux/generic/files/drivers/net/phy/b53/b53_hdr.c
>     > index 2a562a9..8fa7929 100644
>     > --- a/target/linux/generic/files/drivers/net/phy/b53/b53_hdr.c
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_hdr.c
>     > @@ -21,14 +21,32 @@
>     >
>     >  #include "b53_regs.h"
>     >  #include "b53_priv.h"
>     > +#include "slave.h"
>     >
>     >  /* This tag length is 4 bytes, older ones were 6 bytes, we do not
>     >   * handle them
>     >   */
>     >  #define BRCM_HDR_LEN    4
>     >  #define MIN_FRAME_LEN   64
>     > +#define BRCM_IG_DSTMAP2_MASK 1
>     > +#define BRCM_IG_DSTMAP1_MASK 0xff
>     > +#define BRCM_EG_PID_MASK     0x1f
>     >
>     > -static struct sk_buff *b53_mangle_tx(struct net_device *dev,
>     struct sk_buff *skb)
>     > +/* Ingress and egress opcodes */
>     > +#define BRCM_OPCODE_SHIFT   5
>     > +
>     > +static inline void b53_brcm_tag_set(struct sk_buff *skb, int
>     port_idx)
>     > +{
>     > +     u8 *brcm_tag = skb->data + 2 * ETH_ALEN;
>     > +
>     > +     brcm_tag[0] = (1 << BRCM_OPCODE_SHIFT);
>     > +     brcm_tag[1] = 0;
>     > +     brcm_tag[2] = (port_idx == 8) ? BRCM_IG_DSTMAP2_MASK : 0;
>     > +     brcm_tag[3] = (1 << port_idx) & BRCM_IG_DSTMAP1_MASK;
>     > +}
>     > +
>     > +static struct sk_buff *b53_mangle_tx_port(struct net_device *dev,
>     > +                     struct sk_buff *skb, struct slave_priv* p)
>     >  {
>     >       if (unlikely(skb_headroom(skb) < BRCM_HDR_LEN)) {
>     >               if (pskb_expand_head(skb, BRCM_HDR_LEN, 0,
>     GFP_ATOMIC) < 0)
>     > @@ -40,7 +58,20 @@ static struct sk_buff *b53_mangle_tx(struct
>     net_device *dev, struct sk_buff *skb
>     >       memmove(skb->data, skb->data + BRCM_HDR_LEN, 2 * ETH_ALEN);
>     >
>     >       /* Build the tag after the MAC Source Address */
>     > -     memset(skb->data + 2 * ETH_ALEN, 0, BRCM_HDR_LEN);
>     > +     if (!p) {
>     > +             memset(skb->data + 2 * ETH_ALEN, 0, BRCM_HDR_LEN);
>     > +     } else {
>     > +             /* Register some TX stats for this device before
>     > +              * passing the skb to the parent device */
>     > +             dev->stats.tx_packets++;
>     > +             dev->stats.tx_bytes += skb->len;
>     > +
>     > +             b53_brcm_tag_set(skb, p->port_idx);
>     > +
>     > +             skb->dev = p->parent_dev;
>     > +             skb->protocol = htons(ETH_P_DSA);
>     > +     }
>     > +
>     >  #ifdef CONFIG_B53_HDR_TX_SW_PADDING
>     >       /* FIXME: we're doing some padding here for runt ( < 64
>     bytes) packets;
>     >        *        some drivers/hw refuse to add hw padding for us
>     after we add
>     > @@ -64,12 +95,88 @@ out_err:
>     >       return NULL;
>     >  }
>     >
>     > +static struct sk_buff *b53_mangle_tx(struct net_device *dev,
>     struct sk_buff *skb)
>     > +{
>     > +     /* The b53_mangle_tx() function can get called twice now
>     that there are
>     > +      * slave devices: once for the lanX device, and one for
>     the ethY device
>     > +      * which means that the Broadcom Header would get added twice.
>     > +      * Which is why the packet type has been marked by the
>     slave lanX device
>     > +      * to tell us that we've tagged this packet already. */
>     > +     if (unlikely(skb->protocol == htons(ETH_P_DSA)))
>     > +             return skb;
>     > +     return b53_mangle_tx_port(dev, skb, NULL);
>     > +}
>     > +
>     >  static void b53_mangle_rx(struct net_device *dev, struct
>     sk_buff *skb)
>     >  {
>     > +     struct b53_device *p = dev->phy_ptr;
>     > +     u8 *brcm_tag;
>     > +     u8 source_port;
>     > +
>     > +     /* We're only interested in the 4th byte of the Broadcom
>     Header right now */
>     > +     brcm_tag = skb->data + (2 * ETH_ALEN) + 3;
>     > +     source_port = *brcm_tag & BRCM_EG_PID_MASK;
>     > +
>     >       skb_pull(skb, BRCM_HDR_LEN);
>     >       memmove(skb->data,
>     >               skb->data - BRCM_HDR_LEN,
>     >               2 * ETH_ALEN);
>     > +
>     > +     if ((source_port < B53_N_PORTS) &&
>     (p->ports[source_port].port_dev)) {
>     > +             skb->dev = p->ports[source_port].port_dev;
>     > +             skb->dev->stats.rx_packets++;
>     > +             skb->dev->stats.rx_bytes += skb->len;
>     > +     }
>     > +}
>     > +
>     > +static void b53_register_netdevs(struct b53_device *dev)
>     > +{
>     > +     int i;
>     > +     bool unlock = false;
>     > +
>     > +     if (!rtnl_is_locked()) {
>     > +             rtnl_lock();
>     > +             unlock = true;
>     > +     }
>     > +     b53_for_each_port(dev, i) {
>     > +             if (is_cpu_port(dev, i))
>     > +                     continue;
>     > +             if (!(dev->enabled_ports & BIT(i))) {
>     > +                     if (dev->ports[i].port_dev) {
>     > +  unregister_netdevice(dev->ports[i].port_dev);
>     > +  dev->ports[i].port_dev = NULL;
>     > +                     }
>     > +                     continue;
>     > +             }
>     > +             /* Check if devices already exist for these devices */
>     > +             if (!dev->ports[i].port_dev &&
>     > +                 !(dev->ports[i].port_dev =
>     slave_create(dev->eth_dev, i, b53_mangle_tx_port))) {
>     > +                     pr_warn("%s: can't create slave device for
>     port %d\n",
>     > +                             dev->sw_dev.name
>     <http://sw_dev.name>, i);
>     > +                     continue;
>     > +             }
>     > +     }
>     > +     if (unlock)
>     > +             rtnl_unlock();
>     > +}
>     > +
>     > +void b53_unregister_netdevs(struct b53_device *dev)
>     > +{
>     > +     int i;
>     > +     bool unlock = false;
>     > +
>     > +     if (!rtnl_is_locked()) {
>     > +             rtnl_lock();
>     > +             unlock = true;
>     > +     }
>     > +     b53_for_each_port(dev, i) {
>     > +             if (!dev->ports[i].port_dev)
>     > +                     continue;
>     > +  unregister_netdevice(dev->ports[i].port_dev);
>     > +             dev->ports[i].port_dev = NULL;
>     > +     }
>     > +     if (unlock)
>     > +             rtnl_unlock();
>     >  }
>     >
>     >  void b53_enable_brcm_hdr(struct b53_device *dev)
>     > @@ -86,6 +193,7 @@ void b53_enable_brcm_hdr(struct b53_device *dev)
>     >       }
>     >       brcm_hdr_ctrl &= ~B53_BRCM_HDR_EN;
>     >       if (!dev->eth_dev) {
>     > +             b53_unregister_netdevs(dev);
>     >               goto out;
>     >       }
>     >
>     > @@ -93,6 +201,8 @@ void b53_enable_brcm_hdr(struct b53_device *dev)
>     >       if (!dev->enable_management)
>     >               goto out;
>     >
>     > +     pr_info("%s: registering lan devices\n", dev->sw_dev.name
>     <http://sw_dev.name>);
>     > +     b53_register_netdevs(dev);
>     >       dev->eth_dev->phy_ptr = dev;
>     >       dev->eth_dev->priv_flags |= IFF_NO_IP_ALIGN;
>     >       dev->eth_dev->eth_mangle_rx = b53_mangle_rx;
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
>     b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
>     > index f487bf2..167e042 100644
>     > --- a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
>     > @@ -359,8 +359,10 @@ int b53_global_get_brcm_hdr(struct
>     switch_dev *dev,
>     >  int b53_global_set_brcm_hdr(struct switch_dev *dev,
>     >               const struct switch_attr *attr,
>     >               struct switch_val *val);
>     > +void b53_unregister_netdevs(struct b53_device *dev);
>     >  #else
>     >  #define b53_enable_brcm_hdr(x)
>     > +#define b53_unregister_netdevs(x)
>     >  #endif
>     >
>     >  #ifdef CONFIG_BCM47XX
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/slave.c
>     b/target/linux/generic/files/drivers/net/phy/b53/slave.c
>     > new file mode 100644
>     > index 0000000..b8cd2dc
>     > --- /dev/null
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/slave.c
>     > @@ -0,0 +1,196 @@
>     > +/*
>     > + * Slave devices logic.
>     > + * Adapted/copied from the Linux kernel DSA driver (net/dsa).
>     > + *
>     > + * Permission to use, copy, modify, and/or distribute this
>     software for any
>     > + * purpose with or without fee is hereby granted, provided that
>     the above
>     > + * copyright notice and this permission notice appear in all
>     copies.
>     > + *
>     > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
>     ALL WARRANTIES
>     > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>     > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>     LIABLE FOR
>     > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR
>     ANY DAMAGES
>     > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>     WHETHER IN AN
>     > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>     ARISING OUT OF
>     > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>     > + */
>     > +
>     > +#include <linux/rtnetlink.h>
>     > +#include <linux/etherdevice.h>
>     > +
>     > +#include "slave.h"
>     > +
>     > +static int slave_init(struct net_device *dev)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +     dev->iflink = p->parent_dev->ifindex;
>     > +     return 0;
>     > +}
>     > +
>     > +static int slave_open(struct net_device *dev)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +     struct net_device *parent = p->parent_dev;
>     > +     int err;
>     > +
>     > +     if (!(parent->flags & IFF_UP))
>     > +             return -ENETDOWN;
>     > +
>     > +     if (!ether_addr_equal(dev->dev_addr, parent->dev_addr)) {
>     > +             err = dev_uc_add(parent, dev->dev_addr);
>     > +             if (err < 0)
>     > +                     goto out;
>     > +     }
>     > +
>     > +     if (dev->flags & IFF_ALLMULTI) {
>     > +             err = dev_set_allmulti(parent, 1);
>     > +             if (err < 0)
>     > +                     goto del_unicast;
>     > +     }
>     > +     if (dev->flags & IFF_PROMISC) {
>     > +             err = dev_set_promiscuity(parent, 1);
>     > +             if (err < 0)
>     > +                     goto clear_allmulti;
>     > +     }
>     > +
>     > +     return 0;
>     > +
>     > +clear_allmulti:
>     > +     if (dev->flags & IFF_ALLMULTI)
>     > +             dev_set_allmulti(parent, -1);
>     > +del_unicast:
>     > +     if (!ether_addr_equal(dev->dev_addr, parent->dev_addr))
>     > +             dev_uc_del(parent, dev->dev_addr);
>     > +out:
>     > +     return err;
>     > +}
>     > +
>     > +static int slave_close(struct net_device *dev)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +     struct net_device *parent = p->parent_dev;
>     > +
>     > +     dev_mc_unsync(parent, dev);
>     > +     dev_uc_unsync(parent, dev);
>     > +     if (dev->flags & IFF_ALLMULTI)
>     > +             dev_set_allmulti(parent, -1);
>     > +     if (dev->flags & IFF_PROMISC)
>     > +             dev_set_promiscuity(parent, -1);
>     > +
>     > +     if (!ether_addr_equal(dev->dev_addr, parent->dev_addr))
>     > +             dev_uc_del(parent, dev->dev_addr);
>     > +
>     > +     return 0;
>     > +}
>     > +
>     > +static void slave_change_rx_flags(struct net_device *dev, int
>     change)
>     > +{
>     > +    struct slave_priv *p = netdev_priv(dev);
>     > +     struct net_device *parent = p->parent_dev;
>     > +
>     > +     if (change & IFF_ALLMULTI)
>     > +             dev_set_allmulti(parent, dev->flags & IFF_ALLMULTI
>     ? 1 : -1);
>     > +     if (change & IFF_PROMISC)
>     > +             dev_set_promiscuity(parent, dev->flags &
>     IFF_PROMISC ? 1 : -1);
>     > +}
>     > +
>     > +static void slave_set_rx_mode(struct net_device *dev)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +     struct net_device *parent = p->parent_dev;
>     > +
>     > +     dev_mc_sync(parent, dev);
>     > +     dev_uc_sync(parent, dev);
>     > +}
>     > +
>     > +static int slave_set_mac_address(struct net_device *dev, void *a)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +     struct net_device *parent = p->parent_dev;
>     > +     struct sockaddr *addr = a;
>     > +     int err;
>     > +
>     > +     if (!is_valid_ether_addr(addr->sa_data))
>     > +             return -EADDRNOTAVAIL;
>     > +
>     > +     if (!(dev->flags & IFF_UP))
>     > +             goto out;
>     > +
>     > +     if (!ether_addr_equal(addr->sa_data, parent->dev_addr)) {
>     > +             err = dev_uc_add(parent, addr->sa_data);
>     > +             if (err < 0)
>     > +                     return err;
>     > +     }
>     > +
>     > +     if (!ether_addr_equal(dev->dev_addr, parent->dev_addr))
>     > +             dev_uc_del(parent, dev->dev_addr);
>     > +
>     > +out:
>     > +     memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
>     > +
>     > +     return 0;
>     > +}
>     > +
>     > +static netdev_tx_t slave_xmit(struct sk_buff *skb, struct
>     net_device *dev)
>     > +{
>     > +     struct slave_priv *p = netdev_priv(dev);
>     > +
>     > +     skb->dev = p->parent_dev;
>     > +     skb = p->eth_mangle_tx_port(dev, skb, p);
>     > +     dev_queue_xmit(skb);
>     > +
>     > +     return NETDEV_TX_OK;
>     > +}
>     > +
>     > +static const struct net_device_ops slave_netdev_ops = {
>     > +     .ndo_init               = slave_init,
>     > +     .ndo_open               = slave_open,
>     > +     .ndo_stop               = slave_close,
>     > +     .ndo_start_xmit         = slave_xmit,
>     > +     .ndo_change_rx_flags    = slave_change_rx_flags,
>     > +     .ndo_set_rx_mode        = slave_set_rx_mode,
>     > +     .ndo_set_mac_address    = slave_set_mac_address,
>     > +};
>     > +
>     > +struct net_device *slave_create(struct net_device *parent, int
>     port,
>     > +             eth_mangle_tx_port_t eth_mangle_tx_port)
>     > +{
>     > +     /* Parent dev should not be null according to the code
>     path below */
>     > +     struct net_device *slave_dev = NULL;
>     > +     struct slave_priv *p;
>     > +     char port_name[] = "lan1000";
>     > +
>     > +     snprintf(port_name, sizeof(port_name), "lan%d", (port + 1));
>     > +     slave_dev = alloc_netdev(sizeof(struct slave_priv),
>     > +                 port_name, ether_setup);
>     > +     if (!slave_dev) {
>     > +             pr_err("Failed to allocate memory for slave device");
>     > +             goto out;
>     > +     }
>     > +
>     > +     slave_dev->features = parent->vlan_features;
>     > +     eth_hw_addr_inherit(slave_dev, parent);
>     > +     slave_dev->tx_queue_len = 0;
>     > +     slave_dev->netdev_ops = &slave_netdev_ops;
>     > +
>     > +     SET_NETDEV_DEV(slave_dev, &parent->dev);
>     > +     slave_dev->vlan_features = parent->vlan_features;
>     > +
>     > +     p = netdev_priv(slave_dev);
>     > +     p->parent_dev = parent;
>     > +     p->port_dev   = slave_dev;
>     > +     p->port_idx   = port;
>     > +     p->eth_mangle_tx_port = eth_mangle_tx_port;
>     > +
>     > +     if (register_netdevice(slave_dev)) {
>     > +             free_netdev(slave_dev);
>     > +             slave_dev = NULL;
>     > +             goto out;
>     > +     }
>     > +
>     > +     netif_carrier_on(slave_dev);
>     > +
>     > +out:
>     > +     return slave_dev;
>     > +}
>     > +
>     > diff --git
>     a/target/linux/generic/files/drivers/net/phy/b53/slave.h
>     b/target/linux/generic/files/drivers/net/phy/b53/slave.h
>     > new file mode 100644
>     > index 0000000..3cfe7c7
>     > --- /dev/null
>     > +++ b/target/linux/generic/files/drivers/net/phy/b53/slave.h
>     > @@ -0,0 +1,38 @@
>     > +/*
>     > + * Slave devices logic.
>     > + * Adapted/copied from the Linux kernel DSA driver (net/dsa).
>     > + *
>     > + * Permission to use, copy, modify, and/or distribute this
>     software for any
>     > + * purpose with or without fee is hereby granted, provided that
>     the above
>     > + * copyright notice and this permission notice appear in all
>     copies.
>     > + *
>     > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
>     ALL WARRANTIES
>     > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>     > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>     LIABLE FOR
>     > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR
>     ANY DAMAGES
>     > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>     WHETHER IN AN
>     > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>     ARISING OUT OF
>     > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>     > + */
>     > +
>     > +#ifndef __SLAVE_H__
>     > +#define __SLAVE_H__
>     > +
>     > +#include <linux/etherdevice.h>
>     > +
>     > +struct slave_priv;
>     > +typedef struct sk_buff *(*eth_mangle_tx_port_t)(struct
>     net_device *dev,
>     > +             struct sk_buff *skb, struct slave_priv* p);
>     > +
>     > +struct slave_priv {
>     > +     struct net_device *parent_dev;
>     > +     struct net_device *port_dev;
>     > +     eth_mangle_tx_port_t eth_mangle_tx_port;
>     > +     int port_idx;
>     > +};
>     > +
>     > +/* For the moment, the rtnl_lock() needs to be called by the
>     caller */
>     > +struct net_device *slave_create(struct net_device *parent, int
>     port,
>     > +             eth_mangle_tx_port_t eth_mangle_tx_port);
>     > +
>     > +#endif /* __SLAVE_H__ */
>     >
>
>
>     --
>     Florian
>
>
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/openwrt-devel/attachments/20150226/db3ade53/attachment.htm>
-------------- next part --------------
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list