From patchwork Wed Oct 27 14:20:52 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Drake X-Patchwork-Id: 285862 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 o9REL2PY027313 for ; Wed, 27 Oct 2010 14:21:02 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756890Ab0J0OVB (ORCPT ); Wed, 27 Oct 2010 10:21:01 -0400 Received: from mtaout02-winn.ispmail.ntl.com ([81.103.221.48]:5881 "EHLO mtaout02-winn.ispmail.ntl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755177Ab0J0OVA (ORCPT ); Wed, 27 Oct 2010 10:21:00 -0400 Received: from aamtaout04-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout02-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20101027142054.EGEH7723.mtaout02-winn.ispmail.ntl.com@aamtaout04-winn.ispmail.ntl.com>; Wed, 27 Oct 2010 15:20:54 +0100 Received: from zog.reactivated.net ([86.14.215.141]) by aamtaout04-winn.ispmail.ntl.com (InterMail vG.3.00.04.00 201-2196-133-20080908) with ESMTP id <20101027142054.EVZM25656.aamtaout04-winn.ispmail.ntl.com@zog.reactivated.net>; Wed, 27 Oct 2010 15:20:54 +0100 Received: by zog.reactivated.net (Postfix, from userid 1000) id 9607A9D401B; Wed, 27 Oct 2010 15:20:52 +0100 (BST) From: Daniel Drake To: linville@tuxdriver.com Cc: linux-wireless@vger.kernel.org Cc: dcbw@redhat.com Cc: libertas-dev@lists.infradead.org Cc: pgf@laptop.org Subject: [PATCH v2] libertas: Fix sd8686 firmware reload Message-Id: <20101027142052.9607A9D401B@zog.reactivated.net> Date: Wed, 27 Oct 2010 15:20:52 +0100 (BST) X-Cloudmark-Analysis: v=1.1 cv=3ENABmdyEd/Fm7fR7+mZIuMDn6+IErAeEhlfWBImZFk= c=1 sm=0 a=zH_cRNeAYSQA:10 a=Op-mwl0xAAAA:8 a=qKhpMBf-pyuUNgeEgjcA:9 a=gWHC9e_Ka_I6wMtJW3AA:7 a=B0ObxHJ58DaMV9nPZZaZRXF8oekA:4 a=d4CUUju0HPYA:10 a=ppTAD0l90c20fVJE:21 a=-uT6HVo67vZ73ZZh: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, 27 Oct 2010 14:21:03 +0000 (UTC) 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 */