Merge "mac80211: keep jiffies of recent per-station events in sta_info"
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 06d5293..e88bfdf 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -372,6 +372,11 @@
 	DEBUGFS_ADD_COUNTER(rx_fragments, rx_fragments);
 	DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count);
 
+	DEBUGFS_ADD_COUNTER(last_tx, last_tx);
+	DEBUGFS_ADD_COUNTER(last_ack, last_ack);
+	DEBUGFS_ADD_COUNTER(last_noack, last_noack);
+	DEBUGFS_ADD_COUNTER(last_rx, last_rx);
+
 	if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
 		debugfs_create_x32("driver_buffered_tids", 0400,
 				   sta->debugfs.dir,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 7566f81..07b2105 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -241,11 +241,28 @@
  */
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 {
+	struct timespec ts_last_tx, ts_last_ack, ts_last_noack, ts_last_rx;
+
 	if (sta->rate_ctrl)
 		rate_control_free_sta(sta);
 
 	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
 
+
+	jiffies_to_timespec(sta->last_tx - INITIAL_JIFFIES, &ts_last_tx);
+	jiffies_to_timespec(sta->last_ack - INITIAL_JIFFIES, &ts_last_ack);
+	jiffies_to_timespec(sta->last_noack - INITIAL_JIFFIES, &ts_last_noack);
+	jiffies_to_timespec(sta->last_rx - INITIAL_JIFFIES, &ts_last_rx);
+
+	printk(KERN_DEBUG "sta_info_free: %pM "
+	       "last_tx %lu.%06lu last_ack %lu.%06lu "
+	       "last_noack %lu.%06lu last_rcv %lu.%06lu\n",
+	       sta->sta.addr,
+	       ts_last_tx.tv_sec, ts_last_tx.tv_nsec / 1000,
+	       ts_last_ack.tv_sec, ts_last_ack.tv_nsec / 1000,
+	       ts_last_noack.tv_sec, ts_last_noack.tv_nsec / 1000,
+	       ts_last_rx.tv_sec, ts_last_rx.tv_nsec / 1000);
+
 	if (sta->sta.txq[0])
 		kfree(to_txq_info(sta->sta.txq[0]));
 	kfree(rcu_dereference_raw(sta->sta.rates));
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1954328..90d9791 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -494,6 +494,10 @@
 	/* TDLS timeout data */
 	unsigned long last_tdls_pkt_time;
 
+	unsigned long last_tx;
+	unsigned long last_ack;
+	unsigned long last_noack;
+
 	u8 reserved_tid;
 
 	/* keep last! */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4615949..600af2b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -787,8 +787,12 @@
 			}
 		}
 
-		if (acked)
+		if (acked) {
 			sta->last_ack_signal = info->status.ack_signal;
+			sta->last_ack = jiffies;
+		} else {
+			sta->last_noack = jiffies;
+		}
 	}
 
 	rcu_read_unlock();
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a5a933b..55b6f48 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1319,6 +1319,7 @@
 
 static bool ieee80211_tx_frags(struct ieee80211_local *local,
 			       struct ieee80211_vif *vif,
+			       struct sta_info *privsta,
 			       struct ieee80211_sta *sta,
 			       struct sk_buff_head *skbs,
 			       bool txpending)
@@ -1379,6 +1380,9 @@
 		}
 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
+		if (privsta)
+			privsta->last_tx = jiffies;
+
 		info->control.vif = vif;
 
 		__skb_unlink(skb, skbs);
@@ -1444,7 +1448,7 @@
 		break;
 	}
 
-	result = ieee80211_tx_frags(local, vif, pubsta, skbs,
+	result = ieee80211_tx_frags(local, vif, sta, pubsta, skbs,
 				    txpending);
 
 	ieee80211_tpt_led_trig_tx(local, fc, led_len);
@@ -2839,7 +2843,7 @@
 				     struct ieee80211_sub_if_data, u.ap);
 
 	__skb_queue_tail(&tx.skbs, skb);
-	ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false);
+	ieee80211_tx_frags(local, &sdata->vif, sta, &sta->sta, &tx.skbs, false);
 	return true;
 }