Changeset 50
- Timestamp:
- 03/15/03 19:32:09 (5 years ago)
- Files:
-
- cvs-import/trunk/driver/if_ath.c (modified) (19 diffs)
- cvs-import/trunk/driver/if_athvar.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cvs-import/trunk/driver/if_ath.c
r47 r50 47 47 #include "ah_desc.h" 48 48 49 #define ATH_SCHEDTASK(_tq) do { \50 if (queue_task(_tq, &tq_immediate)) \51 mark_bh(IMMEDIATE_BH); \52 } while (0);53 54 49 #define TXBUF_DEQUEUE(_sc, _bf) do { \ 55 50 spin_lock(&(_sc)->sc_txbuflock); \ … … 79 74 static void ath_bmiss_tasklet(void *); 80 75 static int ath_stop(struct net_device *); 81 static void ath_start(struct net_device *);82 76 static void ath_watchdog(struct net_device *); 83 77 static void ath_mode_init(struct net_device *); … … 91 85 static void ath_rx_tasklet(void *); 92 86 static int ath_hardstart(struct sk_buff *, struct net_device *); 87 static int ath_mgtstart(struct sk_buff *, struct net_device *); 93 88 static int ath_tx_start(struct ath_softc *, struct ieee80211_node *, 94 89 struct ath_buf *, struct sk_buff *); … … 145 140 DPRINTF(("ath_attach: devid 0x%x\n", devid)); 146 141 147 skb_queue_head_init(&sc->sc_sndq);148 142 spin_lock_init(&sc->sc_txbuflock); 149 143 spin_lock_init(&sc->sc_txqlock); … … 229 223 230 224 ic->ic_watchdog = ath_watchdog; 231 ic->ic_ start = ath_start;225 ic->ic_mgtstart = ath_mgtstart; 232 226 ic->ic_init = ath_init; 233 227 … … 324 318 } 325 319 320 /* 321 * Interrupt handler. All the actual processing is 322 * deferred to tasklets. 323 */ 326 324 void 327 325 ath_intr(int irq, void *dev_id, struct pt_regs *regs) … … 330 328 struct ath_softc *sc = dev->priv; 331 329 struct ath_hal *ah = sc->sc_ah; 332 HAL_INT status;333 int i; 334 330 int i, needmark; 331 332 needmark = 0; 335 333 for (i = 0; i < 10 && ath_hal_intrpend(ah); i++) { 334 HAL_INT status; 335 336 336 ath_hal_getisr(ah, &status); 337 DPRINTF(("%s: interrupt, status 0x%x\n", 338 dev->name, status)); 337 DPRINTF(("%s: interrupt, status 0x%x\n", dev->name, status)); 339 338 if (status & HAL_INT_FATAL) { 340 ATH_SCHEDTASK(&sc->sc_fataltq);339 needmark |= queue_task(&sc->sc_fataltq, &tq_immediate); 341 340 break; /* XXX??? */ 342 341 } 343 342 if (status & HAL_INT_RXORN) { 344 ATH_SCHEDTASK(&sc->sc_rxorntq);343 needmark |= queue_task(&sc->sc_rxorntq, &tq_immediate); 345 344 break; /* XXX??? */ 346 345 } … … 356 355 357 356 if (status & HAL_INT_RX) 358 ATH_SCHEDTASK(&sc->sc_rxtq);357 needmark |= queue_task(&sc->sc_rxtq, &tq_immediate); 359 358 if (status & HAL_INT_TX) 360 ATH_SCHEDTASK(&sc->sc_txtq);359 needmark |= queue_task(&sc->sc_txtq, &tq_immediate); 361 360 if (status & HAL_INT_SWBA) 362 ATH_SCHEDTASK(&sc->sc_swbatq);361 needmark |= queue_task(&sc->sc_swbatq, &tq_immediate); 363 362 #if 0 364 363 if (status & (HAL_INT_BMISS | HAL_INT_RXNOFRM)) { 365 364 DPRINTF(("ath_intr: beacon miss | rxnofrm: status 0x%x\n", status)); 366 ATH_SCHEDTASK(&sc->sc_bmisstq);365 needmark |= queue_task(&sc->sc_bmisstq, &tq_immediate); 367 366 } 368 367 #endif … … 370 369 if (i == 10) 371 370 printk("%s: intr processing stopped prematurely\n", dev->name); 371 if (needmark) 372 mark_bh(IMMEDIATE_BH); 372 373 } 373 374 … … 481 482 val |= HAL_INT_SWBA; /* beacon prepare */ 482 483 ath_hal_intrset(ah, val | HAL_INT_GLOBAL); 483 484 netif_start_queue(dev);485 484 486 485 /* … … 542 541 ath_beacon_free(sc); 543 542 sc->sc_txlink = sc->sc_rxlink = NULL; 544 sc->sc_oactive = 0;545 543 sc->sc_ic.ic_timer = 0; 546 544 sc->sc_tx_timer = 0; 547 skb_queue_purge(&sc->sc_sndq);548 545 549 546 /* free transmit queue */ … … 562 559 563 560 /* 564 * Accept packets from above; we queue them and kick the common 565 * start code. This is very un-Linux like but insures any management 566 * frames get priority w/o totally mangling the existing logic. 561 * Transmit a data packet. On failure caller is 562 * assumed to reclaim the resources. 567 563 */ 568 564 static int … … 570 566 { 571 567 struct ath_softc *sc = dev->priv; 572 573 skb_queue_tail(&sc->sc_sndq, skb); 574 if (!sc->sc_oactive) 575 ath_start(dev); 576 return 0; 577 } 578 579 static void 580 ath_start(struct net_device *dev) 568 struct ieee80211com *ic = &sc->sc_ic; 569 struct ieee80211_node *ni; 570 struct ath_buf *bf = NULL; 571 struct ieee80211_frame *wh; 572 int error; 573 574 if (sc->sc_invalid) { 575 DPRINTF(("ath_hardstart: discard, invalid\n")); 576 error = -ENETDOWN; 577 goto bad; 578 } 579 /* 580 * No data frames go out unless we're associated; this 581 * should not happen as the 802.11 layer does not enable 582 * the xmit queue until we enter the RUN state. 583 */ 584 if (ic->ic_state != IEEE80211_S_RUN) { 585 DPRINTF(("ath_hardstart: discard, state %u\n", ic->ic_state)); 586 sc->sc_stats.ast_tx_discard++; 587 error = -ENETDOWN; 588 goto bad; 589 } 590 /* 591 * Grab a TX buffer and associated resources. 592 */ 593 TXBUF_DEQUEUE(sc, bf); 594 if (bf == NULL) { 595 DPRINTF(("ath_hardstart: discard, no xmit buf\n")); 596 sc->sc_stats.ast_tx_nobuf++; 597 error = -ENOBUFS; 598 goto bad; 599 } 600 /* 601 * Encapsulate the packet for transmission. 602 */ 603 skb = ieee80211_encap(dev, skb); 604 if (skb == NULL) { 605 DPRINTF(("ath_hardstart: discard, encapsulation failure\n")); 606 sc->sc_stats.ast_tx_encap++; 607 #ifdef notdef 608 error = -ENOMEM; 609 #else 610 /* 611 * Can't return an error code here because the caller 612 * reclaims the skbuff on error and it's already gone. 613 */ 614 error = 0; 615 #endif 616 goto bad; 617 } 618 wh = (struct ieee80211_frame *) skb->data; 619 if (ic->ic_flags & IEEE80211_F_WEPON) 620 wh->i_fc[1] |= IEEE80211_FC1_WEP; 621 622 ni = ieee80211_find_node(ic, wh->i_addr1); 623 if (ni == NULL && 624 !IEEE80211_IS_MULTICAST(wh->i_addr1) && 625 ic->ic_opmode != IEEE80211_M_STA) { 626 DPRINTF(("ath_hardstart: discard, no destination state\n")); 627 sc->sc_stats.ast_tx_nonode++; 628 error = -EHOSTUNREACH; 629 goto bad; 630 } 631 if (ni == NULL) 632 ni = &ic->ic_bss; 633 634 /* 635 * TODO: 636 * The duration field of 802.11 header should be filled. 637 * XXX This may be done in the ieee80211 layer, but the upper 638 * doesn't know the detail of parameters such as IFS 639 * for now.. 640 */ 641 642 if (IFF_DUMPPKTS(ic)) 643 ieee80211_dump_pkt(skb->data, skb->len, 644 ni->ni_rates[ni->ni_txrate] & IEEE80211_RATE_VAL, -1); 645 646 error = ath_tx_start(sc, ni, bf, skb); 647 if (error == 0) { 648 sc->sc_tx_timer = 5; 649 ic->ic_timer = 1; 650 return 0; 651 } 652 /* fall thru... */ 653 bad: 654 if (bf != NULL) 655 TXBUF_QUEUE_TAIL(sc, bf); 656 ic->ic_stats.tx_errors++; 657 return error; 658 } 659 660 /* 661 * Transmit a management frame. On failure we reclaim the skbuff. 662 */ 663 static int 664 ath_mgtstart(struct sk_buff *skb, struct net_device *dev) 581 665 { 582 666 struct ath_softc *sc = dev->priv; … … 584 668 struct ieee80211com *ic = &sc->sc_ic; 585 669 struct ieee80211_node *ni; 586 struct ath_buf *bf; 587 struct sk_buff *skb; 670 struct ath_buf *bf = NULL; 588 671 struct ieee80211_frame *wh; 589 590 if (sc->sc_invalid) 591 return; 592 for (;;) { 593 /* 594 * Grab a TX buffer and associated resources. 595 */ 596 TXBUF_DEQUEUE(sc, bf); 597 if (bf == NULL) { 598 sc->sc_oactive = 0; 599 DPRINTF(("ath_start: out of xmit buffers\n")); 600 break; 601 } 602 /* 603 * Poll the management queue for frames; they 604 * have priority over normal data frames. 605 */ 606 skb = skb_dequeue(&ic->ic_mgtq); 607 if (skb != NULL) { 608 wh = (struct ieee80211_frame *) skb->data; 609 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 610 IEEE80211_FC0_SUBTYPE_PROBE_RESP) { 611 /* fill time stamp */ 612 u_int64_t tsf; 613 u_int32_t *tstamp; 614 615 tsf = ath_hal_gettsf(ah); 616 /* XXX: adjust 100us delay to xmit */ 617 tsf += 100; 618 tstamp = (u_int32_t *)&wh[1]; 619 tstamp[0] = cpu_to_le32(tsf & 0xffffffff); 620 tstamp[1] = cpu_to_le32(tsf >> 32); 621 } 622 } else { 623 /* 624 * No data frames go out unless we're associated. 625 */ 626 if (ic->ic_state != IEEE80211_S_RUN) { 627 DPRINTF(("ath_start: discard data packet, " 628 "state %u\n", ic->ic_state)); 629 TXBUF_QUEUE_TAIL(sc, bf); 630 break; 631 } 632 skb = skb_dequeue(&sc->sc_sndq); 633 if (skb == NULL) { 634 TXBUF_QUEUE_TAIL(sc, bf); 635 break; 636 } 637 ic->ic_stats.tx_packets++; 638 /* 639 * Encapsulate the packet in prep for transmission. 640 */ 641 skb = ieee80211_encap(dev, skb); 642 if (skb == NULL) { 643 DPRINTF(("ath_start: encapsulation failure\n")); 644 sc->sc_stats.ast_tx_encap++; 645 goto txerror; 646 } 647 wh = (struct ieee80211_frame *) skb->data; 648 if (ic->ic_flags & IEEE80211_F_WEPON) 649 wh->i_fc[1] |= IEEE80211_FC1_WEP; 650 } 651 652 ni = ieee80211_find_node(ic, wh->i_addr1); 653 if (ni == NULL && 654 !IEEE80211_IS_MULTICAST(wh->i_addr1) && 655 ic->ic_opmode != IEEE80211_M_STA && 656 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 657 IEEE80211_FC0_TYPE_DATA) { 658 dev_kfree_skb(skb); 659 sc->sc_stats.ast_tx_nonode++; 660 goto txerror; 661 } 662 if (ni == NULL) 663 ni = &ic->ic_bss; 664 665 /* 666 * TODO: 667 * The duration field of 802.11 header should be filled. 668 * XXX This may be done in the ieee80211 layer, but the upper 669 * doesn't know the detail of parameters such as IFS 670 * for now.. 671 */ 672 673 if (IFF_DUMPPKTS(ic)) 674 ieee80211_dump_pkt(skb->data, skb->len, 675 ni->ni_rates[ni->ni_txrate] & IEEE80211_RATE_VAL, 676 -1); 677 678 if (ath_tx_start(sc, ni, bf, skb)) { 679 txerror: 680 ic->ic_stats.tx_errors++; 681 TXBUF_QUEUE_TAIL(sc, bf); 682 continue; 683 } 684 672 int error; 673 674 if (sc->sc_invalid) { 675 DPRINTF(("ath_mgtstart: discard, invalid\n")); 676 error = -ENETDOWN; 677 goto bad; 678 } 679 /* 680 * Grab a TX buffer and associated resources. 681 */ 682 TXBUF_DEQUEUE(sc, bf); 683 if (bf == NULL) { 684 DPRINTF(("ath_mgtstart: discard, no xmit buf\n")); 685 sc->sc_stats.ast_tx_nobuf++; 686 error = -ENOBUFS; 687 goto bad; 688 } 689 wh = (struct ieee80211_frame *) skb->data; 690 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 691 IEEE80211_FC0_SUBTYPE_PROBE_RESP) { 692 /* fill time stamp */ 693 u_int64_t tsf; 694 u_int32_t *tstamp; 695 696 tsf = ath_hal_gettsf(ah); 697 /* XXX: adjust 100us delay to xmit */ 698 tsf += 100; 699 tstamp = (u_int32_t *)&wh[1]; 700 tstamp[0] = cpu_to_le32(tsf & 0xffffffff); 701 tstamp[1] = cpu_to_le32(tsf >> 32); 702 } 703 ni = ieee80211_find_node(ic, wh->i_addr1); 704 if (ni == NULL) 705 ni = &ic->ic_bss; 706 707 /* 708 * TODO: 709 * The duration field of 802.11 header should be filled. 710 * XXX This may be done in the ieee80211 layer, but the upper 711 * doesn't know the detail of parameters such as IFS 712 * for now.. 713 */ 714 715 if (IFF_DUMPPKTS(ic)) 716 ieee80211_dump_pkt(skb->data, skb->len, 717 ni->ni_rates[ni->ni_txrate] & IEEE80211_RATE_VAL, -1); 718 719 error = ath_tx_start(sc, ni, bf, skb); 720 if (error == 0) { 721 sc->sc_stats.ast_tx_mgmt++; 685 722 sc->sc_tx_timer = 5; 686 723 ic->ic_timer = 1; 687 } 724 return 0; 725 } 726 /* fall thru... */ 727 bad: 728 if (bf != NULL) 729 TXBUF_QUEUE_TAIL(sc, bf); 730 dev_kfree_skb(skb); 731 ic->ic_stats.tx_errors++; 732 return error; 688 733 } 689 734 … … 696 741 697 742 ic->ic_timer = 0; 698 if (sc->sc_invalid)699 return;700 743 if (sc->sc_tx_timer) { 701 744 if (--sc->sc_tx_timer == 0) { … … 1309 1352 1310 1353 ath_hal_txstart(ah); 1354 sc->sc_ic.ic_stats.tx_packets++; 1311 1355 1312 1356 return 0; … … 1368 1412 TXBUF_QUEUE_TAIL(sc, bf); 1369 1413 } 1370 sc->sc_oactive = 0;1371 1414 sc->sc_tx_timer = 0; 1372 ath_start(dev);1373 1415 } 1374 1416 … … 1412 1454 } 1413 1455 1414 sc->sc_oactive = 0;1415 1456 sc->sc_tx_timer = 0; 1416 1457 } … … 1828 1869 } 1829 1870 #define STAT(x) cp += sprintf(cp, #x "=%u\n", sc->sc_stats.ast_##x) 1830 STAT(watchdog); STAT(tx_ encap); STAT(tx_nonode);1831 STAT(tx_ nombuf); STAT(tx_nomcl); STAT(tx_linear);1832 STAT(tx_nodata); STAT(tx_ busdma); STAT(tx_descerr);1871 STAT(watchdog); STAT(tx_mgmt); STAT(tx_discard); 1872 STAT(tx_encap); STAT(tx_nonode); STAT(tx_nobuf); 1873 STAT(tx_nodata); STAT(tx_descerr); 1833 1874 STAT(rx_crcerr); STAT(rx_fifoerr); STAT(rx_badcrypt); 1834 1875 STAT(rx_phyerr); STAT(rx_phy_tim); STAT(rx_phy_par); cvs-import/trunk/driver/if_athvar.h
r46 r50 52 52 struct ath_stats { 53 53 u_int32_t ast_watchdog; /* device reset by watchdog */ 54 u_int32_t ast_tx_mgmt; /* management frames transmitted */ 55 u_int32_t ast_tx_discard; /* frames discarded prior to assoc */ 54 56 u_int32_t ast_tx_encap; /* tx encapsulation failed */ 55 57 u_int32_t ast_tx_nonode; /* tx failed 'cuz no node */ 56 u_int32_t ast_tx_nombuf; /* tx failed 'cuz no mbuf */ 57 u_int32_t ast_tx_nomcl; /* tx failed 'cuz no cluster */ 58 u_int32_t ast_tx_linear; /* tx linearized to cluster */ 58 u_int32_t ast_tx_nobuf; /* tx failed 'cuz no tx buffer */ 59 59 u_int32_t ast_tx_nodata; /* tx discarded empty frame */ 60 u_int32_t ast_tx_busdma; /* tx failed for dma resrcs */61 60 u_int32_t ast_tx_descerr; /* tx failure reported in desc*/ 62 61 u_int32_t ast_rx_crcerr; /* rx failed 'cuz of bad CRC */ … … 90 89 struct ath_hal *sc_ah; /* Atheros HAL */ 91 90 struct pci_dev *sc_pdev; /* associated pci device */ 92 int (*sc_enable)(struct ath_softc *); 93 void (*sc_disable)(struct ath_softc *); 94 unsigned int sc_invalid : 1,/* being detached */ 95 sc_oactive : 1;/* output processing active */ 91 volatile int sc_invalid; /* being detached */ 96 92 int sc_cachelsz; /* system cache line size */ 97 93 struct ath_desc *sc_desc; /* TX/RX descriptors */ … … 109 105 u_int32_t *sc_txlink; /* link ptr in last TX desc */ 110 106 int sc_tx_timer; /* tx timeout */ 111 struct sk_buff_head sc_sndq; /* data packet queue */112 107 TAILQ_HEAD(, ath_buf) sc_txbuf; /* tx buffer queue */ 113 108 spinlock_t sc_txbuflock; /* txbuf lock */
