kernel/ath - Synchronize with FreeBSD
authorMatthew Dillon <dillon@backplane.com>
Tue, 20 Jan 2015 16:51:00 +0000 (08:51 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 3 Feb 2015 20:11:08 +0000 (12:11 -0800)
* Synchronize ath with FreeBSD.

65 files changed:
sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h
sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h
sys/dev/netif/ath/ath/if_ath.c
sys/dev/netif/ath/ath/if_ath_ahb.c
sys/dev/netif/ath/ath/if_ath_beacon.c
sys/dev/netif/ath/ath/if_ath_beacon.h
sys/dev/netif/ath/ath/if_ath_btcoex.c
sys/dev/netif/ath/ath/if_ath_debug.c
sys/dev/netif/ath/ath/if_ath_debug.h
sys/dev/netif/ath/ath/if_ath_keycache.c
sys/dev/netif/ath/ath/if_ath_led.c
sys/dev/netif/ath/ath/if_ath_lna_div.c
sys/dev/netif/ath/ath/if_ath_pci.c
sys/dev/netif/ath/ath/if_ath_pci_devlist.h [new file with mode: 0644]
sys/dev/netif/ath/ath/if_ath_rx.c
sys/dev/netif/ath/ath/if_ath_rx_edma.c
sys/dev/netif/ath/ath/if_ath_spectral.c
sys/dev/netif/ath/ath/if_ath_sysctl.c
sys/dev/netif/ath/ath/if_ath_tdma.c
sys/dev/netif/ath/ath/if_ath_tx.c
sys/dev/netif/ath/ath/if_ath_tx_edma.c
sys/dev/netif/ath/ath/if_ath_tx_ht.c
sys/dev/netif/ath/ath/if_athvar.h
sys/dev/netif/ath/ath_dfs/null/dfs_null.c
sys/dev/netif/ath/ath_hal/ah.c
sys/dev/netif/ath/ath_hal/ah.h
sys/dev/netif/ath/ath_hal/ah_decode.h
sys/dev/netif/ath/ath_hal/ah_internal.h
sys/dev/netif/ath/ath_hal/ah_osdep.c
sys/dev/netif/ath/ath_hal/ah_osdep.h
sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c
sys/dev/netif/ath/ath_hal/ar5211/ar5211_attach.c
sys/dev/netif/ath/ath_hal/ar5212/ar5212_attach.c
sys/dev/netif/ath/ath_hal/ar5212/ar5212_reset.c
sys/dev/netif/ath/ath_hal/ar5312/ar5312_attach.c
sys/dev/netif/ath/ath_hal/ar5416/ar5416_attach.c
sys/dev/netif/ath/ath_hal/ar5416/ar5416_radar.c
sys/dev/netif/ath/ath_hal/ar5416/ar5416_reset.c
sys/dev/netif/ath/ath_hal/ar71xx/ar71xx_cpudef.h [deleted file]
sys/dev/netif/ath/ath_hal/ar71xx/ar71xxreg.h [deleted file]
sys/dev/netif/ath/ath_hal/ar9001/ar9130_attach.c
sys/dev/netif/ath/ath_hal/ar9001/ar9160_attach.c
sys/dev/netif/ath/ath_hal/ar9002/ar9280_attach.c
sys/dev/netif/ath/ath_hal/ar9002/ar9280_olc.c
sys/dev/netif/ath/ath_hal/ar9002/ar9285_attach.c
sys/dev/netif/ath/ath_hal/ar9002/ar9285_btcoex.c
sys/dev/netif/ath/ath_hal/ar9002/ar9287_attach.c
sys/dev/netif/ath/ath_hal/ar91xx/ar91xxreg.h [deleted file]
sys/dev/netif/ath/ath_rate/amrr/amrr.c
sys/dev/netif/ath/ath_rate/onoe/onoe.c
sys/dev/netif/ath/ath_rate/sample/sample.c
sys/dev/netif/ath/ath_rate/sample/tx_schedules.h

index 73b902f..30c55a0 100644 (file)
@@ -1181,10 +1181,11 @@ struct ath_hal;
 
 extern  struct ath_hal_9300 * ar9300_new_state(u_int16_t devid,
         HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+        HAL_OPS_CONFIG *ah_config,
         HAL_STATUS *status);
 extern  struct ath_hal * ar9300_attach(u_int16_t devid,
         HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
-        HAL_STATUS *status);
+        HAL_OPS_CONFIG *ah_config, HAL_STATUS *status);
 extern  void ar9300_detach(struct ath_hal *ah);
 extern void ar9300_read_revisions(struct ath_hal *ah);
 extern  HAL_BOOL ar9300_chip_test(struct ath_hal *ah);
index 7bfb2c5..75746fc 100644 (file)
@@ -484,6 +484,9 @@ ar9300_ani_control(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
              */
             is_on = param ? 1 : 0;
 
+            if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah))
+                goto skip_ws_det;
+
             /*
              * make register setting for default (weak sig detect ON)
              * come from INI file
@@ -528,6 +531,7 @@ ar9300_ani_control(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
                 m1_thresh_ext);
             OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH,
                 m2_thresh_ext);
+skip_ws_det:
             if (is_on) {
                 OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
                     AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
@@ -1201,7 +1205,7 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
         }
         if (old_phy_noise_spur != ani_state->phy_noise_spur) {
             HALDEBUG(ah, HAL_DEBUG_ANI,
-                     "%s: environment change from %d to %d\n",
+                     "%s: enviroment change from %d to %d\n",
                      __func__, old_phy_noise_spur, ani_state->phy_noise_spur);
         }
     }
index 9cc99ec..80dc2a3 100644 (file)
@@ -618,7 +618,8 @@ ar9300_read_revisions(struct ath_hal *ah)
  */
 struct ath_hal *
 ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
-  HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *status)
+  HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_OPS_CONFIG *ah_config,
+  HAL_STATUS *status)
 {
     struct ath_hal_9300     *ahp;
     struct ath_hal          *ah;
@@ -628,7 +629,7 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
     HAL_NO_INTERSPERSED_READS;
 
     /* NB: memory is returned zero'd */
-    ahp = ar9300_new_state(devid, sc, st, sh, eepromdata, status);
+    ahp = ar9300_new_state(devid, sc, st, sh, eepromdata, ah_config, status);
     if (ahp == AH_NULL) {
         return AH_NULL;
     }
@@ -654,12 +655,6 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
     /* XXX FreeBSD: enable RX mitigation */
     ah->ah_config.ath_hal_intr_mitigation_rx = 1;
 
-    /*
-     * XXX what's this do? Check in the qcamain driver code
-     * as to what it does.
-     */
-    ah->ah_config.ath_hal_ext_atten_margin_cfg = 0;
-
     /* interrupt mitigation */
 #ifdef AR5416_INT_MITIGATION
     if (ah->ah_config.ath_hal_intr_mitigation_rx != 0) {
@@ -2378,7 +2373,9 @@ ar9300_detach(struct ath_hal *ah)
 struct ath_hal_9300 *
 ar9300_new_state(u_int16_t devid, HAL_SOFTC sc,
     HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
-    uint16_t *eepromdata, HAL_STATUS *status)
+    uint16_t *eepromdata,
+    HAL_OPS_CONFIG *ah_config,
+    HAL_STATUS *status)
 {
     static const u_int8_t defbssidmask[IEEE80211_ADDR_LEN] =
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -2430,7 +2427,7 @@ ar9300_new_state(u_int16_t devid, HAL_SOFTC sc,
     ** Initialize factory defaults in the private space
     */
 //    ath_hal_factory_defaults(AH_PRIVATE(ah), hal_conf_parm);
-    ar9300_config_defaults_freebsd(ah);
+    ar9300_config_defaults_freebsd(ah, ah_config);
 
     /* XXX FreeBSD: cal is always in EEPROM */
 #if 0
@@ -2456,6 +2453,7 @@ ar9300_new_state(u_int16_t devid, HAL_SOFTC sc,
     AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;  /* no scaling */
 
     ahp->ah_atim_window = 0;         /* [0..1000] */
+
     ahp->ah_diversity_control =
         ah->ah_config.ath_hal_diversity_control;
     ahp->ah_antenna_switch_swap =
@@ -3835,6 +3833,11 @@ ar9300_ant_div_comb_get_config(struct ath_hal *ah,
     } else {
         div_comb_conf->antdiv_configgroup = DEFAULT_ANTDIV_CONFIG_GROUP;
     }
+
+    /*
+     * XXX TODO: allow the HAL to override the rssithres and fast_div_bias
+     * values (eg CUS198.)
+     */
 }
 
 void
index 97c5193..669104a 100644 (file)
@@ -1606,6 +1606,7 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
     if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
         value &= ~AR_SWITCH_TABLE_COM2_ALL;
         value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value)
     }
 #endif  /* ATH_ANT_DIV_COMB */
     OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@@ -1711,6 +1712,8 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
             /* For WB225, need to swith ANT2 from BT to Wifi
              * This will not affect HB125 LNA diversity feature.
              */
+            HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__,
+                ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable)
             OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, 
                 ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable);
             break;
@@ -1776,6 +1779,7 @@ ar9300_attenuation_margin_chain_get(struct ath_hal *ah, int chain,
     return 0;
 }
 
+#if 0
 HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
 {
     u_int32_t value;
@@ -1814,6 +1818,75 @@ HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
     }
     return 0;
 }
+#endif
+HAL_BOOL
+ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
+{
+       int i;
+       uint32_t value;
+       uint32_t ext_atten_reg[3] = {
+           AR_PHY_EXT_ATTEN_CTL_0,
+           AR_PHY_EXT_ATTEN_CTL_1,
+           AR_PHY_EXT_ATTEN_CTL_2
+       };
+
+       /*
+        * If it's an AR9462 and we're receiving on the second
+        * chain only, set the chain 0 details from chain 1
+        * calibration.
+        *
+        * This is from ath9k.
+        */
+       if (AR_SREV_JUPITER(ah) && (AH9300(ah)->ah_rx_chainmask == 0x2)) {
+               value = ar9300_attenuation_chain_get(ah, 1, channel);
+               OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
+                   AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+               value = ar9300_attenuation_margin_chain_get(ah, 1, channel);
+               OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
+                   AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
+       }
+
+       /*
+        * Now, loop over the configured transmit chains and
+        * load in the attenuation/margin settings as appropriate.
+        */
+       for (i = 0; i < 3; i++) {
+               if ((AH9300(ah)->ah_tx_chainmask & (1 << i)) == 0)
+                       continue;
+
+               value = ar9300_attenuation_chain_get(ah, i, channel);
+               OS_REG_RMW_FIELD(ah, ext_atten_reg[i],
+                   AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB,
+                   value);
+
+               if (AR_SREV_POSEIDON(ah) &&
+                   (ar9300_rx_gain_index_get(ah) == 0) &&
+                   ah->ah_config.ath_hal_ext_atten_margin_cfg) {
+                       value = 5;
+               } else {
+                       value = ar9300_attenuation_margin_chain_get(ah, 0,
+                           channel);
+               }
+
+               /*
+                * I'm not sure why it's loading in this setting into
+                * the chain 0 margin regardless of the current chain.
+                */
+               if (ah->ah_config.ath_hal_min_gainidx)
+                       OS_REG_RMW_FIELD(ah,
+                           AR_PHY_EXT_ATTEN_CTL_0,
+                           AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+                           value);
+
+               OS_REG_RMW_FIELD(ah,
+                   ext_atten_reg[i],
+                   AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+                   value);
+       }
+
+       return (0);
+}
+
 
 static u_int16_t ar9300_quick_drop_get(struct ath_hal *ah, 
                                                                int chain, u_int16_t channel)
@@ -3789,7 +3862,7 @@ ar9300_eeprom_restore_internal_address(struct ath_hal *ah,
                     dptr = ar9300_eeprom_struct_default_find_by_id(reference);
                     if (dptr == 0) {
                         HALDEBUG(ah, HAL_DEBUG_EEPROM,
-                            "%s: can't find reference eeprom struct %d\n",
+                            "%s: cant find reference eeprom struct %d\n",
                             __func__, reference);
                         break;
                     }
index a2cc25d..315086c 100644 (file)
@@ -70,9 +70,6 @@ void
 ar9300_attach_freebsd_ops(struct ath_hal *ah)
 {
 
-       /* stub everything first */
-       ar9300_set_stub_functions(ah);
-
        /* Global functions */
        ah->ah_detach           = ar9300_detach;
        ah->ah_getRateTable             = ar9300_get_rate_table;
@@ -252,12 +249,21 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
        ah->ah_btCoexDisable            = ar9300_bt_coex_disable;
        ah->ah_btCoexEnable             = ar9300_bt_coex_enable;
 
+       /* MCI bluetooth functions */
+       if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
+               ah->ah_btCoexSetWeights = ar9300_mci_bt_coex_set_weights;
+               ah->ah_btCoexDisable = ar9300_mci_bt_coex_disable;
+               ah->ah_btCoexEnable = ar9300_mci_bt_coex_enable;
+       }
+       ah->ah_btMciSetup               = ar9300_mci_setup;
+       ah->ah_btMciSendMessage         = ar9300_mci_send_message;
+       ah->ah_btMciGetInterrupt        = ar9300_mci_get_interrupt;
+       ah->ah_btMciGetState            = ar9300_mci_state;
+       ah->ah_btMciDetach              = ar9300_mci_detach;
+
        /* LNA diversity functions */
        ah->ah_divLnaConfGet = ar9300_ant_div_comb_get_config;
        ah->ah_divLnaConfSet = ar9300_ant_div_comb_set_config;
-
-       /* Setup HAL configuration defaults */
-       ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable = 0x000bbb88;
 }
 
 HAL_BOOL
@@ -341,9 +347,11 @@ ar9300_ani_poll_freebsd(struct ath_hal *ah,
  * wants.
  */
 void
-ar9300_config_defaults_freebsd(struct ath_hal *ah)
+ar9300_config_defaults_freebsd(struct ath_hal *ah, HAL_OPS_CONFIG *ah_config)
 {
 
+       /* Until FreeBSD's HAL does this by default - just copy */
+       OS_MEMCPY(&ah->ah_config, ah_config, sizeof(HAL_OPS_CONFIG));
        ah->ah_config.ath_hal_enable_ani = AH_TRUE;
 }
 
@@ -471,11 +479,13 @@ ar9300_freebsd_setup_x_tx_desc(struct ath_hal *ah, struct ath_desc *ds,
     u_int txRate3, u_int txTries3)
 {
 
+#if 0
        ath_hal_printf(ah, "%s: called, 0x%x/%d, 0x%x/%d, 0x%x/%d\n",
            __func__,
            txRate1, txTries1,
            txRate2, txTries2,
            txRate3, txTries3);
+#endif
 
        /* XXX should only be called during probe */
        return (AH_TRUE);
@@ -596,8 +606,8 @@ ar9300_freebsd_beacon_init(struct ath_hal *ah, uint32_t next_beacon,
     uint32_t beacon_period)
 {
 
-       ar9300_beacon_init(ah, AH_PRIVATE(ah)->ah_opmode,
-           next_beacon, beacon_period);
+       ar9300_beacon_init(ah, next_beacon, beacon_period,
+           AH_PRIVATE(ah)->ah_opmode);
 }
 
 HAL_BOOL
index c07c32f..524c3f3 100644 (file)
@@ -11,7 +11,8 @@ extern        HAL_STATUS ar9300_eeprom_get_freebsd(struct ath_hal *, int param,
 extern HAL_BOOL ar9300_stop_tx_dma_freebsd(struct ath_hal *ah, u_int q);
 extern void ar9300_ani_poll_freebsd(struct ath_hal *ah,
            const struct ieee80211_channel *chan);
-extern void ar9300_config_defaults_freebsd(struct ath_hal *ah);
+extern void ar9300_config_defaults_freebsd(struct ath_hal *ah,
+           HAL_OPS_CONFIG *ah_config);
 extern HAL_BOOL ar9300_stop_dma_receive_freebsd(struct ath_hal *ah);
 extern HAL_BOOL ar9300_get_pending_interrupts_freebsd(struct ath_hal *ah,
            HAL_INT *masked);
index a159c2c..f7ddf15 100644 (file)
@@ -57,7 +57,9 @@
 #ifdef AH_SUPPORT_AR9340
 #define AH_SUPPORT_WASP                        1
 #endif /* AH_SUPPORT_AR9340 */
-//#define AH_SUPPORT_SCORPION             1
+#ifdef AH_SUPPORT_QCA9550
+#define AH_SUPPORT_SCORPION             1
+#endif /* AH_SUPPORT_QCA9550 */
 #define FIX_NOISE_FLOOR                 1
 
 /* XXX this needs to be removed! No atomics in the HAL! */
index 2d9f4a2..5660c1f 100644 (file)
@@ -285,7 +285,7 @@ ar9300_gpio_cfg_output_led_off(
         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL1,
         AR_GPIO_OUTPUT_MUX_AS_SMARTANT_CTRL2
     };
-    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
+    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);
 
     /* Convert HAL signal type definitions to hardware-specific values. */
     if ((int) halSignalType < ARRAY_LENGTH(mux_signal_conversion_table))
index c97a5f5..5a4623f 100644 (file)
@@ -666,15 +666,8 @@ ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip)
     HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
         modes[ar9300_get_power_mode(ah)], modes[mode],
         set_chip ? "set chip " : "");
-
-#if 0
-    kprintf("%s: %s -> %s (%s)\n", __func__,
-        modes[ar9300_get_power_mode(ah)], modes[mode],
-        set_chip ? "set chip " : "");
-#endif
-
     OS_MARK(ah, AH_MARK_CHIP_POWER, mode);
-
+    
     switch (mode) {
     case HAL_PM_AWAKE:
         if (set_chip)
index 1090c9c..51ce195 100644 (file)
@@ -6151,6 +6151,7 @@ ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, cons
             value &= ~AR_SWITCH_TABLE_COM2_ALL;
             value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
         }
+       HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value);
         OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
 
         value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
index 2dd9472..211e201 100644 (file)
@@ -33,7 +33,7 @@ void
 ar9300_set_stub_functions(struct ath_hal *ah)
 {
 
-       ath_hal_printf(ah, "%s: setting stub functions\n", __func__);
+//     ath_hal_printf(ah, "%s: setting stub functions\n", __func__);
 
        ah->ah_getRateTable             = ar9300_Stub_GetRateTable;
 //     ah->ah_detach                   = ar9300_Stub_detach;
index 9eda1a9..ab39284 100644 (file)
@@ -699,7 +699,7 @@ ar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout)
 #define AH_TIME_QUANTUM        100     /* usec */
     u_int wait;
 
-    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);
+    HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues);
 
     HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);
 
index 596f6dc..72ed110 100644 (file)
@@ -68,9 +68,11 @@ ar9300_fill_tx_desc(
     const void *ds0)
 {
     struct ar9300_txc *ads = AR9300TXC(ds);
+    short desclen;
 
     /* Fill TXC info field */
-    ads->ds_info = TXC_INFO(qcu);
+    desclen = (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) ? 0x18 : 0x17;
+    ads->ds_info = TXC_INFO(qcu, desclen);
 
     /* Set the buffer addresses */
     ads->ds_data0 = buf_addr[0];
@@ -124,6 +126,9 @@ ar9300_fill_tx_desc(
         ads->ds_ctl17 = SM(key_type, AR_encr_type);
     }
 
+    /* Only relevant for Jupiter/Aphrodite */
+    ads->ds_ctl23 = 0;
+
     return AH_TRUE;
 }
 
index 9054db0..5dbf927 100644 (file)
@@ -78,7 +78,8 @@ struct ar9300_txc {
     u_int32_t   ds_ctl20;  /* DMA control 20 */
     u_int32_t   ds_ctl21;  /* DMA control 21 */
     u_int32_t   ds_ctl22;  /* DMA control 22 */
-    u_int32_t   ds_pad[9]; /* pad to cache line (128 bytes/32 dwords) */
+    u_int32_t   ds_ctl23;  /* DMA control 23 */
+    u_int32_t   ds_pad[8]; /* pad to cache line (128 bytes/32 dwords) */
 };
 
 
@@ -347,6 +348,7 @@ struct ar9300_txc {
 
 /* ds_status2 */
 #define AR_data_len          0x00000fff
+#define AR_data_len_S        0
 #define AR_rx_more           0x00001000
 #define AR_num_delim         0x003fc000
 #define AR_num_delim_S       14
@@ -428,11 +430,11 @@ struct ar9300_txc {
 #define RXSTATUS_NUMWORDS(ah) 11
 
 
-#define TXC_INFO(_qcu) (ATHEROS_VENDOR_ID << AR_desc_id_S) \
+#define TXC_INFO(_qcu, _desclen) (ATHEROS_VENDOR_ID << AR_desc_id_S) \
                         | (1 << AR_tx_rx_desc_S) \
                         | (1 << AR_ctrl_stat_S) \
                         | (_qcu << AR_tx_qcu_num_S) \
-                        | (0x17)
+                        | (_desclen)
 
 #define VALID_KEY_TYPES \
         ((1 << HAL_KEY_TYPE_CLEAR) | (1 << HAL_KEY_TYPE_WEP)|\
index 0e59bb9..5da0971 100644 (file)
@@ -139,9 +139,9 @@ enum Ar9300EepromTemplate
 #define OSPREY_CUSTOMER_DATA_SIZE    20
 
 #define FREQ2FBIN(x,y) \
-    (((uintmax_t)(y) == (uintmax_t)HAL_FREQ_BAND_2GHZ) ? ((x) - 2300) : (((x) - 4800) / 5))
+    (((y) == (int)HAL_FREQ_BAND_2GHZ) ? ((x) - 2300) : (((x) - 4800) / 5))
 #define FBIN2FREQ(x,y) \
-    (((uintmax_t)(y) == (uintmax_t)HAL_FREQ_BAND_2GHZ) ? (2300 + x) : (4800 + 5 * x))
+    (((y) == (int)HAL_FREQ_BAND_2GHZ) ? (2300 + x) : (4800 + 5 * x))
 #define OSPREY_MAX_CHAINS            3
 #define OSPREY_ANT_16S               25
 #define OSPREY_FUTURE_MODAL_SZ       6
index 7b8884c..2ed6576 100644 (file)
@@ -28,6 +28,9 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define CTLFLAG_RWTUN  CTLFLAG_RW
 
 /*
  * Driver for the Atheros Wireless LAN controller.
 #include <dev/netif/ath/ath/if_athdfs.h>
 
 #ifdef ATH_TX99_DIAG
-#include <dev/netif/ath/ath_tx99/ath_tx99.h>
+#include <dev/netif/ath/ath/ath_tx99/ath_tx99.h>
 #endif
 
 #ifdef ATH_DEBUG_ALQ
@@ -153,18 +156,22 @@ static void       ath_stop_locked(struct ifnet *);
 static void    ath_stop(struct ifnet *);
 static int     ath_reset_vap(struct ieee80211vap *, u_long);
 static int     ath_transmit(struct ifnet *ifp, struct mbuf *m);
-#if 0
+#if !defined(__DragonFly__)
 static void    ath_qflush(struct ifnet *ifp);
 #endif
 static int     ath_media_change(struct ifnet *);
 static void    ath_watchdog(void *);
-static void    ath_start(struct ifnet *, struct ifaltq_subque *);
-static int     ath_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
+#if defined(__DragonFly__)
+static int     ath_ioctl(struct ifnet *, u_long, caddr_t, struct ucred * __unused);
+#else
+static int     ath_ioctl(struct ifnet *, u_long, caddr_t);
+#endif
 static void    ath_fatal_proc(void *, int);
 static void    ath_bmiss_vap(struct ieee80211vap *);
 static void    ath_bmiss_proc(void *, int);
 static void    ath_key_update_begin(struct ieee80211vap *);
 static void    ath_key_update_end(struct ieee80211vap *);
+static void    ath_update_mcast_hw(struct ath_softc *);
 static void    ath_update_mcast(struct ifnet *);
 static void    ath_update_promisc(struct ifnet *);
 static void    ath_updateslot(struct ifnet *);
@@ -214,18 +221,18 @@ static void       ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
 static void    ath_announce(struct ath_softc *);
 
 static void    ath_dfs_tasklet(void *, int);
-#if 0
 static void    ath_node_powersave(struct ieee80211_node *, int);
+static int     ath_node_set_tim(struct ieee80211_node *, int);
 static void    ath_node_recv_pspoll(struct ieee80211_node *, struct mbuf *);
+
+#if defined(__DragonFly__)
+static void    ath_start(struct ifnet *ifp, struct ifaltq_subque *ifsq);
 #endif
-static int     ath_node_set_tim(struct ieee80211_node *, int);
 
 #ifdef IEEE80211_SUPPORT_TDMA
 #include <dev/netif/ath/ath/if_ath_tdma.h>
 #endif
 
-extern const char* ath_hal_ether_sprintf(const u_int8_t *mac);
-
 SYSCTL_DECL(_hw_ath);
 
 /* XXX validate sysctl values */
@@ -243,15 +250,17 @@ SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval,
            0, "ANI calibration (msecs)");
 
 int ath_rxbuf = ATH_RXBUF;             /* # rx buffers to allocate */
-SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf,
+SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RWTUN, &ath_rxbuf,
            0, "rx buffers allocated");
 TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf);
+
 int ath_txbuf = ATH_TXBUF;             /* # tx buffers to allocate */
-SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf,
+SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RWTUN, &ath_txbuf,
            0, "tx buffers allocated");
 TUNABLE_INT("hw.ath.txbuf", &ath_txbuf);
+
 int ath_txbuf_mgmt = ATH_MGMT_TXBUF;   /* # mgmt tx buffers to allocate */
-SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RW, &ath_txbuf_mgmt,
+SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RWTUN, &ath_txbuf_mgmt,
            0, "tx (mgmt) buffers allocated");
 TUNABLE_INT("hw.ath.txbuf_mgmt", &ath_txbuf_mgmt);
 
@@ -441,6 +450,81 @@ _ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line)
 
 }
 
