Discussion:
timing issues with udev and firmware loading
Karl Relton
2008-02-20 20:43:27 UTC
Permalink
[I've moved over to the devel alias]
Hi,
I have some trouble with the new (svn version 1851) wlan_wext_write
auto-enabling and loading of firmware through udev scripts. I reported
this in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465681 but I
"The firmware loading fails because when /etc/wlan/wlan-udev.sh is
run, the wlan0 interface is not available
wlanctl-ng: No such device
wlanctl-ng: No such device
prism2dl: No such device
Running it manually later works fine. I inserted a "sleep 2" on the
top of wlan-udev.sh and then it works
fine. It can seem like the udev rule 84-linux-wlan-ng runs the
wlan-udev.sh script "too early". I also stopped
network-manager to verify that it was not to blame.
However, if I echo 0 > /sys/module/p80211/parameters/wlan_wext_write,
the firmware loading works. So this
problem might be related to the new auto-enabling in the driver."
What we have here is a race condition, which is exasperated by the fact
that the drvr_start operation now has a 1000 msec sleep inserted it (to
work-around dodgy hardware etc. etc.).

What is happening is as follows:

- prism2sta_probe_usb is calling register_wlandev(), setting
wlandev->msdstate = WLAN_MSD_HWPRESENT
and then calling prism2sta_ifstate to do the automatic enable.

- The automatic enable is sets
wlandev->msdstate = WLAN_MSD_RUNNING_PENDING
and then calls drvr_start which will take at least 1 second due to
its enforced waiting time.

- in parallel, as a result of register_wlandev, udev will be signalled
with the 'ADD NET' which triggers the rule to call wlan-udev.sh

- wlan-udev.sh results in wlanctl-ng being called, which in turn results
in p80211req_dorequest being called.

- p80211req_dorequest tests wlandev->msdstate, and since it is not in a
'normal' state, returns with -ENODEV

So its not that the device doesn't exist, its that it is in a funny
state that p80211req_dorequest throws out with the 'no device' error
code.


The quick work-around is of course to insert a 2 second sleep into
wlan-udev.sh, as you have found.


p80211req_dorequest could be changed to return -EBUSY, the correct
status for what is happening at that point. This would still need work
in wlan-udev.sh (or its friends) to wait-loop while -EBUSY is returned
by wlanctl-ng.

Perhaps it would be better though to re-order prism2sta_probe_usb to
call prism2sta_ifstate before registering the device? That way udev and
associated user-space stuff would be delayed until the device really was
ready.

I would imagine that even if you weren't trying to do a firmware upload,
the current code could give NetworkManager head-aches because it might
try controlling the device while the prism2sta_ifstate is still in
operation.

Karl
Karl Relton
2008-02-23 11:21:50 UTC
Permalink
Post by Karl Relton
[I've moved over to the devel alias]
Hi,
I have some trouble with the new (svn version 1851) wlan_wext_write
auto-enabling and loading of firmware through udev scripts. I reported
this in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465681 but I
"The firmware loading fails because when /etc/wlan/wlan-udev.sh is
run, the wlan0 interface is not available
wlanctl-ng: No such device
wlanctl-ng: No such device
prism2dl: No such device
Running it manually later works fine. I inserted a "sleep 2" on the
top of wlan-udev.sh and then it works
fine. It can seem like the udev rule 84-linux-wlan-ng runs the
wlan-udev.sh script "too early". I also stopped
network-manager to verify that it was not to blame.
However, if I echo 0 > /sys/module/p80211/parameters/wlan_wext_write,
the firmware loading works. So this
problem might be related to the new auto-enabling in the driver."
What we have here is a race condition, which is exasperated by the fact
that the drvr_start operation now has a 1000 msec sleep inserted it (to
work-around dodgy hardware etc. etc.).
- prism2sta_probe_usb is calling register_wlandev(), setting
wlandev->msdstate = WLAN_MSD_HWPRESENT
and then calling prism2sta_ifstate to do the automatic enable.
- The automatic enable is sets
wlandev->msdstate = WLAN_MSD_RUNNING_PENDING
and then calls drvr_start which will take at least 1 second due to
its enforced waiting time.
- in parallel, as a result of register_wlandev, udev will be signalled
with the 'ADD NET' which triggers the rule to call wlan-udev.sh
- wlan-udev.sh results in wlanctl-ng being called, which in turn results
in p80211req_dorequest being called.
- p80211req_dorequest tests wlandev->msdstate, and since it is not in a
'normal' state, returns with -ENODEV
So its not that the device doesn't exist, its that it is in a funny
state that p80211req_dorequest throws out with the 'no device' error
code.
The quick work-around is of course to insert a 2 second sleep into
wlan-udev.sh, as you have found.
p80211req_dorequest could be changed to return -EBUSY, the correct
status for what is happening at that point. This would still need work
in wlan-udev.sh (or its friends) to wait-loop while -EBUSY is returned
by wlanctl-ng.
Perhaps it would be better though to re-order prism2sta_probe_usb to
call prism2sta_ifstate before registering the device? That way udev and
associated user-space stuff would be delayed until the device really was
ready.
I would imagine that even if you weren't trying to do a firmware upload,
the current code could give NetworkManager head-aches because it might
try controlling the device while the prism2sta_ifstate is still in
operation.
Okay - here's a patch (for the usb driver only) that moves the
register_wlan until after the card is initialized - which solves the
race condition problem.

Note I had to hack in hfa384_usb.c a bit, to only test the netif_device
being present if the usbin packet is types HFA384x_USB_ISRXFRM or
HFA384x_USB_ISTXFRM. This is because we now may end up in this routine
before we've registered and made the netif_device present.

-->Chris/Paul - should I be testing on other types of packet too?

I've tested this on my prism2_usb card with firmware loading via
wlan-udev.sh - all is okay. I haven't tried the
no-firmware-just-let-NetworkManager-take-Control approach though.

If this patch is good a similar shuffling of code should happen for the
other types card.

Karl
Solomon Peachy
2008-02-25 15:39:23 UTC
Permalink
Post by Karl Relton
Okay - here's a patch (for the usb driver only) that moves the
register_wlan until after the card is initialized - which solves the
race condition problem.
This is the right thing to do -- the register_wlandev() call should be
the very last thing performed. I've applied the first part of your
patch to the USB code, and mirrored the changes to the PLX/PCI/CS code.
Post by Karl Relton
Note I had to hack in hfa384_usb.c a bit, to only test the netif_device
being present if the usbin packet is types HFA384x_USB_ISRXFRM or
HFA384x_USB_ISTXFRM. This is because we now may end up in this routine
before we've registered and made the netif_device present.
We won't get an RXFRM or TXFRM if we haven't programmed anything into
the card -- which can't happen until after the netif_device is present.

So, I've dropped the changes you made to hfa384x_usb.c.

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-02-26 17:47:19 UTC
Permalink
Post by Solomon Peachy
Post by Karl Relton
Okay - here's a patch (for the usb driver only) that moves the
register_wlan until after the card is initialized - which solves the
race condition problem.
This is the right thing to do -- the register_wlandev() call should be
the very last thing performed. I've applied the first part of your
patch to the USB code, and mirrored the changes to the PLX/PCI/CS code.
Thanks for doing the mirroring work.
Post by Solomon Peachy
Post by Karl Relton
Note I had to hack in hfa384_usb.c a bit, to only test the netif_device
being present if the usbin packet is types HFA384x_USB_ISRXFRM or
HFA384x_USB_ISTXFRM. This is because we now may end up in this routine
before we've registered and made the netif_device present.
We won't get an RXFRM or TXFRM if we haven't programmed anything into
the card -- which can't happen until after the netif_device is present.
So, I've dropped the changes you made to hfa384x_usb.c.
Dropping the hfa384x_usb.c change wont work. The original code for
hfa384x_usb has the test for netif_device being present right at the top
of the usbin callback. This means that when we are doing those first
couple of ctlx messages to set ifstate=enable (ahead of register_wlan)
this test will fail, so the usbin ctlx msgs returns are dropped (and
thus cmd_initialise() returns a failure status, reporting error messages
to syslog).

So we need usbin to allow some types of msg even when there is no
netif_device present ... hence my change. I figured that the two msg
types that really mattered were the RXFRM & TXFRM - hence the patch
moves the test to those types.

Of course alternatively one could dispense with the netif_device test
altogether (I couldn't find any similar test for the non-usb types of
card).

Karl
Solomon Peachy
2008-02-26 18:35:30 UTC
Permalink
Post by Karl Relton
Thanks for doing the mirroring work.
It's worth mentioning that I didn't apply the exact patch -- the
register_wlan is now the last thing to happen before ifstate_enable() is
called.

Another thing to keep in mind is that ifstate_enable() won't succeed on
some prism3 (pcmcia/usb) hardware because they *require* a firmare
download.
Post by Karl Relton
Of course alternatively one could dispense with the netif_device test
altogether (I couldn't find any similar test for the non-usb types of
card).
Yeah, I think the test can simply go away altogether, replaced with a
test against wlandev->hwremoved.

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-02-26 21:39:29 UTC
Permalink
Post by Solomon Peachy
It's worth mentioning that I didn't apply the exact patch -- the
register_wlan is now the last thing to happen before ifstate_enable() is
called.
Solomon

Your alteration misses the point! The ifstate_enable needs to happen
before the register_wlan ... otherwise we will still have the same
timing issue.

So as it stands things are still broken.
Post by Solomon Peachy
Post by Karl Relton
Of course alternatively one could dispense with the netif_device test
altogether (I couldn't find any similar test for the non-usb types of
card).
Yeah, I think the test can simply go away altogether, replaced with a
test against wlandev->hwremoved.
Great thanks.

Karl
Solomon Peachy
2008-02-26 22:31:48 UTC
Permalink
Post by Karl Relton
Your alteration misses the point! The ifstate_enable needs to happen
before the register_wlan ... otherwise we will still have the same
timing issue.
... yes and no -- It's happening after the corereset, which is also a
major source of delay. At least on non-usb targets, assuming that it
hasn't been overridden.
Post by Karl Relton
So as it stands things are still broken.
Yeah, I see that, but with the patch they're still broken; only
differently. The ifstate_enable isn't guaranteed to succeed, so
at netdev_register, the hardware is still in an unknown state.

From my perspective, wlan-udev.sh should do nothing if we're in
wlan_wext_write=1 mode and the hardware is initialized. These days the
only real reason to do anything is if the user explicitly wants to do a
firmware load, and that will screw with NetworkManager or other apps
anyway.

Of course, the RightWay(tm) to solve all of these problems is to push
the firmware loading/plugging into the kernel, so we can use the hotplug
firmware loader and have everything up and running before we call
register_netdevice().

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-02-28 19:25:31 UTC
Permalink
Post by Solomon Peachy
Post by Karl Relton
Your alteration misses the point! The ifstate_enable needs to happen
before the register_wlan ... otherwise we will still have the same
timing issue.
... yes and no -- It's happening after the corereset, which is also a
major source of delay. At least on non-usb targets, assuming that it
hasn't been overridden.
Post by Karl Relton
So as it stands things are still broken.
Yeah, I see that, but with the patch they're still broken; only
differently. The ifstate_enable isn't guaranteed to succeed, so
at netdev_register, the hardware is still in an unknown state.
Well if ifstate_enable doesn't succeed, we could even refrain from
registering the device at all! Of course that would leave the user with
no handle on which to try and bring the device up manually though, which
wouldn't be good ...
Post by Solomon Peachy
From my perspective, wlan-udev.sh should do nothing if we're in
wlan_wext_write=1 mode and the hardware is initialized. These days the
only real reason to do anything is if the user explicitly wants to do a
firmware load, and that will screw with NetworkManager or other apps
anyway.
I don't quite see things the same at this point: if wlan_wext_write=1
then wlan-udev.sh becomes just the 'firmware helper'. If
wlan_wext_write=0 then it is 'hardware initialise helper'.

I can see your point (potentially) about firmware loading messing with
NetworkManager. Hopefully Tormod might be able to help us here - I don't
use NetworkManager but I'm guessing Tormod builds test installs with
NetworkManager running.

-->Tormod: have you worked out how NetworkManager copes when the net
device is registered (so NetworkManager presumably then wants to take
the device) and yet needs to wait for wlan-udev.sh to do firmware
uploading?

[Note: it might not be a problem at all, depending on how udev works. I
think udev gets the event from the kernel, processes it and sends its
own udev-event on to things like Hal and NetworkManager. If udev doesn't
send the udev-event on until after udev has seen wlan-udev.sh complete,
then we have no problem anyway]
Post by Solomon Peachy
Of course, the RightWay(tm) to solve all of these problems is to push
the firmware loading/plugging into the kernel, so we can use the hotplug
firmware loader and have everything up and running before we call
register_netdevice().
Agreed on this. I wonder just how difficult that is - especially if it is legitimate to
still use a shell 'helper' script to do the file choice and loading. If I get some time,
I might look into how other drivers do it. However, that will take me a while, so
before then we need an interim workable solution that is basically free of race
conditions even if not totally elegant.

Cheers
Karl
Solomon Peachy
2008-02-29 18:04:04 UTC
Permalink
Post by Karl Relton
Well if ifstate_enable doesn't succeed, we could even refrain from
registering the device at all! Of course that would leave the user with
no handle on which to try and bring the device up manually though, which
wouldn't be good ...
Yeah, we need some way of communicating with the driver.
Post by Karl Relton
I don't quite see things the same at this point: if wlan_wext_write=1
then wlan-udev.sh becomes just the 'firmware helper'. If
wlan_wext_write=0 then it is 'hardware initialise helper'.
Those are actually the same thing. when wext_write=0, the key
difference is that the udev script basically is responsible for
configuring the device, not just loading the firmware.
Post by Karl Relton
[Note: it might not be a problem at all, depending on how udev works. I
think udev gets the event from the kernel, processes it and sends its
own udev-event on to things like Hal and NetworkManager. If udev doesn't
send the udev-event on until after udev has seen wlan-udev.sh complete,
then we have no problem anyway]
Indeed -- if there's a way of delaying the registration event until some
point in the future...
Post by Karl Relton
Agreed on this. I wonder just how difficult that is - especially if it
is legitimate to still use a shell 'helper' script to do the file
choice and loading. If I get some time, I might look into how other
drivers do it. However, that will take me a while, so before then we
need an interim workable solution that is basically free of race
conditions even if not totally elegant.
The way the kernel firmware loader interface is set up is that you
basically request a specific filename, and the loader hands that to the
kernel. It only deals with static files; though if you replace the
helper script it's conceivable you can make it do whatever you want.

However, there's a catch -- to upload the firmware, we need to get the
Production Data out of the card's EEPROM.

So, worst case, this is what has to happen for non-usb targets:

1) Drop into 'genesis mode'. Guess at a couple of the key PDRs (flash
type)
2) Plug with guessed PDRs and upload primary firmware.
3) Try to init the card.
4) If fail, switch to other guess and go back to (1).
5) Download actual PDR from card.
6) [re-]plug correct primary firmware, upload to card via genesis mode.
7) plug secondary firmware, upload to card.
8) issue final initilize, and we're ready.

