diff options
-rw-r--r-- | Documentation/devicetree/bindings/net/dsa/dsa.txt | 33 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 109 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_dev.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_wq.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/vnic_wq.h | 4 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 7 | ||||
-rw-r--r-- | drivers/net/vrf.c | 15 | ||||
-rw-r--r-- | include/net/dsa.h | 5 | ||||
-rw-r--r-- | include/net/lwtunnel.h | 7 | ||||
-rw-r--r-- | include/net/vrf.h | 1 | ||||
-rw-r--r-- | net/dsa/dsa.c | 40 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 10 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel_core.c | 7 |
18 files changed, 235 insertions, 54 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt index 9cf9a0ec333c..04e6bef3ac3f 100644 --- a/Documentation/devicetree/bindings/net/dsa/dsa.txt +++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt @@ -44,9 +44,10 @@ Note that a port labelled "dsa" will imply checking for the uplink phandle described below. Optionnal property: -- link : Should be a phandle to another switch's DSA port. +- link : Should be a list of phandles to another switch's DSA port. This property is only used when switches are being - chained/cascaded together. + chained/cascaded together. This port is used as outgoing port + towards the phandle port, which can be more than one hop away. - phy-handle : Phandle to a PHY on an external MDIO bus, not the switch internal one. See @@ -100,10 +101,11 @@ Example: label = "cpu"; }; - switch0uplink: port@6 { + switch0port6: port@6 { reg = <6>; label = "dsa"; - link = <&switch1uplink>; + link = <&switch1port0 + &switch2port0>; }; }; @@ -113,10 +115,29 @@ Example: reg = <17 1>; /* MDIO address 17, switch 1 in tree */ mii-bus = <&mii_bus1>; - switch1uplink: port@0 { + switch1port0: port@0 { reg = <0>; label = "dsa"; - link = <&switch0uplink>; + link = <&switch0port6>; + }; + switch1port1: port@1 { + reg = <1>; + label = "dsa"; + link = <&switch2port1>; + }; + }; + + switch@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <18 2>; /* MDIO address 18, switch 2 in tree */ + mii-bus = <&mii_bus1>; + + switch2port0: port@0 { + reg = <0>; + label = "dsa"; + link = <&switch1port1 + &switch0port6>; }; }; }; diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 332f2c8090d0..2ab3f9810593 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1926,8 +1926,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * full duplex. */ reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL); - if (dsa_is_cpu_port(ds, port) || - ds->dsa_port_mask & (1 << port)) { + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP | PORT_PCS_CTRL_DUPLEX_FULL | @@ -1988,12 +1987,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) reg |= PORT_CONTROL_EGRESS_ADD_TAG; } } - if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || - mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || - mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) || - mv88e6xxx_6320_family(ds)) { - if (ds->dsa_port_mask & (1 << port)) + if (dsa_is_dsa_port(ds, port)) { + if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) + reg |= PORT_CONTROL_DSA_TAG; + if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || + mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || + mv88e6xxx_6320_family(ds)) { reg |= PORT_CONTROL_FRAME_MODE_DSA; + } + if (port == dsa_upstream_port(ds)) reg |= PORT_CONTROL_FORWARD_UNKNOWN | PORT_CONTROL_FORWARD_UNKNOWN_MC; diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 8be9eab73320..e930aa9a3cfb 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -139,6 +139,16 @@ config BNX2X_SRIOV Virtualization support in the 578xx and 57712 products. This allows for virtual function acceleration in virtual environments. +config BNX2X_VXLAN + bool "Virtual eXtensible Local Area Network support" + default n + depends on BNX2X && VXLAN && !(BNX2X=y && VXLAN=m) + ---help--- + This enables hardward offload support for VXLAN protocol over the + NetXtremeII series adapters. + Say Y here if you want to enable hardware offload support for + Virtual eXtensible Local Area Network (VXLAN) in the driver. + config BGMAC tristate "BCMA bus GBit core support" depends on BCMA_HOST_SOC && HAS_DMA && (BCM47XX || ARCH_BCM_5301X) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index e28c90c15e0b..ba936635322a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1392,6 +1392,8 @@ enum sp_rtnl_flag { BNX2X_SP_RTNL_HYPERVISOR_VLAN, BNX2X_SP_RTNL_TX_STOP, BNX2X_SP_RTNL_GET_DRV_VERSION, + BNX2X_SP_RTNL_ADD_VXLAN_PORT, + BNX2X_SP_RTNL_DEL_VXLAN_PORT, }; enum bnx2x_iov_flag { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index e18a0e4d3ed1..d276de328c5c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -967,6 +967,8 @@ static inline int bnx2x_func_start(struct bnx2x *bp) else /* CHIP_IS_E1X */ start_params->network_cos_mode = FW_WRR; + start_params->vxlan_dst_port = cpu_to_le16(bp->vxlan_dst_port); + start_params->inner_rss = 1; if (IS_MF_UFP(bp) && BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index eafd25d8142a..26fbfcc6f7db 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10075,6 +10075,81 @@ static void bnx2x_parity_recover(struct bnx2x *bp) } } +#ifdef CONFIG_BNX2X_VXLAN +static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port) +{ + struct bnx2x_func_switch_update_params *switch_update_params; + struct bnx2x_func_state_params func_params = {NULL}; + int rc; + + switch_update_params = &func_params.params.switch_update; + + /* Prepare parameters for function state transitions */ + __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); + __set_bit(RAMROD_RETRY, &func_params.ramrod_flags); + + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE; + + /* Function parameters */ + __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, + &switch_update_params->changes); + switch_update_params->vxlan_dst_port = port; + rc = bnx2x_func_state_change(bp, &func_params); + if (rc) + BNX2X_ERR("failed to change vxlan dst port to %d (rc = 0x%x)\n", + port, rc); + return rc; +} + +static void __bnx2x_add_vxlan_port(struct bnx2x *bp, u16 port) +{ + if (!netif_running(bp->dev)) + return; + + if (bp->vxlan_dst_port || !IS_PF(bp)) { + DP(BNX2X_MSG_SP, "Vxlan destination port limit reached\n"); + return; + } + + bp->vxlan_dst_port = port; + bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_ADD_VXLAN_PORT, 0); +} + +static void bnx2x_add_vxlan_port(struct net_device *netdev, + sa_family_t sa_family, __be16 port) +{ + struct bnx2x *bp = netdev_priv(netdev); + u16 t_port = ntohs(port); + + __bnx2x_add_vxlan_port(bp, t_port); +} + +static void __bnx2x_del_vxlan_port(struct bnx2x *bp, u16 port) +{ + if (!bp->vxlan_dst_port || bp->vxlan_dst_port != port || !IS_PF(bp)) { + DP(BNX2X_MSG_SP, "Invalid vxlan port\n"); + return; + } + + if (netif_running(bp->dev)) { + bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_DEL_VXLAN_PORT, 0); + } else { + bp->vxlan_dst_port = 0; + netdev_info(bp->dev, "Deleted vxlan dest port %d", port); + } +} + +static void bnx2x_del_vxlan_port(struct net_device *netdev, + sa_family_t sa_family, __be16 port) +{ + struct bnx2x *bp = netdev_priv(netdev); + u16 t_port = ntohs(port); + + __bnx2x_del_vxlan_port(bp, t_port); +} +#endif + static int bnx2x_close(struct net_device *dev); /* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is @@ -10083,6 +10158,9 @@ static int bnx2x_close(struct net_device *dev); static void bnx2x_sp_rtnl_task(struct work_struct *work) { struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work); +#ifdef CONFIG_BNX2X_VXLAN + u16 port; +#endif rtnl_lock(); @@ -10181,6 +10259,27 @@ sp_rtnl_not_reset: &bp->sp_rtnl_state)) bnx2x_update_mng_version(bp); +#ifdef CONFIG_BNX2X_VXLAN + port = bp->vxlan_dst_port; + if (test_and_clear_bit(BNX2X_SP_RTNL_ADD_VXLAN_PORT, + &bp->sp_rtnl_state)) { + if (!bnx2x_vxlan_port_update(bp, port)) + netdev_info(bp->dev, "Added vxlan dest port %d", port); + else + bp->vxlan_dst_port = 0; + } + + if (test_and_clear_bit(BNX2X_SP_RTNL_DEL_VXLAN_PORT, + &bp->sp_rtnl_state)) { + if (!bnx2x_vxlan_port_update(bp, 0)) { + netdev_info(bp->dev, + "Deleted vxlan dest port %d", port); + bp->vxlan_dst_port = 0; + vxlan_get_rx_port(bp->dev); + } + } +#endif + /* work which needs rtnl lock not-taken (as it takes the lock itself and * can be called from other contexts as well) */ @@ -12379,6 +12478,12 @@ static int bnx2x_open(struct net_device *dev) rc = bnx2x_nic_load(bp, LOAD_OPEN); if (rc) return rc; + +#ifdef CONFIG_BNX2X_VXLAN + if (IS_PF(bp)) + vxlan_get_rx_port(dev); +#endif + return 0; } @@ -12894,6 +12999,10 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_get_phys_port_id = bnx2x_get_phys_port_id, .ndo_set_vf_link_state = bnx2x_set_vf_link_state, .ndo_features_check = bnx2x_features_check, +#ifdef CONFIG_BNX2X_VXLAN + .ndo_add_vxlan_port = bnx2x_add_vxlan_port, + .ndo_del_vxlan_port = bnx2x_del_vxlan_port, +#endif }; static int bnx2x_set_coherency_mask(struct bnx2x *bp) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 1732e29253cd..0a87a3247464 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -1289,13 +1289,14 @@ static unsigned int xdigit2int(unsigned char c) static ssize_t mps_trc_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { - int i, j, enable, ret; + int i, enable, ret; u32 *data, *mask; struct trace_params tp; const struct inode *ino; unsigned int trcidx; char *s, *p, *word, *end; struct adapter *adap; + u32 j; ino = file_inode(file); trcidx = (uintptr_t)ino->i_private & 3; @@ -1340,7 +1341,7 @@ static ssize_t mps_trc_write(struct file *file, const char __user *buf, if (!strncmp(word, "qid=", 4)) { end = (char *)word + 4; - ret = kstrtoul(end, 10, (unsigned long *)&j); + ret = kstrtouint(end, 10, &j); if (ret) goto out; if (!adap->trace_rss) { @@ -1369,7 +1370,7 @@ static ssize_t mps_trc_write(struct file *file, const char __user *buf, } if (!strncmp(word, "snaplen=", 8)) { end = (char *)word + 8; - ret = kstrtoul(end, 10, (unsigned long *)&j); + ret = kstrtouint(end, 10, &j); if (ret || j > 9600) { inval: count = -EINVAL; goto out; @@ -1379,7 +1380,7 @@ inval: count = -EINVAL; } if (!strncmp(word, "minlen=", 7)) { end = (char *)word + 7; - ret = kstrtoul(end, 10, (unsigned long *)&j); + ret = kstrtouint(end, 10, &j); if (ret || j > TFMINPKTSIZE_M) goto inval; tp.min_len = j; @@ -1453,7 +1454,7 @@ inval: count = -EINVAL; } if (*word == '@') { end = (char *)word + 1; - ret = kstrtoul(end, 10, (unsigned long *)&j); + ret = kstrtouint(end, 10, &j); if (*end && *end != '\n') goto inval; if (j & 7) /* doesn't start at multiple of 8 */ diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c index 9f6c641ca66e..19a49a6e3911 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.c +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c @@ -388,7 +388,7 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev) vdev->devcmd2->color = 1; vdev->devcmd2->result_size = DEVCMD2_RING_SIZE; - err = vnic_wq_devcmd2_alloc(vdev, &vdev->devcmd2->wq, DEVCMD2_RING_SIZE, + err = enic_wq_devcmd2_alloc(vdev, &vdev->devcmd2->wq, DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE); if (err) goto err_free_devcmd2; @@ -400,7 +400,7 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev) return -ENODEV; } - vnic_wq_init_start(&vdev->devcmd2->wq, 0, fetch_index, fetch_index, 0, + enic_wq_init_start(&vdev->devcmd2->wq, 0, fetch_index, fetch_index, 0, 0); vnic_wq_enable(&vdev->devcmd2->wq); diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c index 627f3b1d4b9f..05ad16a7e872 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_wq.c +++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c @@ -114,7 +114,7 @@ int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, return 0; } -int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, +int enic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int desc_count, unsigned int desc_size) { int err; @@ -131,7 +131,7 @@ int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, return err; } -void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, +void enic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) @@ -158,7 +158,7 @@ void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) { - vnic_wq_init_start(wq, cq_index, 0, 0, + enic_wq_init_start(wq, cq_index, 0, 0, error_interrupt_enable, error_interrupt_offset); } diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.h b/drivers/net/ethernet/cisco/enic/vnic_wq.h index c9b25d31c4b8..8944af935a60 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_wq.h +++ b/drivers/net/ethernet/cisco/enic/vnic_wq.h @@ -185,9 +185,9 @@ void vnic_wq_enable(struct vnic_wq *wq); int vnic_wq_disable(struct vnic_wq *wq); void vnic_wq_clean(struct vnic_wq *wq, void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)); -int vnic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, +int enic_wq_devcmd2_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int desc_count, unsigned int desc_size); -void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, +void enic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f3b9d3eb753b..2990024b90f9 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -777,14 +777,17 @@ static int netvsc_set_channels(struct net_device *net, struct hv_device *dev = net_device_ctx->device_ctx; struct netvsc_device *nvdev = hv_get_drvdata(dev); struct netvsc_device_info device_info; - const u32 num_chn = nvdev->num_chn; - const u32 max_chn = min_t(u32, nvdev->max_chn, num_online_cpus()); + u32 num_chn; + u32 max_chn; int ret = 0; bool recovering = false; if (!nvdev || nvdev->destroy) return -ENODEV; + num_chn = nvdev->num_chn; + max_chn = min_t(u32, nvdev->max_chn, num_online_cpus()); + if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5) { pr_info("vRSS unsupported before NVSP Version 5\n"); return -EINVAL; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 95097cb79354..ed208317cbb5 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -265,8 +265,7 @@ static void vrf_rtable_destroy(struct net_vrf *vrf) { struct dst_entry *dst = (struct dst_entry *)vrf->rth; - if (dst) - dst_destroy(dst); + dst_destroy(dst); vrf->rth = NULL; } @@ -334,16 +333,12 @@ static struct slave *__vrf_find_slave_dev(struct slave_queue *queue, /* inverse of __vrf_insert_slave */ static void __vrf_remove_slave(struct slave_queue *queue, struct slave *slave) { - dev_put(slave->dev); list_del(&slave->list); - queue->num_slaves--; } static void __vrf_insert_slave(struct slave_queue *queue, struct slave *slave) { - dev_hold(slave->dev); list_add(&slave->list, &queue->all_slaves); - queue->num_slaves++; } static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) @@ -459,8 +454,7 @@ static void vrf_dev_uninit(struct net_device *dev) list_for_each_entry_safe(slave, next, head, list) vrf_del_slave(dev, slave->dev); - if (dev->dstats) - free_percpu(dev->dstats); + free_percpu(dev->dstats); dev->dstats = NULL; } @@ -630,9 +624,8 @@ static int vrf_device_event(struct notifier_block *unused, if (!vrf_ptr || netif_is_vrf(dev)) goto out; - vrf_dev = __dev_get_by_index(dev_net(dev), vrf_ptr->ifindex); - if (vrf_dev) - vrf_del_slave(vrf_dev, dev); + vrf_dev = netdev_master_upper_dev_get(dev); + vrf_del_slave(vrf_dev, dev); } out: return NOTIFY_DONE; diff --git a/include/net/dsa.h b/include/net/dsa.h index bd9b76502458..b34d812bc5d0 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -171,6 +171,11 @@ static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); } +static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) +{ + return !!((ds->dsa_port_mask) & (1 << p)); +} + static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) { return ds->phys_port_mask & (1 << p) && ds->ports[p]; diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index e25b60eb262d..34fd8f70c2ca 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -36,6 +36,11 @@ struct lwtunnel_encap_ops { }; #ifdef CONFIG_LWTUNNEL +static inline void lwtstate_free(struct lwtunnel_state *lws) +{ + kfree(lws); +} + static inline struct lwtunnel_state * lwtstate_get(struct lwtunnel_state *lws) { @@ -51,7 +56,7 @@ static inline void lwtstate_put(struct lwtunnel_state *lws) return; if (atomic_dec_and_test(&lws->refcnt)) - kfree(lws); + lwtstate_free(lws); } static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate) diff --git a/include/net/vrf.h b/include/net/vrf.h index 40e3793c7a05..3bb4af462ed6 100644 --- a/include/net/vrf.h +++ b/include/net/vrf.h @@ -24,7 +24,6 @@ struct slave { struct slave_queue { struct list_head all_slaves; - int num_slaves; }; struct net_vrf { diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 78d4ac97aae3..053eb2b8e682 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -554,6 +554,31 @@ static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, return 0; } +static int dsa_of_probe_links(struct dsa_platform_data *pd, + struct dsa_chip_data *cd, + int chip_index, int port_index, + struct device_node *port, + const char *port_name) +{ + struct device_node *link; + int link_index; + int ret; + + for (link_index = 0;; link_index++) { + link = of_parse_phandle(port, "link", link_index); + if (!link) + break; + + if (!strcmp(port_name, "dsa") && pd->nr_chips > 1) { + ret = dsa_of_setup_routing_table(pd, cd, chip_index, + port_index, link); + if (ret) + return ret; + } + } + return 0; +} + static void dsa_of_free_platform_data(struct dsa_platform_data *pd) { int i; @@ -573,7 +598,7 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd) static int dsa_of_probe(struct device *dev) { struct device_node *np = dev->of_node; - struct device_node *child, *mdio, *ethernet, *port, *link; + struct device_node *child, *mdio, *ethernet, *port; struct mii_bus *mdio_bus, *mdio_bus_switch; struct net_device *ethernet_dev; struct dsa_platform_data *pd; @@ -668,15 +693,10 @@ static int dsa_of_probe(struct device *dev) goto out_free_chip; } - link = of_parse_phandle(port, "link", 0); - - if (!strcmp(port_name, "dsa") && link && - pd->nr_chips > 1) { - ret = dsa_of_setup_routing_table(pd, cd, - chip_index, port_index, link); - if (ret) - goto out_free_chip; - } + ret = dsa_of_probe_links(pd, cd, chip_index, + port_index, port, port_name); + if (ret) + goto out_free_chip; } } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index c8025851dac7..d5253071f71f 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -539,7 +539,7 @@ int fib_encap_match(struct net *net, u16 encap_type, { struct lwtunnel_state *lwtstate; struct net_device *dev = NULL; - int ret; + int ret, result = 0; if (encap_type == LWTUNNEL_ENCAP_NONE) return 0; @@ -548,10 +548,12 @@ int fib_encap_match(struct net *net, u16 encap_type, dev = __dev_get_by_index(net, oif); ret = lwtunnel_build_state(dev, encap_type, encap, &lwtstate); - if (!ret) - return lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); + if (!ret) { + result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); + lwtstate_free(lwtstate); + } - return 0; + return result; } int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index fd6319681c50..1c2389d582a6 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -286,10 +286,17 @@ static int ip_tun_encap_nlsize(struct lwtunnel_state *lwtstate) + nla_total_size(2); /* LWTUNNEL_IP_FLAGS */ } +static int ip_tun_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b) +{ + return memcmp(lwt_tun_info(a), lwt_tun_info(b), + sizeof(struct ip_tunnel_info)); +} + static const struct lwtunnel_encap_ops ip_tun_lwt_ops = { .build_state = ip_tun_build_state, .fill_encap = ip_tun_fill_encap_info, .get_encap_size = ip_tun_encap_nlsize, + .cmp_encap = ip_tun_cmp_encap, }; void __init ip_tunnel_core_init(void) |