+/*
+ * Configure the initial HAL configuration values based on bus
+ * specific parameters.
+ *
+ * Some PCI IDs and other information may need tweaking.
+ *
+ * XXX TODO: ath9k and the Atheros HAL only program comm2g_switch_enable
+ * if BT antenna diversity isn't enabled.
+ *
+ * So, let's also figure out how to enable BT diversity for AR9485.
+ */
+static void
+ath_setup_hal_config(struct ath_softc *sc, HAL_OPS_CONFIG *ah_config)
+{
+       /* XXX TODO: only for PCI devices? */
+
+       if (sc->sc_pci_devinfo & (ATH_PCI_CUS198 | ATH_PCI_CUS230)) {
+               ah_config->ath_hal_ext_lna_ctl_gpio = 0x200; /* bit 9 */
+               ah_config->ath_hal_ext_atten_margin_cfg = AH_TRUE;
+               ah_config->ath_hal_min_gainidx = AH_TRUE;
+               ah_config->ath_hal_ant_ctrl_comm2g_switch_enable = 0x000bbb88;
+               /* XXX low_rssi_thresh */
+               /* XXX fast_div_bias */
+               device_printf(sc->sc_dev, "configuring for %s\n",
+                   (sc->sc_pci_devinfo & ATH_PCI_CUS198) ?
+                   "CUS198" : "CUS230");
+       }
+
+       if (sc->sc_pci_devinfo & ATH_PCI_CUS217)
+               device_printf(sc->sc_dev, "CUS217 card detected\n");
+
+       if (sc->sc_pci_devinfo & ATH_PCI_CUS252)
+               device_printf(sc->sc_dev, "CUS252 card detected\n");
+
+       if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT)
+               device_printf(sc->sc_dev, "WB335 1-ANT card detected\n");
+
+       if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT)
+               device_printf(sc->sc_dev, "WB335 2-ANT card detected\n");
+
+       if (sc->sc_pci_devinfo & ATH_PCI_KILLER)
+               device_printf(sc->sc_dev, "Killer Wireless card detected\n");
+
+#if 0
+        /*
+         * Some WB335 cards do not support antenna diversity. Since
+         * we use a hardcoded value for AR9565 instead of using the
+         * EEPROM/OTP data, remove the combining feature from
+         * the HW capabilities bitmap.
+         */
+        if (sc->sc_pci_devinfo & (ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_AR9565_2ANT)) {
+                if (!(sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV))
+                        pCap->hw_caps &= ~ATH9K_HW_CAP_ANT_DIV_COMB;
+        }
+
+        if (sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV) {
+                pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV;
+                device_printf(sc->sc_dev, "Set BT/WLAN RX diversity capability\n");
+        }
+#endif
+
+        if (sc->sc_pci_devinfo & ATH_PCI_D3_L1_WAR) {
+                ah_config->ath_hal_pcie_waen = 0x0040473b;
+                device_printf(sc->sc_dev, "Enable WAR for ASPM D3/L1\n");
+        }
+
+#if 0
+        if (sc->sc_pci_devinfo & ATH9K_PCI_NO_PLL_PWRSAVE) {
+                ah->config.no_pll_pwrsave = true;
+                device_printf(sc->sc_dev, "Disable PLL PowerSave\n");
+        }
+#endif
+
+}
+
 #define        HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20)
 #define        HAL_MODE_HT40 \
        (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \
@@ -456,9 +540,11 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
        u_int wmodes;
        uint8_t macaddr[IEEE80211_ADDR_LEN];
        int rx_chainmask, tx_chainmask;
+       HAL_OPS_CONFIG ah_config;
 
        DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
 
+       wlan_serialize_enter();
        CURVNET_SET(vnet0);
        ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
        if (ifp == NULL) {
@@ -474,10 +560,17 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
                device_get_unit(sc->sc_dev));
        CURVNET_RESTORE();
 
-       sc->sc_rxfifo_state = ATH_RXFIFO_RESET;
+       /*
+        * Configure the initial configuration data.
+        *
+        * This is stuff that may be needed early during attach
+        * rather than done via configuration calls later.
+        */
+       bzero(&ah_config, sizeof(ah_config));
+       ath_setup_hal_config(sc, &ah_config);
 
        ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh,
-           sc->sc_eepromdata, &status);
+           sc->sc_eepromdata, &ah_config, &status);
        if (ah == NULL) {
                if_printf(ifp, "unable to attach hardware; HAL status %u\n",
                        status);
@@ -569,10 +662,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
        /*
         * Allocate TX descriptors and populate the lists.
         */
-       wlan_assert_serialized();
-       wlan_serialize_exit();
        error = ath_desc_alloc(sc);
-       wlan_serialize_enter();
        if (error != 0) {
                if_printf(ifp, "failed to allocate TX descriptors: %d\n",
                    error);
@@ -595,8 +685,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
                goto bad;
        }
 
-       callout_init_mp(&sc->sc_cal_ch);
-       callout_init_mp(&sc->sc_wd_ch);
+       callout_init_lk(&sc->sc_cal_ch, &sc->sc_mtx);
+       callout_init_lk(&sc->sc_wd_ch, &sc->sc_mtx);
 
        ATH_TXBUF_LOCK_INIT(sc);
 
@@ -746,15 +836,18 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
 
        ifp->if_softc = sc;
        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
-#if 0
+#if defined(__DragonFly__)
+       ifp->if_start = ath_start;
+#else
        ifp->if_transmit = ath_transmit;
        ifp->if_qflush = ath_qflush;
 #endif
-       ifp->if_start = ath_start;
        ifp->if_ioctl = ath_ioctl;
        ifp->if_init = ath_init;
+#if defined(__DragonFly__)
        ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
-#if 0
+#else
+       IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
        ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
        IFQ_SET_READY(&ifp->if_snd);
 #endif
@@ -972,6 +1065,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
                            | IEEE80211_HTCAP_MAXAMSDU_3839
                                                        /* max A-MSDU length */
                            | IEEE80211_HTCAP_SMPS_OFF; /* SM power save off */
+                       ;
 
                /*
                 * Enable short-GI for HT20 only if the hardware
@@ -1175,7 +1269,11 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
        /*
         * Put it to sleep for now.
         */
+       ATH_LOCK(sc);
        ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
+       ATH_UNLOCK(sc);
+
+       wlan_serialize_exit();
 
        return 0;
 bad2:
@@ -1195,11 +1293,13 @@ bad:
                CURVNET_SET(ifp->if_vnet);
                if_free(ifp);
                CURVNET_RESTORE();
-       } else
+       } else 
 #endif
        if (ifp != NULL)
                if_free(ifp);
        sc->sc_invalid = 1;
+       wlan_serialize_exit();
+
        return error;
 }
 
@@ -1231,13 +1331,16 @@ ath_detach(struct ath_softc *sc)
         * wake it up first, but I'd rather do it here just to
         * ensure it's awake.
         */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        ath_power_setpower(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        /*
         * Stop things cleanly.
         */
        ath_stop(ifp);
+
        wlan_serialize_enter();
        ieee80211_ifdetach(ifp->if_l2com);
        wlan_serialize_exit();
@@ -1346,8 +1449,7 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
        int needbeacon, error;
        enum ieee80211_opmode ic_opmode;
 
-       avp = (struct ath_vap *) kmalloc(sizeof(struct ath_vap),
-           M_80211_VAP, M_WAITOK | M_ZERO);
+       avp = kmalloc(sizeof(struct ath_vap), M_80211_VAP, M_WAITOK | M_ZERO);
        needbeacon = 0;
        IEEE80211_ADDR_COPY(mac, mac0);
 
@@ -1473,18 +1575,14 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
        avp->av_bmiss = vap->iv_bmiss;
        vap->iv_bmiss = ath_bmiss_vap;
 
-#if 0
        avp->av_node_ps = vap->iv_node_ps;
        vap->iv_node_ps = ath_node_powersave;
-#endif
 
        avp->av_set_tim = vap->iv_set_tim;
        vap->iv_set_tim = ath_node_set_tim;
 
-#if 0
        avp->av_recv_pspoll = vap->iv_recv_pspoll;
        vap->iv_recv_pspoll = ath_node_recv_pspoll;
-#endif
 
        /* Set default parameters */
 
@@ -1606,7 +1704,9 @@ ath_vap_delete(struct ieee80211vap *vap)
        struct ath_hal *ah = sc->sc_ah;
        struct ath_vap *avp = ATH_VAP(vap);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
        if (ifp->if_flags & IFF_RUNNING) {
@@ -1616,9 +1716,9 @@ ath_vap_delete(struct ieee80211vap *vap)
                 * the vap state by any frames pending on the tx queues.
                 */
                ath_hal_intrset(ah, 0);         /* disable interrupts */
-               ath_draintxq(sc, ATH_RESET_DEFAULT);            /* stop hw xmit side */
                /* XXX Do all frames from all vaps/nodes need draining here? */
                ath_stoprecv(sc, 1);            /* stop recv side */
+               ath_draintxq(sc, ATH_RESET_DEFAULT);            /* stop hw xmit side */
        }
 
        /* .. leave the hardware awake for now. */
@@ -1732,12 +1832,25 @@ ath_suspend(struct ath_softc *sc)
         * NB: don't worry about putting the chip in low power
         * mode; pci will power off our socket on suspend and
         * CardBus detaches the device.
+        *
+        * XXX TODO: well, that's great, except for non-cardbus
+        * devices!
         */
 
        /*
-        * XXX ensure none of the taskqueues are running
+        * XXX This doesn't wait until all pending taskqueue
+        * items and parallel transmit/receive/other threads
+        * are running!
+        */
+       ath_hal_intrset(sc->sc_ah, 0);
+       taskqueue_block(sc->sc_tq);
+
+       ATH_LOCK(sc);
+       callout_stop_sync(&sc->sc_cal_ch);
+       ATH_UNLOCK(sc);
+
+       /*
         * XXX ensure sc_invalid is 1
-        * XXX ensure the calibration callout is disabled
         */
 
        /* Disable the PCIe PHY, complete with workarounds */
@@ -1758,10 +1871,12 @@ ath_reset_keycache(struct ath_softc *sc)
        struct ath_hal *ah = sc->sc_ah;
        int i;
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        for (i = 0; i < sc->sc_keymax; i++)
                ath_hal_keyreset(ah, i);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
        ieee80211_crypto_reload_keys(ic);
 }
 
@@ -1815,16 +1930,22 @@ ath_resume(struct ath_softc *sc)
            sc->sc_cur_rxchainmask);
 
        /* Ensure we set the current power state to on */
+       ATH_LOCK(sc);
        ath_power_setselfgen(sc, HAL_PM_AWAKE);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        ath_power_setpower(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
-       sc->sc_rxfifo_state = ATH_RXFIFO_RESET;
        ath_hal_reset(ah, sc->sc_opmode,
            sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan,
            AH_FALSE, &status);
        ath_reset_keycache(sc);
 
+       ATH_RX_LOCK(sc);
+       sc->sc_rx_stopped = 1;
+       sc->sc_rx_resetted = 1;
+       ATH_RX_UNLOCK(sc);
+
        /* Let DFS at it in case it's a DFS channel */
        ath_dfs_radar_enable(sc, ic->ic_curchan);
 
@@ -1852,7 +1973,9 @@ ath_resume(struct ath_softc *sc)
        if (sc->sc_resume_up)
                ieee80211_resume_all(ic);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        /* XXX beacons ? */
 }
@@ -1911,7 +2034,9 @@ ath_intr(void *arg)
                return;
        }
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        if ((ifp->if_flags & IFF_UP) == 0 ||
            (ifp->if_flags & IFF_RUNNING) == 0) {
@@ -1922,7 +2047,10 @@ ath_intr(void *arg)
                ath_hal_getisr(ah, &status);    /* clear ISR */
                ath_hal_intrset(ah, 0);         /* disable further intr's */
                ATH_PCU_UNLOCK(sc);
+
+               ATH_LOCK(sc);
                ath_power_restore_power_state(sc);
+               ATH_UNLOCK(sc);
                return;
        }
 
@@ -1962,7 +2090,11 @@ ath_intr(void *arg)
        /* Short-circuit un-handled interrupts */
        if (status == 0x0) {
                ATH_PCU_UNLOCK(sc);
+
+               ATH_LOCK(sc);
                ath_power_restore_power_state(sc);
+               ATH_UNLOCK(sc);
+
                return;
        }
 
@@ -2015,46 +2147,49 @@ ath_intr(void *arg)
 #endif
                        }
                }
-               if ((status & HAL_INT_RXEOL) && sc->sc_kickpcu == 0) {
+               if (status & HAL_INT_RXEOL) {
                        int imask;
                        ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXEOL");
-                       ATH_PCU_LOCK(sc);
-                       /*
-                        * NB: the hardware should re-read the link when
-                        *     RXE bit is written, but it doesn't work at
-                        *     least on older hardware revs.
-                        */
-                       sc->sc_stats.ast_rxeol++;
-                       /*
-                        * Disable RXEOL/RXORN - prevent an interrupt
-                        * storm until the PCU logic can be reset.
-                        * In case the interface is reset some other
-                        * way before "sc_kickpcu" is called, don't
-                        * modify sc_imask - that way if it is reset
-                        * by a call to ath_reset() somehow, the
-                        * interrupt mask will be correctly reprogrammed.
-                        */
-                       imask = sc->sc_imask;
-                       imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN);
-                       ath_hal_intrset(ah, imask);
-                       /*
-                        * Only blank sc_rxlink if we've not yet kicked
-                        * the PCU.
-                        *
-                        * This isn't entirely correct - the correct solution
-                        * would be to have a PCU lock and engage that for
-                        * the duration of the PCU fiddling; which would include
-                        * running the RX process. Otherwise we could end up
-                        * messing up the RX descriptor chain and making the
-                        * RX desc list much shorter.
-                        */
-                       sc->sc_rxlink = NULL;
-                       sc->sc_kickpcu = 1;
-                       ATH_PCU_UNLOCK(sc);
+                       if (! sc->sc_isedma) {
+                               ATH_PCU_LOCK(sc);
+                               /*
+                                * NB: the hardware should re-read the link when
+                                *     RXE bit is written, but it doesn't work at
+                                *     least on older hardware revs.
+                                */
+                               sc->sc_stats.ast_rxeol++;
+                               /*
+                                * Disable RXEOL/RXORN - prevent an interrupt
+                                * storm until the PCU logic can be reset.
+                                * In case the interface is reset some other
+                                * way before "sc_kickpcu" is called, don't
+                                * modify sc_imask - that way if it is reset
+                                * by a call to ath_reset() somehow, the
+                                * interrupt mask will be correctly reprogrammed.
+                                */
+                               imask = sc->sc_imask;
+                               imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN);
+                               ath_hal_intrset(ah, imask);
+                               /*
+                                * Only blank sc_rxlink if we've not yet kicked
+                                * the PCU.
+                                *
+                                * This isn't entirely correct - the correct solution
+                                * would be to have a PCU lock and engage that for
+                                * the duration of the PCU fiddling; which would include
+                                * running the RX process. Otherwise we could end up
+                                * messing up the RX descriptor chain and making the
+                                * RX desc list much shorter.
+                                */
+                               if (! sc->sc_kickpcu)
+                                       sc->sc_rxlink = NULL;
+                               sc->sc_kickpcu = 1;
+                               ATH_PCU_UNLOCK(sc);
+                       }
                        /*
-                        * Enqueue an RX proc, to handled whatever
+                        * Enqueue an RX proc to handle whatever
                         * is in the RX queue.
-                        * This will then kick the PCU.
+                        * This will then kick the PCU if required.
                         */
                        sc->sc_rx.recv_sched(sc, 1);
                }
@@ -2137,7 +2272,9 @@ ath_intr(void *arg)
        sc->sc_intr_cnt--;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 }
 
 static void
@@ -2186,9 +2323,13 @@ ath_bmiss_vap(struct ieee80211vap *vap)
         * that way we don't have to wake up again just to read it
         * again.
         */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) {
+               struct ifnet *ifp = vap->iv_ic->ic_ifp;
+               struct ath_softc *sc = ifp->if_softc;
                u_int64_t lastrx = sc->sc_lastrx;
                u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
                /* XXX should take a locked ref to iv_bss */
@@ -2203,7 +2344,11 @@ ath_bmiss_vap(struct ieee80211vap *vap)
 
                if (tsf - lastrx <= bmisstimeout) {
                        sc->sc_stats.ast_bmiss_phantom++;
+
+                       ATH_LOCK(sc);
                        ath_power_restore_power_state(sc);
+                       ATH_UNLOCK(sc);
+
                        return;
                }
        }
@@ -2212,7 +2357,9 @@ ath_bmiss_vap(struct ieee80211vap *vap)
         * There's no need to keep the hardware awake during the call
         * to av_bmiss().
         */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        /*
         * Attempt to force a beacon resync.
@@ -2245,15 +2392,18 @@ ath_bmiss_proc(void *arg, int pending)
 
        DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
 
+       ATH_LOCK(sc);
+       ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
+
+       ath_beacon_miss(sc);
+
        /*
         * Do a reset upon any becaon miss event.
         *
         * It may be a non-recognised RX clear hang which needs a reset
         * to clear.
         */
-       wlan_serialize_enter();
-       ath_power_set_power_state(sc, HAL_PM_AWAKE);
-       ath_beacon_miss(sc);
        if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
                ath_reset(ifp, ATH_RESET_NOLOSS);
                if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
@@ -2264,9 +2414,10 @@ ath_bmiss_proc(void *arg, int pending)
 
        /* Force a beacon resync, in case they've drifted */
        sc->sc_syncbeacon = 1;
-       ath_power_restore_power_state(sc);
 
-       wlan_serialize_exit();
+       ATH_LOCK(sc);
+       ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 }
 
 /*
@@ -2305,6 +2456,13 @@ ath_init(void *arg)
                __func__, ifp->if_flags);
 
        ATH_LOCK(sc);
+       /*
+        * Force the sleep state awake.
+        */
+       ath_power_setselfgen(sc, HAL_PM_AWAKE);
+       ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ath_power_setpower(sc, HAL_PM_AWAKE);
+
        /*
         * Stop anything previously setup.  This is safe
         * whether this is the first time through or not.
@@ -2322,13 +2480,19 @@ ath_init(void *arg)
        ath_update_chainmasks(sc, ic->ic_curchan);
        ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
            sc->sc_cur_rxchainmask);
-       sc->sc_rxfifo_state = ATH_RXFIFO_RESET;
+
        if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) {
                if_printf(ifp, "unable to reset hardware; hal status %u\n",
                        status);
                ATH_UNLOCK(sc);
                return;
        }
+
+       ATH_RX_LOCK(sc);
+       sc->sc_rx_stopped = 1;
+       sc->sc_rx_resetted = 1;
+       ATH_RX_UNLOCK(sc);
+
        ath_chan_change(sc, ic->ic_curchan);
 
        /* Let DFS at it in case it's a DFS channel */
@@ -2387,8 +2551,7 @@ ath_init(void *arg)
         * Enable interrupts.
         */
        sc->sc_imask = HAL_INT_RX | HAL_INT_TX
-                 | HAL_INT_RXEOL | HAL_INT_RXORN
-                 | HAL_INT_TXURN
+                 | HAL_INT_RXORN | HAL_INT_TXURN
                  | HAL_INT_FATAL | HAL_INT_GLOBAL;
 
        /*
@@ -2398,6 +2561,14 @@ ath_init(void *arg)
        if (sc->sc_isedma)
                sc->sc_imask |= (HAL_INT_RXHP | HAL_INT_RXLP);
 
+       /*
+        * If we're an EDMA NIC, we don't care about RXEOL.
+        * Writing a new descriptor in will simply restart
+        * RX DMA.
+        */
+       if (! sc->sc_isedma)
+               sc->sc_imask |= HAL_INT_RXEOL;
+
        /*
         * Enable MIB interrupts when there are hardware phy counters.
         * Note we only do this (at the moment) for station mode.
@@ -2472,24 +2643,25 @@ ath_stop_locked(struct ifnet *ifp)
                if (sc->sc_tx99 != NULL)
                        sc->sc_tx99->stop(sc->sc_tx99);
 #endif
-               callout_stop(&sc->sc_wd_ch);
+               callout_stop_sync(&sc->sc_wd_ch);
                sc->sc_wd_timer = 0;
                ifp->if_flags &= ~IFF_RUNNING;
                if (!sc->sc_invalid) {
                        if (sc->sc_softled) {
-                               callout_stop(&sc->sc_ledtimer);
+                               callout_stop_sync(&sc->sc_ledtimer);
                                ath_hal_gpioset(ah, sc->sc_ledpin,
                                        !sc->sc_ledon);
                                sc->sc_blinking = 0;
                        }
                        ath_hal_intrset(ah, 0);
                }
-               ath_draintxq(sc, ATH_RESET_DEFAULT);
+               /* XXX we should stop RX regardless of whether it's valid */
                if (!sc->sc_invalid) {
                        ath_stoprecv(sc, 1);
                        ath_hal_phydisable(ah);
                } else
                        sc->sc_rxlink = NULL;
+               ath_draintxq(sc, ATH_RESET_DEFAULT);
                ath_beacon_free(sc);    /* XXX not needed */
        }
 
@@ -2526,10 +2698,12 @@ ath_txrx_stop_locked(struct ath_softc *sc)
                        break;
                if (wlan_is_serialized()) {
                        wlan_serialize_exit();
-                       tsleep(sc, 0, "ath_txrx_stop", (hz + 99) / 100);
+                       lksleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop",
+                               msecs_to_ticks(10));
                        wlan_serialize_enter();
                } else {
-                       tsleep(sc, 0, "ath_txrx_stop", (hz + 99) / 100);
+                       lksleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop",
+                               msecs_to_ticks(10));
                }
                i--;
        }
@@ -2595,13 +2769,17 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
                        break;
                }
                ATH_PCU_UNLOCK(sc);
-               if (wlan_is_serialized()) {
-                       wlan_serialize_exit();
-                       tsleep(sc, 0, "ath_reset_grablock", (hz + 9) / 10);
-                       wlan_serialize_enter();
-               } else {
-                       tsleep(sc, 0, "ath_reset_grablock", (hz + 9) / 10);
-               }
+
+               /*
+                * 1 tick is likely not enough time for long calibrations
+                * to complete.  So we should wait quite a while.
+                */
+#if defined(__DragonFly__)
+               tsleep(&sc->sc_inreset_cnt, 0,
+                      "ath_reset_grablock", (hz + 99) / 100);
+#else
+               pause("ath_reset_grablock", msecs_to_ticks(100));
+#endif
                i--;
                ATH_PCU_LOCK(sc);
        } while (i > 0);
@@ -2634,7 +2812,7 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
 static void
 ath_stop(struct ifnet *ifp)
 {
-       struct ath_softc *sc __unused = ifp->if_softc;
+       struct ath_softc *sc = ifp->if_softc;
 
        ATH_LOCK(sc);
        ath_stop_locked(ifp);
@@ -2669,7 +2847,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
        /*
         * Wake the hardware up.
         */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_PCU_LOCK(sc);
 
@@ -2695,13 +2875,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
 
        ATH_PCU_UNLOCK(sc);
 
-       /*
-        * Should now wait for pending TX/RX to complete
-        * and block future ones from occuring. This needs to be
-        * done before the TX queue is drained.
-        */
-       ath_draintxq(sc, reset_type);   /* stop xmit side */
-
        /*
         * Regardless of whether we're doing a no-loss flush or
         * not, stop the PCU and handle what's in the RX queue.
@@ -2710,17 +2883,28 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
        ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS));
        ath_rx_flush(sc);
 
+       /*
+        * Should now wait for pending TX/RX to complete
+        * and block future ones from occuring. This needs to be
+        * done before the TX queue is drained.
+        */
+       ath_draintxq(sc, reset_type);   /* stop xmit side */
+
        ath_settkipmic(sc);             /* configure TKIP MIC handling */
        /* NB: indicate channel change so we do a full reset */
        ath_update_chainmasks(sc, ic->ic_curchan);
        ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
            sc->sc_cur_rxchainmask);
-       sc->sc_rxfifo_state = ATH_RXFIFO_RESET;
        if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
                if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
                        __func__, status);
        sc->sc_diversity = ath_hal_getdiversity(ah);
 
+       ATH_RX_LOCK(sc);
+       sc->sc_rx_stopped = 1;
+       sc->sc_rx_resetted = 1;
+       ATH_RX_UNLOCK(sc);
+
        /* Let DFS at it in case it's a DFS channel */
        ath_dfs_radar_enable(sc, ic->ic_curchan);
 
@@ -2786,11 +2970,11 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
         * run.
         */
 
-       /* XXX TODO: we need to hold the tx refcount here! */
-
        /* Restart TX/RX as needed */
        ath_txrx_start(sc);
 
+       /* XXX TODO: we need to hold the tx refcount here! */
+
        /* Restart TX completion and pending TX */
        if (reset_type == ATH_RESET_NOLOSS) {
                for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
@@ -2806,19 +2990,22 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
                }
        }
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        /*
         * This may have been set during an ath_start() call which
         * set this once it detected a concurrent TX was going on.
         * So, clear it.
         */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ATH_PCU_LOCK(sc);
        sc->sc_txstart_cnt--;
@@ -3013,23 +3200,22 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype)
                bf = _ath_getbuf_locked(sc, ATH_BUFTYPE_NORMAL);
        ATH_TXBUF_UNLOCK(sc);
        if (bf == NULL) {
-#if 0
                struct ifnet *ifp = sc->sc_ifp;
-#endif
 
                DPRINTF(sc, ATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
                sc->sc_stats.ast_tx_qstop++;
-#if 0
-               /* remove, DragonFly uses OACTIVE to control if_start calls */
                IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
                ifq_set_oactive(&ifp->if_snd);
-               IF_UNLOCK(&ifp->if_snd);
+#else
+               ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 #endif
+               IF_UNLOCK(&ifp->if_snd);
        }
        return bf;
 }
 
-#if 0
+#if !defined(__DragonFly__)
 
 static void
 ath_qflush(struct ifnet *ifp)
@@ -3067,21 +3253,27 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
                ATH_PCU_UNLOCK(sc);
                IF_LOCK(&ifp->if_snd);
                sc->sc_stats.ast_tx_qstop++;
-#if 0
-               /* remove, DragonFly uses OACTIVE to control if_start calls */
-               ifq_set_oactive(&ifp->if_snd);
+#if defined(__DragonFly__)
+               /* removed, DragonFly uses OACTIVE to control if_start calls */
+               /*ifq_set_oactive(&ifp->if_snd);*/
+#else
+               ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 #endif
                IF_UNLOCK(&ifp->if_snd);
                ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: OACTIVE, finish");
+#if defined(__DragonFly__)
                m_freem(m);
                m = NULL;
+#endif
                return (ENOBUFS);       /* XXX should be EINVAL or? */
        }
        sc->sc_txstart_cnt++;
        ATH_PCU_UNLOCK(sc);
 
        /* Wake the hardware up already */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: start");
        /*
@@ -3165,12 +3357,14 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
                 * above.
                 */
                sc->sc_stats.ast_tx_nobuf++;
-#if 0
-               /* remove, DragonFly uses OACTIVE to control if_start calls */
                IF_LOCK(&ifp->if_snd);
-               ifq_set_oactive(&ifp->if_snd);
-               IF_UNLOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
+               /* removed, DragonFly uses OACTIVE to control if_start calls */
+               /*ifq_set_oactive(&ifp->if_snd);*/
+#else
+               ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 #endif
+               IF_UNLOCK(&ifp->if_snd);
                m_freem(m);
                m = NULL;
                retval = ENOBUFS;
@@ -3194,7 +3388,11 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
                DPRINTF(sc, ATH_DEBUG_XMIT,
                    "%s: out of txfrag buffers\n", __func__);
                sc->sc_stats.ast_tx_nofrag++;
