wl1271: Add hardware recovery mechanism

There is some probability of hardware failures, which currently go largely
undetected. Attempt to recover from these failures by shutting down the
hardware, and requesting mac80211 to reconfigure it.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index e7f096f..fecb0c3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -235,6 +235,9 @@
 	}
 };
 
+static void __wl1271_op_remove_interface(struct wl1271 *wl);
+
+
 static void wl1271_device_release(struct device *dev)
 {
 
@@ -612,6 +615,26 @@
 	return ret;
 }
 
+static void wl1271_recovery_work(struct work_struct *work)
+{
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, recovery_work);
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state != WL1271_STATE_ON)
+		goto out;
+
+	wl1271_info("Hardware recovery in progress.");
+
+	/* reboot the chipset */
+	__wl1271_op_remove_interface(wl);
+	ieee80211_restart_hw(wl->hw);
+
+out:
+	mutex_unlock(&wl->mutex);
+}
+
 static void wl1271_fw_wakeup(struct wl1271 *wl)
 {
 	u32 elp_reg;
@@ -635,6 +658,7 @@
 	INIT_WORK(&wl->irq_work, wl1271_irq_work);
 	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
 
 	return 0;
 }
@@ -793,11 +817,11 @@
 	mutex_unlock(&wl->mutex);
 
 	cancel_work_sync(&wl->irq_work);
+	cancel_work_sync(&wl->recovery_work);
 
 	return ret;
 }
 
-
 static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
@@ -1046,6 +1070,8 @@
 	WARN_ON(wl->vif != vif);
 	__wl1271_op_remove_interface(wl);
 	mutex_unlock(&wl->mutex);
+
+	cancel_work_sync(&wl->recovery_work);
 }
 
 static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)