USB targets are much simpler -- they always have primary firmware.

1) Issue reset (...and pray it works...)
2) Download PDR from card.
3) plug secondary firmware, upload to card.
4) Issue initilize, and we're ready.

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-03-06 20:32:28 UTC
Permalink
Post by Solomon Peachy
However, there's a catch -- to upload the firmware, we need to get the
Production Data out of the card's EEPROM.
1) Drop into 'genesis mode'. Guess at a couple of the key PDRs (flash
type)
2) Plug with guessed PDRs and upload primary firmware.
3) Try to init the card.
4) If fail, switch to other guess and go back to (1).
5) Download actual PDR from card.
6) [re-]plug correct primary firmware, upload to card via genesis mode.
7) plug secondary firmware, upload to card.
8) issue final initilize, and we're ready.
I don't see this sequence played out in the existing shared.prism2 shell
script code. But then I might be missing something.
Post by Solomon Peachy
USB targets are much simpler -- they always have primary firmware.
1) Issue reset (...and pray it works...)
2) Download PDR from card.
3) plug secondary firmware, upload to card.
4) Issue initilize, and we're ready.
Yep - I could have a go at coding the USB case sometime.
Richard Kennedy
2008-03-12 14:08:26 UTC
Permalink
Hi Karl,

The latest svn with this auto enable doesn't work very well with
network_manager, at least for me anyway.