-               ifp->if_oerrors++;
+#if defined(__DragonFly__)
+               ++ifp->if_oerrors;
+#else
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+#endif
                ath_freetx(m);
                goto bad;
        }
@@ -3242,7 +3440,11 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
         *
         * XXX should use atomics?
         */
-       ifp->if_opackets++;
+#if defined(__DragonFly__)
+       ++ifp->if_opackets;
+#else
+       if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+#endif
 nextfrag:
        /*
         * Pass the frame to the h/w for transmission.
@@ -3262,7 +3464,11 @@ nextfrag:
        next = m->m_nextpkt;
        if (ath_tx_start(sc, ni, bf, m)) {
 bad:
-               ifp->if_oerrors++;
+#if defined(__DragonFly__)
+               ++ifp->if_oerrors;
+#else
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+#endif
 reclaim:
                bf->bf_m = NULL;
                bf->bf_node = NULL;
@@ -3320,7 +3526,9 @@ finish:
        ATH_PCU_UNLOCK(sc);
 
        /* Sleep the hardware if required */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: finished");
        
@@ -3368,18 +3576,25 @@ ath_update_promisc(struct ifnet *ifp)
        u_int32_t rfilt;
 
        /* configure rx filter */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        rfilt = ath_calcrxfilter(sc);
        ath_hal_setrxfilter(sc->sc_ah, rfilt);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt);
 }
 
+/*
+ * Driver-internal mcast update call.
+ *
+ * Assumes the hardware is already awake.
+ */
 static void
-ath_update_mcast(struct ifnet *ifp)
+ath_update_mcast_hw(struct ath_softc *sc)
 {
-       struct ath_softc *sc = ifp->if_softc;
+       struct ifnet *ifp = sc->sc_ifp;
        u_int32_t mfilt[2];
 
        /* calculate and install multicast filter */
@@ -3389,7 +3604,9 @@ ath_update_mcast(struct ifnet *ifp)
                 * Merge multicast addresses to form the hardware filter.
                 */
                mfilt[0] = mfilt[1] = 0;
-#if 0
+#if defined(__DragonFly__)
+               /* nothing */
+#else
                if_maddr_rlock(ifp);    /* XXX need some fiddling to remove? */
 #endif
                TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
@@ -3406,18 +3623,40 @@ ath_update_mcast(struct ifnet *ifp)
                        pos &= 0x3f;
                        mfilt[pos / 32] |= (1 << (pos % 32));
                }
-#if 0
+#if defined(__DragonFly__)
+               /* nothing */
+#else
                if_maddr_runlock(ifp);
 #endif
        } else
                mfilt[0] = mfilt[1] = ~0;
-       ath_power_set_power_state(sc, HAL_PM_AWAKE);
+
        ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
-       ath_power_restore_power_state(sc);
+
        DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n",
                __func__, mfilt[0], mfilt[1]);
 }
 
+/*
+ * Called from the net80211 layer - force the hardware
+ * awake before operating.
+ */
+static void
+ath_update_mcast(struct ifnet *ifp)
+{
+       struct ath_softc *sc = ifp->if_softc;
+
+       ATH_LOCK(sc);
+       ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
+
+       ath_update_mcast_hw(sc);
+
+       ATH_LOCK(sc);
+       ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
+}
+
 void
 ath_mode_init(struct ath_softc *sc)
 {
@@ -3432,7 +3671,7 @@ ath_mode_init(struct ath_softc *sc)
        /* configure operational mode */
        ath_hal_setopmode(ah);
 
-#if 0
+#if !defined(__DragonFly__)
        DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_MODE,
            "%s: ah=%p, ifp=%p, if_addr=%p\n",
            __func__,
@@ -3445,7 +3684,7 @@ ath_mode_init(struct ath_softc *sc)
        ath_hal_setmac(ah, IF_LLADDR(ifp));
 
        /* calculate and install multicast filter */
-       ath_update_mcast(ifp);
+       ath_update_mcast_hw(sc);
 }
 
 /*
@@ -3478,10 +3717,12 @@ ath_setslottime(struct ath_softc *sc)
            ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", usec);
 
        /* Wake up the hardware first before updating the slot time */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        ath_hal_setslottime(ah, usec);
        ath_power_restore_power_state(sc);
        sc->sc_updateslot = OK;
+       ATH_UNLOCK(sc);
 }
 
 /*
@@ -3637,6 +3878,10 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
                       1,                       /* nsegments */
                       dd->dd_desc_len,         /* maxsegsize */
                       0,                       /* flags */
+#if !defined(__DragonFly__)
+                      NULL,                    /* lockfunc */
+                      NULL,                    /* lockarg */
+#endif
                       &dd->dd_dmat);
        if (error != 0) {
                if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
@@ -3707,7 +3952,7 @@ ath_descdma_setup(struct ath_softc *sc,
 
        /* allocate rx buffers */
        bsize = sizeof(struct ath_buf) * nbuf;
-       bf = kmalloc(bsize, M_ATHDEV, M_INTWAIT|M_ZERO);
+       bf = kmalloc(bsize, M_ATHDEV, M_INTWAIT | M_ZERO);
        if (bf == NULL) {
                if_printf(ifp, "malloc of %s buffers failed, size %u\n",
                        dd->dd_name, bsize);
@@ -3942,7 +4187,7 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
        const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
        struct ath_node *an;
 
-       an = kmalloc(space, M_80211_NODE, M_INTWAIT|M_ZERO);
+       an = kmalloc(space, M_80211_NODE, M_INTWAIT | M_ZERO);
        if (an == NULL) {
                /* XXX stat+msg */
                return NULL;
@@ -3952,15 +4197,12 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
        /* Setup the mutex - there's no associd yet so set the name to NULL */
        ksnprintf(an->an_name, sizeof(an->an_name), "%s: node %p",
            device_get_nameunit(sc->sc_dev), an);
-#if 0
-       mtx_init(&an->an_mtx, an->an_name, NULL, MTX_DEF);
-#endif
+       lockinit(&an->an_mtx, an->an_name, 0, 0);
 
        /* XXX setup ath_tid */
        ath_tx_tid_init(sc, an);
 
-       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %s: an %p\n", __func__,
-           ath_hal_ether_sprintf(mac), an);
+       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, mac, ":", an);
        return &an->an_node;
 }
 
@@ -3970,8 +4212,8 @@ ath_node_cleanup(struct ieee80211_node *ni)
        struct ieee80211com *ic = ni->ni_ic;
        struct ath_softc *sc = ic->ic_ifp->if_softc;
 
-       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %s: an %p\n", __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr), ATH_NODE(ni));
+       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
+           ni->ni_macaddr, ":", ATH_NODE(ni));
 
        /* Cleanup ath_tid, free unused bufs, unlink bufs in TXQ */
        ath_tx_node_flush(sc, ATH_NODE(ni));
@@ -3985,11 +4227,9 @@ ath_node_free(struct ieee80211_node *ni)
        struct ieee80211com *ic = ni->ni_ic;
        struct ath_softc *sc = ic->ic_ifp->if_softc;
 
-       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %s: an %p\n", __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr), ATH_NODE(ni));
-#if 0
-       mtx_destroy(&ATH_NODE(ni)->an_mtx);
-#endif
+       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
+           ni->ni_macaddr, ":", ATH_NODE(ni));
+       lockuninit(&ATH_NODE(ni)->an_mtx);
        sc->sc_node_free(ni);
 }
 
@@ -4412,14 +4652,12 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq,
     struct ath_tx_status *ts, struct ath_buf *bf)
 {
        struct ieee80211_node *ni = bf->bf_node;
-       struct ath_node *an = NULL;
 
        ATH_TX_UNLOCK_ASSERT(sc);
        ATH_TXQ_UNLOCK_ASSERT(txq);
 
        /* If unicast frame, update general statistics */
        if (ni != NULL) {
-               an = ATH_NODE(ni);
                /* update statistics */
                ath_tx_update_stats(sc, ts, bf);
        }
@@ -4619,19 +4857,18 @@ static void
 ath_tx_proc_q0(void *arg, int npending)
 {
        struct ath_softc *sc = arg;
-#if 0
        struct ifnet *ifp = sc->sc_ifp;
-#endif
        uint32_t txqs;
 
-       wlan_serialize_enter();
        ATH_PCU_LOCK(sc);
        sc->sc_txproc_cnt++;
        txqs = sc->sc_txq_active;
        sc->sc_txq_active &= ~txqs;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
            "ath_tx_proc_q0: txqs=0x%08x", txqs);
@@ -4641,12 +4878,13 @@ ath_tx_proc_q0(void *arg, int npending)
                sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
        if (TXQACTIVE(txqs, sc->sc_cabq->axq_qnum))
                ath_tx_processq(sc, sc->sc_cabq, 1);
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        sc->sc_wd_timer = 0;
 
        if (sc->sc_softled)
@@ -4656,10 +4894,11 @@ ath_tx_proc_q0(void *arg, int npending)
        sc->sc_txproc_cnt--;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ath_tx_kick(sc);
-       wlan_serialize_exit();
 }
 
 /*
@@ -4670,20 +4909,19 @@ static void
 ath_tx_proc_q0123(void *arg, int npending)
 {
        struct ath_softc *sc = arg;
-#if 0
        struct ifnet *ifp = sc->sc_ifp;
-#endif
        int nacked;
        uint32_t txqs;
 
-       wlan_serialize_enter();
        ATH_PCU_LOCK(sc);
        sc->sc_txproc_cnt++;
        txqs = sc->sc_txq_active;
        sc->sc_txq_active &= ~txqs;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
            "ath_tx_proc_q0123: txqs=0x%08x", txqs);
@@ -4705,12 +4943,13 @@ ath_tx_proc_q0123(void *arg, int npending)
        if (nacked)
                sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        sc->sc_wd_timer = 0;
 
        if (sc->sc_softled)
@@ -4720,10 +4959,11 @@ ath_tx_proc_q0123(void *arg, int npending)
        sc->sc_txproc_cnt--;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ath_tx_kick(sc);
-       wlan_serialize_exit();
 }
 
 /*
@@ -4733,20 +4973,19 @@ static void
 ath_tx_proc(void *arg, int npending)
 {
        struct ath_softc *sc = arg;
-#if 0
        struct ifnet *ifp = sc->sc_ifp;
-#endif
        int i, nacked;
        uint32_t txqs;
 
-       wlan_serialize_enter();
        ATH_PCU_LOCK(sc);
        sc->sc_txproc_cnt++;
        txqs = sc->sc_txq_active;
        sc->sc_txq_active &= ~txqs;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc: txqs=0x%08x", txqs);
 
@@ -4760,13 +4999,14 @@ ath_tx_proc(void *arg, int npending)
        if (nacked)
                sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        /* XXX check this inside of IF_LOCK? */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        sc->sc_wd_timer = 0;
 
        if (sc->sc_softled)
@@ -4776,10 +5016,11 @@ ath_tx_proc(void *arg, int npending)
        sc->sc_txproc_cnt--;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ath_tx_kick(sc);
-       wlan_serialize_exit();
 }
 #undef TXQACTIVE
 
@@ -4792,8 +5033,6 @@ ath_txq_sched_tasklet(void *arg, int npending)
        struct ath_softc *sc = arg;
        int i;
 
-       wlan_serialize_enter();
-
        /* XXX is skipping ok? */
        ATH_PCU_LOCK(sc);
 #if 0
@@ -4801,14 +5040,15 @@ ath_txq_sched_tasklet(void *arg, int npending)
                device_printf(sc->sc_dev,
                    "%s: sc_inreset_cnt > 0; skipping\n", __func__);
                ATH_PCU_UNLOCK(sc);
-               wlan_serialize_exit();
                return;
        }
 #endif
        sc->sc_txproc_cnt++;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_TX_LOCK(sc);
        for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
@@ -4818,12 +5058,13 @@ ath_txq_sched_tasklet(void *arg, int npending)
        }
        ATH_TX_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ATH_PCU_LOCK(sc);
        sc->sc_txproc_cnt--;
        ATH_PCU_UNLOCK(sc);
-       wlan_serialize_exit();
 }
 
 void
@@ -5221,9 +5462,7 @@ void
 ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
 {
        struct ath_hal *ah = sc->sc_ah;
-#ifdef ATH_DEBUG
        struct ifnet *ifp = sc->sc_ifp;
-#endif
        int i;
        struct ath_buf *bf_last;
 
@@ -5283,12 +5522,13 @@ ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
                }
        }
 #endif /* ATH_DEBUG */
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        sc->sc_wd_timer = 0;
 }
 
@@ -5333,14 +5573,15 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
 
        ATH_PCU_LOCK(sc);
 
+       /* Disable interrupts */
+       ath_hal_intrset(ah, 0);
+
        /* Stop new RX/TX/interrupt completion */
        if (ath_reset_grablock(sc, 1) == 0) {
                device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n",
                    __func__);
        }
 
-       ath_hal_intrset(ah, 0);
-
        /* Stop pending RX/TX completion */
        ath_txrx_stop_locked(sc);
 
@@ -5374,7 +5615,6 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
                ath_update_chainmasks(sc, chan);
                ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
                    sc->sc_cur_rxchainmask);
-               sc->sc_rxfifo_state = ATH_RXFIFO_RESET;
                if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
                        if_printf(ifp, "%s: unable to reset "
                            "channel %u (%u MHz, flags 0x%x), hal status %u\n",
@@ -5385,6 +5625,11 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
                }
                sc->sc_diversity = ath_hal_getdiversity(ah);
 
+               ATH_RX_LOCK(sc);
+               sc->sc_rx_stopped = 1;
+               sc->sc_rx_resetted = 1;
+               ATH_RX_UNLOCK(sc);
+
                /* Let DFS at it in case it's a DFS channel */
                ath_dfs_radar_enable(sc, chan);
 
@@ -5450,12 +5695,13 @@ finish:
        ath_hal_intrset(ah, sc->sc_imask);
        ATH_PCU_UNLOCK(sc);
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        ath_txrx_start(sc);
        /* XXX ath_start? */
 
@@ -5477,16 +5723,17 @@ ath_calibrate(void *arg)
        HAL_BOOL aniCal, shortCal = AH_FALSE;
        int nextcal;
 
+       ATH_LOCK_ASSERT(sc);
+
        /*
         * Force the hardware awake for ANI work.
         */
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
 
-       wlan_serialize_enter();
-
        /* Skip trying to do this if we're in reset */
        if (sc->sc_inreset_cnt)
                goto restart;
+
        if (ic->ic_flags & IEEE80211_F_SCAN)    /* defer, off channel */
                goto restart;
        longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz);
@@ -5516,7 +5763,8 @@ ath_calibrate(void *arg)
                        sc->sc_doresetcal = AH_TRUE;
                        taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask);
                        callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc);
-                       goto done;
+                       ath_power_restore_power_state(sc);
+                       return;
                }
                /*
                 * If this long cal is after an idle period, then
@@ -5587,12 +5835,10 @@ restart:
                    __func__);
                /* NB: don't rearm timer */
        }
-done:
        /*
         * Restore power state now that we're done.
         */
        ath_power_restore_power_state(sc);
-       wlan_serialize_exit();
 }
 
 static void
@@ -5617,7 +5863,7 @@ ath_scan_start(struct ieee80211com *ic)
        ATH_PCU_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
-                __func__, rfilt, ath_hal_ether_sprintf(ifp->if_broadcastaddr));
+                __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
 }
 
 static void
@@ -5641,7 +5887,7 @@ ath_scan_end(struct ieee80211com *ic)
        ATH_PCU_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
-                __func__, rfilt, ath_hal_ether_sprintf(sc->sc_curbssid),
+                __func__, rfilt, ether_sprintf(sc->sc_curbssid),
                 sc->sc_curaid);
 }
 
@@ -5678,6 +5924,10 @@ ath_set_channel(struct ieee80211com *ic)
        struct ifnet *ifp = ic->ic_ifp;
        struct ath_softc *sc = ifp->if_softc;
 
+       ATH_LOCK(sc);
+       ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
+
        (void) ath_chan_set(sc, ic->ic_curchan);
        /*
         * If we are returning to our bss channel then mark state
@@ -5686,7 +5936,6 @@ ath_set_channel(struct ieee80211com *ic)
         * sta/ibss mode this has no effect in other operating modes.
         */
        ATH_LOCK(sc);
-       ath_power_set_power_state(sc, HAL_PM_AWAKE);
        if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan)
                sc->sc_syncbeacon = 1;
        ath_power_restore_power_state(sc);
@@ -5749,6 +5998,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
        IEEE80211_LOCK_ASSERT(ic);
 
        /* Before we touch the hardware - wake it up */
+       ATH_LOCK(sc);
        /*
         * If the NIC is in anything other than SLEEP state,
         * we need to ensure that self-generated frames are
@@ -5765,16 +6015,16 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
         */
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
 
+       /*
+        * And stop the calibration callout whilst we have
+        * ATH_LOCK held.
+        */
+       callout_stop_sync(&sc->sc_cal_ch);
+       ATH_UNLOCK(sc);
+
        if (ostate == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
                csa_run_transition = 1;
 
-       if (wlan_is_serialized()) {
-               wlan_serialize_exit();
-               callout_stop_sync(&sc->sc_cal_ch);
-               wlan_serialize_enter();
-       } else {
-               callout_stop_sync(&sc->sc_cal_ch);
-       }
        ath_hal_setledstate(ah, leds[nstate]);  /* set LED */
 
        if (nstate == IEEE80211_S_SCAN) {
@@ -5786,8 +6036,10 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                 */
 
                /* Ensure we stay awake during scan */
+               ATH_LOCK(sc);
                ath_power_setselfgen(sc, HAL_PM_AWAKE);
                ath_power_setpower(sc, HAL_PM_AWAKE);
+               ATH_UNLOCK(sc);
 
                ath_hal_intrset(ah,
                    sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
@@ -5812,8 +6064,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
        }
        DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
-          __func__, rfilt,
-          ath_hal_ether_sprintf(sc->sc_curbssid), sc->sc_curaid);
+          __func__, rfilt, ether_sprintf(sc->sc_curbssid), sc->sc_curaid);
        ath_hal_setrxfilter(ah, rfilt);
 
        /* XXX is this to restore keycache on resume? */
@@ -5845,8 +6096,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                DPRINTF(sc, ATH_DEBUG_STATE,
                    "%s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
                    "capinfo 0x%04x chan %d\n", __func__,
-                   vap->iv_flags, ni->ni_intval,
-                   ath_hal_ether_sprintf(ni->ni_bssid),
+                   vap->iv_flags, ni->ni_intval, ether_sprintf(ni->ni_bssid),
                    ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
 
                switch (vap->iv_opmode) {
@@ -5913,25 +6163,24 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                        if (ostate != IEEE80211_S_RUN &&
                            ostate != IEEE80211_S_SLEEP) {
                                DPRINTF(sc, ATH_DEBUG_BEACON,
-                                       "%s: STA; syncbeacon=1\n", __func__);
+                                   "%s: STA; syncbeacon=1\n", __func__);
                                sc->sc_syncbeacon = 1;
 
                                if (csa_run_transition)
                                        ath_beacon_config(sc, vap);
 
-                               /*
-                                * PR: kern/175227
-                                *
-                                * Reconfigure beacons during reset; as
-                                * otherwise
-                                * we won't get the beacon timers reprogrammed
-                                * after a reset and thus we won't pick up a
-                                * beacon miss interrupt.
-                                *
-                                * Hopefully we'll see a beacon before the BMISS
-                                * timer fires (too often), leading to a STA
-                                * disassociation.
-                                */
+                       /*
+                        * PR: kern/175227
+                        *
+                        * Reconfigure beacons during reset; as otherwise
+                        * we won't get the beacon timers reprogrammed
+                        * after a reset and thus we won't pick up a
+                        * beacon miss interrupt.
+                        *
+                        * Hopefully we'll see a beacon before the BMISS
+                        * timer fires (too often), leading to a STA
+                        * disassociation.
+                        */
                                sc->sc_beacons = 1;
                        }
                        break;
@@ -5961,8 +6210,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
 
                /*
-                * Force awake for RUN mode
+                * Force awake for RUN mode.
                 */
+               ATH_LOCK(sc);
                ath_power_setselfgen(sc, HAL_PM_AWAKE);
                ath_power_setpower(sc, HAL_PM_AWAKE);
 
@@ -5977,6 +6227,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                        DPRINTF(sc, ATH_DEBUG_CALIBRATE,
                            "%s: calibration disabled\n", __func__);
                }
+               ATH_UNLOCK(sc);
 
                taskqueue_unblock(sc->sc_tq);
        } else if (nstate == IEEE80211_S_INIT) {
@@ -6002,9 +6253,8 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                /* For now, only do this if we're a single STA vap */
                if (sc->sc_nvaps == 1 &&
                    vap->iv_opmode == IEEE80211_M_STA) {
-                       DPRINTF(sc, ATH_DEBUG_BEACON,
-                               "%s: syncbeacon=%d\n",
-                               __func__, sc->sc_syncbeacon);
+                       DPRINTF(sc, ATH_DEBUG_BEACON, "%s: syncbeacon=%d\n", __func__, sc->sc_syncbeacon);
+                       ATH_LOCK(sc);
                        /*
                         * Always at least set the self-generated
                         * frame config to set PWRMGT=1.
@@ -6022,6 +6272,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
                        if (sc->sc_syncbeacon == 0) {
                                ath_power_setpower(sc, HAL_PM_NETWORK_SLEEP);
                        }
+                       ATH_UNLOCK(sc);
                }
        }
 bad:
@@ -6031,8 +6282,9 @@ bad:
         * Restore the power state - either to what it was, or
         * to network_sleep if it's alright.
         */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
-
+       ATH_UNLOCK(sc);
        return error;
 }
 
@@ -6087,12 +6339,12 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
        an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
        an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate);
 
-       DPRINTF(sc, ATH_DEBUG_NODE,
-               "%s: %s: reassoc; isnew=%d, is_powersave=%d\n",
-               __func__,
-               ath_hal_ether_sprintf(ni->ni_macaddr),
-               isnew,
-               an->an_is_powersave);
+       DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: reassoc; isnew=%d, is_powersave=%d\n",
+           __func__,
+           ni->ni_macaddr,
+           ":",
+           isnew,
+           an->an_is_powersave);
 
        ATH_NODE_LOCK(an);
        ath_rate_newassoc(sc, an, isnew);
@@ -6114,9 +6366,10 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
         */
        if (! isnew) {
                DPRINTF(sc, ATH_DEBUG_NODE,
-                   "%s: %s: reassoc; is_powersave=%d\n",
+                   "%s: %6D: reassoc; is_powersave=%d\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    an->an_is_powersave);
 
                /* XXX for now, we can't hold the lock across assoc */
@@ -6335,7 +6588,8 @@ ath_watchdog(void *arg)
        struct ath_softc *sc = arg;
        int do_reset = 0;
 
-       wlan_serialize_enter();
+       ATH_LOCK_ASSERT(sc);
+
        if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) {
                struct ifnet *ifp = sc->sc_ifp;
                uint32_t hangs;
@@ -6349,8 +6603,13 @@ ath_watchdog(void *arg)
                } else
                        if_printf(ifp, "device timeout\n");
                do_reset = 1;
-               ifp->if_oerrors++;
+#if defined(__DragonFly__)
+               ++ifp->if_oerrors;
+#else
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+#endif
                sc->sc_stats.ast_watchdog++;
+
                ath_power_restore_power_state(sc);
        }
 
@@ -6364,39 +6623,46 @@ ath_watchdog(void *arg)
                taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask);
        }
 
+#if defined(__DragonFly__)
        callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
-       wlan_serialize_exit();
+#else
+       callout_schedule(&sc->sc_wd_ch, hz);
+#endif
 }
 
+#if defined(__DragonFly__)
+
 /*
  * (DragonFly network start)
  */
 static void
 ath_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
 {
-       struct ath_softc *sc = ifp->if_softc;
-       struct mbuf *m;
-       int wst;
-
-       ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
-       wst = wlan_serialize_push();
-
-       if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid) {
-               ifq_purge(&ifp->if_snd);
-               wlan_serialize_pop(wst);
-               return;
-       }
-       ifq_set_oactive(&ifp->if_snd);
-       for (;;) {
-               m = ifq_dequeue(&ifp->if_snd);
-               if (m == NULL)
-                       break;
-               ath_transmit(ifp, m);
-       }
-       ifq_clr_oactive(&ifp->if_snd);
-       wlan_serialize_pop(wst);
+       struct ath_softc *sc = ifp->if_softc;
+       struct mbuf *m;
+       int wst;
+
+       ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
+       wst = wlan_serialize_push();
+
+       if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid) {
+               ifq_purge(&ifp->if_snd);
+               wlan_serialize_pop(wst);
+               return;
+       }
+       ifq_set_oactive(&ifp->if_snd);
+       for (;;) {
+               m = ifq_dequeue(&ifp->if_snd);
+               if (m == NULL)
+                       break;
+               ath_transmit(ifp, m);
+       }
+       ifq_clr_oactive(&ifp->if_snd);
+       wlan_serialize_pop(wst);
 }
 
+#endif
+
 /*
  * Fetch the rate control statistics for the given node.
  */
@@ -6480,8 +6746,11 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
                }
        }
 
+
+       ATH_LOCK(sc);
        if (id != HAL_DIAG_REGS)
                ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) {
                if (outsize < ad->ad_out_size)
@@ -6492,8 +6761,12 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
        } else {
                error = EINVAL;
        }
+
+       ATH_LOCK(sc);
        if (id != HAL_DIAG_REGS)
                ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
+
 bad:
        if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
                kfree(indata, M_TEMP);
@@ -6503,9 +6776,18 @@ bad:
 }
 #endif /* ATH_DIAGAPI */
 
+#if defined(__DragonFly__)
+
 static int
 ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
