Commit d6fce514 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: sparx5: add switching support

This adds SwitchDev support by hardware offloading the
software bridge.
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarBjarni Jonasson <bjarni.jonasson@microchip.com>
Signed-off-by: default avatarLars Povlsen <lars.povlsen@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 78eab33b
...@@ -6,4 +6,5 @@ ...@@ -6,4 +6,5 @@
obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o
sparx5-switch-objs := sparx5_main.o sparx5_packet.o \ sparx5-switch-objs := sparx5_main.o sparx5_packet.o \
sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o sparx5_vlan.o sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o sparx5_vlan.o \
sparx5_switchdev.o
...@@ -371,6 +371,9 @@ static void sparx5_mact_handle_entry(struct sparx5 *sparx5, ...@@ -371,6 +371,9 @@ static void sparx5_mact_handle_entry(struct sparx5 *sparx5,
if (port >= SPX5_PORTS) if (port >= SPX5_PORTS)
return; return;
if (!test_bit(port, sparx5->bridge_mask))
return;
mutex_lock(&sparx5->mact_lock); mutex_lock(&sparx5->mact_lock);
list_for_each_entry(mact_entry, &sparx5->mact_entries, list) { list_for_each_entry(mact_entry, &sparx5->mact_entries, list) {
if (mact_entry->vid == vid && if (mact_entry->vid == vid &&
......
...@@ -623,6 +623,7 @@ static int sparx5_start(struct sparx5 *sparx5) ...@@ -623,6 +623,7 @@ static int sparx5_start(struct sparx5 *sparx5)
return err; return err;
sparx5_board_init(sparx5); sparx5_board_init(sparx5);
err = sparx5_register_notifier_blocks(sparx5);
/* Start register based INJ/XTR */ /* Start register based INJ/XTR */
err = -ENXIO; err = -ENXIO;
...@@ -812,6 +813,9 @@ static int mchp_sparx5_remove(struct platform_device *pdev) ...@@ -812,6 +813,9 @@ static int mchp_sparx5_remove(struct platform_device *pdev)
sparx5->xtr_irq = -ENXIO; sparx5->xtr_irq = -ENXIO;
} }
sparx5_cleanup_ports(sparx5); sparx5_cleanup_ports(sparx5);
/* Unregister netdevs */
sparx5_unregister_notifier_blocks(sparx5);
return 0; return 0;
} }
......
...@@ -135,9 +135,16 @@ struct sparx5 { ...@@ -135,9 +135,16 @@ struct sparx5 {
/* port structures are in net device */ /* port structures are in net device */
struct sparx5_port *ports[SPX5_PORTS]; struct sparx5_port *ports[SPX5_PORTS];
enum sparx5_core_clockfreq coreclock; enum sparx5_core_clockfreq coreclock;
/* Notifiers */
struct notifier_block netdevice_nb;
struct notifier_block switchdev_nb;
struct notifier_block switchdev_blocking_nb;
/* Switch state */ /* Switch state */
u8 base_mac[ETH_ALEN]; u8 base_mac[ETH_ALEN];
/* Associated bridge device (when bridged) */
struct net_device *hw_bridge_dev;
/* Bridged interfaces */ /* Bridged interfaces */
DECLARE_BITMAP(bridge_mask, SPX5_PORTS);
DECLARE_BITMAP(bridge_fwd_mask, SPX5_PORTS); DECLARE_BITMAP(bridge_fwd_mask, SPX5_PORTS);
DECLARE_BITMAP(bridge_lrn_mask, SPX5_PORTS); DECLARE_BITMAP(bridge_lrn_mask, SPX5_PORTS);
DECLARE_BITMAP(vlan_mask[VLAN_N_VID], SPX5_PORTS); DECLARE_BITMAP(vlan_mask[VLAN_N_VID], SPX5_PORTS);
...@@ -153,6 +160,10 @@ struct sparx5 { ...@@ -153,6 +160,10 @@ struct sparx5 {
int xtr_irq; int xtr_irq;
}; };
/* sparx5_switchdev.c */
int sparx5_register_notifier_blocks(struct sparx5 *sparx5);
void sparx5_unregister_notifier_blocks(struct sparx5 *sparx5);
/* sparx5_packet.c */ /* sparx5_packet.c */
irqreturn_t sparx5_xtr_handler(int irq, void *_priv); irqreturn_t sparx5_xtr_handler(int irq, void *_priv);
int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev); int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
......
...@@ -117,6 +117,15 @@ static int sparx5_port_stop(struct net_device *ndev) ...@@ -117,6 +117,15 @@ static int sparx5_port_stop(struct net_device *ndev)
return 0; return 0;
} }
static void sparx5_set_rx_mode(struct net_device *dev)
{
struct sparx5_port *port = netdev_priv(dev);
struct sparx5 *sparx5 = port->sparx5;
if (!test_bit(port->portno, sparx5->bridge_mask))
__dev_mc_sync(dev, sparx5_mc_sync, sparx5_mc_unsync);
}
static int sparx5_port_get_phys_port_name(struct net_device *dev, static int sparx5_port_get_phys_port_name(struct net_device *dev,
char *buf, size_t len) char *buf, size_t len)
{ {
...@@ -167,6 +176,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = { ...@@ -167,6 +176,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = {
.ndo_open = sparx5_port_open, .ndo_open = sparx5_port_open,
.ndo_stop = sparx5_port_stop, .ndo_stop = sparx5_port_stop,
.ndo_start_xmit = sparx5_port_xmit_impl, .ndo_start_xmit = sparx5_port_xmit_impl,
.ndo_set_rx_mode = sparx5_set_rx_mode,
.ndo_get_phys_port_name = sparx5_port_get_phys_port_name, .ndo_get_phys_port_name = sparx5_port_get_phys_port_name,
.ndo_set_mac_address = sparx5_set_mac_address, .ndo_set_mac_address = sparx5_set_mac_address,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -139,6 +139,12 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap) ...@@ -139,6 +139,12 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap)
return; return;
} }
/* Everything we see on an interface that is in the HW bridge
* has already been forwarded
*/
if (test_bit(port->portno, sparx5->bridge_mask))
skb->offload_fwd_mark = 1;
/* Finish up skb */ /* Finish up skb */
skb_put(skb, byte_cnt - ETH_FCS_LEN); skb_put(skb, byte_cnt - ETH_FCS_LEN);
eth_skb_pad(skb); eth_skb_pad(skb);
......
This diff is collapsed.
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