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