Changeset 50

Show
Ignore:
Timestamp:
03/15/03 19:32:09 (7 years ago)
Author:
sam
Message:

Replicated Change 84 by sam@borg_greg on 2003/03/04 17:52:26<<<

o eliminate bsd-style send q; use direct calls that go all the

way to ath_tx_start (sc_sndq and sc_oactive die)

o split data/mgmt frame sends into separate routines and hookup the

mgmt frame send the wlan module

o update ath statistics block for linux
o eliminate unused sc_enable and sc_disable (inherited from netbsd)
o redo tasklet scheduling in ath_intr to only mark bottom half once

at the end of the handler; this reduces code bloat caused by linux
inline functions

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • cvs-import/trunk/driver/if_ath.c

    r47 r50  
    4747#include "ah_desc.h" 
    4848 
    49 #define ATH_SCHEDTASK(_tq) do {                                         \ 
    50         if (queue_task(_tq, &tq_immediate))                             \ 
    51                 mark_bh(IMMEDIATE_BH);                                  \ 
    52 } while (0); 
    53  
    5449#define TXBUF_DEQUEUE(_sc, _bf) do {                                    \ 
    5550        spin_lock(&(_sc)->sc_txbuflock);                                \ 
     
    7974static void     ath_bmiss_tasklet(void *); 
    8075static int      ath_stop(struct net_device *); 
    81 static void     ath_start(struct net_device *); 
    8276static void     ath_watchdog(struct net_device *); 
    8377static void     ath_mode_init(struct net_device *); 
     
    9185static void     ath_rx_tasklet(void *); 
    9286static int      ath_hardstart(struct sk_buff *, struct net_device *); 
     87static int      ath_mgtstart(struct sk_buff *, struct net_device *); 
    9388static int      ath_tx_start(struct ath_softc *, struct ieee80211_node *, 
    9489                             struct ath_buf *, struct sk_buff *); 
     
    145140        DPRINTF(("ath_attach: devid 0x%x\n", devid)); 
    146141 
    147         skb_queue_head_init(&sc->sc_sndq); 
    148142        spin_lock_init(&sc->sc_txbuflock); 
    149143        spin_lock_init(&sc->sc_txqlock); 
     
    229223 
    230224        ic->ic_watchdog = ath_watchdog; 
    231         ic->ic_start = ath_start; 
     225        ic->ic_mgtstart = ath_mgtstart; 
    232226        ic->ic_init = ath_init; 
    233227 
     
    324318} 
    325319 
     320/* 
     321 * Interrupt handler.  All the actual processing is 
     322 * deferred to tasklets. 
     323 */ 
    326324void 
    327325ath_intr(int irq, void *dev_id, struct pt_regs *regs) 
     
    330328        struct ath_softc *sc = dev->priv; 
    331329        struct ath_hal *ah = sc->sc_ah; 
    332         HAL_INT status
    333         int i; 
    334  
     330        int i, needmark
     331 
     332        needmark = 0; 
    335333        for (i = 0; i < 10 && ath_hal_intrpend(ah); i++) { 
     334                HAL_INT status; 
     335 
    336336                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)); 
    339338                if (status & HAL_INT_FATAL) { 
    340                         ATH_SCHEDTASK(&sc->sc_fataltq); 
     339                        needmark |= queue_task(&sc->sc_fataltq, &tq_immediate); 
    341340                        break;          /* XXX??? */ 
    342341                } 
    343342                if (status & HAL_INT_RXORN) { 
    344                         ATH_SCHEDTASK(&sc->sc_rxorntq); 
     343                        needmark |= queue_task(&sc->sc_rxorntq, &tq_immediate); 
    345344                        break;          /* XXX??? */ 
    346345                } 
     
    356355 
    357356                if (status & HAL_INT_RX) 
    358                         ATH_SCHEDTASK(&sc->sc_rxtq); 
     357                        needmark |= queue_task(&sc->sc_rxtq, &tq_immediate); 
    359358                if (status & HAL_INT_TX) 
    360                         ATH_SCHEDTASK(&sc->sc_txtq); 
     359                        needmark |= queue_task(&sc->sc_txtq, &tq_immediate); 
    361360                if (status & HAL_INT_SWBA) 
    362                         ATH_SCHEDTASK(&sc->sc_swbatq); 
     361                        needmark |= queue_task(&sc->sc_swbatq, &tq_immediate); 
    363362#if 0 
    364363                if (status & (HAL_INT_BMISS | HAL_INT_RXNOFRM)) { 
    365364DPRINTF(("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); 
    367366                } 
    368367#endif 
     
    370369        if (i == 10) 
    371370                printk("%s: intr processing stopped prematurely\n", dev->name); 
     371        if (needmark) 
     372                mark_bh(IMMEDIATE_BH); 
    372373} 
    373374 
     
    481482                val |= HAL_INT_SWBA;                    /* beacon prepare */ 
    482483        ath_hal_intrset(ah, val | HAL_INT_GLOBAL); 
    483  
    484         netif_start_queue(dev); 
    485484 
    486485        /* 
     
    542541        ath_beacon_free(sc); 
    543542        sc->sc_txlink = sc->sc_rxlink = NULL; 
    544         sc->sc_oactive = 0; 
    545543        sc->sc_ic.ic_timer = 0; 
    546544        sc->sc_tx_timer = 0; 
    547         skb_queue_purge(&sc->sc_sndq); 
    548545 
    549546        /* free transmit queue */ 
     
    562559 
    563560/* 
    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. 
    567563 */ 
    568564static int 
     
    570566{ 
    571567        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... */ 
     653bad: 
     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 */ 
     663static int 
     664ath_mgtstart(struct sk_buff *skb, struct net_device *dev) 
    581665{ 
    582666        struct ath_softc *sc = dev->priv; 
     
    584668        struct ieee80211com *ic = &sc->sc_ic; 
    585669        struct ieee80211_node *ni; 
    586         struct ath_buf *bf; 
    587         struct sk_buff *skb; 
     670        struct ath_buf *bf = NULL; 
    588671        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++; 
    685722                sc->sc_tx_timer = 5; 
    686723                ic->ic_timer = 1; 
    687         } 
     724                return 0; 
     725        } 
     726        /* fall thru... */ 
     727bad: 
     728        if (bf != NULL) 
     729                TXBUF_QUEUE_TAIL(sc, bf); 
     730        dev_kfree_skb(skb); 
     731        ic->ic_stats.tx_errors++; 
     732        return error; 
    688733} 
    689734 
     
    696741 
    697742        ic->ic_timer = 0; 
    698         if (sc->sc_invalid) 
    699                 return; 
    700743        if (sc->sc_tx_timer) { 
    701744                if (--sc->sc_tx_timer == 0) { 
     
    13091352 
    13101353        ath_hal_txstart(ah); 
     1354        sc->sc_ic.ic_stats.tx_packets++; 
    13111355 
    13121356        return 0; 
     
    13681412                TXBUF_QUEUE_TAIL(sc, bf); 
    13691413        } 
    1370         sc->sc_oactive = 0; 
    13711414        sc->sc_tx_timer = 0; 
    1372         ath_start(dev); 
    13731415} 
    13741416 
     
    14121454        } 
    14131455 
    1414         sc->sc_oactive = 0; 
    14151456        sc->sc_tx_timer = 0; 
    14161457} 
     
    18281869        } 
    18291870#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); 
    18331874        STAT(rx_crcerr); STAT(rx_fifoerr); STAT(rx_badcrypt); 
    18341875        STAT(rx_phyerr); STAT(rx_phy_tim); STAT(rx_phy_par); 
  • cvs-import/trunk/driver/if_athvar.h

    r46 r50  
    5252struct ath_stats { 
    5353        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 */ 
    5456        u_int32_t       ast_tx_encap;   /* tx encapsulation failed */ 
    5557        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 */ 
    5959        u_int32_t       ast_tx_nodata;  /* tx discarded empty frame */ 
    60         u_int32_t       ast_tx_busdma;  /* tx failed for dma resrcs */ 
    6160        u_int32_t       ast_tx_descerr; /* tx failure reported in desc*/ 
    6261        u_int32_t       ast_rx_crcerr;  /* rx failed 'cuz of bad CRC */ 
     
    9089        struct ath_hal          *sc_ah;         /* Atheros HAL */ 
    9190        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 */ 
    9692        int                     sc_cachelsz;    /* system cache line size */ 
    9793        struct ath_desc         *sc_desc;       /* TX/RX descriptors */ 
     
    109105        u_int32_t               *sc_txlink;     /* link ptr in last TX desc */ 
    110106        int                     sc_tx_timer;    /* tx timeout */ 
    111         struct sk_buff_head     sc_sndq;        /* data packet queue */ 
    112107        TAILQ_HEAD(, ath_buf)   sc_txbuf;       /* tx buffer queue */ 
    113108        spinlock_t              sc_txbuflock;   /* txbuf lock */