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. ...@@ -138,10 +138,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define TX_THRSHLD 8 #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 */ /* IFS parameters */
#define MIN_NUMBER_OF_TRANSMITS_100 1000 #define MIN_NUMBER_OF_TRANSMITS_100 1000
#define MIN_NUMBER_OF_TRANSMITS_10 100 #define MIN_NUMBER_OF_TRANSMITS_10 100
...@@ -1019,6 +1015,14 @@ extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout, ...@@ -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_get_link_state(struct e100_private *bdp);
extern unsigned char e100_wait_scb(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, extern void e100_deisolate_driver(struct e100_private *bdp,
u8 recover, u8 full_reset); u8 recover, u8 full_reset);
extern unsigned char e100_hw_reset_recover(struct e100_private *bdp, extern unsigned char e100_hw_reset_recover(struct e100_private *bdp,
......
...@@ -137,7 +137,7 @@ eeprom_set_semaphore(struct e100_private *adapter) ...@@ -137,7 +137,7 @@ eeprom_set_semaphore(struct e100_private *adapter)
u16 data = 0; u16 data = 0;
unsigned long expiration_time = jiffies + HZ / 100 + 1; unsigned long expiration_time = jiffies + HZ / 100 + 1;
while (time_before(jiffies, expiration_time)) { do {
// Get current value of General Control 2 // Get current value of General Control 2
data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter));
...@@ -154,10 +154,12 @@ eeprom_set_semaphore(struct e100_private *adapter) ...@@ -154,10 +154,12 @@ eeprom_set_semaphore(struct e100_private *adapter)
return true; return true;
} }
set_current_state(TASK_UNINTERRUPTIBLE); if (time_before(jiffies, expiration_time))
schedule_timeout(1+(HZ-1)/100); yield();
} else
return false; return false;
} while (true);
} }
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
...@@ -579,17 +581,16 @@ eeprom_wait_cmd_done(struct e100_private *adapter) ...@@ -579,17 +581,16 @@ eeprom_wait_cmd_done(struct e100_private *adapter)
eeprom_stand_by(adapter); eeprom_stand_by(adapter);
while (time_before(jiffies, expiration_time)) { do {
rmb(); rmb();
x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter));
if (x & EEDO) if (x & EEDO)
return true; return true;
if (time_before(jiffies, expiration_time))
set_current_state(TASK_UNINTERRUPTIBLE); yield();
schedule_timeout(1+(HZ-1)/100); else
} return false;
} while (true);
return false;
} }
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
......
...@@ -165,7 +165,7 @@ static void e100_non_tx_background(unsigned long); ...@@ -165,7 +165,7 @@ static void e100_non_tx_background(unsigned long);
/* Global Data structures and variables */ /* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; 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 " #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) ...@@ -2705,7 +2705,7 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
cb_header_t *ntcb_hdr; cb_header_t *ntcb_hdr;
unsigned long lock_flag; unsigned long lock_flag;
unsigned long expiration_time; 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 */ 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) ...@@ -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)) { if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START)) {
spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag);
rc = false;
goto exit; goto exit;
} }
...@@ -2748,20 +2749,21 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command) ...@@ -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 */ /* now wait for completion of non-cu CB up to 20 msec */
expiration_time = jiffies + HZ / 50 + 1; expiration_time = jiffies + HZ / 50 + 1;
while (time_before(jiffies, expiration_time)) { rmb();
rmb(); while (!(ntcb_hdr->cb_status &
if ((ntcb_hdr->cb_status &
__constant_cpu_to_le16(CB_STATUS_COMPLETE))) { __constant_cpu_to_le16(CB_STATUS_COMPLETE))) {
rc = true;
if (time_before(jiffies, expiration_time)) {
spin_unlock_bh(&(bdp->bd_non_tx_lock));
yield();
spin_lock_bh(&(bdp->bd_non_tx_lock));
} else {
rc = false;
goto exit; goto exit;
} }
spin_unlock_bh(&(bdp->bd_non_tx_lock)); rmb();
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
spin_lock_bh(&(bdp->bd_non_tx_lock));
} }
/* didn't get a C bit assume command failed */
exit: exit:
e100_free_non_tx_cmd(bdp, command); e100_free_non_tx_cmd(bdp, command);
......
...@@ -653,7 +653,7 @@ static void ...@@ -653,7 +653,7 @@ static void
e100_force_speed_duplex(struct e100_private *bdp) e100_force_speed_duplex(struct e100_private *bdp)
{ {
u16 control; u16 control;
int neg_timeout = 2 * HZ; //2 sec in jiffies unsigned long expires;
bdp->flags |= DF_SPEED_FORCED; bdp->flags |= DF_SPEED_FORCED;
...@@ -696,20 +696,18 @@ e100_force_speed_duplex(struct e100_private *bdp) ...@@ -696,20 +696,18 @@ e100_force_speed_duplex(struct e100_private *bdp)
e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);
/* loop must run at least once */ /* loop must run at least once */
expires = jiffies + 2 * HZ;
do { do {
spin_unlock_bh(&(bdp->mdi_access_lock)); if (e100_update_link_state(bdp) ||
time_after(jiffies, expires)) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(SLEEP_TIME);
spin_lock_bh(&(bdp->mdi_access_lock));
if (e100_update_link_state(bdp)) {
break; break;
} else {
spin_unlock_bh(&(bdp->mdi_access_lock));
yield();
spin_lock_bh(&(bdp->mdi_access_lock));
} }
neg_timeout -= SLEEP_TIME;
} while (neg_timeout > 0); } while (true);
spin_unlock_bh(&(bdp->mdi_access_lock)); spin_unlock_bh(&(bdp->mdi_access_lock));
} }
...@@ -819,7 +817,7 @@ static void ...@@ -819,7 +817,7 @@ static void
e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
{ {
u16 stat_reg; u16 stat_reg;
unsigned int i; unsigned long expires;
bdp->flags &= ~DF_SPEED_FORCED; bdp->flags &= ~DF_SPEED_FORCED;
...@@ -840,22 +838,21 @@ e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) ...@@ -840,22 +838,21 @@ e100_auto_neg(struct e100_private *bdp, unsigned char force_restart)
BMCR_ANENABLE | BMCR_ANRESTART); BMCR_ANENABLE | BMCR_ANRESTART);
/* wait for autoneg to complete (up to 3 seconds) */ /* 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 */ /* 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);
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; goto exit;
} else {
spin_unlock_bh(&(bdp->mdi_access_lock)); spin_unlock_bh(&(bdp->mdi_access_lock));
yield();
set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_bh(&(bdp->mdi_access_lock));
schedule_timeout(SLEEP_TIME); }
} while (true);
spin_lock_bh(&(bdp->mdi_access_lock));
}
} }
exit: exit:
......
...@@ -97,7 +97,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -97,7 +97,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef E100_CONFIG_PROC_FS #ifdef E100_CONFIG_PROC_FS
#include "e100.h" #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 */ /* /proc File System Interaface Support Functions */
/***************************************************************************/ /***************************************************************************/
...@@ -230,7 +231,7 @@ set_led(struct e100_private *bdp, u16 led_mdi_op) ...@@ -230,7 +231,7 @@ set_led(struct e100_private *bdp, u16 led_mdi_op)
spin_unlock_bh(&bdp->mdi_access_lock); spin_unlock_bh(&bdp->mdi_access_lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(SLEEP_TIME); schedule_timeout(MDI_SLEEP_TIME);
spin_lock_bh(&bdp->mdi_access_lock); 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