From patchwork Wed Oct 13 19:14:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Drake X-Patchwork-Id: 251291 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9DK2hed031621 for ; Wed, 13 Oct 2010 20:02:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752252Ab0JMUCg (ORCPT ); Wed, 13 Oct 2010 16:02:36 -0400 Received: from queueout02-winn.ispmail.ntl.com ([81.103.221.56]:64635 "EHLO queueout02-winn.ispmail.ntl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751524Ab0JMUCg (ORCPT ); Wed, 13 Oct 2010 16:02:36 -0400 Received: from aamtaout01-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20101013191408.JMZO3266.mtaout01-winn.ispmail.ntl.com@aamtaout01-winn.ispmail.ntl.com>; Wed, 13 Oct 2010 20:14:08 +0100 Received: from zog.reactivated.net ([86.14.215.141]) by aamtaout01-winn.ispmail.ntl.com (InterMail vG.3.00.04.00 201-2196-133-20080908) with ESMTP id <20101013191408.LWMI20122.aamtaout01-winn.ispmail.ntl.com@zog.reactivated.net>; Wed, 13 Oct 2010 20:14:08 +0100 Received: by zog.reactivated.net (Postfix, from userid 1000) id 7C6ED9D401B; Wed, 13 Oct 2010 20:14:02 +0100 (BST) From: Daniel Drake To: linville@tuxdriver.com Cc: linux-wireless@vger.kernel.org Cc: libertas-dev@lists.infradead.org Cc: dcbw@redhat.com Cc: pgf@laptop.org Cc: steve@cozybit.com Subject: [PATCH] libertas: Fix sd8686 firmware reload Message-Id: <20101013191402.7C6ED9D401B@zog.reactivated.net> Date: Wed, 13 Oct 2010 20:14:02 +0100 (BST) X-Cloudmark-Analysis: v=1.1 cv=3ENABmdyEd/Fm7fR7+mZIuMDn6+IErAeEhlfWBImZFk= c=1 sm=0 a=z0aN0FV-YSIA:10 a=Op-mwl0xAAAA:8 a=cwjyRg38cRQ49DGfQfgA:9 a=BsQ8LkI9ILmtkTYFAFwA:7 a=5ajgoqXzSZEmvf3nT0OQnu5ox3YA:4 a=d4CUUju0HPYA:10 a=Yh-N9J8lMPraaShT:21 a=xf6WcZWJqyQ77y_g:21 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 13 Oct 2010 20:02:45 +0000 (UTC) diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 87b6349..d2e5193 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -704,28 +704,54 @@ 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 = if_sdio_prog_helper(card); if (ret) goto out; + lbs_deb_sdio("Helper firmware loaded\n"); + ret = if_sdio_prog_real(card); 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); @@ -1083,8 +1109,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); /* @@ -1105,6 +1129,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 */