Commit 5e18a111 authored by Scott Feldman's avatar Scott Feldman Committed by Jeff Garzik

[PATCH] e100: ICH 10/H Tx hang fix

* Need to carry forward this workaround from old e100 driver to
  avoid a Tx hang on ICH systems linked at 10/Half.  Workaround
  adds a stall before each Tx command queued by issuing a NOP
  command followed by 1us delay.  Yuck!  Otherwise HW locks hard.
  (Probably needed for eepro100 also ;-).
parent 7ce42ae1
...@@ -287,6 +287,7 @@ enum scb_cmd_hi { ...@@ -287,6 +287,7 @@ enum scb_cmd_hi {
}; };
enum scb_cmd_lo { enum scb_cmd_lo {
cuc_nop = 0x00,
ruc_start = 0x01, ruc_start = 0x01,
ruc_load_base = 0x06, ruc_load_base = 0x06,
cuc_start = 0x10, cuc_start = 0x10,
...@@ -514,10 +515,11 @@ struct nic { ...@@ -514,10 +515,11 @@ struct nic {
/* End: frequently used values: keep adjacent for cache effect */ /* End: frequently used values: keep adjacent for cache effect */
enum { enum {
ich = (1 << 0), ich = (1 << 0),
promiscuous = (1 << 1), promiscuous = (1 << 1),
multicast_all = (1 << 2), multicast_all = (1 << 2),
wol_magic = (1 << 3), wol_magic = (1 << 3),
ich_10h_workaround = (1 << 4),
} flags ____cacheline_aligned; } flags ____cacheline_aligned;
enum mac mac; enum mac mac;
...@@ -1225,6 +1227,12 @@ static void e100_watchdog(unsigned long data) ...@@ -1225,6 +1227,12 @@ static void e100_watchdog(unsigned long data)
/* Issue a multicast command to workaround a 557 lock up */ /* Issue a multicast command to workaround a 557 lock up */
e100_set_multicast_list(nic->netdev); e100_set_multicast_list(nic->netdev);
if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
/* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
nic->flags |= ich_10h_workaround;
else
nic->flags &= ~ich_10h_workaround;
mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
} }
...@@ -1244,7 +1252,17 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, ...@@ -1244,7 +1252,17 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct nic *nic = netdev->priv; struct nic *nic = netdev->priv;
int err = e100_exec_cb(nic, skb, e100_xmit_prepare); int err;
if(nic->flags & ich_10h_workaround) {
/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
Issue a NOP command followed by a 1us delay before
issuing the Tx command. */
e100_exec_cmd(nic, cuc_nop, 0);
udelay(1);
}
err = e100_exec_cb(nic, skb, e100_xmit_prepare);
switch(err) { switch(err) {
case -ENOSPC: case -ENOSPC:
......
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