I haven't heard anything in response to my earlier message, so I'm trying again. I don't like being a pest, but I'm stuck with a problem I don't understand, and that I haven't been able to figure out from the code. Can anyone give me some suggestions? Any idea why the sis900 driver is acting so strangely? If not, any clues about how to figure it out? Chris ---------------------------------------------------------------------- Date: Mon, 19 May 2003 14:47:36 -0400 From: Chris Hanson <cph@zurich.ai.mit.edu> 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); } - : 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