eepro100
Stephane Eranian
eranian@cello.hpl.hp.com
Thu Dec 9 12:58:13 1999
Donald,
> > The way the macro clear_suspend() is defined IS NOT
> > SAFE. We ran into a problem with this driver because
>
> It has been changed to
> #define clear_suspend(cmd) ((char *)(&(cmd)->cmd_status))[3] &= ~0x40
> for little-endian machines.
>
How is this better than:
#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status)
with regards to atomicity ?
You clearly need atomicity here, unless I am missing something.
My understanding of the operation is:
- The suspend bit is the marker for the end-of-transmit list.
When the chip reaches this point. It enters the suspended state
and interrupts.
- When you want to add packets to the list, you need to extend the list.
Because you're using a fixed ring buffer, you don't need to link in your
new list. However, you need to tell the chip that the end of list has now
moved (one entry farther). That's why you need to clear the Suspend
bit of the previous tail.
You need atomicity because the chip is working in parallel on the list
otherwise you have a race condition.
Is this correct ?
The bug we were getting by using the:
#define clear_suspend(cmd) (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
form proves the atomicity requirement.
The consequence of the operation not being atomic was that we were
getting timeouts because no transmission had completed for the
last 2seconds (speedo_timer()). At that point speedo_show_state()
was saying:
eth0: Transmit timed out: status 0050 0070 at 3319/3331 command 000c0000.
eth0: Tx ring dump, Tx queue 3331 / 3319:
eth0: 0 000ca000.
eth0: 1 000ca000.
eth0: 2 400ca000.
eth0: =3 000ca000.
eth0: 4 000ca000.
eth0: 5 000ca000.
eth0: 6 000ca000.
eth0: 7 000ca000.
eth0: 8 000ca000.
eth0: 9 000ca000.
eth0: 10 000ca000.
eth0: 11 000ca000.
eth0: 12 000ca000.
eth0: 13 000ca000.
eth0: 14 000ca000.
eth0: 15 000ca000.
eth0: 16 000ca000.
eth0: 17 000ca000.
eth0: 18 000ca000.
eth0: 19 000ca000.
eth0: 20 000ca000.
eth0: 21 000ca000.
eth0: 22 000ca000.
eth0: * 23 000c0000.
eth0: 24 000ca000.
eth0: 25 000ca000.
eth0: 26 000ca000.
eth0: 27 000ca000.
eth0: 28 000ca000.
eth0: 29 000ca000.
eth0: 30 000ca000.
eth0: 31 000ca000.
PHY index 1 register 0 is 3000.
PHY index 1 register 1 is 782d.
PHY index 1 register 2 is 02a8.
PHY index 1 register 3 is 0154.
PHY index 1 register 4 is 05e1.
PHY index 1 register 5 is 0081.
PHY index 1 register 21 is 0000.
eth0: Trying to restart the transmitter...
So I still think the code should rather look like this:
#if defined(__i386__) || defined(__alpha__) /* || defined(__ia64__)*/
#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status)
#elif defined(__powerpc__)
#define clear_suspend(cmd) clear_bit(6, &(cmd)->cmd_status)
#else
#error "You need the clear_bit() atomic operation for your platform"
#endif
+--------------------------------------------------------------------+
| Ste'phane ERANIAN | Email eranian@hpl.hp.com |
| Hewlett-Packard Laboratories | |
| 1501, Page Mill Road MS 1U-15 | |
| Palo Alto, CA 94303-096 | |
| USA | |
| Tel : (650) 857-7174 | |
| Fax : (650) 857-5548 | |
+--------------------------------------------------------------------+