lkml.org 
[lkml]   [2010]   [Jun]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] gainfar.c : skb_over_panic (kernel-2.6.32.15)
David Miller wrote:
> From: Eran Liberty <liberty@extricom.com>
> Date: Mon, 28 Jun 2010 10:57:08 +0300
>
>
>> This code has proved to be insufficient and produce
>> skb_over_panic. The proposed patch fix this.
>>
>
> Then you have to post a patch relative to the current code, rather than
> against the code as it was several releases ago.
>
> Your patch didn't apply, so I can't use it.
>
>
Upon cleaning up my patch for the latest kernel I realized I do not
like: the previous partial fix, the fix in ucc_geth.c, the fix in the
current latest kernel, and my own previously proposed patch. They all
tried to undo the alignment skb_reserve done in gfar_new_skb() before
queuing the skb into the rw_recycle, because upon getting a new one in
gfar_new_skb() if the skb is from the rx_recycle pool rather then newly
allocated it is reserved twice.

Instead of trying to undo the skb_reserve this proposed patch will make
sure the alignment skb_reserve is done once, upon allocating the skb and
not when taken out of the rx_recycle pool. Eliminating the need to undo
anything before queue skb back to the pool.

This patch will apply cleanly against the 2.6.32.15. Another patch will
be submitted separately for the current Linus tree.

-- Liberty

Signed-off-by: Eran Liberty <liberty@extricom.com>

---
drivers/net/gianfar.c | 52 +++++++++++++++++++++++++-------------------------
1 file changed, 27 insertions(+), 25 deletions(-)

--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1568,6 +1568,15 @@
schedule_work(&priv->reset_task);
}

+static void gfar_align_skb(struct sk_buff *skb)
+{
+ /* We need the data buffer to be aligned properly. We will reserve
+ * as many bytes as needed to align the data properly
+ */
+ skb_reserve(skb, RXBUF_ALIGNMENT -
+ (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1)));
+}
+
/* Interrupt Handler for Transmit complete */
static int gfar_clean_tx_ring(struct net_device *dev)
{
@@ -1620,9 +1629,10 @@
*/
if (skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size &&
skb_recycle_check(skb, priv->rx_buffer_size +
- RXBUF_ALIGNMENT))
+ RXBUF_ALIGNMENT)) {
+ gfar_align_skb(skb);
__skb_queue_head(&priv->rx_recycle, skb);
- else
+ } else
dev_kfree_skb_any(skb);

priv->tx_skbuff[skb_dirtytx] = NULL;
@@ -1696,28 +1706,29 @@
bdp->lstatus = lstatus;
}

+static struct sk_buff * gfar_alloc_skb(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct sk_buff *skb = NULL;
+
+ skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+ if (!skb)
+ return NULL;
+
+ gfar_align_skb(skb);
+
+ return skb;
+}

struct sk_buff * gfar_new_skb(struct net_device *dev)
{
- unsigned int alignamount;
struct gfar_private *priv = netdev_priv(dev);
struct sk_buff *skb = NULL;

skb = __skb_dequeue(&priv->rx_recycle);
- if (!skb)
- skb = netdev_alloc_skb(dev,
- priv->rx_buffer_size + RXBUF_ALIGNMENT);

if (!skb)
- return NULL;
-
- alignamount = RXBUF_ALIGNMENT -
- (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1));
-
- /* We need the data buffer to be aligned properly. We will reserve
- * as many bytes as needed to align the data properly
- */
- skb_reserve(skb, alignamount);
+ skb = gfar_alloc_skb(dev);

return skb;
}
@@ -1853,17 +1864,8 @@

if (unlikely(!newskb))
newskb = skb;
- else if (skb) {
- /*
- * We need to reset ->data to what it
- * was before gfar_new_skb() re-aligned
- * it to an RXBUF_ALIGNMENT boundary
- * before we put the skb back on the
- * recycle list.
- */
- skb->data = skb->head + NET_SKB_PAD;
+ else if (skb)
__skb_queue_head(&priv->rx_recycle, skb);
- }
} else {
/* Increment the number of packets */
dev->stats.rx_packets++;
\
 
 \ /
  Last update: 2010-06-29 17:43    [W:0.041 / U:0.216 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site