aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlegacy/iwl-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlegacy/iwl-core.c')
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-core.c90
1 files changed, 30 insertions, 60 deletions
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
index 3be76bd5499a..240d3a80c7bc 100644
--- a/drivers/net/wireless/iwlegacy/iwl-core.c
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -1707,41 +1707,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
1707EXPORT_SYMBOL(iwl_legacy_update_stats); 1707EXPORT_SYMBOL(iwl_legacy_update_stats);
1708#endif 1708#endif
1709 1709
1710static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv) 1710int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
1711{
1712 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
1713 return;
1714
1715 if (!iwl_legacy_is_any_associated(priv)) {
1716 IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
1717 return;
1718 }
1719 /*
1720 * There is no easy and better way to force reset the radio,
1721 * the only known method is switching channel which will force to
1722 * reset and tune the radio.
1723 * Use internal short scan (single channel) operation to should
1724 * achieve this objective.
1725 * Driver should reset the radio when number of consecutive missed
1726 * beacon, or any other uCode error condition detected.
1727 */
1728 IWL_DEBUG_INFO(priv, "perform radio reset.\n");
1729 iwl_legacy_internal_short_hw_scan(priv);
1730}
1731
1732
1733int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
1734{ 1711{
1735 struct iwl_force_reset *force_reset; 1712 struct iwl_force_reset *force_reset;
1736 1713
1737 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 1714 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
1738 return -EINVAL; 1715 return -EINVAL;
1739 1716
1740 if (mode >= IWL_MAX_FORCE_RESET) { 1717 force_reset = &priv->force_reset;
1741 IWL_DEBUG_INFO(priv, "invalid reset request.\n");
1742 return -EINVAL;
1743 }
1744 force_reset = &priv->force_reset[mode];
1745 force_reset->reset_request_count++; 1718 force_reset->reset_request_count++;
1746 if (!external) { 1719 if (!external) {
1747 if (force_reset->last_force_reset_jiffies && 1720 if (force_reset->last_force_reset_jiffies &&
@@ -1754,37 +1727,34 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
1754 } 1727 }
1755 force_reset->reset_success_count++; 1728 force_reset->reset_success_count++;
1756 force_reset->last_force_reset_jiffies = jiffies; 1729 force_reset->last_force_reset_jiffies = jiffies;
1757 IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); 1730
1758 switch (mode) { 1731 /*
1759 case IWL_RF_RESET: 1732 * if the request is from external(ex: debugfs),
1760 _iwl_legacy_force_rf_reset(priv); 1733 * then always perform the request in regardless the module
1761 break; 1734 * parameter setting
1762 case IWL_FW_RESET: 1735 * if the request is from internal (uCode error or driver
1763 /* 1736 * detect failure), then fw_restart module parameter
1764 * if the request is from external(ex: debugfs), 1737 * need to be check before performing firmware reload
1765 * then always perform the request in regardless the module 1738 */
1766 * parameter setting 1739
1767 * if the request is from internal (uCode error or driver 1740 if (!external && !priv->cfg->mod_params->restart_fw) {
1768 * detect failure), then fw_restart module parameter 1741 IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
1769 * need to be check before performing firmware reload 1742 "module parameter setting\n");
1770 */ 1743 return 0;
1771 if (!external && !priv->cfg->mod_params->restart_fw) {
1772 IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
1773 "module parameter setting\n");
1774 break;
1775 }
1776 IWL_ERR(priv, "On demand firmware reload\n");
1777 /* Set the FW error flag -- cleared on iwl_down */
1778 set_bit(STATUS_FW_ERROR, &priv->status);
1779 wake_up_interruptible(&priv->wait_command_queue);
1780 /*
1781 * Keep the restart process from trying to send host
1782 * commands by clearing the INIT status bit
1783 */
1784 clear_bit(STATUS_READY, &priv->status);
1785 queue_work(priv->workqueue, &priv->restart);
1786 break;
1787 } 1744 }
1745
1746 IWL_ERR(priv, "On demand firmware reload\n");
1747
1748 /* Set the FW error flag -- cleared on iwl_down */
1749 set_bit(STATUS_FW_ERROR, &priv->status);
1750 wake_up_interruptible(&priv->wait_command_queue);
1751 /*
1752 * Keep the restart process from trying to send host
1753 * commands by clearing the INIT status bit
1754 */
1755 clear_bit(STATUS_READY, &priv->status);
1756 queue_work(priv->workqueue, &priv->restart);
1757
1788 return 0; 1758 return 0;
1789} 1759}
1790 1760
@@ -1879,7 +1849,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
1879 if (time_after(jiffies, timeout)) { 1849 if (time_after(jiffies, timeout)) {
1880 IWL_ERR(priv, "Queue %d stuck for %u ms.\n", 1850 IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
1881 q->id, priv->cfg->base_params->wd_timeout); 1851 q->id, priv->cfg->base_params->wd_timeout);
1882 ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false); 1852 ret = iwl_legacy_force_reset(priv, false);
1883 return (ret == -EAGAIN) ? 0 : 1; 1853 return (ret == -EAGAIN) ? 0 : 1;
1884 } 1854 }
1885 1855