[vortex] 3c590 media selection
Andrew Morton
andrewm@uow.edu.au
Sun, 07 Jan 2001 18:35:17 +1100
Hi, Don.
I've been looking into a 590 problem report where if the
10baseT cable is pulled out the NIC goes inoperative.
What happens is that the selection logic rotates to
10base2 and then gets stuck there because 10base2
has no link beat indication.
The comment in the code says "Other media types handled
by Tx timeouts."
There is no implementation of this, so I put it in.
It doesn't work very well, because we seem to be able to
send packets into thin air across 10base2. I would _occasionally_
get a tx timeout, and the driver would then advance to
AUI and get completely stuck, because we can happily transmit
packets into thin air across AUI as well.
I don't really see a sensible algorithmic fix for this,
so I took the tx timeout logic out again.
So we're left with forcing the media type via
module parameters.
But there's a problem with the vortex_timer logic. Even
if we try to force 10baseT via `options=0', this code:
media_status = inw(ioaddr + Wn4_Media);
switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
ok = 1;
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
} else if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
break;
will always cause the driver to advance onto the next media type,
which causes it to get stuck on 10base2.
So what I did was to add a new flag to the device structure
`media_was_forced'. Set it in the processing of module
options:
if (option >= 0) {
vp->media_override = ((option & 7) == 2) ? 0 : option & 15;
if (vp->media_override != 7)
vp->media_was_forced = 1;
And test it vortex_timer:
if (vp->media_was_forced)
goto leave_media_alone;
disable_irq(dev->irq);
<all the media selection logic>
enable_irq(dev->irq);
leave_media_alone:
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
vp->timer.expires = RUN_AT(next_tick);
add_timer(&vp->timer);
if (vp->deferred)
outw(FakeIntr, ioaddr + EL3_CMD);
return;
}
Does all this make sense?
Thanks.