aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-01-03 10:52:18 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-04 14:46:14 -0500
commitcc72128750700d01c31f583a355c5f8f809498bb (patch)
treeaaa811a3d9c704b9bf94707e2043fe700bb2b3be /drivers/net/wireless
parenta8851d10aadb46b25db4459aa0d1150c957d2bc1 (diff)
ath9k_htc: Fix packet injection
To inject a packet in monitor mode, a dummy station has to be associated with the monitor interface in the target. Failing to do this would result in a firmware crash on the device. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c72
1 files changed, 64 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ad3dd3186ad2..845b4c938d16 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -235,16 +235,38 @@ err:
235 return ret; 235 return ret;
236} 236}
237 237
238static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
239{
240 struct ath_common *common = ath9k_hw_common(priv->ah);
241 struct ath9k_htc_target_vif hvif;
242 int ret = 0;
243 u8 cmd_rsp;
244
245 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
246 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
247 hvif.index = 0; /* Should do for now */
248 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
249 priv->nvifs--;
250}
251
238static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) 252static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
239{ 253{
240 struct ath_common *common = ath9k_hw_common(priv->ah); 254 struct ath_common *common = ath9k_hw_common(priv->ah);
241 struct ath9k_htc_target_vif hvif; 255 struct ath9k_htc_target_vif hvif;
256 struct ath9k_htc_target_sta tsta;
242 int ret = 0; 257 int ret = 0;
243 u8 cmd_rsp; 258 u8 cmd_rsp;
244 259
245 if (priv->nvifs > 0) 260 if (priv->nvifs > 0)
246 return -ENOBUFS; 261 return -ENOBUFS;
247 262
263 if (priv->nstations >= ATH9K_HTC_MAX_STA)
264 return -ENOBUFS;
265
266 /*
267 * Add an interface.
268 */
269
248 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); 270 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
249 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); 271 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
250 272
@@ -257,23 +279,57 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
257 return ret; 279 return ret;
258 280
259 priv->nvifs++; 281 priv->nvifs++;
282
283 /*
284 * Associate a station with the interface for packet injection.
285 */
286
287 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
288
289 memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
290
291 tsta.is_vif_sta = 1;
292 tsta.sta_index = priv->nstations;
293 tsta.vif_index = hvif.index;
294 tsta.maxampdu = 0xffff;
295
296 WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
297 if (ret) {
298 ath_err(common, "Unable to add station entry for monitor mode\n");
299 goto err_vif;
300 }
301
302 priv->nstations++;
303
260 return 0; 304 return 0;
305
306err_vif:
307 /*
308 * Remove the interface from the target.
309 */
310 __ath9k_htc_remove_monitor_interface(priv);
311 return ret;
261} 312}
262 313
263static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) 314static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
264{ 315{
265 struct ath_common *common = ath9k_hw_common(priv->ah); 316 struct ath_common *common = ath9k_hw_common(priv->ah);
266 struct ath9k_htc_target_vif hvif;
267 int ret = 0; 317 int ret = 0;
268 u8 cmd_rsp; 318 u8 cmd_rsp, sta_idx;
269 319
270 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); 320 __ath9k_htc_remove_monitor_interface(priv);
271 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
272 hvif.index = 0; /* Should do for now */
273 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
274 priv->nvifs--;
275 321
276 return ret; 322 sta_idx = 0; /* Only single interface, for now */
323
324 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
325 if (ret) {
326 ath_err(common, "Unable to remove station entry for monitor mode\n");
327 return ret;
328 }
329
330 priv->nstations--;
331
332 return 0;
277} 333}
278 334
279static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, 335static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,