It's ok on boot, but if I unload/load the module the network interface
never gets brought up. The firmware is loaded ok but nothing else
happens. I guess it's some sort of timing issue, or maybe just the
driver state getting confused.

I added this patch so I can turn off the auto enable.
Adding p80211 wlan_auto_enable=0 to /etc/modprobe.conf makes it all work
as I expect.

However I'm not sure if this is the right approach,so I'll see if I can
work out why the net interface never comes up.

cheers
Richard

diff --git a/src/include/wlan/p80211netdev.h b/src/include/wlan/p80211netdev.h
index 3e23102..58b074d 100644
--- a/src/include/wlan/p80211netdev.h
+++ b/src/include/wlan/p80211netdev.h
@@ -173,6 +173,7 @@ int p80211wext_event_associated(struct wlandevice *wlandev, int assoc);

extern int wlan_watchdog;
extern int wlan_wext_write;
+extern int wlan_auto_enable;

/* WLAN device type */
typedef struct wlandevice
diff --git a/src/p80211/p80211mod.c b/src/p80211/p80211mod.c
index 130a0de..1fd51c1 100644
--- a/src/p80211/p80211mod.c
+++ b/src/p80211/p80211mod.c
@@ -115,6 +115,11 @@ module_param(wlan_wext_write, int, 0644);
MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions");
#endif

