[PATCH] e1000: made loopback test robust
authorMalli Chilakala <mallikarjuna.chilakala@intel.com>
Fri, 29 Apr 2005 02:38:30 +0000 (19:38 -0700)
committerJeff Garzik <jgarzik@pobox.com>
Fri, 13 May 2005 00:48:52 +0000 (20:48 -0400)
Added enhanced functionality to the loopback diags to wrap the descriptor rings.

Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
diff -up net-drivers-2.6/drivers/net/e1000/e1000_ethtool.c net-drivers-2.6/drivers/net/e1000.new/e1000_ethtool.c

drivers/net/e1000/e1000_ethtool.c

index 0a2ca7c73a4120f751918524a24682601ed51b3f..fae585453463387ebb71d411be2c827ee359dbc7 100644 (file)
@@ -919,7 +919,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
        /* Setup Tx descriptor ring and Tx buffers */
 
 
        /* Setup Tx descriptor ring and Tx buffers */
 
-       txdr->count = 80;
+       if(!txdr->count)
+               txdr->count = E1000_DEFAULT_TXD;   
 
        size = txdr->count * sizeof(struct e1000_buffer);
        if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
 
        size = txdr->count * sizeof(struct e1000_buffer);
        if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
@@ -974,7 +975,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
        /* Setup Rx descriptor ring and Rx buffers */
 
 
        /* Setup Rx descriptor ring and Rx buffers */
 
-       rxdr->count = 80;
+       if(!rxdr->count)
+               rxdr->count = E1000_DEFAULT_RXD;   
 
        size = rxdr->count * sizeof(struct e1000_buffer);
        if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
 
        size = rxdr->count * sizeof(struct e1000_buffer);
        if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
@@ -1310,31 +1312,62 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
        struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
        struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
        struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
        struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
        struct pci_dev *pdev = adapter->pdev;
-       int i, ret_val;
+       int i, j, k, l, lc, good_cnt, ret_val=0;
+       unsigned long time;
 
        E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
 
 
        E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
 
-       for(i = 0; i < 64; i++) {
-               e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
-               pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma,
-                                           txdr->buffer_info[i].length,
-                                           PCI_DMA_TODEVICE);
-       }
-       E1000_WRITE_REG(&adapter->hw, TDT, i);
-
-       msec_delay(200);
-
-       i = 0;
-       do {
-               pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[i].dma,
-                                           rxdr->buffer_info[i].length,
-                                           PCI_DMA_FROMDEVICE);
-
-               ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb,
-                                                  1024);
-               i++;
-       } while (ret_val != 0 && i < 64);
+       /* Calculate the loop count based on the largest descriptor ring 
+        * The idea is to wrap the largest ring a number of times using 64
+        * send/receive pairs during each loop
+        */
 
 
+       if(rxdr->count <= txdr->count)
+               lc = ((txdr->count / 64) * 2) + 1;
+       else
+               lc = ((rxdr->count / 64) * 2) + 1;
+
+       k = l = 0;
+       for(j = 0; j <= lc; j++) { /* loop count loop */
+               for(i = 0; i < 64; i++) { /* send the packets */
+                       e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 
+                                       1024);
+                       pci_dma_sync_single_for_device(pdev, 
+                                       txdr->buffer_info[k].dma,
+                                       txdr->buffer_info[k].length,
+                                       PCI_DMA_TODEVICE);
+                       if(unlikely(++k == txdr->count)) k = 0;
+               }
+               E1000_WRITE_REG(&adapter->hw, TDT, k);
+               msec_delay(200);
+               time = jiffies; /* set the start time for the receive */
+               good_cnt = 0;
+               do { /* receive the sent packets */
+                       pci_dma_sync_single_for_cpu(pdev, 
+                                       rxdr->buffer_info[l].dma,
+                                       rxdr->buffer_info[l].length,
+                                       PCI_DMA_FROMDEVICE);
+       
+                       ret_val = e1000_check_lbtest_frame(
+                                       rxdr->buffer_info[l].skb,
+                                       1024);
+                       if(!ret_val)
+                               good_cnt++;
+                       if(unlikely(++l == rxdr->count)) l = 0;
+                       /* time + 20 msecs (200 msecs on 2.4) is more than 
+                        * enough time to complete the receives, if it's 
+                        * exceeded, break and error off
+                        */
+               } while (good_cnt < 64 && jiffies < (time + 20));
+               if(good_cnt != 64) {
+                       ret_val = 13; /* ret_val is the same as mis-compare */
+                       break; 
+               }
+               if(jiffies >= (time + 2)) {
+                       ret_val = 14; /* error code for time out error */
+                       break;
+               }
+       } /* end loop count loop */
        return ret_val;
 }
 
        return ret_val;
 }
 
@@ -1371,6 +1404,8 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
                *data = 1; 
        } else {
                e1000_check_for_link(&adapter->hw);
                *data = 1; 
        } else {
                e1000_check_for_link(&adapter->hw);
+               if(adapter->hw.autoneg)  /* if auto_neg is set wait for it */
+                       msec_delay(4000);
 
                if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
                        *data = 1;
 
                if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
                        *data = 1;