[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>
This commit is contained in:
Andy Fleming
2006-04-20 16:44:29 -05:00
committed by Jeff Garzik
parent f18b95c3e2
commit fef6108d45
4 changed files with 100 additions and 67 deletions

View File

@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
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 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
spin_unlock_irqrestore(&priv->lock, flags);
spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
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 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
gfar_write(&priv->regs->attr, temp);
spin_unlock_irqrestore(&priv->lock, flags);
spin_unlock_irqrestore(&priv->rxlock, flags);
return count;
}
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
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 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
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 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
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;
}