+int wlan_auto_enable = 1;
+module_param(wlan_auto_enable,int,0644);
+MODULE_PARM_DESC(wlan_auto_enable, "auto enable card");
+
+
#ifdef WLAN_INCLUDE_DEBUG
int wlan_debug=0;
module_param(wlan_debug, int, 0644);
@@ -216,3 +221,4 @@ EXPORT_SYMBOL(p80211skb_rxmeta_attach);
EXPORT_SYMBOL(p80211wext_event_associated);

EXPORT_SYMBOL(wlan_wext_write);
+EXPORT_SYMBOL(wlan_auto_enable);
diff --git a/src/prism2/driver/prism2_usb.c b/src/prism2/driver/prism2_usb.c
index b250250..8d5d588 100644
--- a/src/prism2/driver/prism2_usb.c
+++ b/src/prism2/driver/prism2_usb.c
@@ -167,7 +167,7 @@ static int prism2sta_probe_usb(
goto failed;
}

- if (wlan_wext_write)
+ if (wlan_wext_write && wlan_auto_enable)
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);

goto done;
Post by Karl Relton
Post by Solomon Peachy
Post by Karl Relton
Your alteration misses the point! The ifstate_enable needs to happen
before the register_wlan ... otherwise we will still have the same
timing issue.
... yes and no -- It's happening after the corereset, which is also a
major source of delay. At least on non-usb targets, assuming that it
hasn't been overridden.
Post by Karl Relton
So as it stands things are still broken.
Yeah, I see that, but with the patch they're still broken; only
differently. The ifstate_enable isn't guaranteed to succeed, so
at netdev_register, the hardware is still in an unknown state.
Well if ifstate_enable doesn't succeed, we could even refrain from
registering the device at all! Of course that would leave the user with
no handle on which to try and bring the device up manually though, which
wouldn't be good ...
Post by Solomon Peachy
From my perspective, wlan-udev.sh should do nothing if we're in
wlan_wext_write=1 mode and the hardware is initialized. These days the
only real reason to do anything is if the user explicitly wants to do a
firmware load, and that will screw with NetworkManager or other apps
anyway.
I don't quite see things the same at this point: if wlan_wext_write=1
then wlan-udev.sh becomes just the 'firmware helper'. If
wlan_wext_write=0 then it is 'hardware initialise helper'.
I can see your point (potentially) about firmware loading messing with
NetworkManager. Hopefully Tormod might be able to help us here - I don't
use NetworkManager but I'm guessing Tormod builds test installs with
NetworkManager running.
-->Tormod: have you worked out how NetworkManager copes when the net
device is registered (so NetworkManager presumably then wants to take
the device) and yet needs to wait for wlan-udev.sh to do firmware
uploading?
[Note: it might not be a problem at all, depending on how udev works. I
think udev gets the event from the kernel, processes it and sends its
own udev-event on to things like Hal and NetworkManager. If udev doesn't
send the udev-event on until after udev has seen wlan-udev.sh complete,
then we have no problem anyway]
Post by Solomon Peachy
Of course, the RightWay(tm) to solve all of these problems is to push
the firmware loading/plugging into the kernel, so we can use the hotplug
firmware loader and have everything up and running before we call
register_netdevice().
Agreed on this. I wonder just how difficult that is - especially if it is legitimate to
still use a shell 'helper' script to do the file choice and loading. If I get some time,
I might look into how other drivers do it. However, that will take me a while, so
before then we need an interim workable solution that is basically free of race
conditions even if not totally elegant.
Cheers
Karl
_______________________________________________
Linux-wlan-devel mailing list
http://lists.linux-wlan.com/mailman/listinfo/linux-wlan-devel
Karl Relton
2008-03-12 20:37:45 UTC
Permalink
Post by Richard Kennedy
Hi Karl,
The latest svn with this auto enable doesn't work very well with
network_manager, at least for me anyway.
It's ok on boot, but if I unload/load the module the network interface
never gets brought up. The firmware is loaded ok but nothing else
happens. I guess it's some sort of timing issue, or maybe just the
driver state getting confused.
I added this patch so I can turn off the auto enable.
Adding p80211 wlan_auto_enable=0 to /etc/modprobe.conf makes it all work
as I expect.
However I'm not sure if this is the right approach,so I'll see if I can
work out why the net interface never comes up.
cheers
Richard
Hi Richard

