Commit ef7d1b24 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

parents ed0da6fc 78eb8877
...@@ -294,15 +294,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max ...@@ -294,15 +294,15 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
Default: 87380*2 bytes. Default: 87380*2 bytes.
tcp_mem - vector of 3 INTEGERs: min, pressure, max tcp_mem - vector of 3 INTEGERs: min, pressure, max
low: below this number of pages TCP is not bothered about its min: below this number of pages TCP is not bothered about its
memory appetite. memory appetite.
pressure: when amount of memory allocated by TCP exceeds this number pressure: when amount of memory allocated by TCP exceeds this number
of pages, TCP moderates its memory consumption and enters memory of pages, TCP moderates its memory consumption and enters memory
pressure mode, which is exited when memory consumption falls pressure mode, which is exited when memory consumption falls
under "low". under "min".
high: number of pages allowed for queueing by all TCP sockets. max: number of pages allowed for queueing by all TCP sockets.
Defaults are calculated at boot time from amount of available Defaults are calculated at boot time from amount of available
memory. memory.
......
...@@ -56,8 +56,8 @@ ...@@ -56,8 +56,8 @@
#define DRV_MODULE_NAME "bnx2" #define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.4.43" #define DRV_MODULE_VERSION "1.4.44"
#define DRV_MODULE_RELDATE "June 28, 2006" #define DRV_MODULE_RELDATE "August 10, 2006"
#define RUN_AT(x) (jiffies + (x)) #define RUN_AT(x) (jiffies + (x))
...@@ -209,8 +209,10 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); ...@@ -209,8 +209,10 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
static inline u32 bnx2_tx_avail(struct bnx2 *bp) static inline u32 bnx2_tx_avail(struct bnx2 *bp)
{ {
u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons); u32 diff;
smp_mb();
diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
if (diff > MAX_TX_DESC_CNT) if (diff > MAX_TX_DESC_CNT)
diff = (diff & MAX_TX_DESC_CNT) - 1; diff = (diff & MAX_TX_DESC_CNT) - 1;
return (bp->tx_ring_size - diff); return (bp->tx_ring_size - diff);
...@@ -1569,7 +1571,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) ...@@ -1569,7 +1571,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
unsigned long align; unsigned long align;
skb = dev_alloc_skb(bp->rx_buf_size); skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
if (skb == NULL) { if (skb == NULL) {
return -ENOMEM; return -ENOMEM;
} }
...@@ -1578,7 +1580,6 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) ...@@ -1578,7 +1580,6 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
skb_reserve(skb, 8 - align); skb_reserve(skb, 8 - align);
} }
skb->dev = bp->dev;
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size, mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
...@@ -1686,15 +1687,20 @@ bnx2_tx_int(struct bnx2 *bp) ...@@ -1686,15 +1687,20 @@ bnx2_tx_int(struct bnx2 *bp)
} }
bp->tx_cons = sw_cons; bp->tx_cons = sw_cons;
/* Need to make the tx_cons update visible to bnx2_start_xmit()
* before checking for netif_queue_stopped(). Without the
* memory barrier, there is a small possibility that bnx2_start_xmit()
* will miss it and cause the queue to be stopped forever.
*/
smp_mb();
if (unlikely(netif_queue_stopped(bp->dev))) { if (unlikely(netif_queue_stopped(bp->dev)) &&
spin_lock(&bp->tx_lock); (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) {
netif_tx_lock(bp->dev);
if ((netif_queue_stopped(bp->dev)) && if ((netif_queue_stopped(bp->dev)) &&
(bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) { (bnx2_tx_avail(bp) > bp->tx_wake_thresh))
netif_wake_queue(bp->dev); netif_wake_queue(bp->dev);
} netif_tx_unlock(bp->dev);
spin_unlock(&bp->tx_lock);
} }
} }
...@@ -1786,7 +1792,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) ...@@ -1786,7 +1792,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) { if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
struct sk_buff *new_skb; struct sk_buff *new_skb;
new_skb = dev_alloc_skb(len + 2); new_skb = netdev_alloc_skb(bp->dev, len + 2);
if (new_skb == NULL) if (new_skb == NULL)
goto reuse_rx; goto reuse_rx;
...@@ -1797,7 +1803,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget) ...@@ -1797,7 +1803,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
skb_reserve(new_skb, 2); skb_reserve(new_skb, 2);
skb_put(new_skb, len); skb_put(new_skb, len);
new_skb->dev = bp->dev;
bnx2_reuse_rx_skb(bp, skb, bnx2_reuse_rx_skb(bp, skb,
sw_ring_cons, sw_ring_prod); sw_ring_cons, sw_ring_prod);
...@@ -3503,6 +3508,8 @@ bnx2_init_tx_ring(struct bnx2 *bp) ...@@ -3503,6 +3508,8 @@ bnx2_init_tx_ring(struct bnx2 *bp)
struct tx_bd *txbd; struct tx_bd *txbd;
u32 val; u32 val;
bp->tx_wake_thresh = bp->tx_ring_size / 2;
txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT]; txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32; txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
...@@ -3952,7 +3959,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) ...@@ -3952,7 +3959,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
return -EINVAL; return -EINVAL;
pkt_size = 1514; pkt_size = 1514;
skb = dev_alloc_skb(pkt_size); skb = netdev_alloc_skb(bp->dev, pkt_size);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
packet = skb_put(skb, pkt_size); packet = skb_put(skb, pkt_size);
...@@ -4390,10 +4397,8 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) ...@@ -4390,10 +4397,8 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
#endif #endif
/* Called with netif_tx_lock. /* Called with netif_tx_lock.
* hard_start_xmit is pseudo-lockless - a lock is only required when * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
* the tx queue is full. This way, we get the benefit of lockless * netif_wake_queue().
* operations most of the time without the complexities to handle
* netif_stop_queue/wake_queue race conditions.
*/ */
static int static int
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
...@@ -4512,12 +4517,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -4512,12 +4517,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies; dev->trans_start = jiffies;
if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) { if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
spin_lock(&bp->tx_lock);
netif_stop_queue(dev); netif_stop_queue(dev);
if (bnx2_tx_avail(bp) > bp->tx_wake_thresh)
if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
netif_wake_queue(dev); netif_wake_queue(dev);
spin_unlock(&bp->tx_lock);
} }
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -5628,7 +5630,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) ...@@ -5628,7 +5630,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->pdev = pdev; bp->pdev = pdev;
spin_lock_init(&bp->phy_lock); spin_lock_init(&bp->phy_lock);
spin_lock_init(&bp->tx_lock);
INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
...@@ -5751,7 +5752,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) ...@@ -5751,7 +5752,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->mac_addr[5] = (u8) reg; bp->mac_addr[5] = (u8) reg;
bp->tx_ring_size = MAX_TX_DESC_CNT; bp->tx_ring_size = MAX_TX_DESC_CNT;
bnx2_set_rx_ring_size(bp, 100); bnx2_set_rx_ring_size(bp, 255);
bp->rx_csum = 1; bp->rx_csum = 1;
......
...@@ -3890,10 +3890,6 @@ struct bnx2 { ...@@ -3890,10 +3890,6 @@ struct bnx2 {
u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
u16 tx_prod; u16 tx_prod;
struct tx_bd *tx_desc_ring;
struct sw_bd *tx_buf_ring;
int tx_ring_size;
u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
u16 hw_tx_cons; u16 hw_tx_cons;
...@@ -3916,9 +3912,11 @@ struct bnx2 { ...@@ -3916,9 +3912,11 @@ struct bnx2 {
struct sw_bd *rx_buf_ring; struct sw_bd *rx_buf_ring;
struct rx_bd *rx_desc_ring[MAX_RX_RINGS]; struct rx_bd *rx_desc_ring[MAX_RX_RINGS];
/* Only used to synchronize netif_stop_queue/wake_queue when tx */ /* TX constants */
/* ring is full */ struct tx_bd *tx_desc_ring;
spinlock_t tx_lock; struct sw_bd *tx_buf_ring;
int tx_ring_size;
u32 tx_wake_thresh;
/* End of fields used in the performance code paths. */ /* End of fields used in the performance code paths. */
......
...@@ -192,7 +192,7 @@ struct cardmap { ...@@ -192,7 +192,7 @@ struct cardmap {
void *ptr[CARDMAP_WIDTH]; void *ptr[CARDMAP_WIDTH];
}; };
static void *cardmap_get(struct cardmap *map, unsigned int nr); static void *cardmap_get(struct cardmap *map, unsigned int nr);
static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr); static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
static unsigned int cardmap_find_first_free(struct cardmap *map); static unsigned int cardmap_find_first_free(struct cardmap *map);
static void cardmap_destroy(struct cardmap **map); static void cardmap_destroy(struct cardmap **map);
...@@ -1995,10 +1995,9 @@ ppp_register_channel(struct ppp_channel *chan) ...@@ -1995,10 +1995,9 @@ ppp_register_channel(struct ppp_channel *chan)
{ {
struct channel *pch; struct channel *pch;
pch = kmalloc(sizeof(struct channel), GFP_KERNEL); pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
if (pch == 0) if (pch == 0)
return -ENOMEM; return -ENOMEM;
memset(pch, 0, sizeof(struct channel));
pch->ppp = NULL; pch->ppp = NULL;
pch->chan = chan; pch->chan = chan;
chan->ppp = pch; chan->ppp = pch;
...@@ -2408,13 +2407,12 @@ ppp_create_interface(int unit, int *retp) ...@@ -2408,13 +2407,12 @@ ppp_create_interface(int unit, int *retp)
int ret = -ENOMEM; int ret = -ENOMEM;
int i; int i;
ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL); ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL);
if (!ppp) if (!ppp)
goto out; goto out;
dev = alloc_netdev(0, "", ppp_setup); dev = alloc_netdev(0, "", ppp_setup);
if (!dev) if (!dev)
goto out1; goto out1;
memset(ppp, 0, sizeof(struct ppp));
ppp->mru = PPP_MRU; ppp->mru = PPP_MRU;
init_ppp_file(&ppp->file, INTERFACE); init_ppp_file(&ppp->file, INTERFACE);
...@@ -2454,11 +2452,16 @@ ppp_create_interface(int unit, int *retp) ...@@ -2454,11 +2452,16 @@ ppp_create_interface(int unit, int *retp)
} }
atomic_inc(&ppp_unit_count); atomic_inc(&ppp_unit_count);
cardmap_set(&all_ppp_units, unit, ppp); ret = cardmap_set(&all_ppp_units, unit, ppp);
if (ret != 0)
goto out3;
mutex_unlock(&all_ppp_mutex); mutex_unlock(&all_ppp_mutex);
*retp = 0; *retp = 0;
return ppp; return ppp;
out3:
atomic_dec(&ppp_unit_count);
out2: out2:
mutex_unlock(&all_ppp_mutex); mutex_unlock(&all_ppp_mutex);
free_netdev(dev); free_netdev(dev);
...@@ -2695,7 +2698,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr) ...@@ -2695,7 +2698,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr)
return NULL; return NULL;
} }
static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
{ {
struct cardmap *p; struct cardmap *p;
int i; int i;
...@@ -2704,8 +2707,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) ...@@ -2704,8 +2707,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) { if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
do { do {
/* need a new top level */ /* need a new top level */
struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
memset(np, 0, sizeof(*np)); if (!np)
goto enomem;
np->ptr[0] = p; np->ptr[0] = p;
if (p != NULL) { if (p != NULL) {
np->shift = p->shift + CARDMAP_ORDER; np->shift = p->shift + CARDMAP_ORDER;
...@@ -2719,8 +2723,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) ...@@ -2719,8 +2723,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
while (p->shift > 0) { while (p->shift > 0) {
i = (nr >> p->shift) & CARDMAP_MASK; i = (nr >> p->shift) & CARDMAP_MASK;
if (p->ptr[i] == NULL) { if (p->ptr[i] == NULL) {
struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
memset(np, 0, sizeof(*np)); if (!np)
goto enomem;
np->shift = p->shift - CARDMAP_ORDER; np->shift = p->shift - CARDMAP_ORDER;
np->parent = p; np->parent = p;
p->ptr[i] = np; p->ptr[i] = np;
...@@ -2735,6 +2740,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) ...@@ -2735,6 +2740,9 @@ static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
set_bit(i, &p->inuse); set_bit(i, &p->inuse);
else else
clear_bit(i, &p->inuse); clear_bit(i, &p->inuse);
return 0;
enomem:
return -ENOMEM;
} }
static unsigned int cardmap_find_first_free(struct cardmap *map) static unsigned int cardmap_find_first_free(struct cardmap *map)
......
...@@ -155,6 +155,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, ...@@ -155,6 +155,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
{ {
struct net_device_stats *stats; struct net_device_stats *stats;
if (skb_bond_should_drop(skb)) {
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK]; skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
if (skb->dev == NULL) { if (skb->dev == NULL) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
......
...@@ -320,6 +320,9 @@ struct net_device ...@@ -320,6 +320,9 @@ struct net_device
#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
/* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
...@@ -1012,6 +1015,30 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) ...@@ -1012,6 +1015,30 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
unlikely(skb->ip_summed != CHECKSUM_HW)); unlikely(skb->ip_summed != CHECKSUM_HW));
} }
/* On bonding slaves other than the currently active slave, suppress
* duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
*/
static inline int skb_bond_should_drop(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct net_device *master = dev->master;
if (master &&
(dev->priv_flags & IFF_SLAVE_INACTIVE)) {
if (master->priv_flags & IFF_MASTER_ALB) {
if (skb->pkt_type != PACKET_BROADCAST &&
skb->pkt_type != PACKET_MULTICAST)
return 0;
}
if (master->priv_flags & IFF_MASTER_8023AD &&
skb->protocol == __constant_htons(ETH_P_SLOW))
return 0;
return 1;
}
return 0;
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_DEV_H */ #endif /* _LINUX_DEV_H */
...@@ -507,7 +507,7 @@ int __init atm_proc_init(void) ...@@ -507,7 +507,7 @@ int __init atm_proc_init(void)
goto out; goto out;
} }
void __exit atm_proc_exit(void) void atm_proc_exit(void)
{ {
atm_proc_dirs_remove(); atm_proc_dirs_remove();
} }
...@@ -386,12 +386,17 @@ void br_features_recompute(struct net_bridge *br) ...@@ -386,12 +386,17 @@ void br_features_recompute(struct net_bridge *br)
checksum = 0; checksum = 0;
if (feature & NETIF_F_GSO) if (feature & NETIF_F_GSO)
feature |= NETIF_F_TSO; feature |= NETIF_F_GSO_SOFTWARE;
feature |= NETIF_F_GSO; feature |= NETIF_F_GSO;
features &= feature; features &= feature;
} }
if (!(checksum & NETIF_F_ALL_CSUM))
features &= ~NETIF_F_SG;
if (!(features & NETIF_F_SG))
features &= ~NETIF_F_GSO_MASK;
br->dev->features = features | checksum | NETIF_F_LLTX | br->dev->features = features | checksum | NETIF_F_LLTX |
NETIF_F_GSO_ROBUST; NETIF_F_GSO_ROBUST;
} }
......
...@@ -116,6 +116,7 @@ ...@@ -116,6 +116,7 @@
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/ctype.h>
/* /*
* The list of packet types we will receive (as opposed to discard) * The list of packet types we will receive (as opposed to discard)
...@@ -632,14 +633,22 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas ...@@ -632,14 +633,22 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas
* @name: name string * @name: name string
* *
* Network device names need to be valid file names to * Network device names need to be valid file names to
* to allow sysfs to work * to allow sysfs to work. We also disallow any kind of
* whitespace.
*/ */
int dev_valid_name(const char *name) int dev_valid_name(const char *name)
{ {
return !(*name == '\0' if (*name == '\0')
|| !strcmp(name, ".") return 0;
|| !strcmp(name, "..") if (!strcmp(name, ".") || !strcmp(name, ".."))
|| strchr(name, '/')); return 0;
while (*name) {
if (*name == '/' || isspace(*name))
return 0;
name++;
}
return 1;
} }
/** /**
...@@ -1619,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) ...@@ -1619,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
if (dev->master) { if (dev->master) {
/* if (skb_bond_should_drop(skb)) {
* On bonding slaves other than the currently active
* slave, suppress duplicates except for 802.3ad
* ETH_P_SLOW and alb non-mcast/bcast.
*/
if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
if (dev->master->priv_flags & IFF_MASTER_ALB) {
if (skb->pkt_type != PACKET_BROADCAST &&
skb->pkt_type != PACKET_MULTICAST)
goto keep;
}
if (dev->master->priv_flags & IFF_MASTER_8023AD &&
skb->protocol == __constant_htons(ETH_P_SLOW))
goto keep;
kfree_skb(skb); kfree_skb(skb);
return NULL; return NULL;
} }
keep:
skb->dev = dev->master; skb->dev = dev->master;
} }
......
...@@ -130,12 +130,13 @@ void __init net_random_init(void) ...@@ -130,12 +130,13 @@ void __init net_random_init(void)
static int net_random_reseed(void) static int net_random_reseed(void)
{ {
int i; int i;
unsigned long seed[NR_CPUS]; unsigned long seed;
get_random_bytes(seed, sizeof(seed));
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
struct nrnd_state *state = &per_cpu(net_rand_state,i); struct nrnd_state *state = &per_cpu(net_rand_state,i);
__net_srandom(state, seed[i]);
get_random_bytes(&seed, sizeof(seed));
__net_srandom(state, seed);
} }
return 0; return 0;
} }
......
...@@ -159,7 +159,7 @@ void free_fib_info(struct fib_info *fi) ...@@ -159,7 +159,7 @@ void free_fib_info(struct fib_info *fi)
void fib_release_info(struct fib_info *fi) void fib_release_info(struct fib_info *fi)
{ {
write_lock(&fib_info_lock); write_lock_bh(&fib_info_lock);
if (fi && --fi->fib_treeref == 0) { if (fi && --fi->fib_treeref == 0) {
hlist_del(&fi->fib_hash); hlist_del(&fi->fib_hash);
if (fi->fib_prefsrc) if (fi->fib_prefsrc)
...@@ -172,7 +172,7 @@ void fib_release_info(struct fib_info *fi) ...@@ -172,7 +172,7 @@ void fib_release_info(struct fib_info *fi)
fi->fib_dead = 1; fi->fib_dead = 1;
fib_info_put(fi); fib_info_put(fi);
} }
write_unlock(&fib_info_lock); write_unlock_bh(&fib_info_lock);
} }
static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
...@@ -598,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, ...@@ -598,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
unsigned int old_size = fib_hash_size; unsigned int old_size = fib_hash_size;
unsigned int i, bytes; unsigned int i, bytes;
write_lock(&fib_info_lock); write_lock_bh(&fib_info_lock);
old_info_hash = fib_info_hash; old_info_hash = fib_info_hash;
old_laddrhash = fib_info_laddrhash; old_laddrhash = fib_info_laddrhash;
fib_hash_size = new_size; fib_hash_size = new_size;
...@@ -639,7 +639,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, ...@@ -639,7 +639,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
} }
fib_info_laddrhash = new_laddrhash; fib_info_laddrhash = new_laddrhash;
write_unlock(&fib_info_lock); write_unlock_bh(&fib_info_lock);
bytes = old_size * sizeof(struct hlist_head *); bytes = old_size * sizeof(struct hlist_head *);
fib_hash_free(old_info_hash, bytes); fib_hash_free(old_info_hash, bytes);
...@@ -820,7 +820,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta, ...@@ -820,7 +820,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
fi->fib_treeref++; fi->fib_treeref++;
atomic_inc(&fi->fib_clntref); atomic_inc(&fi->fib_clntref);
write_lock(&fib_info_lock); write_lock_bh(&fib_info_lock);
hlist_add_head(&fi->fib_hash, hlist_add_head(&fi->fib_hash,
&fib_info_hash[fib_info_hashfn(fi)]); &fib_info_hash[fib_info_hashfn(fi)]);
if (fi->fib_prefsrc) { if (fi->fib_prefsrc) {
...@@ -839,7 +839,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta, ...@@ -839,7 +839,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
head = &fib_info_devhash[hash]; head = &fib_info_devhash[hash];
hlist_add_head(&nh->nh_hash, head); hlist_add_head(&nh->nh_hash, head);
} endfor_nexthops(fi) } endfor_nexthops(fi)
write_unlock(&fib_info_lock); write_unlock_bh(&fib_info_lock);
return fi; return fi;
err_inval: err_inval:
......
...@@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) ...@@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
struct in_device *in_dev; struct in_device *in_dev;
u32 group = imr->imr_multiaddr.s_addr; u32 group = imr->imr_multiaddr.s_addr;
u32 ifindex; u32 ifindex;
int ret = -EADDRNOTAVAIL;
rtnl_lock(); rtnl_lock();
in_dev = ip_mc_find_dev(imr); in_dev = ip_mc_find_dev(imr);
if (!in_dev) {
rtnl_unlock();
return -ENODEV;
}
ifindex = imr->imr_ifindex; ifindex = imr->imr_ifindex;
for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
if (iml->multi.imr_multiaddr.s_addr == group && if (iml->multi.imr_multiaddr.s_addr != group)
iml->multi.imr_ifindex == ifindex) { continue;
if (ifindex) {
if (iml->multi.imr_ifindex != ifindex)
continue;
} else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
iml->multi.imr_address.s_addr)
continue;
(void) ip_mc_leave_src(sk, iml, in_dev); (void) ip_mc_leave_src(sk, iml, in_dev);
*imlp = iml->next; *imlp = iml->next;
if (in_dev)
ip_mc_dec_group(in_dev, group); ip_mc_dec_group(in_dev, group);
rtnl_unlock(); rtnl_unlock();
sock_kfree_s(sk, iml, sizeof(*iml)); sock_kfree_s(sk, iml, sizeof(*iml));
return 0; return 0;
} }
} if (!in_dev)
ret = -ENODEV;
rtnl_unlock(); rtnl_unlock();
return -EADDRNOTAVAIL; return ret;
} }
int ip_mc_source(int add, int omode, struct sock *sk, struct int ip_mc_source(int add, int omode, struct sock *sk, struct
...@@ -2199,13 +2205,13 @@ void ip_mc_drop_socket(struct sock *sk) ...@@ -2199,13 +2205,13 @@ void ip_mc_drop_socket(struct sock *sk)
struct in_device *in_dev; struct in_device *in_dev;
inet->mc_list = iml->next; inet->mc_list = iml->next;
if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) { in_dev = inetdev_by_index(iml->multi.imr_ifindex);
(void) ip_mc_leave_src(sk, iml, in_dev); (void) ip_mc_leave_src(sk, iml, in_dev);
if (in_dev != NULL) {
ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
in_dev_put(in_dev); in_dev_put(in_dev);
} }
sock_kfree_s(sk, iml, sizeof(*iml)); sock_kfree_s(sk, iml, sizeof(*iml));
} }
rtnl_unlock(); rtnl_unlock();
} }
......
...@@ -415,21 +415,18 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -415,21 +415,18 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
cb->args[0], *id); cb->args[0], *id);
read_lock_bh(&ip_conntrack_lock); read_lock_bh(&ip_conntrack_lock);
last = (struct ip_conntrack *)cb->args[1];
for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
restart: restart:
last = (struct ip_conntrack *)cb->args[1];
list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
h = (struct ip_conntrack_tuple_hash *) i; h = (struct ip_conntrack_tuple_hash *) i;
if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue; continue;
ct = tuplehash_to_ctrack(h); ct = tuplehash_to_ctrack(h);
if (last != NULL) { if (cb->args[1]) {
if (ct == last) { if (ct != last)
ip_conntrack_put(last);
cb->args[1] = 0;
last = NULL;
} else
continue; continue;
cb->args[1] = 0;
} }
if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
...@@ -440,17 +437,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -440,17 +437,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
goto out; goto out;
} }
} }
if (last != NULL) { if (cb->args[1]) {
ip_conntrack_put(last);
cb->args[1] = 0; cb->args[1] = 0;
goto restart; goto restart;
} }
} }
out: out:
read_unlock_bh(&ip_conntrack_lock); read_unlock_bh(&ip_conntrack_lock);
if (last)
ip_conntrack_put(last);
DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
return skb->len; return skb->len;
} }
......
...@@ -230,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb, ...@@ -230,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb,
const char *indev, *outdev; const char *indev, *outdev;
void *table_base; void *table_base;
struct ipt_entry *e, *back; struct ipt_entry *e, *back;
struct xt_table_info *private = table->private; struct xt_table_info *private;
/* Initialization */ /* Initialization */
ip = (*pskb)->nh.iph; ip = (*pskb)->nh.iph;
...@@ -247,6 +247,7 @@ ipt_do_table(struct sk_buff **pskb, ...@@ -247,6 +247,7 @@ ipt_do_table(struct sk_buff **pskb,
read_lock_bh(&table->lock); read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook)); IP_NF_ASSERT(table->valid_hooks & (1 << hook));
private = table->private;
table_base = (void *)private->entries[smp_processor_id()]; table_base = (void *)private->entries[smp_processor_id()];
e = get_entry(table_base, private->hook_entry[hook]); e = get_entry(table_base, private->hook_entry[hook]);
......
...@@ -712,6 +712,11 @@ static int icmpv6_rcv(struct sk_buff **pskb) ...@@ -712,6 +712,11 @@ static int icmpv6_rcv(struct sk_buff **pskb)
return 0; return 0;
} }
/*
* Special lock-class for __icmpv6_socket:
*/
static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
int __init icmpv6_init(struct net_proto_family *ops) int __init icmpv6_init(struct net_proto_family *ops)
{ {
struct sock *sk; struct sock *sk;
...@@ -730,6 +735,14 @@ int __init icmpv6_init(struct net_proto_family *ops) ...@@ -730,6 +735,14 @@ int __init icmpv6_init(struct net_proto_family *ops)
sk = per_cpu(__icmpv6_socket, i)->sk; sk = per_cpu(__icmpv6_socket, i)->sk;
sk->sk_allocation = GFP_ATOMIC; sk->sk_allocation = GFP_ATOMIC;
/*
* Split off their lock-class, because sk->sk_dst_lock
* gets used from softirqs, which is safe for
* __icmpv6_socket (because those never get directly used
* via userspace syscalls), but unsafe for normal sockets.
*/
lockdep_set_class(&sk->sk_dst_lock,
&icmpv6_socket_sk_dst_lock_key);
/* Enough space for 2 64K ICMP packets, including /* Enough space for 2 64K ICMP packets, including
* sk_buff struct overhead. * sk_buff struct overhead.
......
...@@ -268,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) ...@@ -268,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
struct inet6_dev *idev = in6_dev_get(dev); struct inet6_dev *idev = in6_dev_get(dev);
(void) ip6_mc_leave_src(sk, mc_lst, idev);
if (idev) { if (idev) {
(void) ip6_mc_leave_src(sk,mc_lst,idev);
__ipv6_dev_mc_dec(idev, &mc_lst->addr); __ipv6_dev_mc_dec(idev, &mc_lst->addr);
in6_dev_put(idev); in6_dev_put(idev);
} }
dev_put(dev); dev_put(dev);
} } else
(void) ip6_mc_leave_src(sk, mc_lst, NULL);
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
return 0; return 0;
} }
...@@ -334,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk) ...@@ -334,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk)
if (dev) { if (dev) {
struct inet6_dev *idev = in6_dev_get(dev); struct inet6_dev *idev = in6_dev_get(dev);
if (idev) {
(void) ip6_mc_leave_src(sk, mc_lst, idev); (void) ip6_mc_leave_src(sk, mc_lst, idev);
if (idev) {
__ipv6_dev_mc_dec(idev, &mc_lst->addr); __ipv6_dev_mc_dec(idev, &mc_lst->addr);
in6_dev_put(idev); in6_dev_put(idev);
} }
dev_put(dev); dev_put(dev);
} } else
(void) ip6_mc_leave_src(sk, mc_lst, NULL);
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
......
...@@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
cb->args[0], *id); cb->args[0], *id);
read_lock_bh(&nf_conntrack_lock); read_lock_bh(&nf_conntrack_lock);
last = (struct nf_conn *)cb->args[1];
for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
restart: restart:
last = (struct nf_conn *)cb->args[1];
list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
h = (struct nf_conntrack_tuple_hash *) i; h = (struct nf_conntrack_tuple_hash *) i;
if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
...@@ -442,13 +442,10 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -442,13 +442,10 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
* then dump everything. */ * then dump everything. */
if (l3proto && L3PROTO(ct) != l3proto) if (l3proto && L3PROTO(ct) != l3proto)
continue; continue;
if (last != NULL) { if (cb->args[1]) {
if (ct == last) { if (ct != last)
nf_ct_put(last);
cb->args[1] = 0;
last = NULL;
} else
continue; continue;
cb->args[1] = 0;
} }
if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
...@@ -459,17 +456,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -459,17 +456,17 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
goto out; goto out;
} }
} }
if (last != NULL) { if (cb->args[1]) {
nf_ct_put(last);
cb->args[1] = 0; cb->args[1] = 0;
goto restart; goto restart;
} }
} }
out: out:
read_unlock_bh(&nf_conntrack_lock); read_unlock_bh(&nf_conntrack_lock);
if (last)
nf_ct_put(last);
DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
return skb->len; return skb->len;
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter/xt_physdev.h> #include <linux/netfilter/xt_physdev.h>
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge.h> #include <linux/netfilter_bridge.h>
......
...@@ -796,7 +796,7 @@ static int __init init_u32(void) ...@@ -796,7 +796,7 @@ static int __init init_u32(void)
{ {
printk("u32 classifier\n"); printk("u32 classifier\n");
#ifdef CONFIG_CLS_U32_PERF #ifdef CONFIG_CLS_U32_PERF
printk(" Perfomance counters on\n"); printk(" Performance counters on\n");
#endif #endif
#ifdef CONFIG_NET_CLS_POLICE #ifdef CONFIG_NET_CLS_POLICE
printk(" OLD policer on \n"); printk(" OLD policer on \n");
......
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