aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2008-10-29 00:43:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-10 15:14:55 -0500
commitb5aa9bf9460f9e97f2c10940b029d75c6557ad7c (patch)
tree60bc06b72761339e048139fdb076de14f2f4273e /drivers
parent17683c65c8a5f3f29f5408334992986b996d8205 (diff)
ath9k: Node cleanup
Start removing the internal node list in ath9k, in preparation for using mac80211's STA list. Remove lists, locks, routines, flags, functions managing nodes in ath9k. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath9k/core.c116
-rw-r--r--drivers/net/wireless/ath9k/core.h46
-rw-r--r--drivers/net/wireless/ath9k/main.c94
-rw-r--r--drivers/net/wireless/ath9k/rc.c15
-rw-r--r--drivers/net/wireless/ath9k/recv.c42
-rw-r--r--drivers/net/wireless/ath9k/xmit.c107
6 files changed, 94 insertions, 326 deletions
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index 0089e023c609..49fc264cfe5a 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -47,6 +47,41 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
47 *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ 47 *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
48} 48}
49 49
50static u8 parse_mpdudensity(u8 mpdudensity)
51{
52 /*
53 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
54 * 0 for no restriction
55 * 1 for 1/4 us
56 * 2 for 1/2 us
57 * 3 for 1 us
58 * 4 for 2 us
59 * 5 for 4 us
60 * 6 for 8 us
61 * 7 for 16 us
62 */
63 switch (mpdudensity) {
64 case 0:
65 return 0;
66 case 1:
67 case 2:
68 case 3:
69 /* Our lower layer calculations limit our precision to
70 1 microsecond */
71 return 1;
72 case 4:
73 return 2;
74 case 5:
75 return 4;
76 case 6:
77 return 8;
78 case 7:
79 return 16;
80 default:
81 return 0;
82 }
83}
84
50/* 85/*
51 * Set current operating mode 86 * Set current operating mode
52 * 87 *
@@ -1321,7 +1356,7 @@ void ath_deinit(struct ath_softc *sc)
1321/* Node Management */ 1356/* Node Management */
1322/*******************/ 1357/*******************/
1323 1358
1324struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id) 1359void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, int if_id)
1325{ 1360{
1326 struct ath_vap *avp; 1361 struct ath_vap *avp;
1327 struct ath_node *an; 1362 struct ath_node *an;
@@ -1329,90 +1364,30 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
1329 avp = sc->sc_vaps[if_id]; 1364 avp = sc->sc_vaps[if_id];
1330 ASSERT(avp != NULL); 1365 ASSERT(avp != NULL);
1331 1366
1332 /* mac80211 sta_notify callback is from an IRQ context, so no sleep */ 1367 an = (struct ath_node *)sta->drv_priv;
1333 an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
1334 if (an == NULL)
1335 return NULL;
1336 memset(an, 0, sizeof(*an));
1337
1338 an->an_sc = sc;
1339 memcpy(an->an_addr, addr, ETH_ALEN);
1340 atomic_set(&an->an_refcnt, 1);
1341 1368
1342 /* set up per-node tx/rx state */ 1369 /* set up per-node tx/rx state */
1343 ath_tx_node_init(sc, an); 1370 ath_tx_node_init(sc, an);
1344 ath_rx_node_init(sc, an); 1371 ath_rx_node_init(sc, an);
1345 1372
1373 an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1374 sta->ht_cap.ampdu_factor);
1375 an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
1376
1346 ath_chainmask_sel_init(sc, an); 1377 ath_chainmask_sel_init(sc, an);
1347 ath_chainmask_sel_timerstart(&an->an_chainmask_sel); 1378 ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
1348 list_add(&an->list, &sc->node_list);
1349
1350 return an;
1351} 1379}
1352 1380
1353void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag) 1381void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
1354{ 1382{
1355 unsigned long flags; 1383 struct ath_node *an = (struct ath_node *)sta->drv_priv;
1356 1384
1357 ath_chainmask_sel_timerstop(&an->an_chainmask_sel); 1385 ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
1358 an->an_flags |= ATH_NODE_CLEAN; 1386
1359 ath_tx_node_cleanup(sc, an, bh_flag); 1387 ath_tx_node_cleanup(sc, an);
1360 ath_rx_node_cleanup(sc, an);
1361 1388
1362 ath_tx_node_free(sc, an); 1389 ath_tx_node_free(sc, an);
1363 ath_rx_node_free(sc, an); 1390 ath_rx_node_free(sc, an);
1364
1365 spin_lock_irqsave(&sc->node_lock, flags);
1366
1367 list_del(&an->list);
1368
1369 spin_unlock_irqrestore(&sc->node_lock, flags);
1370
1371 kfree(an);
1372}
1373
1374/* Finds a node and increases the refcnt if found */
1375
1376struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr)
1377{
1378 struct ath_node *an = NULL, *an_found = NULL;
1379
1380 if (list_empty(&sc->node_list)) /* FIXME */
1381 goto out;
1382 list_for_each_entry(an, &sc->node_list, list) {
1383 if (!compare_ether_addr(an->an_addr, addr)) {
1384 atomic_inc(&an->an_refcnt);
1385 an_found = an;
1386 break;
1387 }
1388 }
1389out:
1390 return an_found;
1391}
1392
1393/* Decrements the refcnt and if it drops to zero, detach the node */
1394
1395void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
1396{
1397 if (atomic_dec_and_test(&an->an_refcnt))
1398 ath_node_detach(sc, an, bh_flag);
1399}
1400
1401/* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */
1402struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr)
1403{
1404 struct ath_node *an = NULL, *an_found = NULL;
1405
1406 if (list_empty(&sc->node_list))
1407 return NULL;
1408
1409 list_for_each_entry(an, &sc->node_list, list)
1410 if (!compare_ether_addr(an->an_addr, addr)) {
1411 an_found = an;
1412 break;
1413 }
1414
1415 return an_found;
1416} 1391}
1417 1392
1418/* 1393/*
@@ -1437,7 +1412,6 @@ void ath_newassoc(struct ath_softc *sc,
1437 ath_rx_aggr_teardown(sc, an, tidno); 1412 ath_rx_aggr_teardown(sc, an, tidno);
1438 } 1413 }
1439 } 1414 }
1440 an->an_flags = 0;
1441} 1415}
1442 1416
1443/**************/ 1417/**************/
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index fbff9aa4c28f..d7228ec66c2f 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -373,7 +373,6 @@ void ath_flushrecv(struct ath_softc *sc);
373u32 ath_calcrxfilter(struct ath_softc *sc); 373u32 ath_calcrxfilter(struct ath_softc *sc);
374void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an); 374void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
375void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an); 375void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
376void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
377void ath_handle_rx_intr(struct ath_softc *sc); 376void ath_handle_rx_intr(struct ath_softc *sc);
378int ath_rx_init(struct ath_softc *sc, int nbufs); 377int ath_rx_init(struct ath_softc *sc, int nbufs);
379void ath_rx_cleanup(struct ath_softc *sc); 378void ath_rx_cleanup(struct ath_softc *sc);
@@ -546,8 +545,7 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx);
546void ath_tx_draintxq(struct ath_softc *sc, 545void ath_tx_draintxq(struct ath_softc *sc,
547 struct ath_txq *txq, bool retry_tx); 546 struct ath_txq *txq, bool retry_tx);
548void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); 547void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
549void ath_tx_node_cleanup(struct ath_softc *sc, 548void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
550 struct ath_node *an, bool bh_flag);
551void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); 549void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
552void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); 550void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
553int ath_tx_init(struct ath_softc *sc, int nbufs); 551int ath_tx_init(struct ath_softc *sc, int nbufs);
@@ -568,11 +566,6 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
568/* Node / Aggregation */ 566/* Node / Aggregation */
569/**********************/ 567/**********************/
570 568
571/* indicates the node is clened up */
572#define ATH_NODE_CLEAN 0x1
573/* indicates the node is 80211 power save */
574#define ATH_NODE_PWRSAVE 0x2
575
576#define ADDBA_EXCHANGE_ATTEMPTS 10 569#define ADDBA_EXCHANGE_ATTEMPTS 10
577#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ 570#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
578#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ 571#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
@@ -584,6 +577,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
584#define IEEE80211_SEQ_SEQ_SHIFT 4 577#define IEEE80211_SEQ_SEQ_SHIFT 4
585#define IEEE80211_SEQ_MAX 4096 578#define IEEE80211_SEQ_MAX 4096
586#define IEEE80211_MIN_AMPDU_BUF 0x8 579#define IEEE80211_MIN_AMPDU_BUF 0x8
580#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
587 581
588/* return whether a bit at index _n in bitmap _bm is set 582/* return whether a bit at index _n in bitmap _bm is set
589 * _sz is the size of the bitmap */ 583 * _sz is the size of the bitmap */
@@ -638,15 +632,10 @@ struct ath_node_aggr {
638 632
639/* driver-specific node state */ 633/* driver-specific node state */
640struct ath_node { 634struct ath_node {
641 struct list_head list;
642 struct ath_softc *an_sc; 635 struct ath_softc *an_sc;
643 atomic_t an_refcnt;
644 struct ath_chainmask_sel an_chainmask_sel; 636 struct ath_chainmask_sel an_chainmask_sel;
645 struct ath_node_aggr an_aggr; 637 struct ath_node_aggr an_aggr;
646 u8 an_smmode; /* SM Power save mode */ 638 u8 an_smmode; /* SM Power save mode */
647 u8 an_flags;
648 u8 an_addr[ETH_ALEN];
649
650 u16 maxampdu; 639 u16 maxampdu;
651 u8 mpdudensity; 640 u8 mpdudensity;
652}; 641};
@@ -659,28 +648,17 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
659 struct ath_node *an, u8 tidno); 648 struct ath_node *an, u8 tidno);
660void ath_rx_aggr_teardown(struct ath_softc *sc, 649void ath_rx_aggr_teardown(struct ath_softc *sc,
661 struct ath_node *an, u8 tidno); 650 struct ath_node *an, u8 tidno);
662int ath_rx_aggr_start(struct ath_softc *sc, 651int ath_rx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
663 const u8 *addr, 652 u16 tid, u16 *ssn);
664 u16 tid, 653int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
665 u16 *ssn); 654int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
666int ath_rx_aggr_stop(struct ath_softc *sc, 655 u16 tid, u16 *ssn);
667 const u8 *addr, 656int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
668 u16 tid);
669int ath_tx_aggr_start(struct ath_softc *sc,
670 const u8 *addr,
671 u16 tid,
672 u16 *ssn);
673int ath_tx_aggr_stop(struct ath_softc *sc,
674 const u8 *addr,
675 u16 tid);
676void ath_newassoc(struct ath_softc *sc, 657void ath_newassoc(struct ath_softc *sc,
677 struct ath_node *node, int isnew, int isuapsd); 658 struct ath_node *node, int isnew, int isuapsd);
678struct ath_node *ath_node_attach(struct ath_softc *sc, 659void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
679 u8 addr[ETH_ALEN], int if_id); 660 int if_id);
680void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag); 661void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
681struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]);
682void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
683struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
684 662
685/*******************/ 663/*******************/
686/* Beacon Handling */ 664/* Beacon Handling */
@@ -975,7 +953,6 @@ struct ath_softc {
975 u8 sc_rxotherant; /* rx's on non-default antenna */ 953 u8 sc_rxotherant; /* rx's on non-default antenna */
976 954
977 struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ 955 struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
978 struct list_head node_list;
979 struct ath_ht_info sc_ht_info; 956 struct ath_ht_info sc_ht_info;
980 enum ath9k_ht_extprotspacing sc_ht_extprotspacing; 957 enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
981 958
@@ -1036,7 +1013,6 @@ struct ath_softc {
1036 spinlock_t sc_rxbuflock; 1013 spinlock_t sc_rxbuflock;
1037 spinlock_t sc_txbuflock; 1014 spinlock_t sc_txbuflock;
1038 spinlock_t sc_resetlock; 1015 spinlock_t sc_resetlock;
1039 spinlock_t node_lock;
1040 1016
1041 /* LEDs */ 1017 /* LEDs */
1042 struct ath_led radio_led; 1018 struct ath_led radio_led;
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index b25c8f9670d1..b1b1e7f3b0b8 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -21,8 +21,6 @@
21 21
22#define ATH_PCI_VERSION "0.1" 22#define ATH_PCI_VERSION "0.1"
23 23
24#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
25
26static char *dev_info = "ath9k"; 24static char *dev_info = "ath9k";
27 25
28MODULE_AUTHOR("Atheros Communications"); 26MODULE_AUTHOR("Atheros Communications");
@@ -297,41 +295,6 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
297 rx_status->flag |= RX_FLAG_TSFT; 295 rx_status->flag |= RX_FLAG_TSFT;
298} 296}
299 297
300static u8 parse_mpdudensity(u8 mpdudensity)
301{
302 /*
303 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
304 * 0 for no restriction
305 * 1 for 1/4 us
306 * 2 for 1/2 us
307 * 3 for 1 us
308 * 4 for 2 us
309 * 5 for 4 us
310 * 6 for 8 us
311 * 7 for 16 us
312 */
313 switch (mpdudensity) {
314 case 0:
315 return 0;
316 case 1:
317 case 2:
318 case 3:
319 /* Our lower layer calculations limit our precision to
320 1 microsecond */
321 return 1;
322 case 4:
323 return 2;
324 case 5:
325 return 4;
326 case 6:
327 return 8;
328 case 7:
329 return 16;
330 default:
331 return 0;
332 }
333}
334
335static void ath9k_ht_conf(struct ath_softc *sc, 298static void ath9k_ht_conf(struct ath_softc *sc,
336 struct ieee80211_bss_conf *bss_conf) 299 struct ieee80211_bss_conf *bss_conf)
337{ 300{
@@ -479,8 +442,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
479 tx_info->status.rates[0].count = tx_status->retries + 1; 442 tx_info->status.rates[0].count = tx_status->retries + 1;
480 443
481 ieee80211_tx_status(hw, skb); 444 ieee80211_tx_status(hw, skb);
482 if (an)
483 ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
484} 445}
485 446
486int _ath_rx_indicate(struct ath_softc *sc, 447int _ath_rx_indicate(struct ath_softc *sc,
@@ -518,10 +479,6 @@ int _ath_rx_indicate(struct ath_softc *sc,
518 rx_status.flag |= RX_FLAG_DECRYPTED; 479 rx_status.flag |= RX_FLAG_DECRYPTED;
519 } 480 }
520 481
521 spin_lock_bh(&sc->node_lock);
522 an = ath_node_find(sc, hdr->addr2);
523 spin_unlock_bh(&sc->node_lock);
524
525 if (an) { 482 if (an) {
526 ath_rx_input(sc, an, 483 ath_rx_input(sc, an,
527 skb, status, &st); 484 skb, status, &st);
@@ -913,11 +870,6 @@ static int ath_attach(u16 devid,
913 if (error != 0) 870 if (error != 0)
914 return error; 871 return error;
915 872
916 /* Init nodes */
917
918 INIT_LIST_HEAD(&sc->node_list);
919 spin_lock_init(&sc->node_lock);
920
921 /* get mac address from hardware and set in mac80211 */ 873 /* get mac address from hardware and set in mac80211 */
922 874
923 SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); 875 SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
@@ -1404,50 +1356,22 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
1404 __func__, sc->rx_filter); 1356 __func__, sc->rx_filter);
1405} 1357}
1406 1358
1359/* Only a single interface is currently supported,
1360 so pass 0 as the interface id to ath_node_attach */
1361
1407static void ath9k_sta_notify(struct ieee80211_hw *hw, 1362static void ath9k_sta_notify(struct ieee80211_hw *hw,
1408 struct ieee80211_vif *vif, 1363 struct ieee80211_vif *vif,
1409 enum sta_notify_cmd cmd, 1364 enum sta_notify_cmd cmd,
1410 struct ieee80211_sta *sta) 1365 struct ieee80211_sta *sta)
1411{ 1366{
1412 struct ath_softc *sc = hw->priv; 1367 struct ath_softc *sc = hw->priv;
1413 struct ath_node *an;
1414 unsigned long flags;
1415
1416 spin_lock_irqsave(&sc->node_lock, flags);
1417 an = ath_node_find(sc, sta->addr);
1418 spin_unlock_irqrestore(&sc->node_lock, flags);
1419 1368
1420 switch (cmd) { 1369 switch (cmd) {
1421 case STA_NOTIFY_ADD: 1370 case STA_NOTIFY_ADD:
1422 spin_lock_irqsave(&sc->node_lock, flags); 1371 ath_node_attach(sc, sta, 0);
1423 if (!an) {
1424 ath_node_attach(sc, sta->addr, 0);
1425 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %pM\n",
1426 __func__, sta->addr);
1427 } else {
1428 ath_node_get(sc, sta->addr);
1429 }
1430
1431 /* XXX: Is this right? Can the capabilities change? */
1432 an = ath_node_find(sc, sta->addr);
1433 an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
1434 sta->ht_cap.ampdu_factor);
1435 an->mpdudensity =
1436 parse_mpdudensity(sta->ht_cap.ampdu_density);
1437
1438 spin_unlock_irqrestore(&sc->node_lock, flags);
1439 break; 1372 break;
1440 case STA_NOTIFY_REMOVE: 1373 case STA_NOTIFY_REMOVE:
1441 if (!an) 1374 ath_node_detach(sc, sta);
1442 DPRINTF(sc, ATH_DBG_FATAL,
1443 "%s: Removal of a non-existent node\n",
1444 __func__);
1445 else {
1446 ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
1447 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %pM\n",
1448 __func__,
1449 sta->addr);
1450 }
1451 break; 1375 break;
1452 default: 1376 default:
1453 break; 1377 break;
@@ -1595,21 +1519,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
1595 1519
1596 switch (action) { 1520 switch (action) {
1597 case IEEE80211_AMPDU_RX_START: 1521 case IEEE80211_AMPDU_RX_START:
1598 ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn); 1522 ret = ath_rx_aggr_start(sc, sta, tid, ssn);
1599 if (ret < 0) 1523 if (ret < 0)
1600 DPRINTF(sc, ATH_DBG_FATAL, 1524 DPRINTF(sc, ATH_DBG_FATAL,
1601 "%s: Unable to start RX aggregation\n", 1525 "%s: Unable to start RX aggregation\n",
1602 __func__); 1526 __func__);
1603 break; 1527 break;
1604 case IEEE80211_AMPDU_RX_STOP: 1528 case IEEE80211_AMPDU_RX_STOP:
1605 ret = ath_rx_aggr_stop(sc, sta->addr, tid); 1529 ret = ath_rx_aggr_stop(sc, sta, tid);
1606 if (ret < 0) 1530 if (ret < 0)
1607 DPRINTF(sc, ATH_DBG_FATAL, 1531 DPRINTF(sc, ATH_DBG_FATAL,
1608 "%s: Unable to stop RX aggregation\n", 1532 "%s: Unable to stop RX aggregation\n",
1609 __func__); 1533 __func__);
1610 break; 1534 break;
1611 case IEEE80211_AMPDU_TX_START: 1535 case IEEE80211_AMPDU_TX_START:
1612 ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn); 1536 ret = ath_tx_aggr_start(sc, sta, tid, ssn);
1613 if (ret < 0) 1537 if (ret < 0)
1614 DPRINTF(sc, ATH_DBG_FATAL, 1538 DPRINTF(sc, ATH_DBG_FATAL,
1615 "%s: Unable to start TX aggregation\n", 1539 "%s: Unable to start TX aggregation\n",
@@ -1618,7 +1542,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
1618 ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); 1542 ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
1619 break; 1543 break;
1620 case IEEE80211_AMPDU_TX_STOP: 1544 case IEEE80211_AMPDU_TX_STOP:
1621 ret = ath_tx_aggr_stop(sc, sta->addr, tid); 1545 ret = ath_tx_aggr_stop(sc, sta, tid);
1622 if (ret < 0) 1546 if (ret < 0)
1623 DPRINTF(sc, ATH_DBG_FATAL, 1547 DPRINTF(sc, ATH_DBG_FATAL,
1624 "%s: Unable to stop TX aggregation\n", 1548 "%s: Unable to stop TX aggregation\n",
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index ecffd6f45fd0..1305873b2a09 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -1867,9 +1867,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1867 /* XXX: UGLY HACK!! */ 1867 /* XXX: UGLY HACK!! */
1868 tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; 1868 tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
1869 1869
1870 spin_lock_bh(&sc->node_lock); 1870 an = (struct ath_node *)sta->drv_priv;
1871 an = ath_node_find(sc, hdr->addr1);
1872 spin_unlock_bh(&sc->node_lock);
1873 1871
1874 if (tx_info_priv == NULL) 1872 if (tx_info_priv == NULL)
1875 return; 1873 return;
@@ -1984,16 +1982,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
1984 qc = ieee80211_get_qos_ctl(hdr); 1982 qc = ieee80211_get_qos_ctl(hdr);
1985 tid = qc[0] & 0xf; 1983 tid = qc[0] & 0xf;
1986 1984
1987 spin_lock_bh(&sc->node_lock); 1985 an = (struct ath_node *)sta->drv_priv;
1988 an = ath_node_find(sc, hdr->addr1);
1989 spin_unlock_bh(&sc->node_lock);
1990
1991 if (!an) {
1992 DPRINTF(sc, ATH_DBG_AGGR,
1993 "%s: Node not found to "
1994 "init/chk TX aggr\n", __func__);
1995 return;
1996 }
1997 1986
1998 chk = ath_tx_aggr_check(sc, an, tid); 1987 chk = ath_tx_aggr_check(sc, an, tid);
1999 if (chk == AGGR_REQUIRED) { 1988 if (chk == AGGR_REQUIRED) {
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 828322840a86..6b4006ed4e01 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -1095,7 +1095,7 @@ rx_next:
1095/* Process ADDBA request in per-TID data structure */ 1095/* Process ADDBA request in per-TID data structure */
1096 1096
1097int ath_rx_aggr_start(struct ath_softc *sc, 1097int ath_rx_aggr_start(struct ath_softc *sc,
1098 const u8 *addr, 1098 struct ieee80211_sta *sta,
1099 u16 tid, 1099 u16 tid,
1100 u16 *ssn) 1100 u16 *ssn)
1101{ 1101{
@@ -1105,17 +1105,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
1105 struct ieee80211_supported_band *sband; 1105 struct ieee80211_supported_band *sband;
1106 u16 buffersize = 0; 1106 u16 buffersize = 0;
1107 1107
1108 spin_lock_bh(&sc->node_lock); 1108 an = (struct ath_node *)sta->drv_priv;
1109 an = ath_node_find(sc, (u8 *) addr);
1110 spin_unlock_bh(&sc->node_lock);
1111
1112 if (!an) {
1113 DPRINTF(sc, ATH_DBG_AGGR,
1114 "%s: Node not found to initialize RX aggregation\n",
1115 __func__);
1116 return -1;
1117 }
1118
1119 sband = hw->wiphy->bands[hw->conf.channel->band]; 1109 sband = hw->wiphy->bands[hw->conf.channel->band];
1120 buffersize = IEEE80211_MIN_AMPDU_BUF << 1110 buffersize = IEEE80211_MIN_AMPDU_BUF <<
1121 sband->ht_cap.ampdu_factor; /* FIXME */ 1111 sband->ht_cap.ampdu_factor; /* FIXME */
@@ -1172,21 +1162,9 @@ int ath_rx_aggr_start(struct ath_softc *sc,
1172 1162
1173/* Process DELBA */ 1163/* Process DELBA */
1174 1164
1175int ath_rx_aggr_stop(struct ath_softc *sc, 1165int ath_rx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
1176 const u8 *addr,
1177 u16 tid)
1178{ 1166{
1179 struct ath_node *an; 1167 struct ath_node *an = (struct ath_node *)sta->drv_priv;
1180
1181 spin_lock_bh(&sc->node_lock);
1182 an = ath_node_find(sc, (u8 *) addr);
1183 spin_unlock_bh(&sc->node_lock);
1184
1185 if (!an) {
1186 DPRINTF(sc, ATH_DBG_AGGR,
1187 "%s: RX aggr stop for non-existent node\n", __func__);
1188 return -1;
1189 }
1190 1168
1191 ath_rx_aggr_teardown(sc, an, tid); 1169 ath_rx_aggr_teardown(sc, an, tid);
1192 return 0; 1170 return 0;
@@ -1194,8 +1172,7 @@ int ath_rx_aggr_stop(struct ath_softc *sc,
1194 1172
1195/* Rx aggregation tear down */ 1173/* Rx aggregation tear down */
1196 1174
1197void ath_rx_aggr_teardown(struct ath_softc *sc, 1175void ath_rx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
1198 struct ath_node *an, u8 tid)
1199{ 1176{
1200 struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid]; 1177 struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid];
1201 1178
@@ -1253,7 +1230,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
1253 } 1230 }
1254} 1231}
1255 1232
1256void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an) 1233void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
1257{ 1234{
1258 if (sc->sc_flags & SC_OP_RXAGGR) { 1235 if (sc->sc_flags & SC_OP_RXAGGR) {
1259 struct ath_arx_tid *rxtid; 1236 struct ath_arx_tid *rxtid;
@@ -1281,10 +1258,3 @@ void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
1281 } 1258 }
1282 1259
1283} 1260}
1284
1285/* Cleanup per-node receive state */
1286
1287void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
1288{
1289 ath_rx_node_cleanup(sc, an);
1290}
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 7cfab5a542f0..64557133b227 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -214,15 +214,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
214 rt = sc->sc_currates; 214 rt = sc->sc_currates;
215 BUG_ON(!rt); 215 BUG_ON(!rt);
216 216
217 /* Fill misc fields */
218
219 spin_lock_bh(&sc->node_lock);
220 txctl->an = ath_node_get(sc, hdr->addr1);
221 /* create a temp node, if the node is not there already */
222 if (!txctl->an)
223 txctl->an = ath_node_attach(sc, hdr->addr1, 0);
224 spin_unlock_bh(&sc->node_lock);
225
226 if (ieee80211_is_data_qos(fc)) { 217 if (ieee80211_is_data_qos(fc)) {
227 qc = ieee80211_get_qos_ctl(hdr); 218 qc = ieee80211_get_qos_ctl(hdr);
228 txctl->tidno = qc[0] & 0xf; 219 txctl->tidno = qc[0] & 0xf;
@@ -496,11 +487,9 @@ unlock:
496 487
497/* Compute the number of bad frames */ 488/* Compute the number of bad frames */
498 489
499static int ath_tx_num_badfrms(struct ath_softc *sc, 490static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
500 struct ath_buf *bf, int txok) 491 int txok)
501{ 492{
502 struct ath_node *an = bf->bf_node;
503 int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
504 struct ath_buf *bf_last = bf->bf_lastbf; 493 struct ath_buf *bf_last = bf->bf_lastbf;
505 struct ath_desc *ds = bf_last->bf_desc; 494 struct ath_desc *ds = bf_last->bf_desc;
506 u16 seq_st = 0; 495 u16 seq_st = 0;
@@ -509,7 +498,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc,
509 int nbad = 0; 498 int nbad = 0;
510 int isaggr = 0; 499 int isaggr = 0;
511 500
512 if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) 501 if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
513 return 0; 502 return 0;
514 503
515 isaggr = bf_isaggr(bf); 504 isaggr = bf_isaggr(bf);
@@ -908,7 +897,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
908 u16 seq_st = 0; 897 u16 seq_st = 0;
909 u32 ba[WME_BA_BMP_SIZE >> 5]; 898 u32 ba[WME_BA_BMP_SIZE >> 5];
910 int isaggr, txfail, txpending, sendbar = 0, needreset = 0; 899 int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
911 int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
912 900
913 isaggr = bf_isaggr(bf); 901 isaggr = bf_isaggr(bf);
914 if (isaggr) { 902 if (isaggr) {
@@ -954,7 +942,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
954 /* transmit completion */ 942 /* transmit completion */
955 } else { 943 } else {
956 944
957 if (!tid->cleanup_inprogress && !isnodegone && 945 if (!tid->cleanup_inprogress &&
958 ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { 946 ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
959 if (bf->bf_retries < ATH_MAX_SW_RETRIES) { 947 if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
960 ath_tx_set_retry(sc, bf); 948 ath_tx_set_retry(sc, bf);
@@ -1083,15 +1071,6 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
1083 bf = bf_next; 1071 bf = bf_next;
1084 } 1072 }
1085 1073
1086 /*
1087 * node is already gone. no more assocication
1088 * with the node. the node might have been freed
1089 * any node acces can result in panic.note tid
1090 * is part of the node.
1091 */
1092 if (isnodegone)
1093 return;
1094
1095 if (tid->cleanup_inprogress) { 1074 if (tid->cleanup_inprogress) {
1096 /* check to see if we're done with cleaning the h/w queue */ 1075 /* check to see if we're done with cleaning the h/w queue */
1097 spin_lock_bh(&txq->axq_lock); 1076 spin_lock_bh(&txq->axq_lock);
@@ -1795,8 +1774,8 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
1795 1774
1796static void ath_tid_drain(struct ath_softc *sc, 1775static void ath_tid_drain(struct ath_softc *sc,
1797 struct ath_txq *txq, 1776 struct ath_txq *txq,
1798 struct ath_atx_tid *tid, 1777 struct ath_atx_tid *tid)
1799 bool bh_flag) 1778
1800{ 1779{
1801 struct ath_buf *bf; 1780 struct ath_buf *bf;
1802 struct list_head bf_head; 1781 struct list_head bf_head;
@@ -1817,18 +1796,12 @@ static void ath_tid_drain(struct ath_softc *sc,
1817 * do not indicate packets while holding txq spinlock. 1796 * do not indicate packets while holding txq spinlock.
1818 * unlock is intentional here 1797 * unlock is intentional here
1819 */ 1798 */
1820 if (likely(bh_flag)) 1799 spin_unlock(&txq->axq_lock);
1821 spin_unlock_bh(&txq->axq_lock);
1822 else
1823 spin_unlock(&txq->axq_lock);
1824 1800
1825 /* complete this sub-frame */ 1801 /* complete this sub-frame */
1826 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); 1802 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
1827 1803
1828 if (likely(bh_flag)) 1804 spin_lock(&txq->axq_lock);
1829 spin_lock_bh(&txq->axq_lock);
1830 else
1831 spin_lock(&txq->axq_lock);
1832 } 1805 }
1833 1806
1834 /* 1807 /*
@@ -1847,8 +1820,7 @@ static void ath_tid_drain(struct ath_softc *sc,
1847 */ 1820 */
1848 1821
1849static void ath_txq_drain_pending_buffers(struct ath_softc *sc, 1822static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
1850 struct ath_txq *txq, 1823 struct ath_txq *txq)
1851 bool bh_flag)
1852{ 1824{
1853 struct ath_atx_ac *ac, *ac_tmp; 1825 struct ath_atx_ac *ac, *ac_tmp;
1854 struct ath_atx_tid *tid, *tid_tmp; 1826 struct ath_atx_tid *tid, *tid_tmp;
@@ -1859,7 +1831,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
1859 list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { 1831 list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
1860 list_del(&tid->list); 1832 list_del(&tid->list);
1861 tid->sched = false; 1833 tid->sched = false;
1862 ath_tid_drain(sc, txq, tid, bh_flag); 1834 ath_tid_drain(sc, txq, tid);
1863 } 1835 }
1864 } 1836 }
1865} 1837}
@@ -2294,8 +2266,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
2294 * or asynchrounsly once DMA is complete. 2266 * or asynchrounsly once DMA is complete.
2295 */ 2267 */
2296 xmit_map_sg(sc, skb, &txctl); 2268 xmit_map_sg(sc, skb, &txctl);
2297 else
2298 ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
2299 2269
2300 /* failed packets will be dropped by the caller */ 2270 /* failed packets will be dropped by the caller */
2301 return error; 2271 return error;
@@ -2374,8 +2344,7 @@ void ath_tx_draintxq(struct ath_softc *sc,
2374 if (sc->sc_flags & SC_OP_TXAGGR) { 2344 if (sc->sc_flags & SC_OP_TXAGGR) {
2375 if (!retry_tx) { 2345 if (!retry_tx) {
2376 spin_lock_bh(&txq->axq_lock); 2346 spin_lock_bh(&txq->axq_lock);
2377 ath_txq_drain_pending_buffers(sc, txq, 2347 ath_txq_drain_pending_buffers(sc, txq);
2378 ATH9K_BH_STATUS_CHANGE);
2379 spin_unlock_bh(&txq->axq_lock); 2348 spin_unlock_bh(&txq->axq_lock);
2380 } 2349 }
2381 } 2350 }
@@ -2441,24 +2410,13 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
2441 2410
2442/* Start TX aggregation */ 2411/* Start TX aggregation */
2443 2412
2444int ath_tx_aggr_start(struct ath_softc *sc, 2413int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
2445 const u8 *addr, 2414 u16 tid, u16 *ssn)
2446 u16 tid,
2447 u16 *ssn)
2448{ 2415{
2449 struct ath_atx_tid *txtid; 2416 struct ath_atx_tid *txtid;
2450 struct ath_node *an; 2417 struct ath_node *an;
2451 2418
2452 spin_lock_bh(&sc->node_lock); 2419 an = (struct ath_node *)sta->drv_priv;
2453 an = ath_node_find(sc, (u8 *) addr);
2454 spin_unlock_bh(&sc->node_lock);
2455
2456 if (!an) {
2457 DPRINTF(sc, ATH_DBG_AGGR,
2458 "%s: Node not found to initialize "
2459 "TX aggregation\n", __func__);
2460 return -1;
2461 }
2462 2420
2463 if (sc->sc_flags & SC_OP_TXAGGR) { 2421 if (sc->sc_flags & SC_OP_TXAGGR) {
2464 txtid = ATH_AN_2_TID(an, tid); 2422 txtid = ATH_AN_2_TID(an, tid);
@@ -2471,21 +2429,9 @@ int ath_tx_aggr_start(struct ath_softc *sc,
2471 2429
2472/* Stop tx aggregation */ 2430/* Stop tx aggregation */
2473 2431
2474int ath_tx_aggr_stop(struct ath_softc *sc, 2432int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
2475 const u8 *addr,
2476 u16 tid)
2477{ 2433{
2478 struct ath_node *an; 2434 struct ath_node *an = (struct ath_node *)sta->drv_priv;
2479
2480 spin_lock_bh(&sc->node_lock);
2481 an = ath_node_find(sc, (u8 *) addr);
2482 spin_unlock_bh(&sc->node_lock);
2483
2484 if (!an) {
2485 DPRINTF(sc, ATH_DBG_AGGR,
2486 "%s: TX aggr stop for non-existent node\n", __func__);
2487 return -1;
2488 }
2489 2435
2490 ath_tx_aggr_teardown(sc, an, tid); 2436 ath_tx_aggr_teardown(sc, an, tid);
2491 return 0; 2437 return 0;
@@ -2498,8 +2444,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc,
2498 * - Discard all retry frames from the s/w queue. 2444 * - Discard all retry frames from the s/w queue.
2499 */ 2445 */
2500 2446
2501void ath_tx_aggr_teardown(struct ath_softc *sc, 2447void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
2502 struct ath_node *an, u8 tid)
2503{ 2448{
2504 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); 2449 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
2505 struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum]; 2450 struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
@@ -2625,8 +2570,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2625 struct ath_atx_ac *ac; 2570 struct ath_atx_ac *ac;
2626 int tidno, acno; 2571 int tidno, acno;
2627 2572
2628 an->maxampdu = ATH_AMPDU_LIMIT_DEFAULT;
2629
2630 /* 2573 /*
2631 * Init per tid tx state 2574 * Init per tid tx state
2632 */ 2575 */
@@ -2684,8 +2627,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2684 2627
2685/* Cleanupthe pending buffers for the node. */ 2628/* Cleanupthe pending buffers for the node. */
2686 2629
2687void ath_tx_node_cleanup(struct ath_softc *sc, 2630void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
2688 struct ath_node *an, bool bh_flag)
2689{ 2631{
2690 int i; 2632 int i;
2691 struct ath_atx_ac *ac, *ac_tmp; 2633 struct ath_atx_ac *ac, *ac_tmp;
@@ -2695,10 +2637,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
2695 if (ATH_TXQ_SETUP(sc, i)) { 2637 if (ATH_TXQ_SETUP(sc, i)) {
2696 txq = &sc->sc_txq[i]; 2638 txq = &sc->sc_txq[i];
2697 2639
2698 if (likely(bh_flag)) 2640 spin_lock(&txq->axq_lock);
2699 spin_lock_bh(&txq->axq_lock);
2700 else
2701 spin_lock(&txq->axq_lock);
2702 2641
2703 list_for_each_entry_safe(ac, 2642 list_for_each_entry_safe(ac,
2704 ac_tmp, &txq->axq_acq, list) { 2643 ac_tmp, &txq->axq_acq, list) {
@@ -2713,17 +2652,14 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
2713 tid_tmp, &ac->tid_q, list) { 2652 tid_tmp, &ac->tid_q, list) {
2714 list_del(&tid->list); 2653 list_del(&tid->list);
2715 tid->sched = false; 2654 tid->sched = false;
2716 ath_tid_drain(sc, txq, tid, bh_flag); 2655 ath_tid_drain(sc, txq, tid);
2717 tid->addba_exchangecomplete = 0; 2656 tid->addba_exchangecomplete = 0;
2718 tid->addba_exchangeattempts = 0; 2657 tid->addba_exchangeattempts = 0;
2719 tid->cleanup_inprogress = false; 2658 tid->cleanup_inprogress = false;
2720 } 2659 }
2721 } 2660 }
2722 2661
2723 if (likely(bh_flag)) 2662 spin_unlock(&txq->axq_lock);
2724 spin_unlock_bh(&txq->axq_lock);
2725 else
2726 spin_unlock(&txq->axq_lock);
2727 } 2663 }
2728 } 2664 }
2729} 2665}
@@ -2794,7 +2730,6 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
2794 */ 2730 */
2795 xmit_map_sg(sc, skb, &txctl); 2731 xmit_map_sg(sc, skb, &txctl);
2796 } else { 2732 } else {
2797 ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
2798 DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__); 2733 DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
2799 dev_kfree_skb_any(skb); 2734 dev_kfree_skb_any(skb);
2800 } 2735 }