On Wed, 2010-10-27 at 15:20 +0100, Daniel Drake wrote: > From: Paul Fox <pgf@xxxxxxxxxx> > > For the SD8686, we cannot rely on the scratch register to read the firmware > load status, because the same register is used for storing RX packet length. > Broaden the check to account for this. > > The module can now be unloaded/reloaded successfully. > > Based on the implementation from libertas_tf. > > Signed-off-by: Daniel Drake <dsd@xxxxxxxxxx> Acked-by: Dan Williams <dcbw@xxxxxxxxxx> > --- > drivers/net/wireless/libertas/if_sdio.c | 32 ++++++++++++++++++++++++++++-- > 1 files changed, 29 insertions(+), 3 deletions(-) > > v2: rebase on latest pull to overcome a trivial conflict generated by another > recent change > > diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c > index 296fd00..f41a5ab 100644 > --- a/drivers/net/wireless/libertas/if_sdio.c > +++ b/drivers/net/wireless/libertas/if_sdio.c > @@ -684,18 +684,40 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) > > lbs_deb_enter(LBS_DEB_SDIO); > > + /* > + * Disable interrupts > + */ > + sdio_claim_host(card->func); > + sdio_writeb(card->func, 0x00, IF_SDIO_H_INT_MASK, &ret); > + sdio_release_host(card->func); > + > sdio_claim_host(card->func); > scratch = if_sdio_read_scratch(card, &ret); > sdio_release_host(card->func); > > + lbs_deb_sdio("firmware status = %#x\n", scratch); > + lbs_deb_sdio("scratch ret = %d\n", ret); > + > if (ret) > goto out; > > - lbs_deb_sdio("firmware status = %#x\n", scratch); > > + /* > + * The manual clearly describes that FEDC is the right code to use > + * to detect firmware presence, but for SD8686 it is not that simple. > + * Scratch is also used to store the RX packet length, so we lose > + * the FEDC value early on. So we use a non-zero check in order > + * to validate firmware presence. > + * Additionally, the SD8686 in the Gumstix always has the high scratch > + * bit set, even when the firmware is not loaded. So we have to > + * exclude that from the test. > + */ > if (scratch == IF_SDIO_FIRMWARE_OK) { > lbs_deb_sdio("firmware already loaded\n"); > goto success; > + } else if ((card->model == IF_SDIO_MODEL_8686) && (scratch & 0x7fff)) { > + lbs_deb_sdio("firmware may be running\n"); > + goto success; > } > > ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, > @@ -709,10 +731,14 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) > if (ret) > goto out; > > + lbs_deb_sdio("Helper firmware loaded\n"); > + > ret = if_sdio_prog_real(card, mainfw); > if (ret) > goto out; > > + lbs_deb_sdio("Firmware loaded\n"); > + > success: > sdio_claim_host(card->func); > sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); > @@ -1042,8 +1068,6 @@ static int if_sdio_probe(struct sdio_func *func, > priv->exit_deep_sleep = if_sdio_exit_deep_sleep; > priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; > > - priv->fw_ready = 1; > - > sdio_claim_host(func); > > /* > @@ -1064,6 +1088,8 @@ static int if_sdio_probe(struct sdio_func *func, > if (ret) > goto reclaim; > > + priv->fw_ready = 1; > + > /* > * FUNC_INIT is required for SD8688 WLAN/BT multiple functions > */ -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html