00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include <linux/config.h>
00054 #include <linux/version.h>
00055 #include <linux/module.h>
00056 #include <linux/init.h>
00057 #include <linux/skbuff.h>
00058 #include <linux/netdevice.h>
00059 #include <linux/random.h>
00060
00061 #include <linux/delay.h>
00062 #include <linux/cache.h>
00063 #include <linux/sysctl.h>
00064 #include <linux/proc_fs.h>
00065 #include <linux/if_arp.h>
00066 #include <linux/wait.h>
00067 #include <linux/timer.h>
00068
00069
00070 #include <linux/netdevice.h>
00071 #include <linux/etherdevice.h>
00072 #include <linux/if_ether.h>
00073 #include <asm/uaccess.h>
00074 #include "../../click_wifi/packet_anno.h"
00075
00076 #define AR_DEBUG
00077 #include "if_athvar.h"
00078 #include "ah_desc.h"
00079 #include "ah_devid.h"
00080 #include "if_llc.h"
00081
00082 #include "if_ath_bus.h"
00083 #include "if_ethersubr.h"
00084
00085
00086 #ifndef timeradd
00087 # define timeradd(a, b, result) \
00088 do { \
00089 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
00090 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
00091 if ((result)->tv_usec >= 1000000) \
00092 { \
00093 ++(result)->tv_sec; \
00094 (result)->tv_usec -= 1000000; \
00095 } \
00096 } while (0)
00097 #endif
00098
00099 #ifndef timersub
00100 # define timersub(a, b, result) \
00101 do { \
00102 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
00103 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
00104 if ((result)->tv_usec < 0) { \
00105 --(result)->tv_sec; \
00106 (result)->tv_usec += 1000000; \
00107 } \
00108 } while (0)
00109 #endif
00110
00111 #define LE_READ_2(p) \
00112 ((u_int16_t) \
00113 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8)))
00114 #define LE_READ_4(p) \
00115 ((u_int32_t) \
00116 ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
00117 (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
00118
00119 static int ath_init(struct net_device *);
00120 static int ath_reset(struct net_device *);
00121 static void ath_fatal_tasklet(TQUEUE_ARG);
00122 static void ath_rxorn_tasklet(TQUEUE_ARG);
00123 static int ath_stop(struct net_device *);
00124 static void ath_initkeytable(struct net_device *);
00125 static void ath_mode_init(struct net_device *);
00126 static int ath_desc_alloc(struct ath_softc *);
00127 static void ath_desc_free(struct ath_softc *);
00128 static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
00129 static void ath_rx_tasklet(TQUEUE_ARG data);
00130 static int ath_tx_setup(struct ath_softc *, int ac, int txq);
00131 static int ath_hardstart(struct sk_buff *, struct net_device *);
00132 static int ath_tx_start(struct net_device *,
00133 struct ath_buf *, struct sk_buff *);
00134 static void ath_tx_tasklet(TQUEUE_ARG data);
00135 static void ath_tx_timeout(struct net_device *);
00136 static void ath_draintxq(struct ath_softc *);
00137 static void ath_stoprecv(struct ath_softc *);
00138 static int ath_startrecv(struct net_device *);
00139 static void ath_calibrate(unsigned long);
00140 static struct net_device_stats *ath_getstats(struct net_device *);
00141 static int ath_getchannels(struct net_device *, u_int cc,
00142 HAL_BOOL outdoor, HAL_BOOL xchanmode);
00143 static void ath_update_led(struct ath_softc *, u_int16_t);
00144
00145 static int ath_set_mac_address(struct net_device *, void *);
00146 static int ath_change_mtu(struct net_device *, int);
00147 static int ath_ioctl(struct net_device *, struct ifreq *, int);
00148
00149 static int ath_setchannel(struct ath_softc *, struct ieee80211channel *channel);
00150
00151 #ifdef CONFIG_SYSCTL
00152 static void ath_dynamic_sysctl_register(struct ath_softc *);
00153 static void ath_dynamic_sysctl_unregister(struct ath_softc *);
00154 #endif
00155 static void ath_announce(struct net_device *);
00156
00157 static int ath_rate_setup(struct net_device *dev, u_int mode);
00158 static int ath_dwelltime = 200;
00159 static int ath_calinterval = 30;
00160 static int ath_countrycode = CTRY_DEFAULT;
00161 static int ath_regdomain = 0;
00162 static int ath_outdoor = AH_TRUE;
00163 static int ath_xchanmode = AH_TRUE;
00164 static int ath_phyerr = AH_FALSE;
00165
00166 #ifdef AR_DEBUG
00167 int ath_debug = 0;
00168 #define IFF_DUMPPKTS(_ic) (ath_debug)
00169 static void ath_printrxbuf(struct ath_buf *bf, int);
00170 static void ath_printtxbuf(struct ath_buf *bf, int);
00171 enum {
00172 ATH_DEBUG_ANY = 0xffffffff
00173 };
00174
00175 #else
00176 #define IFF_DUMPPKTS(_ic) (0)
00177 #endif
00178
00179
00180
00181
00182
00183 const char*
00184 ether_sprintf(const u_int8_t *mac)
00185 {
00186 static char etherbuf[18];
00187 snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x",
00188 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00189 return etherbuf;
00190 }
00191
00192
00193
00194
00195
00196 u_int
00197 chan2ieee(struct ath_softc *sc, struct ieee80211channel *c)
00198 {
00199 if (sc->ic_channels <= c && c <= &sc->ic_channels[IEEE80211_CHAN_MAX])
00200 return c - sc->ic_channels;
00201 else if (c == IEEE80211_CHAN_ANYC)
00202 return IEEE80211_CHAN_ANY;
00203 else {
00204 printk(KERN_ERR "wlan: invalid channel freq %u flags %x\n",
00205 c->ic_freq, c->ic_flags);
00206 return 0;
00207 }
00208 }
00209
00210
00211 void dump_pkt(struct sk_buff *skb)
00212 {
00213 u_int8_t *buf = skb->data;
00214 int i = 0;
00215
00216 if (!skb) {
00217 printk("NULL dump_pkt\n");
00218 }
00219 printk("len %d ", skb->len);
00220
00221 if (skb->len > 0) {
00222 for (i = 0; i < skb->len; i++) {
00223 if ((i & 1) == 0)
00224 printk(" ");
00225 printk("%02x", buf[i]);
00226 }
00227 printk("\n");
00228 }
00229
00230 }
00231 void
00232 ieee80211_dump_pkt(u_int8_t *buf, int len, int rate, int rssi)
00233 {
00234 struct ieee80211_frame *wh;
00235 int i;
00236
00237 wh = (struct ieee80211_frame *)buf;
00238 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
00239 case IEEE80211_FC1_DIR_NODS:
00240 printk("NODS %s", ether_sprintf(wh->i_addr2));
00241 printk("->%s", ether_sprintf(wh->i_addr1));
00242 printk("(%s)", ether_sprintf(wh->i_addr3));
00243 break;
00244 case IEEE80211_FC1_DIR_TODS:
00245 printk("TODS %s", ether_sprintf(wh->i_addr2));
00246 printk("->%s", ether_sprintf(wh->i_addr3));
00247 printk("(%s)", ether_sprintf(wh->i_addr1));
00248 break;
00249 case IEEE80211_FC1_DIR_FROMDS:
00250 printk("FRDS %s", ether_sprintf(wh->i_addr3));
00251 printk("->%s", ether_sprintf(wh->i_addr1));
00252 printk("(%s)", ether_sprintf(wh->i_addr2));
00253 break;
00254 case IEEE80211_FC1_DIR_DSTODS:
00255 printk("DSDS %s", ether_sprintf((u_int8_t *)&wh[1]));
00256 printk("->%s", ether_sprintf(wh->i_addr3));
00257 printk("(%s", ether_sprintf(wh->i_addr2));
00258 printk("->%s)", ether_sprintf(wh->i_addr1));
00259 break;
00260 }
00261 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
00262 case IEEE80211_FC0_TYPE_DATA:
00263 printk(" data");
00264 break;
00265 case IEEE80211_FC0_TYPE_MGT:
00266 printk(" mgt");
00267 break;
00268 default:
00269 printk(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
00270 break;
00271 }
00272 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
00273 int i;
00274 printk(" WEP [IV");
00275 for (i = 0; i < IEEE80211_WEP_IVLEN; i++)
00276 printk(" %.02x", buf[sizeof(*wh)+i]);
00277 printk(" KID %u]", buf[sizeof(*wh)+i] >> 6);
00278 }
00279 if (rate >= 0)
00280 printk(" %dM", rate / 2);
00281 if (rssi >= 0)
00282 printk(" +%d", rssi);
00283
00284 printk(" len %d", len);
00285 printk("\n");
00286
00287 if (0 && len > 0) {
00288 for (i = 0; i < len; i++) {
00289 if ((i & 1) == 0)
00290 printk(" ");
00291 printk("%02x", buf[i]);
00292 }
00293 printk("\n");
00294 }
00295 }
00296
00297
00298 struct sk_buff *
00299 ieee80211_encap(struct net_device *dev, struct sk_buff *skb)
00300 {
00301 struct ath_softc *sc = dev->priv;
00302 struct ether_header eh;
00303 struct ieee80211_frame *wh;
00304 struct llc *llc;
00305 u_int8_t fc0;
00306 u_int8_t qospri = 0;
00307 u_int8_t isqos = 0;
00308 u_int8_t acc = 0;
00309 u_int16_t headersize = 0;
00310 u_int16_t padbytes = 0;
00311
00312 memcpy(&eh, skb->data, sizeof(struct ether_header));
00313 skb_pull(skb, sizeof(struct ether_header));
00314
00315 qospri = 0; acc = WME_AC_BE;
00316
00317 llc = (struct llc *) skb_push(skb, sizeof(struct llc));
00318 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
00319 llc->llc_control = LLC_UI;
00320 llc->llc_snap.org_code[0] = 0;
00321 llc->llc_snap.org_code[1] = 0;
00322 llc->llc_snap.org_code[2] = 0;
00323 llc->llc_snap.ether_type = eh.ether_type;
00324
00325
00326 headersize += sizeof(struct ieee80211_frame) + isqos;
00327 if (sc->ic_flags & IEEE80211_F_DATAPAD) {
00328 padbytes = roundup(headersize, 4) - headersize;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338 if ((skb_headroom(skb) < (headersize+padbytes)) &&
00339 pskb_expand_head(skb, sizeof(*wh), 0, GFP_ATOMIC)) {
00340 dev_kfree_skb_any(skb);
00341 return NULL;
00342 }
00343
00344 if (padbytes) {
00345 unsigned char *p;
00346
00347 p = skb_push(skb, padbytes);
00348 }
00349
00350 fc0 = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
00351
00352
00353 if (isqos) {
00354 u_int8_t *q;
00355
00356 q = (u_int8_t *) skb_push(skb, sizeof(struct ieee80211_qoscntl));
00357 q[0] = qospri;
00358 q[1] = 0;
00359 skb->priority = acc;
00360 fc0 |= IEEE80211_FC0_SUBTYPE_QOS;
00361 }
00362
00363 wh = (struct ieee80211_frame *) skb_push(skb, sizeof(struct ieee80211_frame));
00364 wh->i_fc[0] = fc0;
00365 *(u_int16_t *)wh->i_dur = 0;
00366 *(u_int16_t *)wh->i_seq =
00367 cpu_to_le16(sc->txseq << IEEE80211_SEQ_SEQ_SHIFT);
00368 sc->txseq++;
00369 switch (sc->ic_opmode) {
00370 case IEEE80211_M_STA:
00371 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
00372 IEEE80211_ADDR_COPY(wh->i_addr1, sc->bssid);
00373 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
00374 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
00375 break;
00376 case IEEE80211_M_IBSS:
00377 case IEEE80211_M_AHDEMO:
00378 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
00379 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
00380 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
00381 IEEE80211_ADDR_COPY(wh->i_addr3, sc->bssid);
00382 break;
00383 case IEEE80211_M_HOSTAP:
00384 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
00385 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
00386 IEEE80211_ADDR_COPY(wh->i_addr2, sc->bssid);
00387 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
00388 break;
00389 case IEEE80211_M_MONITOR:
00390 printk("%s: invalid mode\n", __func__);
00391 break;
00392 }
00393
00394 if (sc->ic_flags & IEEE80211_F_WEPON &&
00395 eh.ether_type != __constant_htons(ETHERTYPE_PAE))
00396 wh->i_fc[1] |= IEEE80211_FC1_WEP;
00397
00398 return skb;
00399 }
00400
00401
00402
00403
00404
00405
00406 enum ieee80211_phymode
00407 chan2mode(struct ath_softc *sc, struct ieee80211channel *chan)
00408 {
00409
00410
00411
00412
00413
00414 if (IEEE80211_IS_CHAN_5GHZ(chan))
00415 return IEEE80211_MODE_11A;
00416 else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
00417 return IEEE80211_MODE_11G;
00418 else
00419 return IEEE80211_MODE_11B;
00420 }
00421
00422
00423 extern struct iw_statistics *ath_iw_getstats(struct net_device *);
00424 extern const struct iw_handler_def ath_iw_handler_def;
00425
00426 #define DPRINTF(sc, _m, _fmt, ...) do { \
00427 if (sc->sc_debug & _m) \
00428 printk(_fmt, __VA_ARGS__); \
00429 } while (0)
00430
00431
00432
00433 static int countrycode = -1;
00434 MODULE_PARM(countrycode, "i");
00435 MODULE_PARM_DESC(countrycode, "Override default country code");
00436 static int outdoor = -1;
00437 MODULE_PARM(outdoor, "i");
00438 MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use");
00439 static int xchanmode = -1;
00440 MODULE_PARM(xchanmode, "i");
00441 MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode");
00442
00443 static const char *acnames[] = {
00444 "WME_AC_BE",
00445 "WME_AC_BK",
00446 "WME_AC_VI",
00447 "WME_AC_VO",
00448 "WME_UPSD",
00449 };
00450
00451
00452 int
00453 ath_attach(u_int16_t devid, struct net_device *dev)
00454 {
00455 struct ath_softc *sc = dev->priv;
00456 struct ath_hal *ah;
00457 int error = 0;
00458 u_int8_t csz;
00459 HAL_STATUS status;
00460 int i;
00461 u_int32_t result;
00462 int channels_printed;
00463
00464 DPRINTF(sc, ATH_DEBUG_ANY, "ath_attach: devid 0x%x\n", devid);
00465
00466
00467
00468
00469 bus_read_cachesize(sc, &csz);
00470
00471 sc->sc_cachelsz = csz << 2;
00472
00473 ATH_LOCK_INIT(sc);
00474 ATH_TXBUF_LOCK_INIT(sc);
00475
00476 ATH_INIT_TQUEUE(&sc->sc_rxtq, ath_rx_tasklet, dev);
00477 ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet, dev);
00478
00479 ATH_INIT_TQUEUE(&sc->sc_rxorntq,ath_rxorn_tasklet, dev);
00480 ATH_INIT_TQUEUE(&sc->sc_fataltq,ath_fatal_tasklet, dev);
00481
00482 ah = _ath_hal_attach(devid, sc, 0, (void *) dev->mem_start, &status);
00483 if (ah == NULL) {
00484 printk(KERN_ERR "%s: unable to attach hardware; HAL status %u\n",
00485 dev->name, status);
00486 error = ENXIO;
00487 goto bad;
00488 }
00489 if (ah->ah_abi != HAL_ABI_VERSION) {
00490 printk(KERN_ERR "%s: HAL ABI msmatch; "
00491 "driver expects 0x%x, HAL reports 0x%x\n",
00492 dev->name, HAL_ABI_VERSION, ah->ah_abi);
00493 error = ENXIO;
00494 goto bad;
00495 }
00496 sc->sc_ah = ah;
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 if (AH_TRUE != ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0)) {
00508 printk(KERN_WARNING "%s: no multi-rate retry support\n",
00509 dev->name);
00510 goto bad;
00511 }
00512
00513
00514
00515
00516
00517 sc->sc_keymax = ath_hal_keycachesize(ah);
00518 for (i = 0; i < sc->sc_keymax; i++)
00519 ath_hal_keyreset(ah, i);
00520
00521
00522
00523
00524
00525
00526 if (countrycode != -1)
00527 ath_countrycode = countrycode;
00528 if (outdoor != -1)
00529 ath_outdoor = outdoor;
00530 if (xchanmode != -1)
00531 ath_xchanmode = xchanmode;
00532 error = ath_getchannels(dev, ath_countrycode,
00533 ath_outdoor, ath_xchanmode);
00534 if (error != 0)
00535 goto bad;
00536
00537
00538
00539
00540 ath_rate_setup(dev, IEEE80211_MODE_11A);
00541 ath_rate_setup(dev, IEEE80211_MODE_11B);
00542 ath_rate_setup(dev, IEEE80211_MODE_11G);
00543 ath_rate_setup(dev, IEEE80211_MODE_TURBO);
00544
00545
00546
00547
00548
00549
00550 ath_hal_getregdomain(ah, &ath_regdomain);
00551 ath_hal_getcountrycode(ah, &ath_countrycode);
00552
00553 error = ath_desc_alloc(sc);
00554 if (error != 0) {
00555 printk("%s: failed to allocate descriptors: %d\n",
00556 dev->name, error);
00557 goto bad;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if (!ath_tx_setup(sc, WME_AC_BE, HAL_WME_AC_BK) ||
00572 !ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BE) ||
00573 !ath_tx_setup(sc, WME_AC_VI, HAL_WME_AC_VI) ||
00574 !ath_tx_setup(sc, WME_AC_VO, HAL_WME_AC_VO)) {
00575 error = EIO;
00576 goto bad2;
00577 }
00578
00579 init_timer(&sc->sc_cal_ch);
00580 sc->sc_cal_ch.function = ath_calibrate;
00581 sc->sc_cal_ch.data = (unsigned long) dev;
00582
00583
00584 sc->sc_ledstate = 1;
00585
00586
00587
00588
00589
00590 sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID);
00591 if (sc->sc_softled) {
00592 ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
00593 ath_hal_gpioset(ah, sc->sc_ledpin, 0);
00594 }
00595
00596 dev->open = ath_init;
00597 dev->stop = ath_stop;
00598 dev->hard_start_xmit = ath_hardstart;
00599 dev->tx_timeout = ath_tx_timeout;
00600 dev->watchdog_timeo = 5 * HZ;
00601 dev->set_multicast_list = ath_mode_init;
00602 dev->do_ioctl = ath_ioctl;
00603 dev->get_stats = ath_getstats;
00604
00605 #ifdef CONFIG_NET_WIRELESS
00606 dev->get_wireless_stats = ath_iw_getstats;
00607 dev->wireless_handlers = (struct iw_handler_def *) &ath_iw_handler_def;
00608 #endif
00609
00610 sc->dev_type = ARPHRD_ETHER;
00611 ether_setup(dev);
00612 dev->set_mac_address = ath_set_mac_address;
00613 dev->change_mtu = &ath_change_mtu;
00614 dev->mtu = 2000;
00615 dev->tx_queue_len = ATH_TXBUF;
00616
00617 if (register_netdev(&sc->dev)) {
00618 printk(KERN_WARNING "%s: unable to register device\n",
00619 sc->dev.name);
00620 goto bad3;
00621 }
00622
00623
00624
00625
00626 sc->ic_phytype = IEEE80211_T_OFDM;
00627 sc->ic_opmode = IEEE80211_M_STA;
00628 sc->ic_caps = IEEE80211_C_WEP
00629 | IEEE80211_C_IBSS
00630 | IEEE80211_C_HOSTAP
00631 | IEEE80211_C_MONITOR
00632 | IEEE80211_C_TXPMGT
00633 | IEEE80211_C_SHPREAMBLE;
00634 sc->ic_flags |= IEEE80211_F_DATAPAD;
00635 sc->ic_rts_threshold = IEEE80211_RTS_MAX;
00636
00637
00638
00639
00640
00641 if (ath_hal_hasdiversity(ah)) {
00642 sc->sc_hasdiversity = 1;
00643 sc->sc_diversity = ath_hal_getdiversity(ah);
00644 }
00645 sc->sc_defant = ath_hal_getdefantenna(ah);
00646 sc->sc_txantenna = 0;
00647 sc->sc_debug = ath_debug;
00648 sc->sc_rxotherant = 0;
00649
00650
00651 ath_hal_getmac(ah, dev->dev_addr);
00652
00653 if (1) {
00654 u_int modes = ath_hal_getwirelessmodes(ah, ath_countrycode);
00655 printk(KERN_WARNING "%s: modes: 0x%02x\n",
00656 sc->dev.name,
00657 modes);
00658 }
00659
00660 result = 0;
00661 if (HAL_OK != ath_hal_getcapability(ah, HAL_CAP_TXPOW, 0, &result)) {
00662 printk(KERN_WARNING "%s: couldn't get capability\n",
00663 sc->dev.name);
00664 } else {
00665 printk(KERN_WARNING "%s: TXPOW %d\n",
00666 sc->dev.name, result);
00667 }
00668 result = 0;
00669 if (HAL_OK != ath_hal_getcapability(ah, HAL_CAP_TPC, 0, &result)) {
00670 printk(KERN_WARNING "%s: couldn't get capability\n",
00671 sc->dev.name);
00672 } else {
00673 printk(KERN_WARNING "%s: TXPC %d\n",
00674 sc->dev.name, result);
00675 }
00676
00677
00678 {
00679
00680
00681
00682
00683
00684 memset(sc->ic_chan_avail, 0, sizeof(sc->ic_chan_avail));
00685 sc->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
00686 sc->current_channel = NULL;
00687 channels_printed = 0;
00688 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
00689 struct ieee80211channel *c = &sc->ic_channels[i];
00690 if (c->ic_flags) {
00691
00692
00693
00694 if (i != chan2ieee(sc, c)) {
00695 printk(KERN_WARNING "%s: bad channel ignored; "
00696 "freq %u flags %x number %u\n",
00697 dev->name, c->ic_freq, c->ic_flags, i);
00698 c->ic_flags = 0;
00699 continue;
00700 }
00701 if (sc->current_channel == NULL) {
00702 sc->current_channel = c;
00703 }
00704 setbit(sc->ic_chan_avail, i);
00705
00706 if (channels_printed % 3 == 0) {
00707 if (channels_printed) {
00708 printk("\n");
00709 }
00710 printk("%s: available channels:", dev->name);
00711 }
00712 channels_printed++;
00713
00714 printk(" %d (%1d.%3dGHz/", i,
00715 c->ic_freq / 1000,
00716 c->ic_freq % 1000);
00717
00718
00719
00720
00721 if (IEEE80211_IS_CHAN_A(c)) {
00722 sc->ic_modecaps |= 1<<IEEE80211_MODE_11A;
00723 printk("a");
00724 }
00725 if (IEEE80211_IS_CHAN_B(c)) {
00726 sc->ic_modecaps |= 1<<IEEE80211_MODE_11B;
00727 printk("b");
00728 }
00729 if (IEEE80211_IS_CHAN_PUREG(c)) {
00730 sc->ic_modecaps |= 1<<IEEE80211_MODE_11G;
00731 printk("g");
00732 }
00733 if (IEEE80211_IS_CHAN_T(c)) {
00734 sc->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
00735 printk("t");
00736 }
00737
00738 if (IEEE80211_IS_CHAN_X(c)) {
00739 printk("x");
00740 }
00741
00742 printk(")");
00743 }
00744 }
00745 if (channels_printed) {
00746 printk("\n");
00747 }
00748 }
00749 if (!sc->current_channel) {
00750 printk("no channels?\n");
00751 return 0;
00752
00753 }
00754
00755
00756
00757
00758
00759 #ifdef CONFIG_SYSCTL
00760 ath_dynamic_sysctl_register(sc);
00761 #endif
00762 ath_announce(dev);
00763
00764 printk("%s: 802.11 address: %s\n",
00765 dev->name, ether_sprintf(dev->dev_addr));
00766
00767 return ath_init(dev);
00768
00769 bad3:
00770 bad2:
00771 if (sc->sc_txq[WME_AC_BK].axq_qnum != (u_int) -1)
00772 ATH_TXQ_LOCK_DESTROY(&sc->sc_txq[WME_AC_BK]);
00773 if (sc->sc_txq[WME_AC_BE].axq_qnum != (u_int) -1)
00774 ATH_TXQ_LOCK_DESTROY(&sc->sc_txq[WME_AC_BE]);
00775 if (sc->sc_txq[WME_AC_VI].axq_qnum != (u_int) -1)
00776 ATH_TXQ_LOCK_DESTROY(&sc->sc_txq[WME_AC_VI]);
00777 if (sc->sc_txq[WME_AC_VO].axq_qnum != (u_int) -1)
00778 ATH_TXQ_LOCK_DESTROY(&sc->sc_txq[WME_AC_VO]);
00779 ath_desc_free(sc);
00780 bad:
00781 if (ah)
00782 ath_hal_detach(ah);
00783 ATH_TXBUF_LOCK_DESTROY(sc);
00784 ATH_LOCK_DESTROY(sc);
00785 sc->sc_invalid = 1;
00786 return error;
00787 }
00788
00789 int
00790 ath_detach(struct net_device *dev)
00791 {
00792 struct ath_softc *sc = dev->priv;
00793 int i = 0;
00794
00795 DPRINTF(sc, ATH_DEBUG_ANY, "ath_detach flags %x\n", dev->flags);
00796
00797 ath_stop(dev);
00798 sc->sc_invalid = 1;
00799 ath_desc_free(sc);
00800 ath_hal_detach(sc->sc_ah);
00801
00802 ATH_TXBUF_LOCK_DESTROY(sc);
00803 for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
00804 if (ATH_TXQ_SETUP(sc, i))
00805 ATH_TXQ_LOCK_DESTROY(&sc->sc_txq[i]);
00806
00807 #ifdef CONFIG_SYSCTL
00808 ath_dynamic_sysctl_unregister(sc);
00809 #endif
00810 ATH_LOCK_DESTROY(sc);
00811 unregister_netdev(&sc->dev);
00812
00813
00814 return 0;
00815 }
00816
00817 void
00818 ath_suspend(struct net_device *dev)
00819 {
00820 struct ath_softc *sc = dev->priv;
00821 DPRINTF(sc, ATH_DEBUG_ANY, "ath_suspend flags %x\n", dev->flags);
00822 ath_stop(dev);
00823 }
00824
00825 void
00826 ath_resume(struct net_device *dev)
00827 {
00828 struct ath_softc *sc = dev->priv;
00829 DPRINTF(sc, ATH_DEBUG_ANY, "ath_resume %x\n", dev->flags);
00830 ath_init(dev);
00831 }
00832
00833 void
00834 ath_shutdown(struct net_device *dev)
00835 {
00836 struct ath_softc *sc = dev->priv;
00837 DPRINTF(sc, ATH_DEBUG_ANY, "ath_shutdown %x\n", dev->flags);
00838 ath_stop(dev);
00839 }
00840
00841
00842
00843
00844
00845 irqreturn_t
00846 ath_intr(int irq, void *dev_id, struct pt_regs *regs)
00847 {
00848 struct net_device *dev = dev_id;
00849 struct ath_softc *sc = dev->priv;
00850 struct ath_hal *ah = sc->sc_ah;
00851 HAL_INT status;
00852 int needmark;
00853
00854 if (sc->sc_invalid) {
00855
00856
00857
00858
00859 return IRQ_NONE;
00860 }
00861 if (!ath_hal_intrpend(ah)) {
00862 return IRQ_NONE;
00863 }
00864 if ((dev->flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP)) {
00865 printk("%s: %s: flags 0x%x\n", dev->name, __func__, dev->flags);
00866 ath_hal_getisr(ah, &status);
00867 ath_hal_intrset(ah, 0);
00868 return IRQ_HANDLED;
00869 }
00870 needmark = 0;
00871 ath_hal_getisr(ah, &status);
00872 DPRINTF(sc, ATH_DEBUG_ANY, "%s: interrupt, status 0x%x\n", dev->name, status);
00873 #ifdef AR_DEBUG
00874 if (ath_debug &&
00875 (status & (HAL_INT_FATAL|HAL_INT_RXORN|HAL_INT_BMISS))) {
00876 printk("%s: ath_intr: status 0x%x\n", dev->name, status);
00877
00878 }
00879 #endif
00880 status &= sc->sc_imask;
00881 if (status & HAL_INT_FATAL) {
00882 printk("%s: %s: FATAL\n", dev->name, __func__);
00883 sc->sc_stats.ast_hardware++;
00884 ath_hal_intrset(ah, 0);
00885 ATH_SCHEDULE_TQUEUE(&sc->sc_fataltq, &needmark);
00886 } else if (status & HAL_INT_RXORN) {
00887 printk("%s: %s: RXORN\n", dev->name, __func__);
00888 sc->sc_stats.ast_rxorn++;
00889 ath_hal_intrset(ah, 0);
00890 ATH_SCHEDULE_TQUEUE(&sc->sc_rxorntq, &needmark);
00891 } else {
00892 if (status & HAL_INT_RXEOL) {
00893 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: RXEOL\n", dev->name);
00894
00895
00896
00897
00898
00899 sc->sc_stats.ast_rxeol++;
00900 sc->sc_rxlink = NULL;
00901 }
00902 if (status & HAL_INT_TXURN) {
00903 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: TXURN\n", dev->name);
00904 sc->sc_stats.ast_txurn++;
00905
00906 ath_hal_updatetxtriglevel(ah, AH_TRUE);
00907 }
00908 if (status & HAL_INT_RX) {
00909 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: RX\n", dev->name);
00910 ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, &needmark);
00911 }
00912 if (status & HAL_INT_TX) {
00913 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: TX\n", dev->name);
00914 ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
00915
00916 }
00917 if (status & HAL_INT_SWBA) {
00918 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: SWBA?\n", dev->name);
00919
00920
00921
00922
00923
00924
00925 }
00926 if (status & HAL_INT_BMISS) {
00927 DPRINTF(sc, ATH_DEBUG_ANY, "%s: ath_intr: BMISS?\n", dev->name);
00928 sc->sc_stats.ast_bmiss++;
00929
00930 }
00931 }
00932 if (needmark)
00933 mark_bh(IMMEDIATE_BH);
00934 return IRQ_HANDLED;
00935 }
00936
00937 static void
00938 ath_fatal_tasklet(TQUEUE_ARG data)
00939 {
00940 struct net_device *dev = (struct net_device *) data;
00941
00942 printk("%s: hardware error; resetting\n", dev->name);
00943 ath_reset(dev);
00944 }
00945
00946 static void
00947 ath_rxorn_tasklet(TQUEUE_ARG data)
00948 {
00949 struct net_device *dev = (struct net_device *) data;
00950
00951 printk("%s: rx FIFO overrun; resetting\n", dev->name);
00952 ath_reset(dev);
00953 }
00954
00955
00956 static u_int
00957 ath_chan2flags(struct ath_softc *sc, struct ieee80211channel *chan)
00958 {
00959 static const u_int modeflags[] = {
00960 0,
00961 CHANNEL_A,
00962 CHANNEL_B,
00963 CHANNEL_PUREG,
00964 CHANNEL_T
00965 };
00966 return modeflags[chan2mode(sc, chan)];
00967 }
00968
00969 static int
00970 ath_init(struct net_device *dev)
00971 {
00972 struct ath_softc *sc = dev->priv;
00973 struct ath_hal *ah = sc->sc_ah;
00974 HAL_STATUS status;
00975 HAL_CHANNEL hchan;
00976
00977 DPRINTF(sc, ATH_DEBUG_ANY, "ath_init: mode=%d\n",sc->ic_opmode);
00978
00979
00980
00981
00982 ath_stop(dev);
00983
00984
00985
00986
00987 if (sc->ic_opmode == IEEE80211_M_MONITOR) {
00988 struct ath_buf *bf;
00989 STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list)
00990 if (bf->bf_skb != NULL) {
00991 bus_unmap_single(sc->sc_bdev,
00992 bf->bf_skbaddr, sc->sc_rxbufsize,
00993 BUS_DMA_FROMDEVICE);
00994 dev_kfree_skb_any(bf->bf_skb);
00995 bf->bf_skb = NULL;
00996 }
00997 }
00998
00999
01000
01001
01002 dev->addr_len = ETH_ALEN;
01003 dev->type = sc->dev_type;
01004
01005
01006 if (sc->current_channel == NULL) {
01007 printk("%s: current_channel == NULL\n", dev->name);
01008 return EIO;
01009 }
01010
01011
01012
01013
01014
01015
01016
01017
01018 if (ath_setchannel(sc, sc->current_channel) != 0) {
01019 return EIO;
01020 }
01021
01022 hchan.channel = sc->current_channel->ic_freq;
01023 hchan.channelFlags = ath_chan2flags(sc, sc->current_channel);
01024
01025
01026 if (!ath_hal_reset(ah, sc->ic_opmode, &hchan, AH_FALSE, &status)) {
01027 printk("%s: unable to reset hardware; hal status %u\n",
01028 dev->name, status);
01029 return EIO;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 ath_initkeytable(dev);
01041 if (ath_startrecv(dev) != 0) {
01042 printk("%s: unable to start recv logic\n", dev->name);
01043 return EIO;
01044 }
01045
01046
01047 if (chan2mode(sc, sc->current_channel) != sc->ic_curmode) {
01048 printk (KERN_EMERG "%s: mode incorrect!\n",
01049 __func__);
01050 return -EIO;
01051 }
01052
01053
01054 dev->flags |= IFF_RUNNING;
01055
01056
01057
01058
01059 sc->sc_imask = HAL_INT_RX | HAL_INT_TX
01060 | HAL_INT_RXEOL | HAL_INT_RXORN
01061 | HAL_INT_FATAL | HAL_INT_GLOBAL;
01062 ath_hal_intrset(ah, sc->sc_imask);
01063
01064 netif_start_queue(dev);
01065
01066 return 0;
01067 }
01068
01069 static int
01070 ath_stop_locked(struct net_device *dev)
01071 {
01072 struct ath_softc *sc = dev->priv;
01073 struct ath_hal *ah = sc->sc_ah;
01074
01075 DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u flags 0x%x\n",
01076 __func__, sc->sc_invalid, dev->flags);
01077
01078 if (dev->flags & IFF_RUNNING) {
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095 netif_stop_queue(dev);
01096 dev->flags &= ~IFF_RUNNING;
01097 if (!sc->sc_invalid) {
01098 if (sc->sc_softled)
01099 ath_hal_gpioset(ah, sc->sc_ledpin, 1);
01100 ath_hal_intrset(ah, 0);
01101 }
01102 ath_draintxq(sc);
01103 if (!sc->sc_invalid) {
01104 ath_stoprecv(sc);
01105 ath_hal_phydisable(ah);
01106 } else
01107 sc->sc_rxlink = NULL;
01108 }
01109 return 0;
01110 }
01111
01112 static int
01113 ath_stop(struct net_device *dev)
01114 {
01115 struct ath_softc *sc = dev->priv;
01116 int error;
01117
01118 ATH_LOCK(sc);
01119 error = ath_stop_locked(dev);
01120 if (error == 0 && !sc->sc_invalid) {
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP, 0);
01131 }
01132 ATH_UNLOCK(sc);
01133 return error;
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143 static int
01144 ath_reset(struct net_device *dev)
01145 {
01146 struct ath_softc *sc = dev->priv;
01147 struct ath_hal *ah = sc->sc_ah;
01148 struct ieee80211channel *c;
01149 HAL_STATUS status;
01150 HAL_CHANNEL hchan;
01151
01152
01153
01154
01155
01156 c = sc->current_channel;
01157 hchan.channel = c->ic_freq;
01158 hchan.channelFlags = ath_chan2flags(sc, c);
01159
01160 ath_hal_intrset(ah, 0);
01161 ath_draintxq(sc);
01162 ath_stoprecv(sc);
01163
01164 if (!ath_hal_reset(ah, sc->ic_opmode, &hchan, AH_TRUE, &status))
01165 printk("%s: %s: unable to reset hardware; hal status %u\n",
01166 dev->name, __func__, status);
01167 if (ath_startrecv(dev) != 0)
01168 printk("%s: %s: unable to start recv logic\n",
01169 dev->name, __func__);
01170
01171 ath_hal_intrset(ah, sc->sc_imask);
01172
01173
01174 netif_wake_queue(dev);
01175 return 0;
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185 static int
01186 ath_skbhdr_adjust(struct sk_buff *skb, struct net_device *dev)
01187 {
01188 struct ath_softc *sc = (void*)dev->priv;
01189 int len = sizeof(struct ieee80211_qosframe) + sizeof(struct llc) +
01190 IEEE80211_ADDR_LEN - sizeof(struct ether_header);
01191
01192 if (sc->ic_flags & IEEE80211_F_WEPON)
01193 len += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
01194 if ((skb_headroom(skb) < len) &&
01195 pskb_expand_head(skb, len - skb_headroom(skb), 0, GFP_ATOMIC)) {
01196 dev_kfree_skb_any(skb);
01197 return -ENOMEM;
01198 }
01199 return 0;
01200 }
01201
01202
01203
01204
01205
01206 static int
01207 ath_hardstart(struct sk_buff *skb, struct net_device *dev)
01208 {
01209 struct ath_softc *sc = dev->priv;
01210 struct ath_buf *bf = NULL;
01211 int error;
01212
01213
01214 DPRINTF(sc, ATH_DEBUG_ANY, "%s: hardstart\n", dev->name);
01215
01216 if ((dev->flags & IFF_RUNNING) == 0 || sc->sc_invalid) {
01217 DPRINTF(sc, ATH_DEBUG_ANY, "%s: discard, invalid %d flags %x\n", __func__,
01218 sc->sc_invalid, dev->flags);
01219 sc->sc_stats.ast_tx_invalid++;
01220 return -ENETDOWN;
01221 }
01222
01223 error = ath_skbhdr_adjust(skb, dev);
01224 if (error != 0)
01225 return error;
01226
01227
01228
01229
01230
01231
01232
01233
01234 if (skb->len > sizeof(wlan_ng_prism2_header)) {
01235 pull_prism2_header(skb);
01236 }
01237
01238
01239 if (skb->len > sizeof(struct click_wifi_extra)) {
01240 pull_wifi_extra_header(skb);
01241 }
01242
01243
01244
01245
01246
01247
01248 ATH_TXBUF_LOCK_BH(sc);
01249 bf = STAILQ_FIRST(&sc->sc_txbuf);
01250 if (bf != NULL)
01251 STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
01252
01253 if (STAILQ_EMPTY(&sc->sc_txbuf)) {
01254 DPRINTF(sc, ATH_DEBUG_ANY, "%s: stop queue\n", __func__);
01255 sc->sc_stats.ast_tx_qstop++;
01256 netif_stop_queue(dev);
01257 }
01258 ATH_TXBUF_UNLOCK_BH(sc);
01259 if (bf == NULL) {
01260 printk("%s: discard, no xmit buf\n", __func__);
01261 sc->sc_stats.ast_tx_nobuf++;
01262 goto bad;
01263 }
01264
01265
01266
01267
01268
01269
01270
01271 error = ath_tx_start(dev, bf, skb);
01272
01273
01274
01275
01276
01277 if (error == 0)
01278 return 0;
01279
01280 bad:
01281 printk("%s: %s got to bad\n", dev->name, __func__);
01282 if (bf != NULL) {
01283 ATH_TXBUF_LOCK_BH(sc);
01284 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
01285 ATH_TXBUF_UNLOCK_BH(sc);
01286 }
01287 if (skb)
01288 dev_kfree_skb_any(skb);
01289 return 0;
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 static u_int32_t
01309 ath_calcrxfilter(struct net_device *dev)
01310 {
01311 u_int32_t rfilt;
01312
01313 rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
01314
01315 rfilt |= HAL_RX_FILTER_PROBEREQ;
01316
01317 if (dev->flags & IFF_PROMISC) {
01318 rfilt |= HAL_RX_FILTER_PROM;
01319 rfilt |= HAL_RX_FILTER_CONTROL;
01320 }
01321
01322 if (ath_phyerr) {
01323 rfilt |= HAL_RX_FILTER_PHYERR;
01324 }
01325
01326
01327 rfilt |= HAL_RX_FILTER_BEACON;
01328 return rfilt;
01329 }
01330
01331 static void
01332 ath_mode_init(struct net_device *dev)
01333 {
01334 struct ath_softc *sc = dev->priv;
01335 struct ath_hal *ah = sc->sc_ah;
01336 u_int32_t rfilt, mfilt[2], val;
01337 u_int8_t pos;
01338 struct dev_mc_list *mc;
01339
01340
01341 rfilt = ath_calcrxfilter(dev);
01342 ath_hal_setrxfilter(ah, rfilt);
01343
01344
01345 ath_hal_setopmode(ah);
01346
01347
01348 if ((dev->flags & IFF_ALLMULTI) == 0) {
01349 mfilt[0] = mfilt[1] = 0;
01350 for (mc = dev->mc_list; mc; mc = mc->next) {
01351
01352 val = LE_READ_4(mc->dmi_addr + 0);
01353 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
01354 val = LE_READ_4(mc->dmi_addr + 3);
01355 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
01356 pos &= 0x3f;
01357 mfilt[pos / 32] |= (1 << (pos % 32));
01358 }
01359 } else {
01360 mfilt[0] = mfilt[1] = ~0;
01361 }
01362 ath_hal_setmcastfilter(ah, mfilt[0], mfilt[1]);
01363 DPRINTF(sc, ATH_DEBUG_ANY, "ath_mode_init: RX filter 0x%x, MC filter %08x:%08x\n",
01364 rfilt, mfilt[0], mfilt[1]);
01365 }
01366
01367 static struct sk_buff *
01368 ath_alloc_skb(u_int size, u_int align)
01369 {
01370 struct sk_buff *skb;
01371 u_int off;
01372
01373 skb = dev_alloc_skb(size + align-1);
01374 if (skb != NULL) {
01375 off = ((unsigned long) skb->data) % align;
01376 if (off != 0)
01377 skb_reserve(skb, align - off);
01378 }
01379 return skb;
01380 }
01381
01382 static int
01383 ath_desc_alloc(struct ath_softc *sc)
01384 {
01385 #define DS2PHYS(_sc, _ds) \
01386 ((_sc)->sc_desc_daddr + ((caddr_t)(_ds) - (caddr_t)(_sc)->sc_desc))
01387 int i, bsize;
01388 struct ath_desc *ds;
01389 struct ath_buf *bf;
01390
01391
01392 sc->sc_desc_len = sizeof(struct ath_desc) *
01393 (ATH_TXBUF * ATH_TXDESC + ATH_RXBUF + 1);
01394 sc->sc_desc = bus_alloc_consistent(sc->sc_bdev,
01395 sc->sc_desc_len, &sc->sc_desc_daddr);
01396 if (sc->sc_desc == NULL)
01397 return ENOMEM;
01398 ds = sc->sc_desc;
01399 DPRINTF(sc, ATH_DEBUG_ANY, "ath_desc_alloc: DMA map: %p (%d) -> %p\n",
01400 ds, sc->sc_desc_len, (caddr_t) sc->sc_desc_daddr);
01401
01402
01403 bsize = sizeof(struct ath_buf) * (ATH_TXBUF + ATH_RXBUF + 1);
01404 bf = kmalloc(bsize, GFP_KERNEL);
01405 if (bf == NULL)
01406 goto bad;
01407 memset(bf, 0, bsize);
01408 sc->sc_bufptr = bf;
01409
01410 STAILQ_INIT(&sc->sc_rxbuf);
01411 for (i = 0; i < ATH_RXBUF; i++, bf++, ds++) {
01412 bf->bf_desc = ds;
01413 bf->bf_daddr = sc->sc_desc_daddr +
01414 ((caddr_t)ds - (caddr_t)sc->sc_desc);
01415 STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
01416 }
01417
01418 STAILQ_INIT(&sc->sc_txbuf);
01419 for (i = 0; i < ATH_TXBUF; i++, bf++, ds += ATH_TXDESC) {
01420 bf->bf_desc = ds;
01421 bf->bf_daddr = sc->sc_desc_daddr +
01422 ((caddr_t)ds - (caddr_t)sc->sc_desc);
01423 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
01424 }
01425
01426
01427
01428
01429 sc->sc_bcbuf = NULL;
01430 return 0;
01431 bad:
01432 bus_free_consistent(sc->sc_bdev, sc->sc_desc_len,
01433 sc->sc_desc, sc->sc_desc_daddr);
01434 sc->sc_desc = NULL;
01435 return ENOMEM;
01436 }
01437
01438 static void
01439 ath_desc_free(struct ath_softc *sc)
01440 {
01441 struct ath_buf *bf;
01442
01443
01444
01445
01446
01447
01448
01449 STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list)
01450 if (bf->bf_skb != NULL) {
01451 bus_unmap_single(sc->sc_bdev,
01452 bf->bf_skbaddr, sc->sc_rxbufsize,
01453 BUS_DMA_FROMDEVICE);
01454 dev_kfree_skb_any(bf->bf_skb);
01455 bf->bf_skb = NULL;
01456 }
01457
01458
01459 if (sc->sc_bcbuf != NULL) {
01460 bf = sc->sc_bcbuf;
01461 if (bf->bf_skb != NULL) {
01462 bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
01463 bf->bf_skb->len, BUS_DMA_TODEVICE);
01464 }
01465 sc->sc_bcbuf = NULL;
01466 }
01467
01468
01469 bus_free_consistent(sc->sc_bdev, sc->sc_desc_len,
01470 sc->sc_desc, sc->sc_desc_daddr);
01471
01472 STAILQ_INIT(&sc->sc_rxbuf);
01473 STAILQ_INIT(&sc->sc_txbuf);
01474 kfree(sc->sc_bufptr);
01475 sc->sc_bufptr = NULL;
01476 }
01477
01478 static int
01479 ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
01480 {
01481 struct ath_hal *ah = sc->sc_ah;
01482 struct sk_buff *skb;
01483 struct ath_desc *ds;
01484
01485 skb = bf->bf_skb;
01486 if (skb == NULL) {
01487
01488
01489
01490
01491
01492
01493 skb = ath_alloc_skb(sc->sc_rxbufsize, sc->sc_cachelsz);
01494 if (skb == NULL) {
01495 DPRINTF(sc, ATH_DEBUG_ANY, "%s: skbuff alloc of size %u failed\n",
01496 __func__, sc->sc_rxbufsize);
01497 sc->sc_stats.ast_rx_nobuf++;
01498 return ENOMEM;
01499 }
01500
01501 skb_reserve(skb, sizeof(wlan_ng_prism2_header));
01502
01503 skb->dev = &sc->dev;
01504 bf->bf_skb = skb;
01505 bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
01506 skb->data, sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
01507 }
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 ds = bf->bf_desc;
01525 ds->ds_link = bf->bf_daddr;
01526 ds->ds_data = bf->bf_skbaddr;
01527 ath_hal_setuprxdesc(ah, ds
01528 , skb_tailroom(skb)
01529 , 0
01530 );
01531
01532 if (sc->sc_rxlink != NULL)
01533 *sc->sc_rxlink = bf->bf_daddr;
01534 sc->sc_rxlink = &ds->ds_link;
01535 return 0;
01536 }
01537
01538
01539 static void
01540 ath_update_led (struct ath_softc *sc, u_int16_t ledstate)
01541 {
01542 struct ath_hal *ah = sc->sc_ah;
01543
01544
01545
01546
01547 ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
01548 ath_hal_gpioset(ah, sc->sc_ledpin, ledstate);
01549 sc->sc_ledstate = ledstate;
01550
01551 }
01552
01553 struct sk_buff *
01554 ieee80211_decap(struct net_device *dev, struct sk_buff *skb)
01555 {
01556 struct ether_header *eh;
01557 struct ieee80211_frame wh;
01558 struct llc *llc;
01559 u_short ether_type = 0;
01560
01561 memcpy(&wh, skb->data, sizeof(struct ieee80211_frame));
01562 llc = (struct llc *) skb_pull(skb, sizeof(struct ieee80211_frame));
01563 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
01564 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
01565 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) {
01566 ether_type = llc->llc_un.type_snap.ether_type;
01567 skb_pull(skb, sizeof(struct llc));
01568 llc = NULL;
01569 }
01570 eh = (struct ether_header *) skb_push(skb, sizeof(struct ether_header));
01571 if (!eh) {
01572 return skb;
01573 }
01574 switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) {
01575 case IEEE80211_FC1_DIR_NODS:
01576 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
01577 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
01578 break;
01579 case IEEE80211_FC1_DIR_TODS:
01580 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3);
01581 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2);
01582 break;
01583 case IEEE80211_FC1_DIR_FROMDS:
01584 IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1);
01585 IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3);
01586 break;
01587 case IEEE80211_FC1_DIR_DSTODS:
01588
01589 printk("%s: DS to DS\n", __func__);
01590 dev_kfree_skb_any(skb);
01591 return NULL;
01592 }
01593 if (!ALIGNED_POINTER(skb->data + sizeof(*eh), u_int32_t)) {
01594 struct sk_buff *n;
01595
01596
01597 n = skb_copy(skb, GFP_ATOMIC);
01598 dev_kfree_skb_any(skb);
01599 if (n == NULL)
01600 return NULL;
01601 skb = n;
01602 eh = (struct ether_header *) skb->data;
01603 }
01604 if (llc != NULL)
01605 eh->ether_type = htons(skb->len - sizeof(*eh));
01606 else
01607 eh->ether_type = ether_type;
01608 return skb;
01609 }
01610
01611 static struct timeval get_stamp(struct ath_hal *ah, u_int32_t t) {
01612 struct timeval now;
01613 struct timeval stamp;
01614 u_int32_t tsf_now;
01615 u_int32_t tsf;
01616 u_int32_t d;
01617 u_int32_t period;
01618 struct timeval diff;
01619
01620
01621
01622
01623
01624
01625 t &= 0x7fff;
01626
01627
01628 tsf_now = ath_hal_gettsf32(ah);
01629 tsf = tsf_now;
01630 do_gettimeofday(&now);
01631 if ((tsf & 0x7fff) < t)
01632 tsf -= 0x8000;
01633
01634 tsf = t | (tsf &~ 0x7fff);
01635
01636 d = (tsf_now - tsf);
01637
01638 period = 1000*1000;
01639 diff.tv_sec = d/period;
01640 diff.tv_usec = d % period;
01641 timersub(&now, &diff, &stamp);
01642 return stamp;
01643
01644 }
01645
01646 static void
01647 ath_setdefantenna(struct ath_softc *sc, u_int antenna)
01648 {
01649 struct ath_hal *ah = sc->sc_ah;
01650
01651
01652 ath_hal_setdefantenna(ah, antenna);
01653 sc->sc_defant = antenna;
01654 sc->sc_rxotherant = 0;
01655 }
01656
01657 static void
01658 ath_rx_tasklet(TQUEUE_ARG data)
01659 {
01660 #define PA2DESC(_sc, _pa) \
01661 ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
01662 ((_pa) - (_sc)->sc_desc_daddr)))
01663 struct net_device *dev = (struct net_device *) data;
01664 struct ath_buf *bf;
01665 struct ath_softc *sc = dev->priv;
01666 struct net_device_stats *stats = &sc->ic_stats;
01667 struct ath_hal *ah = sc->sc_ah;
01668 struct ath_desc *ds;
01669 struct sk_buff *skb;
01670 struct ieee80211_frame *wh;
01671 int len;
01672 int prev_more = 0;
01673 u_int8_t phyerr;
01674 HAL_STATUS status;
01675 const HAL_RATE_TABLE *rt;
01676 u_int16_t dur = 0;
01677
01678 DPRINTF(sc, ATH_DEBUG_ANY, "%s\n", __func__);
01679 do {
01680 bf = STAILQ_FIRST(&sc->sc_rxbuf);
01681 if (bf == NULL) {
01682 printk("ath_rx_tasklet: no buffer\n");
01683 break;
01684 }
01685 ds = bf->bf_desc;
01686 if (ds->ds_link == bf->bf_daddr) {
01687
01688 break;
01689 }
01690 skb = bf->bf_skb;
01691 if (skb == NULL) {
01692 printk("ath_rx_tasklet: no skbuff\n");
01693 continue;
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707 status = ath_hal_rxprocdesc(ah, ds,
01708 bf->bf_daddr, PA2DESC(sc, ds->ds_link));
01709 #ifdef AR_DEBUG
01710 if (ath_debug > 1)
01711 ath_printrxbuf(bf, status == HAL_OK);
01712 #endif
01713 if (status == HAL_EINPROGRESS)
01714 break;
01715 STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
01716
01717 if (ds->ds_rxstat.rs_more) {
01718
01719
01720
01721
01722
01723
01724
01725 } else if (ds->ds_rxstat.rs_status != 0) {
01726 if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC)
01727 sc->sc_stats.ast_rx_crcerr++;
01728 if (ds->ds_rxstat.rs_status & HAL_RXERR_FIFO)
01729 sc->sc_stats.ast_rx_fifoerr++;
01730 if (ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT)
01731 sc->sc_stats.ast_rx_badcrypt++;
01732 if (ds->ds_rxstat.rs_status & HAL_RXERR_PHY) {
01733 sc->sc_stats.ast_rx_phyerr++;
01734 phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
01735 sc->sc_stats.ast_rx_phy[phyerr]++;
01736 }
01737
01738
01739
01740
01741
01742 if (!ath_phyerr &&
01743 ((ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT ) ||
01744 (ds->ds_rxstat.rs_status & HAL_RXERR_PHY))) {
01745 goto rx_next;
01746 }
01747
01748
01749
01750
01751
01752
01753 if (!ath_phyerr &&
01754 ((ds->ds_rxstat.rs_status & ~HAL_RXERR_DECRYPT) ||
01755 sc->ic_opmode != IEEE80211_M_MONITOR)) {
01756 goto rx_next;
01757 }
01758 }
01759
01760 len = ds->ds_rxstat.rs_datalen;
01761 if (len == 0) {
01762 if (0) {
01763 printk(KERN_WARNING "%s: ath_rx_tasklet: short packet %d\n",
01764 dev->name, len);
01765 }
01766 sc->sc_stats.ast_rx_tooshort++;
01767 goto rx_next;
01768 }
01769
01770 bus_dma_sync_single(sc->sc_bdev,
01771 bf->bf_skbaddr, len, BUS_DMA_FROMDEVICE);
01772
01773
01774
01775
01776 wh = (struct ieee80211_frame *) skb->data;
01777 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
01778 case IEEE80211_FC0_TYPE_CTL:
01779 sc->sc_stats.ast_rx_ctl++;
01780 case IEEE80211_FC0_TYPE_MGT:
01781 sc->sc_stats.ast_rx_mgt++;
01782 }
01783 bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
01784 sc->sc_rxbufsize, BUS_DMA_FROMDEVICE);
01785 bf->bf_skb = NULL;
01786 skb_put(skb, len);
01787 skb->protocol = ETH_P_CONTROL;
01788 if (IFF_DUMPPKTS(sc)) {
01789 ieee80211_dump_pkt(skb->data, len,
01790 sc->sc_hwmap[ds->ds_rxstat.rs_rate] &
01791 IEEE80211_RATE_VAL,
01792 ds->ds_rxstat.rs_rssi);
01793 }
01794 if (!prev_more) {
01795 skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
01796 }
01797
01798 prev_more = ds->ds_rxstat.rs_more;
01799
01800 if (0 && sc->sc_softled) {
01801 ath_update_led(sc, sc->sc_ledstate ^= 1);
01802 }
01803
01804
01805
01806 if (skb != NULL) {
01807
01808 struct click_wifi_extra *ceh = (struct click_wifi_extra *) (skb->cb + EXTRA_HEADER_CB_OFFSET);
01809 memset(ceh, 0, sizeof(struct click_wifi_extra));
01810 ceh->magic = WIFI_EXTRA_MAGIC;
01811 ceh->flags = 0;
01812
01813 if (ds->ds_rxstat.rs_status) {
01814 ceh->flags |= WIFI_EXTRA_RX_ERR;
01815 }
01816 if (ds->ds_rxstat.rs_more) {
01817 ceh->flags |= WIFI_EXTRA_RX_MORE;
01818 }
01819 ceh->rssi = ds->ds_rxstat.rs_rssi;
01820 ceh->silence = 0;
01821 ceh->rate = sc->sc_hwmap[ds->ds_rxstat.rs_rate] & IEEE80211_RATE_VAL;
01822
01823 skb->protocol = 0;
01824 dev->last_rx = jiffies;
01825 skb->dev = &sc->dev;
01826
01827 rt = sc->sc_currates;
01828 if (rt) {
01829 int index = sc->sc_rixmap[ceh->rate];
01830 if (index >= 0 && index < rt->rateCount) {
01831 dur = ath_hal_computetxtime(ah, rt, len,
01832 index, AH_TRUE);
01833 }
01834 }
01835 skb->stamp = get_stamp(ah, ds->ds_rxstat.rs_tstamp);
01836
01837
01838
01839 if (sc->dev_type == ARPHRD_IEEE80211_PRISM) {
01840
01841
01842
01843
01844
01845
01846 u_int32_t tsf = ath_hal_gettsf32(sc->sc_ah);
01847
01848 if ((tsf & 0x7fff) < ds->ds_rxstat.rs_tstamp)
01849 tsf -= 0x8000;
01850
01851 tsf = ds->ds_rxstat.rs_tstamp | (tsf &~ 0x7fff);
01852
01853 push_prism2_header(&sc->dev, skb,
01854 ds->ds_rxstat.rs_datalen,
01855 ds->ds_rxstat.rs_rssi,
01856 sc->sc_hwmap[ds->ds_rxstat.rs_rate] &
01857 IEEE80211_RATE_VAL,
01858 0,
01859 tsf);
01860 } else {
01861 push_wifi_extra_header(skb);
01862 }
01863
01864 if (skb) {
01865 netif_rx(skb);
01866 }
01867
01868
01869 }
01870
01871 stats->rx_packets++;
01872 stats->rx_bytes += len;
01873 rx_next:
01874 STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
01875 } while (ath_rxbuf_init(sc, bf) == 0);
01876
01877
01878 #undef PA2DESC
01879 }
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 static int
01891 ath_tx_setup(struct ath_softc *sc, int ac, int haltype)
01892 {
01893 #define N(a) (sizeof(a)/sizeof(a[0]))
01894 struct ath_hal *ah = sc->sc_ah;
01895 HAL_TXQ_INFO qi;
01896 int qnum;
01897
01898 if (ac >= N(sc->sc_ac2q)) {
01899 printk("%s: AC %u out of range, max %u!\n",
01900 sc->dev.name, ac, N(sc->sc_ac2q));
01901 return 0;
01902 }
01903 memset(&qi, 0, sizeof(qi));
01904 qi.tqi_subtype = haltype;
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE;
01918 qnum = ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_DATA, &qi);
01919 if (qnum == -1) {
01920 printk("%s: Unable to setup hardware queue for %s traffic!\n",
01921 sc->dev.name, acnames[ac]);
01922 return 0;
01923 }
01924 if (qnum >= N(sc->sc_txq)) {
01925 printk("%s: hal qnum %u out of range, max %u!\n",
01926 sc->dev.name, qnum, N(sc->sc_txq));
01927 return 0;
01928 }
01929 if (!ATH_TXQ_SETUP(sc, qnum)) {
01930 struct ath_txq *txq = &sc->sc_txq[qnum];
01931
01932 txq->axq_qnum = qnum;
01933 txq->axq_depth = 0;
01934 txq->axq_intrcnt = 0;
01935 txq->axq_link = NULL;
01936 STAILQ_INIT(&txq->axq_q);
01937 ATH_TXQ_LOCK_INIT(txq);
01938 sc->sc_txqsetup |= 1<<qnum;
01939 }
01940 sc->sc_ac2q[ac] = &sc->sc_txq[qnum];
01941 return 1;
01942 #undef N
01943 }
01944
01945
01946
01947 static void
01948 ath_initkeytable(struct net_device *dev)
01949 {
01950 struct ath_softc *sc = dev->priv;
01951 struct ath_hal *ah = sc->sc_ah;
01952 int i;
01953
01954
01955 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
01956 ath_hal_keyreset(ah, i);
01957 }
01958 }
01959
01960
01961
01962
01963 #define IEEE80211_ACK_SIZE (2+2+IEEE80211_ADDR_LEN+4)
01964
01965 static int
01966 ath_tx_start(struct net_device *dev, struct ath_buf *bf,
01967 struct sk_buff *skb)
01968 {
01969 #define MIN(a,b) ((a) < (b) ? (a) : (b))
01970 #define MAX(a,b) ((a) > (b) ? (a) : (b))
01971 struct ath_softc *sc = dev->priv;
01972 struct ath_hal *ah = sc->sc_ah;
01973 struct net_device_stats *stats = &sc->ic_stats;
01974 int iswep, hdrlen, pktlen, try0,isqos=0;
01975 u_int8_t rix, txrate, ctsrate;
01976 struct ath_desc *ds;
01977 struct ieee80211_frame *wh;
01978 u_int8_t acc=0;
01979 u_int flags, ctsduration, antenna;
01980 HAL_PKT_TYPE atype;
01981 HAL_BOOL shortPreamble;
01982 struct ath_txq *txq;
01983 struct click_wifi_extra *ceh = (struct click_wifi_extra *) (skb->cb + EXTRA_HEADER_CB_OFFSET);
01984 u_int8_t dot11Rate = ceh->rate;
01985 const HAL_RATE_TABLE *rt;
01986 int txrate_index;
01987 int power;
01988
01989
01990 wh = (struct ieee80211_frame *) skb->data;
01991 iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
01992 hdrlen = sizeof(struct ieee80211_frame);
01993 if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
01994 isqos = 1;
01995 acc = skb->priority;
01996 hdrlen += sizeof(struct ieee80211_qoscntl);
01997 }
01998 txq = sc->sc_ac2q[acc];
01999
02000
02001
02002 pktlen = skb->len;
02003
02004 pktlen += IEEE80211_CRC_LEN;
02005
02006
02007
02008
02009
02010 bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
02011 skb->data, pktlen, BUS_DMA_TODEVICE);
02012 DPRINTF(sc, ATH_DEBUG_ANY, "ath_tx_start: skb %p [data %p len %u] skbaddr %x\n",
02013 skb, skb->data, skb->len, bf->bf_skbaddr);
02014 bf->bf_skb = skb;
02015 bf->bf_node = NULL;
02016
02017
02018 ds = bf->bf_desc;
02019
02020
02021
02022
02023
02024
02025 shortPreamble = AH_TRUE;
02026
02027
02028
02029
02030
02031 atype = HAL_PKT_TYPE_NORMAL;
02032 if (ceh->magic == WIFI_EXTRA_MAGIC &&
02033 (ceh->flags & WIFI_EXTRA_NO_SEQ)) {
02034 atype = HAL_PKT_TYPE_PSPOLL;
02035 }
02036 rix = 0;
02037 try0 = ATH_TXMAXTRY;
02038
02039
02040 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) {
02041 u_int subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
02042 switch (subtype) {
02043 case IEEE80211_FC0_SUBTYPE_BEACON:
02044 atype = HAL_PKT_TYPE_BEACON;
02045 break;
02046 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: {
02047
02048 u_int64_t tsf;
02049 u_int32_t *tstamp;
02050
02051 atype = HAL_PKT_TYPE_PROBE_RESP;
02052 tsf = ath_hal_gettsf64(ah);
02053
02054 tsf += 100;
02055 tstamp = (u_int32_t *)&wh[1];
02056 tstamp[0] = cpu_to_le32(tsf & 0xffffffff);
02057 tstamp[1] = cpu_to_le32(tsf >> 32);
02058 break;
02059 }
02060 case IEEE80211_FC0_SUBTYPE_ATIM:
02061 atype = HAL_PKT_TYPE_ATIM;
02062 break;
02063 }
02064 }
02065
02066
02067
02068
02069 flags = HAL_TXDESC_CLRDMASK;
02070 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
02071 DPRINTF(sc, ATH_DEBUG_ANY, "%s: %s: noack\n", dev->name,__func__);
02072 flags |= HAL_TXDESC_NOACK;
02073 sc->sc_stats.ast_tx_noack++;
02074 } else if (ceh->magic == WIFI_EXTRA_MAGIC &&
02075 (ceh->flags & WIFI_EXTRA_DO_RTS_CTS)) {
02076 flags |= HAL_TXDESC_RTSENA;
02077 sc->sc_stats.ast_tx_rts++;
02078 }
02079 if (ceh->magic == WIFI_EXTRA_MAGIC &&
02080 ceh->flags & WIFI_EXTRA_DO_CTS) {
02081 flags |= HAL_TXDESC_CTSENA;
02082 }
02083
02084
02085 rt = sc->sc_currates;
02086 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
02087
02088 txrate = 0;
02089 txrate_index = 0;
02090 dot11Rate = ceh->rate;
02091 if (ceh->magic == WIFI_EXTRA_MAGIC && dot11Rate) {
02092 int index = sc->sc_rixmap[dot11Rate & IEEE80211_RATE_VAL];
02093 if (index >= 0 && index < rt->rateCount) {
02094 txrate = rt->info[index].rateCode;
02095 txrate_index = index;
02096 }
02097 }
02098
02099 if (txrate == 0) {
02100 int index;
02101 dot11Rate = sc->ic_fixed_rate;
02102 index = sc->sc_rixmap[dot11Rate & IEEE80211_RATE_VAL];
02103 if (index >= 0 && index < rt->rateCount) {
02104 txrate = rt->info[index].rateCode;
02105 txrate_index = index;
02106 } else {
02107 printk(KERN_WARNING "%s: %s: fixed rate is %d, index invalid %d rateCount %d\n",
02108 dev->name,
02109 __func__,
02110 dot11Rate,
02111 index,
02112 rt->info[index].rateCode);
02113 }
02114 }
02115
02116 if (txrate == 0) {
02117 printk(KERN_WARNING "%s: %s: can't find txrate! fixed rate is %d\n",
02118 dev->name,
02119 __func__,
02120 sc->ic_fixed_rate);
02121
02122
02123 txrate = rt->info[0].rateCode;
02124 txrate_index = 0;
02125 }
02126
02127
02128
02129
02130
02131
02132
02133 if ((flags & HAL_TXDESC_NOACK) == 0 &&
02134 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
02135 u_int16_t dur;
02136
02137 dur = ath_hal_computetxtime(ah, rt, IEEE80211_ACK_SIZE,
02138 txrate_index, shortPreamble);
02139 *(u_int16_t *)wh->i_dur = cpu_to_le16(dur);
02140 }
02141
02142
02143
02144
02145 ctsduration = 0;
02146 ctsrate = 0;
02147
02148 if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
02149
02150
02151
02152
02153
02154 u_int8_t cix = rt->info[txrate_index].controlRate;
02155 ctsrate = rt->info[cix].rateCode;
02156 if (shortPreamble)
02157 ctsrate |= rt->info[cix].shortPreamble;
02158
02159
02160
02161
02162
02163
02164 if (flags & HAL_TXDESC_RTSENA) {
02165 ctsduration += ath_hal_computetxtime(ah,
02166 rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
02167 }
02168
02169 ctsduration += ath_hal_computetxtime(ah,
02170 rt, pktlen, rix, shortPreamble);
02171 if ((flags & HAL_TXDESC_NOACK) == 0) {
02172 ctsduration += ath_hal_computetxtime(ah,
02173 rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
02174 }
02175 }
02176
02177
02178
02179
02180
02181
02182
02183
02184 antenna = 0;
02185
02186 if (IFF_DUMPPKTS(sc)) {
02187 ieee80211_dump_pkt(skb->data, skb->len,
02188 0 & IEEE80211_RATE_VAL, -1);
02189 }
02190
02191
02192 if (1) {
02193 flags |= HAL_TXDESC_INTREQ;
02194 txq->axq_intrcnt = 0;
02195 }
02196
02197 try0 = (ceh->magic == WIFI_EXTRA_MAGIC && ceh->max_retries) ? ceh->max_retries : ATH_TXMAXTRY;
02198 try0 = max(0, try0);
02199 try0 = min(ATH_TXMAXTRY, try0);
02200
02201
02202 power = (ceh->magic == WIFI_EXTRA_MAGIC && ceh->power) ?
02203 ceh->power : ATH_TPC_MAX;
02204 power = max(0, power);
02205 power = min(ATH_TPC_MAX, power);
02206
02207
02208
02209
02210 if (!ath_hal_setuptxdesc(ah, ds
02211 , pktlen
02212 , hdrlen
02213 , atype
02214 , MIN(60,power)
02215 , txrate, try0
02216 , HAL_TXKEYIX_INVALID
02217 , sc->sc_txantenna
02218 , flags
02219 , ctsrate
02220 , ctsduration
02221 )) {
02222 printk("%s: %s ath_hal_setuptxdesc failed\n", dev->name, __func__);
02223 printk("%s: ah %d ds %d pktlen %d hrdlen %d atype %d twpower %d txrate %d tries %d wep %d antenna %d flags %d ctsrate %d ctsduration %d\n"
02224 , dev->name
02225 , (int)ah
02226 , (int)ds
02227 , pktlen
02228 , hdrlen
02229 , atype
02230 , ATH_TPC_MAX
02231 , txrate, try0
02232 , HAL_TXKEYIX_INVALID
02233 , antenna
02234 , flags
02235 , ctsrate
02236 , ctsduration
02237 );
02238
02239 return -1;
02240 }
02241
02242
02243 ds->ds_link = 0;
02244 ds->ds_data = bf->bf_skbaddr;
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254 if (!(flags & HAL_TXDESC_NOACK) &&
02255 ceh->magic == WIFI_EXTRA_MAGIC &&
02256 ceh->rate1) {
02257
02258 int index1 = sc->sc_rixmap[ceh->rate1 & IEEE80211_RATE_VAL];
02259 int index2 = sc->sc_rixmap[ceh->rate2 & IEEE80211_RATE_VAL];
02260 int index3 = sc->sc_rixmap[ceh->rate3 & IEEE80211_RATE_VAL];
02261
02262 u_int8_t txrate1;
02263 u_int8_t txrate2;
02264 u_int8_t txrate3;
02265
02266 index1 = MAX(0, MIN(index1, rt->rateCount));
02267 index2 = MAX(0, MIN(index2, rt->rateCount));
02268 index3 = MAX(0, MIN(index3, rt->rateCount));
02269
02270 txrate1 = rt->info[index1].rateCode;
02271 txrate2 = rt->info[index2].rateCode;
02272 txrate3 = rt->info[index3].rateCode;
02273
02274 if (AH_TRUE != ath_hal_setupxtxdesc(ah, ds
02275 , txrate1, ceh->max_retries1
02276 , txrate2, ceh->max_retries2
02277 , txrate3, ceh->max_retries3
02278 )) {
02279 printk(KERN_WARNING "%s: %s: couldn't setupxtxdesc\n",
02280 dev->name,
02281 __func__);
02282 }
02283
02284 }
02285
02286 if (AH_TRUE != ath_hal_filltxdesc(ah, ds
02287 , roundup(skb->len,4)
02288 , AH_TRUE
02289 , AH_TRUE
02290 , ds
02291 )) {
02292 DPRINTF(sc, ATH_DEBUG_ANY, "%s: %s ath_hal_filltxdesc failed\n", dev->name, __func__);
02293 }
02294 DPRINTF(sc, ATH_DEBUG_ANY, "ath_tx_start: %d: %08x %08x %08x %08x %08x %08x\n",
02295 0, ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
02296 ds->ds_hw[0], ds->ds_hw[1]);
02297
02298
02299
02300
02301
02302 ATH_TXQ_LOCK_BH(txq);
02303 ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
02304 DPRINTF(sc, ATH_DEBUG_ANY, "%s: txq depth = %d\n",
02305 __func__, txq->axq_depth);
02306 if (txq->axq_link == NULL) {
02307 if (AH_TRUE != ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr)) {
02308 printk("%s: %s ath_hal_puttxbuf failed\n",
02309 dev->name,
02310 __func__);
02311 }
02312 } else {
02313 *txq->axq_link = bf->bf_daddr;
02314 DPRINTF(sc, ATH_DEBUG_ANY, "%s: link[%u](%p)=%p (%p)\n",
02315 __func__,
02316 txq->axq_qnum, txq->axq_link,
02317 (caddr_t)bf->bf_daddr, bf->bf_desc);
02318 }
02319 txq->axq_link = &ds->ds_link;
02320 ATH_TXQ_UNLOCK_BH(txq);
02321
02322 if (0 && sc->sc_softled)
02323 ath_update_led(sc, sc->sc_ledstate ^= 1);
02324
02325
02326 if (AH_TRUE != ath_hal_txstart(ah, txq->axq_qnum)) {
02327 printk("%s: %s ath_hal_txstart failed\n", dev->name, __func__);
02328 }
02329
02330 stats->tx_packets++;
02331 stats->tx_bytes += pktlen;
02332
02333 sc->subsequent_kicks = 0;
02334 dev->trans_start = jiffies;
02335 return 0;
02336 #undef MIN
02337 }
02338
02339
02340
02341
02342 static void
02343 ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
02344 {
02345 struct ath_hal *ah = sc->sc_ah;
02346 struct ath_buf *bf;
02347 struct ath_desc *ds;
02348 HAL_STATUS status;
02349 struct click_wifi_extra *ceh;
02350 struct ieee80211_frame *wh;
02351
02352
02353 DPRINTF(sc, ATH_DEBUG_ANY, "%s: tx queue %p, link %p\n", __func__,
02354 (caddr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
02355 txq->axq_link);
02356 for (;;) {
02357 ATH_TXQ_LOCK(txq);
02358 txq->axq_intrcnt = 0;
02359 bf = STAILQ_FIRST(&txq->axq_q);
02360 if (bf == NULL) {
02361 txq->axq_link = NULL;
02362 ATH_TXQ_UNLOCK(txq);
02363 break;
02364 }
02365 ds = bf->bf_desc;
02366 status = ath_hal_txprocdesc(ah, ds);
02367
02368 if (ath_debug > 1)
02369 ath_printtxbuf(bf, status == HAL_OK);
02370
02371
02372 if (status == HAL_EINPROGRESS) {
02373 ATH_TXQ_UNLOCK(txq);
02374 break;
02375 }
02376
02377 ATH_TXQ_REMOVE_HEAD(txq, bf_list);
02378 ATH_TXQ_UNLOCK(txq);
02379
02380 bus_unmap_single(sc->sc_bdev,
02381 bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
02382
02383 ceh = (struct click_wifi_extra *) (bf->bf_skb->cb + EXTRA_HEADER_CB_OFFSET);
02384
02385 if (1) {
02386 ceh->len = bf->bf_skb->len;
02387 if (bf->bf_skb->len > sizeof(struct ieee80211_frame)) {
02388
02389 }
02390
02391 if (ceh->magic != WIFI_EXTRA_MAGIC) {
02392 ceh->flags = 0;
02393 }
02394 ceh->magic = WIFI_EXTRA_MAGIC;
02395 ceh->flags |= WIFI_EXTRA_TX;
02396 if (ds->ds_txstat.ts_status) {
02397 ceh->flags |= WIFI_EXTRA_TX_FAIL;
02398 }
02399 if (ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE) {
02400 ceh->flags |= WIFI_EXTRA_TX_USED_ALT_RATE;
02401 }
02402 if (!ceh->rate) {
02403 ceh->rate = sc->sc_hwmap[ds->ds_txstat.ts_rate] & IEEE80211_RATE_VAL;
02404 }
02405
02406
02407
02408 ceh->retries = ds->ds_txstat.ts_longretry;
02409 ceh->rssi = ds->ds_txstat.ts_rssi;
02410 ceh->virt_col = ds->ds_txstat.ts_virtcol;
02411
02412 ceh->virt_col = ((ds->ds_hw[3] >> 16) & 0xf);
02413 }
02414
02415 wh = (struct ieee80211_frame *) bf->bf_skb->data;
02416 if (0) {
02417 u_int16_t old_seq = le16_to_cpu(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
02418 printk ("old seq %d new seq %d\n",
02419 old_seq,
02420 ds->ds_txstat.ts_seqnum);
02421 }
02422
02423
02424 if (!(ceh->flags & WIFI_EXTRA_NO_SEQ) &&
02425 bf->bf_skb->len >= sizeof(struct ieee80211_frame)) {
02426
02427 *(u_int16_t *) wh->i_seq = cpu_to_le16(ds->ds_txstat.ts_seqnum << IEEE80211_SEQ_SEQ_SHIFT);
02428 }
02429
02430 if (sc->dev_type == ARPHRD_IEEE80211_PRISM) {
02431 push_prism2_header(&sc->dev, bf->bf_skb,
02432 ds->ds_rxstat.rs_datalen,
02433 ds->ds_rxstat.rs_rssi,
02434 sc->sc_hwmap[ds->ds_txstat.ts_rate] &
02435 IEEE80211_RATE_VAL,
02436 1,
02437 0);
02438 }
02439 if (ceh->magic == WIFI_EXTRA_MAGIC && !(ceh->flags & WIFI_EXTRA_NO_TXF)) {
02440
02441
02442
02443
02444
02445 if (atomic_read(&bf->bf_skb->users) != 1) {
02446 struct sk_buff *skb2=bf->bf_skb;
02447 bf->bf_skb=skb_clone(bf->bf_skb, GFP_ATOMIC);
02448 if (bf->bf_skb == NULL) {
02449 dev_kfree_skb(skb2);
02450 bf->bf_skb = NULL;
02451 }
02452 kfree_skb(skb2);
02453 } else {
02454 skb_orphan(bf->bf_skb);
02455 }
02456 if (bf->bf_skb) {
02457 bf->bf_skb->dev = &sc->dev;
02458 bf->bf_skb = push_wifi_extra_header(bf->bf_skb);
02459 if (bf->bf_skb) {
02460 netif_rx(bf->bf_skb);
02461 }
02462 }
02463 } else {
02464 dev_kfree_skb(bf->bf_skb);
02465 }
02466
02467
02468 bf->bf_skb = NULL;
02469 bf->bf_node = NULL;
02470
02471 ATH_TXBUF_LOCK(sc);
02472 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
02473 ATH_TXBUF_UNLOCK(sc);
02474 }
02475 }
02476
02477
02478 static void
02479 ath_tx_tasklet(TQUEUE_ARG data)
02480 {
02481 struct net_device *dev = (struct net_device *) data;
02482 struct ath_softc *sc = dev->priv;
02483
02484 int i;
02485
02486 DPRINTF(sc, ATH_DEBUG_ANY, "%s: %s\n", dev->name, __func__);
02487 for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
02488 if (ATH_TXQ_SETUP(sc, i))
02489 ath_tx_processq(sc, &sc->sc_txq[i]);
02490 }
02491
02492
02493
02494
02495
02496
02497 if (!STAILQ_EMPTY(&sc->sc_txbuf) && netif_queue_stopped(dev)) {
02498 netif_wake_queue(dev);
02499 }
02500 }
02501
02502 static void
02503 ath_tx_timeout(struct net_device *dev)
02504 {
02505 struct ath_softc *sc = dev->priv;
02506 sc->sc_stats.ast_watchdog++;
02507 printk("%s: %s timeout at %ld, latency %ld pending %d\n",
02508 dev->name,
02509 __func__,
02510 jiffies,
02511 jiffies - dev->trans_start,
02512 ath_hal_intrpend(sc->sc_ah));
02513
02514 sc->subsequent_kicks++;
02515 if (sc->subsequent_kicks == 1) {
02516
02517 ath_intr(dev->irq, dev, 0);
02518 } else {
02519
02520 ath_init(dev);
02521
02522 }
02523 }
02524
02525 static void
02526 ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
02527 {
02528 struct ath_hal *ah = sc->sc_ah;
02529 struct ath_buf *bf;
02530
02531
02532
02533
02534
02535 for (;;) {
02536 ATH_TXQ_LOCK(txq);
02537 bf = STAILQ_FIRST(&txq->axq_q);
02538 if (bf == NULL) {
02539 txq->axq_link = NULL;
02540 ATH_TXQ_UNLOCK(txq);
02541 break;
02542 }
02543 ATH_TXQ_REMOVE_HEAD(txq, bf_list);
02544 ATH_TXQ_UNLOCK(txq);
02545 #ifdef AR_DEBUG
02546 if (sc->sc_debug & ATH_DEBUG_ANY)
02547 ath_printtxbuf(bf,
02548 ath_hal_txprocdesc(ah, bf->bf_desc) == HAL_OK);
02549 #endif
02550 bus_unmap_single(sc->sc_bdev,
02551 bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE);
02552 dev_kfree_skb(bf->bf_skb);
02553 bf->bf_skb = NULL;
02554 bf->bf_node = NULL;
02555 ATH_TXBUF_LOCK(sc);
02556 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
02557 ATH_TXBUF_UNLOCK(sc);
02558 }
02559 }
02560 static void
02561 ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
02562 {
02563 struct ath_hal *ah = sc->sc_ah;
02564
02565 (void) ath_hal_stoptxdma(ah, txq->axq_qnum);
02566 DPRINTF(sc, ATH_DEBUG_ANY, "%s: tx queue [%u] %p, link %p\n",
02567 __func__, txq->axq_qnum,
02568 (caddr_t) ath_hal_gettxbuf(ah, txq->axq_qnum), txq->axq_link);
02569 }
02570
02571
02572
02573 static void
02574 ath_draintxq(struct ath_softc *sc)
02575 {
02576 int i;
02577
02578
02579 if (!sc->sc_invalid) {
02580 for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
02581 if (ATH_TXQ_SETUP(sc, i))
02582 ath_tx_stopdma(sc, &sc->sc_txq[i]);
02583 }
02584 sc->dev.trans_start = jiffies;
02585 netif_start_queue(&sc->dev);
02586 for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
02587 if (ATH_TXQ_SETUP(sc, i))
02588 ath_tx_draintxq(sc, &sc->sc_txq[i]);
02589 }
02590
02591
02592
02593
02594 static void
02595 ath_stoprecv(struct ath_softc *sc)
02596 {
02597 #define PA2DESC(_sc, _pa) \
02598 ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
02599 ((_pa) - (_sc)->sc_desc_daddr)))
02600 struct ath_hal *ah = sc->sc_ah;
02601
02602 ath_hal_stoppcurecv(ah);
02603 ath_hal_setrxfilter(ah, 0);
02604 ath_hal_stopdmarecv(ah);
02605 mdelay(3);
02606 #ifdef AR_DEBUG
02607 if (ath_debug) {
02608 struct ath_buf *bf;
02609
02610 printk("ath_stoprecv: rx queue %p, link %p\n",
02611 (caddr_t) ath_hal_getrxbuf(ah), sc->sc_rxlink);
02612 STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
02613 struct ath_desc *ds = bf->bf_desc;
02614 HAL_STATUS status = ath_hal_rxprocdesc(ah, ds,
02615 bf->bf_daddr, PA2DESC(sc, ds->ds_link));
02616 if (status == HAL_OK || (sc->sc_debug & ATH_DEBUG_ANY))
02617 ath_printrxbuf(bf, status == HAL_OK);
02618 }
02619 }
02620 #endif
02621 sc->sc_rxlink = NULL;
02622 #undef PA2DESC
02623 }
02624
02625
02626
02627
02628 static int
02629 ath_startrecv(struct net_device *dev)
02630 {
02631 struct ath_softc *sc = dev->priv;
02632 struct ath_hal *ah = sc->sc_ah;
02633 struct ath_buf *bf;
02634
02635
02636 sc->sc_rxbufsize = roundup(3196, sc->sc_cachelsz);
02637
02638 DPRINTF(sc, ATH_DEBUG_ANY, "ath_startrecv: mtu %u cachelsz %u rxbufsize %u\n",
02639 dev->mtu, sc->sc_cachelsz, sc->sc_rxbufsize);
02640
02641 sc->sc_rxlink = NULL;
02642
02643 STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
02644 int error = ath_rxbuf_init(sc, bf);
02645 if (error != 0)
02646 return error;
02647 }
02648
02649 bf = STAILQ_FIRST(&sc->sc_rxbuf);
02650 ath_hal_putrxbuf(ah, bf->bf_daddr);
02651 ath_hal_rxena(ah);
02652 ath_mode_init(&sc->dev);
02653 ath_hal_startpcurecv(ah);
02654 return 0;
02655 }
02656
02657
02658
02659
02660
02661 static void
02662 ath_calibrate(unsigned long arg)
02663 {
02664 struct net_device *dev = (struct net_device *) arg;
02665 struct ath_softc *sc = dev->priv;
02666 struct ath_hal *ah = sc->sc_ah;
02667 struct ieee80211channel *c;
02668 HAL_CHANNEL hchan;
02669
02670 sc->sc_stats.ast_per_cal++;
02671
02672
02673
02674
02675
02676 c = sc->current_channel;
02677 hchan.channel = c->ic_freq;
02678 hchan.channelFlags = ath_chan2flags(sc, c);
02679
02680
02681
02682 if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) {
02683
02684
02685
02686
02687 sc->sc_stats.ast_per_rfgain++;
02688 ath_reset(dev);
02689 }
02690 if (!ath_hal_calibrate(ah, &hchan)) {
02691 DPRINTF(sc, ATH_DEBUG_ANY, "%s: %s: calibration of channel %u failed\n",
02692 dev->name, __func__, c->ic_freq);
02693 sc->sc_stats.ast_per_calfail++;
02694 }
02695 sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
02696 add_timer(&sc->sc_cal_ch);
02697 }
02698
02699
02700 static int
02701 ath_getchannels(struct net_device *dev, u_int cc,
02702 HAL_BOOL outdoor, HAL_BOOL xchanmode)
02703 {
02704 struct ath_softc *sc = dev->priv;
02705 struct ath_hal *ah = sc->sc_ah;
02706 HAL_CHANNEL *chans;
02707 int i, ix, nchan;
02708
02709 chans = kmalloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL), GFP_KERNEL);
02710 if (chans == NULL) {
02711 printk("%s: unable to allocate channel table\n", dev->name);
02712 return ENOMEM;
02713 }
02714 if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
02715 cc, HAL_MODE_ALL, outdoor, xchanmode)) {
02716 u_int32_t rd;
02717
02718 ath_hal_getregdomain(ah, &rd);
02719 printk("%s: unable to collect channel list from hal; "
02720 "regdomain likely %u country code %u\n",
02721 dev->name, rd, cc);
02722 kfree(chans);
02723 return 0;
02724
02725 }
02726
02727
02728
02729
02730
02731
02732 for (i = 0; i < nchan; i++) {
02733 HAL_CHANNEL *c = &chans[i];
02734 ix = ath_hal_mhz2ieee(c->channel, c->channelFlags);
02735 if (ix > IEEE80211_CHAN_MAX) {
02736 continue;
02737 }
02738
02739 if (sc->ic_channels[ix].ic_freq == 0) {
02740 sc->ic_channels[ix].ic_freq = c->channel;
02741 sc->ic_channels[ix].ic_flags = c->channelFlags;
02742 } else {
02743
02744 sc->ic_channels[ix].ic_flags |= c->channelFlags;
02745 }
02746 }
02747
02748 kfree(chans);
02749 return 0;
02750 }
02751
02752 static int
02753 ath_setchannel(struct ath_softc *sc, struct ieee80211channel *channel)
02754 {
02755
02756
02757 #define N(a) (sizeof(a) / sizeof(a[0]))
02758 static const u_int chanflags[] = {
02759 0,
02760 IEEE80211_CHAN_A,
02761 IEEE80211_CHAN_B,
02762 IEEE80211_CHAN_PUREG,
02763 IEEE80211_CHAN_T,
02764 };
02765 struct ieee80211channel *c;
02766 u_int modeflags;
02767 int i;
02768 const HAL_RATE_TABLE *rt;
02769
02770
02771
02772
02773
02774 enum ieee80211_phymode mode = chan2mode(sc, channel);
02775
02776
02777
02778
02779
02780 KASSERT(mode < N(chanflags), ("Unexpected mode %u\n", mode));
02781 modeflags = chanflags[mode];
02782 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
02783 c = &sc->ic_channels[i];
02784 if (mode == IEEE80211_MODE_AUTO) {
02785
02786 if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
02787 break;
02788 } else {
02789 if ((c->ic_flags & modeflags) == modeflags)
02790 break;
02791 }
02792 }
02793 if (i > IEEE80211_CHAN_MAX) {
02794 printk("%s: no channels found for mode %u\n",
02795 __func__, mode);
02796 return -EINVAL;
02797 }
02798
02799
02800
02801
02802
02803
02804
02805 if (channel == NULL ||
02806 isclr(sc->ic_chan_avail, chan2ieee(sc, channel))) {
02807 printk("%s: %s: invalid channel %d\n",
02808 __func__,
02809 sc->dev.name,
02810 channel ? chan2ieee(sc, channel) : 0);
02811 channel = NULL;
02812 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
02813 if ((c->ic_flags & modeflags) == modeflags) {
02814 channel = &sc->ic_channels[i];
02815 break;
02816 }
02817 }
02818
02819 if (!channel) {
02820 printk("%s: %s couldn't find valid channel\n",
02821 __func__,
02822 sc->dev.name);
02823 return -EINVAL;
02824 }
02825
02826 rt = sc->sc_rates[mode];
02827 if (!rt) {
02828 printk("%s: %s: no h/w rate set for phy mode %u",
02829 __func__,
02830 sc->dev.name,
02831 mode);
02832 return -EINVAL;
02833 }
02834 sc->current_channel = channel;
02835 sc->ic_curmode = mode;
02836
02837 memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
02838
02839
02840
02841
02842 sc->ic_fixed_rate = 0;
02843
02844 for (i = 0; i < rt->rateCount; i++) {
02845 sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i;
02846 if (!sc->ic_fixed_rate && rt->info[i].valid) {
02847
02848 sc->ic_fixed_rate = rt->info[i].dot11Rate & IEEE80211_RATE_VAL;
02849 }
02850 }
02851
02852 memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
02853 for (i = 0; i < 32; i++) {
02854 u_int8_t ix = rt->rateCodeToIndex[i];
02855 if (ix != 0xff)
02856 sc->sc_hwmap[i] = rt->info[ix].dot11Rate;
02857
02858 }
02859 sc->sc_currates = rt;
02860 return 0;
02861 }
02862
02863
02864 static int
02865 ath_rate_setup(struct net_device *dev, u_int mode)
02866 {
02867 struct ath_softc *sc = dev->priv;
02868 struct ath_hal *ah = sc->sc_ah;
02869 const HAL_RATE_TABLE *rt;
02870 int maxrates;
02871 int x = 0;
02872 switch (mode) {
02873 case IEEE80211_MODE_11A:
02874 sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A);
02875 break;
02876 case IEEE80211_MODE_11B:
02877 sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11B);
02878 break;
02879 case IEEE80211_MODE_11G:
02880 sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11G);
02881 break;
02882 case IEEE80211_MODE_TURBO:
02883 sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_TURBO);
02884 break;
02885 default:
02886 DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid mode %u\n", __func__, mode);
02887 return 0;
02888 }
02889 rt = sc->sc_rates[mode];
02890 if (rt == NULL)
02891 return 0;
02892 if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
02893 DPRINTF(sc, ATH_DEBUG_ANY, "%s: rate table too small (%u > %u)\n",
02894 __func__, rt->rateCount, IEEE80211_RATE_MAXSIZE);
02895 maxrates = IEEE80211_RATE_MAXSIZE;
02896 } else
02897 maxrates = rt->rateCount;
02898
02899 printk("%s: mode %d rates (in Mbps):",
02900 dev->name,
02901 mode);
02902 for ( x = 0; x < rt->rateCount; x++) {
02903 if (rt->info[x].valid) {
02904 if (rt->info[x].rateKbps % 1000) {
02905 printk(" %d.%1d",
02906 rt->info[x].rateKbps / 1000,
02907 (rt->info[x].rateKbps % 1000) / 100);
02908 } else {
02909 printk(" %d", rt->info[x].rateKbps / 1000);
02910 }
02911 }
02912 }
02913 printk("\n");
02914 return 1;
02915 }
02916
02917 #ifdef AR_DEBUG
02918 static void
02919 ath_printrxbuf(struct ath_buf *bf, int done)
02920 {
02921 struct ath_desc *ds = bf->bf_desc;
02922
02923 printk("R (%p %p) %08x %08x %08x %08x %08x %08x %c\n",
02924 ds, (struct ath_desc *)bf->bf_daddr,
02925 ds->ds_link, ds->ds_data,
02926 ds->ds_ctl0, ds->ds_ctl1,
02927 ds->ds_hw[0], ds->ds_hw[1],
02928 !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
02929 }
02930
02931 static void
02932 ath_printtxbuf(struct ath_buf *bf, int done)
02933 {
02934 struct ath_desc *ds = bf->bf_desc;
02935
02936 printk("T (%p %p) %08x %08x %08x %08x %08x %08x %08x %08x %c\n",
02937 ds, (struct ath_desc *)bf->bf_daddr,
02938 ds->ds_link, ds->ds_data,
02939 ds->ds_ctl0, ds->ds_ctl1,
02940 ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
02941 !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
02942 }
02943 #endif
02944
02945
02946
02947
02948 static struct net_device_stats *
02949 ath_getstats(struct net_device *dev)
02950 {
02951 struct ath_softc *sc = dev->priv;
02952 struct net_device_stats *stats = &sc->ic_stats;
02953
02954
02955 stats->tx_errors = sc->sc_stats.ast_tx_encap
02956 + sc->sc_stats.ast_tx_nonode
02957 + sc->sc_stats.ast_tx_xretries
02958 + sc->sc_stats.ast_tx_fifoerr
02959 + sc->sc_stats.ast_tx_filtered
02960 ;
02961 stats->tx_dropped = sc->sc_stats.ast_tx_nobuf
02962 + sc->sc_stats.ast_tx_nobufmgt;
02963 stats->rx_errors = sc->sc_stats.ast_rx_tooshort
02964 + sc->sc_stats.ast_rx_crcerr
02965 + sc->sc_stats.ast_rx_fifoerr
02966 + sc->sc_stats.ast_rx_badcrypt
02967 ;
02968 stats->rx_crc_errors = sc->sc_stats.ast_rx_crcerr;
02969
02970 return stats;
02971 }
02972
02973 static int
02974 ath_set_mac_address(struct net_device *dev, void *addr)
02975 {
02976 struct ath_softc *sc = dev->priv;
02977 struct ath_hal *ah = sc->sc_ah;
02978 struct sockaddr *mac = addr;
02979
02980 if (netif_running(dev)) {
02981 DPRINTF(sc, ATH_DEBUG_ANY, "%s: cannot set address; device running\n", __func__);
02982 return -EBUSY;
02983 }
02984 DPRINTF(sc, ATH_DEBUG_ANY, "%s: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", __func__,
02985 mac->sa_data[0], mac->sa_data[1], mac->sa_data[2],
02986 mac->sa_data[3], mac->sa_data[4], mac->sa_data[5]);
02987 IEEE80211_ADDR_COPY(dev->dev_addr, mac->sa_data);
02988 ath_hal_setmac(ah, dev->dev_addr);
02989 return -ath_reset(dev);
02990 }
02991
02992 static int
02993 ath_change_mtu(struct net_device *dev, int mtu)
02994 {
02995 if (!(ATH_MIN_MTU < mtu && mtu <= ATH_MAX_MTU)) {
02996 return -EINVAL;
02997 }
02998 dev->mtu = mtu;
02999 return -ath_reset(dev);
03000 }
03001
03002
03003
03004
03005
03006
03007
03008 static int
03009 ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
03010 {
03011 struct ath_hal *ah = sc->sc_ah;
03012 u_int id = ad->ad_id & ATH_DIAG_ID;
03013 void *indata = NULL;
03014 void *outdata = NULL;
03015 u_int32_t insize = ad->ad_in_size;
03016 u_int32_t outsize = ad->ad_out_size;
03017 int error = 0;
03018
03019 if (ad->ad_id & ATH_DIAG_IN) {
03020
03021
03022
03023 indata = kmalloc(insize, GFP_KERNEL);
03024 if (indata == NULL) {
03025 error = -ENOMEM;
03026 goto bad;
03027 }
03028 if (copy_from_user(indata, ad->ad_in_data, insize)) {
03029 error = -EFAULT;
03030 goto bad;
03031 }
03032 }
03033 if (ad->ad_id & ATH_DIAG_DYN) {
03034
03035
03036
03037
03038
03039
03040
03041 outdata = kmalloc(outsize, GFP_KERNEL);
03042 if (outdata == NULL) {
03043 error = -ENOMEM;
03044 goto bad;
03045 }
03046 }
03047 if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) {
03048 if (outsize < ad->ad_out_size)
03049 ad->ad_out_size = outsize;
03050 if (outdata &&
03051 copy_to_user(ad->ad_out_data, outdata, ad->ad_out_size))
03052 error = -EFAULT;
03053 } else {
03054 error = -EINVAL;
03055 }
03056 bad:
03057 if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
03058 kfree(indata);
03059 if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
03060 kfree(outdata);
03061 return error;
03062 }
03063
03064
03065 extern int ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void *addr);
03066
03067 static int
03068 ath_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
03069 {
03070 struct ath_softc *sc = dev->priv;
03071 int error;
03072
03073 switch (cmd) {
03074 case SIOCGATHSTATS:
03075 error = 0;
03076 break;
03077 case SIOCGATHDIAG:
03078 if (!capable(CAP_NET_ADMIN))
03079 error = -EPERM;
03080 else
03081 error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
03082 break;
03083 case SIOCETHTOOL:
03084 if (copy_from_user(&cmd, ifr->ifr_data, sizeof(cmd)))
03085 error = -EFAULT;
03086 else
03087 error = ath_ioctl_ethtool(sc, cmd, ifr->ifr_data);
03088 break;
03089 default:
03090 error = 0;
03091 break;
03092 }
03093 return error;
03094 }
03095
03096 #ifdef CONFIG_SYSCTL
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113 enum {
03114 ATH_SLOTTIME = 1,
03115 ATH_ACKTIMEOUT = 2,
03116 ATH_CTSTIMEOUT = 3,
03117 ATH_SOFTLED = 4,
03118 ATH_LEDPIN = 5,
03119 ATH_COUNTRYCODE = 6,
03120 ATH_REGDOMAIN = 7,
03121 ATH_DEBUG = 8,
03122 ATH_TXANTENNA = 9,
03123 ATH_RXANTENNA = 10,
03124 ATH_DIVERSITY = 11,
03125 ATH_PHYERR = 12,
03126 };
03127
03128 static int
03129 ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
03130 {
03131 struct ath_softc *sc = ctl->extra1;
03132 struct ath_hal *ah = sc->sc_ah;
03133 u_int val;
03134 int ret;
03135
03136 ctl->data = &val;
03137 ctl->maxlen = sizeof(val);
03138 if (write) {
03139 ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
03140 lenp, ppos);
03141 if (ret == 0) {
03142 switch (ctl->ctl_name) {
03143 case ATH_SLOTTIME:
03144 if (!ath_hal_setslottime(ah, val))
03145 ret = -EINVAL;
03146 break;
03147 case ATH_ACKTIMEOUT:
03148 if (!ath_hal_setacktimeout(ah, val))
03149 ret = -EINVAL;
03150 break;
03151 case ATH_CTSTIMEOUT:
03152 if (!ath_hal_setctstimeout(ah, val))
03153 ret = -EINVAL;
03154 break;
03155 case ATH_SOFTLED:
03156 if (val != sc->sc_softled) {
03157 if (val)
03158 ath_hal_gpioCfgOutput(ah,
03159 sc->sc_ledpin);
03160 ath_hal_gpioset(ah, sc->sc_ledpin,!val);
03161 sc->sc_softled = val;
03162 }
03163 break;
03164 case ATH_LEDPIN:
03165 sc->sc_ledpin = val;
03166 break;
03167 case ATH_DEBUG:
03168 sc->sc_debug = val;
03169 break;
03170 case ATH_TXANTENNA:
03171
03172 sc->sc_txantenna = val;
03173 break;
03174 case ATH_RXANTENNA:
03175
03176 ath_setdefantenna(sc, val);
03177 break;
03178 case ATH_DIVERSITY:
03179
03180 if (!sc->sc_hasdiversity)
03181 return -EINVAL;
03182 sc->sc_diversity = val;
03183 ath_hal_setdiversity(ah, val);
03184 break;
03185 case ATH_PHYERR: {
03186 uint32_t rfilt = ath_calcrxfilter(&sc->dev);
03187 ath_phyerr = val;
03188 ath_hal_setrxfilter(ah, rfilt);
03189 break;
03190 }
03191 default:
03192 return -EINVAL;
03193 }
03194 }
03195 } else {
03196 switch (ctl->ctl_name) {
03197 case ATH_SLOTTIME:
03198 val = ath_hal_getslottime(ah);
03199 break;
03200 case ATH_ACKTIMEOUT:
03201 val = ath_hal_getacktimeout(ah);
03202 break;
03203 case ATH_CTSTIMEOUT:
03204 val = ath_hal_getctstimeout(ah);
03205 break;
03206 case ATH_SOFTLED:
03207 val = sc->sc_softled;
03208 break;
03209 case ATH_LEDPIN:
03210 val = sc->sc_ledpin;
03211 break;
03212 case ATH_COUNTRYCODE:
03213 ath_hal_getcountrycode(ah, &val);
03214 break;
03215 case ATH_REGDOMAIN:
03216 ath_hal_getregdomain(ah, &val);
03217 break;
03218 case ATH_DEBUG:
03219 val = sc->sc_debug;
03220 break;
03221 case ATH_TXANTENNA:
03222 val = sc->sc_txantenna;
03223 break;
03224 case ATH_RXANTENNA:
03225 val = ath_hal_getdefantenna(ah);
03226 break;
03227 case ATH_DIVERSITY:
03228 val = sc->sc_diversity;
03229 break;
03230 case ATH_PHYERR:
03231 val = ath_phyerr;
03232 break;
03233 default:
03234 return -EINVAL;
03235 }
03236 ret = ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
03237 lenp, ppos);
03238 }
03239 return ret;
03240 }
03241
03242 static int mindwelltime = 100;
03243 static int mincalibrate = 1;
03244 static int maxint = 0x7fffffff;
03245
03246 #define CTL_AUTO -2
03247
03248 static const ctl_table ath_sysctl_template[] = {
03249 { .ctl_name = ATH_SLOTTIME,
03250 .procname = "slottime",
03251 .mode = 0644,
03252 .proc_handler = ath_sysctl_halparam
03253 },
03254 { .ctl_name = ATH_ACKTIMEOUT,
03255 .procname = "acktimeout",
03256 .mode = 0644,
03257 .proc_handler = ath_sysctl_halparam
03258 },
03259 { .ctl_name = ATH_CTSTIMEOUT,
03260 .procname = "ctstimeout",
03261 .mode = 0644,
03262 .proc_handler = ath_sysctl_halparam
03263 },
03264 { .ctl_name = ATH_SOFTLED,
03265 .procname = "softled",
03266 .mode = 0644,
03267 .proc_handler = ath_sysctl_halparam
03268 },
03269 { .ctl_name = ATH_LEDPIN,
03270 .procname = "ledpin",
03271 .mode = 0644,
03272 .proc_handler = ath_sysctl_halparam
03273 },
03274 { .ctl_name = ATH_COUNTRYCODE,
03275 .procname = "countrycode",
03276 .mode = 0444,
03277 .proc_handler = ath_sysctl_halparam
03278 },
03279 { .ctl_name = ATH_REGDOMAIN,
03280 .procname = "regdomain",
03281 .mode = 0444,
03282 .proc_handler = ath_sysctl_halparam
03283 },
03284 #ifdef AR_DEBUG
03285 { .ctl_name = ATH_DEBUG,
03286 .procname = "debug",
03287 .mode = 0644,
03288 .proc_handler = ath_sysctl_halparam
03289 },
03290 #endif
03291 { .ctl_name = ATH_TXANTENNA,
03292 .procname = "txantenna",
03293 .mode = 0644,
03294 .proc_handler = ath_sysctl_halparam
03295 },
03296 { .ctl_name = ATH_RXANTENNA,
03297 .procname = "rxantenna",
03298 .mode = 0644,
03299 .proc_handler = ath_sysctl_halparam
03300 },
03301 { .ctl_name = ATH_DIVERSITY,
03302 .procname = "diversity",
03303 .mode = 0644,
03304 .proc_handler = ath_sysctl_halparam
03305 },
03306 { .ctl_name = ATH_PHYERR,
03307 .procname = "phyerr",
03308 .mode = 0644,
03309 .proc_handler = ath_sysctl_halparam
03310 },
03311 { 0 }
03312 };
03313
03314 static void
03315 ath_dynamic_sysctl_register(struct ath_softc *sc)
03316 {
03317 int i, space;
03318
03319 space = 5*sizeof(struct ctl_table) + sizeof(ath_sysctl_template);
03320 sc->sc_sysctls = kmalloc(space, GFP_KERNEL);
03321 if (sc->sc_sysctls == NULL) {
03322 printk("%s: no memory for sysctl table!\n", __func__);
03323 return;
03324 }
03325
03326
03327 memset(sc->sc_sysctls, 0, space);
03328 sc->sc_sysctls[0].ctl_name = CTL_DEV;
03329 sc->sc_sysctls[0].procname = "dev";
03330 sc->sc_sysctls[0].mode = 0555;
03331 sc->sc_sysctls[0].child = &sc->sc_sysctls[2];
03332
03333 sc->sc_sysctls[2].ctl_name = CTL_AUTO;
03334 sc->sc_sysctls[2].procname = sc->dev.name;
03335 sc->sc_sysctls[2].mode = 0555;
03336 sc->sc_sysctls[2].child = &sc->sc_sysctls[4];
03337
03338
03339 memcpy(&sc->sc_sysctls[4], ath_sysctl_template,
03340 sizeof(ath_sysctl_template));
03341
03342
03343 for (i = 4; sc->sc_sysctls[i].ctl_name; i++)
03344 if (sc->sc_sysctls[i].extra1 == NULL)
03345 sc->sc_sysctls[i].extra1 = sc;
03346
03347
03348 sc->sc_sysctl_header = register_sysctl_table(sc->sc_sysctls, 1);
03349 if (!sc->sc_sysctl_header) {
03350 printk("%s: failed to register sysctls!\n", sc->dev.name);
03351 kfree(sc->sc_sysctls);
03352 sc->sc_sysctls = NULL;
03353 }
03354
03355
03356 sc->sc_debug = ath_debug;
03357 sc->sc_txantenna = 0;
03358 }
03359
03360 static void
03361 ath_dynamic_sysctl_unregister(struct ath_softc *sc)
03362 {
03363 if (sc->sc_sysctl_header) {
03364 unregister_sysctl_table(sc->sc_sysctl_header);
03365 sc->sc_sysctl_header = NULL;
03366 }
03367 if (sc->sc_sysctls) {
03368 kfree(sc->sc_sysctls);
03369 sc->sc_sysctls = NULL;
03370 }
03371 }
03372
03373
03374
03375
03376 static void
03377 ath_announce(struct net_device *dev)
03378 {
03379 #define HAL_MODE_DUALBAND (HAL_MODE_11A|HAL_MODE_11B)
03380 struct ath_softc *sc = dev->priv;
03381 struct ath_hal *ah = sc->sc_ah;
03382 u_int modes, cc;
03383 int i;
03384
03385 printk("%s: mac %d.%d phy %d.%d", dev->name,
03386 ah->ah_macVersion, ah->ah_macRev,
03387 ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
03388
03389
03390
03391
03392
03393 ath_hal_getcountrycode(ah, &cc);
03394 modes = ath_hal_getwirelessmodes(ah, cc);
03395 if ((modes & HAL_MODE_DUALBAND) == HAL_MODE_DUALBAND) {
03396 if (ah->ah_analog5GhzRev && ah->ah_analog2GhzRev)
03397 printk(" 5ghz radio %d.%d 2ghz radio %d.%d",
03398 ah->ah_analog5GhzRev >> 4,
03399 ah->ah_analog5GhzRev & 0xf,
03400 ah->ah_analog2GhzRev >> 4,
03401 ah->ah_analog2GhzRev & 0xf);
03402 else
03403 printk(" radio %d.%d", ah->ah_analog5GhzRev >> 4,
03404 ah->ah_analog5GhzRev & 0xf);
03405 } else
03406 printk(" radio %d.%d", ah->ah_analog5GhzRev >> 4,
03407 ah->ah_analog5GhzRev & 0xf);
03408 printk("\n");
03409 printk("%s: 802.11 address: %s\n",
03410 dev->name, ether_sprintf(dev->dev_addr));
03411 for (i = 0; i <= WME_AC_VO; i++) {
03412 struct ath_txq *txq = sc->sc_ac2q[i];
03413 printk("%s: Use hw queue %u for %s traffic\n",
03414 dev->name, txq->axq_qnum, acnames[i]);
03415 }
03416 #undef HAL_MODE_DUALBAND
03417 }
03418
03419
03420
03421
03422
03423 enum {
03424 DEV_ATH = 9,
03425 };
03426
03427 static ctl_table ath_static_sysctls[] = {
03428 #ifdef AR_DEBUG
03429 { .ctl_name = CTL_AUTO,
03430 .procname = "debug",
03431 .mode = 0644,
03432 .data = &ath_debug,
03433 .maxlen = sizeof(ath_debug),
03434 .proc_handler = proc_dointvec
03435 },
03436 #endif
03437 { .ctl_name = CTL_AUTO,
03438 .procname = "countrycode",
03439 .mode = 0444,
03440 .data = &ath_countrycode,
03441 .maxlen = sizeof(ath_countrycode),
03442 .proc_handler = proc_dointvec
03443 },
03444 { .ctl_name = CTL_AUTO,
03445 .procname = "regdomain",
03446 .mode = 0444,
03447 .data = &ath_regdomain,
03448 .maxlen = sizeof(ath_regdomain),
03449 .proc_handler = proc_dointvec
03450 },
03451 { .ctl_name = CTL_AUTO,
03452 .procname = "outdoor",
03453 .mode = 0444,
03454 .data = &ath_outdoor,
03455 .maxlen = sizeof(ath_outdoor),
03456 .proc_handler = proc_dointvec
03457 },
03458 { .ctl_name = CTL_AUTO,
03459 .procname = "xchanmode",
03460 .mode = 0444,
03461 .data = &ath_xchanmode,
03462 .maxlen = sizeof(ath_xchanmode),
03463 .proc_handler = proc_dointvec
03464 },
03465 { .ctl_name = CTL_AUTO,
03466 .procname = "dwelltime",
03467 .mode = 0644,
03468 .data = &ath_dwelltime,
03469 .maxlen = sizeof(ath_dwelltime),
03470 .extra1 = &mindwelltime,
03471 .extra2 = &maxint,
03472 .proc_handler = proc_dointvec_minmax
03473 },
03474 { .ctl_name = CTL_AUTO,
03475 .procname = "calibrate",
03476 .mode = 0644,
03477 .data = &ath_calinterval,
03478 .maxlen = sizeof(ath_calinterval),
03479 .extra1 = &mincalibrate,
03480 .extra2 = &maxint,
03481 .proc_handler = proc_dointvec_minmax
03482 },
03483 { 0 }
03484 };
03485 static ctl_table ath_ath_table[] = {
03486 { .ctl_name = DEV_ATH,
03487 .procname = "ath",
03488 .mode = 0555,
03489 .child = ath_static_sysctls
03490 }, { 0 }
03491 };
03492 static ctl_table ath_root_table[] = {
03493 { .ctl_name = CTL_DEV,
03494 .procname = "dev",
03495 .mode = 0555,
03496 .child = ath_ath_table
03497 }, { 0 }
03498 };
03499 static struct ctl_table_header *ath_sysctl_header;
03500
03501 void
03502 ath_sysctl_register(void)
03503 {
03504 static int initialized = 0;
03505
03506 if (!initialized) {
03507 ath_sysctl_header =
03508 register_sysctl_table(ath_root_table, 1);
03509 initialized = 1;
03510 }
03511 }
03512
03513 void
03514 ath_sysctl_unregister(void)
03515 {
03516 if (ath_sysctl_header)
03517 unregister_sysctl_table(ath_sysctl_header);
03518 }
03519 #endif