The code in svn isn't how I would prefer it - it has the register_netdev
before the card is first initialised. I would do it the other way round.
Solomon has his reasons for the way it currently is, but it does leave
us with potentially bad side effects at the moment.

I'm surprised things are working well for you on boot up. Have you
checked your log to see that firmware is actually being loaded on boot
(e.g. in your syslog can you see the firmware version that you would
expect?). With the current code, my suspicion is that firmware load on
boot is doomed to fail, unless you have some sleep statement(s)
somewhere in your wlan-udev.sh/shared/shared.prism2 scripts.

A module unload/reload should result in the same process, since the
driver sees the hardware afresh and goes through the same sequence.
Similarly networkmanager ought to have forgot about the interface and
then pick it up again (but I've never really used it myself).

Karl
Tormod Volden
2008-03-12 21:41:05 UTC
Permalink
On Wed, Mar 12, 2008 at 9:37 PM, Karl Relton
Post by Karl Relton
I'm surprised things are working well for you on boot up. Have you
checked your log to see that firmware is actually being loaded on boot
(e.g. in your syslog can you see the firmware version that you would
expect?). With the current code, my suspicion is that firmware load on
boot is doomed to fail, unless you have some sleep statement(s)
somewhere in your wlan-udev.sh/shared/shared.prism2 scripts.
A module unload/reload should result in the same process, since the
driver sees the hardware afresh and goes through the same sequence.
Similarly networkmanager ought to have forgot about the interface and
then pick it up again (but I've never really used it myself).
Sorry for not following up on this thread for a while. On Debian with
v1854, firmware loading works at boot, also without any "sleep". After
an unplug/replug, the firmware is not loaded, only if I also unload
the modules or if I add a "sleep 2" to wlan-udev.sh. So I guess the
"reason" it works at boot is that the modules are not already loaded.

The above is true also with network-manager started. N-m also seems to
bring up the card (and list available networks) faster when using the
"sleep", maybe it otherwise sees the card is not ready initially but
tries again later.

Hope this makes sense (I had to rewrite it a couple of times),
Tormod
Richard Kennedy
2008-03-13 17:46:23 UTC
Permalink
Post by Karl Relton
Post by Richard Kennedy
Hi Karl,
The latest svn with this auto enable doesn't work very well with
network_manager, at least for me anyway.
It's ok on boot, but if I unload/load the module the network interface
never gets brought up. The firmware is loaded ok but nothing else
happens. I guess it's some sort of timing issue, or maybe just the
driver state getting confused.
I added this patch so I can turn off the auto enable.
Adding p80211 wlan_auto_enable=0 to /etc/modprobe.conf makes it all work
as I expect.
However I'm not sure if this is the right approach,so I'll see if I can
work out why the net interface never comes up.
cheers
Richard
Hi Richard
The code in svn isn't how I would prefer it - it has the register_netdev
before the card is first initialised. I would do it the other way round.
Solomon has his reasons for the way it currently is, but it does leave
us with potentially bad side effects at the moment.
I'm surprised things are working well for you on boot up. Have you
checked your log to see that firmware is actually being loaded on boot
(e.g. in your syslog can you see the firmware version that you would
expect?). With the current code, my suspicion is that firmware load on
boot is doomed to fail, unless you have some sleep statement(s)
somewhere in your wlan-udev.sh/shared/shared.prism2 scripts.
A module unload/reload should result in the same process, since the
driver sees the hardware afresh and goes through the same sequence.
Similarly networkmanager ought to have forgot about the interface and
then pick it up again (but I've never really used it myself).
Karl
Hi Karl,

I checked and the firmware _does_ get loaded properly at boot time, but
it fails on unload/reload! I guess it's just luck that udev is kind of
late to startup so the usb card is settled before it starts loading the
firmware.

Also Networkmanager doesn't do much during boot either, because it has
to wait for the user to log on to get the WEP keys from the default
keyring. In the reload case NM starts trying to setup the card
immediately which I think might break things too -- as there is nothing
to stop the WEXT functions if the card's not ready.

Maybe all(?) the WEXT functions should include a check something like
this?

if ( wlandev->msdstate != WLAN_MSD_RUNNING ) return -EBUSY;

disabling the auto enable works for me though :)

Richard
Solomon Peachy
2008-03-14 13:04:30 UTC
Permalink
Post by Richard Kennedy
Maybe all(?) the WEXT functions should include a check something like
this?
if ( wlandev->msdstate != WLAN_MSD_RUNNING ) return -EBUSY;
I think this is a good idea. Is -EBUSY correct, or would -ENODEV be
better?

- Solomon.
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-03-24 11:10:09 UTC
Permalink
Post by Tormod Volden
Sorry for not following up on this thread for a while. On Debian with
v1854, firmware loading works at boot, also without any "sleep". After
an unplug/replug, the firmware is not loaded, only if I also unload
the modules or if I add a "sleep 2" to wlan-udev.sh. So I guess the
"reason" it works at boot is that the modules are not already loaded.
I checked and the firmware _does_ get loaded properly at boot time, but
it fails on unload/reload! I guess it's just luck that udev is kind of
late to startup so the usb card is settled before it starts loading the
firmware.
I've done some of my own tests to confirm your results. Basically
wlan-udev.sh is being called at different points in the overall
sequence, depending on whether it is a 'cold' or 'warm' start. I'm not
sure why there is the difference - perhaps something in udev. If it is
something in udev, then on a 'cold' start it is working in our favour
'by chance' rather by design.

Since the 'correct' fix is to move firmware loading into the driver,
which is non-trivial, perhaps a work-around would be put a loop test in
wlan-udev.sh to wait for the card to become ready.

I'll do some more tests to think on that idea.

Karl
Richard Kennedy
2008-03-24 14:03:23 UTC
Permalink
Post by Karl Relton
Post by Tormod Volden
Sorry for not following up on this thread for a while. On Debian with
v1854, firmware loading works at boot, also without any "sleep". After
an unplug/replug, the firmware is not loaded, only if I also unload
the modules or if I add a "sleep 2" to wlan-udev.sh. So I guess the
"reason" it works at boot is that the modules are not already loaded.
I checked and the firmware _does_ get loaded properly at boot time, but
it fails on unload/reload! I guess it's just luck that udev is kind of
late to startup so the usb card is settled before it starts loading the
firmware.
I've done some of my own tests to confirm your results. Basically
wlan-udev.sh is being called at different points in the overall
sequence, depending on whether it is a 'cold' or 'warm' start. I'm not
sure why there is the difference - perhaps something in udev. If it is
something in udev, then on a 'cold' start it is working in our favour
'by chance' rather by design.
Yes, the usb discovery happens really early (at least on my laptop) and
I think it's just luck that the probe routine has finished before udev
starts trying to load the firmware.
Post by Karl Relton
Since the 'correct' fix is to move firmware loading into the driver,
which is non-trivial, perhaps a work-around would be put a loop test in
wlan-udev.sh to wait for the card to become ready.
I'll do some more tests to think on that idea.
Karl
What about this patch? It adds a mutex to protect the ioctl calls and
holds it locked until the init routine has finished.

It works for me, but it's only had minimal testing.

But it works for both the cold boot and reload cases and we don't have
to add any delays into the scripts. It should just work, and hold up any
user space processes until prism2sta_probe_usb has finished.
It also means that you can't run 2 ioctls at the same time, which I
think is a good thing :)

BTW -- it will only work on usb devices -- I haven't fixed up the others
to release the ioctl mutex so it will probably lock up on them!!

Richard

diff --git a/src/include/wlan/p80211netdev.h
b/src/include/wlan/p80211netdev.h
index 3e23102..b6e683d 100644
--- a/src/include/wlan/p80211netdev.h
+++ b/src/include/wlan/p80211netdev.h
@@ -257,6 +257,7 @@ typedef struct wlandevice

#endif

+ struct mutex ioctl_lock;
} wlandevice_t;

/* WEP stuff */
@@ -281,6 +282,8 @@ void p80211netdev_hwremoved(wlandevice_t *wlandev);
void p80211_suspend(wlandevice_t *wlandev);
void p80211_resume(wlandevice_t *wlandev);

+void p80211_allow_ioctls(wlandevice_t *wlandev);
+
/*================================================================*/
/* Function Definitions */

diff --git a/src/p80211/p80211mod.c b/src/p80211/p80211mod.c
index 130a0de..f356a66 100644
--- a/src/p80211/p80211mod.c
+++ b/src/p80211/p80211mod.c
@@ -216,3 +216,4 @@ EXPORT_SYMBOL(p80211skb_rxmeta_attach);
EXPORT_SYMBOL(p80211wext_event_associated);

EXPORT_SYMBOL(wlan_wext_write);
+EXPORT_SYMBOL(p80211_allow_ioctls);
diff --git a/src/p80211/p80211netdev.c b/src/p80211/p80211netdev.c
index 9c40038..78f93b0 100644
--- a/src/p80211/p80211netdev.c
+++ b/src/p80211/p80211netdev.c
@@ -702,6 +702,7 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev,
struct ifreq *ifr, int cmd)

WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len);

+ mutex_lock(&wlandev->ioctl_lock);
#if WIRELESS_EXT < 13
/* Is this a wireless extensions ioctl? */
if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
@@ -751,6 +752,8 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev,
struct ifreq *ifr, int cmd)
result = -ENOMEM;
}
bail:
+ mutex_unlock(&wlandev->ioctl_lock);
+
DBFEXIT;

