diff options
44 files changed, 329 insertions, 192 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 22abfb39d813..68d45ba2d9b9 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev) if (phydev->interface == PHY_INTERFACE_MODE_RMII) { opmode |= RMII; /* For Now only 100MBit are supported */ -#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2 - opmode |= TE; +#if defined(CONFIG_BF537) || defined(CONFIG_BF536) + if (__SILICON_REVISION__ < 3) { + /* + * This isn't publicly documented (fun times!), but in + * silicon <=0.2, the RX and TX pins are clocked together. + * So in order to recv, we must enable the transmit side + * as well. This will cause a spurious TX interrupt too, + * but we can easily consume that. + */ + opmode |= TE; + } #endif } diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d1865cc97313..8e6d618b5305 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = { #endif }; -static void inline vlan_features_add(struct net_device *dev, u32 flags) +static inline void vlan_features_add(struct net_device *dev, u32 flags) { dev->vlan_features |= flags; } diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 110eda01843c..31552959aed7 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); - if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) - /* disable automatic retransmission */ - priv->write_reg(priv, &priv->regs->control, - CONTROL_DISABLE_AR); - else - /* enable automatic retransmission */ - priv->write_reg(priv, &priv->regs->control, - CONTROL_ENABLE_AR); + /* enable automatic retransmission */ + priv->write_reg(priv, &priv->regs->control, + CONTROL_ENABLE_AR); if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & CAN_CTRLMODE_LOOPBACK)) { @@ -704,7 +699,6 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); - c_can_inval_msg_object(dev, 0, msg_obj_no); val = c_can_read_reg32(priv, &priv->regs->txrqst1); if (!(val & (1 << msg_obj_no))) { can_get_echo_skb(dev, @@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev) &priv->regs->ifregs[0].msg_cntrl) & IF_MCONT_DLC_MASK; stats->tx_packets++; + c_can_inval_msg_object(dev, 0, msg_obj_no); } } @@ -1112,8 +1107,7 @@ struct net_device *alloc_c_can_dev(void) priv->can.bittiming_const = &c_can_bittiming_const; priv->can.do_set_mode = c_can_set_mode; priv->can.do_get_berr_counter = c_can_get_berr_counter; - priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT | - CAN_CTRLMODE_LOOPBACK | + priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING; diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index e629b961ae2d..cc90824f2c9c 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) void __iomem *addr; struct net_device *dev; struct c_can_priv *priv; - struct resource *mem, *irq; + struct resource *mem; + int irq; #ifdef CONFIG_HAVE_CLK struct clk *clk; @@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) /* get the platform data */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mem || (irq <= 0)) { + irq = platform_get_irq(pdev, 0); + if (!mem || irq <= 0) { ret = -ENODEV; goto exit_free_clk; } @@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) priv = netdev_priv(dev); - dev->irq = irq->start; + dev->irq = irq; priv->regs = addr; #ifdef CONFIG_HAVE_CLK priv->can.clock.freq = clk_get_rate(clk); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 4d538a4e9d55..910893143295 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1983,14 +1983,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - struct qset_params *qsp = &adapter->params.sge.qset[0]; - struct sge_qset *qs = &adapter->sge.qs[0]; + struct qset_params *qsp; + struct sge_qset *qs; + int i; if (c->rx_coalesce_usecs * 10 > M_NEWTIMER) return -EINVAL; - qsp->coalesce_usecs = c->rx_coalesce_usecs; - t3_update_qset_coalesce(qs, qsp); + for (i = 0; i < pi->nqsets; i++) { + qsp = &adapter->params.sge.qset[i]; + qs = &adapter->sge.qs[i]; + qsp->coalesce_usecs = c->rx_coalesce_usecs; + t3_update_qset_coalesce(qs, qsp); + } + return 0; } diff --git a/drivers/net/jme.c b/drivers/net/jme.c index f690474f4409..994c80939c7a 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme) { jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); pci_set_power_state(jme->pdev, PCI_D0); - pci_enable_wake(jme->pdev, PCI_D0, false); + device_set_wakeup_enable(&jme->pdev->dev, false); } static int @@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev, jwrite32(jme, JME_PMCS, jme->reg_pmcs); + device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs); + return 0; } @@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int -jme_suspend(struct pci_dev *pdev, pm_message_t state) +static int jme_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct net_device *netdev = pci_get_drvdata(pdev); struct jme_adapter *jme = netdev_priv(netdev); @@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) tasklet_hi_enable(&jme->rxclean_task); tasklet_hi_enable(&jme->rxempty_task); - pci_save_state(pdev); jme_powersave_phy(jme); - pci_enable_wake(jme->pdev, PCI_D3hot, true); - pci_set_power_state(pdev, PCI_D3hot); return 0; } -static int -jme_resume(struct pci_dev *pdev) +static int jme_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct net_device *netdev = pci_get_drvdata(pdev); struct jme_adapter *jme = netdev_priv(netdev); - jme_clear_pm(jme); - pci_restore_state(pdev); + jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); jme_phy_on(jme); if (test_bit(JME_FLAG_SSET, &jme->flags)) @@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev) return 0; } + +static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); +#define JME_PM_OPS (&jme_pm_ops) + +#else + +#define JME_PM_OPS NULL #endif static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { @@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = { .id_table = jme_pci_tbl, .probe = jme_init_one, .remove = __devexit_p(jme_remove_one), -#ifdef CONFIG_PM - .suspend = jme_suspend, - .resume = jme_resume, -#endif /* CONFIG_PM */ .shutdown = jme_shutdown, + .driver.pm = JME_PM_OPS, }; static int __init diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 540a8dcbcc46..7f7d5708a658 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) goto unlock; } skb_copy_and_csum_dev(org_skb, skb->data); - org_skb->ip_summed = 0; + org_skb->ip_summed = CHECKSUM_NONE; skb->len = org_skb->len; copy_old_skb(org_skb, skb); } diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 5762ebde4455..4f158baa0246 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev) 0, MLX4_PROT_ETH)) mlx4_warn(mdev, "Failed Attaching Broadcast\n"); + /* Must redo promiscuous mode setup. */ + priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC); + /* Schedule multicast task to populate multicast list */ queue_work(mdev->workqueue, &priv->mcast_task); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1f4e8680a96a..673dc600c891 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, * page into an skb */ static inline int -myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, - int bytes, int len, __wsum csum) +myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, + int lro_enabled) { struct myri10ge_priv *mgp = ss->mgp; struct sk_buff *skb; struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; - int i, idx, hlen, remainder; + struct myri10ge_rx_buf *rx; + int i, idx, hlen, remainder, bytes; struct pci_dev *pdev = mgp->pdev; struct net_device *dev = mgp->dev; u8 *va; + if (len <= mgp->small_bytes) { + rx = &ss->rx_small; + bytes = mgp->small_bytes; + } else { + rx = &ss->rx_big; + bytes = mgp->big_bytes; + } + len += MXGEFW_PAD; idx = rx->cnt & rx->mask; va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; @@ -1341,7 +1350,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, remainder -= MYRI10GE_ALLOC_SIZE; } - if (dev->features & NETIF_F_LRO) { + if (lro_enabled) { rx_frags[0].page_offset += MXGEFW_PAD; rx_frags[0].size -= MXGEFW_PAD; len -= MXGEFW_PAD; @@ -1463,7 +1472,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) { struct myri10ge_rx_done *rx_done = &ss->rx_done; struct myri10ge_priv *mgp = ss->mgp; - struct net_device *netdev = mgp->dev; + unsigned long rx_bytes = 0; unsigned long rx_packets = 0; unsigned long rx_ok; @@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) u16 length; __wsum checksum; + /* + * Prevent compiler from generating more than one ->features memory + * access to avoid theoretical race condition with functions that + * change NETIF_F_LRO flag at runtime. + */ + bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO; + while (rx_done->entry[idx].length != 0 && work_done < budget) { length = ntohs(rx_done->entry[idx].length); rx_done->entry[idx].length = 0; checksum = csum_unfold(rx_done->entry[idx].checksum); - if (length <= mgp->small_bytes) - rx_ok = myri10ge_rx_done(ss, &ss->rx_small, - mgp->small_bytes, - length, checksum); - else - rx_ok = myri10ge_rx_done(ss, &ss->rx_big, - mgp->big_bytes, - length, checksum); + rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled); rx_packets += rx_ok; rx_bytes += rx_ok * (unsigned long)length; cnt++; @@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ss->stats.rx_packets += rx_packets; ss->stats.rx_bytes += rx_bytes; - if (netdev->features & NETIF_F_LRO) + if (lro_enabled) lro_flush_all(&rx_done->lro_mgr); /* restock receive rings if needed */ diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 653d308e0f5d..3bdcc803ec68 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data) struct netxen_adapter *adapter = netdev_priv(netdev); int hw_lro; - if (data & ~ETH_FLAG_LRO) + if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) return -EINVAL; if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 4c14510e2a87..45b2755d6cba 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data) struct qlcnic_adapter *adapter = netdev_priv(netdev); int hw_lro; - if (data & ~ETH_FLAG_LRO) + if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) return -EINVAL; if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2ad6364103ea..356e74d20b80 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) int rc = 0; int changed = 0; - if (data & ~ETH_FLAG_LRO) + if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO)) return -EINVAL; if (data & ETH_FLAG_LRO) { diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ebec88882c3b..73c942d85f07 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -48,9 +48,9 @@ #include <net/ip.h> #include <asm/system.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/byteorder.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #ifdef CONFIG_SPARC #include <asm/idprom.h> @@ -13118,7 +13118,7 @@ done: static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); -static void inline vlan_features_add(struct net_device *dev, unsigned long flags) +static inline void vlan_features_add(struct net_device *dev, unsigned long flags) { dev->vlan_features |= flags; } diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 81254be85b92..51f2ef142a5b 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1; unsigned long flags; - if (data & ~ETH_FLAG_LRO) - return -EOPNOTSUPP; + if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) + return -EINVAL; if (lro_requested ^ lro_present) { /* toggle the LRO feature*/ diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index 1dd3a21b3a43..c5eb034107fd 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data) struct vxgedev *vdev = netdev_priv(dev); enum vxge_hw_status status; - if (data & ~ETH_FLAG_RXHASH) - return -EOPNOTSUPP; + if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH)) + return -EINVAL; if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) return 0; diff --git a/include/linux/can/core.h b/include/linux/can/core.h index 6c507bea275f..6f70a6d3a16e 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -36,10 +36,10 @@ * @prot: pointer to struct proto structure. */ struct can_proto { - int type; - int protocol; - struct proto_ops *ops; - struct proto *prot; + int type; + int protocol; + const struct proto_ops *ops; + struct proto *prot; }; /* function prototypes for the CAN networklayer core (af_can.c) */ @@ -58,5 +58,6 @@ extern void can_rx_unregister(struct net_device *dev, canid_t can_id, void *data); extern int can_send(struct sk_buff *skb, int loop); +extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); #endif /* CAN_CORE_H */ diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ae757bcf1280..c8fcbdd2b0e7 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data); u32 ethtool_op_get_flags(struct net_device *dev); int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported); void ethtool_ntuple_flush(struct net_device *dev); +bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** * ðtool_ops - Alter and report network device settings diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 24cfa626931e..239083bfea13 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -122,8 +122,14 @@ struct sk_buff_head { struct sk_buff; -/* To allow 64K frame to be packed as single skb without frag_list */ +/* To allow 64K frame to be packed as single skb without frag_list. Since + * GRO uses frags we allocate at least 16 regardless of page size. + */ +#if (65536/PAGE_SIZE + 2) < 16 +#define MAX_SKB_FRAGS 16 +#else #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2) +#endif typedef struct skb_frag_struct skb_frag_t; diff --git a/include/net/dst.h b/include/net/dst.h index 2a46cbaef92d..75b95df4afe7 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -345,7 +345,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) { - struct dst_entry *child = skb_dst(skb)->child; + struct dst_entry *child = dst_clone(skb_dst(skb)->child); skb_dst_drop(skb); return child; diff --git a/include/net/rose.h b/include/net/rose.h index 5ba9f02731eb..555dd198aab7 100644 --- a/include/net/rose.h +++ b/include/net/rose.h @@ -14,6 +14,12 @@ #define ROSE_MIN_LEN 3 +#define ROSE_CALL_REQ_ADDR_LEN_OFF 3 +#define ROSE_CALL_REQ_ADDR_LEN_VAL 0xAA /* each address is 10 digits */ +#define ROSE_CALL_REQ_DEST_ADDR_OFF 4 +#define ROSE_CALL_REQ_SRC_ADDR_OFF 9 +#define ROSE_CALL_REQ_FACILITIES_OFF 14 + #define ROSE_GFI 0x10 #define ROSE_Q_BIT 0x80 #define ROSE_D_BIT 0x40 @@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *); extern int rose_validate_nr(struct sock *, unsigned short); extern void rose_write_internal(struct sock *, int); extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); -extern int rose_parse_facilities(unsigned char *, struct rose_facilities_struct *); +extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *); extern void rose_disconnect(struct sock *, int, int, int); /* rose_timer.c */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index cffa5dc66449..6ae4bc5ce8a7 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay } #ifdef CONFIG_XFRM_MIGRATE +static inline int xfrm_replay_clone(struct xfrm_state *x, + struct xfrm_state *orig) +{ + x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn), + GFP_KERNEL); + if (!x->replay_esn) + return -ENOMEM; + + x->replay_esn->bmp_len = orig->replay_esn->bmp_len; + x->replay_esn->replay_window = orig->replay_esn->replay_window; + + x->preplay_esn = kmemdup(x->replay_esn, + xfrm_replay_state_esn_len(x->replay_esn), + GFP_KERNEL); + if (!x->preplay_esn) { + kfree(x->replay_esn); + return -ENOMEM; + } + + return 0; +} + static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig) { return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index dce8f0009a12..718b60366dfe 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) { struct net_bridge_port *p; int err = 0; + bool changed_addr; /* Don't allow bridging non-ethernet like devices */ if ((dev->flags & IFF_LOOPBACK) || @@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) list_add_rcu(&p->list, &br->port_list); spin_lock_bh(&br->lock); - br_stp_recalculate_bridge_id(br); + changed_addr = br_stp_recalculate_bridge_id(br); br_features_recompute(br); if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && @@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) br_ifinfo_notify(RTM_NEWLINK, p); + if (changed_addr) + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + dev_set_mtu(br->dev, br_min_mtu(br)); kobject_uevent(&p->kobj, KOBJ_ADD); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 19e2f46ed086..387013d33745 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); extern void br_stp_enable_port(struct net_bridge_port *p); extern void br_stp_disable_port(struct net_bridge_port *p); -extern void br_stp_recalculate_bridge_id(struct net_bridge *br); +extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); extern void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio); diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 79372d4a4055..5593f5aec942 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; /* called under bridge lock */ -void br_stp_recalculate_bridge_id(struct net_bridge *br) +bool br_stp_recalculate_bridge_id(struct net_bridge *br) { const unsigned char *br_mac_zero = (const unsigned char *)br_mac_zero_aligned; @@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) } - if (compare_ether_addr(br->bridge_id.addr, addr)) - br_stp_change_bridge_id(br, addr); + if (compare_ether_addr(br->bridge_id.addr, addr) == 0) + return false; /* no change */ + + br_stp_change_bridge_id(br, addr); + return true; } /* called under bridge lock */ diff --git a/net/can/af_can.c b/net/can/af_can.c index 702be5a2c956..733d66f1b05a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ * af_can socket functions */ -static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; @@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return -ENOIOCTLCMD; |