-         struct ucred *cr __unused)
+         struct ucred *cred __unused)
+
+#else
+
+static int
+ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+
+#endif
 {
 #define        IS_RUNNING(ifp) \
        ((ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
@@ -6517,14 +6799,17 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
 
        switch (cmd) {
        case SIOCSIFFLAGS:
-               ATH_LOCK(sc);
                if (IS_RUNNING(ifp)) {
                        /*
                         * To avoid rescanning another access point,
                         * do not call ath_init() here.  Instead,
                         * only reflect promisc mode settings.
                         */
+                       ATH_LOCK(sc);
+                       ath_power_set_power_state(sc, HAL_PM_AWAKE);
                        ath_mode_init(sc);
+                       ath_power_restore_power_state(sc);
+                       ATH_UNLOCK(sc);
                } else if (ifp->if_flags & IFF_UP) {
                        /*
                         * Beware of being called during attach/detach
@@ -6538,11 +6823,12 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
                        if (!sc->sc_invalid)
                                ath_init(sc);   /* XXX lose error */
                } else {
+                       ATH_LOCK(sc);
                        ath_stop_locked(ifp);
                        if (!sc->sc_invalid)
                                ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
+                       ATH_UNLOCK(sc);
                }
-               ATH_UNLOCK(sc);
                break;
        case SIOCGIFMEDIA:
        case SIOCSIFMEDIA:
@@ -6550,8 +6836,15 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
                break;
        case SIOCGATHSTATS:
                /* NB: embed these numbers to get a consistent view */
+#if defined(__DragonFly__)
                sc->sc_stats.ast_tx_packets = ifp->if_opackets;
                sc->sc_stats.ast_rx_packets = ifp->if_ipackets;
+#else
+               sc->sc_stats.ast_tx_packets = ifp->if_get_counter(ifp,
+                   IFCOUNTER_OPACKETS);
+               sc->sc_stats.ast_rx_packets = ifp->if_get_counter(ifp,
+                   IFCOUNTER_IPACKETS);
+#endif
                sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
                sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
 #ifdef IEEE80211_SUPPORT_TDMA
@@ -6563,12 +6856,12 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data,
                    rt->info[sc->sc_txrix].dot11Rate &~ IEEE80211_RATE_BASIC;
                if (rt->info[sc->sc_txrix].phy & IEEE80211_T_HT)
                        sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS;
-               error = copyout(&sc->sc_stats, ifr->ifr_data,
-                               sizeof (sc->sc_stats));
+               error = copyout(&sc->sc_stats,
+                   ifr->ifr_data, sizeof (sc->sc_stats));
                break;
        case SIOCGATHAGSTATS:
-               error = copyout(&sc->sc_aggr_stats, ifr->ifr_data,
-                               sizeof (sc->sc_aggr_stats));
+               error = copyout(&sc->sc_aggr_stats,
+                   ifr->ifr_data, sizeof (sc->sc_aggr_stats));
                break;
        case SIOCZATHSTATS:
                error = priv_check(curthread, PRIV_DRIVER);
@@ -6650,7 +6943,6 @@ ath_dfs_tasklet(void *p, int npending)
         * signal this to the net80211 layer to begin DFS
         * processing.
         */
-       wlan_serialize_enter();
        if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) {
                /* DFS event found, initiate channel change */
                /*
@@ -6662,10 +6954,8 @@ ath_dfs_tasklet(void *p, int npending)
                ieee80211_dfs_notify_radar(ic, sc->sc_curchan);
                IEEE80211_UNLOCK(ic);
        }
-       wlan_serialize_exit();
 }
 
-#if 0
 /*
  * Enable/disable power save.  This must be called with
  * no TX driver locks currently held, so it should only
@@ -6683,9 +6973,10 @@ ath_node_powersave(struct ieee80211_node *ni, int enable)
 
        /* XXX and no TXQ locks should be held here */
 
-       DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE, "%s: %6s: enable=%d\n",
+       DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE, "%s: %6D: enable=%d\n",
            __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            !! enable);
 
        /* Suspend or resume software queue handling */
@@ -6695,19 +6986,15 @@ ath_node_powersave(struct ieee80211_node *ni, int enable)
                ath_tx_node_wakeup(sc, an);
 
        /* Update net80211 state */
-       if (avp->av_node_ps)
-               avp->av_node_ps(ni, enable);
+       avp->av_node_ps(ni, enable);
 #else
        struct ath_vap *avp = ATH_VAP(ni->ni_vap);
 
        /* Update net80211 state */
-       if (avp->av_node_ps)
-               avp->av_node_ps(ni, enable);
+       avp->av_node_ps(ni, enable);
 #endif/* ATH_SW_PSQ */
 }
 
-#endif
-
 /*
  * Notification from net80211 that the powersave queue state has
  * changed.
@@ -6784,16 +7071,18 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
         */
        if (enable && an->an_tim_set == 1) {
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: enable=%d, tim_set=1, ignoring\n",
+                   "%s: %6D: enable=%d, tim_set=1, ignoring\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    enable);
                ATH_TX_UNLOCK(sc);
        } else if (enable) {
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: enable=%d, enabling TIM\n",
+                   "%s: %6D: enable=%d, enabling TIM\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    enable);
                an->an_tim_set = 1;
                ATH_TX_UNLOCK(sc);
@@ -6801,9 +7090,10 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
        } else if (an->an_swq_depth == 0) {
                /* disable */
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: enable=%d, an_swq_depth == 0, disabling\n",
+                   "%s: %6D: enable=%d, an_swq_depth == 0, disabling\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    enable);
                an->an_tim_set = 0;
                ATH_TX_UNLOCK(sc);
@@ -6813,9 +7103,10 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
                 * disable regardless; the node isn't in powersave now
                 */
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: enable=%d, an_pwrsave=0, disabling\n",
+                   "%s: %6D: enable=%d, an_pwrsave=0, disabling\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    enable);
                an->an_tim_set = 0;
                ATH_TX_UNLOCK(sc);
@@ -6828,9 +7119,10 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
                 */
                ATH_TX_UNLOCK(sc);
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: enable=%d, an_swq_depth > 0, ignoring\n",
+                   "%s: %6D: enable=%d, an_swq_depth > 0, ignoring\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    enable);
                changed = 0;
        }
@@ -6900,9 +7192,10 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
                    an->an_tim_set == 0 &&
                    an->an_swq_depth != 0) {
                        DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                           "%s: %s: swq_depth>0, tim_set=0, set!\n",
+                           "%s: %6D: swq_depth>0, tim_set=0, set!\n",
                            __func__,
-                           ath_hal_ether_sprintf(ni->ni_macaddr));
+                           ni->ni_macaddr,
+                           ":");
                        an->an_tim_set = 1;
                        (void) avp->av_set_tim(ni, 1);
                }
@@ -6910,7 +7203,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
                /*
                 * Don't bother grabbing the lock unless the queue is empty.
                 */
-               if (&an->an_swq_depth != 0)
+               if (an->an_swq_depth != 0)
                        return;
 
                if (an->an_is_powersave &&
@@ -6918,10 +7211,11 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
                    an->an_tim_set == 1 &&
                    an->an_swq_depth == 0) {
                        DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                           "%s: %s: swq_depth=0, tim_set=1, psq_set=0,"
+                           "%s: %6D: swq_depth=0, tim_set=1, psq_set=0,"
                            " clear!\n",
                            __func__,
-                           ath_hal_ether_sprintf(ni->ni_macaddr));
+                           ni->ni_macaddr,
+                           ":");
                        an->an_tim_set = 0;
                        (void) avp->av_set_tim(ni, 0);
                }
@@ -6931,7 +7225,24 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
 #endif /* ATH_SW_PSQ */
 }
 
-#if 0
+/*
+ * A device_printf() equivalent that does not require gcc hacks
+ */
+int
+athdev_printf(device_t dev, const char *ctl, ...)
+{
+       __va_list va;
+       int retval;
+
+       retval = device_print_prettyname(dev);
+       __va_start(va, ctl);
+       retval += kvprintf(ctl, va);
+       __va_end(va);
+
+       return retval;
+}
+
+
 /*
  * Received a ps-poll frame from net80211.
  *
@@ -7005,8 +7316,7 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
                    ni->ni_macaddr,
                    ":");
                ATH_TX_UNLOCK(sc);
-               if (avp->av_recv_pspoll)
-                       avp->av_recv_pspoll(ni, m);
+               avp->av_recv_pspoll(ni, m);
                return;
        }
 
@@ -7031,8 +7341,7 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
                    __func__,
                    ni->ni_macaddr,
                    ":");
-               if (avp->av_recv_pspoll)
-                       avp->av_recv_pspoll(ni, m);
+               avp->av_recv_pspoll(ni, m);
                return;
        }
 
@@ -7074,18 +7383,14 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
            __func__,
            ni->ni_macaddr,
            ":");
-       if (avp->av_recv_pspoll)
-               avp->av_recv_pspoll(ni, m);
+       avp->av_recv_pspoll(ni, m);
 #else
-       if (avp->av_recv_pspoll)
-               avp->av_recv_pspoll(ni, m);
+       avp->av_recv_pspoll(ni, m);
 #endif /* ATH_SW_PSQ */
 }
 
-#endif
-
 MODULE_VERSION(if_ath, 1);
 MODULE_DEPEND(if_ath, wlan, 1, 1, 1);          /* 802.11 media layer */
-#if    defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ)
+#if    defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ) || defined(ATH_DEBUG_ALQ)
 MODULE_DEPEND(if_ath, alq, 1, 1, 1);
 #endif
index 099ffb7..e48da3b 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * AHB bus front-end for the Atheros Wireless LAN controller driver.
 
 #include <dev/netif/ath/ath/if_athvar.h>
 
-#define MIPS_KSEG1_START                ((intptr_t)(int32_t)0xa0000000)
-#define MIPS_PHYS_TO_KSEG1(x)           ((uintptr_t)(x) | MIPS_KSEG1_START)
-
-#include <dev/netif/ath/ath_hal/ar71xx/ar71xxreg.h>
-#include <dev/netif/ath/ath_hal/ar91xx/ar91xxreg.h>
-#include <dev/netif/ath/ath_hal/ar71xx/ar71xx_cpudef.h>
+#if 0
+#include <mips/atheros/ar71xxreg.h>
+#include <mips/atheros/ar91xxreg.h>
+#include <mips/atheros/ar71xx_cpudef.h>
+#endif
 
 /*
  * bus glue.
@@ -164,8 +164,7 @@ ath_ahb_attach(device_t dev)
                goto bad0;
        }
 
-       /* XXX uintptr_t is a bandaid for ia64; to be fixed */
-       sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr);
+       sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr);
        sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
        /*
         * Mark device invalid so any interrupts (shared or otherwise)
@@ -199,19 +198,33 @@ ath_ahb_attach(device_t dev)
                device_printf(dev, "could not map interrupt\n");
                goto bad1;
        }
+
+#if defined(__DragonFly__)
        if (bus_setup_intr(dev, psc->sc_irq,
-                          INTR_MPSAFE, ath_intr,
-                          sc, &psc->sc_ih,
+                          INTR_MPSAFE,
+                          ath_intr, sc, &psc->sc_ih,
                           &wlan_global_serializer)) {
                device_printf(dev, "could not establish interrupt\n");
                goto bad2;
        }
+#else
+       if (bus_setup_intr(dev, psc->sc_irq,
+                          INTR_TYPE_NET | INTR_MPSAFE,
+                          NULL, ath_intr, sc, &psc->sc_ih)) {
+               device_printf(dev, "could not establish interrupt\n");
+               goto bad2;
+       }
+#endif
 
        /*
         * Setup DMA descriptor area.
         */
        if (bus_dma_tag_create(bus_get_dma_tag(dev),    /* parent */
+#if defined(__DragonFly__)
                               4, 0,                    /* alignment, bounds */
+#else
+                              1, 0,                    /* alignment, bounds */
+#endif
                               BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
                               BUS_SPACE_MAXADDR,       /* highaddr */
                               NULL, NULL,              /* filter, filterarg */
@@ -219,6 +232,10 @@ ath_ahb_attach(device_t dev)
                               ATH_MAX_SCATTER,         /* nsegments */
                               0x3ffff,                 /* maxsegsize XXX */
                               BUS_DMA_ALLOCNOW,        /* flags */
+#if !defined(__DragonFly__)
+                              NULL,                    /* lockfunc */
+                              NULL,                    /* lockarg */
+#endif
                               &sc->sc_dmat)) {
                device_printf(dev, "cannot allocate DMA tag\n");
                goto bad3;
@@ -244,9 +261,7 @@ ath_ahb_attach(device_t dev)
        ATH_TX_IC_LOCK_INIT(sc);
        ATH_TXSTATUS_LOCK_INIT(sc);
 
-       wlan_serialize_enter();
        error = ath_attach(device_id, sc);
-       wlan_serialize_exit();
        if (error == 0)                                 /* success */
                return 0;
 
@@ -350,10 +365,7 @@ static driver_t ath_ahb_driver = {
        sizeof (struct ath_ahb_softc)
 };
 static devclass_t ath_devclass;
-DRIVER_MODULE(ath_ahb, nexus, ath_ahb_driver, ath_devclass, NULL, NULL);
-MODULE_VERSION(ath_ahb, 1);
-MODULE_DEPEND(ath_ahb, wlan, 1, 1, 1);          /* 802.11 media layer */
-MODULE_DEPEND(ath_ahb, if_ath, 1, 1, 1);        /* if_ath driver */
-MODULE_DEPEND(ath_ahb, ath_hal, 1, 1, 1);       /* Atheros HAL */
-MODULE_DEPEND(ath_ahb, ath_rate, 1, 1, 1);      /* rate control alg */
-MODULE_DEPEND(ath_ahb, ath_dfs, 1, 1, 1);      /* wtf */
+DRIVER_MODULE(ath, nexus, ath_ahb_driver, ath_devclass, 0, 0);
+MODULE_VERSION(ath, 1);
+MODULE_DEPEND(ath, wlan, 1, 1, 1);             /* 802.11 media layer */
+MODULE_DEPEND(ath, if_ath, 1, 1, 1);           /* if_ath driver */
index 54bbc0c..cf0fc96 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -68,6 +69,7 @@
 #include <sys/module.h>
 #include <sys/ktr.h>
 
+
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/if_dl.h>
 #include <dev/netif/ath/ath/if_ath_beacon.h>
 
 #ifdef ATH_TX99_DIAG
-#include <dev/netif/ath/ath_tx99/ath_tx99.h>
+#include <dev/netif/ath/ath/ath_tx99/ath_tx99.h>
 #endif
 
 /*
@@ -201,9 +203,15 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
                sc->sc_stats.ast_be_nombuf++;
                return ENOMEM;
        }
+#if defined(__DragonFly__)
        error = bus_dmamap_load_mbuf_segment(sc->sc_dmat, bf->bf_dmamap, m,
                                     bf->bf_segs, 1, &bf->bf_nseg,
                                     BUS_DMA_NOWAIT);
+#else
+       error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
+                                    bf->bf_segs, &bf->bf_nseg,
+                                    BUS_DMA_NOWAIT);
+#endif
        if (error != 0) {
                device_printf(sc->sc_dev,
                    "%s: cannot map mbuf, bus_dmamap_load_mbuf_sg returns %d\n",
@@ -240,7 +248,7 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
                    "%s: %s beacons bslot %d intval %u tsfadjust %llu\n",
                    __func__, sc->sc_stagbeacons ? "stagger" : "burst",
                    avp->av_bslot, ni->ni_intval,
-                   (unsigned long long) le64toh(tsfadjust));
+                   (long long unsigned) le64toh(tsfadjust));
 
                wh = mtod(m, struct ieee80211_frame *);
                memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust));
@@ -712,10 +720,16 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
        if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, nmcastq)) {
                /* XXX too conservative? */
                bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+#if defined(__DragonFly__)
                error = bus_dmamap_load_mbuf_segment(sc->sc_dmat,
                                             bf->bf_dmamap, m,
                                             bf->bf_segs, 1, &bf->bf_nseg,
                                             BUS_DMA_NOWAIT);
+#else
+               error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
+                                            bf->bf_segs, &bf->bf_nseg,
+                                            BUS_DMA_NOWAIT);
+#endif
                if (error != 0) {
                        if_printf(vap->iv_ifp,
                            "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
@@ -746,6 +760,11 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
                         *
                         * More thought is required here.
                         */
+                       /*
+                        * XXX can we even stop TX DMA here? Check what the
+                        * reference driver does for cabq for beacons, given
+                        * that stopping TX requires RX is paused.
+                        */
                        ath_tx_draintxq(sc, cabq);
                }
        }
@@ -824,10 +843,16 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
        if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, 0)) {
                /* XXX too conservative? */
                bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+#if defined(__DragonFly__)
                error = bus_dmamap_load_mbuf_segment(sc->sc_dmat,
                                             bf->bf_dmamap, m,
                                             bf->bf_segs, 1, &bf->bf_nseg,
                                             BUS_DMA_NOWAIT);
+#else
+               error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
+                                            bf->bf_segs, &bf->bf_nseg,
+                                            BUS_DMA_NOWAIT);
+#endif
                if (error != 0) {
                        if_printf(vap->iv_ifp,
                            "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
@@ -930,7 +955,9 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
 
        ni = ieee80211_ref_node(vap->iv_bss);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        /* extract tstamp from last beacon and convert to TU */
        nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4),
@@ -1171,7 +1198,9 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
        }
        ieee80211_free_node(ni);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 #undef FUDGE
 #undef TSF_TO_TU
 }
index 9a17149..a940268 100644 (file)
@@ -51,3 +51,4 @@ extern        void ath_beacon_proc(void *arg, int pending);
 extern void ath_beacon_miss(struct ath_softc *sc);
 
 #endif
+
index 6c2d39b..b789993 100644 (file)
@@ -29,6 +29,7 @@
  * $FreeBSD$
  */
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * This implements some very basic bluetooth coexistence methods for
@@ -46,7 +47,9 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
+
 #include <sys/bus.h>
+
 #include <sys/socket.h>
  
 #include <net/if.h>
@@ -183,6 +186,72 @@ ath_btcoex_cfg_wb225(struct ath_softc *sc)
        return (0);
 }
 
+/*
+ * Initial AR9462 / (WB222) bluetooth coexistence settings,
+ * just for experimentation.
+ *
+ * Return 0 for OK; errno for error.
+ */
+static int
+ath_btcoex_cfg_wb222(struct ath_softc *sc)
+{
+       HAL_BT_COEX_INFO btinfo;
+       HAL_BT_COEX_CONFIG btconfig;
+       struct ath_hal *ah = sc->sc_ah;
+
+       if (! ath_hal_btcoex_supported(ah))
+               return (EINVAL);
+
+       bzero(&btinfo, sizeof(btinfo));
+       bzero(&btconfig, sizeof(btconfig));
+
+       device_printf(sc->sc_dev, "Enabling WB222 BTCOEX\n");
+
+       btinfo.bt_module = HAL_BT_MODULE_JANUS; /* XXX not used? */
+       btinfo.bt_coex_config = HAL_BT_COEX_CFG_MCI;
+
+       /*
+        * MCI uses a completely different interface to speak
+        * to the bluetooth module - it's a command based
+        * thing over a serial line, rather than
+        * state pins to/from the bluetooth module.
+        *
+        * So, the GPIO configuration, polarity, etc
+        * doesn't matter on MCI devices; it's just
+        * completely ignored by the HAL.
+        */
+       btinfo.bt_gpio_bt_active = 4;
+       btinfo.bt_gpio_bt_priority = 8;
+       btinfo.bt_gpio_wlan_active = 5;
+
+       btinfo.bt_active_polarity = 1;  /* XXX not used */
+       btinfo.bt_single_ant = 0;       /* 2 antenna on WB222 */
+       btinfo.bt_isolation = 0;        /* in dB, not used */
+
+       ath_hal_btcoex_set_info(ah, &btinfo);
+
+       btconfig.bt_time_extend = 0;
+       btconfig.bt_txstate_extend = 1; /* true */
+       btconfig.bt_txframe_extend = 1; /* true */
+       btconfig.bt_mode = HAL_BT_COEX_MODE_SLOTTED;
+       btconfig.bt_quiet_collision = 1;        /* true */
+       btconfig.bt_rxclear_polarity = 1;       /* true */
+       btconfig.bt_priority_time = 2;
+       btconfig.bt_first_slot_time = 5;
+       btconfig.bt_hold_rxclear = 1;   /* true */
+
+       ath_hal_btcoex_set_config(ah, &btconfig);
+
+       /*
+        * Enable antenna diversity.
+        */
+       ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1);
+
+       return (0);
+}
+
+
+
 
 #if 0
 /*
@@ -238,6 +307,8 @@ ath_btcoex_attach(struct ath_softc *sc)
 
        if (strncmp(profname, "wb195", 5) == 0) {
                ret = ath_btcoex_cfg_wb195(sc);
+       } else if (strncmp(profname, "wb222", 5) == 0) {
+               ret = ath_btcoex_cfg_wb222(sc);
        } else if (strncmp(profname, "wb225", 5) == 0) {
                ret = ath_btcoex_cfg_wb225(sc);
        } else {
index 76d7d22..4f04851 100644 (file)
@@ -28,6 +28,9 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define CTLFLAG_RWTUN  CTLFLAG_RW
 
 #include "opt_inet.h"
 #include "opt_ath.h"
@@ -80,7 +83,7 @@
 #include <dev/netif/ath/ath_hal/ah_diagcodes.h>
 
 #ifdef ATH_TX99_DIAG
-#include <dev/netif/ath/ath_tx99/ath_tx99.h>
+#include <dev/netif/ath/ath/ath_tx99/ath_tx99.h>
 #endif
 
 #ifdef ATH_DEBUG
@@ -89,9 +92,8 @@
 uint64_t ath_debug = 0;
 
 SYSCTL_DECL(_hw_ath);
-SYSCTL_QUAD(_hw_ath, OID_AUTO, debug, CTLFLAG_RW, &ath_debug,
+SYSCTL_QUAD(_hw_ath, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_debug,
            0, "control debugging printfs");
-TUNABLE_QUAD("hw.ath.debug", &ath_debug);
 
 void
 ath_printrxbuf(struct ath_softc *sc, const struct ath_buf *bf,
index 38d0d9c..706eaec 100644 (file)
@@ -84,9 +84,12 @@ enum {
        ATH_KTR_TX              = 0x00000080,
 };
 
-#ifdef __DragonFly__           /* XXX: port to our ktr */
-#define        ATH_KTR(_sc, _km, _kf, ...)     do { } while (0)
+#if defined(__DragonFly__)
+
+#define        ATH_KTR(_sc, _km, _kf, ...)
+
 #else
+
 #define        ATH_KTR(_sc, _km, _kf, ...)     do {    \
        if (sc->sc_ktrdebug & (_km))            \
                CTR##_kf(KTR_DEV, __VA_ARGS__); \
@@ -98,15 +101,32 @@ extern uint64_t ath_debug;
 #define        IFF_DUMPPKTS(sc, m) \
        ((sc->sc_debug & (m)) || \
            (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
+
+#if defined(__DragonFly__)
+
+/* doesn't support %6D (requires hacking gcc, not gonna do it) */
+#define        DPRINTF(sc, m, fmt, ...) do {                           \
+       if (sc->sc_debug & (m))                                 \
+               athdev_printf(sc->sc_dev, fmt, __VA_ARGS__);            \
+} while (0)
+
+#else
+
 #define        DPRINTF(sc, m, fmt, ...) do {                           \
        if (sc->sc_debug & (m))                                 \
                device_printf(sc->sc_dev, fmt, __VA_ARGS__);            \
 } while (0)
+
+#endif
+
+
 #define        KEYPRINTF(sc, ix, hk, mac) do {                         \
        if (sc->sc_debug & ATH_DEBUG_KEYCACHE)                  \
                ath_keyprint(sc, __func__, ix, hk, mac);        \
 } while (0)
 
+extern int athdev_printf(device_t dev, const char *, ...);
+
 extern void ath_printrxbuf(struct ath_softc *, const struct ath_buf *bf,
        u_int ix, int);
 extern void ath_printtxbuf(struct ath_softc *, const struct ath_buf *bf,
index f505258..7987ab8 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -77,8 +78,6 @@
 #include <dev/netif/ath/ath/if_ath_keycache.h>
 #include <dev/netif/ath/ath/if_ath_misc.h>
 
-extern  const char* ath_hal_ether_sprintf(const uint8_t *mac);
-
 #ifdef ATH_DEBUG
 static void
 ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix,
@@ -97,7 +96,7 @@ ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix,
        kprintf("%s: [%02u] %-7s ", tag, ix, ciphers[hk->kv_type]);
        for (i = 0, n = hk->kv_len; i < n; i++)
                kprintf("%02x", hk->kv_val[i]);
-       kprintf(" mac %s", ath_hal_ether_sprintf(mac));
+       kprintf(" mac %s", ether_sprintf(mac));
        if (hk->kv_type == HAL_CIPHER_TKIP) {
                kprintf(" %s ", sc->sc_splitmic ? "mic" : "rxmic");
                for (i = 0; i < sizeof(hk->kv_mic); i++)
@@ -252,6 +251,7 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap,
        } else
                mac = k->wk_macaddr;
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        if (hk.kv_type == HAL_CIPHER_TKIP &&
            (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
@@ -261,6 +261,7 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap,
                ret = ath_hal_keyset(ah, k->wk_keyix, &hk, mac);
        }
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        return (ret);
 #undef N
@@ -497,6 +498,7 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
 
        DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        ath_hal_keyreset(ah, keyix);
        /*
@@ -522,6 +524,7 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
                }
        }
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
        return 1;
 }
 
index 7d22e36..e616d4a 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
 void
 ath_led_config(struct ath_softc *sc)
 {
+
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        /* Software LED blinking - GPIO controlled LED */
        if (sc->sc_softled) {
@@ -143,7 +147,9 @@ ath_led_config(struct ath_softc *sc)
                            HAL_GPIO_OUTPUT_MUX_MAC_NETWORK_LED);
        }
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 }
 
 static void
@@ -151,9 +157,7 @@ ath_led_done(void *arg)
 {
        struct ath_softc *sc = arg;
 
-       wlan_serialize_enter();
        sc->sc_blinking = 0;
-       wlan_serialize_exit();
 }
 
 /*
@@ -165,10 +169,8 @@ ath_led_off(void *arg)
 {
        struct ath_softc *sc = arg;
 
-       wlan_serialize_enter();
        ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon);
        callout_reset(&sc->sc_ledtimer, sc->sc_ledoff, ath_led_done, sc);
-       wlan_serialize_exit();
 }
 
 /*
@@ -178,7 +180,6 @@ static void
 ath_led_blink(struct ath_softc *sc, int on, int off)
 {
        DPRINTF(sc, ATH_DEBUG_LED, "%s: on %u off %u\n", __func__, on, off);
-       wlan_assert_serialized();
        ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, sc->sc_ledon);
        sc->sc_blinking = 1;
        sc->sc_ledoff = off;
index 64c098c..8cbb4e9 100644 (file)
@@ -29,6 +29,7 @@
  * $FreeBSD$
  */
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * This module handles LNA diversity for those chips which implement LNA
@@ -46,7 +47,9 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
+
 #include <sys/bus.h>
+
 #include <sys/socket.h>
  
 #include <net/if.h>
@@ -204,6 +207,10 @@ bad:
        return (error);
 }
 
+/*
+ * XXX need to low_rssi_thresh config from ath9k, to support CUS198
+ * antenna diversity correctly.
+ */
 static HAL_BOOL
 ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, int mindelta,
     int main_rssi_avg, int alt_rssi_avg, int pkt_count)
index c2c18ee..5ec0b03 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * PCI/Cardbus front-end for the Atheros Wireless LAN controller driver.
 
 #include <dev/netif/ath/ath/if_athvar.h>
 
+#if defined(__DragonFly__)
+
 #include <bus/pci/pcivar.h>
 #include <bus/pci/pcireg.h>
 
+#else
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#endif
+
 /* For EEPROM firmware */
 #ifdef ATH_EEPROM_FIRMWARE
 #include <sys/linker.h>
