From patchwork Wed Feb 22 02:10:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Chamberlain X-Patchwork-Id: 9586047 X-Patchwork-Delegate: luca@coelho.fi Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2E41160431 for ; Wed, 22 Feb 2017 02:11:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1382C28696 for ; Wed, 22 Feb 2017 02:11:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 083F4287EE; Wed, 22 Feb 2017 02:11:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A00BC28696 for ; Wed, 22 Feb 2017 02:11:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754458AbdBVCLN (ORCPT ); Tue, 21 Feb 2017 21:11:13 -0500 Received: from mail.kernel.org ([198.145.29.136]:55632 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754324AbdBVCKv (ORCPT ); Tue, 21 Feb 2017 21:10:51 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D2639200EC; Wed, 22 Feb 2017 02:10:43 +0000 (UTC) Received: from garbanzo.do-not-panic.com (c-73-15-241-2.hsd1.ca.comcast.net [73.15.241.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 7EB7A201C8; Wed, 22 Feb 2017 02:10:42 +0000 (UTC) From: "Luis R. Rodriguez" To: johannes.berg@intel.com, luciano.coelho@intel.com, emmanuel.grumbach@intel.com Cc: ming.lei@canonical.com, zajec5@gmail.com, linuxwifi@intel.com, linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, "Luis R. Rodriguez" Subject: [PATCH v2 1/2] iwlwifi: share opmode start work code Date: Tue, 21 Feb 2017 18:10:38 -0800 Message-Id: <20170222021039.28193-2-mcgrof@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170222021039.28193-1-mcgrof@kernel.org> References: <20170222001822.GE31264@wotan.suse.de> <20170222021039.28193-1-mcgrof@kernel.org> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The firmware async callback and the opmode registration share some functionality -- to start the drv's opmode. Move this work into a helper which is shared. This should help us share fixes should these diverging code paths change. Signed-off-by: Luis R. Rodriguez --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 90 +++++++++++++++++++--------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index e96095c1824a..ea88b5cec869 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -102,6 +102,7 @@ static struct dentry *iwl_dbgfs_root; * @op_mode: the running op_mode * @trans: transport layer * @dev: for debug prints only + * @start_requested: start op has been requested and is pending on this device * @fw_index: firmware revision to try loading * @firmware_name: composite filename of ucode file to load * @request_firmware_complete: the firmware has been obtained from user space @@ -113,6 +114,7 @@ struct iwl_drv { struct iwl_op_mode *op_mode; struct iwl_trans *trans; struct device *dev; + bool start_requested; int fw_index; /* firmware we're trying to load */ char firmware_name[64]; /* name of firmware file to load */ @@ -1231,6 +1233,48 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv) } } +static void iwlwifi_opmode_start_drv(struct iwlwifi_opmode_table *op, + struct iwl_drv *drv) +{ + if (!drv->start_requested) + return; + + drv->op_mode = _iwl_op_mode_start(drv, op); + drv->start_requested = false; + + /* + * Complete the firmware request last so that + * a driver unbind (stop) doesn't run while we + * are doing the start() above. + */ + complete(&drv->request_firmware_complete); + + if (!drv->op_mode) + device_release_driver(drv->trans->dev); +} + +static void iwlwifi_opmode_start(struct iwlwifi_opmode_table *op) +{ + struct iwl_drv *drv; + + list_for_each_entry(drv, &op->drv, list) + iwlwifi_opmode_start_drv(op, drv); +} + +static void iwlwifi_opmode_dowork(void) +{ + unsigned int i; + struct iwlwifi_opmode_table *op; + + mutex_lock(&iwlwifi_opmode_table_mtx); + for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { + op = &iwlwifi_opmode_table[i]; + if (op->ops) + iwlwifi_opmode_start(op); + } + mutex_unlock(&iwlwifi_opmode_table_mtx); +} + /** * iwl_req_fw_callback - callback when firmware was loaded * @@ -1443,30 +1487,17 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) IWL_INFO(drv, "loaded firmware version %s op_mode %s\n", drv->fw.fw_version, op->name); + drv->start_requested = true; /* add this device to the list of devices using this op_mode */ list_add_tail(&drv->list, &op->drv); - if (op->ops) { - drv->op_mode = _iwl_op_mode_start(drv, op); - - if (!drv->op_mode) { - mutex_unlock(&iwlwifi_opmode_table_mtx); - goto out_unbind; - } - } mutex_unlock(&iwlwifi_opmode_table_mtx); - /* - * Complete the firmware request last so that - * a driver unbind (stop) doesn't run while we - * are doing the start() above. - */ - complete(&drv->request_firmware_complete); - err = request_module_nowait("%s", op->name); if (err) goto out_unbind; + iwlwifi_opmode_dowork(); goto free; try_again: @@ -1588,8 +1619,8 @@ IWL_EXPORT_SYMBOL(iwlwifi_mod_params); int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) { int i; - struct iwl_drv *drv; struct iwlwifi_opmode_table *op; + int ret = -EIO; mutex_lock(&iwlwifi_opmode_table_mtx); for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { @@ -1597,20 +1628,15 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops) if (strcmp(op->name, name)) continue; op->ops = ops; - /* TODO: need to handle exceptional case */ - list_for_each_entry(drv, &op->drv, list) { - drv->op_mode = _iwl_op_mode_start(drv, op); - if (!drv->op_mode) { - complete(&drv->request_firmware_complete); - device_release_driver(drv->trans->dev); - } - } - - mutex_unlock(&iwlwifi_opmode_table_mtx); - return 0; + ret = 0; + break; } mutex_unlock(&iwlwifi_opmode_table_mtx); - return -EIO; + + if (!ret) + iwlwifi_opmode_dowork(); + + return ret; } IWL_EXPORT_SYMBOL(iwl_opmode_register); @@ -1626,8 +1652,14 @@ void iwl_opmode_deregister(const char *name) iwlwifi_opmode_table[i].ops = NULL; /* call the stop routine for all devices */ - list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) + list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) { _iwl_op_mode_stop(drv); + /* + * So that if iwlmvm gets unloaded alone, but then + * loaded again we can kick the old registered devices + */ + drv->start_requested = true; + } mutex_unlock(&iwlwifi_opmode_table_mtx); return;