Date: Thu, 08 May 2003 10:29:06 -0700 (PDT)
From: "David S. Miller" <davem@redhat.com>
From: Chris Hanson <cph@zurich.ai.mit.edu>
Date: Thu, 08 May 2003 14:34:21 -0400
For example, is it sufficient to just set IFF_UP and leave the
other flags off?
Setting this interface flag from userspace should work.
OK, but... (I bet you thought this conversation was finished :)
This seems to work most of the time, except for one of my users. He's
using the sis900 driver in kernel 2.4.21-rc1. When I don't force the
interface up, my code is able to detect link beat with no trouble.
When I _do_ force the interface up, it doesn't.
Any ideas why this would be true? I've tried a number of different
things and have failed to come up with a working configuration, other
than to leave the interface down when it is already down.
I did notice that the sis900 doesn't seem to immediately detect
link-beat when it is up, instead deferring to a timer event, but
sleeping for a full second after bringing the interface up didn't
change anything.
FYI, here is my current detection code. Perhaps there's something
wrong with it, although it's quite similar to mii-diag.
Chris
static unsigned int
get_link_status (int fd, const char * if_name, unsigned int * result_r)
{
struct ifreq ifr;
u16 * data = ((u16 *) (& (ifr . ifr_data)));
unsigned int if_flags;
int up_p;
int run_p;
int conn_p;
unsigned int retval;
strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
if ((ioctl (fd, SIOCGIFFLAGS, (&ifr))) < 0)
return (errno);
if_flags = (ifr . ifr_flags);
up_p = ((if_flags & IFF_UP) != 0);
run_p = ((if_flags & IFF_RUNNING) != 0);
/* As of 2.4.20, interfaces must be up in order to be interrogated. */
if (!up_p)
{
strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
(ifr . ifr_flags) = IFF_UP;
ioctl (fd, SIOCSIFFLAGS, (&ifr));
}
strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
(data[1]) = 1; /* read Basic Mode Status Register */
if ((ioctl (fd, SIOCGMIIPHY, (&ifr))) < 0)
retval = errno;
else if ((data[3]) == 0xFFFF)
/* Interface no longer available. */
retval = ENODEV;
else
{
/* Check for:
0x0002 clear = no jabber
0x0004 set = link up
0x0010 clear = no remote fault */
conn_p = (((data[3]) & 0x0016) == 0x0004);
retval = 0;
}
/* Restore original interface flags. */
if (!up_p)
{
strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
(ifr . ifr_flags) = if_flags;
ioctl (fd, SIOCSIFFLAGS, (&ifr));
}
if (retval == 0)
(*result_r)
= ((up_p ? STATUS_UP : 0)
| (run_p ? STATUS_RUNNING : 0)
| (conn_p ? STATUS_CONNECTED : 0));
return (retval);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
This archive was generated by hypermail 2b29 : Fri May 23 2003 - 22:00:02 EST