Commit 535f010d authored by Egil Hjelmeland's avatar Egil Hjelmeland Committed by David S. Miller

net: dsa: lan9303: Learn addresses on CPU port when bridged

When CPU transmit directly to port using tag, the LAN9303 does not
learn MAC addresses received on the CPU port into the ALR.
ALR learning is performed only when transmitting using ALR lookup.

Solution:
If the two external ports are bridged and the packet is not STP BPDU,
then use ALR lookup to allow ALR learning on CPU port.
Otherwise transmit directly to port with STP state override.
Signed-off-by: default avatarEgil Hjelmeland <privat@egil-hjelmeland.no>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 356c3e9a
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
*/ */
#include <linux/dsa/lan9303.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -39,6 +40,23 @@ ...@@ -39,6 +40,23 @@
*/ */
#define LAN9303_TAG_LEN 4 #define LAN9303_TAG_LEN 4
# define LAN9303_TAG_TX_USE_ALR BIT(3)
# define LAN9303_TAG_TX_STP_OVERRIDE BIT(4)
#define eth_stp_addr eth_reserved_addr_base
/* Decide whether to transmit using ALR lookup, or transmit directly to
* port using tag. ALR learning is performed only when using ALR lookup.
* If the two external ports are bridged and the packet is not STP BPDU,
* then use ALR lookup to allow ALR learning on CPU port.
* Otherwise transmit directly to port with STP state override.
* See also: lan9303_separate_ports() and lan9303.pdf 6.4.10.1
*/
static int lan9303_xmit_use_arl(struct dsa_port *dp, u8 *dest_addr)
{
struct lan9303 *chip = dp->ds->priv;
return chip->is_bridged && !ether_addr_equal(dest_addr, eth_stp_addr);
}
static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev) static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
...@@ -62,7 +80,10 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -62,7 +80,10 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
lan9303_tag = (u16 *)(skb->data + 2 * ETH_ALEN); lan9303_tag = (u16 *)(skb->data + 2 * ETH_ALEN);
lan9303_tag[0] = htons(ETH_P_8021Q); lan9303_tag[0] = htons(ETH_P_8021Q);
lan9303_tag[1] = htons(dp->index | BIT(4)); lan9303_tag[1] = lan9303_xmit_use_arl(dp, skb->data) ?
LAN9303_TAG_TX_USE_ALR :
dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
lan9303_tag[1] = htons(lan9303_tag[1]);
return skb; return skb;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment