BUG() in if_sdio_handle_cmd()

Daniel Drake dsd at laptop.org
Wed Jan 6 09:51:34 EST 2010


Hi,

I've further investigated the crash reported here:
http://lists.infradead.org/pipermail/libertas-dev/2009-December/002917.html

The issue is triggered by the fact that sometimes, the firmware sends
event 18 (wakeup confirm) during resume. When this happens, the crash is
triggered. At times when this event is not sent, no crash happens.
So, we additionally seem to have a firmware bug on our hands, unless
this inconsistency can be explained.


As for the driver crash, what happens is that event 18 causes
lbs_send_confirmwake() to be called, which *directly* submits cmd 44
(CMD_802_11_WAKEUP_CONFIRM) to the hardware, bypassing the regular
command queuing infrastructure. It does not wait for a response.

Soon after, another command is submitted through the regular course of
the driver - usually 6 (scan) or 43 (host sleep cfg). At this point,
there are 2 commands pending.

Then both commands complete quickly within quick succession.
cmd 44 response comes in, gets saved into one of the cmd response slots.
Then before the worker thread has had a chance to process it, the
command response for the 2nd command comes in. This gets saved in the
other slot, the worker thread wakes up and processes it.

Then on the execution of the next command, the response is targetted to
be saved in the first slot, but because the unprocessed cmd 44 response
is sitting here, the BUG() is triggered.

I tried to modify lbs_send_confirmwake() to use the regular command
queuing infrastructure:

	struct cmd_header cmd;
	lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd, sizeof(cmd));

however, it looks like that event 18 requires an immediate response with
cmd44, otherwise things just stop working. And when the above code
executes, there is already another command in the queue, so the cmd44
doesn't get executed until later, and by then, the device is totally
unresponsive.


An alternative workaround, which seems to work, is simply to add the
following to the top of if_sdio_handle_command():

	if (buffer[0] == 0x44 && buffer[1] == 0x80)
		return 0;

i.e. totally ignore responses to this command.


Any thoughts?
What does the documentation say about event 18 and cmd 44?

cheers
Daniel





More information about the libertas-dev mailing list