* Re: [NET]: Add netif_tx_lock
From: Herbert Xu @ 2006-06-09 5:48 UTC (permalink / raw)
To: David Miller; +Cc: mchan, jgarzik, netdev
In-Reply-To: <20060601111503.GA16097@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 1967 bytes --]
On Thu, Jun 01, 2006 at 09:15:03PM +1000, herbert wrote:
>
> OK, here is a patch which does this.
>
> [NET]: Add netif_tx_lock
Just noticed that I showed dyslexia in winbond.c :) Here is the corrected
version.
[NET]: Add netif_tx_lock
Various drivers use xmit_lock internally to synchronise with their
transmission routines. They do so without setting xmit_lock_owner.
This is fine as long as netpoll is not in use.
With netpoll it is possible for deadlocks to occur if xmit_lock_owner
isn't set. This is because if a printk occurs while xmit_lock is held
and xmit_lock_owner is not set can cause netpoll to attempt to take
xmit_lock recursively.
While it is possible to resolve this by getting netpoll to use trylock,
it is suboptimal because netpoll's sole objective is to maximise the
chance of getting the printk out on the wire. So delaying or dropping
the message is to be avoided as much as possible.
So the only alternative is to always set xmit_lock_owner. The following
patch does this by introducing the netif_tx_lock family of functions that
take care of setting/unsetting xmit_lock_owner.
I renamed xmit_lock to _xmit_lock to indicate that it should not be used
directly. I didn't provide irq versions of the netif_tx_lock functions
since xmit_lock is meant to be a BH-disabling lock.
This is pretty much a straight text substitution except for a small bug
fix in winbond. It currently uses netif_stop_queue/spin_unlock_wait to
stop transmission. This is unsafe as an IRQ can potentially wake up the
queue. So it is safer to use netif_tx_disable.
The hamradio bits used spin_lock_irq but it is unnecessary as xmit_lock
must never be taken in an IRQ handler.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: netif-tx-lock-2.patch --]
[-- Type: text/plain, Size: 23979 bytes --]
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 3c0a5ba..847cedb 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -42,9 +42,9 @@ dev->get_stats:
Context: nominally process, but don't sleep inside an rwlock
dev->hard_start_xmit:
- Synchronization: dev->xmit_lock spinlock.
+ Synchronization: netif_tx_lock spinlock.
When the driver sets NETIF_F_LLTX in dev->features this will be
- called without holding xmit_lock. In this case the driver
+ called without holding netif_tx_lock. In this case the driver
has to lock by itself when needed. It is recommended to use a try lock
for this and return -1 when the spin lock fails.
The locking there should also properly protect against
@@ -62,12 +62,12 @@ dev->hard_start_xmit:
Only valid when NETIF_F_LLTX is set.
dev->tx_timeout:
- Synchronization: dev->xmit_lock spinlock.
+ Synchronization: netif_tx_lock spinlock.
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed true
dev->set_multicast_list:
- Synchronization: dev->xmit_lock spinlock.
+ Synchronization: netif_tx_lock spinlock.
Context: BHs disabled
dev->poll:
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 1dae4b2..1d917ed 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_
ipoib_mcast_stop_thread(dev, 0);
- spin_lock_irqsave(&dev->xmit_lock, flags);
+ local_irq_save(flags);
+ netif_tx_lock(dev);
spin_lock(&priv->lock);
/*
@@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_
}
spin_unlock(&priv->lock);
- spin_unlock_irqrestore(&dev->xmit_lock, flags);
+ netif_tx_unlock(dev);
+ local_irq_restore(flags);
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 2f0f358..9fd8752 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void
dvb_net_feed_stop(dev);
priv->rx_mode = RX_MODE_UNI;
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
if (dev->flags & IFF_PROMISC) {
dprintk("%s: promiscuous mode\n", dev->name);
@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void
}
}
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
dvb_net_feed_start(dev);
}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 54161ae..9c5a884 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2009,7 +2009,7 @@ bnx2_poll(struct net_device *dev, int *b
return 1;
}
-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
* from set_multicast.
*/
static void
@@ -4252,7 +4252,7 @@ bnx2_vlan_rx_kill_vid(struct net_device
}
#endif
-/* Called with dev->xmit_lock.
+/* Called with netif_tx_lock.
* hard_start_xmit is pseudo-lockless - a lock is only required when
* the tx queue is full. This way, we get the benefit of lockless
* operations most of the time without the complexities to handle
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55d2367..46326cd 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4191,7 +4191,7 @@ static int bond_init(struct net_device *
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
- /* don't acquire bond device's xmit_lock when
+ /* don't acquire bond device's netif_tx_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index feb5b22..5a8651b 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -533,9 +533,9 @@ #define NV_MSI_X_VECTOR_OTHER 0x2
* critical parts:
* - rx is (pseudo-) lockless: it relies on the single-threading provided
* by the arch code for interrupts.
- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
+ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
* needs dev->priv->lock :-(
- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
+ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
*/
/* in dev: base, irq */
@@ -1213,7 +1213,7 @@ static void drain_ring(struct net_device
/*
* nv_start_xmit: dev->hard_start_xmit function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
*/
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
@@ -1407,7 +1407,7 @@ static void nv_tx_done(struct net_device
/*
* nv_tx_timeout: dev->tx_timeout function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
*/
static void nv_tx_timeout(struct net_device *dev)
{
@@ -1737,7 +1737,7 @@ static int nv_change_mtu(struct net_devi
* Changing the MTU is a rare event, it shouldn't matter.
*/
nv_disable_irq(dev);
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
spin_lock(&np->lock);
/* stop engines */
nv_stop_rx(dev);
@@ -1768,7 +1768,7 @@ static int nv_change_mtu(struct net_devi
nv_start_rx(dev);
nv_start_tx(dev);
spin_unlock(&np->lock);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
nv_enable_irq(dev);
}
return 0;
@@ -1803,7 +1803,7 @@ static int nv_set_mac_address(struct net
memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
if (netif_running(dev)) {
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
spin_lock_irq(&np->lock);
/* stop rx engine */
@@ -1815,7 +1815,7 @@ static int nv_set_mac_address(struct net
/* restart rx engine */
nv_start_rx(dev);
spin_unlock_irq(&np->lock);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
} else {
nv_copy_mac_to_hw(dev);
}
@@ -1824,7 +1824,7 @@ static int nv_set_mac_address(struct net
/*
* nv_set_multicast: dev->set_multicast function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
*/
static void nv_set_multicast(struct net_device *dev)
{
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 102c1f0..d12605f 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net
{
struct sockaddr_ax25 *sa = addr;
- spin_lock_irq(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
- spin_unlock_irq(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return 0;
}
@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru
break;
}
- spin_lock_irq(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
- spin_unlock_irq(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
err = 0;
break;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d81a8e1..3ebbbe5 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net
{
struct sockaddr_ax25 *sa = addr;
- spin_lock_irq(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
- spin_unlock_irq(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return 0;
}
@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct
break;
}
- spin_lock_irq(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
- spin_unlock_irq(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
err = 0;
break;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 31fb2d7..2e222ef 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev
dp->st_task_enter++;
if ((skb = skb_peek(&dp->tq)) == NULL) {
dp->st_txq_refl_try++;
- if (spin_trylock(&_dev->xmit_lock)) {
+ if (netif_tx_trylock(_dev)) {
dp->st_rxq_enter++;
while ((skb = skb_dequeue(&dp->rq)) != NULL) {
skb_queue_tail(&dp->tq, skb);
dp->st_rx2tx_tran++;
}
- spin_unlock(&_dev->xmit_lock);
+ netif_tx_unlock(_dev);
} else {
/* reschedule */
dp->st_rxq_notenter++;
@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev
}
}
- if (spin_trylock(&_dev->xmit_lock)) {
+ if (netif_tx_trylock(_dev)) {
dp->st_rxq_check++;
if ((skb = skb_peek(&dp->rq)) == NULL) {
dp->tasklet_pending = 0;
@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev
netif_wake_queue(_dev);
} else {
dp->st_rxq_rsch++;
- spin_unlock(&_dev->xmit_lock);
+ netif_tx_unlock(_dev);
goto resched;
}
- spin_unlock(&_dev->xmit_lock);
+ netif_tx_unlock(_dev);
} else {
resched:
dp->tasklet_pending = 1;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 97a49e0..d70b9e8 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s
|| (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
break;
udelay(100);
- /* must not sleep here - we are called under xmit_lock! */
+ /* must not sleep here - called under netif_tx_lock! */
}
}
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 9062775..2e4eced 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -318,12 +318,12 @@ performance critical codepaths:
The rx process only runs in the interrupt handler. Access from outside
the interrupt handler is only permitted after disable_irq().
-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
+The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
is set, then access is permitted under spin_lock_irq(&np->lock).
Thus configuration functions that want to access everything must call
disable_irq(dev->irq);
- spin_lock_bh(dev->xmit_lock);
+ netif_tx_lock_bh(dev);
spin_lock_irq(&np->lock);
IV. Notes
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 136a70c..56d86c7 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1605,11 +1605,11 @@ #ifdef CONFIG_PM
* - get_stats:
* spin_lock_irq(np->lock), doesn't touch hw if not present
* - hard_start_xmit:
- * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
+ * synchronize_irq + netif_tx_disable;
* - tx_timeout:
- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * netif_device_detach + netif_tx_disable;
* - set_multicast_list
- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * netif_device_detach + netif_tx_disable;
* - interrupt handler
* doesn't touch hw if not present, synchronize_irq waits for
* running instances of the interrupt handler.
@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev
netif_device_detach(dev);
update_csr6(dev, 0);
iowrite32(0, ioaddr + IntrEnable);
- netif_stop_queue(dev);
spin_unlock_irq(&np->lock);
- spin_unlock_wait(&dev->xmit_lock);
synchronize_irq(dev->irq);
+ netif_tx_disable(dev);
np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index c2d0b09..a5fcfcd 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1833,7 +1833,9 @@ static int __orinoco_program_rids(struct
/* Set promiscuity / multicast*/
priv->promiscuous = 0;
priv->mc_count = 0;
- __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
+
+ /* FIXME: what about netif_tx_lock */
+ __orinoco_set_multicast_list(dev);
return 0;
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f4169bb..01699eb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -406,7 +406,7 @@ #define NETIF_F_UFO 8192
* One part is mostly used on xmit path (device)
*/
/* hard_start_xmit synchronizer */
- spinlock_t xmit_lock ____cacheline_aligned_in_smp;
+ spinlock_t _xmit_lock ____cacheline_aligned_in_smp;
/* cpu id of processor entered to hard_start_xmit or -1,
if nobody entered there.
*/
@@ -889,11 +889,43 @@ static inline void __netif_rx_complete(s
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}
+static inline void netif_tx_lock(struct net_device *dev)
+{
+ spin_lock(&dev->_xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline void netif_tx_lock_bh(struct net_device *dev)
+{
+ spin_lock_bh(&dev->_xmit_lock);
+ dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline int netif_tx_trylock(struct net_device *dev)
+{
+ int err = spin_trylock(&dev->_xmit_lock);
+ if (!err)
+ dev->xmit_lock_owner = smp_processor_id();
+ return err;
+}
+
+static inline void netif_tx_unlock(struct net_device *dev)
+{
+ dev->xmit_lock_owner = -1;
+ spin_unlock(&dev->_xmit_lock);
+}
+
+static inline void netif_tx_unlock_bh(struct net_device *dev)
+{
+ dev->xmit_lock_owner = -1;
+ spin_unlock_bh(&dev->_xmit_lock);
+}
+
static inline void netif_tx_disable(struct net_device *dev)
{
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
netif_stop_queue(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
}
/* These functions live elsewhere (drivers/net/net_init.c, but related) */
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 72d8529..f92f9c9 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -98,7 +98,7 @@ static void unlink_clip_vcc(struct clip_
printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
return;
}
- spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */
+ netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */
entry->neigh->used = jiffies;
for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
if (*walk == clip_vcc) {
@@ -122,7 +122,7 @@ static void unlink_clip_vcc(struct clip_
printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
"0x%p)\n", entry, clip_vcc);
out:
- spin_unlock_bh(&entry->neigh->dev->xmit_lock);
+ netif_tx_unlock_bh(entry->neigh->dev);
}
/* The neighbour entry n->lock is held. */
diff --git a/net/core/dev.c b/net/core/dev.c
index 4fba549..8906f59 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1275,15 +1275,13 @@ int __skb_linearize(struct sk_buff *skb,
#define HARD_TX_LOCK(dev, cpu) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
- spin_lock(&dev->xmit_lock); \
- dev->xmit_lock_owner = cpu; \
+ netif_tx_lock(dev); \
} \
}
#define HARD_TX_UNLOCK(dev) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
- dev->xmit_lock_owner = -1; \
- spin_unlock(&dev->xmit_lock); \
+ netif_tx_unlock(dev); \
} \
}
@@ -1382,8 +1380,8 @@ #endif
/* The device has no queue. Common case for software devices:
loopback, all the sorts of tunnels...
- Really, it is unlikely that xmit_lock protection is necessary here.
- (f.e. loopback and IP tunnels are clean ignoring statistics
+ Really, it is unlikely that netif_tx_lock protection is necessary
+ here. (f.e. loopback and IP tunnels are clean ignoring statistics
counters.)
However, it is possible, that they rely on protection
made by us here.
@@ -2785,7 +2783,7 @@ int register_netdevice(struct net_device
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
spin_lock_init(&dev->queue_lock);
- spin_lock_init(&dev->xmit_lock);
+ spin_lock_init(&dev->_xmit_lock);
dev->xmit_lock_owner = -1;
#ifdef CONFIG_NET_CLS_ACT
spin_lock_init(&dev->ingress_lock);
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 05d6085..c57d887 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -62,7 +62,7 @@ #include <net/arp.h>
* Device mc lists are changed by bh at least if IPv6 is enabled,
* so that it must be bh protected.
*
- * We block accesses to device mc filters with dev->xmit_lock.
+ * We block accesses to device mc filters with netif_tx_lock.
*/
/*
@@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_d
void dev_mc_upload(struct net_device *dev)
{
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
__dev_mc_upload(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
}
/*
@@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev
int err = 0;
struct dev_mc_list *dmi, **dmip;
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
/*
@@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev
*/
__dev_mc_upload(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return 0;
}
}
err = -ENOENT;
done:
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return err;
}
@@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, v
dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
dmi->dmi_addrlen == alen) {
@@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, v
}
if ((dmi = dmi1) == NULL) {
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return -ENOMEM;
}
memcpy(dmi->dmi_addr, addr, alen);
@@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, v
__dev_mc_upload(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return 0;
done:
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
kfree(dmi1);
return err;
}
@@ -204,7 +204,7 @@ done:
void dev_mc_discard(struct net_device *dev)
{
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
while (dev->mc_list != NULL) {
struct dev_mc_list *tmp = dev->mc_list;
@@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *d
}
dev->mc_count = 0;
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
}
#ifdef CONFIG_PROC_FS
@@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_fi
struct dev_mc_list *m;
struct net_device *dev = v;
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
for (m = dev->mc_list; m; m = m->next) {
int i;
@@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_fi
seq_putc(seq, '\n');
}
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
return 0;
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index e8e05ce..9cb7818 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netp
do {
npinfo->tries--;
- spin_lock(&np->dev->xmit_lock);
- np->dev->xmit_lock_owner = smp_processor_id();
+ netif_tx_lock(np->dev);
/*
* network drivers do not expect to be called if the queue is
* stopped.
*/
if (netif_queue_stopped(np->dev)) {
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ netif_tx_unlock(np->dev);
netpoll_poll(np);
udelay(50);
continue;
}
status = np->dev->hard_start_xmit(skb, np->dev);
- np->dev->xmit_lock_owner = -1;
- spin_unlock(&np->dev->xmit_lock);
+ netif_tx_unlock(np->dev);
/* success */
if(!status) {
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index c23e9c0..67ed14d 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2897,7 +2897,7 @@ static __inline__ void pktgen_xmit(struc
}
}
- spin_lock_bh(&odev->xmit_lock);
+ netif_tx_lock_bh(odev);
if (!netif_queue_stopped(odev)) {
atomic_inc(&(pkt_dev->skb->users));
@@ -2942,7 +2942,7 @@ static __inline__ void pktgen_xmit(struc
pkt_dev->next_tx_ns = 0;
}
- spin_unlock_bh(&odev->xmit_lock);
+ netif_tx_unlock_bh(odev);
/* If pkt_dev->count is zero, then run forever */
if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 138ea92..b1e4c5e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -72,9 +72,9 @@ void qdisc_unlock_tree(struct net_device
dev->queue_lock serializes queue accesses for this device
AND dev->qdisc pointer itself.
- dev->xmit_lock serializes accesses to device driver.
+ netif_tx_lock serializes accesses to device driver.
- dev->queue_lock and dev->xmit_lock are mutually exclusive,
+ dev->queue_lock and netif_tx_lock are mutually exclusive,
if one is grabbed, another must be free.
*/
@@ -108,7 +108,7 @@ int qdisc_restart(struct net_device *dev
* will be requeued.
*/
if (!nolock) {
- if (!spin_trylock(&dev->xmit_lock)) {
+ if (!netif_tx_trylock(dev)) {
collision:
/* So, someone grabbed the driver. */
@@ -126,8 +126,6 @@ int qdisc_restart(struct net_device *dev
__get_cpu_var(netdev_rx_stat).cpu_collision++;
goto requeue;
}
- /* Remember that the driver is grabbed by us. */
- dev->xmit_lock_owner = smp_processor_id();
}
{
@@ -142,8 +140,7 @@ int qdisc_restart(struct net_device *dev
ret = dev->hard_start_xmit(skb, dev);
if (ret == NETDEV_TX_OK) {
if (!nolock) {
- dev->xmit_lock_owner = -1;
- spin_unlock(&dev->xmit_lock);
+ netif_tx_unlock(dev);
}
spin_lock(&dev->queue_lock);
return -1;
@@ -157,8 +154,7 @@ int qdisc_restart(struct net_device *dev
/* NETDEV_TX_BUSY - we need to requeue */
/* Release the driver */
if (!nolock) {
- dev->xmit_lock_owner = -1;
- spin_unlock(&dev->xmit_lock);
+ netif_tx_unlock(dev);
}
spin_lock(&dev->queue_lock);
q = dev->qdisc;
@@ -187,7 +183,7 @@ static void dev_watchdog(unsigned long a
{
struct net_device *dev = (struct net_device *)arg;
- spin_lock(&dev->xmit_lock);
+ netif_tx_lock(dev);
if (dev->qdisc != &noop_qdisc) {
if (netif_device_present(dev) &&
netif_running(dev) &&
@@ -203,7 +199,7 @@ static void dev_watchdog(unsigned long a
dev_hold(dev);
}
}
- spin_unlock(&dev->xmit_lock);
+ netif_tx_unlock(dev);
dev_put(dev);
}
@@ -227,17 +223,17 @@ void __netdev_watchdog_up(struct net_dev
static void dev_watchdog_up(struct net_device *dev)
{
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
__netdev_watchdog_up(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
}
static void dev_watchdog_down(struct net_device *dev)
{
- spin_lock_bh(&dev->xmit_lock);
+ netif_tx_lock_bh(dev);
if (del_timer(&dev->watchdog_timer))
dev_put(dev);
- spin_unlock_bh(&dev->xmit_lock);
+ netif_tx_unlock_bh(dev);
}
void netif_carrier_on(struct net_device *dev)
@@ -582,7 +578,7 @@ void dev_deactivate(struct net_device *d
while (test_bit(__LINK_STATE_SCHED, &dev->state))
yield();
- spin_unlock_wait(&dev->xmit_lock);
+ spin_unlock_wait(&dev->_xmit_lock);
}
void dev_init_scheduler(struct net_device *dev)
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 79b8ef3..4c16ad5 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -302,20 +302,17 @@ restart:
switch (teql_resolve(skb, skb_res, slave)) {
case 0:
- if (spin_trylock(&slave->xmit_lock)) {
- slave->xmit_lock_owner = smp_processor_id();
+ if (netif_tx_trylock(slave)) {
if (!netif_queue_stopped(slave) &&
slave->hard_start_xmit(skb, slave) == 0) {
- slave->xmit_lock_owner = -1;
- spin_unlock(&slave->xmit_lock);
+ netif_tx_unlock(slave);
master->slaves = NEXT_SLAVE(q);
netif_wake_queue(dev);
master->stats.tx_packets++;
master->stats.tx_bytes += len;
return 0;
}
- slave->xmit_lock_owner = -1;
- spin_unlock(&slave->xmit_lock);
+ netif_tx_unlock(slave);
}
if (netif_queue_stopped(dev))
busy = 1;
^ permalink raw reply related
* Re: Using netconsole for debugging suspend/resume
From: Andi Kleen @ 2006-06-09 5:50 UTC (permalink / raw)
To: David Miller; +Cc: auke-jan.h.kok, jeremy, mpm, linux-kernel, netdev
In-Reply-To: <20060608.222352.59657133.davem@davemloft.net>
On Friday 09 June 2006 07:23, David Miller wrote:
> From: Auke Kok <auke-jan.h.kok@intel.com>
> Date: Thu, 08 Jun 2006 22:13:48 -0700
>
> > netconsole should retry. There is no timeout programmed here since that might
> > lose important information, and you rather want netconsole to survive an odd
> > unplugged cable then to lose vital debugging information when the system is
> > busy for instance. (losing link will cause the interface to be down and thus
> > the queue to be stopped)
>
> I completely disagree that netpoll should loop when the ethernet
> cable is plugged out.
Currently it is a bit dumb and doesn't distingush the various cases
well.
I submitted a patch to loop to be a bit more clever at some point. It can be still
found in the netdev archives.
-Andi
^ permalink raw reply
* Re: [PATCH 1/1] LSM-IPsec SELinux Authorize (with minor fix)
From: David Miller @ 2006-06-09 6:40 UTC (permalink / raw)
To: cxzhang
Cc: jmorris, netdev, chrisw, herbert, sds, tjaeger, latten, sergeh,
gcwilson, czhang.us
In-Reply-To: <OF4F545512.79E4862D-ON85257185.005181A7-85257185.00520729@us.ibm.com>
From: Xiaolan Zhang <cxzhang@us.ibm.com>
Date: Tue, 6 Jun 2006 10:55:58 -0400
> Singned-off-by: Catherine Zhang <cxzhang@watson.ibm.com>
>
> James, is this enough or do I need to modify the original patch to add the
> above line? The code was taken from various pieces of patches originally
> from Trent and merged/modified by me. Let me know what else I need to do.
That's good enough for me, patch applied, thanks a lot.
^ permalink raw reply
* Re: [PATCH 1/1] LSM-IPsec SELinux Authorize (with minor fix)
From: David Miller @ 2006-06-09 6:53 UTC (permalink / raw)
To: cxzhang
Cc: jmorris, netdev, chrisw, herbert, sds, tjaeger, latten, sergeh,
gcwilson, czhang.us
In-Reply-To: <20060608.234003.18579552.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Thu, 08 Jun 2006 23:40:03 -0700 (PDT)
> From: Xiaolan Zhang <cxzhang@us.ibm.com>
> Date: Tue, 6 Jun 2006 10:55:58 -0400
>
> > Singned-off-by: Catherine Zhang <cxzhang@watson.ibm.com>
> >
> > James, is this enough or do I need to modify the original patch to add the
> > above line? The code was taken from various pieces of patches originally
> > from Trent and merged/modified by me. Let me know what else I need to do.
>
> That's good enough for me, patch applied, thanks a lot.
BTW, can I ask you SELINUX folks to at least attempt to do
a build with SELINUX disabled when you submit networking
changes to me? It would save me a lot of time, this one
failed with:
net/xfrm/xfrm_user.c: In function ^[$,1rx^[(Bxfrm_del_sa^[$,1ry^[(B:
net/xfrm/xfrm_user.c:430: warning: passing argument 1 of ^[$,1rx^[(Bsecurity_xfrm_state_delete^[$,1ry^[(B from incompatible pointer type
net/xfrm/xfrm_user.c:430: warning: suggest parentheses around assignment used as truth value
net/xfrm/xfrm_user.c: In function ^[$,1rx^[(Bxfrm_get_policy^[$,1ry^[(B:
net/xfrm/xfrm_user.c:1060: warning: suggest parentheses around assignment used as truth value
because the nop implementation of security_xfrm_state_delete()
was declared to take an xfrm_policy instead of an xfrm_state.
I've fixed all of this up, but please test this stuff out next
time around. Thanks a lot.
^ permalink raw reply
* Re: [patch 1/9] git-net: NET_TCPPROBE Kconfig fix
From: David Miller @ 2006-06-09 7:23 UTC (permalink / raw)
To: akpm; +Cc: netdev, davej
In-Reply-To: <200606090520.k595Kpba032080@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:50 -0700
> From: Dave Jones <davej@redhat.com>
>
> Just spotted this typo in a new option.
>
> Signed-off-by: Dave Jones <davej@redhat.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 2/9] selinux: add security class for appletalk sockets
From: David Miller @ 2006-06-09 7:26 UTC (permalink / raw)
To: akpm; +Cc: netdev, cpebenito, jmorris, sds
In-Reply-To: <200606090520.k595KqQU032083@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:52 -0700
>
> From: Christopher J. PeBenito <cpebenito@tresys.com>
>
> Add a security class for appletalk sockets so that they can be
> distinguished in SELinux policy. Please apply.
>
> Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
> Acked-by: James Morris <jmorris@namei.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 3/9] secmark: Add new flask definitions to SELinux
From: David Miller @ 2006-06-09 7:27 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KsJD032089@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:54 -0700
> This patch:
>
> Add support for a new object class ('packet'), and associated permissions
> ('send', 'recv', 'relabelto'). These are used to enforce security policy for
> network packets labeled with SECMARK, and for adding labeling rules.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 4/9] secmark: Add SELinux exports
From: David Miller @ 2006-06-09 7:28 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KtvV032092@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:54 -0700
> From: James Morris <jmorris@namei.org>
>
> Add and export new functions to the in-kernel SELinux API in support of the
> new secmark-based packet controls.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 5/9] secmark: Add secmark support to core networking.
From: David Miller @ 2006-06-09 7:29 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KtAs032095@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:55 -0700
> Add a secmark field to the skbuff structure, to allow security subsystems to
> place security markings on network packets. This is similar to the nfmark
> field, except is intended for implementing security policy, rather than than
> networking policy.
>
> This patch was already acked in principle by Dave Miller.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
Remember James, you're on the hook now to shrink sk_buff
when you get a chance :-)
Thanks again.
^ permalink raw reply
* Re: [patch 6/9] secmark: Add xtables SECMARK target
From: David Miller @ 2006-06-09 7:31 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KutY032098@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:56 -0700
> Add a SECMARK target to xtables, allowing the admin to apply security marks to
> packets via both iptables and ip6tables.
>
> The target currently handles SELinux security marking, but can be extended
> for other purposes as needed.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 7/9] secmark: Add secmark support to conntrack
From: David Miller @ 2006-06-09 7:32 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KvVd032101@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:57 -0700
> Add a secmark field to IP and NF conntracks, so that security markings on
> packets can be copied to their associated connections, and also copied back to
> packets as required. This is similar to the network mark field currently used
> with conntrack, although it is intended for enforcement of security policy
> rather than network policy.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 8/9] secmark: Add CONNSECMARK xtables target
From: David Miller @ 2006-06-09 7:32 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris
In-Reply-To: <200606090520.k595KwnD032104@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:58 -0700
> Add a new xtables target, CONNSECMARK, which is used to specify rules for
> copying security marks from packets to connections, and for copyying security
> marks back from connections to packets. This is similar to the CONNMARK
> target, but is more limited in scope in that it only allows copying of
> security marks to and from packets, as this is all it needs to do.
>
> A typical scenario would be to apply a security mark to a 'new' packet with
> SECMARK, then copy that to its conntrack via CONNMARK, and then restore the
> security mark from the connection to established and related packets on that
> connection.
>
> Signed-off-by: James Morris <jmorris@namei.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks.
^ permalink raw reply
* Re: [patch 9/9] secmark: Add new packet controls to SELinux
From: David Miller @ 2006-06-09 7:33 UTC (permalink / raw)
To: akpm; +Cc: netdev, jmorris, sds
In-Reply-To: <200606090520.k595Kx8J032108@shell0.pdx.osdl.net>
From: akpm@osdl.org
Date: Thu, 08 Jun 2006 22:20:59 -0700
> Add new per-packet access controls to SELinux, replacing the old packet
> controls.
...
> Signed-off-by: James Morris <jmorris@namei.org>
> Cc: Stephen Smalley <sds@tycho.nsa.gov>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
Applied to net-2.6.18, thanks a lot.
^ permalink raw reply
* [1/3] [NET]: Clean up skb_linearize
From: Herbert Xu @ 2006-06-09 7:42 UTC (permalink / raw)
To: David S. Miller, netdev
[-- Attachment #1: Type: text/plain, Size: 1051 bytes --]
Hi:
The following patches are based on net-2.6.18.
[NET]: Clean up skb_linearize
The linearisation operation doesn't need to be super-optimised. So we can
replace __skb_linearize with __pskb_pull_tail which does the same thing but
is more general.
Also, most users of skb_linearize end up testing whether the skb is linear
or not so it helps to make skb_linearize do just that.
Some callers of skb_linearize also use it to copy cloned data, so it's
useful to have a new function skb_linearize_cow to copy the data if it's
either non-linear or cloned.
Last but not least, I've removed the gfp argument since nobody uses it
anymore. If it's ever needed we can easily add it back.
Misc bugs fixed by this patch:
* via-velocity error handling (also, no SG => no frags)
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p1.patch --]
[-- Type: text/plain, Size: 8249 bytes --]
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -116,8 +116,7 @@ aoenet_rcv(struct sk_buff *skb, struct n
skb = skb_share_check(skb, GFP_ATOMIC);
if (skb == NULL)
return 0;
- if (skb_is_nonlinear(skb))
- if (skb_linearize(skb, GFP_ATOMIC) < 0)
+ if (skb_linearize(skb))
goto exit;
if (!is_aoe_netif(ifp))
goto exit;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1200,7 +1200,7 @@ static int mv643xx_eth_start_xmit(struct
}
if (has_tiny_unaligned_frags(skb)) {
- if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+ if (__skb_linearize(skb)) {
stats->tx_dropped++;
printk(KERN_DEBUG "%s: failed to linearize tiny "
"unaligned fragment\n", dev->name);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff
int pktlen = skb->len;
+#ifdef VELOCITY_ZERO_COPY_SUPPORT
+ if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
+ kfree_skb(skb);
+ return 0;
+ }
+#endif
+
spin_lock_irqsave(&vptr->lock, flags);
index = vptr->td_curr[qnum];
@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff
*/
if (pktlen < ETH_ZLEN) {
/* Cannot occur until ZC support */
- if(skb_linearize(skb, GFP_ATOMIC))
- return 0;
pktlen = ETH_ZLEN;
memcpy(tdinfo->buf, skb->data, skb->len);
memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
@@ -1933,7 +1938,6 @@ static int velocity_xmit(struct sk_buff
int nfrags = skb_shinfo(skb)->nr_frags;
tdinfo->skb = skb;
if (nfrags > 6) {
- skb_linearize(skb, GFP_ATOMIC);
memcpy(tdinfo->buf, skb->data, skb->len);
tdinfo->skb_dma[0] = tdinfo->buf_dma;
td_ptr->tdesc0.pktsize =
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1165,18 +1165,34 @@ static inline int skb_can_coalesce(struc
return 0;
}
+static inline int __skb_linearize(struct sk_buff *skb)
+{
+ return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
+}
+
/**
* skb_linearize - convert paged skb to linear one
* @skb: buffer to linarize
- * @gfp: allocation mode
*
* If there is no free memory -ENOMEM is returned, otherwise zero
* is returned and the old skb data released.
*/
-extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
-static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
+static inline int skb_linearize(struct sk_buff *skb)
+{
+ return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
+}
+
+/**
+ * skb_linearize_cow - make sure skb is linear and writable
+ * @skb: buffer to process
+ *
+ * If there is no free memory -ENOMEM is returned, otherwise zero
+ * is returned and the old skb data released.
+ */
+static inline int skb_linearize_cow(struct sk_buff *skb)
{
- return __skb_linearize(skb, gfp);
+ return skb_is_nonlinear(skb) || skb_cloned(skb) ?
+ __skb_linearize(skb) : 0;
}
/**
diff --git a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1220,64 +1220,6 @@ static inline int illegal_highdma(struct
#define illegal_highdma(dev, skb) (0)
#endif
-/* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
-{
- unsigned int size;
- u8 *data;
- long offset;
- struct skb_shared_info *ninfo;
- int headerlen = skb->data - skb->head;
- int expand = (skb->tail + skb->data_len) - skb->end;
-
- if (skb_shared(skb))
- BUG();
-
- if (expand <= 0)
- expand = 0;
-
- size = skb->end - skb->head + expand;
- size = SKB_DATA_ALIGN(size);
- data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
- if (!data)
- return -ENOMEM;
-
- /* Copy entire thing */
- if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
- BUG();
-
- /* Set up shinfo */
- ninfo = (struct skb_shared_info*)(data + size);
- atomic_set(&ninfo->dataref, 1);
- ninfo->tso_size = skb_shinfo(skb)->tso_size;
- ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
- ninfo->nr_frags = 0;
- ninfo->frag_list = NULL;
-
- /* Offset between the two in bytes */
- offset = data - skb->head;
-
- /* Free old data. */
- skb_release_data(skb);
-
- skb->head = data;
- skb->end = data + size;
-
- /* Set up new pointers */
- skb->h.raw += offset;
- skb->nh.raw += offset;
- skb->mac.raw += offset;
- skb->tail += offset;
- skb->data += offset;
-
- /* We are no longer a clone, even if we were. */
- skb->cloned = 0;
-
- skb->tail += skb->data_len;
- skb->data_len = 0;
- return 0;
-}
-
#define HARD_TX_LOCK(dev, cpu) { \
if ((dev->features & NETIF_F_LLTX) == 0) { \
spin_lock(&dev->xmit_lock); \
@@ -1326,7 +1268,7 @@ int dev_queue_xmit(struct sk_buff *skb)
if (skb_shinfo(skb)->frag_list &&
!(dev->features & NETIF_F_FRAGLIST) &&
- __skb_linearize(skb, GFP_ATOMIC))
+ __skb_linearize(skb))
goto out_kfree_skb;
/* Fragmented skb is linearized if device does not support SG,
@@ -1335,7 +1277,7 @@ int dev_queue_xmit(struct sk_buff *skb)
*/
if (skb_shinfo(skb)->nr_frags &&
(!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
- __skb_linearize(skb, GFP_ATOMIC))
+ __skb_linearize(skb))
goto out_kfree_skb;
/* If packet is not checksummed and device does not support
@@ -3473,7 +3415,6 @@ subsys_initcall(net_dev_init);
EXPORT_SYMBOL(__dev_get_by_index);
EXPORT_SYMBOL(__dev_get_by_name);
EXPORT_SYMBOL(__dev_remove_pack);
-EXPORT_SYMBOL(__skb_linearize);
EXPORT_SYMBOL(dev_valid_name);
EXPORT_SYMBOL(dev_add_pack);
EXPORT_SYMBOL(dev_alloc_name);
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -801,8 +801,7 @@ got_it:
* We linearize everything except data segments here.
*/
if (cb->nsp_flags & ~0x60) {
- if (unlikely(skb_is_nonlinear(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0)
+ if (unlikely(skb_linearize(skb)))
goto free_out;
}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, st
padlen);
if (flags & DN_RT_PKT_CNTL) {
- if (unlikely(skb_is_nonlinear(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0)
+ if (unlikely(skb_linearize(skb)))
goto dump_it;
switch(flags & DN_RT_CNTL_MSK) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -80,15 +80,12 @@ out:
static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
- int err = 0;
+ int err = -ENOMEM;
struct iphdr *iph;
struct ip_comp_hdr *ipch;
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
- err = -ENOMEM;
+ if (skb_linearize_cow(skb))
goto out;
- }
skb->ip_summed = CHECKSUM_NONE;
@@ -158,10 +155,8 @@ static int ipcomp_output(struct xfrm_sta
goto out_ok;
}
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
+ if (skb_linearize_cow(skb))
goto out_ok;
- }
err = ipcomp_compress(x, skb);
iph = skb->nh.iph;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -65,7 +65,7 @@ static LIST_HEAD(ipcomp6_tfms_list);
static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
- int err = 0;
+ int err = -ENOMEM;
struct ipv6hdr *iph;
struct ipv6_comp_hdr *ipch;
int plen, dlen;
@@ -74,11 +74,8 @@ static int ipcomp6_input(struct xfrm_sta
struct crypto_tfm *tfm;
int cpu;
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
- err = -ENOMEM;
+ if (skb_linearize_cow(skb))
goto out;
- }
skb->ip_summed = CHECKSUM_NONE;
@@ -142,10 +139,8 @@ static int ipcomp6_output(struct xfrm_st
goto out_ok;
}
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
+ if (skb_linearize_cow(skb))
goto out_ok;
- }
/* compression */
plen = skb->len - hdr_len;
^ permalink raw reply
* [2/3] [NET] ppp: Remove unnecessary pskb_may_pull
From: Herbert Xu @ 2006-06-09 7:43 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20060609074234.GA17580@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 598 bytes --]
Hi:
[NET] ppp: Remove unnecessary pskb_may_pull
In ppp_receive_nonmp_frame, we call pskb_may_pull(skb, skb->len) if the
tailroom is >= 124. This is pointless because this pskb_may_pull is only
needed if the skb is non-linear. However, if it is non-linear then the
tailroom would be zero.
So it can be safely removed.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p2.patch --]
[-- Type: text/plain, Size: 336 bytes --]
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1609,8 +1609,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp,
kfree_skb(skb);
skb = ns;
}
- else if (!pskb_may_pull(skb, skb->len))
- goto err;
else
skb->ip_summed = CHECKSUM_NONE;
^ permalink raw reply
* [3/3] [NET]: skb_trim audit
From: Herbert Xu @ 2006-06-09 7:44 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20060609074234.GA17580@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 509 bytes --]
Hi:
[NET]: skb_trim audit
I found a few more spots where pskb_trim_rcsum could be used but were not.
This patch changes them to use it.
Also, sk_filter can get paged skb data. Therefore we must use pskb_trim
instead of skb_trim.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p3.patch --]
[-- Type: text/plain, Size: 2139 bytes --]
diff --git a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -873,10 +873,7 @@ static inline int sk_filter(struct sock
if (filter) {
unsigned int pkt_len = sk_run_filter(skb, filter->insns,
filter->len);
- if (!pkt_len)
- err = -EPERM;
- else
- skb_trim(skb, pkt_len);
+ err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
}
if (needlock)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -407,12 +407,8 @@ static unsigned int br_nf_pre_routing_ip
if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
goto inhdr_error;
- if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
- if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
- goto inhdr_error;
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
- }
+ if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
+ goto inhdr_error;
}
if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
goto inhdr_error;
@@ -495,11 +491,7 @@ static unsigned int br_nf_pre_routing(un
if (skb->len < len || len < 4 * iph->ihl)
goto inhdr_error;
- if (skb->len > len) {
- __pskb_trim(skb, len);
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
- }
+ pskb_trim_rcsum(skb, len);
nf_bridge_put(skb->nf_bridge);
if (!nf_bridge_alloc(skb))
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -456,13 +456,9 @@ static int nf_ct_frag6_queue(struct nf_c
DEBUGP("queue: message is too short.\n");
goto err;
}
- if (end-offset < skb->len) {
- if (pskb_trim(skb, end - offset)) {
- DEBUGP("Can't trim\n");
- goto err;
- }
- if (skb->ip_summed != CHECKSUM_UNNECESSARY)
- skb->ip_summed = CHECKSUM_NONE;
+ if (pskb_trim_rcsum(skb, end - offset)) {
+ DEBUGP("Can't trim\n");
+ goto err;
}
/* Find out which fragments are in front and at the back of us
^ permalink raw reply
* [4/3] [NET]: Warn in __skb_trim if skb is paged
From: Herbert Xu @ 2006-06-09 7:55 UTC (permalink / raw)
To: David S. Miller, netdev
In-Reply-To: <20060609074234.GA17580@gondor.apana.org.au>
[-- Attachment #1: Type: text/plain, Size: 459 bytes --]
Hi:
[NET]: Warn in __skb_trim if skb is paged
It's better to warn and fail rather than rarely triggering BUG on paths
that incorrectly call skb_trim/__skb_trim on a non-linear skb.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: p4.patch --]
[-- Type: text/plain, Size: 2332 bytes --]
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 197f2d2..6ceec04 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -971,15 +971,16 @@ #ifndef NET_SKB_PAD
#define NET_SKB_PAD 16
#endif
-extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
{
- if (!skb->data_len) {
- skb->len = len;
- skb->tail = skb->data + len;
- } else
- ___pskb_trim(skb, len, 0);
+ if (unlikely(skb->data_len)) {
+ WARN_ON(1);
+ return;
+ }
+ skb->len = len;
+ skb->tail = skb->data + len;
}
/**
@@ -989,6 +990,7 @@ static inline void __skb_trim(struct sk_
*
* Cut the length of a buffer down by removing data from the tail. If
* the buffer is already under the length specified it is not modified.
+ * The skb must be linear.
*/
static inline void skb_trim(struct sk_buff *skb, unsigned int len)
{
@@ -999,12 +1001,10 @@ static inline void skb_trim(struct sk_bu
static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
{
- if (!skb->data_len) {
- skb->len = len;
- skb->tail = skb->data+len;
- return 0;
- }
- return ___pskb_trim(skb, len, 1);
+ if (skb->data_len)
+ return ___pskb_trim(skb, len);
+ __skb_trim(skb, len);
+ return 0;
}
static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fb3770f..0af4861 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -800,12 +800,10 @@ struct sk_buff *skb_pad(struct sk_buff *
return nskb;
}
-/* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
- * If realloc==0 and trimming is impossible without change of data,
- * it is BUG().
+/* Trims skb to length len. It can change skb pointers.
*/
-int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
+int ___pskb_trim(struct sk_buff *skb, unsigned int len)
{
int offset = skb_headlen(skb);
int nfrags = skb_shinfo(skb)->nr_frags;
@@ -815,7 +813,6 @@ int ___pskb_trim(struct sk_buff *skb, un
int end = offset + skb_shinfo(skb)->frags[i].size;
if (end > len) {
if (skb_cloned(skb)) {
- BUG_ON(!realloc);
if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return -ENOMEM;
}
^ permalink raw reply related
* Re: ipsec tunnel asymmetrical mtu
From: Marco Berizzi @ 2006-06-09 8:04 UTC (permalink / raw)
To: herbert; +Cc: netdev
In-Reply-To: <BAY103-F5BDFFFFDAB4CFB03007D9B2A60@phx.gbl>
Marco Berizzi wrote:
>Marco Berizzi wrote:
>
>>Herbert Xu wrote:
>>
>>>However, the fact that the tcpdump causes more chunky packets to
>>>make it through could be an indication that there is a bug somewhere
>>>in our NAT/IPsec code or at least a suboptimal memory allocation
>>>strategy that's somehow avoided when AF_PACKET pins the skb down.
>
>JFYI: same problem with 2.6.17-rc4-git5
JFYI: same problem with 2.6.17-rc6
^ permalink raw reply
* Re: [patch 5/9] secmark: Add secmark support to core networking.
From: James Morris @ 2006-06-09 8:18 UTC (permalink / raw)
To: David Miller; +Cc: akpm, netdev
In-Reply-To: <20060609.002953.70217215.davem@davemloft.net>
On Fri, 9 Jun 2006, David Miller wrote:
> Remember James, you're on the hook now to shrink sk_buff
> when you get a chance :-)
Yep, I remember.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: Using netconsole for debugging suspend/resume
From: Pavel Machek @ 2006-06-09 8:34 UTC (permalink / raw)
To: Jeremy Fitzhardinge; +Cc: Matt Mackall, Linux Kernel Mailing List, netdev
In-Reply-To: <44886381.9050506@goop.org>
On Čt 08-06-06 10:50:57, Jeremy Fitzhardinge wrote:
> I've been trying to get suspend/resume working well on my new laptop.
Suspend-to-disk or -to-ram? You know about suspend.sf.net, right?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCH 2.6.17-rc6-mm1 ] net: RFC 3828-compliant UDP-Lite support
From: Gerrit Renker @ 2006-06-09 9:36 UTC (permalink / raw)
To: David Miller
Cc: jmorris, alan, kuznet, pekkas, yoshfuji, kaber, linux-kernel,
netdev
In-Reply-To: <20060608.151347.55505744.davem@davemloft.net>
Quoting David Miller:
| From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
| Date: Thu, 8 Jun 2006 21:09:33 +0100
|
| > That is why I held back regarding the IPv6 port:
<snip>
|
| It's not like an ipv6 port is such a big pile of work.
|
I see the point and will port to v6 (have asked colleages for help).
Until then, I will keep an up-to-date (-mm) patch in the tarball
http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/udplite_linux.tar.gz
This has applications as well. I would value any more input: the suggestion to
use SOCK_DGRAM has already been integrated and proved a really good idea (much less
to patch, cleaner code). Usually an update is there on the same day the new kernel
comes out.
Thank you for your replies and comments, I will be back when the v6 side is ready.
^ permalink raw reply
* Re: Using netconsole for debugging suspend/resume
From: Rafael J. Wysocki @ 2006-06-09 10:34 UTC (permalink / raw)
To: Jeremy Fitzhardinge; +Cc: Matt Mackall, Linux Kernel Mailing List, netdev
In-Reply-To: <4488D565.2020103@goop.org>
On Friday 09 June 2006 03:56, Jeremy Fitzhardinge wrote:
> Rafael J. Wysocki wrote:
> > Please try doing "echo 8 > /proc/sys/kernel/printk" before suspend.
> >
> Um, why? That would increase the amount of log output, but I don't see
> how it would help with netconsole preventing suspend, or not being able
> to see console messages on a blank screen after resume.
Ah, that's after resume. Sorry for the noise. :-)
Rafael
^ permalink raw reply
* [Fwd: Packet Lost] ip_rt_bug error
From: Vasantha Kumar Puttappa @ 2006-06-09 7:38 UTC (permalink / raw)
To: netdev
Hi,
I am working on a small application using iptables/libipq. In this, the
application would capture a specific packets based on the destination IP
address. Then I encapsulate this IP packet inside another new IP packet.
My problem is that the encapsulation part works fine in
kernel-2.6.11-6(mandriva 2005) and IPtables V 1.2.9.
(I can capture encapsulated packets using tcpdump at the sender side i.e,
packets are being put on to the network)
But this doesn't work in kernel-2.6.12-12(mandriva 2006) and the
IPtables-1.3.5(even though there are no erros after callig
ipq_set_verdict, the packets are not being put on to the channel. The
packets are getting lost after
the call to ipq_set_verdict)
/***
In my syslog I can see ip_rt_bug , but isn't ip_rt_bug occurs when
destiantion address is changed to local address ?
In my application I am changing destination IP to an another non-local IP
address.
****/
please let me know if you need more information
As you already have experience with these kinds of error plz help me out here
Thanx
^ permalink raw reply
* Re: Problem authenticating using WPA with bcm43xx-softmac
From: Johannes Berg @ 2006-06-09 11:44 UTC (permalink / raw)
To: Larry Finger; +Cc: Dan Williams, netdev, Jouni Malinen
In-Reply-To: <44871723.3040803@lwfinger.net>
[-- Attachment #1: Type: text/plain, Size: 895 bytes --]
On Wed, 2006-06-07 at 13:12 -0500, Larry Finger wrote:
> > (ie, add the "hh" before the x to tell the print that it's a char)
> >
> That doesn't work - the result is
>
> %hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx%hx
Looks like the kernel doesn't support that modifier.
> I changed the line to cast the output byte as a u8 as follows:
>
> dprintk("%.2x", (u8)mac->wpa.IE[i]);
>
> This produces the line
>
> generic IE set to dd160050f20101000050f20201000050f20201000050f202
>
> This is the WPA IE supplied by wpa_supplicant and it matches the one used in the ndiswrapper case.
> One mystery solved,
Yeah good :)
> but why doesn't it work?
No idea. If we had a dump maybe we could tell :/
> Johannes - should I submit the patch to fix this printout, or would you like to do it?
Please do.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]
^ permalink raw reply
* Re: [patch 1/8] myri10ge: alpha build fix
From: Brice Goglin @ 2006-06-09 11:46 UTC (permalink / raw)
To: akpm; +Cc: jeff, netdev
In-Reply-To: <200606090519.k595JfxP032014@shell0.pdx.osdl.net>
A similar fix is included in the myri10ge update that Jeff merged into
netdev yesterday.
thanks,
Brice
akpm@osdl.org wrote:
> From: Andrew Morton <akpm@osdl.org>
>
> drivers/net/myri10ge/myri10ge.c: In function 'myri10ge_submit_8rx':
> drivers/net/myri10ge/myri10ge.c:772: error: 'DMA_32BIT_MASK' undeclared (first use in this function)
> drivers/net/myri10ge/myri10ge.c:772: error: (Each undeclared identifier is reported only once
> drivers/net/myri10ge/myri10ge.c:772: error: for each function it appears in.)
> drivers/net/myri10ge/myri10ge.c: In function 'myri10ge_probe':
> drivers/net/myri10ge/myri10ge.c:2607: error: 'DMA_64BIT_MASK' undeclared (first use in this function)
> drivers/net/myri10ge/myri10ge.c:2612: error: 'DMA_32BIT_MASK' undeclared (first use in this function)
>
> Cc: Brice Goglin <brice@myri.com>
> Cc: Jeff Garzik <jeff@garzik.org>
> Signed-off-by: Andrew Morton <akpm@osdl.org>
> ---
>
> drivers/net/myri10ge/myri10ge.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff -puN drivers/net/myri10ge/myri10ge.c~myri10ge-alpha-build-fix drivers/net/myri10ge/myri10ge.c
> --- devel/drivers/net/myri10ge/myri10ge.c~myri10ge-alpha-build-fix 2006-06-03 21:13:30.000000000 -0700
> +++ devel-akpm/drivers/net/myri10ge/myri10ge.c 2006-06-03 21:13:43.000000000 -0700
> @@ -59,6 +59,8 @@
> #include <linux/crc32.h>
> #include <linux/moduleparam.h>
> #include <linux/io.h>
> +#include <linux/dma-mapping.h>
> +
> #include <net/checksum.h>
> #include <asm/byteorder.h>
> #include <asm/io.h>
> _
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox