Browse Source

Merge branch 'for-linville' of git://github.com/kvalo/ath

John W. Linville 11 năm trước cách đây
mục cha
commit
75e58071c0

+ 4 - 2
drivers/net/wireless/ath/ath10k/core.c

@@ -680,8 +680,8 @@ static void ath10k_core_restart(struct work_struct *work)
 
 
 	switch (ar->state) {
 	switch (ar->state) {
 	case ATH10K_STATE_ON:
 	case ATH10K_STATE_ON:
-		ath10k_halt(ar);
 		ar->state = ATH10K_STATE_RESTARTING;
 		ar->state = ATH10K_STATE_RESTARTING;
+		ath10k_halt(ar);
 		ieee80211_restart_hw(ar->hw);
 		ieee80211_restart_hw(ar->hw);
 		break;
 		break;
 	case ATH10K_STATE_OFF:
 	case ATH10K_STATE_OFF:
@@ -908,7 +908,9 @@ void ath10k_core_stop(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 	lockdep_assert_held(&ar->conf_mutex);
 
 
 	/* try to suspend target */
 	/* try to suspend target */
-	ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
+	if (ar->state != ATH10K_STATE_RESTARTING)
+		ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
+
 	ath10k_debug_stop(ar);
 	ath10k_debug_stop(ar);
 	ath10k_htc_stop(&ar->htc);
 	ath10k_htc_stop(&ar->htc);
 	ath10k_htt_detach(&ar->htt);
 	ath10k_htt_detach(&ar->htt);

+ 16 - 0
drivers/net/wireless/ath/ath10k/mac.c

@@ -2291,6 +2291,8 @@ static void ath10k_tx(struct ieee80211_hw *hw,
  */
  */
 void ath10k_halt(struct ath10k *ar)
 void ath10k_halt(struct ath10k *ar)
 {
 {
+	struct ath10k_vif *arvif;
+
 	lockdep_assert_held(&ar->conf_mutex);
 	lockdep_assert_held(&ar->conf_mutex);
 
 
 	if (ath10k_monitor_is_enabled(ar)) {
 	if (ath10k_monitor_is_enabled(ar)) {
@@ -2313,6 +2315,17 @@ void ath10k_halt(struct ath10k *ar)
 		ar->scan.in_progress = false;
 		ar->scan.in_progress = false;
 		ieee80211_scan_completed(ar->hw, true);
 		ieee80211_scan_completed(ar->hw, true);
 	}
 	}
+
+	list_for_each_entry(arvif, &ar->arvifs, list) {
+		if (!arvif->beacon)
+			continue;
+
+		dma_unmap_single(arvif->ar->dev,
+				 ATH10K_SKB_CB(arvif->beacon)->paddr,
+				 arvif->beacon->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(arvif->beacon);
+		arvif->beacon = NULL;
+	}
 	spin_unlock_bh(&ar->data_lock);
 	spin_unlock_bh(&ar->data_lock);
 }
 }
 
 
@@ -2771,6 +2784,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 
 
 	spin_lock_bh(&ar->data_lock);
 	spin_lock_bh(&ar->data_lock);
 	if (arvif->beacon) {
 	if (arvif->beacon) {
+		dma_unmap_single(arvif->ar->dev,
+				 ATH10K_SKB_CB(arvif->beacon)->paddr,
+				 arvif->beacon->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(arvif->beacon);
 		dev_kfree_skb_any(arvif->beacon);
 		arvif->beacon = NULL;
 		arvif->beacon = NULL;
 	}
 	}

+ 17 - 1
drivers/net/wireless/ath/ath10k/pci.c

@@ -2452,6 +2452,10 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
 		if (val == 0xffffffff)
 		if (val == 0xffffffff)
 			continue;
 			continue;
 
 
+		/* the device has crashed so don't bother trying anymore */
+		if (val & FW_IND_EVENT_PENDING)
+			break;
+
 		if (val & FW_IND_INITIALIZED)
 		if (val & FW_IND_INITIALIZED)
 			break;
 			break;
 
 
@@ -2464,7 +2468,19 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
 		mdelay(10);
 		mdelay(10);
 	} while (time_before(jiffies, timeout));
 	} while (time_before(jiffies, timeout));
 
 
-	if (val == 0xffffffff || !(val & FW_IND_INITIALIZED)) {
+	if (val == 0xffffffff) {
+		ath10k_err("failed to read device register, device is gone\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	if (val & FW_IND_EVENT_PENDING) {
+		ath10k_warn("device has crashed during init\n");
+		ret = -ECOMM;
+		goto out;
+	}
+
+	if (!(val & FW_IND_INITIALIZED)) {
 		ath10k_err("failed to receive initialized event from target: %08x\n",
 		ath10k_err("failed to receive initialized event from target: %08x\n",
 			   val);
 			   val);
 		ret = -ETIMEDOUT;
 		ret = -ETIMEDOUT;

+ 2 - 0
drivers/net/wireless/ath/ath10k/wmi.c

@@ -1431,6 +1431,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 					 ATH10K_SKB_CB(arvif->beacon)->paddr,
 					 ATH10K_SKB_CB(arvif->beacon)->paddr,
 					 arvif->beacon->len, DMA_TO_DEVICE);
 					 arvif->beacon->len, DMA_TO_DEVICE);
 			dev_kfree_skb_any(arvif->beacon);
 			dev_kfree_skb_any(arvif->beacon);
+			arvif->beacon = NULL;
 		}
 		}
 
 
 		ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
 		ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
@@ -1440,6 +1441,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 					ATH10K_SKB_CB(bcn)->paddr);
 					ATH10K_SKB_CB(bcn)->paddr);
 		if (ret) {
 		if (ret) {
 			ath10k_warn("failed to map beacon: %d\n", ret);
 			ath10k_warn("failed to map beacon: %d\n", ret);
+			dev_kfree_skb_any(bcn);
 			goto skip;
 			goto skip;
 		}
 		}