* Re: [PATCH RFC] vhost: fix barrier pairing
From: Juan Quintela @ 2010-05-12 9:22 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Rusty Russell, David S. Miller, Paul E. McKenney, kvm,
virtualization, netdev, linux-kernel
In-Reply-To: <20100511172633.GA9091@redhat.com>
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> According to memory-barriers.txt, an smp memory barrier
> should always be paired with another smp memory barrier,
> and I quote "a lack of appropriate pairing is almost certainly an
> error".
>
> In case of vhost, failure to flush out used index
> update before looking at the interrupt disable flag
> could result in missed interrupts, resulting in
> networking hang under stress.
>
> This might happen when flags read bypasses used index write.
> So we see interrupts disabled and do not interrupt, at the
> same time guest writes flags value to enable interrupt,
> reads an old used index value, thinks that
> used ring is empty and waits for interrupt.
>
> Note: the barrier we pair with here is in
> drivers/virtio/virtio_ring.c, function
> vring_enable_cb.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>
> Dave, I think this is needed in 2.6.34, I'll send a pull
> request after doing some more testing.
>
> Rusty, Juan, could you take a look as well please?
> Thanks!
I would have prefered to put it:
void vhost_add_used_and_signal(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
unsigned int head, int len)
{
vhost_add_used(vq, head, len);
>>>> smp_mb();
vhost_signal(dev, vq);
}
Because it looks strange to have a barrier as the 1st instruction of a
function. And this way it is clearer (at least to me) what we are
protecting.
But on the other hand, we would have to put a comment explainingthat all
users of vhost_signal() have to put that smp_mb() so .....
Perhaps just improving the commet stating that the corresponding barrier
is there?
> Note: the barrier we pair with here is in
> drivers/virtio/virtio_ring.c, function
> vring_enable_cb.
Good catch.
Later, Juan.
^ permalink raw reply
* Re: [PATCH V4 1/4] net: add a noref bit on skb dst
From: Eric Dumazet @ 2010-05-12 9:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <1273527162.10889.10.camel@edumazet-laptop>
Le lundi 10 mai 2010 à 23:32 +0200, Eric Dumazet a écrit :
> skb_dst_force() helper is used to force a refcount on dst, when skb
> is queued and not anymore RCU protected.
>
> Use skb_dst_force() in __sk_add_backlog(), __dev_xmit_skb() if
> !IFF_XMIT_DST_RELEASE or skb enqueued on qdisc queue, in
> sock_queue_rcv_skb(), in __nf_queue().
While doing benches, I noticed one spot was forgotten, in case of
requeueing from a work-conserving queue (dev_requeue_skb() must call
skb_dst_force())
Here is updated first patch.
[PATCH V4 1/4] net: add a noref bit on skb dst
Use low order bit of skb->_skb_dst to tell dst is not refcounted.
Change _skb_dst to _skb_refdst to make sure all uses are catched.
skb_dst() returns the dst, regardless of noref bit set or not, but
with a lockdep check to make sure a noref dst is not given if current
user is not rcu protected.
New skb_dst_set_noref() helper to set an notrefcounted dst on a skb.
(with lockdep check)
skb_dst_drop() drops a reference only if skb dst was refcounted.
skb_dst_force() helper is used to force a refcount on dst, when skb
is queued and not anymore RCU protected.
Use skb_dst_force() in __sk_add_backlog(), __dev_xmit_skb() if
!IFF_XMIT_DST_RELEASE or skb enqueued on qdisc queue, in
sock_queue_rcv_skb(), in __nf_queue().
Use skb_dst_force() in dev_requeue_skb().
Note: dst_use_noref() still dirties dst, we might transform it
later to do one dirtying per jiffies.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/skbuff.h | 58 ++++++++++++++++++++++++++++++++++---
include/net/dst.h | 48 ++++++++++++++++++++++++++++--
include/net/sock.h | 13 +++++---
net/core/dev.c | 3 +
net/core/skbuff.c | 2 -
net/core/sock.c | 6 +++
net/ipv4/icmp.c | 6 +--
net/ipv4/ip_options.c | 9 +++--
net/ipv4/netfilter.c | 6 +--
net/ipv4/route.c | 2 -
net/netfilter/nf_queue.c | 2 +
net/sched/sch_generic.c | 4 +-
12 files changed, 134 insertions(+), 25 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c9525bc..7cdfb4d 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -264,7 +264,7 @@ typedef unsigned char *sk_buff_data_t;
* @transport_header: Transport layer header
* @network_header: Network layer header
* @mac_header: Link layer header
- * @_skb_dst: destination entry
+ * @_skb_refdst: destination entry (with norefcount bit)
* @sp: the security path, used for xfrm
* @cb: Control buffer. Free for use by every layer. Put private vars here
* @len: Length of actual data
@@ -328,7 +328,7 @@ struct sk_buff {
*/
char cb[48] __aligned(8);
- unsigned long _skb_dst;
+ unsigned long _skb_refdst;
#ifdef CONFIG_XFRM
struct sec_path *sp;
#endif
@@ -419,14 +419,64 @@ struct sk_buff {
#include <asm/system.h>
+/*
+ * skb might have a dst pointer attached, refcounted or not.
+ * _skb_refdst low order bit is set if refcount was _not_ taken
+ */
+#define SKB_DST_NOREF 1UL
+#define SKB_DST_PTRMASK ~(SKB_DST_NOREF)
+
+/**
+ * skb_dst - returns skb dst_entry
+ * @skb: buffer
+ *
+ * Returns skb dst_entry, regardless of reference taken or not.
+ */
static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
{
- return (struct dst_entry *)skb->_skb_dst;
+ /* If refdst was not refcounted, check we still are in a
+ * rcu_read_lock section
+ */
+ WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) &&
+ !rcu_read_lock_held() &&
+ !rcu_read_lock_bh_held());
+ return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK);
}
+/**
+ * skb_dst_set - sets skb dst
+ * @skb: buffer
+ * @dst: dst entry
+ *
+ * Sets skb dst, assuming a reference was taken on dst and should
+ * be released by skb_dst_drop()
+ */
static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
{
- skb->_skb_dst = (unsigned long)dst;
+ skb->_skb_refdst = (unsigned long)dst;
+}
+
+/**
+ * skb_dst_set_noref - sets skb dst, without a reference
+ * @skb: buffer
+ * @dst: dst entry
+ *
+ * Sets skb dst, assuming a reference was not taken on dst
+ * skb_dst_drop() should not dst_release() this dst
+ */
+static inline void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)
+{
+ WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
+ skb->_skb_refdst = (unsigned long)dst | SKB_DST_NOREF;
+}
+
+/**
+ * skb_dst_is_noref - Test if skb dst isnt refcounted
+ * @skb: buffer
+ */
+static inline bool skb_dst_is_noref(const struct sk_buff *skb)
+{
+ return (skb->_skb_refdst & SKB_DST_NOREF) && skb_dst(skb);
}
static inline struct rtable *skb_rtable(const struct sk_buff *skb)
diff --git a/include/net/dst.h b/include/net/dst.h
index aac5a5f..27207a1 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -168,6 +168,12 @@ static inline void dst_use(struct dst_entry *dst, unsigned long time)
dst->lastuse = time;
}
+static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
+{
+ dst->__use++;
+ dst->lastuse = time;
+}
+
static inline
struct dst_entry * dst_clone(struct dst_entry * dst)
{
@@ -177,11 +183,47 @@ struct dst_entry * dst_clone(struct dst_entry * dst)
}
extern void dst_release(struct dst_entry *dst);
+
+static inline void refdst_drop(unsigned long refdst)
+{
+ if (!(refdst & SKB_DST_NOREF))
+ dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK));
+}
+
+/**
+ * skb_dst_drop - drops skb dst
+ * @skb: buffer
+ *
+ * Drops dst reference count if a reference was taken.
+ */
static inline void skb_dst_drop(struct sk_buff *skb)
{
- if (skb->_skb_dst)
- dst_release(skb_dst(skb));
- skb->_skb_dst = 0UL;
+ if (skb->_skb_refdst) {
+ refdst_drop(skb->_skb_refdst);
+ skb->_skb_refdst = 0UL;
+ }
+}
+
+static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb)
+{
+ nskb->_skb_refdst = oskb->_skb_refdst;
+ if (!(nskb->_skb_refdst & SKB_DST_NOREF))
+ dst_clone(skb_dst(nskb));
+}
+
+/**
+ * skb_dst_force - makes sure skb dst is refcounted
+ * @skb: buffer
+ *
+ * If dst is not yet refcounted, let's do it
+ */
+static inline void skb_dst_force(struct sk_buff *skb)
+{
+ if (skb_dst_is_noref(skb)) {
+ WARN_ON(!rcu_read_lock_held());
+ skb->_skb_refdst &= ~SKB_DST_NOREF;
+ dst_clone(skb_dst(skb));
+ }
}
/* Children define the path of the packet through the
diff --git a/include/net/sock.h b/include/net/sock.h
index 328e03f..307affa 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -598,12 +598,15 @@ static inline int sk_stream_memory_free(struct sock *sk)
/* OOB backlog add */
static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
{
- if (!sk->sk_backlog.tail) {
- sk->sk_backlog.head = sk->sk_backlog.tail = skb;
- } else {
+ /* dont let skb dst not refcounted, we are going to leave rcu lock */
+ skb_dst_force(skb);
+
+ if (!sk->sk_backlog.tail)
+ sk->sk_backlog.head = skb;
+ else
sk->sk_backlog.tail->next = skb;
- sk->sk_backlog.tail = skb;
- }
+
+ sk->sk_backlog.tail = skb;
skb->next = NULL;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 32611c8..dfe6ba6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2047,6 +2047,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
* waiting to be sent out; and the qdisc is not running -
* xmit the skb directly.
*/
+ if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
+ skb_dst_force(skb);
__qdisc_update_bstats(q, skb->len);
if (sch_direct_xmit(skb, q, dev, txq, root_lock))
__qdisc_run(q);
@@ -2055,6 +2057,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
rc = NET_XMIT_SUCCESS;
} else {
+ skb_dst_force(skb);
rc = qdisc_enqueue_root(skb, q);
qdisc_run(q);
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index a9b0e1f..c543dd2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -520,7 +520,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->transport_header = old->transport_header;
new->network_header = old->network_header;
new->mac_header = old->mac_header;
- skb_dst_set(new, dst_clone(skb_dst(old)));
+ skb_dst_copy(new, old);
new->rxhash = old->rxhash;
#ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp);
diff --git a/net/core/sock.c b/net/core/sock.c
index 94c4aff..d24b5c1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -307,6 +307,11 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
*/
skb_len = skb->len;
+ /* we escape from rcu protected region, make sure we dont leak
+ * a norefcounted dst
+ */
+ skb_dst_force(skb);
+
spin_lock_irqsave(&list->lock, flags);
skb->dropcount = atomic_read(&sk->sk_drops);
__skb_queue_tail(list, skb);
@@ -1535,6 +1540,7 @@ static void __release_sock(struct sock *sk)
do {
struct sk_buff *next = skb->next;
+ WARN_ON_ONCE(skb_dst_is_noref(skb));
skb->next = NULL;
sk_backlog_rcv(sk, skb);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index f3d339f..d65e921 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -587,20 +587,20 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
err = __ip_route_output_key(net, &rt2, &fl);
else {
struct flowi fl2 = {};
- struct dst_entry *odst;
+ unsigned long orefdst;
fl2.fl4_dst = fl.fl4_src;
if (ip_route_output_key(net, &rt2, &fl2))
goto relookup_failed;
/* Ugh! */
- odst = skb_dst(skb_in);
+ orefdst = skb_in->_skb_refdst; /* save old refdst */
err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
RT_TOS(tos), rt2->u.dst.dev);
dst_release(&rt2->u.dst);
rt2 = skb_rtable(skb_in);
- skb_dst_set(skb_in, odst);
+ skb_in->_skb_refdst = orefdst; /* restore old refdst */
}
if (err)
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 4c09a31..3244133 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -601,6 +601,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
unsigned char *optptr = skb_network_header(skb) + opt->srr;
struct rtable *rt = skb_rtable(skb);
struct rtable *rt2;
+ unsigned long orefdst;
int err;
if (!opt->srr)
@@ -624,16 +625,16 @@ int ip_options_rcv_srr(struct sk_buff *skb)
}
memcpy(&nexthop, &optptr[srrptr-1], 4);
- rt = skb_rtable(skb);
+ orefdst = skb->_skb_refdst;
skb_dst_set(skb, NULL);
err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);
rt2 = skb_rtable(skb);
if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
- ip_rt_put(rt2);
- skb_dst_set(skb, &rt->u.dst);
+ skb_dst_drop(skb);
+ skb->_skb_refdst = orefdst;
return -EINVAL;
}
- ip_rt_put(rt);
+ refdst_drop(orefdst);
if (rt2->rt_type != RTN_LOCAL)
break;
/* Superfast 8) loopback forward */
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 82fb43c..07de855 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -17,7 +17,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
const struct iphdr *iph = ip_hdr(skb);
struct rtable *rt;
struct flowi fl = {};
- struct dst_entry *odst;
+ unsigned long orefdst;
unsigned int hh_len;
unsigned int type;
@@ -51,14 +51,14 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
if (ip_route_output_key(net, &rt, &fl) != 0)
return -1;
- odst = skb_dst(skb);
+ orefdst = skb->_skb_refdst;
if (ip_route_input(skb, iph->daddr, iph->saddr,
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
dst_release(&rt->u.dst);
return -1;
}
dst_release(&rt->u.dst);
- dst_release(odst);
+ refdst_drop(orefdst);
}
if (skb_dst(skb)->error)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index dea3f92..705eccf 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3033,7 +3033,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
continue;
if (rt_is_expired(rt))
continue;
- skb_dst_set(skb, dst_clone(&rt->u.dst));
+ skb_dst_set_noref(skb, &rt->u.dst);
if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWROUTE,
1, NLM_F_MULTI) <= 0) {
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index c49ef21..cb3cde4 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -9,6 +9,7 @@
#include <linux/rcupdate.h>
#include <net/protocol.h>
#include <net/netfilter/nf_queue.h>
+#include <net/dst.h>
#include "nf_internals.h"
@@ -170,6 +171,7 @@ static int __nf_queue(struct sk_buff *skb,
dev_hold(physoutdev);
}
#endif
+ skb_dst_force(skb);
afinfo->saveroute(skb, entry);
status = qh->outfn(entry, queuenum);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index a969b11..a63029e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -26,6 +26,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <net/pkt_sched.h>
+#include <net/dst.h>
/* Main transmission queue. */
@@ -40,6 +41,7 @@
static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
{
+ skb_dst_force(skb);
q->gso_skb = skb;
q->qstats.requeues++;
q->q.qlen++; /* it's still part of the queue */
@@ -179,7 +181,7 @@ static inline int qdisc_restart(struct Qdisc *q)
skb = dequeue_skb(q);
if (unlikely(!skb))
return 0;
-
+ WARN_ON_ONCE(skb_dst_is_noref(skb));
root_lock = qdisc_lock(q);
dev = qdisc_dev(q);
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
^ permalink raw reply related
* Re: does the broadcom bnx2x support RSS/multi queue
From: Eilon Greenstein @ 2010-05-12 9:19 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Jon Zhou, netdev@vger.kernel.org
In-Reply-To: <1273650119.2621.5.camel@edumazet-laptop>
On Wed, 2010-05-12 at 00:41 -0700, Eric Dumazet wrote:
> Le mercredi 12 mai 2010 à 00:31 -0700, Jon Zhou a écrit :
> > hi there
> >
> > I am not sure if my Broadcom 10G nic driver(bnx2x) support RSS/multi queue
> >
> > ibm-bc-53:/home/ruizhou/nprobe # uname -a
> > Linux ibm-bc-53 2.6.27.19-5-default #1 SMP 2009-02-28 04:40:21 +0100 x86_64 x86_64 x86_64 GNU/Linux
> >
> > ibm-bc-53:/home/ruizhou/nprobe # ethtool -S eth5
> > NIC statistics:
> > rx_bytes: 68100170
> > rx_error_bytes: 0
> > tx_bytes: 0
> > tx_error_bytes: 0
> > rx_ucast_packets: 201654
> > rx_mcast_packets: 0
> > rx_bcast_packets: 0
> > tx_packets: 0
> > tx_mac_errors: 0
> > tx_carrier_errors: 0
> > rx_crc_errors: 0
> > rx_align_errors: 0
> > tx_single_collisions: 0
> > tx_multi_collisions: 0
> > tx_deferred: 0
> > tx_excess_collisions: 0
> > tx_late_collisions: 0
> > tx_total_collisions: 0
> > rx_fragments: 0
> > rx_jabbers: 0
> > rx_undersize_packets: 0
> > rx_oversize_packets: 0
> > tx_64_byte_packets: 0
> > tx_65_to_127_byte_packets: 0
> > tx_128_to_255_byte_packets: 0
> > tx_256_to_511_byte_packets: 0
> > tx_512_to_1023_byte_packets: 0
> > tx_1024_to_1522_byte_packets: 0
> > tx_1523_to_9022_byte_packets: 0
> > rx_xon_frames: 0
> > rx_xoff_frames: 0
> > tx_xon_frames: 0
> > tx_xoff_frames: 0
> > rx_mac_ctrl_frames: 0
> > rx_filtered_packets: 0
> > rx_discards: 0
> > rx_fw_discards: 0
> > brb_discard: 0
> > brb_truncate: 0
> > rx_phy_ip_err_discards: 0
> > rx_skb_alloc_discard: 0
> > rx_csum_offload_errors: 6
> >
> > the driver ver is:
> > bnx2x_main.c
> > #define DRV_MODULE_VERSION "1.45.26"
> >
> > looks not support?
> >
> > thanks
> > jon
>
> Per queue stats were added last year only (Thu Feb 12 08:36:33 2009)
>
> You might check "grep eth5 /proc/interrupts"
>
> Or upgrade to 2.6.33.x kernel :)
>
The HW and current driver support multi-queue. However, you are using a version which is too old.
^ permalink raw reply
* [PATCH net-next] bnx2x: avoid TX timeout when stopping device
From: Stanislaw Gruszka @ 2010-05-12 9:09 UTC (permalink / raw)
To: netdev; +Cc: Eilon Greenstein, Vladislav Zolotarov, Dmitry Kravkov
When stop device call netif_carrier_off() just after disabling TX queue to
avoid possibility of netdev watchdog warning and ->ndo_tx_timeout() invocation.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/bnx2x_main.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 2bc35c7..57ff5b3 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -8499,6 +8499,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
/* Disable HW interrupts, NAPI and Tx */
bnx2x_netif_stop(bp, 1);
+ netif_carrier_off(bp->dev);
del_timer_sync(&bp->timer);
SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
@@ -8524,8 +8525,6 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->state = BNX2X_STATE_CLOSED;
- netif_carrier_off(bp->dev);
-
/* The last driver must disable a "close the gate" if there is no
* parity attention or "process kill" pending.
*/
@@ -13431,6 +13430,7 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_netif_stop(bp, 0);
+ netif_carrier_off(bp->dev);
del_timer_sync(&bp->timer);
bp->stats_state = STATS_STATE_DISABLED;
@@ -13457,8 +13457,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bp->state = BNX2X_STATE_CLOSED;
- netif_carrier_off(bp->dev);
-
return 0;
}
--
1.5.5.6
^ permalink raw reply related
* Re: [PATCH 2/2] ioat2,3: convert to producer/consumer locking
From: David Howells @ 2010-05-12 8:36 UTC (permalink / raw)
To: Dan Williams
Cc: dhowells, linux-kernel, linux-raid, netdev, Paul E. McKenney,
Maciej Sosnowski
In-Reply-To: <20100511185141.6139.98842.stgit@localhost.localdomain>
Out of interest, does it make the code smaller if you mark
ioat2_get_ring_ent() and ioat2_ring_mask() with __attribute_const__?
I'm not sure whether it'll affect how long gcc is willing to cache these, but
once computed, I would guess they won't change within the calling function.
Also, is the device you're driving watching the ring and its indices? If so,
does it modify the indices? If that is the case, you might need to use
read_barrier_depends() rather than smp_read_barrier_depends().
> + prefetch(ioat2_get_ring_ent(ioat, idx + i + 1));
> + desc = ioat2_get_ring_ent(ioat, idx + i);
> dump_desc_dbg(ioat, desc);
> tx = &desc->txd;
> if (tx->cookie) {
Is this right, I wonder? You're prefetching [i+1] before reading [i]? Doesn't
this mean that you might have to wait for [i+1] to be retrieved from RAM before
[i] can be read? Should you instead read tx->cookie before issuing the
prefetch? Admittedly, this is only likely to affect the reading of the head of
the queue - subsequent reads in the same loop will, of course, have been
prefetched.
David
^ permalink raw reply
* Re: does the broadcom bnx2x support RSS/multi queue
From: Eric Dumazet @ 2010-05-12 7:41 UTC (permalink / raw)
To: Jon Zhou; +Cc: netdev@vger.kernel.org
In-Reply-To: <4A6A2125329CFD4D8CC40C9E8ABCAB9F2497D85D43@MILEXCH2.ds.jdsu.net>
Le mercredi 12 mai 2010 à 00:31 -0700, Jon Zhou a écrit :
> hi there
>
> I am not sure if my Broadcom 10G nic driver(bnx2x) support RSS/multi queue
>
> ibm-bc-53:/home/ruizhou/nprobe # uname -a
> Linux ibm-bc-53 2.6.27.19-5-default #1 SMP 2009-02-28 04:40:21 +0100 x86_64 x86_64 x86_64 GNU/Linux
>
> ibm-bc-53:/home/ruizhou/nprobe # ethtool -S eth5
> NIC statistics:
> rx_bytes: 68100170
> rx_error_bytes: 0
> tx_bytes: 0
> tx_error_bytes: 0
> rx_ucast_packets: 201654
> rx_mcast_packets: 0
> rx_bcast_packets: 0
> tx_packets: 0
> tx_mac_errors: 0
> tx_carrier_errors: 0
> rx_crc_errors: 0
> rx_align_errors: 0
> tx_single_collisions: 0
> tx_multi_collisions: 0
> tx_deferred: 0
> tx_excess_collisions: 0
> tx_late_collisions: 0
> tx_total_collisions: 0
> rx_fragments: 0
> rx_jabbers: 0
> rx_undersize_packets: 0
> rx_oversize_packets: 0
> tx_64_byte_packets: 0
> tx_65_to_127_byte_packets: 0
> tx_128_to_255_byte_packets: 0
> tx_256_to_511_byte_packets: 0
> tx_512_to_1023_byte_packets: 0
> tx_1024_to_1522_byte_packets: 0
> tx_1523_to_9022_byte_packets: 0
> rx_xon_frames: 0
> rx_xoff_frames: 0
> tx_xon_frames: 0
> tx_xoff_frames: 0
> rx_mac_ctrl_frames: 0
> rx_filtered_packets: 0
> rx_discards: 0
> rx_fw_discards: 0
> brb_discard: 0
> brb_truncate: 0
> rx_phy_ip_err_discards: 0
> rx_skb_alloc_discard: 0
> rx_csum_offload_errors: 6
>
> the driver ver is:
> bnx2x_main.c
> #define DRV_MODULE_VERSION "1.45.26"
>
> looks not support?
>
> thanks
> jon
Per queue stats were added last year only (Thu Feb 12 08:36:33 2009)
You might check "grep eth5 /proc/interrupts"
Or upgrade to 2.6.33.x kernel :)
^ permalink raw reply
* does the broadcom bnx2x support RSS/multi queue
From: Jon Zhou @ 2010-05-12 7:31 UTC (permalink / raw)
To: netdev@vger.kernel.org
hi there
I am not sure if my Broadcom 10G nic driver(bnx2x) support RSS/multi queue
ibm-bc-53:/home/ruizhou/nprobe # uname -a
Linux ibm-bc-53 2.6.27.19-5-default #1 SMP 2009-02-28 04:40:21 +0100 x86_64 x86_64 x86_64 GNU/Linux
ibm-bc-53:/home/ruizhou/nprobe # ethtool -S eth5
NIC statistics:
rx_bytes: 68100170
rx_error_bytes: 0
tx_bytes: 0
tx_error_bytes: 0
rx_ucast_packets: 201654
rx_mcast_packets: 0
rx_bcast_packets: 0
tx_packets: 0
tx_mac_errors: 0
tx_carrier_errors: 0
rx_crc_errors: 0
rx_align_errors: 0
tx_single_collisions: 0
tx_multi_collisions: 0
tx_deferred: 0
tx_excess_collisions: 0
tx_late_collisions: 0
tx_total_collisions: 0
rx_fragments: 0
rx_jabbers: 0
rx_undersize_packets: 0
rx_oversize_packets: 0
tx_64_byte_packets: 0
tx_65_to_127_byte_packets: 0
tx_128_to_255_byte_packets: 0
tx_256_to_511_byte_packets: 0
tx_512_to_1023_byte_packets: 0
tx_1024_to_1522_byte_packets: 0
tx_1523_to_9022_byte_packets: 0
rx_xon_frames: 0
rx_xoff_frames: 0
tx_xon_frames: 0
tx_xoff_frames: 0
rx_mac_ctrl_frames: 0
rx_filtered_packets: 0
rx_discards: 0
rx_fw_discards: 0
brb_discard: 0
brb_truncate: 0
rx_phy_ip_err_discards: 0
rx_skb_alloc_discard: 0
rx_csum_offload_errors: 6
the driver ver is:
bnx2x_main.c
#define DRV_MODULE_VERSION "1.45.26"
looks not support?
thanks
jon
^ permalink raw reply
* Re: [BUG] crashes with kvm/nat networking and net-next
From: Eric Dumazet @ 2010-05-12 7:32 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Bart De Schuymer, Patrick McHardy, netdev
In-Reply-To: <20100511202544.267d33ee@nehalam>
Le mardi 11 mai 2010 à 20:25 -0700, Stephen Hemminger a écrit :
> This is a regression that is showing up now in net-next, not sure what
> changed recently in bridge netfilter that could be causing it?
>
> [ 4593.956206] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
> [ 4593.956219] IP: [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
> [ 4593.956232] PGD 195ece067 PUD 1ba005067 PMD 0
> [ 4593.956241] Oops: 0000 [#1] SMP
> [ 4593.956248] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:08/ATK0110:00/hwmon/hwmon0/temp2_label
> [ 4593.956253] CPU 3
> [ 4593.956256] Modules linked in: netconsole configfs hid_belkin tun ntfs vfat msdos fat autofs4 binfmt_misc ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc kvm_intel kvm radeon ttm drm_kms_helper drm i2c_algo_bit snd_hda_codec_analog ipv6 snd_hda_intel snd_hda_codec snd_hwdep snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device psmouse asus_atk0110 snd serio_raw soundcore snd_page_alloc usbhid mvsas libsas scsi_transport_sas floppy sky2 e1000e [last unloaded: netconsole]
> [ 4593.956375]
> [ 4593.956380] Pid: 29512, comm: kvm Not tainted 2.6.34-rc7-net #195 P6T DELUXE/System Product Name
> [ 4593.956384] RIP: 0010:[<ffffffffa03357a4>] [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
> [ 4593.956395] RSP: 0018:ffff880001e63b78 EFLAGS: 00010246
> [ 4593.956399] RAX: 0000000000000608 RBX: ffff880057181700 RCX: ffff8801b813d000
> [ 4593.956402] RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff880057181700
> [ 4593.956406] RBP: ffff880001e63ba8 R08: ffff8801b9d97000 R09: ffffffffa0335650
> [ 4593.956410] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8801b813d000
> [ 4593.956413] R13: ffffffff81ab3940 R14: ffff880057181700 R15: 0000000000000002
> [ 4593.956418] FS: 00007fc40d380710(0000) GS:ffff880001e60000(0000) knlGS:0000000000000000
> [ 4593.956422] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
> [ 4593.956426] CR2: 0000000000000018 CR3: 00000001ba1d7000 CR4: 00000000000026e0
> [ 4593.956429] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [ 4593.956433] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [ 4593.956437] Process kvm (pid: 29512, threadinfo ffff8801ba566000, task ffff8801b8003870)
> [ 4593.956441] Stack:
> [ 4593.956443] 0000000100000020 ffff880001e63ba0 ffff880001e63ba0 ffff880057181700
> [ 4593.956451] <0> ffffffffa0335650 ffffffff81ab3940 ffff880001e63bd8 ffffffffa03350e6
> [ 4593.956462] <0> ffff880001e63c40 000000000000024d ffff880057181700 0000000080000000
> [ 4593.956474] Call Trace:
> [ 4593.956478] <IRQ>
> [ 4593.956488] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
> [ 4593.956496] [<ffffffffa03350e6>] NF_HOOK_THRESH+0x56/0x60 [bridge]
> [ 4593.956504] [<ffffffffa0335282>] br_nf_forward_arp+0x112/0x120 [bridge]
> [ 4593.956511] [<ffffffff813f7184>] nf_iterate+0x64/0xa0
> [ 4593.956519] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
> [ 4593.956524] [<ffffffff813f722c>] nf_hook_slow+0x6c/0x100
> [ 4593.956531] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
> [ 4593.956538] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
> [ 4593.956545] [<ffffffffa032f86d>] __br_forward+0x6d/0xc0 [bridge]
> [ 4593.956550] [<ffffffff813c5d8e>] ? skb_clone+0x3e/0x70
> [ 4593.956557] [<ffffffffa032f462>] deliver_clone+0x32/0x60 [bridge]
> [ 4593.956564] [<ffffffffa032f6b6>] br_flood+0xa6/0xe0 [bridge]
> [ 4593.956571] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
> [ 4593.956578] [<ffffffffa032f700>] br_flood_forward+0x10/0x20 [bridge]
> [ 4593.956586] [<ffffffffa0330ace>] br_handle_frame_finish+0x23e/0x260 [bridge]
> [ 4593.956595] [<ffffffffa03307ea>] br_handle_frame+0x1aa/0x250 [bridge]
> [ 4593.956605] [<ffffffff81070331>] ? autoremove_wake_function+0x11/0x40
> [ 4593.956614] [<ffffffff813cf537>] __netif_receive_skb+0x187/0x5d0
> [ 4593.956622] [<ffffffff813cfa81>] process_backlog+0x101/0x210
> [ 4593.956630] [<ffffffff813d092d>] net_rx_action+0x10d/0x260
> [ 4593.956639] [<ffffffff81058100>] __do_softirq+0xb0/0x230
> [ 4593.956648] [<ffffffff81009e5c>] call_softirq+0x1c/0x30
> [ 4593.956653] <EOI>
> [ 4593.956662] [<ffffffff8100bad5>] ? do_softirq+0x65/0xa0
> [ 4593.956667] [<ffffffff813d3e48>] netif_rx_ni+0x28/0x30
> [ 4593.956673] [<ffffffffa03e2196>] tun_chr_aio_write+0x276/0x540 [tun]
> [ 4593.956679] [<ffffffffa03e1f20>] ? tun_chr_aio_write+0x0/0x540 [tun]
> [ 4593.956686] [<ffffffff8110cd0b>] do_sync_readv_writev+0xcb/0x110
> [ 4593.956692] [<ffffffff8120d593>] ? selinux_file_permission+0xf3/0x150
> [ 4593.956699] [<ffffffff81203081>] ? security_file_permission+0x11/0x20
> [ 4593.956704] [<ffffffff8110dd9a>] do_readv_writev+0xca/0x1f0
> [ 4593.956710] [<ffffffff8111c888>] ? vfs_ioctl+0x38/0xd0
> [ 4593.956714] [<ffffffff8111ceda>] ? do_vfs_ioctl+0x8a/0x610
> [ 4593.956719] [<ffffffff8110defe>] vfs_writev+0x3e/0x60
> [ 4593.956723] [<ffffffff8110e02c>] sys_writev+0x4c/0xb0
> [ 4593.956730] [<ffffffff81008f42>] system_call_fastpath+0x16/0x1b
> [ 4593.956733] Code: d8 00 00 00 66 81 7c 01 10 08 06 0f 85 fc fe ff ff 44 8b 15 ff 6e 00 00 45 85 d2 0f 84 ec fe ff ff 66 0f 1f 44 00 00 4c 8b 63 28 <8b> 42 18 e9 e5 fe ff ff 0f 1f 40 00 48 89 df e8 68 a1 ff ff e9
> [ 4593.956838] RIP [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
> [ 4593.956848] RSP <ffff880001e63b78>
> [ 4593.956851] CR2: 0000000000000018
> [ 4593.956855] ---[ end trace 5703d55ac3604d1c ]---
> [ 4593.956859] Kernel panic - not syncing: Fatal exception in interrupt
> [ 4593.956864] Pid: 29512, comm: kvm Tainted: G D 2.6.34-rc7-net #195
> [ 4593.956867] Call Trace:
> [ 4593.956869] <IRQ> [<ffffffff81484ff2>] panic+0x78/0xf1
> [ 4593.956880] [<ffffffff81489449>] oops_end+0xa9/0xb0
> [ 4593.956885] [<ffffffff81033963>] no_context+0xf3/0x260
> [ 4593.956891] [<ffffffff81256664>] ? do_raw_spin_lock+0x54/0x150
> [ 4593.956896] [<ffffffff81033be5>] __bad_area_nosemaphore+0x115/0x1d0
> [ 4593.956901] [<ffffffff81033cae>] bad_area_nosemaphore+0xe/0x10
> [ 4593.956907] [<ffffffff8148bb3f>] do_page_fault+0x28f/0x330
> [ 4593.956913] [<ffffffff814887b5>] page_fault+0x25/0x30
> [ 4593.956921] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
> [ 4593.956929] [<ffffffffa03357a4>] ? br_nf_forward_finish+0x154/0x170 [bridge]
> [ 4593.956938] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
> [ 4593.956951] [<ffffffffa03350e6>] NF_HOOK_THRESH+0x56/0x60 [bridge]
> [ 4593.956963] [<ffffffffa0335282>] br_nf_forward_arp+0x112/0x120 [bridge]
> [ 4593.956972] [<ffffffff813f7184>] nf_iterate+0x64/0xa0
> [ 4593.956983] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
> [ 4593.956990] [<ffffffff813f722c>] nf_hook_slow+0x6c/0x100
> [ 4593.956997] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
> [ 4593.957005] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
> [ 4593.957012] [<ffffffffa032f86d>] __br_forward+0x6d/0xc0 [bridge]
> [ 4593.957017] [<ffffffff813c5d8e>] ? skb_clone+0x3e/0x70
> [ 4593.957023] [<ffffffffa032f462>] deliver_clone+0x32/0x60 [bridge]
> [ 4593.957030] [<ffffffffa032f6b6>] br_flood+0xa6/0xe0 [bridge]
> [ 4593.957037] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
> [ 4593.957044] [<ffffffffa032f700>] br_flood_forward+0x10/0x20 [bridge]
> [ 4593.957052] [<ffffffffa0330ace>] br_handle_frame_finish+0x23e/0x260 [bridge]
> [ 4593.957059] [<ffffffffa03307ea>] br_handle_frame+0x1aa/0x250 [bridge]
> [ 4593.957065] [<ffffffff81070331>] ? autoremove_wake_function+0x11/0x40
> [ 4593.957070] [<ffffffff813cf537>] __netif_receive_skb+0x187/0x5d0
> [ 4593.957076] [<ffffffff813cfa81>] process_backlog+0x101/0x210
> [ 4593.957081] [<ffffffff813d092d>] net_rx_action+0x10d/0x260
> [ 4593.957086] [<ffffffff81058100>] __do_softirq+0xb0/0x230
> [ 4593.957091] [<ffffffff81009e5c>] call_softirq+0x1c/0x30
> [ 4593.957094] <EOI> [<ffffffff8100bad5>] ? do_softirq+0x65/0xa0
> [ 4593.957102] [<ffffffff813d3e48>] netif_rx_ni+0x28/0x30
> [ 4593.957108] [<ffffffffa03e2196>] tun_chr_aio_write+0x276/0x540 [tun]
> [ 4593.957113] [<ffffffffa03e1f20>] ? tun_chr_aio_write+0x0/0x540 [tun]
> [ 4593.957119] [<ffffffff8110cd0b>] do_sync_readv_writev+0xcb/0x110
> [ 4593.957125] [<ffffffff8120d593>] ? selinux_file_permission+0xf3/0x150
> [ 4593.957130] [<ffffffff81203081>] ? security_file_permission+0x11/0x20
> [ 4593.957135] [<ffffffff8110dd9a>] do_readv_writev+0xca/0x1f0
> [ 4593.957139] [<ffffffff8111c888>] ? vfs_ioctl+0x38/0xd0
> [ 4593.957144] [<ffffffff8111ceda>] ? do_vfs_ioctl+0x8a/0x610
> [ 4593.957148] [<ffffffff8110defe>] vfs_writev+0x3e/0x60
> [ 4593.957153] [<ffffffff8110e02c>] sys_writev+0x4c/0xb0
> [ 4593.957158] [<ffffffff81008f42>] system_call_fastpath+0x16/0x1b
Not sure, but br_nf_forward_ip() has following check :
if (!skb->nf_bridge)
return NF_ACCEPT;
while br_nf_forward_arp() missed this check ...
So we can dereference null pointer later
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 93f80fe..cd2e5f5 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -723,6 +723,9 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
return NF_ACCEPT;
#endif
+ if (!skb->nf_bridge)
+ return NF_ACCEPT;
+
if (skb->protocol != htons(ETH_P_ARP)) {
if (!IS_VLAN_ARP(skb))
return NF_ACCEPT;
^ permalink raw reply related
* Re: [Uclinux-dist-devel] [PATCH 1/9] netdev: bfin_mac: add support for IEEE 1588 PTP
From: Richard Cochran @ 2010-05-12 7:20 UTC (permalink / raw)
To: Mike Frysinger
Cc: Barry Song, netdev, Barry Song, David S. Miller,
uclinux-dist-devel
In-Reply-To: <AANLkTimPOxc4RQ5iDMk8N9xYFb95VaqFleUa_nG4Gwwn@mail.gmail.com>
On Tue, May 11, 2010 at 11:31:37PM -0400, Mike Frysinger wrote:
> On Tue, May 11, 2010 at 23:20, Barry Song wrote:
> >
> > I think the API can work for blackfin. But our PTP driver is based on
> > drivers/net/igb and has worked together with user-space PTPD utility.
> > Here he is writing a different driver framework. It is not the moment
> > for us to merge now. Maybe next kernel version after his patches have
> > been popular.
>
> i'm not going to merge them into our tree ahead of the net->mainline
> merge. Richard would just like some feedback on the proposed
> framework to make sure it doesnt have limitations we'd have to fix
> after things get merged.
Yes, thats right. It is enough just to know that the API *could* work
for blackfin. The idea is to have a standard API that works for all
current (and likely future) PTP hardware clocks.
The patch set is still under active development and review, so it is
better for you to wait until the dust settles.
Thanks,
Richard
^ permalink raw reply
* [PATCH net-next-2.6] [PPP] cleanup: remove pppoe_ioctl() declaration.
From: Rami Rosen @ 2010-05-12 5:37 UTC (permalink / raw)
To: davem, netdev
[-- Attachment #1: Type: text/plain, Size: 167 bytes --]
Hi,
- This patch removes pppoe_ioctl() declaration in
drivers/net/pppoe.c as it is unneeded.
Regards,
Rami Rosen
Signed-off-by: Rami Rosen <ramirose@gmail.com>
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 511 bytes --]
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
old mode 100644
new mode 100755
index 99f031a..6fd84ed
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -89,7 +89,6 @@
#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
#define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1)
-static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
^ permalink raw reply related
* [patch 2/3] [PATCH] qeth: new message if OLM limit is reached
From: frank.blaschka @ 2010-05-12 5:34 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, Ursula Braun
In-Reply-To: <20100512053444.035939000@de.ibm.com>
[-- Attachment #1: 602-qeth-olm-limit-msg.diff --]
[-- Type: text/plain, Size: 1621 bytes --]
From: Ursula Braun <ursula.braun@de.ibm.com>
z/OS may activate Optimized Latency Mode (OLM) for a connection
through an OSA Express3 adapter, which reduces the number of
allowed concurrent connections, if adapter is used in shared mode.
Create a meaningful message, if activation of an OSA-connection fails
due to an active OLM-connection on the shared OSA-adapter.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_core_main.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff -urpN linux-2.6/drivers/s390/net/qeth_core_main.c linux-2.6-patched/drivers/s390/net/qeth_core_main.c
--- linux-2.6/drivers/s390/net/qeth_core_main.c 2010-05-11 22:10:12.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_core_main.c 2010-05-11 22:10:34.000000000 +0200
@@ -1976,6 +1976,7 @@ static int qeth_ulp_setup_cb(struct qeth
unsigned long data)
{
struct qeth_cmd_buffer *iob;
+ int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
@@ -1983,8 +1984,15 @@ static int qeth_ulp_setup_cb(struct qeth
memcpy(&card->token.ulp_connection_r,
QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
QETH_MPC_TOKEN_LENGTH);
+ if (!strncmp("00S", QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+ 3)) {
+ QETH_DBF_TEXT(SETUP, 2, "olmlimit");
+ dev_err(&card->gdev->dev, "A connection could not be "
+ "established because of an OLM limit\n");
+ rc = -EMLINK;
+ }
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
- return 0;
+ return rc;
}
static int qeth_ulp_setup(struct qeth_card *card)
^ permalink raw reply
* [patch 0/3] s390: qeth patches for 2.6.35
From: frank.blaschka @ 2010-05-12 5:34 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390
Hi Dave,
here are some qeth patches for 2.6.35 (net-next).
shortlog:
Ursula Braun (1)
qeth: new message if OLM limit is reached
Frank Blaschka (2)
qeth: exploit HW TX checksumming
qeth: synchronize configuration interface
Thanks,
Frank
^ permalink raw reply
* [patch 3/3] [PATCH] qeth: synchronize configuration interface
From: frank.blaschka @ 2010-05-12 5:34 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390
In-Reply-To: <20100512053444.035939000@de.ibm.com>
[-- Attachment #1: 609-qeth-sync-conf.diff --]
[-- Type: text/plain, Size: 23432 bytes --]
From: Frank Blaschka <frank.blaschka@de.ibm.com>
Synchronize access to the drivers configuration interface.
Also do not allow configuration changes during online/offline
transition.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_core.h | 1
drivers/s390/net/qeth_core_main.c | 1
drivers/s390/net/qeth_core_sys.c | 148 ++++++++++++++---------
drivers/s390/net/qeth_l2_main.c | 8 +
drivers/s390/net/qeth_l3_main.c | 8 +
drivers/s390/net/qeth_l3_sys.c | 244 +++++++++++++++++++++-----------------
6 files changed, 242 insertions(+), 168 deletions(-)
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -740,6 +740,7 @@ struct qeth_card {
atomic_t force_alloc_skb;
struct service_level qeth_service_level;
struct qdio_ssqd_desc ssqd;
+ struct mutex conf_mutex;
};
struct qeth_card_list_struct {
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1100,6 +1100,7 @@ static int qeth_setup_card(struct qeth_c
spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock);
+ mutex_init(&card->conf_mutex);
card->thread_start_mask = 0;
card->thread_allowed_mask = 0;
card->thread_running_mask = 0;
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -122,23 +122,32 @@ static ssize_t qeth_dev_portno_store(str
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
unsigned int portno, limit;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
portno = simple_strtoul(buf, &tmp, 16);
- if (portno > QETH_MAX_PORTNO)
- return -EINVAL;
+ if (portno > QETH_MAX_PORTNO) {
+ rc = -EINVAL;
+ goto out;
+ }
limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt);
- if (portno > limit)
- return -EINVAL;
-
+ if (portno > limit) {
+ rc = -EINVAL;
+ goto out;
+ }
card->info.portno = portno;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
@@ -165,18 +174,23 @@ static ssize_t qeth_dev_portname_store(s
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
tmp = strsep((char **) &buf, "\n");
- if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
- return -EINVAL;
+ if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
+ rc = -EINVAL;
+ goto out;
+ }
card->info.portname[0] = strlen(tmp);
/* for beauty reasons */
@@ -184,8 +198,9 @@ static ssize_t qeth_dev_portname_store(s
card->info.portname[i] = ' ';
strcpy(card->info.portname + 1, tmp);
ASCEBC(card->info.portname + 1, 8);
-
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
@@ -215,20 +230,25 @@ static ssize_t qeth_dev_prioqing_store(s
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
/* check if 1920 devices are supported ,
* if though we have to permit priority queueing
*/
if (card->qdio.no_out_queues == 1) {
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
- return -EPERM;
+ rc = -EPERM;
+ goto out;
}
tmp = strsep((char **) &buf, "\n");
@@ -251,10 +271,11 @@ static ssize_t qeth_dev_prioqing_store(s
} else if (!strcmp(tmp, "no_prio_queueing")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
@@ -277,14 +298,17 @@ static ssize_t qeth_dev_bufcnt_store(str
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int cnt, old_cnt;
- int rc;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
old_cnt = card->qdio.in_buf_pool.buf_count;
cnt = simple_strtoul(buf, &tmp, 10);
@@ -293,7 +317,9 @@ static ssize_t qeth_dev_bufcnt_store(str
if (old_cnt != cnt) {
rc = qeth_realloc_buffer_pool(card, cnt);
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
@@ -337,25 +363,27 @@ static ssize_t qeth_dev_performance_stat
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1)) {
if (i == card->options.performance_stats)
- return count;
+ goto out;;
card->options.performance_stats = i;
if (i == 0)
memset(&card->perf_stats, 0,
sizeof(struct qeth_perf_stats));
card->perf_stats.initial_rx_packets = card->stats.rx_packets;
card->perf_stats.initial_tx_packets = card->stats.tx_packets;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
@@ -377,15 +405,17 @@ static ssize_t qeth_dev_layer2_store(str
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i, rc;
+ int i, rc = 0;
enum qeth_discipline_id newdis;
if (!card)
return -EINVAL;
- if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)))
- return -EPERM;
+ mutex_lock(&card->conf_mutex);
+ if (card->state != CARD_STATE_DOWN) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 16);
switch (i) {
@@ -396,12 +426,13 @@ static ssize_t qeth_dev_layer2_store(str
newdis = QETH_DISCIPLINE_LAYER2;
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
- if (card->options.layer2 == newdis) {
- return count;
- } else {
+ if (card->options.layer2 == newdis)
+ goto out;
+ else {
if (card->discipline.ccwgdriver) {
card->discipline.ccwgdriver->remove(card->gdev);
qeth_core_free_discipline(card);
@@ -410,12 +441,12 @@ static ssize_t qeth_dev_layer2_store(str
rc = qeth_core_load_discipline(card, newdis);
if (rc)
- return rc;
+ goto out;
rc = card->discipline.ccwgdriver->probe(card->gdev);
- if (rc)
- return rc;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
@@ -454,11 +485,10 @@ static ssize_t qeth_dev_isolation_store(
char *tmp, *curtoken;
curtoken = (char *) buf;
- if (!card) {
- rc = -EINVAL;
- goto out;
- }
+ if (!card)
+ return -EINVAL;
+ mutex_lock(&card->conf_mutex);
/* check for unknown, too, in case we do not yet know who we are */
if (card->info.type != QETH_CARD_TYPE_OSAE &&
card->info.type != QETH_CARD_TYPE_UNKNOWN) {
@@ -491,6 +521,7 @@ static ssize_t qeth_dev_isolation_store(
rc = ipa_rc;
}
out:
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -510,22 +541,25 @@ static ssize_t qeth_dev_blkt_store(struc
const char *buf, size_t count, int *value, int max_value)
{
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
-
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 10);
- if (i <= max_value) {
+ if (i <= max_value)
*value = i;
- } else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_dev_blkt_total_show(struct device *dev,
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -924,6 +924,7 @@ static int __qeth_l2_set_online(struct c
enum qeth_card_states recover_flag;
BUG_ON(!card);
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -956,7 +957,7 @@ static int __qeth_l2_set_online(struct c
dev_warn(&card->gdev->dev,
"The LAN is offline\n");
card->lan_online = 0;
- return 0;
+ goto out;
}
rc = -ENODEV;
goto out_remove;
@@ -995,6 +996,8 @@ static int __qeth_l2_set_online(struct c
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+out:
+ mutex_unlock(&card->conf_mutex);
return 0;
out_remove:
@@ -1007,6 +1010,7 @@ out_remove:
card->state = CARD_STATE_RECOVER;
else
card->state = CARD_STATE_DOWN;
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -1022,6 +1026,7 @@ static int __qeth_l2_set_offline(struct
int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag;
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
@@ -1040,6 +1045,7 @@ static int __qeth_l2_set_offline(struct
card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+ mutex_unlock(&card->conf_mutex);
return 0;
}
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3378,6 +3378,7 @@ static int __qeth_l3_set_online(struct c
enum qeth_card_states recover_flag;
BUG_ON(!card);
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -3409,7 +3410,7 @@ static int __qeth_l3_set_online(struct c
dev_warn(&card->gdev->dev,
"The LAN is offline\n");
card->lan_online = 0;
- return 0;
+ goto out;
}
rc = -ENODEV;
goto out_remove;
@@ -3456,6 +3457,8 @@ static int __qeth_l3_set_online(struct c
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+out:
+ mutex_unlock(&card->conf_mutex);
return 0;
out_remove:
card->use_hard_stop = 1;
@@ -3467,6 +3470,7 @@ out_remove:
card->state = CARD_STATE_RECOVER;
else
card->state = CARD_STATE_DOWN;
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -3482,6 +3486,7 @@ static int __qeth_l3_set_offline(struct
int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag;
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
@@ -3500,6 +3505,7 @@ static int __qeth_l3_set_offline(struct
card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+ mutex_unlock(&card->conf_mutex);
return 0;
}
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -70,10 +70,10 @@ static ssize_t qeth_l3_dev_route_store(s
{
enum qeth_routing_types old_route_type = route->type;
char *tmp;
- int rc;
+ int rc = 0;
tmp = strsep((char **) &buf, "\n");
-
+ mutex_lock(&card->conf_mutex);
if (!strcmp(tmp, "no_router")) {
route->type = NO_ROUTER;
} else if (!strcmp(tmp, "primary_connector")) {
@@ -87,7 +87,8 @@ static ssize_t qeth_l3_dev_route_store(s
} else if (!strcmp(tmp, "multicast_router")) {
route->type = MULTICAST_ROUTER;
} else {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
if (((card->state == CARD_STATE_SOFTSETUP) ||
(card->state == CARD_STATE_UP)) &&
@@ -97,7 +98,9 @@ static ssize_t qeth_l3_dev_route_store(s
else if (prot == QETH_PROT_IPV6)
rc = qeth_l3_setrouting_v6(card);
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_route4_store(struct device *dev,
@@ -157,22 +160,26 @@ static ssize_t qeth_l3_dev_fake_broadcas
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1))
card->options.fake_broadcast = i;
- else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
@@ -200,31 +207,35 @@ static ssize_t qeth_l3_dev_broadcast_mod
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
(card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
tmp = strsep((char **) &buf, "\n");
- if (!strcmp(tmp, "local")) {
+ if (!strcmp(tmp, "local"))
card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
- return count;
- } else if (!strcmp(tmp, "all_rings")) {
+ else if (!strcmp(tmp, "all_rings"))
card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
- return count;
- } else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
@@ -251,18 +262,22 @@ static ssize_t qeth_l3_dev_canonical_mac
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
(card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
i = simple_strtoul(buf, &tmp, 16);
@@ -270,10 +285,11 @@ static ssize_t qeth_l3_dev_canonical_mac
card->options.macaddr_mode = i?
QETH_TR_MACADDR_CANONICAL :
QETH_TR_MACADDR_NONCANONICAL;
- else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
@@ -297,11 +313,12 @@ static ssize_t qeth_l3_dev_checksum_stor
struct qeth_card *card = dev_get_drvdata(dev);
enum qeth_checksum_types csum_type;
char *tmp;
- int rc;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "sw_checksumming"))
csum_type = SW_CHECKSUMMING;
@@ -309,13 +326,15 @@ static ssize_t qeth_l3_dev_checksum_stor
csum_type = HW_CHECKSUMMING;
else if (!strcmp(tmp, "no_checksumming"))
csum_type = NO_CHECKSUMMING;
- else
- return -EINVAL;
+ else {
+ rc = -EINVAL;
+ goto out;
+ }
rc = qeth_l3_set_rx_csum(card, csum_type);
- if (rc)
- return rc;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
@@ -336,7 +355,7 @@ static ssize_t qeth_l3_dev_sniffer_store
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
- int ret;
+ int rc = 0;
unsigned long i;
if (!card)
@@ -345,19 +364,24 @@ static ssize_t qeth_l3_dev_sniffer_store
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
- ret = strict_strtoul(buf, 16, &i);
- if (ret)
- return -EINVAL;
+ rc = strict_strtoul(buf, 16, &i);
+ if (rc) {
+ rc = -EINVAL;
+ goto out;
+ }
switch (i) {
case 0:
card->options.sniffer = i;
break;
case 1:
- ret = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
+ qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) {
card->options.sniffer = i;
if (card->qdio.init_pool.buf_count !=
@@ -366,11 +390,13 @@ static ssize_t qeth_l3_dev_sniffer_store
QETH_IN_BUF_COUNT_MAX);
break;
} else
- return -EPERM;
+ rc = -EPERM;
default: /* fall through */
- return -EINVAL;
+ rc = -EINVAL;
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
@@ -412,12 +438,11 @@ static ssize_t qeth_l3_dev_large_send_st
else
return -EINVAL;
- if (card->options.large_send == type)
- return count;
- rc = qeth_l3_set_large_send(card, type);
- if (rc)
- return rc;
- return count;
+ mutex_lock(&card->conf_mutex);
+ if (card->options.large_send != type)
+ rc = qeth_l3_set_large_send(card, type);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
@@ -455,13 +480,17 @@ static ssize_t qeth_l3_dev_ipato_enable_
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
@@ -470,10 +499,11 @@ static ssize_t qeth_l3_dev_ipato_enable_
card->ipato.enabled = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.enabled = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
@@ -497,10 +527,12 @@ static ssize_t qeth_l3_dev_ipato_invert4
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
@@ -508,10 +540,10 @@ static ssize_t qeth_l3_dev_ipato_invert4
card->ipato.invert4 = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.invert4 = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
@@ -593,27 +625,28 @@ static ssize_t qeth_l3_dev_ipato_add_sto
struct qeth_ipato_entry *ipatoe;
u8 addr[16];
int mask_bits;
- int rc;
+ int rc = 0;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
if (rc)
- return rc;
+ goto out;
ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
if (!ipatoe) {
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out;
}
ipatoe->proto = proto;
memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
ipatoe->mask_bits = mask_bits;
rc = qeth_l3_add_ipato_entry(card, ipatoe);
- if (rc) {
+ if (rc)
kfree(ipatoe);
- return rc;
- }
-
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
@@ -636,15 +669,14 @@ static ssize_t qeth_l3_dev_ipato_del_sto
{
u8 addr[16];
int mask_bits;
- int rc;
+ int rc = 0;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
- if (rc)
- return rc;
-
- qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
-
- return count;
+ if (!rc)
+ qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
@@ -677,10 +709,12 @@ static ssize_t qeth_l3_dev_ipato_invert6
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
@@ -688,10 +722,10 @@ static ssize_t qeth_l3_dev_ipato_invert6
card->ipato.invert6 = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.invert6 = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
@@ -813,15 +847,12 @@ static ssize_t qeth_l3_dev_vipa_add_stor
u8 addr[16] = {0, };
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
- if (rc)
- return rc;
-
- rc = qeth_l3_add_vipa(card, proto, addr);
- if (rc)
- return rc;
-
- return count;
+ if (!rc)
+ rc = qeth_l3_add_vipa(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
@@ -845,13 +876,12 @@ static ssize_t qeth_l3_dev_vipa_del_stor
u8 addr[16];
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
- if (rc)
- return rc;
-
- qeth_l3_del_vipa(card, proto, addr);
-
- return count;
+ if (!rc)
+ qeth_l3_del_vipa(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
@@ -979,15 +1009,12 @@ static ssize_t qeth_l3_dev_rxip_add_stor
u8 addr[16] = {0, };
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
- if (rc)
- return rc;
-
- rc = qeth_l3_add_rxip(card, proto, addr);
- if (rc)
- return rc;
-
- return count;
+ if (!rc)
+ rc = qeth_l3_add_rxip(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
@@ -1011,13 +1038,12 @@ static ssize_t qeth_l3_dev_rxip_del_stor
u8 addr[16];
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
- if (rc)
- return rc;
-
- qeth_l3_del_rxip(card, proto, addr);
-
- return count;
+ if (!rc)
+ qeth_l3_del_rxip(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
^ permalink raw reply
* [patch 1/3] [PATCH] qeth: exploit HW TX checksumming
From: frank.blaschka @ 2010-05-12 5:34 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390
In-Reply-To: <20100512053444.035939000@de.ibm.com>
[-- Attachment #1: 601-qeth-hw-tx-checksum.diff --]
[-- Type: text/plain, Size: 6550 bytes --]
From: Frank Blaschka <frank.blaschka@de.ibm.com>
OSA supports HW TX checksumming in layer 3 mode. Enable this
feature and remove software fallback used for TSO. Cleanup
checksum bits to indicate OSA can do checksumming only for
IPv4 TCP and UDP.
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
---
drivers/s390/net/qeth_core.h | 3 -
drivers/s390/net/qeth_l3_main.c | 92 +++++++++++++++++++++++++++++-----------
2 files changed, 69 insertions(+), 26 deletions(-)
diff -urpN linux-2.6/drivers/s390/net/qeth_core.h linux-2.6-patched/drivers/s390/net/qeth_core.h
--- linux-2.6/drivers/s390/net/qeth_core.h 2010-05-11 22:10:12.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_core.h 2010-05-11 22:10:34.000000000 +0200
@@ -351,7 +351,7 @@ enum qeth_header_ids {
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
-#define QETH_HDR_EXT_UDP_TSO 0x40 /*bit off for TCP*/
+#define QETH_HDR_EXT_UDP 0x40 /*bit off for TCP*/
static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
{
@@ -630,6 +630,7 @@ struct qeth_card_info {
int unique_id;
struct qeth_card_blkt blkt;
__u32 csum_mask;
+ __u32 tx_csum_mask;
enum qeth_ipa_promisc_modes promisc_mode;
};
diff -urpN linux-2.6/drivers/s390/net/qeth_l3_main.c linux-2.6-patched/drivers/s390/net/qeth_l3_main.c
--- linux-2.6/drivers/s390/net/qeth_l3_main.c 2010-05-11 22:10:12.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_l3_main.c 2010-05-11 22:10:34.000000000 +0200
@@ -54,16 +54,16 @@ int qeth_l3_set_large_send(struct qeth_c
if (card->options.large_send == QETH_LARGE_SEND_TSO) {
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM;
+ NETIF_F_IP_CSUM;
} else {
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM);
+ NETIF_F_IP_CSUM);
card->options.large_send = QETH_LARGE_SEND_NO;
rc = -EOPNOTSUPP;
}
} else {
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM);
+ NETIF_F_IP_CSUM);
card->options.large_send = QETH_LARGE_SEND_NO;
}
return rc;
@@ -1108,6 +1108,13 @@ static int qeth_l3_default_setassparms_c
card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
QETH_DBF_TEXT_(TRACE, 3, "csum:%d", card->info.csum_mask);
}
+ if (cmd->data.setassparms.hdr.assist_no == IPA_OUTBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.tx_csum_mask =
+ cmd->data.setassparms.data.flags_32bit;
+ QETH_DBF_TEXT_(TRACE, 3, "tcsu:%d", card->info.tx_csum_mask);
+ }
+
return 0;
}
@@ -1536,6 +1543,28 @@ static int qeth_l3_start_ipa_checksum(st
return rc;
}
+static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
+{
+ int rc = 0;
+
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ return rc;
+ rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc)
+ goto err_out;
+ rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE, card->info.tx_csum_mask);
+ if (rc)
+ goto err_out;
+ dev_info(&card->gdev->dev, "HW TX Checksumming enabled\n");
+ return rc;
+err_out:
+ dev_warn(&card->gdev->dev, "Enabling HW TX checksumming for %s "
+ "failed, using SW TX checksumming\n", QETH_CARD_IFNAME(card));
+ return rc;
+}
+
static int qeth_l3_start_ipa_tso(struct qeth_card *card)
{
int rc;
@@ -1578,6 +1607,7 @@ static int qeth_l3_start_ipassists(struc
qeth_l3_start_ipa_ipv6(card); /* go on*/
qeth_l3_start_ipa_broadcast(card); /* go on*/
qeth_l3_start_ipa_checksum(card); /* go on*/
+ qeth_l3_start_ipa_tx_checksum(card);
qeth_l3_start_ipa_tso(card); /* go on*/
return 0;
}
@@ -2817,6 +2847,21 @@ static void qeth_l3_fill_header(struct q
}
}
+static inline void qeth_l3_hdr_csum(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* tcph->check contains already the pseudo hdr checksum
+ * so just set the header flags
+ */
+ if (iph->protocol == IPPROTO_UDP)
+ hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP;
+ hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ;
+ if (card->options.performance_stats)
+ card->perf_stats.tx_csum++;
+}
+
static void qeth_tso_fill_header(struct qeth_card *card,
struct qeth_hdr *qhdr, struct sk_buff *skb)
{
@@ -2852,21 +2897,6 @@ static void qeth_tso_fill_header(struct
}
}
-static void qeth_tx_csum(struct sk_buff *skb)
-{
- __wsum csum;
- int offset;
-
- skb_set_transport_header(skb, skb->csum_start - skb_headroom(skb));
- offset = skb->csum_start - skb_headroom(skb);
- BUG_ON(offset >= skb_headlen(skb));
- csum = skb_checksum(skb, offset, skb->len - offset, 0);
-
- offset += skb->csum_offset;
- BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
- *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-}
-
static inline int qeth_l3_tso_elements(struct sk_buff *skb)
{
unsigned long tcpd = (unsigned long)tcp_hdr(skb) +
@@ -2923,12 +2953,6 @@ static int qeth_l3_hard_start_xmit(struc
if (skb_is_gso(skb))
large_send = card->options.large_send;
- else
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- qeth_tx_csum(skb);
- if (card->options.performance_stats)
- card->perf_stats.tx_csum++;
- }
if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
(skb_shinfo(skb)->nr_frags == 0)) {
@@ -3007,6 +3031,9 @@ static int qeth_l3_hard_start_xmit(struc
cast_type);
hdr->hdr.l3.length = new_skb->len - data_offset;
}
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ qeth_l3_hdr_csum(card, hdr, new_skb);
}
elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
@@ -3132,10 +3159,25 @@ static int qeth_l3_ethtool_set_tso(struc
return rc;
}
+static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ if (data) {
+ if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ dev->features |= NETIF_F_IP_CSUM;
+ else
+ return -EPERM;
+ } else
+ dev->features &= ~NETIF_F_IP_CSUM;
+
+ return 0;
+}
+
static const struct ethtool_ops qeth_l3_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_hw_csum,
+ .set_tx_csum = qeth_l3_ethtool_set_tx_csum,
.get_rx_csum = qeth_l3_ethtool_get_rx_csum,
.set_rx_csum = qeth_l3_ethtool_set_rx_csum,
.get_sg = ethtool_op_get_sg,
^ permalink raw reply
* Re: get beyond 1Gbps with pktgen on 10Gb nic?
From: Jesse Brandeburg @ 2010-05-12 4:51 UTC (permalink / raw)
To: Jon Zhou; +Cc: Ben Greear, Ben Hutchings, netdev@vger.kernel.org
In-Reply-To: <4A6A2125329CFD4D8CC40C9E8ABCAB9F2497D85C81@MILEXCH2.ds.jdsu.net>
On Tue, May 11, 2010 at 9:00 PM, Jon Zhou <Jon.Zhou@jdsu.com> wrote:
> I just used multi netperf instances to reach 900K pps/8Gb+ traffic on the Broadcom 10G nic:
>
> command:
>
> for i in 1 2 3 4 5 6 7 8 9 10
> do
> netperf -l 60 -H 192.168.0.53 -- -m 60 -s 100M -S 100M &
> done
>
> the msg size was assigned as 64 bytes, but when I checked the file captured by tcpdump,
> found that netperf sent many frames which are large than 64 bytes(i.e.4000-10K+ bytes) and these frames
> were truncated by tcpdump.
>
> so that the actual avg packet size is around 1500 bytes, but what I want is avg packet: 300-400 bytes and reach 5Gb+.
>
> does it make sense?
if you set the TCP_NODELAY (to disable nagle) option on netperf (check
netperf -t TCP_STREAM -- -h) then you should be able to control packet
size.
^ permalink raw reply
* RE: get beyond 1Gbps with pktgen on 10Gb nic?
From: Jon Zhou @ 2010-05-12 4:00 UTC (permalink / raw)
To: Ben Greear, Ben Hutchings; +Cc: netdev@vger.kernel.org
In-Reply-To: <4BE97DD7.7000704@candelatech.com>
I just used multi netperf instances to reach 900K pps/8Gb+ traffic on the Broadcom 10G nic:
command:
for i in 1 2 3 4 5 6 7 8 9 10
do
netperf -l 60 -H 192.168.0.53 -- -m 60 -s 100M -S 100M &
done
the msg size was assigned as 64 bytes, but when I checked the file captured by tcpdump,
found that netperf sent many frames which are large than 64 bytes(i.e.4000-10K+ bytes) and these frames
were truncated by tcpdump.
so that the actual avg packet size is around 1500 bytes, but what I want is avg packet: 300-400 bytes and reach 5Gb+.
does it make sense?
thanks
jon
-----Original Message-----
From: Ben Greear [mailto:greearb@candelatech.com]
Sent: Tuesday, May 11, 2010 11:55 PM
To: Ben Hutchings
Cc: Jon Zhou; netdev@vger.kernel.org
Subject: Re: get beyond 1Gbps with pktgen on 10Gb nic?
On 05/11/2010 06:35 AM, Ben Hutchings wrote:
> On Tue, 2010-05-11 at 06:13 -0700, Jon Zhou wrote:
>> hi there:
>>
>> anyone can get beyond 1Gbps with pktgen or other SW traffic generator with 10Gb nic(intel 82599 or BCM 57711)?
>> found that some one had met similar situation with broadcom 10G nic but no solution yet
>
> I don't know about those specific controllers, but you should be able to
> achieve close to 10G line rate with netperf's TCP_STREAM on any recent
> PC server. UDP throughput tends to be poorer as there is less support
> for offloading segmentation and reassembly. Performance may also be
> constrained by PCI Express bandwidth (you need a real 8-lane slot) and
> memory bandwidth (a single memory bank may not be enough).
We can easily push right at 10Gbps full-duplex on two ports (sending to self)
with a 2-port 82599 NIC, 3.3Ghz quad-core Intel core i7 6GT/s processor, etc.
In fact, recent testing with a 2-port 10G NIC and a bunch of intel 1G ports showed about
50Gbps aggregate bandwidth across the network on such a system. (We were using 9000 MTU
for the 50Gbps test, but can reach 10G send-to-self with 1500 MTU on the 10G ports by themselves.)
This is all using a slightly modified pktgen, but normal pktgen should do just fine.
Thanks,
Ben
>
> Ben.
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [Uclinux-dist-devel] [PATCH 1/9] netdev: bfin_mac: add support for IEEE 1588 PTP
From: Mike Frysinger @ 2010-05-12 3:31 UTC (permalink / raw)
To: Barry Song
Cc: Richard Cochran, netdev, Barry Song, David S. Miller,
uclinux-dist-devel
In-Reply-To: <AANLkTilpgUrQfFpmgHhUSCprbnTSC9LCGpFxSUEaGSWr@mail.gmail.com>
On Tue, May 11, 2010 at 23:20, Barry Song wrote:
> On Wed, May 12, 2010 at 5:03 AM, Mike Frysinger wrote:
>> On Tue, May 11, 2010 at 03:07, Richard Cochran wrote:
>>> On Mon, May 10, 2010 at 11:39:06AM -0400, Mike Frysinger wrote:
>>>> diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
>>>> index 587f93c..6a9519f 100644
>>>> --- a/drivers/net/bfin_mac.c
>>>> +++ b/drivers/net/bfin_mac.c
>>> ...
>>>> +#define PTP_CLK 25000000
>>>> +
>>>> +static void bfin_mac_hwtstamp_init(struct net_device *netdev)
>>>> +{
>>>> + struct bfin_mac_local *lp = netdev_priv(netdev);
>>>> + u64 append;
>>>> +
>>>> + /* Initialize hardware timer */
>>>> + append = PTP_CLK * (1ULL << 32);
>>>> + do_div(append, get_sclk());
>>>> + bfin_write_EMAC_PTP_ADDEND((u32)append);
>>>
>>> It appears that one can tune this PTP clock.
>>>
>>> I recently posted a suggestion for a PTP clock class driver. Would you
>>> care to take a look at that and say whether that API would also work
>>> for the blackfin?
>>
>> i'm guessing you mean:
>> http://thread.gmane.org/gmane.linux.network/159179
>> http://thread.gmane.org/gmane.linux.network/159180
>> http://thread.gmane.org/gmane.linux.network/159181
>> http://thread.gmane.org/gmane.linux.network/159182
>>
>> Barry: could you take a look please ?
>
> I think the API can work for blackfin. But our PTP driver is based on
> drivers/net/igb and has worked together with user-space PTPD utility.
> Here he is writing a different driver framework. It is not the moment
> for us to merge now. Maybe next kernel version after his patches have
> been popular.
i'm not going to merge them into our tree ahead of the net->mainline
merge. Richard would just like some feedback on the proposed
framework to make sure it doesnt have limitations we'd have to fix
after things get merged.
-mike
^ permalink raw reply
* [BUG] crashes with kvm/nat networking and net-next
From: Stephen Hemminger @ 2010-05-12 3:25 UTC (permalink / raw)
To: Bart De Schuymer, Patrick McHardy; +Cc: netdev
This is a regression that is showing up now in net-next, not sure what
changed recently in bridge netfilter that could be causing it?
[ 4593.956206] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
[ 4593.956219] IP: [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
[ 4593.956232] PGD 195ece067 PUD 1ba005067 PMD 0
[ 4593.956241] Oops: 0000 [#1] SMP
[ 4593.956248] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:08/ATK0110:00/hwmon/hwmon0/temp2_label
[ 4593.956253] CPU 3
[ 4593.956256] Modules linked in: netconsole configfs hid_belkin tun ntfs vfat msdos fat autofs4 binfmt_misc ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc kvm_intel kvm radeon ttm drm_kms_helper drm i2c_algo_bit snd_hda_codec_analog ipv6 snd_hda_intel snd_hda_codec snd_hwdep snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device psmouse asus_atk0110 snd serio_raw soundcore snd_page_alloc usbhid mvsas libsas scsi_transport_sas floppy sky2 e1000e [last unloaded: netconsole]
[ 4593.956375]
[ 4593.956380] Pid: 29512, comm: kvm Not tainted 2.6.34-rc7-net #195 P6T DELUXE/System Product Name
[ 4593.956384] RIP: 0010:[<ffffffffa03357a4>] [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
[ 4593.956395] RSP: 0018:ffff880001e63b78 EFLAGS: 00010246
[ 4593.956399] RAX: 0000000000000608 RBX: ffff880057181700 RCX: ffff8801b813d000
[ 4593.956402] RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff880057181700
[ 4593.956406] RBP: ffff880001e63ba8 R08: ffff8801b9d97000 R09: ffffffffa0335650
[ 4593.956410] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8801b813d000
[ 4593.956413] R13: ffffffff81ab3940 R14: ffff880057181700 R15: 0000000000000002
[ 4593.956418] FS: 00007fc40d380710(0000) GS:ffff880001e60000(0000) knlGS:0000000000000000
[ 4593.956422] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
[ 4593.956426] CR2: 0000000000000018 CR3: 00000001ba1d7000 CR4: 00000000000026e0
[ 4593.956429] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 4593.956433] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 4593.956437] Process kvm (pid: 29512, threadinfo ffff8801ba566000, task ffff8801b8003870)
[ 4593.956441] Stack:
[ 4593.956443] 0000000100000020 ffff880001e63ba0 ffff880001e63ba0 ffff880057181700
[ 4593.956451] <0> ffffffffa0335650 ffffffff81ab3940 ffff880001e63bd8 ffffffffa03350e6
[ 4593.956462] <0> ffff880001e63c40 000000000000024d ffff880057181700 0000000080000000
[ 4593.956474] Call Trace:
[ 4593.956478] <IRQ>
[ 4593.956488] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
[ 4593.956496] [<ffffffffa03350e6>] NF_HOOK_THRESH+0x56/0x60 [bridge]
[ 4593.956504] [<ffffffffa0335282>] br_nf_forward_arp+0x112/0x120 [bridge]
[ 4593.956511] [<ffffffff813f7184>] nf_iterate+0x64/0xa0
[ 4593.956519] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
[ 4593.956524] [<ffffffff813f722c>] nf_hook_slow+0x6c/0x100
[ 4593.956531] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
[ 4593.956538] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
[ 4593.956545] [<ffffffffa032f86d>] __br_forward+0x6d/0xc0 [bridge]
[ 4593.956550] [<ffffffff813c5d8e>] ? skb_clone+0x3e/0x70
[ 4593.956557] [<ffffffffa032f462>] deliver_clone+0x32/0x60 [bridge]
[ 4593.956564] [<ffffffffa032f6b6>] br_flood+0xa6/0xe0 [bridge]
[ 4593.956571] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
[ 4593.956578] [<ffffffffa032f700>] br_flood_forward+0x10/0x20 [bridge]
[ 4593.956586] [<ffffffffa0330ace>] br_handle_frame_finish+0x23e/0x260 [bridge]
[ 4593.956595] [<ffffffffa03307ea>] br_handle_frame+0x1aa/0x250 [bridge]
[ 4593.956605] [<ffffffff81070331>] ? autoremove_wake_function+0x11/0x40
[ 4593.956614] [<ffffffff813cf537>] __netif_receive_skb+0x187/0x5d0
[ 4593.956622] [<ffffffff813cfa81>] process_backlog+0x101/0x210
[ 4593.956630] [<ffffffff813d092d>] net_rx_action+0x10d/0x260
[ 4593.956639] [<ffffffff81058100>] __do_softirq+0xb0/0x230
[ 4593.956648] [<ffffffff81009e5c>] call_softirq+0x1c/0x30
[ 4593.956653] <EOI>
[ 4593.956662] [<ffffffff8100bad5>] ? do_softirq+0x65/0xa0
[ 4593.956667] [<ffffffff813d3e48>] netif_rx_ni+0x28/0x30
[ 4593.956673] [<ffffffffa03e2196>] tun_chr_aio_write+0x276/0x540 [tun]
[ 4593.956679] [<ffffffffa03e1f20>] ? tun_chr_aio_write+0x0/0x540 [tun]
[ 4593.956686] [<ffffffff8110cd0b>] do_sync_readv_writev+0xcb/0x110
[ 4593.956692] [<ffffffff8120d593>] ? selinux_file_permission+0xf3/0x150
[ 4593.956699] [<ffffffff81203081>] ? security_file_permission+0x11/0x20
[ 4593.956704] [<ffffffff8110dd9a>] do_readv_writev+0xca/0x1f0
[ 4593.956710] [<ffffffff8111c888>] ? vfs_ioctl+0x38/0xd0
[ 4593.956714] [<ffffffff8111ceda>] ? do_vfs_ioctl+0x8a/0x610
[ 4593.956719] [<ffffffff8110defe>] vfs_writev+0x3e/0x60
[ 4593.956723] [<ffffffff8110e02c>] sys_writev+0x4c/0xb0
[ 4593.956730] [<ffffffff81008f42>] system_call_fastpath+0x16/0x1b
[ 4593.956733] Code: d8 00 00 00 66 81 7c 01 10 08 06 0f 85 fc fe ff ff 44 8b 15 ff 6e 00 00 45 85 d2 0f 84 ec fe ff ff 66 0f 1f 44 00 00 4c 8b 63 28 <8b> 42 18 e9 e5 fe ff ff 0f 1f 40 00 48 89 df e8 68 a1 ff ff e9
[ 4593.956838] RIP [<ffffffffa03357a4>] br_nf_forward_finish+0x154/0x170 [bridge]
[ 4593.956848] RSP <ffff880001e63b78>
[ 4593.956851] CR2: 0000000000000018
[ 4593.956855] ---[ end trace 5703d55ac3604d1c ]---
[ 4593.956859] Kernel panic - not syncing: Fatal exception in interrupt
[ 4593.956864] Pid: 29512, comm: kvm Tainted: G D 2.6.34-rc7-net #195
[ 4593.956867] Call Trace:
[ 4593.956869] <IRQ> [<ffffffff81484ff2>] panic+0x78/0xf1
[ 4593.956880] [<ffffffff81489449>] oops_end+0xa9/0xb0
[ 4593.956885] [<ffffffff81033963>] no_context+0xf3/0x260
[ 4593.956891] [<ffffffff81256664>] ? do_raw_spin_lock+0x54/0x150
[ 4593.956896] [<ffffffff81033be5>] __bad_area_nosemaphore+0x115/0x1d0
[ 4593.956901] [<ffffffff81033cae>] bad_area_nosemaphore+0xe/0x10
[ 4593.956907] [<ffffffff8148bb3f>] do_page_fault+0x28f/0x330
[ 4593.956913] [<ffffffff814887b5>] page_fault+0x25/0x30
[ 4593.956921] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
[ 4593.956929] [<ffffffffa03357a4>] ? br_nf_forward_finish+0x154/0x170 [bridge]
[ 4593.956938] [<ffffffffa0335650>] ? br_nf_forward_finish+0x0/0x170 [bridge]
[ 4593.956951] [<ffffffffa03350e6>] NF_HOOK_THRESH+0x56/0x60 [bridge]
[ 4593.956963] [<ffffffffa0335282>] br_nf_forward_arp+0x112/0x120 [bridge]
[ 4593.956972] [<ffffffff813f7184>] nf_iterate+0x64/0xa0
[ 4593.956983] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
[ 4593.956990] [<ffffffff813f722c>] nf_hook_slow+0x6c/0x100
[ 4593.956997] [<ffffffffa032f920>] ? br_forward_finish+0x0/0x60 [bridge]
[ 4593.957005] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
[ 4593.957012] [<ffffffffa032f86d>] __br_forward+0x6d/0xc0 [bridge]
[ 4593.957017] [<ffffffff813c5d8e>] ? skb_clone+0x3e/0x70
[ 4593.957023] [<ffffffffa032f462>] deliver_clone+0x32/0x60 [bridge]
[ 4593.957030] [<ffffffffa032f6b6>] br_flood+0xa6/0xe0 [bridge]
[ 4593.957037] [<ffffffffa032f800>] ? __br_forward+0x0/0xc0 [bridge]
[ 4593.957044] [<ffffffffa032f700>] br_flood_forward+0x10/0x20 [bridge]
[ 4593.957052] [<ffffffffa0330ace>] br_handle_frame_finish+0x23e/0x260 [bridge]
[ 4593.957059] [<ffffffffa03307ea>] br_handle_frame+0x1aa/0x250 [bridge]
[ 4593.957065] [<ffffffff81070331>] ? autoremove_wake_function+0x11/0x40
[ 4593.957070] [<ffffffff813cf537>] __netif_receive_skb+0x187/0x5d0
[ 4593.957076] [<ffffffff813cfa81>] process_backlog+0x101/0x210
[ 4593.957081] [<ffffffff813d092d>] net_rx_action+0x10d/0x260
[ 4593.957086] [<ffffffff81058100>] __do_softirq+0xb0/0x230
[ 4593.957091] [<ffffffff81009e5c>] call_softirq+0x1c/0x30
[ 4593.957094] <EOI> [<ffffffff8100bad5>] ? do_softirq+0x65/0xa0
[ 4593.957102] [<ffffffff813d3e48>] netif_rx_ni+0x28/0x30
[ 4593.957108] [<ffffffffa03e2196>] tun_chr_aio_write+0x276/0x540 [tun]
[ 4593.957113] [<ffffffffa03e1f20>] ? tun_chr_aio_write+0x0/0x540 [tun]
[ 4593.957119] [<ffffffff8110cd0b>] do_sync_readv_writev+0xcb/0x110
[ 4593.957125] [<ffffffff8120d593>] ? selinux_file_permission+0xf3/0x150
[ 4593.957130] [<ffffffff81203081>] ? security_file_permission+0x11/0x20
[ 4593.957135] [<ffffffff8110dd9a>] do_readv_writev+0xca/0x1f0
[ 4593.957139] [<ffffffff8111c888>] ? vfs_ioctl+0x38/0xd0
[ 4593.957144] [<ffffffff8111ceda>] ? do_vfs_ioctl+0x8a/0x610
[ 4593.957148] [<ffffffff8110defe>] vfs_writev+0x3e/0x60
[ 4593.957153] [<ffffffff8110e02c>] sys_writev+0x4c/0xb0
[ 4593.957158] [<ffffffff81008f42>] system_call_fastpath+0x16/0x1b
^ permalink raw reply
* Re: [Uclinux-dist-devel] [PATCH 1/9] netdev: bfin_mac: add support for IEEE 1588 PTP
From: Barry Song @ 2010-05-12 3:20 UTC (permalink / raw)
To: Mike Frysinger
Cc: Richard Cochran, netdev, Barry Song, David S. Miller,
uclinux-dist-devel
In-Reply-To: <AANLkTikcdpIlZAE-AwahNie8KOys7jIhiNb9kiT_B7Av@mail.gmail.com>
On Wed, May 12, 2010 at 5:03 AM, Mike Frysinger <vapier.adi@gmail.com> wrote:
> On Tue, May 11, 2010 at 03:07, Richard Cochran wrote:
>> On Mon, May 10, 2010 at 11:39:06AM -0400, Mike Frysinger wrote:
>>> diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
>>> index 587f93c..6a9519f 100644
>>> --- a/drivers/net/bfin_mac.c
>>> +++ b/drivers/net/bfin_mac.c
>> ...
>>> +#define PTP_CLK 25000000
>>> +
>>> +static void bfin_mac_hwtstamp_init(struct net_device *netdev)
>>> +{
>>> + struct bfin_mac_local *lp = netdev_priv(netdev);
>>> + u64 append;
>>> +
>>> + /* Initialize hardware timer */
>>> + append = PTP_CLK * (1ULL << 32);
>>> + do_div(append, get_sclk());
>>> + bfin_write_EMAC_PTP_ADDEND((u32)append);
>>
>> It appears that one can tune this PTP clock.
>>
>> I recently posted a suggestion for a PTP clock class driver. Would you
>> care to take a look at that and say whether that API would also work
>> for the blackfin?
>
> i'm guessing you mean:
> http://thread.gmane.org/gmane.linux.network/159179
> http://thread.gmane.org/gmane.linux.network/159180
> http://thread.gmane.org/gmane.linux.network/159181
> http://thread.gmane.org/gmane.linux.network/159182
>
> Barry: could you take a look please ?
I think the API can work for blackfin. But our PTP driver is based on
drivers/net/igb and has worked together with user-space PTPD utility.
Here he is writing a different driver framework. It is not the moment
for us to merge now. Maybe next kernel version after his patches have
been popular.
> -mike
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: TCP-MD5 checksum failure on x86_64 SMP
From: Eric Dumazet @ 2010-05-12 3:20 UTC (permalink / raw)
To: Bijay Singh
Cc: Stephen Hemminger, David Miller, <bhaskie@gmail.com>,
<bhutchings@solarflare.com>, netdev, Ilpo Järvinen
In-Reply-To: <1273611036.2512.18.camel@edumazet-laptop>
Le mardi 11 mai 2010 à 22:50 +0200, Eric Dumazet a écrit :
> Le mardi 11 mai 2010 à 04:08 +0000, Bijay Singh a écrit :
> > Hi Eric,
> >
> > I guess that makes me the enviable one. So I am keen to test out this feature completely, as long as I know what to do as a next step, directions, patches.
> >
> > Thanks
>
>
> I believe third problem comes from commit 4957faad
> (TCPCT part 1g: Responder Cookie => Initiator), from William Allen
> Simpson.
And a fourth problem might be that tcp_md5_hash_skb_data() is not
frag_list aware ?
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 8ce2974..56ee0f2 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2985,6 +2985,7 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
const unsigned head_data_len = skb_headlen(skb) > header_len ?
skb_headlen(skb) - header_len : 0;
const struct skb_shared_info *shi = skb_shinfo(skb);
+ struct sk_buff *frag_iter;
sg_init_table(&sg, 1);
@@ -2999,6 +3000,10 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
return 1;
}
+ skb_walk_frags(skb, frag_iter)
+ if (tcp_md5_hash_skb_data(hp, frag_iter, 0))
+ return 1;
+
return 0;
}
^ permalink raw reply related
* linux-next: manual merge of the net tree with Linus' tree
From: Stephen Rothwell @ 2010-05-12 2:26 UTC (permalink / raw)
To: David Miller, netdev
Cc: linux-next, linux-kernel, Andreas Meissner, Patrick McHardy
Hi all,
Today's linux-next merge of the net tree got a conflict in
net/ipv4/ipmr.c between commit bbd725435ddb1cac732f7a8c23c21ff67f24c60f
("IPv4: unresolved multicast route cleanup") from Linus' tree and commits
e258beb22f4d3ea3dc88586ffc9c990d0eb03380 ("ipv4: ipmr: move unres_queue
and timer to per-namespace data") and
0c12295a741d3186987f96f518cfbdaf01abb087 ("ipv4: ipmr: move mroute data
into seperate structure") from the net tree.
I fixed it up (see below) and can carry the fix for a while.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --cc net/ipv4/ipmr.c
index ec19a89,f3f1c6b..0000000
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@@ -750,12 -995,10 +995,11 @@@ ipmr_cache_unresolved(struct mr_table *
return err;
}
- atomic_inc(&net->ipv4.cache_resolve_queue_len);
- c->next = mfc_unres_queue;
- mfc_unres_queue = c;
+ atomic_inc(&mrt->cache_resolve_queue_len);
+ list_add(&c->list, &mrt->mfc_unres_queue);
- mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
+ if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1)
- mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);
++ mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
}
/*
^ permalink raw reply
* linux-next: manual merge of the net tree with the wireless-current tree
From: Stephen Rothwell @ 2010-05-12 2:15 UTC (permalink / raw)
To: David Miller, netdev
Cc: linux-next, linux-kernel, Johannes Berg, Reinette Chatre,
John W. Linville
Hi all,
Today's linux-next merge of the net tree got a conflict in
drivers/net/wireless/iwlwifi/iwl-dev.h between commit
562db532760827f6ce30801a08e6b568848bc9f2 ("iwlagn: wait for asynchronous
firmware loading") from the wireless-current tree and commit
ee525d13f501baeaa33209620398adaf0a820629 ("iwlwifi: move 3945 specific
data into union") from the net tree.
Just context changes. I fixed it up (see below) and can carry the fix for
a while.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --cc drivers/net/wireless/iwlwifi/iwl-dev.h
index 4d4c651,58c69a5..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@@ -1304,12 -1274,6 +1274,8 @@@ struct iwl_priv
struct delayed_work alive_start;
struct delayed_work scan_check;
+ struct completion firmware_loading_complete;
+
- /*For 3945 only*/
- struct delayed_work thermal_periodic;
- struct delayed_work rfkill_poll;
-
/* TX Power */
s8 tx_power_user_lmt;
s8 tx_power_device_lmt;
^ permalink raw reply
* [PATCH] ARCNET: Limit com20020 PCI ID matches for SOHARD cards
From: Andreas Bombe @ 2010-05-12 0:49 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kernel, stable
The SH SOHARD ARCNET cards are implemented using generic PLX Technology
PCI<->IOBus bridges. Subvendor and subdevice IDs were not specified,
causing the driver to attach to any such bridge and likely crash the
system by attempting to initialize an unrelated device.
Fix by specifying subvendor and subdevice according to the values found
in the PCI-ID Repository at http://pci-ids.ucw.cz/ .
Cc: stable@kernel.org
Signed-off-by: Andreas Bombe <aeb@debian.org>
---
Compile tested only. This bug caused a new machine to be unbootable with
Debian install media due to rebooting right after some arc%d: SOHARD log
messages appeared. Current SUSE and Fedora boot, presumably because
there are no compiled ARCNET drivers.
I couldn't find any information on the other PLX device ID 10b5:2200.
Also, the PCI ID repository says 14ba:6000 should really be 14ba:0600.
I have no way to verify that.
drivers/net/arcnet/com20020-pci.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 2c712af..48a1dbf 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -164,8 +164,8 @@ static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = {
{ 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x10B5, 0x9030, 0x10B5, 0x2978, 0, 0, ARC_CAN_10MBIT },
+ { 0x10B5, 0x9050, 0x10B5, 0x2273, 0, 0, ARC_CAN_10MBIT },
{ 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{0,}
--
1.7.1
^ permalink raw reply related
* [PATCH net-next 16/16] tipc: Reduce footprint by un-inlining tipc_msg_* routines
From: Paul Gortmaker @ 2010-05-12 0:30 UTC (permalink / raw)
To: netdev; +Cc: allan.stephens
In-Reply-To: <f90800f460df4ef216412e83e148771d2b6a7183.1273621271.git.paul.gortmaker@windriver.com>
From: Allan Stephens <allan.stephens@windriver.com>
Convert tipc_msg_* inline routines that are more than one line into
standard functions, thereby eliminating some repeated code.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
net/tipc/msg.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
net/tipc/msg.h | 99 +++----------------------------------------------------
2 files changed, 100 insertions(+), 93 deletions(-)
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 73dcd00..3810638 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -40,6 +40,100 @@
#include "msg.h"
#include "bearer.h"
+u32 tipc_msg_tot_importance(struct tipc_msg *m)
+{
+ if (likely(msg_isdata(m))) {
+ if (likely(msg_orignode(m) == tipc_own_addr))
+ return msg_importance(m);
+ return msg_importance(m) + 4;
+ }
+ if ((msg_user(m) == MSG_FRAGMENTER) &&
+ (msg_type(m) == FIRST_FRAGMENT))
+ return msg_importance(msg_get_wrapped(m));
+ return msg_importance(m);
+}
+
+
+void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
+ u32 hsize, u32 destnode)
+{
+ memset(m, 0, hsize);
+ msg_set_version(m);
+ msg_set_user(m, user);
+ msg_set_hdr_sz(m, hsize);
+ msg_set_size(m, hsize);
+ msg_set_prevnode(m, tipc_own_addr);
+ msg_set_type(m, type);
+ if (!msg_short(m)) {
+ msg_set_orignode(m, tipc_own_addr);
+ msg_set_destnode(m, destnode);
+ }
+}
+
+/**
+ * tipc_msg_calc_data_size - determine total data size for message
+ */
+
+int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
+{
+ int dsz = 0;
+ int i;
+
+ for (i = 0; i < num_sect; i++)
+ dsz += msg_sect[i].iov_len;
+ return dsz;
+}
+
+/**
+ * tipc_msg_build - create message using specified header and data
+ *
+ * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
+ *
+ * Returns message data size or errno
+ */
+
+int tipc_msg_build(struct tipc_msg *hdr,
+ struct iovec const *msg_sect, u32 num_sect,
+ int max_size, int usrmem, struct sk_buff** buf)
+{
+ int dsz, sz, hsz, pos, res, cnt;
+
+ dsz = tipc_msg_calc_data_size(msg_sect, num_sect);
+ if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
+ *buf = NULL;
+ return -EINVAL;
+ }
+
+ pos = hsz = msg_hdr_sz(hdr);
+ sz = hsz + dsz;
+ msg_set_size(hdr, sz);
+ if (unlikely(sz > max_size)) {
+ *buf = NULL;
+ return dsz;
+ }
+
+ *buf = buf_acquire(sz);
+ if (!(*buf))
+ return -ENOMEM;
+ skb_copy_to_linear_data(*buf, hdr, hsz);
+ for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
+ if (likely(usrmem))
+ res = !copy_from_user((*buf)->data + pos,
+ msg_sect[cnt].iov_base,
+ msg_sect[cnt].iov_len);
+ else
+ skb_copy_to_linear_data_offset(*buf, pos,
+ msg_sect[cnt].iov_base,
+ msg_sect[cnt].iov_len);
+ pos += msg_sect[cnt].iov_len;
+ }
+ if (likely(res))
+ return dsz;
+
+ buf_discard(*buf);
+ *buf = NULL;
+ return -EFAULT;
+}
#ifdef CONFIG_TIPC_DEBUG
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index fbcd46f..995d2da 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -708,100 +708,13 @@ static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)
#define DSC_REQ_MSG 0
#define DSC_RESP_MSG 1
-static inline u32 tipc_msg_tot_importance(struct tipc_msg *m)
-{
- if (likely(msg_isdata(m))) {
- if (likely(msg_orignode(m) == tipc_own_addr))
- return msg_importance(m);
- return msg_importance(m) + 4;
- }
- if ((msg_user(m) == MSG_FRAGMENTER) &&
- (msg_type(m) == FIRST_FRAGMENT))
- return msg_importance(msg_get_wrapped(m));
- return msg_importance(m);
-}
-
-
-static inline void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
- u32 hsize, u32 destnode)
-{
- memset(m, 0, hsize);
- msg_set_version(m);
- msg_set_user(m, user);
- msg_set_hdr_sz(m, hsize);
- msg_set_size(m, hsize);
- msg_set_prevnode(m, tipc_own_addr);
- msg_set_type(m, type);
- if (!msg_short(m)) {
- msg_set_orignode(m, tipc_own_addr);
- msg_set_destnode(m, destnode);
- }
-}
-
-/**
- * tipc_msg_calc_data_size - determine total data size for message
- */
-
-static inline int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
-{
- int dsz = 0;
- int i;
-
- for (i = 0; i < num_sect; i++)
- dsz += msg_sect[i].iov_len;
- return dsz;
-}
-
-/**
- * tipc_msg_build - create message using specified header and data
- *
- * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
- *
- * Returns message data size or errno
- */
-
-static inline int tipc_msg_build(struct tipc_msg *hdr,
+u32 tipc_msg_tot_importance(struct tipc_msg *m);
+void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
+ u32 hsize, u32 destnode);
+int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect);
+int tipc_msg_build(struct tipc_msg *hdr,
struct iovec const *msg_sect, u32 num_sect,
- int max_size, int usrmem, struct sk_buff** buf)
-{
- int dsz, sz, hsz, pos, res, cnt;
-
- dsz = tipc_msg_calc_data_size(msg_sect, num_sect);
- if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
- *buf = NULL;
- return -EINVAL;
- }
-
- pos = hsz = msg_hdr_sz(hdr);
- sz = hsz + dsz;
- msg_set_size(hdr, sz);
- if (unlikely(sz > max_size)) {
- *buf = NULL;
- return dsz;
- }
-
- *buf = buf_acquire(sz);
- if (!(*buf))
- return -ENOMEM;
- skb_copy_to_linear_data(*buf, hdr, hsz);
- for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
- if (likely(usrmem))
- res = !copy_from_user((*buf)->data + pos,
- msg_sect[cnt].iov_base,
- msg_sect[cnt].iov_len);
- else
- skb_copy_to_linear_data_offset(*buf, pos,
- msg_sect[cnt].iov_base,
- msg_sect[cnt].iov_len);
- pos += msg_sect[cnt].iov_len;
- }
- if (likely(res))
- return dsz;
-
- buf_discard(*buf);
- *buf = NULL;
- return -EFAULT;
-}
+ int max_size, int usrmem, struct sk_buff** buf);
static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
{
--
1.7.1.rc2
^ permalink raw reply related
* [PATCH net-next 15/16] tipc: Reduce footprint by un-inlining buf_acquire routine
From: Paul Gortmaker @ 2010-05-12 0:30 UTC (permalink / raw)
To: netdev; +Cc: allan.stephens
In-Reply-To: <f90800f460df4ef216412e83e148771d2b6a7183.1273621271.git.paul.gortmaker@windriver.com>
From: Allan Stephens <allan.stephens@windriver.com>
Convert buf_acquire inline routine that is more than one line into
a standard function, thereby eliminating some repeated code.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
net/tipc/core.c | 24 ++++++++++++++++++++++++
net/tipc/core.h | 24 +-----------------------
2 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/net/tipc/core.c b/net/tipc/core.c
index b47d184..6964681 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -102,6 +102,30 @@ int tipc_get_mode(void)
}
/**
+ * buf_acquire - creates a TIPC message buffer
+ * @size: message size (including TIPC header)
+ *
+ * Returns a new buffer with data pointers set to the specified size.
+ *
+ * NOTE: Headroom is reserved to allow prepending of a data link header.
+ * There may also be unrequested tailroom present at the buffer's end.
+ */
+
+struct sk_buff *buf_acquire(u32 size)
+{
+ struct sk_buff *skb;
+ unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
+
+ skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+ if (skb) {
+ skb_reserve(skb, BUF_HEADROOM);
+ skb_put(skb, size);
+ skb->next = NULL;
+ }
+ return skb;
+}
+
+/**
* tipc_core_stop_net - shut down TIPC networking sub-systems
*/
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 1e149f5..1887990 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -328,29 +328,7 @@ static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
return (struct tipc_msg *)skb->data;
}
-/**
- * buf_acquire - creates a TIPC message buffer
- * @size: message size (including TIPC header)
- *
- * Returns a new buffer with data pointers set to the specified size.
- *
- * NOTE: Headroom is reserved to allow prepending of a data link header.
- * There may also be unrequested tailroom present at the buffer's end.
- */
-
-static inline struct sk_buff *buf_acquire(u32 size)
-{
- struct sk_buff *skb;
- unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
-
- skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
- if (skb) {
- skb_reserve(skb, BUF_HEADROOM);
- skb_put(skb, size);
- skb->next = NULL;
- }
- return skb;
-}
+extern struct sk_buff *buf_acquire(u32 size);
/**
* buf_discard - frees a TIPC message buffer
--
1.7.1.rc2
^ permalink raw reply related
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