Commit 52989765 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  be2net: Fix to avoid a crash seen on PPC with LRO and Jumbo frames.
  gro: Flush GRO packets in napi_disable_pending path
  inet: Call skb_orphan before tproxy activates
  mac80211: Use rcu_barrier() on unload.
  sunrpc: Use rcu_barrier() on unload.
  bridge: Use rcu_barrier() instead of syncronize_net() on unload.
  ipv6: Use rcu_barrier() on module unload.
  decnet: Use rcu_barrier() on module unload.
  sky2: Fix checksum endianness
  mdio add missing GPL flag
  sh_eth: remove redundant test on unsigned
  fsl_pq_mdio: Fix fsl_pq_mdio to work with modules
  ipv6: avoid wraparound for expired preferred lifetime
  tcp: missing check ACK flag of received segment in FIN-WAIT-2 state
  atl1*: add device_set_wakeup_enable to atl1*_set_wol
  Phonet: generate Netlink RTM_DELADDR when destroying a device
  Phonet: publicize the Netlink notification function
  Revert "veth: prevent oops caused by netdev destructor"
  cpmac: fix compilation failure introduced with netdev_ops conversion
  ipsec: Fix name of CAST algorithm
parents 9a8fb9ee bd46cb6c
...@@ -281,6 +281,8 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ...@@ -281,6 +281,8 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & WAKE_PHY) if (wol->wolopts & WAKE_PHY)
adapter->wol |= AT_WUFC_LNKC; adapter->wol |= AT_WUFC_LNKC;
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
return 0; return 0;
} }
......
...@@ -365,6 +365,8 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ...@@ -365,6 +365,8 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
if (wol->wolopts & WAKE_PHY) if (wol->wolopts & WAKE_PHY)
adapter->wol |= AT_WUFC_LNKC; adapter->wol |= AT_WUFC_LNKC;
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
return 0; return 0;
} }
......
...@@ -73,7 +73,7 @@ static inline char *nic_name(struct pci_dev *pdev) ...@@ -73,7 +73,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
#define BE_MAX_LRO_DESCRIPTORS 16 #define BE_MAX_LRO_DESCRIPTORS 16
#define BE_MAX_FRAGS_PER_FRAME 16 #define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS))
struct be_dma_mem { struct be_dma_mem {
void *va; void *va;
......
...@@ -162,8 +162,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) ...@@ -162,8 +162,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
return -EINVAL; return -EINVAL;
adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
if (adapter->max_rx_coal > MAX_SKB_FRAGS) if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME)
adapter->max_rx_coal = MAX_SKB_FRAGS - 1; adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
/* if AIC is being turned on now, start with an EQD of 0 */ /* if AIC is being turned on now, start with an EQD of 0 */
if (rx_eq->enable_aic == 0 && if (rx_eq->enable_aic == 0 &&
......
...@@ -666,7 +666,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, ...@@ -666,7 +666,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
{ {
struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_queue_info *rxq = &adapter->rx_obj.q;
struct be_rx_page_info *page_info; struct be_rx_page_info *page_info;
u16 rxq_idx, i, num_rcvd; u16 rxq_idx, i, num_rcvd, j;
u32 pktsize, hdr_len, curr_frag_len; u32 pktsize, hdr_len, curr_frag_len;
u8 *start; u8 *start;
...@@ -709,22 +709,33 @@ static void skb_fill_rx_data(struct be_adapter *adapter, ...@@ -709,22 +709,33 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
/* More frags present for this completion */ /* More frags present for this completion */
pktsize -= curr_frag_len; /* account for above copied frag */ pktsize -= curr_frag_len; /* account for above copied frag */
for (i = 1; i < num_rcvd; i++) { for (i = 1, j = 0; i < num_rcvd; i++) {
index_inc(&rxq_idx, rxq->len); index_inc(&rxq_idx, rxq->len);
page_info = get_rx_page_info(adapter, rxq_idx); page_info = get_rx_page_info(adapter, rxq_idx);
curr_frag_len = min(pktsize, rx_frag_size); curr_frag_len = min(pktsize, rx_frag_size);
skb_shinfo(skb)->frags[i].page = page_info->page; /* Coalesce all frags from the same physical page in one slot */
skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; if (page_info->page_offset == 0) {
skb_shinfo(skb)->frags[i].size = curr_frag_len; /* Fresh page */
j++;
skb_shinfo(skb)->frags[j].page = page_info->page;
skb_shinfo(skb)->frags[j].page_offset =
page_info->page_offset;
skb_shinfo(skb)->frags[j].size = 0;
skb_shinfo(skb)->nr_frags++;
} else {
put_page(page_info->page);
}
skb_shinfo(skb)->frags[j].size += curr_frag_len;
skb->len += curr_frag_len; skb->len += curr_frag_len;
skb->data_len += curr_frag_len; skb->data_len += curr_frag_len;
skb_shinfo(skb)->nr_frags++;
pktsize -= curr_frag_len; pktsize -= curr_frag_len;
memset(page_info, 0, sizeof(*page_info)); memset(page_info, 0, sizeof(*page_info));
} }
BUG_ON(j > MAX_SKB_FRAGS);
done: done:
be_rx_stats_update(adapter, pktsize, num_rcvd); be_rx_stats_update(adapter, pktsize, num_rcvd);
...@@ -786,7 +797,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, ...@@ -786,7 +797,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_queue_info *rxq = &adapter->rx_obj.q;
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
u16 i, rxq_idx = 0, vid; u16 i, rxq_idx = 0, vid, j;
num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
...@@ -794,20 +805,28 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, ...@@ -794,20 +805,28 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
remaining = pkt_size; remaining = pkt_size;
for (i = 0; i < num_rcvd; i++) { for (i = 0, j = -1; i < num_rcvd; i++) {
page_info = get_rx_page_info(adapter, rxq_idx); page_info = get_rx_page_info(adapter, rxq_idx);
curr_frag_len = min(remaining, rx_frag_size); curr_frag_len = min(remaining, rx_frag_size);
rx_frags[i].page = page_info->page; /* Coalesce all frags from the same physical page in one slot */
rx_frags[i].page_offset = page_info->page_offset; if (i == 0 || page_info->page_offset == 0) {
rx_frags[i].size = curr_frag_len; /* First frag or Fresh page */
remaining -= curr_frag_len; j++;
rx_frags[j].page = page_info->page;
rx_frags[j].page_offset = page_info->page_offset;
rx_frags[j].size = 0;
} else {
put_page(page_info->page);
}
rx_frags[j].size += curr_frag_len;
remaining -= curr_frag_len;
index_inc(&rxq_idx, rxq->len); index_inc(&rxq_idx, rxq->len);
memset(page_info, 0, sizeof(*page_info)); memset(page_info, 0, sizeof(*page_info));
} }
BUG_ON(j > MAX_SKB_FRAGS);
if (likely(!vlanf)) { if (likely(!vlanf)) {
lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size,
......
...@@ -1097,7 +1097,7 @@ static const struct net_device_ops cpmac_netdev_ops = { ...@@ -1097,7 +1097,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
.ndo_start_xmit = cpmac_start_xmit, .ndo_start_xmit = cpmac_start_xmit,
.ndo_tx_timeout = cpmac_tx_timeout, .ndo_tx_timeout = cpmac_tx_timeout,
.ndo_set_multicast_list = cpmac_set_multicast_list, .ndo_set_multicast_list = cpmac_set_multicast_list,
.ndo_so_ioctl = cpmac_ioctl, .ndo_do_ioctl = cpmac_ioctl,
.ndo_set_config = cpmac_config, .ndo_set_config = cpmac_config,
.ndo_change_mtu = eth_change_mtu, .ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
......
...@@ -188,7 +188,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) ...@@ -188,7 +188,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
} }
#ifdef CONFIG_GIANFAR #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
{ {
struct gfar __iomem *enet_regs; struct gfar __iomem *enet_regs;
...@@ -206,7 +206,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) ...@@ -206,7 +206,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
#endif #endif
#ifdef CONFIG_UCC_GETH #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
{ {
struct device_node *np = NULL; struct device_node *np = NULL;
...@@ -291,7 +291,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, ...@@ -291,7 +291,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
if (of_device_is_compatible(np, "fsl,gianfar-mdio") || if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
of_device_is_compatible(np, "fsl,gianfar-tbi") || of_device_is_compatible(np, "fsl,gianfar-tbi") ||
of_device_is_compatible(np, "gianfar")) { of_device_is_compatible(np, "gianfar")) {
#ifdef CONFIG_GIANFAR #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
tbipa = get_gfar_tbipa(regs); tbipa = get_gfar_tbipa(regs);
#else #else
err = -ENODEV; err = -ENODEV;
...@@ -299,7 +299,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, ...@@ -299,7 +299,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
#endif #endif
} else if (of_device_is_compatible(np, "fsl,ucc-mdio") || } else if (of_device_is_compatible(np, "fsl,ucc-mdio") ||
of_device_is_compatible(np, "ucc_geth_phy")) { of_device_is_compatible(np, "ucc_geth_phy")) {
#ifdef CONFIG_UCC_GETH #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
u32 id; u32 id;
static u32 mii_mng_master; static u32 mii_mng_master;
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include <linux/mdio.h> #include <linux/mdio.h>
#include <linux/module.h> #include <linux/module.h>
MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
MODULE_LICENSE("GPL");
/** /**
* mdio45_probe - probe for an MDIO (clause 45) device * mdio45_probe - probe for an MDIO (clause 45) device
* @mdio: MDIO interface * @mdio: MDIO interface
......
...@@ -865,8 +865,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ...@@ -865,8 +865,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_private *mdp = netdev_priv(ndev);
struct sh_eth_cpu_data *cd = mdp->cd; struct sh_eth_cpu_data *cd = mdp->cd;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u32 ioaddr, boguscnt = RX_RING_SIZE; u32 ioaddr, intr_status = 0;
u32 intr_status = 0;
ioaddr = ndev->base_addr; ioaddr = ndev->base_addr;
spin_lock(&mdp->lock); spin_lock(&mdp->lock);
...@@ -901,12 +900,6 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ...@@ -901,12 +900,6 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
if (intr_status & cd->eesr_err_check) if (intr_status & cd->eesr_err_check)
sh_eth_error(ndev, intr_status); sh_eth_error(ndev, intr_status);
if (--boguscnt < 0) {
printk(KERN_WARNING
"%s: Too much work at interrupt, status=0x%4.4x.\n",
ndev->name, intr_status);
}
other_irq: other_irq:
spin_unlock(&mdp->lock); spin_unlock(&mdp->lock);
......
...@@ -2495,7 +2495,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) ...@@ -2495,7 +2495,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
if (likely(status >> 16 == (status & 0xffff))) { if (likely(status >> 16 == (status & 0xffff))) {
skb = sky2->rx_ring[sky2->rx_next].skb; skb = sky2->rx_ring[sky2->rx_next].skb;
skb->ip_summed = CHECKSUM_COMPLETE; skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = status & 0xffff; skb->csum = le16_to_cpu(status);
} else { } else {
printk(KERN_NOTICE PFX "%s: hardware receive " printk(KERN_NOTICE PFX "%s: hardware receive "
"checksum problem (status = %#x)\n", "checksum problem (status = %#x)\n",
......
...@@ -208,11 +208,14 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -208,11 +208,14 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *veth_get_stats(struct net_device *dev) static struct net_device_stats *veth_get_stats(struct net_device *dev)
{ {
struct veth_priv *priv = netdev_priv(dev); struct veth_priv *priv;
struct net_device_stats *dev_stats = &dev->stats; struct net_device_stats *dev_stats;
unsigned int cpu; int cpu;
struct veth_net_stats *stats; struct veth_net_stats *stats;
priv = netdev_priv(dev);
dev_stats = &dev->stats;
dev_stats->rx_packets = 0; dev_stats->rx_packets = 0;
dev_stats->tx_packets = 0; dev_stats->tx_packets = 0;
dev_stats->rx_bytes = 0; dev_stats->rx_bytes = 0;
...@@ -220,7 +223,6 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) ...@@ -220,7 +223,6 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev)
dev_stats->tx_dropped = 0; dev_stats->tx_dropped = 0;
dev_stats->rx_dropped = 0; dev_stats->rx_dropped = 0;
if (priv->stats)
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
stats = per_cpu_ptr(priv->stats, cpu); stats = per_cpu_ptr(priv->stats, cpu);
...@@ -257,8 +259,6 @@ static int veth_close(struct net_device *dev) ...@@ -257,8 +259,6 @@ static int veth_close(struct net_device *dev)
netif_carrier_off(dev); netif_carrier_off(dev);
netif_carrier_off(priv->peer); netif_carrier_off(priv->peer);
free_percpu(priv->stats);
priv->stats = NULL;
return 0; return 0;
} }
...@@ -289,6 +289,15 @@ static int veth_dev_init(struct net_device *dev) ...@@ -289,6 +289,15 @@ static int veth_dev_init(struct net_device *dev)
return 0; return 0;
} }
static void veth_dev_free(struct net_device *dev)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
free_percpu(priv->stats);
free_netdev(dev);
}
static const struct net_device_ops veth_netdev_ops = { static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init, .ndo_init = veth_dev_init,
.ndo_open = veth_open, .ndo_open = veth_open,
...@@ -306,7 +315,7 @@ static void veth_setup(struct net_device *dev) ...@@ -306,7 +315,7 @@ static void veth_setup(struct net_device *dev)
dev->netdev_ops = &veth_netdev_ops; dev->netdev_ops = &veth_netdev_ops;
dev->ethtool_ops = &veth_ethtool_ops; dev->ethtool_ops = &veth_ethtool_ops;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
dev->destructor = free_netdev; dev->destructor = veth_dev_free;
} }
/* /*
......
...@@ -45,6 +45,7 @@ int phonet_address_add(struct net_device *dev, u8 addr); ...@@ -45,6 +45,7 @@ int phonet_address_add(struct net_device *dev, u8 addr);
int phonet_address_del(struct net_device *dev, u8 addr); int phonet_address_del(struct net_device *dev, u8 addr);
u8 phonet_address_get(struct net_device *dev, u8 addr); u8 phonet_address_get(struct net_device *dev, u8 addr);
int phonet_address_lookup(struct net *net, u8 addr); int phonet_address_lookup(struct net *net, u8 addr);
void phonet_address_notify(int event, struct net_device *dev, u8 addr);
#define PN_NO_ADDR 0xff #define PN_NO_ADDR 0xff
......
...@@ -93,7 +93,7 @@ static void __exit br_deinit(void) ...@@ -93,7 +93,7 @@ static void __exit br_deinit(void)
unregister_pernet_subsys(&br_net_ops); unregister_pernet_subsys(&br_net_ops);
synchronize_net(); rcu_barrier(); /* Wait for completion of call_rcu()'s */
br_netfilter_fini(); br_netfilter_fini();
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
......
...@@ -2823,9 +2823,11 @@ static void net_rx_action(struct softirq_action *h) ...@@ -2823,9 +2823,11 @@ static void net_rx_action(struct softirq_action *h)
* move the instance around on the list at-will. * move the instance around on the list at-will.
*/ */
if (unlikely(work == weight)) { if (unlikely(work == weight)) {
if (unlikely(napi_disable_pending(n))) if (unlikely(napi_disable_pending(n))) {
__napi_complete(n); local_irq_enable();
else napi_complete(n);
local_irq_disable();
} else
list_move_tail(&n->poll_list, list); list_move_tail(&n->poll_list, list);
} }
......
...@@ -2413,6 +2413,8 @@ static void __exit decnet_exit(void) ...@@ -2413,6 +2413,8 @@ static void __exit decnet_exit(void)
proc_net_remove(&init_net, "decnet"); proc_net_remove(&init_net, "decnet");
proto_unregister(&dn_proto); proto_unregister(&dn_proto);
rcu_barrier_bh(); /* Wait for completion of call_rcu_bh()'s */
} }
module_exit(decnet_exit); module_exit(decnet_exit);
#endif #endif
...@@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, ...@@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
/* Remove any debris in the socket control block */ /* Remove any debris in the socket control block */
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
/* Must drop socket now because of tproxy. */
skb_orphan(skb);
return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL,
ip_rcv_finish); ip_rcv_finish);
......
...@@ -128,7 +128,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, ...@@ -128,7 +128,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
goto kill_with_rst; goto kill_with_rst;
/* Dup ACK? */ /* Dup ACK? */
if (!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || if (!th->ack ||
!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) { TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
inet_twsk_put(tw); inet_twsk_put(tw);
return TCP_TW_SUCCESS; return TCP_TW_SUCCESS;
......
...@@ -3362,7 +3362,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, ...@@ -3362,7 +3362,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
valid = ifa->valid_lft; valid = ifa->valid_lft;
if (preferred != INFINITY_LIFE_TIME) { if (preferred != INFINITY_LIFE_TIME) {
long tval = (jiffies - ifa->tstamp)/HZ; long tval = (jiffies - ifa->tstamp)/HZ;
if (preferred > tval)
preferred -= tval; preferred -= tval;
else
preferred = 0;
if (valid != INFINITY_LIFE_TIME) if (valid != INFINITY_LIFE_TIME)
valid -= tval; valid -= tval;
} }
......
...@@ -1284,6 +1284,8 @@ static void __exit inet6_exit(void) ...@@ -1284,6 +1284,8 @@ static void __exit inet6_exit(void)
proto_unregister(&udplitev6_prot); proto_unregister(&udplitev6_prot);
proto_unregister(&udpv6_prot); proto_unregister(&udpv6_prot);
proto_unregister(&tcpv6_prot); proto_unregister(&tcpv6_prot);
rcu_barrier(); /* Wait for completion of call_rcu()'s */
} }
module_exit(inet6_exit); module_exit(inet6_exit);
......
...@@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
rcu_read_unlock(); rcu_read_unlock();
/* Must drop socket now because of tproxy. */
skb_orphan(skb);
return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL,
ip6_rcv_finish); ip6_rcv_finish);
err: err:
......
...@@ -494,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -494,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
* should it be using the interface and enqueuing * should it be using the interface and enqueuing
* frames at this very time on another CPU. * frames at this very time on another CPU.
*/ */
synchronize_rcu(); rcu_barrier(); /* Wait for RX path and call_rcu()'s */
skb_queue_purge(&sdata->u.mesh.skb_queue); skb_queue_purge(&sdata->u.mesh.skb_queue);
} }
......
...@@ -69,10 +69,27 @@ static struct phonet_device *__phonet_get(struct net_device *dev) ...@@ -69,10 +69,27 @@ static struct phonet_device *__phonet_get(struct net_device *dev)
return NULL; return NULL;
} }
static void __phonet_device_free(struct phonet_device *pnd) static void phonet_device_destroy(struct net_device *dev)
{ {
struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
struct phonet_device *pnd;
ASSERT_RTNL();
spin_lock_bh(&pndevs->lock);
pnd = __phonet_get(dev);
if (pnd)
list_del(&pnd->list); list_del(&pnd->list);
spin_unlock_bh(&pndevs->lock);
if (pnd) {
u8 addr;
for (addr = find_first_bit(pnd->addrs, 64); addr < 64;
addr = find_next_bit(pnd->addrs, 64, 1+addr))
phonet_address_notify(RTM_DELADDR, dev, addr);
kfree(pnd); kfree(pnd);
}
} }
struct net_device *phonet_device_get(struct net *net) struct net_device *phonet_device_get(struct net *net)
...@@ -126,8 +143,10 @@ int phonet_address_del(struct net_device *dev, u8 addr) ...@@ -126,8 +143,10 @@ int phonet_address_del(struct net_device *dev, u8 addr)
pnd = __phonet_get(dev); pnd = __phonet_get(dev);
if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs))
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
else if (bitmap_empty(pnd->addrs, 64)) else if (bitmap_empty(pnd->addrs, 64)) {
__phonet_device_free(pnd); list_del(&pnd->list);
kfree(pnd);
}
spin_unlock_bh(&pndevs->lock); spin_unlock_bh(&pndevs->lock);
return err; return err;
} }
...@@ -181,18 +200,8 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, ...@@ -181,18 +200,8 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what,
{ {
struct net_device *dev = arg; struct net_device *dev = arg;
if (what == NETDEV_UNREGISTER) { if (what == NETDEV_UNREGISTER)
struct phonet_device_list *pndevs; phonet_device_destroy(dev);
struct phonet_device *pnd;
/* Destroy phonet-specific device data */
pndevs = phonet_device_list(dev_net(dev));
spin_lock_bh(&pndevs->lock);
pnd = __phonet_get(dev);
if (pnd)
__phonet_device_free(pnd);
spin_unlock_bh(&pndevs->lock);
}
return 0; return 0;
} }
...@@ -218,11 +227,12 @@ static int phonet_init_net(struct net *net) ...@@ -218,11 +227,12 @@ static int phonet_init_net(struct net *net)
static void phonet_exit_net(struct net *net) static void phonet_exit_net(struct net *net)
{ {
struct phonet_net *pnn = net_generic(net, phonet_net_id); struct phonet_net *pnn = net_generic(net, phonet_net_id);
struct phonet_device *pnd, *n; struct net_device *dev;
list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list)
__phonet_device_free(pnd);
rtnl_lock();
for_each_netdev(net, dev)
phonet_device_destroy(dev);
rtnl_unlock();
kfree(pnn); kfree(pnn);
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
u32 pid, u32 seq, int event); u32 pid, u32 seq, int event);
static void rtmsg_notify(int event, struct net_device *dev, u8 addr) void phonet_address_notify(int event, struct net_device *dev, u8 addr)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
...@@ -94,7 +94,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr) ...@@ -94,7 +94,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
else else
err = phonet_address_del(dev, pnaddr); err = phonet_address_del(dev, pnaddr);
if (!err) if (!err)
rtmsg_notify(nlh->nlmsg_type, dev, pnaddr); phonet_address_notify(nlh->nlmsg_type, dev, pnaddr);
return err; return err;
} }
......
...@@ -66,6 +66,7 @@ cleanup_sunrpc(void) ...@@ -66,6 +66,7 @@ cleanup_sunrpc(void)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
rpc_proc_exit(); rpc_proc_exit();
#endif #endif
rcu_barrier(); /* Wait for completion of call_rcu()'s */
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(init_sunrpc); module_init(init_sunrpc);
......
...@@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] = { ...@@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] = {
} }
}, },
{ {
.name = "cbc(cast128)", .name = "cbc(cast5)",
.compat = "cast128", .compat = "cast5",
.uinfo = { .uinfo = {
.encr = { .encr = {
......
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