return result; /* If allocate,copyfrom or copyto fails, return errno
*/
@@ -920,6 +923,11 @@ int wlan_setup(wlandevice_t *wlandev)
dev->priv = wlandev;
dev->hard_start_xmit = p80211knetdev_hard_start_xmit;
dev->get_stats = p80211knetdev_get_stats;
+
+ mutex_init(&wlandev->ioctl_lock);
+ /* block ioctls until fully initialised. Don't forget to call
allow_ioctls at some point!*/
+ mutex_lock(&wlandev->ioctl_lock);
+
#ifdef HAVE_PRIVATE_IOCTL
dev->do_ioctl = p80211knetdev_do_ioctl;
#endif
@@ -1519,3 +1527,7 @@ static void p80211knetdev_tx_timeout( netdevice_t
*netdev)

DBFEXIT;
}
+
+void p80211_allow_ioctls(wlandevice_t *wlandev) {
+ mutex_unlock(&wlandev->ioctl_lock);
+}
diff --git a/src/prism2/driver/prism2_usb.c
b/src/prism2/driver/prism2_usb.c
index b250250..fe051ed 100644
--- a/src/prism2/driver/prism2_usb.c
+++ b/src/prism2/driver/prism2_usb.c
@@ -180,6 +180,7 @@ static int prism2sta_probe_usb(
done:
DBFEXIT;

+ p80211_allow_ioctls(wlandev);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
return wlandev;
#else
Solomon Peachy
2008-03-24 14:37:47 UTC
Permalink
Post by Richard Kennedy
What about this patch? It adds a mutex to protect the ioctl calls and
holds it locked until the init routine has finished.
There used to be a semaphore on ioctl calls many moons ago, but it was
removed for some reason or another.

The mutex idea is sound, and the patch looks good, and it shouldn't
break anything.

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-03-24 16:31:30 UTC
Permalink
Post by Solomon Peachy
Post by Richard Kennedy
What about this patch? It adds a mutex to protect the ioctl calls and
holds it locked until the init routine has finished.
There used to be a semaphore on ioctl calls many moons ago, but it was
removed for some reason or another.
The mutex idea is sound, and the patch looks good, and it shouldn't
break anything.
- Solomon
Good work Richard. I've applied it on my Ubuntu system and it works as
you suggest - nicely holding off any userspace stuff until the card is
ready. Both cold & warm starts are now good for me too. So this patch
looks good to me.

Also it should help with NetworkManager. I was right about udev not
'sending on' the event to Hal & NetworkManager (and whoever else) until
after wlan-udev.sh is run. So with your patch applied, the effect is
that NetworkManager does not get notified of the new network device
until after the firmware is loaded. Thus NetworkManager should not start
dabbling until card is good & ready with its firmware in place.

Karl
Richard Kennedy
2008-03-25 14:13:43 UTC
Permalink
Post by Solomon Peachy
Post by Richard Kennedy
What about this patch? It adds a mutex to protect the ioctl calls and
holds it locked until the init routine has finished.
There used to be a semaphore on ioctl calls many moons ago, but it was
removed for some reason or another.
The mutex idea is sound, and the patch looks good, and it shouldn't
break anything.
- Solomon
Hi Solomon,

As a follow, on here's a quick patch to add allow_ioctls to the probe
methods of other card types. NOT TESTED!

Cheers
Richard

diff --git a/src/prism2/driver/prism2_cs.c b/src/prism2/driver/prism2_cs.c
index 6f3d9fb..6bec478 100644
--- a/src/prism2/driver/prism2_cs.c
+++ b/src/prism2/driver/prism2_cs.c
@@ -579,7 +579,7 @@ static int prism2_cs_probe(struct pcmcia_device *pdev)

if (wlan_wext_write)
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);
-
+ p80211_allow_ioctls(wlandev);
goto done;

