netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Hemminger <shemminger@osdl.org>
To: Beschorner Daniel <Daniel.Beschorner@facton.com>
Cc: "'Krzysztof Oledzki'" <olel@ans.pl>,
	netdev@vger.kernel.org, "'david@mantara.com'" <david@mantara.com>
Subject: Re: skge driver oops
Date: Fri, 26 May 2006 08:17:37 -0700	[thread overview]
Message-ID: <20060526081737.5c5b422f@localhost.localdomain> (raw)
In-Reply-To: <BB1F4EFD574E9F409035BDA71C9612500241A2@exchange.i-bn>

Please give this a try, it rearranges the transmit buffer management,
and may avoid issues with partial completions causing SKB reuse.

--- skge.orig/drivers/net/skge.c
+++ skge/drivers/net/skge.c
@@ -2372,7 +2372,8 @@ static int skge_xmit_frame(struct sk_buf
 					   frag->size, PCI_DMA_TODEVICE);
 
 			e = e->next;
-			e->skb = NULL;
+			e->skb = skb;
+
 			tf = e->desc;
 			tf->dma_lo = map;
 			tf->dma_hi = (u64) map >> 32;
@@ -2408,36 +2409,42 @@ static int skge_xmit_frame(struct sk_buf
 	return NETDEV_TX_OK;
 }
 
-static void skge_tx_complete(struct skge_port *skge, struct skge_element *last)
+
+static void skge_tx_done(struct skge_port *skge, struct skge_element *e)
 {
 	struct pci_dev *pdev = skge->hw->pdev;
-	struct skge_element *e;
+	const struct skge_tx_desc *td = e->desc;
 
-	for (e = skge->tx_ring.to_clean; e != last; e = e->next) {
-		struct sk_buff *skb = e->skb;
-		int i;
-
-		e->skb = NULL;
+	/* skb header vs. fragment */
+	if (td->control & BMU_STF)
 		pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr),
-				 skb_headlen(skb), PCI_DMA_TODEVICE);
+				 pci_unmap_len(e, maplen),
+				 PCI_DMA_TODEVICE);
+	else
+		pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
+			       pci_unmap_len(e, maplen),
+			       PCI_DMA_TODEVICE);
 
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			e = e->next;
-			pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
-				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-		}
+	if (td->control & BMU_EOF) {
+		if (unlikely(netif_msg_tx_done(skge)))
+			printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
+			       skge->netdev->name, e - skge->tx_ring.start);
 
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(e->skb);
 	}
-	skge->tx_ring.to_clean = e;
+	e->skb = NULL;
 }
 
+/* Free all buffers in transmit ring */
 static void skge_tx_clean(struct skge_port *skge)
 {
+	struct skge_element *e;
 
 	spin_lock_bh(&skge->tx_lock);
-	skge_tx_complete(skge, skge->tx_ring.to_use);
+	for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next)
+		skge_tx_done(skge, e);
+
+	skge->tx_ring.to_clean = e;
 	netif_wake_queue(skge->netdev);
 	spin_unlock_bh(&skge->tx_lock);
 }
@@ -2665,30 +2672,24 @@ resubmit:
 	return NULL;
 }
 
-static void skge_tx_done(struct skge_port *skge)
+/* Free all buffers in Tx ring which are no longer owned by device */
+static void skge_tx_complete(struct skge_port *skge)
 {
 	struct skge_ring *ring = &skge->tx_ring;
-	struct skge_element *e, *last;
+	struct skge_element *e;
 
 	spin_lock(&skge->tx_lock);
-	last = ring->to_clean;
+	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
 	for (e = ring->to_clean; e != ring->to_use; e = e->next) {
 		struct skge_tx_desc *td = e->desc;
 
 		if (td->control & BMU_OWN)
 			break;
 
-		if (td->control & BMU_EOF) {
-			last = e->next;
-			if (unlikely(netif_msg_tx_done(skge)))
-				printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
-				       skge->netdev->name, e - ring->start);
-		}
+		skge_tx_done(skge, e);
 	}
-
-	skge_tx_complete(skge, last);
-
-	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+	skge->tx_ring.to_clean = e;
 
 	if (skge_avail(&skge->tx_ring) > TX_LOW_WATER)
 		netif_wake_queue(skge->netdev);
@@ -2705,7 +2706,7 @@ static int skge_poll(struct net_device *
 	int to_do = min(dev->quota, *budget);
 	int work_done = 0;
 
-	skge_tx_done(skge);
+	skge_tx_complete(skge);
 
 	for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
 		struct skge_rx_desc *rd = e->desc;

  reply	other threads:[~2006-05-26 15:18 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-22 18:38 skge driver oops Beschorner Daniel
2006-05-26 15:17 ` Stephen Hemminger [this message]
2006-07-22 22:28   ` Krzysztof Oledzki
2006-07-30 13:33     ` Krzysztof Oledzki
  -- strict thread matches above, loose matches on Subject: below --
2006-05-31 11:05 Beschorner Daniel
2006-05-29 17:54 Beschorner Daniel
2006-05-30 18:25 ` Stephen Hemminger
2006-05-17  9:32 Beschorner Daniel
2006-05-17 10:17 ` Krzysztof Oledzki
     [not found] <20060511150952.4c2cde2e@localhost.localdomain>
2006-05-12  1:36 ` David Arnold
2006-05-12 15:53   ` Stephen Hemminger
2006-05-15 21:55     ` David Arnold
2006-05-16 21:42     ` David Arnold
2006-05-16 21:17   ` Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060526081737.5c5b422f@localhost.localdomain \
    --to=shemminger@osdl.org \
    --cc=Daniel.Beschorner@facton.com \
    --cc=david@mantara.com \
    --cc=netdev@vger.kernel.org \
    --cc=olel@ans.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).