From patchwork Fri Aug 26 06:11:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guy, Wey-Yi W" X-Patchwork-Id: 1100592 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7Q6s9Qn024001 for ; Fri, 26 Aug 2011 06:54:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753601Ab1HZGyF (ORCPT ); Fri, 26 Aug 2011 02:54:05 -0400 Received: from mga01.intel.com ([192.55.52.88]:7217 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753233Ab1HZGxj (ORCPT ); Fri, 26 Aug 2011 02:53:39 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 25 Aug 2011 23:53:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.68,283,1312182000"; d="scan'208";a="45256988" Received: from wwguy-huron.jf.intel.com (HELO localhost.localdomain) ([134.134.163.53]) by fmsmga001.fm.intel.com with ESMTP; 25 Aug 2011 23:53:31 -0700 From: Wey-Yi Guy To: linville@tuxdriver.com Cc: linux-wireless@vger.kernel.org, Emmanuel Grumbach , Wey-Yi Guy Subject: [PATCH 48/60] iwlagn: stop the device before freeing it Date: Thu, 25 Aug 2011 23:11:20 -0700 Message-Id: <1314339092-20797-49-git-send-email-wey-yi.w.guy@intel.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1314339092-20797-1-git-send-email-wey-yi.w.guy@intel.com> References: <1314339092-20797-1-git-send-email-wey-yi.w.guy@intel.com> 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.6 (demeter2.kernel.org [140.211.167.43]); Fri, 26 Aug 2011 06:54:10 +0000 (UTC) From: Emmanuel Grumbach When we remove the module, we free all the tx and rx resources. Before doing that, we'd better stop the tx / rx activity. Calling iwl_trans_stop_device in iwl_remove helps also to remove a few API functions: * rx_free: happens in iwl_trans_free * tx_free: happens in iwl_trans_free * disable_sync_irq: happens in iwl_trans_stop_device Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +------ drivers/net/wireless/iwlwifi/iwl-trans.c | 42 ++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 23 ---------------- 3 files changed, 22 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 65a6db5..e19ff11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3443,20 +3443,13 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->mac80211_registered = 0; } - /* Reset to low power before unloading driver. */ - iwl_apm_stop(priv); - iwl_tt_exit(priv); - /* make sure we flush any pending irq or - * tasklet for the driver */ - iwl_trans_disable_sync_irq(trans(priv)); + /*This will stop the queues, move the device to low power state */ + iwl_trans_stop_device(trans(priv)); iwl_dealloc_ucode(priv); - iwl_trans_rx_free(trans(priv)); - iwl_trans_tx_free(trans(priv)); - iwl_eeprom_free(priv); /*netif_stop_queue(dev); */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index ac401b8..0a3dd6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -555,7 +555,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) return 0; error: - iwl_trans_tx_free(trans); + iwl_trans_pcie_tx_free(trans); return ret; } @@ -603,7 +603,7 @@ static int iwl_tx_init(struct iwl_trans *trans) error: /*Upon error, free only if we allocated something */ if (alloc) - iwl_trans_tx_free(trans); + iwl_trans_pcie_tx_free(trans); return ret; } @@ -958,13 +958,28 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) return 0; } +static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) +{ + unsigned long flags; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans->shrd->lock, flags); + iwl_disable_interrupts(trans); + spin_unlock_irqrestore(&trans->shrd->lock, flags); + + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(bus(trans)->irq); + tasklet_kill(&trans_pcie->irq_tasklet); +} + static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) { /* stop and reset the on-board processor */ iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - iwl_trans_disable_sync_irq(trans); + iwl_trans_pcie_disable_sync_irq(trans); /* device going down, Stop using ICT table */ iwl_disable_ict(trans); @@ -1208,23 +1223,10 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, } } -static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) -{ - unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); - - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(bus(trans)->irq); - tasklet_kill(&trans_pcie->irq_tasklet); -} - static void iwl_trans_pcie_free(struct iwl_trans *trans) { + iwl_trans_pcie_tx_free(trans); + iwl_trans_pcie_rx_free(trans); free_irq(bus(trans)->irq, trans); iwl_free_isr_ict(trans); trans->shrd->trans = NULL; @@ -1860,9 +1862,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx_start = iwl_trans_pcie_tx_start, - .rx_free = iwl_trans_pcie_rx_free, - .tx_free = iwl_trans_pcie_tx_free, - .send_cmd = iwl_trans_pcie_send_cmd, .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, @@ -1875,7 +1874,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .kick_nic = iwl_trans_pcie_kick_nic, - .disable_sync_irq = iwl_trans_pcie_disable_sync_irq, .free = iwl_trans_pcie_free, .dbgfs_register = iwl_trans_pcie_dbgfs_register, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0da6ad5..e72e480 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -88,8 +88,6 @@ struct iwl_shared; * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. * @stop_device:stops the whole device (embedded CPU put to reset) - * @rx_free: frees the rx memory - * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use @@ -99,9 +97,6 @@ struct iwl_shared; * ready and a successful ADDBA response has been received. * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run - * @disable_sync_irq: Disable and sync: after this handler returns, it is - * guaranteed that all the ISR / tasklet etc... have finished running - * and the transport layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... * @dbgfs_register: add the dbgfs files under this directory. Files will be @@ -117,8 +112,6 @@ struct iwl_trans_ops { int (*prepare_card_hw)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); void (*tx_start)(struct iwl_trans *trans); - void (*tx_free)(struct iwl_trans *trans); - void (*rx_free)(struct iwl_trans *trans); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); @@ -138,7 +131,6 @@ struct iwl_trans_ops { void (*kick_nic)(struct iwl_trans *trans); - void (*disable_sync_irq)(struct iwl_trans *trans); void (*free)(struct iwl_trans *trans); int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); @@ -187,16 +179,6 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) trans->ops->tx_start(trans); } -static inline void iwl_trans_rx_free(struct iwl_trans *trans) -{ - trans->ops->rx_free(trans); -} - -static inline void iwl_trans_tx_free(struct iwl_trans *trans) -{ - trans->ops->tx_free(trans); -} - static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { @@ -247,11 +229,6 @@ static inline void iwl_trans_kick_nic(struct iwl_trans *trans) trans->ops->kick_nic(trans); } -static inline void iwl_trans_disable_sync_irq(struct iwl_trans *trans) -{ - trans->ops->disable_sync_irq(trans); -} - static inline void iwl_trans_free(struct iwl_trans *trans) { trans->ops->free(trans);