cs_failed:
diff --git a/src/prism2/driver/prism2_pci.c b/src/prism2/driver/prism2_pci.c
index 476bda2..3ee39bf 100644
--- a/src/prism2/driver/prism2_pci.c
+++ b/src/prism2/driver/prism2_pci.c
@@ -169,6 +169,7 @@ prism2sta_probe_pci(

if (wlan_wext_write)
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);
+ p80211_allow_ioctls(wlandev);

result = 0;
goto done;
diff --git a/src/prism2/driver/prism2_plx.c b/src/prism2/driver/prism2_plx.c
index b57a3f1..b97340f 100644
--- a/src/prism2/driver/prism2_plx.c
+++ b/src/prism2/driver/prism2_plx.c
@@ -278,6 +278,7 @@ prism2sta_probe_plx(

if (wlan_wext_write)
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable);
+ p80211_allow_ioctls(wlandev);

result = 0;
goto done;
Solomon Peachy
2008-03-25 18:25:59 UTC
Permalink
Post by Richard Kennedy
As a follow, on here's a quick patch to add allow_ioctls to the probe
methods of other card types. NOT TESTED!
I've already applied something similar to svn.

- Solomon
--
Solomon Peachy ***@linux-wlan.com
AbsoluteValue Systems http://www.linux-wlan.com
721-D North Drive +1 (321) 259-0737 (office)
Melbourne, FL 32934 +1 (321) 259-0286 (fax)
Karl Relton
2008-03-24 16:22:03 UTC
Permalink
Post by Richard Kennedy
Yes, the usb discovery happens really early (at least on my laptop) and
I think it's just luck that the probe routine has finished before udev
starts trying to load the firmware.
But most systems will rely on udev to do the modprobe of prism2_usb in
the first place - so its not that udev is starting late. It just seems
some peculiar behaviour in udev.
Loading...