Changeset 3505

Timestamp:
04/10/08 05:21:59 (2 months ago)
Author:
mtaylor
Message:

This update uses the recently added HAL extensions for controlling noise immunity settings in order to correctly re-implement disabling of interference mitigation.

A module parameter and sysctl parameter are provided for changing whether interference mitigation is enabled or disabled.

When interference mitigation is disabled, we work around a HAL defect where the interference mitigation auto-tuning algorithm still starts and/or sets some initially high mitigation levels.

With this fix, disabling interference mitigation with the current HAL behaves like it did in prior HALs.

Far greater receive sensitivity and increased range is supported with this disabled. This is especially useful for long distance point-to-point links.

As a part of this fix, a severe bug that was originally a workaround for the HAL issue has been corrected. When interference mitigation is enabled, we NEVER want to eat or throttle the MIB interrupts as the hardware counter callbacks to the HAL are what drives the interference mitigation calibration state machine. Conversely, if interferference mitigation is being blocked by our driver but the hAL may still be enabling the HAL_INT_MIB in the IMR, then we want to force the interrupt OFF in the mask and eat the interrupt.

The failure case was where the interrupt would fire continually and never get properly handled because the HAL wasn't configured to handle interfernece mitigation - now we mask the interrupt OFF. With the 'throttling' hack, we didn't fix hte problem but made it worse - when interfernce mitigation was enabled we just blocked the necessary signals to get the counters updated and stop the interrupt from continuing to fire.

The timer to re-enable the MIB interrupt after it fired was also wrong cause it would make sure the interrupt could never be disabled by the HAL or the driver.