@@ -77,6 +87,98 @@ struct ath_pci_softc {
        void                    *sc_ih;         /* interrupt handler */
 };
 
+/*
+ * XXX eventually this should be some system level definition
+ * so modules will hvae probe/attach information like USB.
+ * But for now..
+ */
+struct pci_device_id {
+       int vendor_id;
+       int device_id;
+
+       int sub_vendor_id;
+       int sub_device_id;
+
+       int driver_data;
+
+       int match_populated:1;
+       int match_vendor_id:1;
+       int match_device_id:1;
+       int match_sub_vendor_id:1;
+       int match_sub_device_id:1;
+};
+
+#define        PCI_VDEVICE(v, s) \
+       .vendor_id = (v), \
+       .device_id = (s), \
+       .match_populated = 1, \
+       .match_vendor_id = 1, \
+       .match_device_id = 1
+
+#define        PCI_DEVICE_SUB(v, d, dv, ds) \
+       .match_populated = 1, \
+       .vendor_id = (v), .match_vendor_id = 1, \
+       .device_id = (d), .match_device_id = 1, \
+       .sub_vendor_id = (dv), .match_sub_vendor_id = 1, \
+       .sub_device_id = (ds), .match_sub_device_id = 1
+
+#define        PCI_VENDOR_ID_ATHEROS           0x168c
+#define        PCI_VENDOR_ID_SAMSUNG           0x144d
+#define        PCI_VENDOR_ID_AZWAVE            0x1a3b
+#define        PCI_VENDOR_ID_FOXCONN           0x105b
+#define        PCI_VENDOR_ID_ATTANSIC          0x1969
+#define        PCI_VENDOR_ID_ASUSTEK           0x1043
+#define        PCI_VENDOR_ID_DELL              0x1028
+#define        PCI_VENDOR_ID_QMI               0x1a32
+#define        PCI_VENDOR_ID_LENOVO            0x17aa
+#define        PCI_VENDOR_ID_HP                0x103c
+
+#include "if_ath_pci_devlist.h"
+
+/*
+ * Attempt to find a match for the given device in
+ * the given device table.
+ *
+ * Returns the device structure or NULL if no matching
+ * PCI device is found.
+ */
+static const struct pci_device_id *
+ath_pci_probe_device(device_t dev, const struct pci_device_id *dev_table, int nentries)
+{
+       int i;
+       int vendor_id, device_id;
+       int sub_vendor_id, sub_device_id;
+
+       vendor_id = pci_get_vendor(dev);
+       device_id = pci_get_device(dev);
+       sub_vendor_id = pci_get_subvendor(dev);
+       sub_device_id = pci_get_subdevice(dev);
+
+       for (i = 0; i < nentries; i++) {
+               /* Don't match on non-populated (eg empty) entries */
+               if (! dev_table[i].match_populated)
+                       continue;
+
+               if (dev_table[i].match_vendor_id &&
+                   (dev_table[i].vendor_id != vendor_id))
+                       continue;
+               if (dev_table[i].match_device_id &&
+                   (dev_table[i].device_id != device_id))
+                       continue;
+               if (dev_table[i].match_sub_vendor_id &&
+                   (dev_table[i].sub_vendor_id != sub_vendor_id))
+                       continue;
+               if (dev_table[i].match_sub_device_id &&
+                   (dev_table[i].sub_device_id != sub_device_id))
+                       continue;
+
+               /* Match */
+               return (&dev_table[i]);
+       }
+
+       return (NULL);
+}
+
 #define        BS_BAR  0x10
 #define        PCIR_RETRY_TIMEOUT      0x41
 #define        PCIR_CFG_PMCSR          0x48
@@ -147,9 +249,15 @@ ath_pci_attach(device_t dev)
        const struct firmware *fw = NULL;
        const char *buf;
 #endif
+       const struct pci_device_id *pd;
 
        sc->sc_dev = dev;
 
+       /* Do this lookup anyway; figure out what to do with it later */
+       pd = ath_pci_probe_device(dev, ath_pci_id_table, nitems(ath_pci_id_table));
+       if (pd)
+               sc->sc_pci_devinfo = pd->driver_data;
+
        /*
         * Enable bus mastering.
         */
@@ -170,8 +278,7 @@ ath_pci_attach(device_t dev)
                device_printf(dev, "cannot map register space\n");
                goto bad;
        }
-       /* XXX uintptr_t is a bandaid for ia64; to be fixed */
-       sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr);
+       sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr);
        sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr);
        /*
         * Mark device invalid so any interrupts (shared or otherwise)
@@ -189,6 +296,7 @@ ath_pci_attach(device_t dev)
                device_printf(dev, "could not map interrupt\n");
                goto bad1;
        }
+#if defined(__DragonFly__)
        if (bus_setup_intr(dev, psc->sc_irq,
                           INTR_MPSAFE,
                           ath_intr, sc, &psc->sc_ih,
@@ -196,19 +304,35 @@ ath_pci_attach(device_t dev)
                device_printf(dev, "could not establish interrupt\n");
                goto bad2;
        }
+#else
+       if (bus_setup_intr(dev, psc->sc_irq,
+                          INTR_TYPE_NET | INTR_MPSAFE,
+                          NULL, ath_intr, sc, &psc->sc_ih)) {
+               device_printf(dev, "could not establish interrupt\n");
+               goto bad2;
+       }
+#endif
 
        /*
         * Setup DMA descriptor area.
         */
        if (bus_dma_tag_create(bus_get_dma_tag(dev),    /* parent */
-                              PAGE_SIZE, 0,                    /* alignment, bounds */
+#if defined(__DragonFly__)
+                              4, 0,                    /* alignment, bounds */
+#else
+                              1, 0,                    /* alignment, bounds */
+#endif
                               BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
                               BUS_SPACE_MAXADDR,       /* highaddr */
                               NULL, NULL,              /* filter, filterarg */
-                              4096*256,                /* maxsize XXX */
+                              0x3ffff,                 /* maxsize XXX */
                               ATH_MAX_SCATTER,         /* nsegments */
                               0x3ffff,                 /* maxsegsize XXX */
                               BUS_DMA_ALLOCNOW,        /* flags */
+#if !defined(__DragonFly__)
+                              NULL,                    /* lockfunc */
+                              NULL,                    /* lockarg */
+#endif
                               &sc->sc_dmat)) {
                device_printf(dev, "cannot allocate DMA tag\n");
                goto bad3;
@@ -252,9 +376,7 @@ ath_pci_attach(device_t dev)
        ATH_TX_IC_LOCK_INIT(sc);
        ATH_TXSTATUS_LOCK_INIT(sc);
 
-       wlan_serialize_enter();
        error = ath_attach(pci_get_device(dev), sc);
-       wlan_serialize_exit();
        if (error == 0)                                 /* success */
                return 0;
 
@@ -362,10 +484,7 @@ static driver_t ath_pci_driver = {
        sizeof (struct ath_pci_softc)
 };
 static devclass_t ath_devclass;
-DRIVER_MODULE(ath_pci, pci, ath_pci_driver, ath_devclass, NULL, NULL);
+DRIVER_MODULE(ath_pci, pci, ath_pci_driver, ath_devclass, 0, 0);
 MODULE_VERSION(ath_pci, 1);
 MODULE_DEPEND(ath_pci, wlan, 1, 1, 1);         /* 802.11 media layer */
 MODULE_DEPEND(ath_pci, if_ath, 1, 1, 1);       /* if_ath driver */
-MODULE_DEPEND(ath_pci, ath_hal, 1, 1, 1);      /* Atheros HAL */
-MODULE_DEPEND(ath_pci, ath_rate, 1, 1, 1);     /* rate control alg */
-MODULE_DEPEND(ath_pci, ath_dfs, 1, 1, 1);      /* wtf */
diff --git a/sys/dev/netif/ath/ath/if_ath_pci_devlist.h b/sys/dev/netif/ath/ath/if_ath_pci_devlist.h
new file mode 100644 (file)
index 0000000..ae65909
--- /dev/null
@@ -0,0 +1,669 @@
+/*-
+ * Copyright (c) 2014 Qualcomm Atheros.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+static const struct pci_device_id ath_pci_id_table[] = {
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0023) }, /* PCI   */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0024) }, /* PCI-E */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0027) }, /* PCI   */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0029) }, /* PCI   */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002A) }, /* PCI-E */
+
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1C71),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE01F),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x11AD, /* LITEON */
+                        0x6632),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x11AD, /* LITEON */
+                        0x6642),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        PCI_VENDOR_ID_QMI,
+                        0x0306),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x185F, /* WNC */
+                        0x309D),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x10CF, /* Fujitsu */
+                        0x147C),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x10CF, /* Fujitsu */
+                        0x147D),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002A,
+                        0x10CF, /* Fujitsu */
+                        0x1536),
+         .driver_data = ATH_PCI_D3_L1_WAR },
+
+       /* AR9285 card for Asus */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x002B,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2C37),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002B) }, /* PCI-E */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002D) }, /* PCI   */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x002E) }, /* PCI-E */
+
+       /* Killer Wireless (3x3) */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2000),
+         .driver_data = ATH_PCI_KILLER },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2001),
+         .driver_data = ATH_PCI_KILLER },
+
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
+
+       /* PCI-E CUS198 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2086),
+         .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1237),
+         .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2126),
+         .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x126A),
+         .driver_data = ATH_PCI_CUS198 | ATH_PCI_BT_ANT_DIV },
+
+       /* PCI-E CUS230 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2152),
+         .driver_data = ATH_PCI_CUS230 | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE075),
+         .driver_data = ATH_PCI_CUS230 | ATH_PCI_BT_ANT_DIV },
+
+       /* WB225 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3119),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3122),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x185F, /* WNC */
+                        0x3119),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x185F, /* WNC */
+                        0x3027),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x4105),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x4106),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x410D),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x410E),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x410F),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0xC706),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0xC680),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0xC708),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x3218),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x3219),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+
+       /* AR9485 cards with PLL power-save disabled by default. */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2C97),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2100),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x1C56, /* ASKEY */
+                        0x4001),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x11AD, /* LITEON */
+                        0x6627),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x11AD, /* LITEON */
+                        0x6628),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE04E),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE04F),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x144F, /* ASKEY */
+                        0x7197),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x1B9A, /* XAVI */
+                        0x2000),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x1B9A, /* XAVI */
+                        0x2001),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1186),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1F86),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1195),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x1F95),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x1B9A, /* XAVI */
+                        0x1C00),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        0x1B9A, /* XAVI */
+                        0x1C01),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0032,
+                        PCI_VENDOR_ID_ASUSTEK,
+                        0x850D),
+         .driver_data = ATH_PCI_NO_PLL_PWRSAVE },
+
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
+
+       /* PCI-E CUS217 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2116),
+         .driver_data = ATH_PCI_CUS217 },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x11AD, /* LITEON */
+                        0x6661),
+         .driver_data = ATH_PCI_CUS217 },
+
+       /* AR9462 with WoW support */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3117),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x3214),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_ATTANSIC,
+                        0x0091),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2110),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_ASUSTEK,
+                        0x850E),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x11AD, /* LITEON */
+                        0x6631),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x11AD, /* LITEON */
+                        0x6641),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        PCI_VENDOR_ID_HP,
+                        0x1864),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x14CD, /* USI */
+                        0x0063),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x14CD, /* USI */
+                        0x0064),
+         .driver_data = ATH_PCI_WOW },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0034,
+                        0x10CF, /* Fujitsu */
+                        0x1783),
+         .driver_data = ATH_PCI_WOW },
+
+       /* Killer Wireless (2x2) */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2003),
+         .driver_data = ATH_PCI_KILLER },
+
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0034) }, /* PCI-E  AR9462 */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0037) }, /* PCI-E  AR1111/AR9485 */
+
+       /* CUS252 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3028),
+         .driver_data = ATH_PCI_CUS252 |
+                        ATH_PCI_AR9565_2ANT |
+                        ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2176),
+         .driver_data = ATH_PCI_CUS252 |
+                        ATH_PCI_AR9565_2ANT |
+                        ATH_PCI_BT_ANT_DIV },
+
+       /* WB335 1-ANT */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE068),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x185F, /* WNC */
+                        0xA119),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0632),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x06B2),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0842),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x6671),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x2811),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x2812),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x28A1),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x218A),
+         .driver_data = ATH_PCI_AR9565_1ANT },
+
+       /* WB335 1-ANT / Antenna Diversity */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3025),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3026),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x302B),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE069),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x185F, /* WNC */
+                        0x3028),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0622),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0672),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0662),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x06A2),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0682),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x213A),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_HP,
+                        0x18E3),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_HP,
+                        0x217F),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_HP,
+                        0x2005),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_DELL,
+                        0x020C),
+         .driver_data = ATH_PCI_AR9565_1ANT | ATH_PCI_BT_ANT_DIV },
+
+       /* WB335 2-ANT / Antenna-Diversity */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x411A),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x411B),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x411C),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x411D),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_SAMSUNG,
+                        0x411E),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x3027),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ATHEROS,
+                        0x302C),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0642),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0652),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0612),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0832),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0692),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2130),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x213B),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_AZWAVE,
+                        0x2182),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x144F, /* ASKEY */
+                        0x7202),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x2810),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x1B9A, /* XAVI */
+                        0x28A2),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x185F, /* WNC */
+                        0x3027),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x185F, /* WNC */
+                        0xA120),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE07F),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE081),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x3026),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_LENOVO,
+                        0x4026),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_ASUSTEK,
+                        0x85F2),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_DELL,
+                        0x020E),
+         .driver_data = ATH_PCI_AR9565_2ANT | ATH_PCI_BT_ANT_DIV },
+
+       /* PCI-E AR9565 (WB335) */
+       { PCI_VDEVICE(PCI_VENDOR_ID_ATHEROS, 0x0036),
+         .driver_data = ATH_PCI_BT_ANT_DIV },
+
+       { 0 }
+};
+
index 42bfe07..2fb8731 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
 #include <dev/netif/ath/ath/if_athdfs.h>
 
 #ifdef ATH_TX99_DIAG
-#include <dev/netif/ath/ath_tx99/ath_tx99.h>
+#include <dev/netif/ath/ath/ath_tx99/ath_tx99.h>
 #endif
 
 #ifdef ATH_DEBUG_ALQ
@@ -253,7 +254,7 @@ ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
                 * multiple of the cache line size.  Not doing this
                 * causes weird stuff to happen (for the 5210 at least).
                 */
-               m = m_getcl(MB_WAIT, MT_DATA, M_PKTHDR);
+               m = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
                if (m == NULL) {
                        DPRINTF(sc, ATH_DEBUG_ANY,
                                "%s: no mbuf/cluster\n", __func__);
@@ -262,10 +263,17 @@ ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
                }
                m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
 
+#if defined(__DragonFly__)
                error = bus_dmamap_load_mbuf_segment(sc->sc_dmat,
                                             bf->bf_dmamap, m,
                                             bf->bf_segs, 1, &bf->bf_nseg,
                                             BUS_DMA_NOWAIT);
+#else
+               error = bus_dmamap_load_mbuf_sg(sc->sc_dmat,
+                                            bf->bf_dmamap, m,
+                                            bf->bf_segs, &bf->bf_nseg,
+                                            BUS_DMA_NOWAIT);
+#endif
                if (error != 0) {
                        DPRINTF(sc, ATH_DEBUG_ANY,
                            "%s: bus_dmamap_load_mbuf_sg failed; error %d\n",
@@ -341,7 +349,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
 
 #define        TU_TO_TSF(_tu)  (((u_int64_t)(_tu)) << 10)
        tsf_intval = 1;
-       if (ni != NULL && ni->ni_intval > 0) {
+       if (ni->ni_intval > 0) {
                tsf_intval = TU_TO_TSF(ni->ni_intval);
        }
 #undef TU_TO_TSF
@@ -701,7 +709,11 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
                                        rs->rs_keyix-32 : rs->rs_keyix);
                        }
                }
-               ifp->if_ierrors++;
+#if defined(__DragonFly__)
+               ++ifp->if_ierrors;
+#else
+               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+#endif
 rx_error:
                /*
                 * Cleanup any pending partial frame.
@@ -827,7 +839,11 @@ rx_accept:
                        rs->rs_antenna |= 0x4;
        }
 
-       ifp->if_ipackets++;
+#if defined(__DragonFly__)
+       ++ifp->if_ipackets;
+#else
+       if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
+#endif
        sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
 
        /*
@@ -1013,7 +1029,9 @@ ath_rx_proc(struct ath_softc *sc, int resched)
        kickpcu = sc->sc_kickpcu;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__);
        ngood = 0;
@@ -1121,7 +1139,6 @@ rx_proc_next:
                sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = bf;
        } while (ret == 0);
 
-
        /* rx signal state monitoring */
        ath_hal_rxmonitor(ah, &sc->sc_halstats, sc->sc_curchan);
        if (ngood)
@@ -1186,19 +1203,30 @@ rx_proc_next:
        }
 
        /* XXX check this inside of IF_LOCK? */
+#if defined(__DragonFly__)
        if (resched && !ifq_is_oactive(&ifp->if_snd)) {
+#else
+       if (resched && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
+#endif
 #ifdef IEEE80211_SUPPORT_SUPERG
                ieee80211_ff_age_all(ic, 100);
 #endif
+#if defined(__DragonFly__)
                if (!ifq_is_empty(&ifp->if_snd))
                        ath_tx_kick(sc);
+#else
+               if (!IFQ_IS_EMPTY(&ifp->if_snd))
+                       ath_tx_kick(sc);
+#endif
        }
 #undef PA2DESC
 
        /*
         * Put the hardware to sleep again if we're done with it.
         */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        /*
         * If we hit the maximum number of frames in this round,
@@ -1226,7 +1254,6 @@ ath_legacy_rx_tasklet(void *arg, int npending)
 {
        struct ath_softc *sc = arg;
 
-       wlan_serialize_enter();
        ATH_KTR(sc, ATH_KTR_RXPROC, 1, "ath_rx_proc: pending=%d", npending);
        DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
        ATH_PCU_LOCK(sc);
@@ -1234,13 +1261,11 @@ ath_legacy_rx_tasklet(void *arg, int npending)
                device_printf(sc->sc_dev,
                    "%s: sc_inreset_cnt > 0; skipping\n", __func__);
                ATH_PCU_UNLOCK(sc);
-               wlan_serialize_exit();
                return;
        }
        ATH_PCU_UNLOCK(sc);
 
        ath_rx_proc(sc, 1);
-       wlan_serialize_exit();
 }
 
 static void
@@ -1254,52 +1279,52 @@ static void
 ath_legacy_flush_rxpending(struct ath_softc *sc)
 {
 
-       /* XXX ATH_RX_LOCK_ASSERT(sc); */
+       /* XXX ATH_RX_LOCK_ASSERT(sc); */
 
-       if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending != NULL) {
-              m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending);
-              sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL;
-       }
-       if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending != NULL) {
-              m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending);
-              sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL;
-       }
+       if (sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending != NULL) {
+               m_freem(sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending);
+               sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL;
+       }
+       if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending != NULL) {
+               m_freem(sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending);
+               sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL;
+       }
 }
 
 static int
 ath_legacy_flush_rxholdbf(struct ath_softc *sc)
 {
-       struct ath_buf *bf;
-
-       /* XXX ATH_RX_LOCK_ASSERT(sc); */
-       /*
-       * If there are RX holding buffers, free them here and return
-       * them to the list.
-       *
-       * XXX should just verify that bf->bf_m is NULL, as it must
-       * be at this point!
-       */
-       bf = sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf;
-       if (bf != NULL) {
-              if (bf->bf_m != NULL)
-                      m_freem(bf->bf_m);
-              bf->bf_m = NULL;
-              TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
-              (void) ath_rxbuf_init(sc, bf);
-       }
-       sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = NULL;
-
-       bf = sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf;
-       if (bf != NULL) {
-              if (bf->bf_m != NULL)
-                      m_freem(bf->bf_m);
-              bf->bf_m = NULL;
-              TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
-              (void) ath_rxbuf_init(sc, bf);
-       }
-       sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf = NULL;
-
-       return (0);
+       struct ath_buf *bf;
+
+       /* XXX ATH_RX_LOCK_ASSERT(sc); */
+       /*
+        * If there are RX holding buffers, free them here and return
+        * them to the list.
+        *
+        * XXX should just verify that bf->bf_m is NULL, as it must
+        * be at this point!
+        */
+       bf = sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf;
+       if (bf != NULL) {
+               if (bf->bf_m != NULL)
+                       m_freem(bf->bf_m);
+               bf->bf_m = NULL;
+               TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
+               (void) ath_rxbuf_init(sc, bf);
+       }
+       sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf = NULL;
+
+       bf = sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf;
+       if (bf != NULL) {
+               if (bf->bf_m != NULL)
+                       m_freem(bf->bf_m);
+               bf->bf_m = NULL;
+               TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
+               (void) ath_rxbuf_init(sc, bf);
+       }
+       sc->sc_rxedma[HAL_RX_QUEUE_LP].m_holdbf = NULL;
+
+       return (0);
 }
 
 /*
@@ -1313,6 +1338,8 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay)
                ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
        struct ath_hal *ah = sc->sc_ah;
 
+       ATH_RX_LOCK(sc);
+
        ath_hal_stoppcurecv(ah);        /* disable PCU */
        ath_hal_setrxfilter(ah, 0);     /* clear recv filter */
        ath_hal_stopdmarecv(ah);        /* disable DMA engine */
@@ -1351,9 +1378,17 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay)
        (void) ath_legacy_flush_rxholdbf(sc);
 
        sc->sc_rxlink = NULL;           /* just in case */
+
+       ATH_RX_UNLOCK(sc);
 #undef PA2DESC
 }
 
+/*
+ * XXX TODO: something was calling startrecv without calling
+ * stoprecv.  Let's figure out what/why.  It was showing up
+ * as a mbuf leak (rxpending) and ath_buf leak (holdbf.)
+ */
+
 /*
  * Enable the receive h/w following a reset.
  */
@@ -1363,6 +1398,11 @@ ath_legacy_startrecv(struct ath_softc *sc)
        struct ath_hal *ah = sc->sc_ah;
        struct ath_buf *bf;
 
+       ATH_RX_LOCK(sc);
+
+       /*
+        * XXX should verify these are already all NULL!
+        */
        sc->sc_rxlink = NULL;
        (void) ath_legacy_flush_rxpending(sc);
        (void) ath_legacy_flush_rxholdbf(sc);
@@ -1385,6 +1425,8 @@ ath_legacy_startrecv(struct ath_softc *sc)
        ath_hal_rxena(ah);              /* enable recv descriptors */
        ath_mode_init(sc);              /* set filters, etc. */
        ath_hal_startpcurecv(ah);       /* re-enable PCU/DMA engine */
+
+       ATH_RX_UNLOCK(sc);
        return 0;
 }
 
index c2e5bd1..e5152cb 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -67,7 +68,6 @@
 #include <sys/priv.h>
 #include <sys/module.h>
 #include <sys/ktr.h>
-#include <machine/pmap.h>
 
 #include <net/if.h>
 #include <net/if_var.h>
@@ -147,7 +147,7 @@ static      int ath_edma_rxfifo_alloc(struct ath_softc *sc, HAL_RX_QUEUE qtype,
            int nbufs);
 static int ath_edma_rxfifo_flush(struct ath_softc *sc, HAL_RX_QUEUE qtype);
 static void ath_edma_rxbuf_free(struct ath_softc *sc, struct ath_buf *bf);
-static int ath_edma_recv_proc_queue(struct ath_softc *sc,
+static void ath_edma_recv_proc_queue(struct ath_softc *sc,
            HAL_RX_QUEUE qtype, int dosched);
 static int ath_edma_recv_proc_deferred_queue(struct ath_softc *sc,
            HAL_RX_QUEUE qtype, int dosched);
@@ -158,10 +158,20 @@ ath_edma_stoprecv(struct ath_softc *sc, int dodelay)
        struct ath_hal *ah = sc->sc_ah;
 
        ATH_RX_LOCK(sc);
+
        ath_hal_stoppcurecv(ah);
        ath_hal_setrxfilter(ah, 0);
-       ath_hal_stopdmarecv(ah);
 
+       /*
+        * 
+        */
+       if (ath_hal_stopdmarecv(ah) == AH_TRUE)
+               sc->sc_rx_stopped = 1;
+
+       /*
+        * Give the various bus FIFOs (not EDMA descriptor FIFO)
+        * time to finish flushing out data.
+        */
        DELAY(3000);
 
        /* Flush RX pending for each queue */
@@ -214,26 +224,8 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype)
        }
 }
 
-static void
-ath_edma_handle_rxfifo_reset(struct ath_softc *sc)
-{
-       if (sc->sc_rxfifo_state == ATH_RXFIFO_RESET) {
-               DPRINTF(sc, ATH_DEBUG_EDMA_RX,
-                   "%s: Re-initing HP FIFO\n", __func__);
-               ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP);
-               DPRINTF(sc, ATH_DEBUG_EDMA_RX,
-                   "%s: Re-initing LP FIFO\n", __func__);
-               ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_LP);
-               sc->sc_rxfifo_state = ATH_RXFIFO_OK;
-       }
-}
-
 /*
  * Start receive.
- *
- * XXX TODO: this needs to reallocate the FIFO entries when a reset
- * occurs, in case the FIFO is filled up and no new descriptors get
- * thrown into the FIFO.
  */
 static int
 ath_edma_startrecv(struct ath_softc *sc)
@@ -242,15 +234,41 @@ ath_edma_startrecv(struct ath_softc *sc)
 
        ATH_RX_LOCK(sc);
 
+       /*
+        * Sanity check - are we being called whilst RX
+        * isn't stopped?  If so, we may end up pushing
+        * too many entries into the RX FIFO and
+        * badness occurs.
+        */
+
        /* Enable RX FIFO */
        ath_hal_rxena(ah);
-       ath_edma_handle_rxfifo_reset(sc);
+
+       /*
+        * In theory the hardware has been initialised, right?
+        */
+       if (sc->sc_rx_resetted == 1) {
+               DPRINTF(sc, ATH_DEBUG_EDMA_RX,
+                   "%s: Re-initing HP FIFO\n", __func__);
+               ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_HP);
+               DPRINTF(sc, ATH_DEBUG_EDMA_RX,
+                   "%s: Re-initing LP FIFO\n", __func__);
+               ath_edma_reinit_fifo(sc, HAL_RX_QUEUE_LP);
+               sc->sc_rx_resetted = 0;
+       } else {
+               device_printf(sc->sc_dev,
+                   "%s: called without resetting chip?\n",
+                   __func__);
+       }
 
        /* Add up to m_fifolen entries in each queue */
        /*
         * These must occur after the above write so the FIFO buffers
         * are pushed/tracked in the same order as the hardware will
         * process them.
+        *
+        * XXX TODO: is this really necessary? We should've stopped
+        * the hardware already and reinitialised it, so it's a no-op.
         */
        ath_edma_rxfifo_alloc(sc, HAL_RX_QUEUE_HP,
            sc->sc_rxedma[HAL_RX_QUEUE_HP].m_fifolen);
@@ -261,6 +279,11 @@ ath_edma_startrecv(struct ath_softc *sc)
        ath_mode_init(sc);
        ath_hal_startpcurecv(ah);
 
+       /*
+        * We're now doing RX DMA!
+        */
+       sc->sc_rx_stopped = 0;
+
        ATH_RX_UNLOCK(sc);
 
        return (0);
@@ -270,11 +293,16 @@ static void
 ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
     int dosched)
 {
+
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
-       if (dosched)
-               ath_edma_handle_rxfifo_reset(sc);
+       ATH_UNLOCK(sc);
+
        ath_edma_recv_proc_queue(sc, qtype, dosched);
+
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
 }
@@ -282,12 +310,17 @@ ath_edma_recv_sched_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
 static void
 ath_edma_recv_sched(struct ath_softc *sc, int dosched)
 {
+
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
-       if (dosched)
-               ath_edma_handle_rxfifo_reset(sc);
+       ATH_UNLOCK(sc);
+
        ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, dosched);
        ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, dosched);
+
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
 }
@@ -302,7 +335,9 @@ ath_edma_recv_flush(struct ath_softc *sc)
        sc->sc_rxproc_cnt++;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        /*
         * Flush any active frames from FIFO -> deferred list
@@ -321,7 +356,9 @@ ath_edma_recv_flush(struct ath_softc *sc)
        ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 0);
        ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 0);
 
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        ATH_PCU_LOCK(sc);
        sc->sc_rxproc_cnt--;
@@ -331,7 +368,7 @@ ath_edma_recv_flush(struct ath_softc *sc)
 /*
  * Process frames from the current queue into the deferred queue.
  */
-static int
+static void
 ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
     int dosched)
 {
@@ -344,7 +381,6 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
        uint64_t tsf;
        uint16_t nf;
        int npkts = 0;
-       int n = 0;
 
        tsf = ath_hal_gettsf64(ah);
        nf = ath_hal_getchannoise(ah, sc->sc_curchan);
@@ -352,6 +388,21 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
 
        ATH_RX_LOCK(sc);
 
+#if 1
+       if (sc->sc_rx_resetted == 1) {
+               /*
+                * XXX We shouldn't ever be scheduled if
+                * receive has been stopped - so complain
+                * loudly!
+                */
+               device_printf(sc->sc_dev,
+                   "%s: sc_rx_resetted=1! Bad!\n",
+                   __func__);
+               ATH_RX_UNLOCK(sc);
+               return;
+       }
+#endif
+
        do {
                bf = re->m_fifo[re->m_fifo_head];
                /* This shouldn't occur! */
@@ -368,9 +419,8 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
                 * Sync descriptor memory - this also syncs the buffer for us.
                 * EDMA descriptors are in cached memory.
                 */
-               cpu_lfence();
                bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
-                               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+                   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                rs = &bf->bf_status.ds_rxstat;
                bf->bf_rxstatus = ath_hal_rxprocdesc(ah, ds, bf->bf_daddr,
                    NULL, rs);
@@ -383,11 +433,8 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
                        if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_RXSTATUS,
                            sc->sc_rx_statuslen, (char *) ds);
 #endif /* ATH_DEBUG */
-               if (bf->bf_rxstatus == HAL_EINPROGRESS) {
-                       DPRINTF(sc, ATH_DEBUG_EDMA_RX,
-                           "%s: Q%d: still in-prog!\n", __func__, qtype);
+               if (bf->bf_rxstatus == HAL_EINPROGRESS)
                        break;
-               }
 
                /*
                 * Completed descriptor.
@@ -415,9 +462,8 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
        } while (re->m_fifo_depth > 0);
 
        /* Append some more fresh frames to the FIFO */
-       /* (kick already handled when dosched != 0) */
        if (dosched)
-               n = ath_edma_rxfifo_alloc(sc, qtype, re->m_fifolen);
+               ath_edma_rxfifo_alloc(sc, qtype, re->m_fifolen);
 
        ATH_RX_UNLOCK(sc);
 
@@ -428,7 +474,7 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
            "ath edma rx proc: npkts=%d\n",
            npkts);
 
-       return n;
+       return;
 }
 
 /*
@@ -445,12 +491,16 @@ ath_edma_flush_deferred_queue(struct ath_softc *sc)
        ATH_RX_LOCK_ASSERT(sc);
 
        /* Free in one set, inside the lock */
-       while ((bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP])) != NULL) {
+       while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP])) {
+               bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP]);
                TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf, bf_list);
+               /* Free the buffer/mbuf */
                ath_edma_rxbuf_free(sc, bf);
        }
-       while ((bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP])) != NULL) {
+       while (! TAILQ_EMPTY(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP])) {
+               bf = TAILQ_FIRST(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP]);
                TAILQ_REMOVE(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf, bf_list);
+               /* Free the buffer/mbuf */
                ath_edma_rxbuf_free(sc, bf);
        }
 }
@@ -461,8 +511,7 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
 {
        int ngood = 0;
        uint64_t tsf;
-       struct ath_buf *bf;
-       struct ath_buf *next;
+       struct ath_buf *bf, *next;
        struct ath_rx_status *rs;
        int16_t nf;
        ath_bufhead rxlist;
@@ -484,7 +533,11 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
        ATH_RX_UNLOCK(sc);
 
        /* Handle the completed descriptors */
-       TAILQ_FOREACH_MUTABLE(bf, &rxlist, bf_list, next) {
+       /*
+        * XXX is this SAFE call needed? The ath_buf entries
+        * aren't modified by ath_rx_pkt, right?
+        */
+       TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) {
                /*
                 * Skip the RX descriptor status - start at the data offset
                 */
@@ -509,10 +562,10 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
 
        /* Free in one set, inside the lock */
        ATH_RX_LOCK(sc);
-
-       while ((bf = TAILQ_FIRST(&rxlist)) != NULL) {
-               /* Free the buffer/mbuf */
+       while (! TAILQ_EMPTY(&rxlist)) {
+               bf = TAILQ_FIRST(&rxlist);
                TAILQ_REMOVE(&rxlist, bf, bf_list);
+               /* Free the buffer/mbuf */
                ath_edma_rxbuf_free(sc, bf);
        }
        ATH_RX_UNLOCK(sc);
@@ -528,62 +581,56 @@ ath_edma_recv_tasklet(void *arg, int npending)
 #ifdef IEEE80211_SUPPORT_SUPERG
        struct ieee80211com *ic = ifp->if_l2com;
 #endif
-       int n1;
-       int n2;
 
        DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n",
            __func__,
            npending);
 
-       wlan_serialize_enter();
        ATH_PCU_LOCK(sc);
        if (sc->sc_inreset_cnt > 0) {
                device_printf(sc->sc_dev, "%s: sc_inreset_cnt > 0; skipping\n",
                    __func__);
                ATH_PCU_UNLOCK(sc);
-               wlan_serialize_exit();
                return;
        }
        sc->sc_rxproc_cnt++;
        ATH_PCU_UNLOCK(sc);
 
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
-       ath_edma_handle_rxfifo_reset(sc);
-       n1 = ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1);
-       n2 = ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1);
+       ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_HP, 1);
+       ath_edma_recv_proc_queue(sc, HAL_RX_QUEUE_LP, 1);
 
        ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_HP, 1);
        ath_edma_recv_proc_deferred_queue(sc, HAL_RX_QUEUE_LP, 1);
 
-       /* Handle resched and kickpcu appropriately */
-       ATH_PCU_LOCK(sc);
-       if (sc->sc_kickpcu) {
-#ifdef ATH_DEBUG
-               if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
-                       kprintf("k(%d,%d)", n1, n2);
-#endif
-               sc->sc_kickpcu = 0;
-               /* reload imask XXX */
-               if (n1 || n2)
-                       ath_hal_intrset(sc->sc_ah, sc->sc_imask);
-       }
-       ATH_PCU_UNLOCK(sc);
-
        /*
         * XXX: If we read the tsf/channoise here and then pass it in,
         * we could restore the power state before processing
         * the deferred queue.
         */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        /* XXX inside IF_LOCK ? */
+#if defined(__DragonFly__)
        if (!ifq_is_oactive(&ifp->if_snd)) {
+#else
+       if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
+#endif
 #ifdef IEEE80211_SUPPORT_SUPERG
                ieee80211_ff_age_all(ic, 100);
 #endif
-               if (!ifq_is_empty(&ifp->if_snd))
+#if defined(__DragonFly__)
+               if (! ifq_is_empty(&ifp->if_snd))
                        ath_tx_kick(sc);
+#else
+               if (! IFQ_IS_EMPTY(&ifp->if_snd))
+                       ath_tx_kick(sc);
+#endif
        }
        if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
                taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
@@ -591,7 +638,6 @@ ath_edma_recv_tasklet(void *arg, int npending)
        ATH_PCU_LOCK(sc);
        sc->sc_rxproc_cnt--;
        ATH_PCU_UNLOCK(sc);
-       wlan_serialize_exit();
 }
 
 /*
@@ -612,9 +658,11 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
 
        ATH_RX_LOCK_ASSERT(sc);
 
+#if defined(__DragonFly__)
        m = m_getjcl(MB_DONTWAIT, MT_DATA, M_PKTHDR, sc->sc_edma_bufsize);
-/*     m = m_getcl(MB_WAIT, MT_DATA, M_PKTHDR);*/
-/*     m = m_getm(NULL, sc->sc_edma_bufsize, MB_WAIT, MT_DATA);*/
+#else
+       m = m_getm(NULL, sc->sc_edma_bufsize, MB_DONTWAIT, MT_DATA);
+#endif
        if (! m)
                return (ENOBUFS);               /* XXX ?*/
 
@@ -634,7 +682,6 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
        /*
         * Populate ath_buf fields.
         */
-       KKASSERT(m->m_len >= sc->sc_rx_statuslen);
        bf->bf_desc = mtod(m, struct ath_desc *);
        bf->bf_lastds = bf->bf_desc;    /* XXX only really for TX? */
        bf->bf_m = m;
@@ -651,8 +698,14 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
        /*
         * Create DMA mapping.
         */
-       error = bus_dmamap_load_mbuf_segment(sc->sc_dmat,
-           bf->bf_dmamap, m, bf->bf_segs, 1, &bf->bf_nseg, BUS_DMA_NOWAIT);
+#if defined(__DragonFly__)
+       error = bus_dmamap_load_mbuf_segment(
+                               sc->sc_dmat, bf->bf_dmamap, m,
+                               bf->bf_segs, 1, &bf->bf_nseg, BUS_DMA_NOWAIT);
+#else
+       error = bus_dmamap_load_mbuf_sg(sc->sc_dmat,
+           bf->bf_dmamap, m, bf->bf_segs, &bf->bf_nseg, BUS_DMA_NOWAIT);
+#endif
 
        if (error != 0) {
                device_printf(sc->sc_dev, "%s: failed; error=%d\n",
@@ -675,7 +728,7 @@ ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
         * to occur.
         */
        bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
-                       BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        /* Finish! */
        return (0);
@@ -859,15 +912,17 @@ ath_edma_setup_rxfifo(struct ath_softc *sc, HAL_RX_QUEUE qtype)
                    qtype);
                return (-EINVAL);
        }
-       device_printf(sc->sc_dev, "%s: type=%d, FIFO depth = %d entries\n",
-           __func__,
-           qtype,
-           re->m_fifolen);
+
+       if (bootverbose)
+               device_printf(sc->sc_dev,
+                   "%s: type=%d, FIFO depth = %d entries\n",
+                   __func__,
+                   qtype,
+                   re->m_fifolen);
 
        /* Allocate ath_buf FIFO array, pre-zero'ed */
        re->m_fifo = kmalloc(sizeof(struct ath_buf *) * re->m_fifolen,
-           M_ATHDEV,
-           M_INTWAIT | M_ZERO);
+                            M_ATHDEV, M_INTWAIT | M_ZERO);
        if (re->m_fifo == NULL) {
                device_printf(sc->sc_dev, "%s: malloc failed\n",
                    __func__);
@@ -953,10 +1008,12 @@ ath_recv_setup_edma(struct ath_softc *sc)
        (void) ath_hal_setrxbufsize(sc->sc_ah, sc->sc_edma_bufsize -
            sc->sc_rx_statuslen);
 
-       device_printf(sc->sc_dev, "RX status length: %d\n",
-           sc->sc_rx_statuslen);
-       device_printf(sc->sc_dev, "RX buffer size: %d\n",
-           sc->sc_edma_bufsize);
+       if (bootverbose) {
+               device_printf(sc->sc_dev, "RX status length: %d\n",
+                   sc->sc_rx_statuslen);
+               device_printf(sc->sc_dev, "RX buffer size: %d\n",
+                   sc->sc_edma_bufsize);
+       }
 
        sc->sc_rx.recv_stop = ath_edma_stoprecv;
        sc->sc_rx.recv_start = ath_edma_startrecv;
index 38d9574..d3b24fc 100644 (file)
@@ -29,6 +29,7 @@
  * $FreeBSD$
  */
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Implement some basic spectral scan control logic.
@@ -45,7 +46,9 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
+
 #include <sys/bus.h>
+
 #include <sys/socket.h>
  
 #include <net/if.h>
index 7bf9f36..e9d143b 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -108,14 +109,22 @@ ath_sysctl_slottime(SYSCTL_HANDLER_ARGS)
        u_int slottime;
        int error;
 
-       wlan_serialize_enter();
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
        slottime = ath_hal_getslottime(sc->sc_ah);
+       ATH_UNLOCK(sc);
+
        error = sysctl_handle_int(oidp, &slottime, 0, req);
-       if (error == 0 && req->newptr)
-               error = !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
+       if (error || !req->newptr)
+               goto finish;
+
+       error = !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
+
+finish:
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
-       wlan_serialize_exit();
+       ATH_UNLOCK(sc);
+
        return error;
 }
 
@@ -123,50 +132,38 @@ static int
 ath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int acktimeout;
+       u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       acktimeout = ath_hal_getacktimeout(sc->sc_ah);
        error = sysctl_handle_int(oidp, &acktimeout, 0, req);
-       if (error == 0 && req->newptr) {
-               error = !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ?
-                       EINVAL : 0;
-       }
-       wlan_serialize_exit();
-       return error;
+       if (error || !req->newptr)
+               return error;
+       return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0;
 }
 
 static int
 ath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int ctstimeout;
+       u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       ctstimeout = ath_hal_getctstimeout(sc->sc_ah);
        error = sysctl_handle_int(oidp, &ctstimeout, 0, req);
-       if (error == 0 && req->newptr) {
-               error = !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ?
-                       EINVAL : 0;
-       }
-       wlan_serialize_exit();
-       return error;
+       if (error || !req->newptr)
+               return error;
+       return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0;
 }
 
 static int
 ath_sysctl_softled(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       int softled;
+       int softled = sc->sc_softled;
        int error;
 
-       wlan_serialize_enter();
-       softled = sc->sc_softled;
        error = sysctl_handle_int(oidp, &softled, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
        softled = (softled != 0);
        if (softled != sc->sc_softled) {
                if (softled) {
@@ -175,48 +172,38 @@ ath_sysctl_softled(SYSCTL_HANDLER_ARGS)
                }
                sc->sc_softled = softled;
        }
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
 ath_sysctl_ledpin(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       int ledpin;
+       int ledpin = sc->sc_ledpin;
        int error;
 
-       wlan_serialize_enter();
-       ledpin = sc->sc_ledpin;
        error = sysctl_handle_int(oidp, &ledpin, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
        if (ledpin != sc->sc_ledpin) {
                sc->sc_ledpin = ledpin;
                if (sc->sc_softled) {
                        ath_led_config(sc);
                }
        }
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
 ath_sysctl_hardled(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       int hardled;
+       int hardled = sc->sc_hardled;
        int error;
 
-       wlan_serialize_enter();
-       hardled = sc->sc_hardled;
        error = sysctl_handle_int(oidp, &hardled, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
        hardled = (hardled != 0);
        if (hardled != sc->sc_hardled) {
                if (hardled) {
@@ -225,29 +212,21 @@ ath_sysctl_hardled(SYSCTL_HANDLER_ARGS)
                }
                sc->sc_hardled = hardled;
        }
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
 ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int txantenna;
+       u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       txantenna = ath_hal_getantennaswitch(sc->sc_ah);
        error = sysctl_handle_int(oidp, &txantenna, 0, req);
        if (!error && req->newptr) {
                /* XXX assumes 2 antenna ports */
-               if (txantenna < HAL_ANT_VARIABLE ||
-                   txantenna > HAL_ANT_FIXED_B) {
-                       error = EINVAL;
-                       goto done;
-               }
+               if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B)
+                       return EINVAL;
                ath_hal_setantennaswitch(sc->sc_ah, txantenna);
                /*
                 * NB: with the switch locked this isn't meaningful,
@@ -256,9 +235,6 @@ ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS)
                 */
                sc->sc_txantenna = txantenna;
        }
-       error = 0;
-done:
-       wlan_serialize_exit();
        return error;
 }
 
@@ -266,15 +242,12 @@ static int
 ath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int defantenna;
+       u_int defantenna = ath_hal_getdefantenna(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       defantenna = ath_hal_getdefantenna(sc->sc_ah);
        error = sysctl_handle_int(oidp, &defantenna, 0, req);
        if (!error && req->newptr)
                ath_hal_setdefantenna(sc->sc_ah, defantenna);
-       wlan_serialize_exit();
        return error;
 }
 
@@ -282,23 +255,16 @@ static int
 ath_sysctl_diversity(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int diversity;
+       u_int diversity = ath_hal_getdiversity(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       diversity = ath_hal_getdiversity(sc->sc_ah);
        error = sysctl_handle_int(oidp, &diversity, 0, req);
        if (error || !req->newptr)
-               goto done;
-       if (!ath_hal_setdiversity(sc->sc_ah, diversity)) {
-               error = EINVAL;
-               goto done;
-       }
+               return error;
+       if (!ath_hal_setdiversity(sc->sc_ah, diversity))
+               return EINVAL;
        sc->sc_diversity = diversity;
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
@@ -308,18 +274,12 @@ ath_sysctl_diag(SYSCTL_HANDLER_ARGS)
        u_int32_t diag;
        int error;
 
-       wlan_serialize_enter();
-       if (!ath_hal_getdiag(sc->sc_ah, &diag)) {
-               error = EINVAL;
-               goto done;
-       }
+       if (!ath_hal_getdiag(sc->sc_ah, &diag))
+               return EINVAL;
        error = sysctl_handle_int(oidp, &diag, 0, req);
        if (error || !req->newptr)
-               goto done;
-       error = !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0;
-done:
-       wlan_serialize_exit();
-       return error;
+               return error;
+       return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0;
 }
 
 static int
@@ -330,35 +290,26 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
        u_int32_t scale;
        int error;
 
-       wlan_serialize_enter();
        (void) ath_hal_gettpscale(sc->sc_ah, &scale);
        error = sysctl_handle_int(oidp, &scale, 0, req);
        if (error || !req->newptr)
-               goto done;
-       error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
+               return error;
+       return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
            (ifp->if_flags & IFF_RUNNING) ?
              ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
-done:
-       wlan_serialize_exit();
-       return error;
 }
 
 static int
 ath_sysctl_tpc(SYSCTL_HANDLER_ARGS)
 {
        struct ath_softc *sc = arg1;
-       u_int tpc;
+       u_int tpc = ath_hal_gettpc(sc->sc_ah);
        int error;
 
-       wlan_serialize_enter();
-       tpc = ath_hal_gettpc(sc->sc_ah);
        error = sysctl_handle_int(oidp, &tpc, 0, req);
        if (error || !req->newptr)
-               goto done;
-       error = !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
-done:
-       wlan_serialize_exit();
-       return error;
+               return error;
+       return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
 }
 
 static int
@@ -367,29 +318,18 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
        struct ath_softc *sc = arg1;
        struct ifnet *ifp = sc->sc_ifp;
        struct ath_hal *ah = sc->sc_ah;
-       u_int rfkill;
+       u_int rfkill = ath_hal_getrfkill(ah);
        int error;
 
-       wlan_serialize_enter();
-       rfkill = ath_hal_getrfkill(ah);
        error = sysctl_handle_int(oidp, &rfkill, 0, req);
        if (error || !req->newptr)
-               goto done;
-       if (rfkill == ath_hal_getrfkill(ah)) {  /* unchanged */
-               error = 0;
-               goto done;
-       }
-       if (!ath_hal_setrfkill(ah, rfkill)) {
-               error = EINVAL;
-               goto done;
-       }
-       if (ifp->if_flags & IFF_RUNNING)
-               error = ath_reset(ifp, ATH_RESET_FULL);
-       else
-               error = 0;
-done:
-       wlan_serialize_exit();
-       return 0;
+               return error;
+       if (rfkill == ath_hal_getrfkill(ah))    /* unchanged */
+               return 0;
+       if (!ath_hal_setrfkill(ah, rfkill))
+               return EINVAL;
+       return (ifp->if_flags & IFF_RUNNING) ?
+           ath_reset(ifp, ATH_RESET_FULL) : 0;
 }
 
 static int
@@ -431,7 +371,6 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS)
        }
        kprintf("\n");
 
-       wlan_serialize_enter();
        for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
                if (ATH_TXQ_SETUP(sc, i)) {
                        kprintf("HW TXQ %d: axq_depth=%d, axq_aggr_depth=%d, "
@@ -488,7 +427,6 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS)
        kprintf("Total RX buffers in free list: %d buffers\n",
            i);
        ATH_RX_UNLOCK(sc);
-       wlan_serialize_exit();
 
        return 0;
 }
@@ -500,20 +438,23 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
        u_int rfsilent;
        int error;
 
-       wlan_serialize_enter();
        (void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent);
        error = sysctl_handle_int(oidp, &rfsilent, 0, req);
        if (error || !req->newptr)
-               goto done;
-       if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) {
-               error = EINVAL;
-               goto done;
-       }
-       sc->sc_rfsilentpin = rfsilent & 0x1c;
+               return error;
+       if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent))
+               return EINVAL;
+       /*
+        * Earlier chips (< AR5212) have up to 8 GPIO
+        * pins exposed.
+        *
+        * AR5416 and later chips have many more GPIO
+        * pins (up to 16) so the mask is expanded to
+        * four bits.
+        */
+       sc->sc_rfsilentpin = rfsilent & 0x3c;
        sc->sc_rfsilentpol = (rfsilent & 0x2) != 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
@@ -523,15 +464,11 @@ ath_sysctl_tpack(SYSCTL_HANDLER_ARGS)
        u_int32_t tpack;
        int error;
 
-       wlan_serialize_enter();
        (void) ath_hal_gettpack(sc->sc_ah, &tpack);
        error = sysctl_handle_int(oidp, &tpack, 0, req);
        if (error || !req->newptr)
-               goto done;
-       error = !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0;
-done:
-       wlan_serialize_exit();
-       return error;
+               return error;
+       return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0;
 }
 
 static int
@@ -541,15 +478,11 @@ ath_sysctl_tpcts(SYSCTL_HANDLER_ARGS)
        u_int32_t tpcts;
        int error;
 
-       wlan_serialize_enter();
        (void) ath_hal_gettpcts(sc->sc_ah, &tpcts);
        error = sysctl_handle_int(oidp, &tpcts, 0, req);
        if (error || !req->newptr)
-               goto done;
-       error = !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0;
-done:
-       wlan_serialize_exit();
-       return error;
+               return error;
+       return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0;
 }
 
 static int
@@ -558,30 +491,25 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
        struct ath_softc *sc = arg1;
        int intmit, error;
 
-       wlan_serialize_enter();
        intmit = ath_hal_getintmit(sc->sc_ah);
        error = sysctl_handle_int(oidp, &intmit, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
 
        /* reusing error; 1 here means "good"; 0 means "fail" */
        error = ath_hal_setintmit(sc->sc_ah, intmit);
-       if (!error) {
-               error = EINVAL;
-               goto done;
-       }
+       if (! error)
+               return EINVAL;
 
        /*
         * Reset the hardware here - disabling ANI in the HAL
         * doesn't reset ANI related registers, so it'll leave
         * things in an inconsistent state.
         */
-       if (sc->sc_ifp->if_flags & IFF_RUNNING)
+       if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
                ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+
+       return 0;
 }
 
 #ifdef IEEE80211_SUPPORT_TDMA
@@ -591,15 +519,12 @@ ath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
        struct ath_softc *sc = arg1;
        int setcca, error;
 
-       wlan_serialize_enter();
        setcca = sc->sc_setcca;
        error = sysctl_handle_int(oidp, &setcca, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
        sc->sc_setcca = (setcca != 0);
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 #endif /* IEEE80211_SUPPORT_TDMA */
 
@@ -610,18 +535,19 @@ ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS)
        int val = 0;
        int error;
 
-       wlan_serialize_enter();
        error = sysctl_handle_int(oidp, &val, 0, req);
        if (error || !req->newptr)
-               goto done;
+               return error;
        if (val == 0)
-               goto done;
+               return 0;
 
+#if defined(__DragonFly__)
        taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask);
+#else
+       taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_bstucktask);
+#endif
        val = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 static int
@@ -642,19 +568,14 @@ ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS)
                return 0;
 
        /* Do a hang check */
-       wlan_serialize_enter();
        if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS,
            &mask, sizeof(mask),
-           (void *) &sp, &rsize)) {
-               goto done;
-       }
+           (void *) &sp, &rsize))
+               return (0);
        device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp);
 
        val = 0;
-       error = 0;
-done:
-       wlan_serialize_exit();
-       return error;
+       return 0;
 }
 
 #ifdef ATH_DEBUG_ALQ
@@ -664,17 +585,15 @@ ath_sysctl_alq_log(SYSCTL_HANDLER_ARGS)
        struct ath_softc *sc = arg1;
        int error, enable;
 
-       wlan_serialize_enter();
        enable = (sc->sc_alq.sc_alq_isactive);
+
        error = sysctl_handle_int(oidp, &enable, 0, req);
        if (error || !req->newptr)
-               goto done;
-       if (enable)
+               return (error);
+       else if (enable)
                error = if_ath_alq_start(&sc->sc_alq);
        else
                error = if_ath_alq_stop(&sc->sc_alq);
-done:
-       wlan_serialize_exit();
        return (error);
 }
 
@@ -723,14 +642,26 @@ ath_sysctlattach(struct ath_softc *sc)
                "regdomain", CTLFLAG_RD, &sc->sc_eerd, 0,
                "EEPROM regdomain code");
 #ifdef ATH_DEBUG
+#if defined(__DragonFly__)
        SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
                "debug", CTLFLAG_RW, &sc->sc_debug, 0,
                "control debugging printfs");
+#else
+       SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+               "debug", CTLFLAG_RW, &sc->sc_debug,
+               "control debugging printfs");
+#endif
 #endif
 #ifdef ATH_DEBUG_ALQ
+#if defined(__DragonFly__)
        SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
                "ktrdebug", CTLFLAG_RW, &sc->sc_ktrdebug, 0,
                "control debugging KTR");
+#else
+       SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+               "ktrdebug", CTLFLAG_RW, &sc->sc_ktrdebug,
+               "control debugging KTR");
+#endif
 #endif /* ATH_DEBUG_ALQ */
        SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
                "slottime", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
@@ -913,11 +844,9 @@ ath_sysctl_clearstats(SYSCTL_HANDLER_ARGS)
                return error;
        if (val == 0)
                return 0;       /* Not clearing the stats is still valid */
-       wlan_serialize_enter();
        memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
        memset(&sc->sc_aggr_stats, 0, sizeof(sc->sc_aggr_stats));
        memset(&sc->sc_intr_stats, 0, sizeof(sc->sc_intr_stats));
-       wlan_serialize_exit();
 
        val = 0;
        return 0;
@@ -1238,8 +1167,7 @@ ath_sysctl_hal_attach(struct ath_softc *sc)
            &sc->sc_ah->ah_config.ah_additional_swba_backoff, 0,
            "Atheros HAL additional SWBA backoff time");
 
-       /* XXX sc_rxfifo_state control requires this to be set */
-       sc->sc_ah->ah_config.ah_force_full_reset = 1;
+       sc->sc_ah->ah_config.ah_force_full_reset = 0;
        SYSCTL_ADD_INT(ctx, child, OID_AUTO, "force_full_reset", CTLFLAG_RW,
            &sc->sc_ah->ah_config.ah_force_full_reset, 0,
            "Force full chip reset rather than a warm reset");
index 785e320..cea09cf 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -471,19 +472,22 @@ ath_tdma_update(struct ieee80211_node *ni,
        tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
 
        DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
-           "rs->rstamp %ju rstamp %ju tsf %ju txtime %d, nextslot %ju, "
+           "rs->rstamp %llu rstamp %llu tsf %llu txtime %d, nextslot %llu, "
            "nextslottu %d, nextslottume %d\n",
-           (uintmax_t)rs->rs_tstamp, (uintmax_t)rstamp, (uintmax_t)tsf, txtime,
-           (uintmax_t)nextslot, nextslottu, TSF_TO_TU(nextslot >> 32, nextslot));
+           (unsigned long long) rs->rs_tstamp,
+           (unsigned long long) rstamp,
+           (unsigned long long) tsf, txtime,
+           (unsigned long long) nextslot,
+           nextslottu, TSF_TO_TU(nextslot >> 32, nextslot));
        DPRINTF(sc, ATH_DEBUG_TDMA,
-           "  beacon tstamp: %ju (0x%016jx)\n",
-           (uintmax_t)le64toh(ni->ni_tstamp.tsf),
-           (uintmax_t)le64toh(ni->ni_tstamp.tsf));
+           "  beacon tstamp: %llu (0x%016llx)\n",
+           (unsigned long long) le64toh(ni->ni_tstamp.tsf),
+           (unsigned long long) le64toh(ni->ni_tstamp.tsf));
 
        DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
-           "nexttbtt %ju (0x%08jx) tsfdelta %d avg +%d/-%d\n",
-           (uintmax_t)nexttbtt,
-           (uintmax_t)nexttbtt,
+           "nexttbtt %llu (0x%08llx) tsfdelta %d avg +%d/-%d\n",
+           (unsigned long long) nexttbtt,
+           (long long) nexttbtt,
            tsfdelta,
            TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam));
 
@@ -574,9 +578,9 @@ ath_tdma_update(struct ieee80211_node *ni,
                tsf = ath_hal_gettsf64(ah);
                ath_hal_settsf64(ah, tsf + tsfdelta);
                DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
-                   "%s: calling ath_hal_adjusttsf: TSF=%ju, tsfdelta=%d\n",
+                   "%s: calling ath_hal_adjusttsf: TSF=%llu, tsfdelta=%d\n",
                    __func__,
-                   (uintmax_t)tsf,
+                   (unsigned long long) tsf,
                    tsfdelta);
 
 #ifdef ATH_DEBUG_ALQ
index 301827b..94c75fa 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
 #include <dev/netif/ath/ath/if_ath_alq.h>
 #endif
 
-extern  const char* ath_hal_ether_sprintf(const uint8_t *mac);
-
 /*
  * How many retries to perform in software
  */
@@ -240,14 +239,11 @@ void
 ath_txfrag_cleanup(struct ath_softc *sc,
        ath_bufhead *frags, struct ieee80211_node *ni)
 {
-       struct ath_buf *bf;
-       struct ath_buf *next;
+       struct ath_buf *bf, *next;
 
        ATH_TXBUF_LOCK_ASSERT(sc);
 
-       next = TAILQ_FIRST(frags);
-       while ((bf = next) != NULL) {
-               next = TAILQ_NEXT(bf, bf_list);
+       TAILQ_FOREACH_SAFE(bf, frags, bf_list, next) {
                /* NB: bf assumed clean */
                TAILQ_REMOVE(frags, bf, bf_list);
                ath_returnbuf_head(sc, bf);
@@ -304,25 +300,65 @@ ath_freetx(struct mbuf *m)
 static int
 ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0)
 {
+#if defined(__DragonFly__)
+#else
+       struct mbuf *m;
+#endif
        int error;
 
        /*
         * Load the DMA map so any coalescing is done.  This
         * also calculates the number of descriptors we need.
         */
-       error = bus_dmamap_load_mbuf_defrag(sc->sc_dmat, bf->bf_dmamap, &m0,
-                                    bf->bf_segs, ATH_TXDESC, &bf->bf_nseg,
+#if defined(__DragonFly__)
+       error = bus_dmamap_load_mbuf_segment(sc->sc_dmat, bf->bf_dmamap, m0,
+                                    bf->bf_segs, 1, &bf->bf_nseg,
                                     BUS_DMA_NOWAIT);
-       if (error != 0) {
+#else
+       error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
+                                    bf->bf_segs, &bf->bf_nseg,
+                                    BUS_DMA_NOWAIT);
+#endif
+       if (error == EFBIG) {
+               /* XXX packet requires too many descriptors */
+               bf->bf_nseg = ATH_MAX_SCATTER + 1;
+       } else if (error != 0) {
                sc->sc_stats.ast_tx_busdma++;
                ath_freetx(m0);
                return error;
        }
-
        /*
-        * Discard null packets.
+        * Discard null packets and check for packets that
+        * require too many TX descriptors.  We try to convert
+        * the latter to a cluster.
         */
-       if (bf->bf_nseg == 0) {
+       if (bf->bf_nseg > ATH_MAX_SCATTER) {            /* too many desc's, linearize */
+               sc->sc_stats.ast_tx_linear++;
+#if defined(__DragonFly__)
+               error = bus_dmamap_load_mbuf_defrag(sc->sc_dmat,
+                                            bf->bf_dmamap, &m0,
+                                            bf->bf_segs, ATH_TXDESC,
+                                            &bf->bf_nseg, BUS_DMA_NOWAIT);
+#else
+               m = m_collapse(m0, M_NOWAIT, ATH_MAX_SCATTER);
+               if (m == NULL) {
+                       ath_freetx(m0);
+                       sc->sc_stats.ast_tx_nombuf++;
+                       return ENOMEM;
+               }
+               m0 = m;
+               error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m0,
+                                            bf->bf_segs, &bf->bf_nseg,
+                                            BUS_DMA_NOWAIT);
+#endif
+               if (error != 0) {
+                       sc->sc_stats.ast_tx_busdma++;
+                       ath_freetx(m0);
+                       return error;
+               }
+               KASSERT(bf->bf_nseg <= ATH_MAX_SCATTER,
+                   ("too many segments after defrag; nseg %u", bf->bf_nseg));
+       } else if (bf->bf_nseg == 0) {          /* null packet, discard */
                sc->sc_stats.ast_tx_nodata++;
                ath_freetx(m0);
                return EIO;
@@ -1442,10 +1478,9 @@ ath_tx_should_swq_frame(struct ath_softc *sc, struct ath_node *an,
                 * for now!
                 */
                DPRINTF(sc, ATH_DEBUG_XMIT, 
-                   "%s: %s: Node is asleep; sending mgmt "
+                   "%s: %6D: Node is asleep; sending mgmt "
                    "(type=%d, subtype=%d)\n",
-                   __func__, ath_hal_ether_sprintf(ni->ni_macaddr),
-                   type, subtype);
+                   __func__, ni->ni_macaddr, ":", type, subtype);
                return (0);
        } else {
                return (1);
@@ -2337,7 +2372,9 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
        ATH_PCU_UNLOCK(sc);
 
        /* Wake the hardware up already */
+       ATH_LOCK(sc);
        ath_power_set_power_state(sc, HAL_PM_AWAKE);
+       ATH_UNLOCK(sc);
 
        ATH_TX_LOCK(sc);
 
@@ -2401,7 +2438,11 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
                }
        }
        sc->sc_wd_timer = 5;
-       ifp->if_opackets++;
+#if defined(__DragonFly__)
+       ++ifp->if_opackets;
+#else
+       if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+#endif
        sc->sc_stats.ast_tx_raw++;
 
        /*
@@ -2419,7 +2460,9 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
 
 
        /* Put the hardware back to sleep if required */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
        return 0;
 
@@ -2441,12 +2484,18 @@ bad:
        ATH_PCU_UNLOCK(sc);
 
        /* Put the hardware back to sleep if required */
+       ATH_LOCK(sc);
        ath_power_restore_power_state(sc);
+       ATH_UNLOCK(sc);
 
 badbad:
        ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p",
            m, params);
-       ifp->if_oerrors++;
+#if defined(__DragonFly__)
+       ++ifp->if_oerrors;
+#else
+       if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+#endif
        sc->sc_stats.ast_tx_raw_fail++;
        ieee80211_free_node(ni);
 
@@ -2764,9 +2813,10 @@ ath_tx_leak_count_update(struct ath_softc *sc, struct ath_tid *tid,
                        wh->i_fc[1] &= ~IEEE80211_FC1_MORE_DATA;
 
                DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
-                   "%s: %s: leak count = %d, psq=%d, swq=%d, MORE=%d\n",
+                   "%s: %6D: leak count = %d, psq=%d, swq=%d, MORE=%d\n",
                    __func__,
-                   ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+                   tid->an->an_node.ni_macaddr,
+                   ":",
                    tid->an->an_leak_count,
                    tid->an->an_stack_psq,
                    tid->an->an_swq_depth,
@@ -3232,9 +3282,9 @@ ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid)
 
        ATH_TX_LOCK_ASSERT(sc);
        tid->paused++;
-       DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: [%s]: tid=%d, paused = %d\n",
+       DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: [%6D]: tid=%d, paused = %d\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr, ":",
            tid->tid,
            tid->paused);
 }
@@ -3253,20 +3303,19 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
         * until it's actually resolved.
         */
        if (tid->paused == 0) {
-               device_printf(sc->sc_dev,
-                             "%s: [%s]: tid=%d, paused=0?\n",
-                             __func__,
-                             ath_hal_ether_sprintf(
-                                               tid->an->an_node.ni_macaddr),
-                             tid->tid);
+               athdev_printf(sc->sc_dev,
+                   "%s: [%6D]: tid=%d, paused=0?\n",
+                   __func__,
+                   tid->an->an_node.ni_macaddr, ":",
+                   tid->tid);
        } else {
                tid->paused--;
        }
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
-           "%s: [%s]: tid=%d, unpaused = %d\n",
+           "%s: [%6D]: tid=%d, unpaused = %d\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr, ":",
            tid->tid,
            tid->paused);
 
@@ -3545,16 +3594,16 @@ ath_tx_tid_bar_unsuspend(struct ath_softc *sc, struct ath_tid *tid)
        ATH_TX_LOCK_ASSERT(sc);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: TID=%d, called\n",
+           "%s: %6D: TID=%d, called\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr,
+           ":",
            tid->tid);
 
        if (tid->bar_tx == 0 || tid->bar_wait == 0) {
                DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-                   "%s: %s: TID=%d, bar_tx=%d, bar_wait=%d: ?\n",
-                   __func__,
-                   ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+                   "%s: %6D: TID=%d, bar_tx=%d, bar_wait=%d: ?\n",
+                   __func__, tid->an->an_node.ni_macaddr, ":",
                    tid->tid, tid->bar_tx, tid->bar_wait);
        }
 
@@ -3577,9 +3626,10 @@ ath_tx_tid_bar_tx_ready(struct ath_softc *sc, struct ath_tid *tid)
                return (0);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: TID=%d, bar ready\n",
+           "%s: %6D: TID=%d, bar ready\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr,
+           ":",
            tid->tid);
 
        return (1);
@@ -3605,9 +3655,10 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
        ATH_TX_LOCK_ASSERT(sc);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: TID=%d, called\n",
+           "%s: %6D: TID=%d, called\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr,
+           ":",
            tid->tid);
 
        tap = ath_tx_get_tx_tid(tid->an, tid->tid);
@@ -3617,9 +3668,8 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
         */
        if (tid->bar_wait == 0 || tid->bar_tx == 1) {
                DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-                   "%s: %s: TID=%d, bar_tx=%d, bar_wait=%d: ?\n",
-                   __func__,
-                   ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+                   "%s: %6D: TID=%d, bar_tx=%d, bar_wait=%d: ?\n",
+                   __func__, tid->an->an_node.ni_macaddr, ":",
                    tid->tid, tid->bar_tx, tid->bar_wait);
                return;
        }
@@ -3627,9 +3677,10 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
        /* Don't do anything if we still have pending frames */
        if (tid->hwq_depth > 0) {
                DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-                   "%s: %s: TID=%d, hwq_depth=%d, waiting\n",
+                   "%s: %6D: TID=%d, hwq_depth=%d, waiting\n",
                    __func__,
-                   ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+                   tid->an->an_node.ni_macaddr,
+                   ":",
                    tid->tid,
                    tid->hwq_depth);
                return;
@@ -3651,9 +3702,10 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
         * XXX verify this is _actually_ the valid value to begin at!
         */
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: TID=%d, new BAW left edge=%d\n",
+           "%s: %6D: TID=%d, new BAW left edge=%d\n",
            __func__,
-           ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           tid->an->an_node.ni_macaddr,
+           ":",
            tid->tid,
            tap->txa_start);
 
@@ -3670,8 +3722,8 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
        /* Failure? For now, warn loudly and continue */
        ATH_TX_LOCK(sc);
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: TID=%d, failed to TX BAR, continue!\n",
-           __func__, ath_hal_ether_sprintf(tid->an->an_node.ni_macaddr),
+           "%s: %6D: TID=%d, failed to TX BAR, continue!\n",
+           __func__, tid->an->an_node.ni_macaddr, ":",
            tid->tid);
        ath_tx_tid_bar_unsuspend(sc, tid);
 }
@@ -3728,44 +3780,48 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
        tap = ath_tx_get_tx_tid(an, tid->tid);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
-           "%s: %s: %s: bf=%p: addbaw=%d, dobaw=%d, "
+           "%s: %s: %6D: bf=%p: addbaw=%d, dobaw=%d, "
            "seqno=%d, retry=%d\n",
            __func__,
            pfx,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            bf,
            bf->bf_state.bfs_addedbaw,
            bf->bf_state.bfs_dobaw,
            SEQNO(bf->bf_state.bfs_seqno),
            bf->bf_state.bfs_retries);
        DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
-           "%s: %s: %s: bf=%p: txq[%d] axq_depth=%d, axq_aggr_depth=%d\n",
+           "%s: %s: %6D: bf=%p: txq[%d] axq_depth=%d, axq_aggr_depth=%d\n",
            __func__,
            pfx,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            bf,
            txq->axq_qnum,
            txq->axq_depth,
            txq->axq_aggr_depth);
        DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
-           "%s: %s: %s: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, "
+           "%s: %s: %6D: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, "
              "isfiltered=%d\n",
            __func__,
            pfx,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            bf,
            tid->axq_depth,
            tid->hwq_depth,
            tid->bar_wait,
            tid->isfiltered);
        DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
-           "%s: %s: %s: tid %d: "
+           "%s: %s: %6D: tid %d: "
            "sched=%d, paused=%d, "
            "incomp=%d, baw_head=%d, "
            "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
             __func__,
             pfx,
-            ath_hal_ether_sprintf(ni->ni_macaddr),
+            ni->ni_macaddr,
+            ":",
             tid->tid,
             tid->sched, tid->paused,
             tid->incomp, tid->baw_head,
@@ -3866,9 +3922,10 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
        if (tap) {
 #if 1
                DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
-                   "%s: %s: node %p: TID %d: sliding BAW left edge to %d\n",
+                   "%s: %6D: node %p: TID %d: sliding BAW left edge to %d\n",
                    __func__,
-                   ath_hal_ether_sprintf(ni->ni_macaddr),
+                   ni->ni_macaddr,
+                   ":",
                    an,
                    tid->tid,
                    tap->txa_start);
