Skip to content

Commit

Permalink
iwlagn: stop the device before freeing it
Browse files Browse the repository at this point in the history
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 <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Emmanuel Grumbach authored and John W. Linville committed Aug 29, 2011
1 parent fd65693 commit ae2c30b
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 54 deletions.
11 changes: 2 additions & 9 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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); */
Expand Down
42 changes: 20 additions & 22 deletions drivers/net/wireless/iwlwifi/iwl-trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,

Expand All @@ -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,
Expand Down
23 changes: 0 additions & 23 deletions drivers/net/wireless/iwlwifi/iwl-trans.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ae2c30b

Please sign in to comment.