[PATCH] Fix locking in gianfar

This patch fixes several bugs in the gianfar driver, including a major one
where spinlocks were horribly broken:

* Split gianfar locks into two types: TX and RX
* Made it so gfar_start() now clears RHALT
* Fixed a bug where calling gfar_start_xmit() with interrupts off would
corrupt the interrupt state
* Fixed a bug where a frame could potentially arrive, and never be handled
(if no more frames arrived
* Fixed a bug where the rx_work_limit would never be observed by the rx
completion code
* Fixed a bug where the interrupt handlers were not actually protected by
their spinlocks

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 51ef181..a6d5c43 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -82,7 +82,7 @@
 	else
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 
 	/* Set the new stashing value */
 	priv->bd_stash_en = new_setting;
@@ -96,7 +96,7 @@
 
 	gfar_write(&priv->regs->attr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -118,7 +118,7 @@
 	u32 temp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 	if (length > priv->rx_buffer_size)
 		return count;
 
@@ -142,7 +142,7 @@
 
 	gfar_write(&priv->regs->attr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -166,7 +166,7 @@
 	u32 temp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 	if (index > priv->rx_stash_size)
 		return count;
 
@@ -180,7 +180,7 @@
 	temp |= ATTRELI_EI(index);
 	gfar_write(&priv->regs->attreli, flags);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -205,7 +205,7 @@
 	if (length > GFAR_MAX_FIFO_THRESHOLD)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_threshold = length;
 
@@ -214,7 +214,7 @@
 	temp |= length;
 	gfar_write(&priv->regs->fifo_tx_thr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }
@@ -240,7 +240,7 @@
 	if (num > GFAR_MAX_FIFO_STARVE)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_starve = num;
 
@@ -249,7 +249,7 @@
 	temp |= num;
 	gfar_write(&priv->regs->fifo_tx_starve, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }
@@ -274,7 +274,7 @@
 	if (num > GFAR_MAX_FIFO_STARVE_OFF)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_starve_off = num;
 
@@ -283,7 +283,7 @@
 	temp |= num;
 	gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }