From patchwork Wed Nov 4 21:39:46 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inaky Perez-Gonzalez X-Patchwork-Id: 37659 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id B6721B6F2B for ; Thu, 5 Nov 2009 08:44:35 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932848AbZKDVnl (ORCPT ); Wed, 4 Nov 2009 16:43:41 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932754AbZKDVmK (ORCPT ); Wed, 4 Nov 2009 16:42:10 -0500 Received: from mga06.intel.com ([134.134.136.21]:20710 "EHLO orsmga101.jf.intel.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932708AbZKDVl7 (ORCPT ); Wed, 4 Nov 2009 16:41:59 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 04 Nov 2009 13:28:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.44,682,1249282800"; d="scan'208";a="464388445" Received: from unknown (HELO localhost.localdomain) ([10.24.164.236]) by orsmga002.jf.intel.com with ESMTP; 04 Nov 2009 13:59:18 -0800 From: Inaky Perez-Gonzalez To: netdev@vger.kernel.org, wimax@linuxwimax.org Subject: [PATCH 2.6.33/2 05/15] wimax/i2400m: during probe, call sdio_disable at most once Date: Wed, 4 Nov 2009 13:39:46 -0800 Message-Id: X-Mailer: git-send-email 1.6.2.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In the Intel Wireless Multicomm 3200, the initialization is orchestrated by a component called Top. This component also monitors how many times a function is reset (via sdio_disable) to detect possible issues and will reset the whole multifunction device if any function triggers a maximum reset level. During WiMAX's probe, the driver needs to wait for Top to come up before it can enable the WiMAX function. If it cannot, it will return -ENODEV and the Top driver will rescan the SDIO bus once done loading. Currently, the WiMAX SDIO probe routine was trying a few times before returning -ENODEV, and this was triggering Top's too-many-resets detector. This is, in any case, unnecessary because the Top driver will force the bus rescan when the functions can be probed successfully. Added then a maxtries argument to i2400ms_enable_func() and set it to 1 when calling from probe. We want to reuse this function instead of flat calling out sdio_enable_func() to take advantage of hardware quirk workarounds. Reported-by: Cindy H Kao Signed-off-by: Inaky Perez-Gonzalez --- drivers/net/wimax/i2400m/sdio.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 9d6046f..7c1b843 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c @@ -95,17 +95,23 @@ static const struct i2400m_poke_table i2400ms_pokes[] = { * when we ask it to explicitly doing). Tries until a timeout is * reached. * + * The @maxtries argument indicates how many times (at most) it should + * be tried to enable the function. 0 means forever. This acts along + * with the timeout (ie: it'll stop trying as soon as the maximum + * number of tries is reached _or_ as soon as the timeout is reached). + * * The reverse of this is...sdio_disable_function() * * Returns: 0 if the SDIO function was enabled, < 0 errno code on * error (-ENODEV when it was unable to enable the function). */ static -int i2400ms_enable_function(struct sdio_func *func) +int i2400ms_enable_function(struct sdio_func *func, unsigned maxtries) { u64 timeout; int err; struct device *dev = &func->dev; + unsigned tries = 0; d_fnstart(3, dev, "(func %p)\n", func); /* Setup timeout (FIXME: This needs to read the CIS table to @@ -131,6 +137,10 @@ int i2400ms_enable_function(struct sdio_func *func) } d_printf(2, dev, "SDIO function failed to enable: %d\n", err); sdio_release_host(func); + if (maxtries > 0 && ++tries >= maxtries) { + err = -ETIME; + break; + } msleep(I2400MS_INIT_SLEEP_INTERVAL); } /* If timed out, device is not there yet -- get -ENODEV so @@ -305,7 +315,7 @@ do_bus_reset: /* Wait for the device to settle */ msleep(40); - result = i2400ms_enable_function(i2400ms->func); + result = i2400ms_enable_function(i2400ms->func, 0); if (result >= 0) i2400ms_rx_setup(i2400ms); } else @@ -452,7 +462,7 @@ int i2400ms_probe(struct sdio_func *func, goto error_set_blk_size; } - result = i2400ms_enable_function(i2400ms->func); + result = i2400ms_enable_function(i2400ms->func, 1); if (result < 0) { dev_err(dev, "Cannot enable SDIO function: %d\n", result); goto error_func_enable;