ath9k_htc: Really fix packet injection
authorSujith Manoharan <Sujith.Manoharan@atheros.com>
Tue, 4 Jan 2011 19:36:21 +0000 (01:06 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 10 Jan 2011 20:40:52 +0000 (15:40 -0500)
The chainmask value along with other configuration has to be set
on the target for packet injection. Fix this and also move the monitor
interface addition before the channel set segment to ensure that
the opmode is updated properly.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_main.c

index a099b3e87ed3c4477c6fcb24514cd43a7529054c..1ce506f231107a22893f9da8aba0faa8dde5e686 100644 (file)
@@ -433,6 +433,7 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id,
 void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
                        enum htc_endpoint_id ep_id, bool txok);
 
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv);
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
 void ath9k_ani_work(struct work_struct *work);;
index 845b4c938d166090efc045ea11083e1cf0ce0789..f4d576bc3ccdbce3bef81d4702a756e9b900a34d 100644 (file)
@@ -301,6 +301,16 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
 
        priv->nstations++;
 
+       /*
+        * Set chainmask etc. on the target.
+        */
+       ret = ath9k_htc_update_cap_target(priv);
+       if (ret)
+               ath_dbg(common, ATH_DBG_CONFIG,
+                       "Failed to update capability in target\n");
+
+       priv->ah->is_monitoring = true;
+
        return 0;
 
 err_vif:
@@ -328,6 +338,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
        }
 
        priv->nstations--;
+       priv->ah->is_monitoring = false;
 
        return 0;
 }
@@ -419,7 +430,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
        return 0;
 }
 
-static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
+int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
 {
        struct ath9k_htc_cap_target tcap;
        int ret;
@@ -1186,6 +1197,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
                }
        }
 
+       /*
+        * Monitor interface should be added before
+        * IEEE80211_CONF_CHANGE_CHANNEL is handled.
+        */
+       if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+               if (conf->flags & IEEE80211_CONF_MONITOR) {
+                       if (ath9k_htc_add_monitor_interface(priv))
+                               ath_err(common, "Failed to set monitor mode\n");
+                       else
+                               ath_dbg(common, ATH_DBG_CONFIG,
+                                       "HW opmode set to Monitor mode\n");
+               }
+       }
+
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
                struct ieee80211_channel *curchan = hw->conf.channel;
                int pos = curchan->hw_value;
@@ -1221,16 +1246,6 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
                ath_update_txpow(priv);
        }
 
-       if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-               if (conf->flags & IEEE80211_CONF_MONITOR) {
-                       if (ath9k_htc_add_monitor_interface(priv))
-                               ath_err(common, "Failed to set monitor mode\n");
-                       else
-                               ath_dbg(common, ATH_DBG_CONFIG,
-                                       "HW opmode set to Monitor mode\n");
-               }
-       }
-
        if (changed & IEEE80211_CONF_CHANGE_IDLE) {
                mutex_lock(&priv->htc_pm_lock);
                if (!priv->ps_idle) {