@@ -3966,10 +4023,11 @@ ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an)
 
        ATH_TX_LOCK(sc);
        DPRINTF(sc, ATH_DEBUG_NODE,
-           "%s: %s: flush; is_powersave=%d, stack_psq=%d, tim=%d, "
+           "%s: %6D: flush; is_powersave=%d, stack_psq=%d, tim=%d, "
            "swq_depth=%d, clrdmask=%d, leak_count=%d\n",
            __func__,
-           ath_hal_ether_sprintf(an->an_node.ni_macaddr),
+           an->an_node.ni_macaddr,
+           ":",
            an->an_is_powersave,
            an->an_stack_psq,
            an->an_tim_set,
@@ -4768,7 +4826,7 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first,
                ath_tx_tid_filt_comp_aggr(sc, atid, bf_first, &bf_cq);
 
                /* Remove from BAW */
-               TAILQ_FOREACH(bf, &bf_cq, bf_list) {
+               TAILQ_FOREACH_SAFE(bf, &bf_cq, bf_list, bf_next) {
                        if (bf->bf_state.bfs_addedbaw)
                                drops++;
                        if (bf->bf_state.bfs_dobaw) {
@@ -5546,7 +5604,7 @@ ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an,
 void
 ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq)
 {
-       struct ath_tid *tid, *last;
+       struct ath_tid *tid, *next, *last;
 
        ATH_TX_LOCK_ASSERT(sc);
 
@@ -5570,7 +5628,7 @@ ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq)
 
        last = TAILQ_LAST(&txq->axq_tidq, axq_t_s);
 
-       while ((tid = TAILQ_FIRST(&txq->axq_tidq)) != NULL) {
+       TAILQ_FOREACH_SAFE(tid, &txq->axq_tidq, axq_qelem, next) {
                /*
                 * Suspend paused queues here; they'll be resumed
                 * once the addba completes or times out.
@@ -5583,9 +5641,7 @@ ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq)
                 * a frame; be careful.
                 */
                if (! ath_tx_tid_can_tx_or_sched(sc, tid)) {
-                       if (tid == last)
-                               break;
-                       continue;
+                       goto loop_done;
                }
                if (ath_tx_ampdu_running(sc, tid->an, tid->tid))
                        ath_tx_tid_hw_queue_aggr(sc, tid->an, tid);
@@ -5608,7 +5664,7 @@ ath_txq_sched(struct ath_softc *sc, struct ath_txq *txq)
                if (txq->axq_depth >= sc->sc_hwq_limit_nonaggr) {
                        break;
                }
-
+loop_done:
                /*
                 * If this was the last entry on the original list, stop.
                 * Otherwise nodes that have been rescheduled onto the end
@@ -5738,9 +5794,10 @@ ath_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
        ATH_TX_UNLOCK(sc);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
-           "%s: %s: called; dialogtoken=%d, baparamset=%d, batimeout=%d\n",
+           "%s: %6D: called; dialogtoken=%d, baparamset=%d, batimeout=%d\n",
            __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            dialogtoken, baparamset, batimeout);
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
            "%s: txa_start=%d, ni_txseqs=%d\n",
@@ -5781,8 +5838,9 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
        int r;
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
-           "%s: %s: called; status=%d, code=%d, batimeout=%d\n", __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           "%s: %6D: called; status=%d, code=%d, batimeout=%d\n", __func__,
+           ni->ni_macaddr,
+           ":",
            status, code, batimeout);
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
@@ -5827,9 +5885,10 @@ ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
        ath_bufhead bf_cq;
        struct ath_buf *bf;
 
-       DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: %s: called\n",
+       DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: %6D: called\n",
            __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr));
+           ni->ni_macaddr,
+           ":");
 
        /*
         * Pause TID traffic early, so there aren't any races
@@ -5912,9 +5971,10 @@ ath_tx_node_reassoc(struct ath_softc *sc, struct ath_node *an)
                if (tid->hwq_depth == 0)
                        continue;
                DPRINTF(sc, ATH_DEBUG_NODE,
-                   "%s: %s: TID %d: cleaning up TID\n",
+                   "%s: %6D: TID %d: cleaning up TID\n",
                    __func__,
-                   ath_hal_ether_sprintf(an->an_node.ni_macaddr),
+                   an->an_node.ni_macaddr,
+                   ":",
                    i);
                /*
                 * In case there's a followup call to this, only call it
@@ -5961,10 +6021,10 @@ ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
        int old_txa_start;
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
-           "%s: %s: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d"
-           ",  txa_start=%d, txa_seqpending=%d\n",
+           "%s: %6D: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d, txa_start=%d, txa_seqpending=%d\n",
            __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            tap->txa_tid,
            atid->tid,
            status,
@@ -5983,17 +6043,18 @@ ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
         * XXX and just correct it afterwards? The below condition should
         * XXX never happen and if it does I need to fix all kinds of things.
         */
+       ATH_TX_LOCK(sc);
        old_txa_start = tap->txa_start;
        sc->sc_bar_response(ni, tap, status);
        if (tap->txa_start != old_txa_start) {
-               device_printf(sc->sc_dev,
-                             "%s: tid=%d; txa_start=%d, old=%d, adjusting\n",
-                             __func__,
-                             tid,
-                             tap->txa_start,
-                             old_txa_start);
+               device_printf(sc->sc_dev, "%s: tid=%d; txa_start=%d, old=%d, adjusting\n",
+                   __func__,
+                   tid,
+                   tap->txa_start,
+                   old_txa_start);
        }
        tap->txa_start = old_txa_start;
+       ATH_TX_UNLOCK(sc);
 
        /* Unpause the TID */
        /*
@@ -6031,9 +6092,10 @@ ath_addba_response_timeout(struct ieee80211_node *ni,
        struct ath_tid *atid = &an->an_tid[tid];
 
        DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
-           "%s: %s: TID=%d, called; resuming\n",
+           "%s: %6D: TID=%d, called; resuming\n",
            __func__,
-           ath_hal_ether_sprintf(ni->ni_macaddr),
+           ni->ni_macaddr,
+           ":",
            tid);
 
        ATH_TX_LOCK(sc);
@@ -6093,8 +6155,8 @@ ath_tx_node_sleep(struct ath_softc *sc, struct ath_node *an)
 
        if (an->an_is_powersave) {
                DPRINTF(sc, ATH_DEBUG_XMIT,
-                   "%s: %s: node was already asleep!\n",
-                   __func__, ath_hal_ether_sprintf(an->an_node.ni_macaddr));
+                   "%s: %6D: node was already asleep!\n",
+                   __func__, an->an_node.ni_macaddr, ":");
                ATH_TX_UNLOCK(sc);
                return;
        }
index 0f13ae2..0edc170 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -465,8 +466,7 @@ ath_edma_setup_txfifo(struct ath_softc *sc, int qnum)
        struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum];
 
        te->m_fifo = kmalloc(sizeof(struct ath_buf *) * HAL_TXFIFO_DEPTH,
-           M_ATHDEV,
-           M_INTWAIT | M_ZERO);
+                            M_ATHDEV, M_INTWAIT | M_ZERO);
        if (te->m_fifo == NULL) {
                device_printf(sc->sc_dev, "%s: malloc failed\n",
                    __func__);
@@ -534,9 +534,7 @@ ath_edma_dma_txteardown(struct ath_softc *sc)
 static void
 ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
 {
-#if 0
        struct ifnet *ifp = sc->sc_ifp;
-#endif
        int i;
 
        DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
@@ -578,12 +576,13 @@ ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
 
        /* XXX dump out the frames */
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        IF_LOCK(&ifp->if_snd);
+#if defined(__DragonFly__)
        ifq_clr_oactive(&ifp->if_snd);
-       IF_UNLOCK(&ifp->if_snd);
+#else
+       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 #endif
+       IF_UNLOCK(&ifp->if_snd);
        sc->sc_wd_timer = 0;
 }
 
@@ -600,9 +599,7 @@ ath_edma_tx_proc(void *arg, int npending)
        DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: called, npending=%d\n",
            __func__, npending);
 #endif
-       wlan_serialize_enter();
        ath_edma_tx_processq(sc, 1);
-       wlan_serialize_exit();
 }
 
 /*
@@ -838,14 +835,15 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
 
        sc->sc_wd_timer = 0;
 
-#if 0
-       /* remove, DragonFly uses OACTIVE to control if_start calls */
        if (idx > 0) {
                IF_LOCK(&sc->sc_ifp->if_snd);
+#if defined(__DragonFly__)
                ifq_clr_oactive(&sc->sc_ifp->if_snd);
+#else
+               sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+#endif
                IF_UNLOCK(&sc->sc_ifp->if_snd);
        }
-#endif
 
        /* Kick software scheduler */
        /*
@@ -873,12 +871,14 @@ ath_xmit_setup_edma(struct ath_softc *sc)
        (void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen);
        (void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps);
 
-       device_printf(sc->sc_dev, "TX descriptor length: %d\n",
-           sc->sc_tx_desclen);
-       device_printf(sc->sc_dev, "TX status length: %d\n",
-           sc->sc_tx_statuslen);
-       device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n",
-           sc->sc_tx_nmaps);
+       if (bootverbose) {
+               device_printf(sc->sc_dev, "TX descriptor length: %d\n",
+                   sc->sc_tx_desclen);
+               device_printf(sc->sc_dev, "TX status length: %d\n",
+                   sc->sc_tx_statuslen);
+               device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n",
+                   sc->sc_tx_nmaps);
+       }
 
        sc->sc_tx.xmit_setup = ath_edma_dma_txsetup;
        sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown;
index 1bc062e..b4f4b0d 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 #include "opt_inet.h"
 #include "opt_ath.h"
@@ -83,7 +84,7 @@
 #include <dev/netif/ath/ath_tx99/ath_tx99.h>
 #endif
 
-#include <dev/netif/ath/ath/if_ath_tx.h>  /* XXX for some support functions */
+#include <dev/netif/ath/ath/if_ath_tx.h>               /* XXX for some support functions */
 #include <dev/netif/ath/ath/if_ath_tx_ht.h>
 #include <dev/netif/ath/ath/if_athrate.h>
 #include <dev/netif/ath/ath/if_ath_debug.h>
index 83b48b1..a95504e 100644 (file)
 
 #define        ATH_TIMEOUT             1000
 
+#if defined(__DragonFly__)
+#define ATH_ENABLE_11N
+#endif
+
 /*
  * There is a separate TX ath_buf pool for management frames.
  * This ensures that management frames such as probe responses
  */
 #define        ATH_MGMT_TXBUF          32
 
-#ifndef ATH_RXBUF
+/*
+ * 802.11n requires more TX and RX buffers to do AMPDU.
+ */
 #ifdef ATH_ENABLE_11N
-#define        ATH_RXBUF       512             /* 802.11n requires more buffers to do AMPDU. */
-#elif defined(__DragonFly__)
-#define        ATH_RXBUF       256             /* a default of 40 RXBUFs is not enough */
-#else
-#define        ATH_RXBUF       40              /* number of RX buffers */
+#define        ATH_TXBUF       512
+#define        ATH_RXBUF       512
 #endif
+
+#ifndef ATH_RXBUF
+#define        ATH_RXBUF       40              /* number of RX buffers */
 #endif
 #ifndef ATH_TXBUF
-#ifdef ATH_ENABLE_11N
-#define        ATH_TXBUF       512             /* 802.11n requires more buffers to do AMPDU. */
-#elif defined(__DragonFly__)
-#define        ATH_TXBUF       256             /* a default of 40 RXBUFs is not enough */
-#else
 #define        ATH_TXBUF       200             /* number of TX buffers */
 #endif
-#endif
 #define        ATH_BCBUF       4               /* number of beacon buffers */
 
 #define        ATH_TXDESC      10              /* number of descriptors per buffer */
 #define        ATH_BEACON_CWMIN_DEFAULT 0      /* default cwmin for ap beacon q */
 #define        ATH_BEACON_CWMAX_DEFAULT 0      /* default cwmax for ap beacon q */
 
+/*
+ * The following bits can be set during the PCI (and perhaps non-PCI
+ * later) device probe path.
+ *
+ * It controls some of the driver and HAL behaviour.
+ */
+
+#define        ATH_PCI_CUS198          0x0001
+#define        ATH_PCI_CUS230          0x0002
+#define        ATH_PCI_CUS217          0x0004
+#define        ATH_PCI_CUS252          0x0008
+#define        ATH_PCI_WOW             0x0010
+#define        ATH_PCI_BT_ANT_DIV      0x0020
+#define        ATH_PCI_D3_L1_WAR       0x0040
+#define        ATH_PCI_AR9565_1ANT     0x0080
+#define        ATH_PCI_AR9565_2ANT     0x0100
+#define        ATH_PCI_NO_PLL_PWRSAVE  0x0200
+#define        ATH_PCI_KILLER          0x0400
+
 /*
  * The key cache is used for h/w cipher state and also for
  * tracking station state such as the current tx antenna.
@@ -182,9 +201,7 @@ struct ath_node {
        struct ath_buf  *an_ff_buf[WME_NUM_AC]; /* ff staging area */
        struct ath_tid  an_tid[IEEE80211_TID_SIZE];     /* per-TID state */
        char            an_name[32];    /* eg "wlan0_a1" */
-#if 0
-       struct mtx      an_mtx;         /* protecting the rate control state */
-#endif
+       struct lock     an_mtx;         /* protecting the rate control state */
        uint32_t        an_swq_depth;   /* how many SWQ packets for this
                                           node */
        int                     clrdmask;       /* has clrdmask been set */
@@ -381,23 +398,22 @@ struct ath_txq {
        TAILQ_HEAD(axq_t_s,ath_tid)     axq_tidq;
 };
 
-#ifdef __DragonFly__
-/* already serialized by wlan_serializer */
-#define IF_LOCK(ifp)
-#define IF_UNLOCK(ifp)
-#endif
+#define        ATH_TXQ_LOCK_INIT(_sc, _tq) do { \
+           ksnprintf((_tq)->axq_name, sizeof((_tq)->axq_name), "%s_txq%u", \
+             device_get_nameunit((_sc)->sc_dev), (_tq)->axq_qnum); \
+           lockinit(&(_tq)->axq_lock, (_tq)->axq_name, 0, 0); \
+       } while (0)
+#define        ATH_TXQ_LOCK_DESTROY(_tq)       lockuninit(&(_tq)->axq_lock)
+#define        ATH_TXQ_LOCK(_tq)               lockmgr(&(_tq)->axq_lock, LK_EXCLUSIVE)
+#define        ATH_TXQ_UNLOCK(_tq)             lockmgr(&(_tq)->axq_lock, LK_RELEASE)
+#define        ATH_TXQ_LOCK_ASSERT(_tq)        KKASSERT(lockstatus(&(_tq)->axq_lock, curthread) == LK_EXCLUSIVE)
+#define        ATH_TXQ_UNLOCK_ASSERT(_tq)      KKASSERT(lockstatus(&(_tq)->axq_lock, curthread) != LK_EXCLUSIVE)
 
-#define        ATH_TXQ_LOCK_INIT(_sc, _tq)
-#define        ATH_TXQ_LOCK_DESTROY(_tq)
-#define        ATH_TXQ_LOCK(_tq)
-#define        ATH_TXQ_UNLOCK(_tq)
-#define        ATH_TXQ_LOCK_ASSERT(_tq)
-#define        ATH_TXQ_UNLOCK_ASSERT(_tq)
 
-#define        ATH_NODE_LOCK(_an)
-#define        ATH_NODE_UNLOCK(_an)
-#define        ATH_NODE_LOCK_ASSERT(_an)
-#define        ATH_NODE_UNLOCK_ASSERT(_an)
+#define        ATH_NODE_LOCK(_an)              lockmgr(&(_an)->an_mtx, LK_EXCLUSIVE)
+#define        ATH_NODE_UNLOCK(_an)            lockmgr(&(_an)->an_mtx, LK_RELEASE)
+#define        ATH_NODE_LOCK_ASSERT(_an)       KKASSERT(lockstatus(&(_an)->an_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_NODE_UNLOCK_ASSERT(_an)     KKASSERT(lockstatus(&(_an)->an_mtx, curthread) != LK_EXCLUSIVE)
 
 /*
  * These are for the hardware queue.
@@ -558,7 +574,6 @@ struct ath_softc {
        ath_bufhead             sc_rx_rxlist[HAL_NUM_RX_QUEUES];        /* deferred RX completion */
        struct ath_tx_methods   sc_tx;
        struct ath_tx_edma_fifo sc_txedma[HAL_NUM_TX_QUEUES];
-       enum { ATH_RXFIFO_RESET, ATH_RXFIFO_OK } sc_rxfifo_state;
 
        /*
         * This is (currently) protected by the TX queue lock;
@@ -572,6 +587,8 @@ struct ath_softc {
        int                     sc_tx_statuslen;
        int                     sc_tx_nmaps;    /* Number of TX maps */
        int                     sc_edma_bufsize;
+       int                     sc_rx_stopped;  /* XXX only for EDMA */
+       int                     sc_rx_resetted; /* XXX only for EDMA */
 
        void                    (*sc_node_cleanup)(struct ieee80211_node *);
        void                    (*sc_node_free)(struct ieee80211_node *);
@@ -579,17 +596,15 @@ struct ath_softc {
        HAL_BUS_TAG             sc_st;          /* bus space tag */
        HAL_BUS_HANDLE          sc_sh;          /* bus space handle */
        bus_dma_tag_t           sc_dmat;        /* bus DMA tag */
-#if 0
-       struct mtx              sc_mtx;         /* master lock (recursive) */
-       struct mtx              sc_pcu_mtx;     /* PCU access mutex */
+       struct lock             sc_mtx;         /* master lock (recursive) */
+       struct lock             sc_pcu_mtx;     /* PCU access mutex */
        char                    sc_pcu_mtx_name[32];
-       struct mtx              sc_rx_mtx;      /* RX access mutex */
+       struct lock             sc_rx_mtx;      /* RX access mutex */
        char                    sc_rx_mtx_name[32];
-       struct mtx              sc_tx_mtx;      /* TX handling/comp mutex */
+       struct lock             sc_tx_mtx;      /* TX handling/comp mutex */
        char                    sc_tx_mtx_name[32];
-       struct mtx              sc_tx_ic_mtx;   /* TX queue mutex */
+       struct lock             sc_tx_ic_mtx;   /* TX queue mutex */
        char                    sc_tx_ic_mtx_name[32];
-#endif
        struct taskqueue        *sc_tq;         /* private task queue */
        struct ath_hal          *sc_ah;         /* Atheros HAL */
        struct ath_ratectrl     *sc_rc;         /* tx rate control support */
@@ -737,10 +752,8 @@ struct ath_softc {
        struct ath_descdma      sc_txdma_mgmt;  /* mgmt TX descriptors */
        ath_bufhead             sc_txbuf_mgmt;  /* mgmt transmit buffer */
        struct ath_descdma      sc_txsdma;      /* EDMA TX status desc's */
-#if 0
-       struct mtx              sc_txbuflock;   /* txbuf lock */
+       struct lock             sc_txbuflock;   /* txbuf lock */
        char                    sc_txname[12];  /* e.g. "ath0_buf" */
-#endif
        u_int                   sc_txqsetup;    /* h/w queues setup */
        u_int                   sc_txintrperiod;/* tx interrupt batching */
        struct ath_txq          sc_txq[HAL_NUM_TX_QUEUES];
@@ -749,10 +762,8 @@ struct ath_softc {
        struct task             sc_txqtask;     /* tx proc processing */
 
        struct ath_descdma      sc_txcompdma;   /* TX EDMA completion */
-#if 0
-       struct mtx              sc_txcomplock;  /* TX EDMA completion lock */
+       struct lock             sc_txcomplock;  /* TX EDMA completion lock */
        char                    sc_txcompname[12];      /* eg ath0_txcomp */
-#endif
 
        int                     sc_wd_timer;    /* count down for wd timer */
        struct callout          sc_wd_ch;       /* tx watchdog timer */
@@ -894,37 +905,55 @@ struct ath_softc {
        HAL_POWER_MODE          sc_cur_powerstate;
 
        int                     sc_powersave_refcnt;
+
+       /* ATH_PCI_* flags */
+       uint32_t                sc_pci_devinfo;
 };
 
-#define        ATH_LOCK_INIT(_sc)
-#define        ATH_LOCK_DESTROY(_sc)
-#define        ATH_LOCK(_sc)
-#define        ATH_UNLOCK(_sc)
-#define        ATH_LOCK_ASSERT(_sc)
-#define        ATH_UNLOCK_ASSERT(_sc)
+#define        ATH_LOCK_INIT(_sc) \
+       lockinit(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
+                0, LK_CANRECURSE)
+#define        ATH_LOCK_DESTROY(_sc)   lockuninit(&(_sc)->sc_mtx)
+#define        ATH_LOCK(_sc)           lockmgr(&(_sc)->sc_mtx, LK_EXCLUSIVE)
+#define        ATH_UNLOCK(_sc)         lockmgr(&(_sc)->sc_mtx, LK_RELEASE)
+#define        ATH_LOCK_ASSERT(_sc)    KKASSERT(lockstatus(&(_sc)->sc_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_UNLOCK_ASSERT(_sc)  KKASSERT(lockstatus(&(_sc)->sc_mtx, curthread) != LK_EXCLUSIVE)
 
 /*
  * The TX lock is non-reentrant and serialises the TX frame send
  * and completion operations.
  */
-#define        ATH_TX_LOCK_INIT(_sc)
-#define        ATH_TX_LOCK_DESTROY(_sc)
-#define        ATH_TX_LOCK(_sc)
-#define        ATH_TX_UNLOCK(_sc)
-#define        ATH_TX_LOCK_ASSERT(_sc)
-#define        ATH_TX_UNLOCK_ASSERT(_sc)
-/* #define ATH_TX_TRYLOCK(_sc) removed */
+#define        ATH_TX_LOCK_INIT(_sc) do {\
+       ksnprintf((_sc)->sc_tx_mtx_name,                                \
+           sizeof((_sc)->sc_tx_mtx_name),                              \
+           "%s TX lock",                                               \
+           device_get_nameunit((_sc)->sc_dev));                        \
+       lockinit(&(_sc)->sc_tx_mtx, (_sc)->sc_tx_mtx_name,              \
+                0, 0);                                                 \
+       } while (0)
+#define        ATH_TX_LOCK_DESTROY(_sc)        lockuninit(&(_sc)->sc_tx_mtx)
+#define        ATH_TX_LOCK(_sc)                lockmgr(&(_sc)->sc_tx_mtx, LK_EXCLUSIVE)
+#define        ATH_TX_UNLOCK(_sc)              lockmgr(&(_sc)->sc_tx_mtx, LK_RELEASE)
+#define        ATH_TX_LOCK_ASSERT(_sc)         KKASSERT(lockstatus(&(_sc)->sc_tx_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_TX_UNLOCK_ASSERT(_sc)       KKASSERT(lockstatus(&(_sc)->sc_tx_mtx, curthread) != LK_EXCLUSIVE)
 
 /*
  * The IC TX lock is non-reentrant and serialises packet queuing from
  * the upper layers.
  */
-#define        ATH_TX_IC_LOCK_INIT(_sc)
-#define        ATH_TX_IC_LOCK_DESTROY(_sc)
-#define        ATH_TX_IC_LOCK(_sc)
-#define        ATH_TX_IC_UNLOCK(_sc)
-#define        ATH_TX_IC_LOCK_ASSERT(_sc)
-#define        ATH_TX_IC_UNLOCK_ASSERT(_sc)
+#define        ATH_TX_IC_LOCK_INIT(_sc) do {\
+       ksnprintf((_sc)->sc_tx_ic_mtx_name,                             \
+           sizeof((_sc)->sc_tx_ic_mtx_name),                           \
+           "%s IC TX lock",                                            \
+           device_get_nameunit((_sc)->sc_dev));                        \
+       lockinit(&(_sc)->sc_tx_ic_mtx, (_sc)->sc_tx_ic_mtx_name,        \
+                0, 0);                                                 \
+       } while (0)
+#define        ATH_TX_IC_LOCK_DESTROY(_sc)     lockuninit(&(_sc)->sc_tx_ic_mtx)
+#define        ATH_TX_IC_LOCK(_sc)             lockmgr(&(_sc)->sc_tx_ic_mtx, LK_EXCLUSIVE)
+#define        ATH_TX_IC_UNLOCK(_sc)           lockmgr(&(_sc)->sc_tx_ic_mtx, LK_RELEASE)
+#define        ATH_TX_IC_LOCK_ASSERT(_sc)      KKASSERT(lockstatus(&(_sc)->sc_tx_ic_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_TX_IC_UNLOCK_ASSERT(_sc)    KKASSERT(lockstatus(&(_sc)->sc_tx_ic_mtx, curthread) != LK_EXCLUSIVE)
 
 /*
  * The PCU lock is non-recursive and should be treated as a spinlock.
@@ -943,12 +972,19 @@ struct ath_softc {
  * (which only acquires ATH_LOCK when recycling buffers to the free list),
  * ath_set_channel, the channel scanning API and perhaps quite a bit more.
  */
-#define        ATH_PCU_LOCK_INIT(_sc)
-#define        ATH_PCU_LOCK_DESTROY(_sc)
-#define        ATH_PCU_LOCK(_sc)
-#define        ATH_PCU_UNLOCK(_sc)
-#define        ATH_PCU_LOCK_ASSERT(_sc)
-#define        ATH_PCU_UNLOCK_ASSERT(_sc)
+#define        ATH_PCU_LOCK_INIT(_sc) do {\
+       ksnprintf((_sc)->sc_pcu_mtx_name,                               \
+           sizeof((_sc)->sc_pcu_mtx_name),                             \
+           "%s PCU lock",                                              \
+           device_get_nameunit((_sc)->sc_dev));                        \
+       lockinit(&(_sc)->sc_pcu_mtx, (_sc)->sc_pcu_mtx_name,            \
+                0, 0);                                         \
+       } while (0)
+#define        ATH_PCU_LOCK_DESTROY(_sc)       lockuninit(&(_sc)->sc_pcu_mtx)
+#define        ATH_PCU_LOCK(_sc)               lockmgr(&(_sc)->sc_pcu_mtx, LK_EXCLUSIVE)
+#define        ATH_PCU_UNLOCK(_sc)             lockmgr(&(_sc)->sc_pcu_mtx, LK_RELEASE)
+#define        ATH_PCU_LOCK_ASSERT(_sc)        KKASSERT(lockstatus(&(_sc)->sc_pcu_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_PCU_UNLOCK_ASSERT(_sc)      KKASSERT(lockstatus(&(_sc)->sc_pcu_mtx, curthread) != LK_EXCLUSIVE)
 
 /*
  * The RX lock is primarily a(nother) workaround to ensure that the
@@ -956,27 +992,47 @@ struct ath_softc {
  * Even though RX occurs in a single context (the ath taskqueue), the
  * RX path can be executed via various reset/channel change paths.
  */
-#define        ATH_RX_LOCK_INIT(_sc)
-#define        ATH_RX_LOCK_DESTROY(_sc)
-#define        ATH_RX_LOCK(_sc)
-#define        ATH_RX_UNLOCK(_sc)
-#define        ATH_RX_LOCK_ASSERT(_sc)
-#define        ATH_RX_UNLOCK_ASSERT(_sc)
+#define        ATH_RX_LOCK_INIT(_sc) do {\
+       ksnprintf((_sc)->sc_rx_mtx_name,                                        \
+           sizeof((_sc)->sc_rx_mtx_name),                              \
+           "%s RX lock",                                               \
+           device_get_nameunit((_sc)->sc_dev));                        \
+       lockinit(&(_sc)->sc_rx_mtx, (_sc)->sc_rx_mtx_name,              \
+                0, 0);                                 \
+       } while (0)
+#define        ATH_RX_LOCK_DESTROY(_sc)        lockuninit(&(_sc)->sc_rx_mtx)
+#define        ATH_RX_LOCK(_sc)                lockmgr(&(_sc)->sc_rx_mtx, LK_EXCLUSIVE)
+#define        ATH_RX_UNLOCK(_sc)              lockmgr(&(_sc)->sc_rx_mtx, LK_RELEASE)
+#define        ATH_RX_LOCK_ASSERT(_sc)         KKASSERT(lockstatus(&(_sc)->sc_rx_mtx, curthread) == LK_EXCLUSIVE)
+#define        ATH_RX_UNLOCK_ASSERT(_sc)       KKASSERT(lockstatus(&(_sc)->sc_rx_mtx, curthread) != LK_EXCLUSIVE)
 
 #define        ATH_TXQ_SETUP(sc, i)    ((sc)->sc_txqsetup & (1<<i))
 
-#define        ATH_TXBUF_LOCK_INIT(_sc)
-#define        ATH_TXBUF_LOCK_DESTROY(_sc)
-#define        ATH_TXBUF_LOCK(_sc)
-#define        ATH_TXBUF_UNLOCK(_sc)
-#define        ATH_TXBUF_LOCK_ASSERT(_sc)
-#define        ATH_TXBUF_UNLOCK_ASSERT(_sc)
-
-#define        ATH_TXSTATUS_LOCK_INIT(_sc)
-#define        ATH_TXSTATUS_LOCK_DESTROY(_sc)
-#define        ATH_TXSTATUS_LOCK(_sc)
-#define        ATH_TXSTATUS_UNLOCK(_sc)
-#define        ATH_TXSTATUS_LOCK_ASSERT(_sc)
+#define        ATH_TXBUF_LOCK_INIT(_sc) do { \
+       ksnprintf((_sc)->sc_txname, sizeof((_sc)->sc_txname), "%s_buf", \
+               device_get_nameunit((_sc)->sc_dev)); \
+       lockinit(&(_sc)->sc_txbuflock, (_sc)->sc_txname, 0, 0); \
+} while (0)
+#define        ATH_TXBUF_LOCK_DESTROY(_sc)     lockuninit(&(_sc)->sc_txbuflock)
+#define        ATH_TXBUF_LOCK(_sc)             lockmgr(&(_sc)->sc_txbuflock, LK_EXCLUSIVE)
+#define        ATH_TXBUF_UNLOCK(_sc)           lockmgr(&(_sc)->sc_txbuflock, LK_RELEASE)
+#define        ATH_TXBUF_LOCK_ASSERT(_sc) \
+       KKASSERT(lockstatus(&(_sc)->sc_txbuflock, curthread) == LK_EXCLUSIVE)
+#define        ATH_TXBUF_UNLOCK_ASSERT(_sc) \
+       KKASSERT(lockstatus(&(_sc)->sc_txbuflock, curthread) != LK_EXCLUSIVE)
+
+#define        ATH_TXSTATUS_LOCK_INIT(_sc) do { \
+       ksnprintf((_sc)->sc_txcompname, sizeof((_sc)->sc_txcompname), \
+               "%s_buf", \
+               device_get_nameunit((_sc)->sc_dev)); \
+       lockinit(&(_sc)->sc_txcomplock, (_sc)->sc_txcompname, 0, \
+               0); \
+} while (0)
+#define        ATH_TXSTATUS_LOCK_DESTROY(_sc)  lockuninit(&(_sc)->sc_txcomplock)
+#define        ATH_TXSTATUS_LOCK(_sc)          lockmgr(&(_sc)->sc_txcomplock, LK_EXCLUSIVE)
+#define        ATH_TXSTATUS_UNLOCK(_sc)        lockmgr(&(_sc)->sc_txcomplock, LK_RELEASE)
+#define        ATH_TXSTATUS_LOCK_ASSERT(_sc) \
+       KKASSERT(lockstatus(&(_sc)->sc_txcomplock, curthread) == LK_EXCLUSIVE)
 
 int    ath_attach(u_int16_t, struct ath_softc *);
 int    ath_detach(struct ath_softc *);
@@ -985,6 +1041,13 @@ void      ath_suspend(struct ath_softc *);
 void   ath_shutdown(struct ath_softc *);
 void   ath_intr(void *);
 
+#if defined(__DragonFly__)
+
+#define IF_LOCK(ifsnd)         /* XXX */
+#define IF_UNLOCK(ifsnd)       /* XXX */
+
+#endif
+
 /*
  * HAL definitions to comply with local coding convention.
  */
@@ -1282,8 +1345,8 @@ void      ath_intr(void *);
        (ath_hal_getcapability(_ah, HAL_CAP_RXSTATUSLEN, 0, _req)       \
        == HAL_OK)
 #define        ath_hal_setrxbufsize(_ah, _req) \
-       (ath_hal_setcapability(_ah, HAL_CAP_RXBUFSIZE, 0, _req, NULL)   \
-       == AH_TRUE)
+       ((int)ath_hal_setcapability(_ah, HAL_CAP_RXBUFSIZE, 0, _req, NULL) \
+       == HAL_OK)
 
 #define        ath_hal_getchannoise(_ah, _c) \
        ((*(_ah)->ah_getChanNoise)((_ah), (_c)))
index 8c43a2d..3151d91 100644 (file)
@@ -29,6 +29,7 @@
  * $FreeBSD$
  */
 #include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * This implements an empty DFS module.
@@ -45,7 +46,9 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/errno.h>
+
 #include <sys/bus.h>
+
 #include <sys/socket.h>
  
 #include <net/if.h>
@@ -295,33 +298,33 @@ ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param)
 static int
 null_dfs_modevent(module_t mod, int type, void *unused)
 {
-        int error;
-
-        wlan_serialize_enter();
-
-        switch (type) {
-        case MOD_LOAD:
-                if (bootverbose) {
-                        kprintf("ath_dfs: WTF module\n");
-                }
-                error = 0;
-                break;
-        case MOD_UNLOAD:
-                error = 0;
-                break;
-        default:
-                error = EINVAL;
-                break;
-        }
-        wlan_serialize_exit();
-
-        return error;
+       int error;
+
+       wlan_serialize_enter();
+
+       switch (type) {
+       case MOD_LOAD:
+               if (bootverbose) {
+                       kprintf("ath_dfs: WTF module\n");
+               }
+               error = 0;
+               break;
+       case MOD_UNLOAD:
+               error = 0;
+               break;
+       default:
+               error = EINVAL;
+               break;
+       }
+       wlan_serialize_exit();
+
+       return error;
 }
 
 static moduledata_t null_dfs_mod = {
-        "ath_dfs",
-        null_dfs_modevent,
-        0
+       "ath_dfs",
+       null_dfs_modevent,
+       0
 };
 
 DECLARE_MODULE(ath_dfs, null_dfs_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
index bbfc09b..2aefc89 100644 (file)
@@ -55,7 +55,9 @@ ath_hal_probe(uint16_t vendorid, uint16_t devid)
  */
 struct ath_hal*
 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
-       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *error)
+       HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+       HAL_OPS_CONFIG *ah_config,
+       HAL_STATUS *error)
 {
        struct ath_hal_chip * const *pchip;
 
@@ -66,7 +68,8 @@ ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
                /* XXX don't have vendorid, assume atheros one works */
                if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
                        continue;
-               ah = chip->attach(devid, sc, st, sh, eepromdata, error);
+               ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
+                   error);
                if (ah != AH_NULL) {
                        /* copy back private state to public area */
                        ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
@@ -850,10 +853,11 @@ ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
        int i;
 
        for (i = 0; space >= 2*sizeof(uint32_t); i++) {
-               u_int r = regs[i].start;
-               u_int e = regs[i].end;
-               *dp++ = (r<<16) | e;
-               space -= sizeof(uint32_t);
+               uint32_t r = regs[i].start;
+               uint32_t e = regs[i].end;
+               *dp++ = r;
+               *dp++ = e;
+               space -= 2*sizeof(uint32_t);
                do {
                        *dp++ = OS_REG_READ(ah, r);
                        r += sizeof(uint32_t);
index 4f2d3e9..67881a3 100644 (file)
@@ -1264,6 +1264,7 @@ typedef struct
        int ath_hal_show_bb_panic;
        int ath_hal_ant_ctrl_comm2g_switch_enable;
        int ath_hal_ext_atten_margin_cfg;
+       int ath_hal_min_gainidx;
        int ath_hal_war70c;
        uint32_t ath_hal_mci_config;
 } HAL_OPS_CONFIG;
@@ -1588,6 +1589,18 @@ struct ath_hal {
        void        __ahdecl(*ah_btCoexDisable)(struct ath_hal *);
        int         __ahdecl(*ah_btCoexEnable)(struct ath_hal *);
 
+       /* Bluetooth MCI methods */
+       void        __ahdecl(*ah_btMciSetup)(struct ath_hal *,
+                               uint32_t, void *, uint16_t, uint32_t);
+       HAL_BOOL    __ahdecl(*ah_btMciSendMessage)(struct ath_hal *,
+                               uint8_t, uint32_t, uint32_t *, uint8_t,
+                               HAL_BOOL, HAL_BOOL);
+&n