Files:
  • madwifi/trunk/ath/if_ath.c (modified) (22 diffs)
  • madwifi/trunk/ath/if_athvar.h (modified) (1 diff)

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • madwifi/trunk/ath/if_ath.c

    r3504 r3505  
    218 218 static void ath_chan_change(struct ath_softc *, struct ieee80211_channel *); 
    219 219 static void ath_calibrate(unsigned long); 
    220   static void ath_mib_enable(unsigned long); 
    221 220 static int ath_newstate(struct ieee80211vap *, enum ieee80211_state, int); 
    222 221  
     
    387 386 static int rfkill = 0; 
    388 387 static int tpc = 0; 
      388  
    389 389 static int countrycode = -1; 
    390 390 static int maxvaps = -1; 
     
    428 428 MODULE_PARM(autocreate, "s"); 
    429 429 MODULE_PARM(ratectl, "s"); 
      430  
    430 431 #else 
    431 432 #include  
     
    441 442 module_param(autocreate, charp, 0600); 
    442 443 module_param(ratectl, charp, 0600); 
      444  
    443 445 #endif 
    444 446 MODULE_PARM_DESC(countrycode, "Override default country code"); 
     
    456 458 MODULE_PARM_DESC(ratectl, "Rate control algorithm [amrr|minstrel|onoe|sample], " 
    457 459                 "defaults to '" DEF_RATE_CTL "'"); 
      460  
    458 461  
    459 462 static int      ath_debug = 0; 
     
    580 583         } 
    581 584         sc->sc_ah = ah; 
    582    
      585         /* 
      586          * Init ic_caps prior to queue init, since WME cap setting 
      587          * depends on queue setup. 
      588          */ 
      589         ic->ic_caps = 0; 
      590  
      591         /* Interference mitigation/ambient noise immunity (ANI). 
      592          * In modes other than HAL_M_STA, it causes receive sensitivity 
      593          * problems for OFDM. */ 
      594         sc->sc_hasintmit = ath_hal_hasintmit(ah); 
      595         if (!sc->sc_hasintmit) { 
      596                 if (intmit) { 
      597                         WPRINTF(sc, "Interference mitigation was requested, " 
      598                                     "but is not supported by the " 
      599                                     "HAL/hardware.\n"); 
      600                         intmit = 0; 
      601                 } 
      602                 sc->sc_useintmit = 0; 
      603         } 
      604         else { 
      605                 ath_hal_setintmit(ah, (sc->sc_useintmit = intmit)); 
      606                 IPRINTF(sc, "Interference mitigation is supported.  Currently %s.\n", 
      607                         (sc->sc_useintmit ? "enabled" : "disabled")); 
      608         } 
    583 609         /* 
    584 610          * Check if the MAC has multi-rate retry support. 
     
    595 621          * so we can act on stat triggers. 
    596 622          */ 
    597           if (ath_hal_hwphycounters(ah)) 
    598                   sc->sc_needmib = 1; 
      623         sc->sc_needmib = ath_hal_hwphycounters(ah) &&  
      624                 sc->sc_hasintmit &&  
      625                 sc->sc_useintmit; 
    599 626  
    600 627         /* 
     
    641 668         ic->ic_country_outdoor = ath_outdoor; 
    642 669  
    643           IPRINTF(sc, "Switching rfkill capability %s\n", 
      670         IPRINTF(sc, "Switching rfkill capability %s\n", 
    644 671                 rfkill ? "on" : "off"); 
    645 672         ath_hal_setrfsilent(ah, rfkill); 
     
    669 696                 goto bad; 
    670 697         } 
    671    
    672           /* 
    673            * Init ic_caps prior to queue init, since WME cap setting 
    674            * depends on queue setup. 
    675            */ 
    676           ic->ic_caps = 0; 
    677 698  
    678 699         /* 
     
    790 811         ath_rp_init(sc); 
    791 812  
    792           init_timer(&sc->sc_mib_enable); 
    793           sc->sc_mib_enable.function = ath_mib_enable; 
    794           sc->sc_mib_enable.data = (unsigned long) sc; 
    795    
    796 813 #ifdef ATH_SUPERG_DYNTURBO 
    797 814         init_timer(&sc->sc_dturbo_switch_mode); 
     
    937 954                 } 
    938 955         } 
      956  
    939 957         /* 
    940 958          * TPC support can be done either with a global cap or 
     
    1001 1019         sc->sc_hasveol = ath_hal_hasveol(ah); 
    1002 1020  
    1003           /* Interference mitigation/ambient noise immunity (ANI). 
    1004            * In modes other than HAL_M_STA, it causes receive sensitivity 
    1005            * problems for OFDM. */ 
    1006           sc->sc_hasintmit = ath_hal_hasintmit(ah); 
    1007 1021  
    1008 1022         /* get mac address from hardware */ 
     
    1584 1598         ath_init(dev); 
    1585 1599 } 
      1600  
      1601  
      1602  
      1603  
      1604  
      1605  
      1606  
      1607  
      1608  
      1609  
      1610  
      1611  
      1612  
      1613  
      1614  
      1615  
      1616  
      1617  
      1618  
      1619  
      1620  
      1621  
      1622  
      1623  
      1624  
      1625  
      1626  
      1627  
      1628  
      1629  
      1630  
      1631  
    1586 1632  
    1587 1633 /* Channel Availability Check is running, or a channel has already found to be  
     
    2317 2363                 if (status & HAL_INT_MIB) { 
    2318 2364                         sc->sc_stats.ast_mib++; 
    2319                           /* When the card receives lots of PHY errors, the MIB 
    2320                            * interrupt will fire at a very rapid rate. We will use 
    2321                            * a timer to enforce at least 1 jiffy delay between 
    2322                            * MIB interrupts. This should be unproblematic, since 
    2323                            * the hardware will continue to update the counters in  
    2324                            * the mean time. */ 
    2325                           sc->sc_imask &= ~HAL_INT_MIB; 
    2326                           ath_hal_intrset(ah, sc->sc_imask); 
    2327                           mod_timer(&sc->sc_mib_enable, jiffies + 1); 
    2328    
    2329                           /* Let the HAL handle the event. */ 
      2365                         /* If we aren't doing interference mitigation and we get 
      2366                          * a lot of MIB events we can safely skip them. 
      2367                          * However, we must never throttle them DURING interference 
      2368                          * mitigation calibration sequence as it depends on this 
      2369                          * hook to advance the calibration sequence / alg. 
      2370                          */ 
      2371                         if (!sc->sc_useintmit) { 
      2372                                 sc->sc_imask &= ~HAL_INT_MIB; 
      2373                                 ath_hal_intrset(ah, sc->sc_imask); 
      2374                         } 
      2375  
      2376                         /* Let the HAL handle the event.*/ 
    2330 2377                         ath_hal_mibevent(ah, &sc->sc_halstats); 
      2378  
    2331 2379                 } 
    2332 2380         } 
     
    6667 6715          *      mode.  
    6668 6716          *      This may will not affect ANI problems in client only mode. */ 
    6669           if (sc->sc_opmode == HAL_M_STA) 
      6717         if (sc->sc_  
    6670 6718                 ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan); 
    6671 6719 #undef PA2DESC 
     
    8570 8618         ath_mode_init(dev);             /* set filters, etc. */ 
    8571 8619         ath_hal_startpcurecv(ah);       /* re-enable PCU/DMA engine */ 
      8620  
    8572 8621         return 0; 
    8573 8622 } 
     
    8780 8829                                 tv.tv_sec, tv.tv_usec); 
    8781 8830         return 0; 
    8782   } 
    8783    
    8784   /* 
    8785    * Enable MIB interrupts again, after the ISR disabled them 
    8786    * to slow down the rate of PHY error reporting. 
    8787    */ 
    8788   static void 
    8789   ath_mib_enable(unsigned long arg) 
    8790   { 
    8791           struct ath_softc *sc = (struct ath_softc *)arg; 
    8792    
    8793           sc->sc_imask |= HAL_INT_MIB; 
    8794           ath_hal_intrset(sc->sc_ah, sc->sc_imask); 
    8795 8831 } 
    8796 8832  
     
    10501 10537         ATH_RADAR_IGNORED       = 25, 
    10502 10538         ATH_MAXVAPS             = 26, 
      10539  
    10503 10540 }; 
    10504 10541  
     
    10511 10548         u_int tab_3_val[3]; 
    10512 10549         int ret = 0; 
      10550  
    10513 10551  
    10514 10552         ctl->data = &val; 
     
    10682 10720                                 sc->sc_radar_ignored = val; 
    10683 10721                                 break; 
      10722  
      10723  
      10724  
      10725  
      10726  
      10727  
      10728  
      10729  
      10730  
      10731  
      10732  
      10733  
      10734  
      10735  
      10736  
      10737  
      10738  
      10739  
      10740  
      10741  
      10742  
      10743  
      10744  
    10684 10745                         default: 
    10685 10746                                 ret = -EINVAL; 
     
    10748 10809                         val = sc->sc_radar_ignored; 
    10749 10810                         break; 
    10750                   default: 
      10811                 case ATH_INTMIT:  
      10812                         val = sc->sc_useintmit;  
      10813                         break;  
      10814                 default: 
    10751 10815                         ret = -EINVAL; 
    10752 10816                         break; 
     
    10925 10989           .extra2       = (void *)ATH_RADAR_IGNORED, 
    10926 10990         }, 
      10991  
      10992  
      10993  
      10994  
      10995  
      10996  
    10927 10997         { 0 } 
    10928 10998 }; 
  • madwifi/trunk/ath/if_athvar.h

    r3504 r3505  
    671 671         unsigned int    sc_dfs_cac:1;           /* waiting on channel for radar detect */ 
    672 672         unsigned int    sc_hasintmit:1;         /* Interference mitigation */ 
      673  
    673 674         unsigned int    sc_txcont:1;            /* Is continuous transmit enabled? */ 
    674 675         unsigned int    sc_dfs_testmode:1;      /* IF this is on, AP vaps will stay in