Commit b8f53f4a authored by Eli Kupermann's avatar Eli Kupermann Committed by Jeff Garzik

e100 net driver update 4/4:

- switch to yield function as suggested by you, Arjan and Andrew.
- fixed broken logic in the use of time_before/time_after - possible
bug cause in previous design - in most of the places we were going to sleep
and than check if time expires before checking if condition is satisfied.
If, for example, we needed to wait up to 3 jiffies we could do
schedule_timeout(1) and get up after 4 ticks check that time expired and go
away crying about failure without checking that condition is OK.(in fact I
saw it happen on one SMP platform here).
parent 3c88d2f4
......@@ -138,10 +138,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define TX_THRSHLD 8
/* sleep time is at least 50 ms, in jiffies */
#define SLEEP_TIME ((HZ / 20) + 1)
#define CUS_TIMEOUT 1000
/* IFS parameters */
#define MIN_NUMBER_OF_TRANSMITS_100 1000
#define MIN_NUMBER_OF_TRANSMITS_10 100
......@@ -1019,6 +1015,14 @@ extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout,
extern unsigned char e100_get_link_state(struct e100_private *bdp);
extern unsigned char e100_wait_scb(struct e100_private *bdp);
#ifndef yield
#define yield() \
do { \
current->policy |= SCHED_YIELD; \
schedule(); \
} while (0)
#endif
extern void e100_deisolate_driver(struct e100_private *bdp,
u8 recover, u8 full_reset);
extern unsigned char e100_hw_reset_recover(struct e100_private *bdp,
......
......@@ -137,7 +137,7 @@ eeprom_set_semaphore(struct e100_private *adapter)
u16 data = 0;
unsigned long expiration_time = jiffies + HZ / 100 + 1;
while (time_before(jiffies, expiration_time)) {
do {
// Get current value of General Control 2
data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
......@@ -154,10 +154,12 @@ eeprom_set_semaphore(struct e100_private *adapter)
return true;
}
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1+(HZ-1)/100);
}
if (time_before(jiffies, expiration_time))
yield();
else
return false;
} while (true);
}
//----------------------------------------------------------------------------------------
......@@ -579,17 +581,16 @@ eeprom_wait_cmd_done(struct e100_private *adapter)
eeprom_stand_by(adapter);
while (time_before(jiffies, expiration_time)) {
do {
rmb();
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
if (x & EEDO)
return true;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1+(HZ-1)/100);
}
if (time_before(jiffies, expiration_time))
yield();
else
return false;
} while (true);
}
//----------------------------------------------------------------------------------------
......
......@@ -165,7 +165,7 @@ static void e100_non_tx_background(unsigned long);
/* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
#define E100_VERSION "2.0.23-pre2"
#define E100_VERSION "2.0.24-pre1"
#define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver "
......@@ -2705,7 +2705,7 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
cb_header_t *ntcb_hdr;
unsigned long lock_flag;
unsigned long expiration_time;
unsigned char rc = false;
unsigned char rc = true;
ntcb_hdr = (cb_header_t *) command->non_tx_cmd; /* get hdr of non tcb cmd */
......@@ -2740,6 +2740,7 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START)) {
spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
rc = false;
goto exit;
}
......@@ -2748,20 +2749,21 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
/* now wait for completion of non-cu CB up to 20 msec */
expiration_time = jiffies + HZ / 50 + 1;
while (time_before(jiffies, expiration_time)) {
rmb();
if ((ntcb_hdr->cb_status &
while (!(ntcb_hdr->cb_status &
__constant_cpu_to_le16(CB_STATUS_COMPLETE))) {
rc = true;
goto exit;
}
if (time_before(jiffies, expiration_time)) {
spin_unlock_bh(&(bdp->bd_non_tx_lock));
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
yield();
spin_lock_bh(&(bdp->bd_non_tx_lock));
} else {
rc = false;
goto exit;
}
rmb();
}
/* didn't get a C bit assume command failed */
exit:
e100_free_non_tx_cmd(bdp, command);
......
......@@ -653,7 +653,7 @@ static void
e100_force_speed_duplex(struct e100_private *bdp)
{
u16 control;
int neg_timeout = 2 * HZ; //2 sec in jiffies
unsigned long expires;
bdp->flags |= DF_SPEED_FORCED;
......@@ -696,20 +696,18 @@ e100_force_speed_duplex(struct e100_private *bdp)
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
/* loop must run at least once */
expires = jiffies + 2 * HZ;
do {
if (e100_update_link_state(bdp) ||
time_after(jiffies, expires)) {
break;
} else {
spin_unlock_bh(&(bdp->mdi_access_lock));
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(SLEEP_TIME);
yield();
spin_lock_bh(&(bdp->mdi_access_lock));
if (e100_update_link_state(bdp)) {
break;
}
neg_timeout -= SLEEP_TIME;
} while (neg_timeout > 0);
} while (true);
spin_unlock_bh(&(bdp->mdi_access_lock));
}
......@@ -819,7 +817,7 @@ static void
e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
{
u16 stat_reg;
unsigned int i;
unsigned long expires;
bdp->flags &= ~DF_SPEED_FORCED;
......@@ -840,22 +838,21 @@ e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
BMCR_ANENABLE | BMCR_ANRESTART);
/* wait for autoneg to complete (up to 3 seconds) */
for (i = 0; i < 60; i++) {
expires = jiffies + HZ * 3;
do {
/* now re-read the value. Sticky so read twice */
e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);
if (stat_reg & BMSR_ANEGCOMPLETE)
if ((stat_reg & BMSR_ANEGCOMPLETE) ||
time_after(jiffies, expires) ) {
goto exit;
} else {
spin_unlock_bh(&(bdp->mdi_access_lock));
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(SLEEP_TIME);
yield();
spin_lock_bh(&(bdp->mdi_access_lock));
}
} while (true);
}
exit:
......
......@@ -97,7 +97,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef E100_CONFIG_PROC_FS
#include "e100.h"
/* MDI sleep time is at least 50 ms, in jiffies */
#define MDI_SLEEP_TIME ((HZ / 20) + 1)
/***************************************************************************/
/* /proc File System Interaface Support Functions */
/***************************************************************************/
......@@ -230,7 +231,7 @@ set_led(struct e100_private *bdp, u16 led_mdi_op)
spin_unlock_bh(&bdp->mdi_access_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(SLEEP_TIME);
schedule_timeout(MDI_SLEEP_TIME);
spin_lock_bh(&bdp->mdi_access_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment