master/ethernet.c
changeset 1489 f77a1182b6f4
parent 1488 3fb343e3fac0
child 1500 ed1a733efbc5
--- a/master/ethernet.c	Mon Jun 29 14:27:06 2009 +0000
+++ b/master/ethernet.c	Tue Jun 30 11:11:56 2009 +0000
@@ -52,7 +52,7 @@
  * 2 = Output actions.
  * 3 = Output actions and frame data.
  */
-#define EOE_DEBUG_LEVEL 0
+#define EOE_DEBUG_LEVEL 1
 
 /** Size of the EoE tx queue.
  */
@@ -60,7 +60,7 @@
 
 /** Number of tries.
  */
-#define EC_EOE_TRIES 10
+#define EC_EOE_TRIES 100
 
 /*****************************************************************************/
 
@@ -107,7 +107,7 @@
     eoe->tx_queue_active = 0;
     eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
     eoe->tx_queued_frames = 0;
-    eoe->tx_queue_lock = SPIN_LOCK_UNLOCKED;
+    init_MUTEX(&eoe->tx_queue_sem);
     eoe->tx_frame_number = 0xFF;
     memset(&eoe->stats, 0, sizeof(struct net_device_stats));
 
@@ -116,6 +116,8 @@
     eoe->rx_rate = 0;
     eoe->tx_rate = 0;
     eoe->rate_jiffies = 0;
+    eoe->rx_idle = 1;
+    eoe->tx_idle = 1;
 
     /* device name eoe<MASTER>[as]<SLAVE>, because networking scripts don't
      * like hyphens etc. in interface names. */
@@ -206,7 +208,7 @@
 {
     ec_eoe_frame_t *frame, *next;
 
-    spin_lock_bh(&eoe->tx_queue_lock);
+    down(&eoe->tx_queue_sem);
 
     list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
         list_del(&frame->queue);
@@ -215,7 +217,7 @@
     }
     eoe->tx_queued_frames = 0;
 
-    spin_unlock_bh(&eoe->tx_queue_lock);
+    up(&eoe->tx_queue_sem);
 }
 
 /*****************************************************************************/
@@ -338,6 +340,18 @@
     return eoe->opened;
 }
 
+/*****************************************************************************/
+
+/** Returns the idle state.
+ *
+ * \retval 1 The device is idle.
+ * \retval 0 The device is busy.
+ */
+int ec_eoe_is_idle(const ec_eoe_t *eoe /**< EoE handler */)
+{
+    return eoe->rx_idle && eoe->tx_idle;
+}
+
 /******************************************************************************
  *  STATE PROCESSING FUNCTIONS
  *****************************************************************************/
@@ -349,8 +363,12 @@
  */
 void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
 {
-    if (eoe->slave->error_flag || !eoe->slave->master->main_device.link_state)
-        return;
+    if (eoe->slave->error_flag ||
+            !eoe->slave->master->main_device.link_state) {
+        eoe->rx_idle = 1;
+        eoe->tx_idle = 1;
+        return;
+    }
 
     ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram);
     eoe->queue_datagram = 1;
@@ -377,10 +395,12 @@
     }
 
     if (!ec_slave_mbox_check(&eoe->datagram)) {
+        eoe->rx_idle = 1;
         eoe->state = ec_eoe_state_tx_start;
         return;
     }
 
+    eoe->rx_idle = 0;
     ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram);
     eoe->queue_datagram = 1;
     eoe->state = ec_eoe_state_rx_fetch;
@@ -566,13 +586,18 @@
     unsigned int wakeup = 0;
 #endif
 
-    if (eoe->slave->error_flag || !eoe->slave->master->main_device.link_state)
-        return;
-
-    spin_lock_bh(&eoe->tx_queue_lock);
+    if (eoe->slave->error_flag ||
+            !eoe->slave->master->main_device.link_state) {
+        eoe->rx_idle = 1;
+        eoe->tx_idle = 1;
+        return;
+    }
+
+    down(&eoe->tx_queue_sem);
 
     if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
-        spin_unlock_bh(&eoe->tx_queue_lock);
+        up(&eoe->tx_queue_sem);
+        eoe->tx_idle = 1;
         // no data available.
         // start a new receive immediately.
         ec_eoe_state_rx_start(eoe);
@@ -592,7 +617,9 @@
     }
 
     eoe->tx_queued_frames--;
-    spin_unlock_bh(&eoe->tx_queue_lock);
+    up(&eoe->tx_queue_sem);
+
+    eoe->tx_idle = 0;
 
     eoe->tx_frame_number++;
     eoe->tx_frame_number %= 16;
@@ -633,15 +660,11 @@
         if (eoe->tries) {
             eoe->tries--; // try again
             eoe->queue_datagram = 1;
-#if EOE_DEBUG_LEVEL >= 1
-            EC_WARN("Failed to receive send datagram for %s. Retrying.\n",
-                    eoe->dev->name);
-#endif
         } else {
             eoe->stats.tx_errors++;
 #if EOE_DEBUG_LEVEL >= 1
-            EC_WARN("Failed to receive send datagram for %s. Giving up.\n",
-                    eoe->dev->name);
+            EC_WARN("Failed to receive send datagram for %s after %u tries.\n",
+                    eoe->dev->name, EC_EOE_TRIES);
 #endif
             eoe->state = ec_eoe_state_rx_start;
         }
@@ -652,13 +675,11 @@
         if (eoe->tries) {
             eoe->tries--; // try again
             eoe->queue_datagram = 1;
-#if EOE_DEBUG_LEVEL >= 1
-            EC_WARN("No sending response for %s. Retrying.\n", eoe->dev->name);
-#endif
         } else {
             eoe->stats.tx_errors++;
 #if EOE_DEBUG_LEVEL >= 1
-            EC_WARN("No sending response for %s. Giving up.\n", eoe->dev->name);
+            EC_WARN("No sending response for %s after %u tries.\n",
+                    eoe->dev->name, EC_EOE_TRIES);
 #endif
             eoe->state = ec_eoe_state_rx_start;
         }
@@ -700,6 +721,8 @@
     ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev));
     ec_eoe_flush(eoe);
     eoe->opened = 1;
+    eoe->rx_idle = 0;
+    eoe->tx_idle = 0;
     netif_start_queue(dev);
     eoe->tx_queue_active = 1;
 #if EOE_DEBUG_LEVEL >= 2
@@ -717,6 +740,8 @@
 {
     ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev));
     netif_stop_queue(dev);
+    eoe->rx_idle = 1;
+    eoe->tx_idle = 1;
     eoe->tx_queue_active = 0;
     eoe->opened = 0;
     ec_eoe_flush(eoe);
@@ -756,14 +781,14 @@
 
     frame->skb = skb;
 
-    spin_lock_bh(&eoe->tx_queue_lock);
+    down(&eoe->tx_queue_sem);
     list_add_tail(&frame->queue, &eoe->tx_queue);
     eoe->tx_queued_frames++;
     if (eoe->tx_queued_frames == eoe->tx_queue_size) {
         netif_stop_queue(dev);
         eoe->tx_queue_active = 0;
     }
-    spin_unlock_bh(&eoe->tx_queue_lock);
+    up(&eoe->tx_queue_sem);
 
 #if EOE_DEBUG_LEVEL >= 2
     EC_DBG("EoE %s TX queued frame with %u octets (%u frames queued).\n",