This is a note to let you know that I've just added the patch titled
rapidio/rionet: fix multicast packet transmit logic
to the 3.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
rapidio-rionet-fix-multicast-packet-transmit-logic.patch
and it can be found in the queue-3.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.
>From 7c4a6106d6451fc03c491e61df37c044505d843a Mon Sep 17 00:00:00 2001
From: Alexandre Bounine <[email protected]>
Date: Thu, 4 Oct 2012 17:15:48 -0700
Subject: rapidio/rionet: fix multicast packet transmit logic
From: Alexandre Bounine <[email protected]>
commit 7c4a6106d6451fc03c491e61df37c044505d843a upstream.
Fix multicast packet transmit logic to account for repetitive transmission
of single skb:
- correct check for available buffers (this bug may produce NULL pointer
crash dump in case of heavy traffic);
- update skb user count (incorrect user counter causes a warning dump from
net_tx_action routine during multicast transfers in systems with three or
more rionet participants).
Signed-off-by: Alexandre Bounine <[email protected]>
Cc: Matt Porter <[email protected]>
Cc: David S. Miller <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/rionet.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -79,6 +79,7 @@ static int rionet_capable = 1;
* on system trade-offs.
*/
static struct rio_dev **rionet_active;
+static int nact; /* total number of active rionet peers */
#define is_rionet_capable(src_ops, dst_ops) \
((src_ops & RIO_SRC_OPS_DATA_MSG) && \
@@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_b
struct ethhdr *eth = (struct ethhdr *)skb->data;
u16 destid;
unsigned long flags;
+ int add_num = 1;
local_irq_save(flags);
if (!spin_trylock(&rnet->tx_lock)) {
@@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_b
return NETDEV_TX_LOCKED;
}
- if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+ if (is_multicast_ether_addr(eth->h_dest))
+ add_num = nact;
+
+ if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
netif_stop_queue(ndev);
spin_unlock_irqrestore(&rnet->tx_lock, flags);
printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
@@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_b
}
if (is_multicast_ether_addr(eth->h_dest)) {
+ int count = 0;
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
i++)
- if (rionet_active[i])
+ if (rionet_active[i]) {
rionet_queue_tx_msg(skb, ndev,
rionet_active[i]);
+ if (count)
+ atomic_inc(&skb->users);
+ count++;
+ }
} else if (RIONET_MAC_MATCH(eth->h_dest)) {
destid = RIONET_GET_DESTID(eth->h_dest);
if (rionet_active[destid])
@@ -220,14 +230,17 @@ static void rionet_dbell_event(struct ri
if (info == RIONET_DOORBELL_JOIN) {
if (!rionet_active[sid]) {
list_for_each_entry(peer, &rionet_peers, node) {
- if (peer->rdev->destid == sid)
+ if (peer->rdev->destid == sid) {
rionet_active[sid] = peer->rdev;
+ nact++;
+ }
}
rio_mport_send_doorbell(mport, sid,
RIONET_DOORBELL_JOIN);
}
} else if (info == RIONET_DOORBELL_LEAVE) {
rionet_active[sid] = NULL;
+ nact--;
} else {
if (netif_msg_intr(rnet))
printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev *
rc = rionet_setup_netdev(rdev->net->hport, ndev);
rionet_check = 1;
+ nact = 0;
}
/*
Patches currently in stable-queue which might be from [email protected]
are
queue-3.4/rapidio-rionet-fix-multicast-packet-transmit-logic.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html