rmmod libertas_sdio and reinsert causes problems with firmware upload.

Jonathan Cameron jic23 at cam.ac.uk
Mon Sep 1 11:24:18 EDT 2008

Dear All, 

I've had a go at following the approach used in if_usb (reset function tried
when firmware initially fails to load.

The function I ended up with is below, but the problem is that the device
seems to end up completely stalled and I can't read the scratch pad without
getting a time out.

Anyone have any suggestions on where I'm going wrong.  As I'm not particularly
familiar with either the libertas code or sdio, it's probably full of bugs!



static int if_sdio_reset_device(struct if_sdio_card *card)
	int ret;
	u8 status;
	struct cmd_ds_command cmd;
	struct if_sdio_packet *packet;
	/* number of bytes in command */
	int nb = S_DS_GEN;
	int size = sdio_align_size(card->func, nb+4);
	printk("Trying to reset the device \n");
	cmd.command = cpu_to_le16(CMD_802_11_RESET);
	cmd.size = cpu_to_le16(S_DS_GEN);
	cmd.result = cpu_to_le16(0);
	cmd.seqnum = cpu_to_le16(0x5a5a);
	//cmd.params.reset.action = cpu_to_le16(CMD_ACT_HALT);

	packet = kzalloc(sizeof(struct if_sdio_packet) +  size, GFP_KERNEL);
	if (!packet) {
		return -ENOMEM;
	packet->next = NULL;
	packet->nb =  size;
	packet->buffer[0] = (nb + 4)&0xff;
	packet->buffer[1] = ((nb + 4) >> 8) & 0xff;
	packet->buffer[2] = MVMS_CMD;
	packet->buffer[3] = 0;
	memcpy(packet->buffer + 4, &cmd, nb);

	printk("claimed card\n");
	while (1) {
		status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
		if (ret)
			goto release;
		if (status & IF_SDIO_IO_RDY)
	ret = sdio_writesb(card->func, card->ioport,
			   packet->buffer, packet->nb);
	if (ret)
	printk("I think I've reset the card by here?\n");

	return ret;

Jonathan Cameron wrote:
> Dear All,
> So procedure is:
> Insert the boards spi host driver and libertas_sdio which
> works fine.
> Next remove libertas_sdio.
> Reinsert libertas_sdio and watch the firmware load fail.
> (using 2.6.27-rc4)
> Firstly I'll admit this a fairly odd circumstance to be in, but technically
> this should be a valid thing to do. 
> The problem lies in the fact that the scratch register is used all over
> the place by the device so unsuprisingly doesn't contain the firmware
> upload succeeded flag and hence tries to load firmware into a device on
> which it is already running causing the driver insertion to fail.
> So question is, what would be the correct fix? 
> I'm not terribly familiar with the sdio subsystem, but I assume it's possible
> to tell whether a remove is due to driver removal or device removal.  If it's
> the driver, then issuing a CMD_802_11_RESET will apparently reset to the extent
> of needing a new firmware load - hence putting our device minus driver back
> to the state it was in before the driver was loaded.
> Another option would be to fudge the test for whether the firmware has already
> loaded to allow for values other than the correct one, though I guess it's
> possible the scratch register can contain zero with firmware loaded as well
> as on startup so that's not ideal.
> Please cc me in to replies as I'm not on libertas-dev...
> --
> Jonathan Cameron

More information about the libertas-dev mailing list