[aadk-commits] dbailey: uClinux/trunk r77 - /uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/...

aadk-commits at lists.digium.com aadk-commits at lists.digium.com
Wed Dec 20 14:30:52 MST 2006


Author: dbailey
Date: Wed Dec 20 15:30:51 2006
New Revision: 77

URL: http://svn.digium.com/view/aadk?view=rev&rev=77
Log:
Corrected a bug with skb free in hard transmit - Now I wait for DMA to finish before freeing.

Modified:
    uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/net/bfin_mac.c

Modified: uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/net/bfin_mac.c
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/net/bfin_mac.c?view=diff&rev=77&r1=76&r2=77
==============================================================================
--- uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/net/bfin_mac.c (original)
+++ uClinux/trunk/uClinux-dist/linux-2.6.x/drivers/net/bfin_mac.c Wed Dec 20 15:30:51 2006
@@ -149,9 +149,7 @@
 
 	/* init rx_list */
 	for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
-
     tmp_desc = rx_desc + i;
-
 	tmp_desc->skb = bf537_alloc_skb(1560 + 4);
 
 		if (i == 0) {
@@ -207,6 +205,10 @@
 	tmp_desc = tx_list_head;
 		for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) {
 		if (tmp_desc != NULL) {
+			if (tmp_desc->skb) {
+				dev_kfree_skb(tmp_desc->skb);
+				tmp_desc->skb = NULL;
+			}
 #if defined(CONFIG_BFIN_MAC_USE_L1)
 			l1_data_A_sram_free((unsigned long)tmp_desc);
 #else
@@ -219,8 +221,10 @@
 	tmp_desc = rx_list_head;
 		for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) {
 		if (tmp_desc != NULL) {
-			if (tmp_desc->skb)
-	  			kfree_skb(tmp_desc->skb);
+			if (tmp_desc->skb) {
+	  			dev_kfree_skb(tmp_desc->skb);
+				tmp_desc->skb = NULL;
+			}
 #if defined(CONFIG_BFIN_MAC_USE_L1)
 			l1_data_A_sram_free((unsigned long)tmp_desc);
 #else
@@ -485,7 +489,11 @@
 	  do {
 		  tx_list_head->desc_a.config.b_DMA_EN = 0;
 		  tx_list_head->status.status_word = 0;
-		  tx_list_head = tx_list_head->next;
+		  if (tx_list_head->skb) {	/* If TX Buff had attached to skb, release it */
+			  dev_kfree_skb(tx_list_head->skb);
+			  tx_list_head->skb = NULL;
+		  }
+  		  tx_list_head = tx_list_head->next;
 	  } while (tx_list_head->status.status_word != 0);
 	  return;  // released something, just return;
 	}
@@ -495,11 +503,15 @@
 	if (current_tx_ptr->next->next == tx_list_head) {
 		while (tx_list_head->status.status_word == 0) {
 			udelay(10);
-	    if (tx_list_head->status.status_word != 0 || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
-	do {
-		tx_list_head->desc_a.config.b_DMA_EN = 0;
-		tx_list_head->status.status_word = 0;
-		tx_list_head = tx_list_head->next;
+	    	if (tx_list_head->status.status_word != 0 || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
+				do {
+					tx_list_head->desc_a.config.b_DMA_EN = 0;
+					tx_list_head->status.status_word = 0;
+					if (tx_list_head->skb) {	/* If TX Buff had attached to skb, release it */
+						dev_kfree_skb(tx_list_head->skb);
+						tx_list_head->skb = NULL;
+					} 
+					tx_list_head = tx_list_head->next;
 		    } while (tx_list_head->status.status_word != 0);
 		    break;
 	    }
@@ -520,67 +532,65 @@
 
 static int bf537mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct bf537mac_local *lp = netdev_priv(dev);
-	unsigned int data;
-  unsigned long flags;
+    struct bf537mac_local *lp = netdev_priv(dev);
+    unsigned int data;
   /* warning: printk in this function may cause error */
 
-  spin_lock_irqsave(&lp->lock, flags);
+/* Do we need some sort of protection against reentrancy since eth0 and eth1 are using this function */
+    current_tx_ptr->skb = skb;		/* attach the skb to the DMA buffer descriptor */
 
 	// Is skb->data always 16-bit aligned? Do we need to memcpy((char *)(tail->packet + 2),skb->data,len)?
-  if (((((unsigned int)(skb->data)) & 0x03) == 2) && (skb_headroom(skb) >= 6)) {
+    if (((((unsigned int)(skb->data)) & 0x03) == 2) && (skb_headroom(skb) >= 6)) {
 		//move skb->data to current_tx_ptr payload
 #ifdef TRACE_PACKETS
-    lp->stats.tx_dropped++;
+        lp->stats.tx_dropped++;
 #endif
-    data = (unsigned int)(skb->data);
-    data -= 6;
-    *((unsigned short *)data) = (unsigned short)(skb->len + 6);
-	memmove((char *)(data + 2), (char *)(data + 6), 12);
-	setup_hdr((unsigned char *)(data + 14), lp->amlan);
-		current_tx_ptr->desc_a.start_addr = (unsigned long)data;
-    if (current_tx_ptr->status.status_word != 0)
+        data = (unsigned int)(skb->data);
+        data -= 6;
+        *((unsigned short *)data) = (unsigned short)(skb->len + 4);  
+        memmove((char *)(data + 2), (char *)(data + 6), 12);
+        setup_hdr((unsigned char *)(data + 14), lp->amlan);
+                current_tx_ptr->desc_a.start_addr = (unsigned long)data;
+        if (current_tx_ptr->status.status_word != 0)
 	    current_tx_ptr->status.status_word = 0;
-    blackfin_dcache_invalidate_range(data, (data+(skb->len)) + 6);  //this is important!
-
-	} else {
+        blackfin_dcache_invalidate_range(data, (data+(skb->len)) + 6);  //this is important!
+
+    } else {
 #ifdef TRACE_PACKETS
     /* XXX use error counter to track complex transmits */
-    lp->stats.tx_errors++;
+        lp->stats.tx_errors++;
 #endif	
-    *((unsigned short *)(current_tx_ptr->packet)) = (unsigned short)(skb->len + 6);
-    memcpy((char *)(current_tx_ptr->packet + 2),skb->data,(12));
+        *((unsigned short *)(current_tx_ptr->packet)) = (unsigned short)(skb->len + 4);  
+        memcpy((char *)(current_tx_ptr->packet + 2),skb->data,(12));
 #ifdef TRACE_PACKETS
-	if (lp->amlan)
-		lp->stats.tx_errors++;
+        if (lp->amlan)
+            lp->stats.tx_errors++;
 #endif		
-	setup_hdr((unsigned char *)(current_tx_ptr->packet + 14), lp->amlan);
-    memcpy((char *)(current_tx_ptr->packet + 18),skb->data + 12,(skb->len - 12));
-    current_tx_ptr->desc_a.start_addr = (unsigned long)current_tx_ptr->packet;
-		if (current_tx_ptr->status.status_word != 0)
-			current_tx_ptr->status.status_word = 0;
-    blackfin_dcache_invalidate_range((unsigned int)current_tx_ptr->packet, (unsigned int)(current_tx_ptr->packet + skb->len) + 6);
-	}
-
-	current_tx_ptr->desc_a.config.b_DMA_EN = 1;	//enable this packet's dma
-
-	if (bfin_read_DMA2_IRQ_STATUS() & 0x08) {	//tx dma is running, just return
-		goto out;
-	} else {		//tx dma is not running
-		bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
-		bfin_write_DMA2_CONFIG(*((unsigned short *)(&(current_tx_ptr->desc_a.config))));	// dma enabled, read from memory, size is 6
-		// Turn on the EMAC tx
-		bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
-	}
-
-      out:
-	adjust_tx_list();
-	current_tx_ptr = current_tx_ptr->next;
-	dev->trans_start = jiffies;
-	lp->stats.tx_packets++;
-	lp->stats.tx_bytes += (skb->len);
-  spin_unlock_irqrestore(&lp->lock, flags);
-  dev_kfree_skb(skb);
+        setup_hdr((unsigned char *)(current_tx_ptr->packet + 14), lp->amlan);
+        memcpy((char *)(current_tx_ptr->packet + 18),skb->data + 12,(skb->len - 12));
+        current_tx_ptr->desc_a.start_addr = (unsigned long)current_tx_ptr->packet;
+        if (current_tx_ptr->status.status_word != 0)
+            current_tx_ptr->status.status_word = 0;
+        blackfin_dcache_invalidate_range((unsigned int)current_tx_ptr->packet, (unsigned int)(current_tx_ptr->packet + skb->len) + 6);
+    } 
+
+    current_tx_ptr->desc_a.config.b_DMA_EN = 1;	//enable this packet's dma
+
+    if (bfin_read_DMA2_IRQ_STATUS() & 0x08) {	//tx dma is running, just return
+        goto out;
+    } else {		//tx dma is not running
+        bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
+        bfin_write_DMA2_CONFIG(*((unsigned short *)(&(current_tx_ptr->desc_a.config))));	// dma enabled, read from memory, size is 6
+         // Turn on the EMAC tx
+        bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);
+    }
+
+  out:
+    adjust_tx_list();
+    current_tx_ptr = current_tx_ptr->next;
+    dev->trans_start = jiffies;
+    lp->stats.tx_packets++;
+    lp->stats.tx_bytes += (skb->len);
 	return 0;
 }
 
@@ -634,21 +644,19 @@
       lp->stats.rx_dropped++;
 #endif	  
   }
-  
-  
 /*
-  if (len >= 300) {
-    printk("going to copy the big packet\n");
+	if (len >= 300) {
+		printk("going to copy the big packet\n");
 		for (i=0;i<len;i++) {
 			printk("%.2x-",((unsigned char *)pkt)[i]);
 			if (((i%8)==0) && (i!=0)) printk("\n");
 		}
-	printk("\n");
+		printk("\n");
 	}
 */
 
 #if 0
-  printk("Rx: %02x%02x\n", skb->data[14], skb->data[15]);
+								   printk("Rx: %02x%02x\n", skb->data[14], skb->data[15]);
 #endif  
 
 	dev->last_rx = jiffies;
@@ -659,12 +667,12 @@
 	lp->stats.rx_bytes += len;
 
       out:
-  if (!rx_desc->skb)
-  	rx_desc->skb = bf537_alloc_skb(1560 + 4);
-  if (rx_desc->skb)
-    rx_desc->desc_a.start_addr = (unsigned long)rx_desc->skb->data;
-  else
-    rx_desc->desc_a.start_addr = (unsigned long)rx_desc->packet;
+	if (!rx_desc->skb)
+	rx_desc->skb = bf537_alloc_skb(1560 + 4);
+	if (rx_desc->skb)
+	rx_desc->desc_a.start_addr = (unsigned long)rx_desc->skb->data;
+	else
+	rx_desc->desc_a.start_addr = (unsigned long)rx_desc->packet;
 	return;
 }
 
@@ -878,7 +886,6 @@
 	/* free the rx/tx buffers */
 	desc_list_free();
   }
-
 	return 0;
 }
 
@@ -1028,7 +1035,6 @@
 
   dev_set_drvdata(dev, ndev);
 
-  //printk("bf537_mac: probe finished\n");
   return ret;
 }
 



More information about the aadk-commits mailing list