summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Smith <mgsmith@netgate.com>2015-11-18 10:33:06 -0600
committerMatt Smith <mgsmith@netgate.com>2015-11-18 10:33:06 -0600
commita5d857c46178a8f007d57d8c9464f87be6cff363 (patch)
tree8a2a2ea905626a6a15e41b022fb9b917ba3670ad
parent86a5f7f4a9d06ce713d5b0f97c87b33683d3fce6 (diff)
downloadFreeBSD-src-a5d857c46178a8f007d57d8c9464f87be6cff363.zip
FreeBSD-src-a5d857c46178a8f007d57d8c9464f87be6cff363.tar.gz
Importing pfSense patch HEAD-wireless-ath.tgz
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h45
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c38
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c60
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c11
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c186
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c137
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h3
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h5
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c13
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c15
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c153
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c128
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini4
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c18
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c5
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c14
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c239
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c2
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c92
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c7
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h8
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini8
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini8
-rw-r--r--sys/dev/ath/ah_osdep.c51
-rw-r--r--sys/dev/ath/ah_osdep.h2
-rw-r--r--sys/dev/ath/ath_dfs/null/dfs_null.c6
-rw-r--r--sys/dev/ath/ath_hal/ah.c54
-rw-r--r--sys/dev/ath/ath_hal/ah.h66
-rw-r--r--sys/dev/ath/ath_hal/ah_debug.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_decode.h5
-rw-r--r--sys/dev/ath/ath_hal/ah_desc.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_devid.h3
-rw-r--r--sys/dev/ath/ath_hal/ah_diagcodes.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_9287.c2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_9287.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v1.c2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v1.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.c2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v3.c2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v3.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v4k.c2
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v4k.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h30
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain.c7
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h3
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_soc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210.h5
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_attach.c6
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_misc.c3
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_power.c14
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_recv.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_reset.c6
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210desc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211.h3
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_attach.c4
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_misc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_power.c14
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_recv.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_reset.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211desc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5211/boss.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar2316.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar2317.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar2413.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar2425.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5111.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5112.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212.h13
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_ani.c15
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_attach.c4
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_misc.c20
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_power.c12
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_recv.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_reset.c13
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212desc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5311reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5413.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_attach.c4
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_misc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_power.c7
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_reset.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar2133.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_ani.c15
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c9
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c28
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal.c5
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c5
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_misc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_power.c15
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_radar.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_recv.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_reset.c5
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416desc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416reg.h6
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_attach.c6
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130reg.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9160.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9160_attach.c3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9002phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_attach.c3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_olc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_olc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280v1.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280v2.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_attach.c3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_cal.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_cal.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_phy.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_reset.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285an.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285v2.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_attach.c3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_cal.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_cal.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_olc.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_olc.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_reset.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_reset.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287an.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287phy.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h2
-rw-r--r--sys/dev/ath/ath_hal/ar9003/ar9300_devid.h2
-rw-r--r--sys/dev/ath/ath_rate/amrr/amrr.c2
-rw-r--r--sys/dev/ath/ath_rate/amrr/amrr.h2
-rw-r--r--sys/dev/ath/ath_rate/onoe/onoe.c2
-rw-r--r--sys/dev/ath/ath_rate/onoe/onoe.h2
-rw-r--r--sys/dev/ath/ath_rate/sample/sample.c8
-rw-r--r--sys/dev/ath/ath_rate/sample/sample.h4
-rw-r--r--sys/dev/ath/ath_rate/sample/tx_schedules.h2
-rw-r--r--sys/dev/ath/if_ath.c925
-rw-r--r--sys/dev/ath/if_ath_ahb.c26
-rw-r--r--sys/dev/ath/if_ath_alq.c2
-rw-r--r--sys/dev/ath/if_ath_alq.h2
-rw-r--r--sys/dev/ath/if_ath_beacon.c95
-rw-r--r--sys/dev/ath/if_ath_beacon.h4
-rw-r--r--sys/dev/ath/if_ath_btcoex.c74
-rw-r--r--sys/dev/ath/if_ath_btcoex.h2
-rw-r--r--sys/dev/ath/if_ath_debug.c5
-rw-r--r--sys/dev/ath/if_ath_debug.h3
-rw-r--r--sys/dev/ath/if_ath_keycache.c19
-rw-r--r--sys/dev/ath/if_ath_keycache.h2
-rw-r--r--sys/dev/ath/if_ath_led.c11
-rw-r--r--sys/dev/ath/if_ath_led.h2
-rw-r--r--sys/dev/ath/if_ath_lna_div.c10
-rw-r--r--sys/dev/ath/if_ath_lna_div.h2
-rw-r--r--sys/dev/ath/if_ath_misc.h15
-rw-r--r--sys/dev/ath/if_ath_pci.c140
-rw-r--r--sys/dev/ath/if_ath_pci_devlist.h669
-rw-r--r--sys/dev/ath/if_ath_rx.c248
-rw-r--r--sys/dev/ath/if_ath_rx.h2
-rw-r--r--sys/dev/ath/if_ath_rx_edma.c177
-rw-r--r--sys/dev/ath/if_ath_rx_edma.h2
-rw-r--r--sys/dev/ath/if_ath_spectral.c6
-rw-r--r--sys/dev/ath/if_ath_spectral.h2
-rw-r--r--sys/dev/ath/if_ath_sysctl.c38
-rw-r--r--sys/dev/ath/if_ath_sysctl.h2
-rw-r--r--sys/dev/ath/if_ath_tdma.c18
-rw-r--r--sys/dev/ath/if_ath_tdma.h2
-rw-r--r--sys/dev/ath/if_ath_tsf.h2
-rw-r--r--sys/dev/ath/if_ath_tx.c420
-rw-r--r--sys/dev/ath/if_ath_tx.h2
-rw-r--r--sys/dev/ath/if_ath_tx_edma.c17
-rw-r--r--sys/dev/ath/if_ath_tx_edma.h2
-rw-r--r--sys/dev/ath/if_ath_tx_ht.c2
-rw-r--r--sys/dev/ath/if_ath_tx_ht.h2
-rw-r--r--sys/dev/ath/if_athdfs.h2
-rw-r--r--sys/dev/ath/if_athioctl.h2
-rw-r--r--sys/dev/ath/if_athrate.h2
-rw-r--r--sys/dev/ath/if_athvar.h50
-rw-r--r--sys/dev/iwn/if_iwn.c2034
-rw-r--r--sys/dev/iwn/if_iwn_chip_cfg.h413
-rw-r--r--sys/dev/iwn/if_iwn_debug.h123
-rw-r--r--sys/dev/iwn/if_iwn_devid.h39
-rw-r--r--sys/dev/iwn/if_iwn_ioctl.h25
-rw-r--r--sys/dev/iwn/if_iwnreg.h326
-rw-r--r--sys/dev/iwn/if_iwnvar.h36
-rw-r--r--sys/net80211/ieee80211.c36
-rw-r--r--sys/net80211/ieee80211_action.c1
-rw-r--r--sys/net80211/ieee80211_adhoc.c1
-rw-r--r--sys/net80211/ieee80211_ageq.c1
-rw-r--r--sys/net80211/ieee80211_alq.c4
-rw-r--r--sys/net80211/ieee80211_amrr.c23
-rw-r--r--sys/net80211/ieee80211_ddb.c1
-rw-r--r--sys/net80211/ieee80211_dfs.c2
-rw-r--r--sys/net80211/ieee80211_freebsd.c1
-rw-r--r--sys/net80211/ieee80211_hostap.c1
-rw-r--r--sys/net80211/ieee80211_ht.c12
-rw-r--r--sys/net80211/ieee80211_hwmp.c2
-rw-r--r--sys/net80211/ieee80211_input.c1
-rw-r--r--sys/net80211/ieee80211_ioctl.c39
-rw-r--r--sys/net80211/ieee80211_mesh.c9
-rw-r--r--sys/net80211/ieee80211_monitor.c1
-rw-r--r--sys/net80211/ieee80211_node.c1
-rw-r--r--sys/net80211/ieee80211_output.c57
-rw-r--r--sys/net80211/ieee80211_phy.c4
-rw-r--r--sys/net80211/ieee80211_power.c106
-rw-r--r--sys/net80211/ieee80211_power.h3
-rw-r--r--sys/net80211/ieee80211_proto.c1
-rw-r--r--sys/net80211/ieee80211_proto.h1
-rw-r--r--sys/net80211/ieee80211_radiotap.c2
-rw-r--r--sys/net80211/ieee80211_ratectl.c3
-rw-r--r--sys/net80211/ieee80211_ratectl.h12
-rw-r--r--sys/net80211/ieee80211_ratectl_none.c3
-rw-r--r--sys/net80211/ieee80211_regdomain.c3
-rw-r--r--sys/net80211/ieee80211_rssadapt.c4
-rw-r--r--sys/net80211/ieee80211_scan.c675
-rw-r--r--sys/net80211/ieee80211_scan.h14
-rw-r--r--sys/net80211/ieee80211_scan_sta.c13
-rw-r--r--sys/net80211/ieee80211_scan_sw.c872
-rw-r--r--sys/net80211/ieee80211_scan_sw.h60
-rw-r--r--sys/net80211/ieee80211_sta.c82
-rw-r--r--sys/net80211/ieee80211_superg.c7
-rw-r--r--sys/net80211/ieee80211_var.h2
-rw-r--r--sys/net80211/ieee80211_wds.c1
287 files changed, 8168 insertions, 1860 deletions
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
index 73b902f..e63b517 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
@@ -185,6 +185,8 @@ struct ar9300_ani_state {
int32_t rssi; /* The current RSSI */
u_int32_t tx_frame_count; /* Last tx_frame_count */
u_int32_t rx_frame_count; /* Last rx Frame count */
+ u_int32_t rx_busy_count; /* Last rx busy count */
+ u_int32_t rx_ext_busy_count; /* Last rx busy count; extension channel */
u_int32_t cycle_count; /* Last cycle_count (can detect wrap-around) */
u_int32_t ofdm_phy_err_count;/* OFDM err count since last reset */
u_int32_t cck_phy_err_count; /* CCK err count since last reset */
@@ -204,6 +206,7 @@ struct ar9300_ani_state {
#define DO_ANI(ah) \
((AH9300(ah)->ah_proc_phy_err & HAL_PROCESS_ANI))
+#if 0
struct ar9300_stats {
u_int32_t ast_ani_niup; /* ANI increased noise immunity */
u_int32_t ast_ani_nidown; /* ANI decreased noise immunity */
@@ -223,6 +226,7 @@ struct ar9300_stats {
HAL_MIB_STATS ast_mibstats; /* MIB counter stats */
HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */
};
+#endif
struct ar9300_rad_reader {
u_int16_t rd_index;
@@ -317,12 +321,12 @@ typedef struct {
/* Support for multiple INIs */
struct ar9300_ini_array {
- u_int32_t *ia_array;
+ const u_int32_t *ia_array;
u_int32_t ia_rows;
u_int32_t ia_columns;
};
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
- (iniarray)->ia_array = (u_int32_t *)(array); \
+ (iniarray)->ia_array = (const u_int32_t *)(array); \
(iniarray)->ia_rows = (rows); \
(iniarray)->ia_columns = (columns); \
} while (0)
@@ -429,7 +433,7 @@ struct ath_hal_9300 {
u_int32_t ah_mask2Reg; /* copy of AR_IMR_S2 */
u_int32_t ah_msi_reg; /* copy of AR_PCIE_MSI */
os_atomic_t ah_ier_ref_count; /* reference count for enabling interrupts */
- struct ar9300_stats ah_stats; /* various statistics */
+ HAL_ANI_STATS ah_stats; /* various statistics */
RF_HAL_FUNCS ah_rf_hal;
u_int32_t ah_tx_desc_mask; /* mask for TXDESC */
u_int32_t ah_tx_ok_interrupt_mask;
@@ -576,6 +580,9 @@ struct ath_hal_9300 {
u_int8_t ah_tx_chainmask; /* tx chain mask */
u_int8_t ah_rx_chainmask; /* rx chain mask */
+ /* optional tx chainmask */
+ u_int8_t ah_tx_chainmaskopt;
+
u_int8_t ah_tx_cal_chainmask; /* tx cal chain mask */
u_int8_t ah_rx_cal_chainmask; /* rx cal chain mask */
@@ -845,6 +852,7 @@ struct ath_hal_9300 {
HAL_BOOL ah_aic_enabled;
u_int32_t ah_aic_sram[ATH_AIC_MAX_BT_CHANNEL];
#endif
+
#endif /* ATH_SUPPORT_MCI */
u_int8_t ah_cac_quiet_enabled;
#if ATH_WOW_OFFLOAD
@@ -852,6 +860,14 @@ struct ath_hal_9300 {
u_int32_t ah_mcast_filter_u32_set;
#endif
HAL_BOOL ah_reduced_self_gen_mask;
+ HAL_BOOL ah_chip_reset_done;
+ HAL_BOOL ah_abort_txdma_norx;
+ /* store previous passive RX Cal info */
+ HAL_BOOL ah_skip_rx_iq_cal;
+ HAL_BOOL ah_rx_cal_complete; /* previous rx cal completed or not */
+ u_int32_t ah_rx_cal_chan; /* chan on which rx cal is done */
+ u_int32_t ah_rx_cal_chan_flag;
+ u_int32_t ah_rx_cal_corr[AR9300_MAX_CHAINS];
/* Local additions for FreeBSD */
/*
@@ -873,11 +889,11 @@ struct ath_hal_9300 {
int ah_fccaifs;
int ah_reset_reason;
int ah_dcs_enable;
+ HAL_ANI_STATE ext_ani_state; /* FreeBSD; external facing ANI state */
struct ar9300NfLimits nf_2GHz;
struct ar9300NfLimits nf_5GHz;
struct ar9300NfLimits *nfp;
-
};
#define AH9300(_ah) ((struct ath_hal_9300 *)(_ah))
@@ -1181,10 +1197,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);
@@ -1193,7 +1210,8 @@ extern HAL_BOOL ar9300_get_channel_edges(struct ath_hal *ah,
extern HAL_BOOL ar9300_fill_capability_info(struct ath_hal *ah);
extern void ar9300_beacon_init(struct ath_hal *ah,
- u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode);
+ u_int32_t next_beacon, u_int32_t beacon_period,
+ u_int32_t beacon_period_fraction, HAL_OPMODE opmode);
extern void ar9300_set_sta_beacon_timers(struct ath_hal *ah,
const HAL_BEACON_STATE *);
@@ -1216,12 +1234,21 @@ extern HAL_BOOL ar9300_set_key_cache_entry_mac(struct ath_hal *,
extern HAL_BOOL ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
const HAL_KEYVAL *k, const u_int8_t *mac, int xor_key);
extern HAL_BOOL ar9300_print_keycache(struct ath_hal *ah);
+#if ATH_SUPPORT_KEYPLUMB_WAR
+extern HAL_BOOL ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
+ const HAL_KEYVAL *k, int xorKey);
+#endif
extern void ar9300_get_mac_address(struct ath_hal *ah, u_int8_t *mac);
extern HAL_BOOL ar9300_set_mac_address(struct ath_hal *ah, const u_int8_t *);
extern void ar9300_get_bss_id_mask(struct ath_hal *ah, u_int8_t *mac);
extern HAL_BOOL ar9300_set_bss_id_mask(struct ath_hal *, const u_int8_t *);
extern HAL_STATUS ar9300_select_ant_config(struct ath_hal *ah, u_int32_t cfg);
+#if 0
+extern u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz);
+#endif
+extern HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
+ u_int32_t *common_tbl1, u_int32_t *common_tbl2);
extern HAL_BOOL ar9300_set_regulatory_domain(struct ath_hal *ah,
u_int16_t reg_domain, HAL_STATUS *stats);
extern u_int ar9300_get_wireless_modes(struct ath_hal *ah);
@@ -1396,6 +1423,8 @@ extern HAL_BOOL ar9300_set_tx_power_limit(struct ath_hal *ah, u_int32_t limit,
u_int16_t extra_txpow, u_int16_t tpc_in_db);
extern void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf,
struct ieee80211_channel *chan, int is_scan);
+extern int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time);
+extern int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal);
extern HAL_BOOL ar9300_load_nf(struct ath_hal *ah, int16_t nf[]);
extern HAL_RFGAIN ar9300_get_rfgain(struct ath_hal *ah);
@@ -1417,7 +1446,7 @@ extern void ar9300_disable_mib_counters(struct ath_hal *);
extern void ar9300_ani_attach(struct ath_hal *);
extern void ar9300_ani_detach(struct ath_hal *);
extern struct ar9300_ani_state *ar9300_ani_get_current_state(struct ath_hal *);
-extern struct ar9300_stats *ar9300_ani_get_current_stats(struct ath_hal *);
+extern HAL_ANI_STATS *ar9300_ani_get_current_stats(struct ath_hal *);
extern HAL_BOOL ar9300_ani_control(struct ath_hal *, HAL_ANI_CMD cmd, int param);
struct ath_rx_status;
@@ -1680,6 +1709,8 @@ extern void ar9300_tx99_start(struct ath_hal *ah, u_int8_t *data);
extern void ar9300_tx99_stop(struct ath_hal *ah);
#endif /* ATH_SUPPORT_HTC */
#endif /* ATH_TX99_DIAG */
+extern HAL_BOOL ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array);
+extern void ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask);
enum {
AR9300_COEFF_TX_TYPE = 0,
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c
index b07ca71..9c2c3ed 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c
@@ -210,7 +210,7 @@ ar9300_ani_get_current_state(struct ath_hal *ah)
/*
* Return the current statistics.
*/
-struct ar9300_stats *
+HAL_ANI_STATS *
ar9300_ani_get_current_stats(struct ath_hal *ah)
{
return &AH9300(ah)->ah_stats;
@@ -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);
@@ -1057,10 +1061,13 @@ ar9300_ani_get_listen_time(struct ath_hal *ah, HAL_ANISTATS *ani_stats)
struct ath_hal_9300 *ahp = AH9300(ah);
struct ar9300_ani_state *ani_state;
u_int32_t tx_frame_count, rx_frame_count, cycle_count;
+ u_int32_t rx_busy_count, rx_ext_busy_count;
int32_t listen_time;
tx_frame_count = OS_REG_READ(ah, AR_TFCNT);
rx_frame_count = OS_REG_READ(ah, AR_RFCNT);
+ rx_busy_count = OS_REG_READ(ah, AR_RCCNT);
+ rx_ext_busy_count = OS_REG_READ(ah, AR_EXTRCCNT);
cycle_count = OS_REG_READ(ah, AR_CCCNT);
ani_state = ahp->ah_curani;
@@ -1081,17 +1088,30 @@ ar9300_ani_get_listen_time(struct ath_hal *ah, HAL_ANISTATS *ani_stats)
int32_t ccdelta = cycle_count - ani_state->cycle_count;
int32_t rfdelta = rx_frame_count - ani_state->rx_frame_count;
int32_t tfdelta = tx_frame_count - ani_state->tx_frame_count;
+ int32_t rcdelta = rx_busy_count - ani_state->rx_busy_count;
+ int32_t extrcdelta = rx_ext_busy_count - ani_state->rx_ext_busy_count;
listen_time = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE(ah);
-#if HAL_ANI_DEBUG
+//#if HAL_ANI_DEBUG
HALDEBUG(ah, HAL_DEBUG_ANI,
- "%s: cyclecount=%d, rfcount=%d, tfcount=%d, listen_time=%d "
+ "%s: cyclecount=%d, rfcount=%d, tfcount=%d, rcdelta=%d, extrcdelta=%d, listen_time=%d "
"CLOCK_RATE=%d\n",
- __func__, ccdelta, rfdelta, tfdelta, listen_time, CLOCK_RATE(ah));
-#endif
+ __func__, ccdelta, rfdelta, tfdelta, rcdelta, extrcdelta,
+ listen_time, CLOCK_RATE(ah));
+//#endif
+ /* Populate as appropriate */
+ ani_stats->cyclecnt_diff = ccdelta;
+ ani_stats->rxclr_cnt = rcdelta;
+ ani_stats->txframecnt_diff = tfdelta;
+ ani_stats->rxframecnt_diff = rfdelta;
+ ani_stats->extrxclr_cnt = extrcdelta;
+ ani_stats->listen_time = listen_time;
+ ani_stats->valid = AH_TRUE;
}
ani_state->cycle_count = cycle_count;
ani_state->tx_frame_count = tx_frame_count;
ani_state->rx_frame_count = rx_frame_count;
+ ani_state->rx_busy_count = rx_busy_count;
+ ani_state->rx_ext_busy_count = rx_ext_busy_count;
return listen_time;
}
@@ -1151,7 +1171,13 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
ofdm_phy_err_cnt = OS_REG_READ(ah, AR_PHY_ERR_1);
cck_phy_err_cnt = OS_REG_READ(ah, AR_PHY_ERR_2);
-
+ /* Populate HAL_ANISTATS */
+ if (ani_stats) {
+ ani_stats->cckphyerr_cnt =
+ cck_phy_err_cnt - ani_state->cck_phy_err_count;
+ ani_stats->ofdmphyerrcnt_diff =
+ ofdm_phy_err_cnt - ani_state->ofdm_phy_err_count;
+ }
/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
ahp->ah_stats.ast_ani_ofdmerrs +=
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
index 335414e..a446f96 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
@@ -302,6 +302,7 @@ static const struct ath_hal_private ar9300hal = {
ar9300_get_desc_info, /* ah_get_desc_info */
ar9300_select_ant_config, /* ah_select_ant_config */
ar9300_ant_ctrl_common_get, /* ah_ant_ctrl_common_get */
+ ar9300_ant_swcom_sel, /* ah_ant_swcom_sel */
ar9300_enable_tpc, /* ah_enable_tpc */
AH_NULL, /* ah_olpc_temp_compensation */
#if ATH_SUPPORT_CRDC
@@ -319,7 +320,9 @@ static const struct ath_hal_private ar9300hal = {
ar9300_set_key_cache_entry, /* ah_set_key_cache_entry */
ar9300_set_key_cache_entry_mac, /* ah_set_key_cache_entry_mac */
ar9300_print_keycache, /* ah_print_key_cache */
-
+#if ATH_SUPPORT_KEYPLUMB_WAR
+ ar9300_check_key_cache_entry, /* ah_check_key_cache_entry */
+#endif
/* Power Management Functions */
ar9300_set_power_mode, /* ah_set_power_mode */
ar9300_set_sm_power_mode, /* ah_set_sm_ps_mode */
@@ -342,6 +345,8 @@ static const struct ath_hal_private ar9300hal = {
/* Get Channel Noise */
ath_hal_get_chan_noise, /* ah_get_chan_noise */
ar9300_chain_noise_floor, /* ah_get_chain_noise_floor */
+ ar9300_get_nf_from_reg, /* ah_get_nf_from_reg */
+ ar9300_get_rx_nf_offset, /* ah_get_rx_nf_offset */
/* Beacon Functions */
ar9300_beacon_init, /* ah_beacon_init */
@@ -499,11 +504,11 @@ static const struct ath_hal_private ar9300hal = {
#else
AH_NULL,
AH_NULL,
- ar9300TX99TgtChannelPwrUpdate, /* ah_tx99channelpwrupdate */
- ar9300TX99TgtStart, /* ah_tx99start */
- ar9300TX99TgtStop, /* ah_tx99stop */
- ar9300TX99TgtChainmskSetup, /* ah_tx99_chainmsk_setup */
- ar9300TX99SetSingleCarrier, /* ah_tx99_set_single_carrier */
+ ar9300_tx99_channel_pwr_update, /* ah_tx99channelpwrupdate */
+ ar9300_tx99_start, /* ah_tx99start */
+ ar9300_tx99_stop, /* ah_tx99stop */
+ ar9300_tx99_chainmsk_setup, /* ah_tx99_chainmsk_setup */
+ ar9300_tx99_set_single_carrier, /* ah_tx99_set_single_carrier */
#endif
#endif
ar9300_chk_rssi_update_tx_pwr,
@@ -525,6 +530,8 @@ static const struct ath_hal_private ar9300hal = {
ar9300_dump_keycache, /* ah_dump_keycache */
ar9300_is_ani_noise_spur, /* ah_is_ani_noise_spur */
ar9300_set_hw_beacon_proc, /* ah_set_hw_beacon_proc */
+ ar9300_set_ctl_pwr, /* ah_set_ctl_pwr */
+ ar9300_set_txchainmaskopt, /* ah_set_txchainmaskopt */
},
ar9300_get_channel_edges, /* ah_get_channel_edges */
@@ -618,7 +625,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 +636,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 +662,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) {
@@ -843,6 +845,18 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
/* Enable RIFS */
ahp->ah_rifs_enabled = AH_TRUE;
+ /* by default, stop RX also in abort txdma, due to
+ "Unable to stop TxDMA" msg observed */
+ ahp->ah_abort_txdma_norx = AH_TRUE;
+
+ /* do not use optional tx chainmask by default */
+ ahp->ah_tx_chainmaskopt = 0;
+
+ ahp->ah_skip_rx_iq_cal = AH_FALSE;
+ ahp->ah_rx_cal_complete = AH_FALSE;
+ ahp->ah_rx_cal_chan = 0;
+ ahp->ah_rx_cal_chan_flag = 0;
+
HALDEBUG(ah, HAL_DEBUG_RESET,
"%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
ahpriv->ah_macVersion,
@@ -2378,7 +2392,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 +2446,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 +2472,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 =
@@ -2934,6 +2951,10 @@ ar9300_fill_capability_info(struct ath_hal *ah)
p_cap->halRxUsingLnaMixing = AH_TRUE;
}
+ /*
+ * AR5416 and later NICs support MYBEACON filtering.
+ */
+ p_cap->halRxDoMyBeacon = AH_TRUE;
#if ATH_WOW_OFFLOAD
if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
@@ -3831,6 +3852,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
@@ -4109,6 +4135,8 @@ ar9300_probe(uint16_t vendorid, uint16_t devid)
return "Qualcomm Atheros QCA955x";
case AR9300_DEVID_QCA9565: /* Aphrodite */
return "Qualcomm Atheros AR9565";
+ case AR9300_DEVID_AR1111_PCIE:
+ return "Atheros AR1111";
default:
return AH_NULL;
}
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c
index 17943a9..f4da88c 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c
@@ -34,7 +34,8 @@ extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q);
*/
void
ar9300_beacon_init(struct ath_hal *ah,
- u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode)
+ u_int32_t next_beacon, u_int32_t beacon_period,
+ u_int32_t beacon_period_fraction, HAL_OPMODE opmode)
{
u_int32_t beacon_period_usec;
@@ -52,6 +53,14 @@ ar9300_beacon_init(struct ath_hal *ah,
beacon_period_usec =
ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8);
+
+ /* Add the fraction adjustment lost due to unit conversions. */
+ beacon_period_usec += beacon_period_fraction;
+
+ HALDEBUG(ah, HAL_DEBUG_BEACON,
+ "%s: next_beacon=0x%08x, beacon_period=%d, opmode=%d, beacon_period_usec=%d\n",
+ __func__, next_beacon, beacon_period, opmode, beacon_period_usec);
+
OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec);
OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec);
OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
index ba7777e..9028ab7 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
@@ -1200,6 +1200,44 @@ ar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency,
return nf_use;
}
+/*
+ * Return the Rx NF offset for specific channel.
+ * The values saved in EEPROM/OTP/Flash is converted through the following way:
+ * ((_p) - NOISE_PWR_DATA_OFFSET) << 2
+ * So we need to convert back to the original values.
+ */
+int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) {
+ HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
+ int8_t rx_nf_pwr, rx_nf_cal;
+ int i;
+ //HALASSERT(ichan);
+
+ /* Fill 0 if valid internal channel is not found */
+ if (ichan == AH_NULL) {
+ OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS);
+ OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS);
+ return -1;
+ }
+
+ for (i = 0; i < OSPREY_MAX_CHAINS; i++) {
+ if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) {
+ nf_pwr[i] = 0;
+ } else {
+ //printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr);
+ nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr);
+ }
+
+ if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) {
+ nf_cal[i] = 0;
+ } else {
+ //printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal);
+ nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal);
+ }
+ }
+
+ return 0;
+}
+
int32_t ar9300_rx_gain_index_get(struct ath_hal *ah)
{
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
@@ -1530,6 +1568,61 @@ u_int16_t ar9300_ant_ctrl_chain_get(struct ath_hal *ah, int chain,
return 0;
}
+/*
+ * Select the usage of antenna via the RF switch.
+ * Default values are loaded from eeprom.
+ */
+HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
+ u_int32_t *common_tbl1, u_int32_t *common_tbl2)
+{
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ struct ath_hal_private *ap = AH_PRIVATE(ah);
+ const struct ieee80211_channel *curchan = ap->ah_curchan;
+ enum {
+ ANT_SELECT_OPS_GET,
+ ANT_SELECT_OPS_SET,
+ };
+
+ if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah))
+ return AH_FALSE;
+
+ if (!curchan)
+ return AH_FALSE;
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+ switch (ops) {
+ case ANT_SELECT_OPS_GET:
+ *common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL);
+ *common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2,
+ AR_SWITCH_TABLE_COM2_ALL);
+ break;
+ case ANT_SELECT_OPS_SET:
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL, *common_tbl1);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
+ AR_SWITCH_TABLE_COM2_ALL, *common_tbl2);
+
+ /* write back to eeprom */
+ if (IEEE80211_IS_CHAN_2GHZ(curchan)) {
+ eep->modal_header_2g.ant_ctrl_common = *common_tbl1;
+ eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2;
+ } else {
+ eep->modal_header_5g.ant_ctrl_common = *common_tbl1;
+ eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return AH_TRUE;
+}
+
HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
{
u_int32_t value;
@@ -1606,6 +1699,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 +1805,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 +1872,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 +1911,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)
@@ -2339,16 +2505,31 @@ ar9300_eeprom_set_power_per_rate_table(
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
#endif
- tx_chainmask = chainmask ? chainmask : ahp->ah_tx_chainmask;
+ if (chainmask)
+ tx_chainmask = chainmask;
+ else
+ tx_chainmask = ahp->ah_tx_chainmaskopt ?
+ ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask;
ar9300_get_channel_centers(ah, chan, &centers);
+#if 1
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain;
} else {
ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain;
}
+#else
+ if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+ ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain,
+ AH_PRIVATE(ah)->ah_antenna_gain_2g);
+ } else {
+ ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain,
+ AH_PRIVATE(ah)->ah_antenna_gain_5g);
+ }
+#endif
+
/* Save max allowed antenna gain to ease future lookups */
ahp->twice_antenna_reduction = twice_antenna_reduction;
@@ -2885,7 +3066,8 @@ ar9300_eeprom_set_transmit_power(struct ath_hal *ah,
}
max_power_level = target_power_val_t2[i];
/* Adjusting the ah_max_power_level based on chains and antennaGain*/
- switch (ar9300_get_ntxchains(ahp->ah_tx_chainmask))
+ switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ?
+ ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask)))
{
case 1:
break;
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
index 251957e..5bdd74f 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
@@ -36,6 +36,9 @@
static HAL_BOOL ar9300ClrMulticastFilterIndex(struct ath_hal *ah, uint32_t ix);
static HAL_BOOL ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix);
+static void ar9300_beacon_set_beacon_timers(struct ath_hal *ah,
+ const HAL_BEACON_TIMERS *bt);
+
static void
ar9300SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
uint32_t rx_chainmask)
@@ -60,14 +63,44 @@ ar9300_freebsd_set_tx_power_limit(struct ath_hal *ah, uint32_t limit)
return (ar9300_set_tx_power_limit(ah, limit, 0, 0));
}
+static uint64_t
+ar9300_get_next_tbtt(struct ath_hal *ah)
+{
+ return (OS_REG_READ(ah, AR_NEXT_TBTT_TIMER));
+}
+
+
+/*
+ * TODO: implement the antenna diversity control for AR9485 and
+ * other LNA mixing based NICs.
+ *
+ * For now we'll just go with the HAL default and make these no-ops.
+ */
+static HAL_ANT_SETTING
+ar9300_freebsd_get_antenna_switch(struct ath_hal *ah)
+{
+
+ return (HAL_ANT_VARIABLE);
+}
+
+static HAL_BOOL
+ar9300_freebsd_set_antenna_switch(struct ath_hal *ah, HAL_ANT_SETTING setting)
+{
+
+ return (AH_TRUE);
+}
+
+static u_int
+ar9300_freebsd_get_cts_timeout(struct ath_hal *ah)
+{
+ u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS);
+ return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
+}
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;
@@ -154,8 +187,8 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
ah->ah_getRfGain = ar9300_get_rfgain;
ah->ah_getDefAntenna = ar9300_get_def_antenna;
ah->ah_setDefAntenna = ar9300_set_def_antenna;
- // ah->ah_getAntennaSwitch = ar9300_get_antenna_switch;
- // ah->ah_setAntennaSwitch = ar9300_set_antenna_switch;
+ ah->ah_getAntennaSwitch = ar9300_freebsd_get_antenna_switch;
+ ah->ah_setAntennaSwitch = ar9300_freebsd_set_antenna_switch;
// ah->ah_setSifsTime = ar9300_set_sifs_time;
// ah->ah_getSifsTime = ar9300_get_sifs_time;
ah->ah_setSlotTime = ar9300_set_slot_time;
@@ -164,6 +197,7 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
ah->ah_setAckTimeout = ar9300_set_ack_timeout;
// XXX ack/ctsrate
// XXX CTS timeout
+ ah->ah_getCTSTimeout = ar9300_freebsd_get_cts_timeout;
// XXX decompmask
// coverageclass
ah->ah_setQuiet = ar9300_set_quiet;
@@ -191,10 +225,10 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
/* Beacon functions */
/* ah_setBeaconTimers */
ah->ah_beaconInit = ar9300_freebsd_beacon_init;
- /* ah_setBeaconTimers */
+ ah->ah_setBeaconTimers = ar9300_beacon_set_beacon_timers;
ah->ah_setStationBeaconTimers = ar9300_set_sta_beacon_timers;
/* ah_resetStationBeaconTimers */
- /* ah_getNextTBTT */
+ ah->ah_getNextTBTT = ar9300_get_next_tbtt;
/* Interrupt functions */
ah->ah_isInterruptPending = ar9300_is_interrupt_pending;
@@ -246,12 +280,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
@@ -323,11 +366,26 @@ ar9300_ani_poll_freebsd(struct ath_hal *ah,
HAL_NODE_STATS stats;
HAL_ANISTATS anistats;
+ HAL_SURVEY_SAMPLE survey;
OS_MEMZERO(&stats, sizeof(stats));
OS_MEMZERO(&anistats, sizeof(anistats));
+ OS_MEMZERO(&survey, sizeof(survey));
ar9300_ani_ar_poll(ah, &stats, chan, &anistats);
+
+ /*
+ * If ANI stats are valid, use them to update the
+ * channel survey.
+ */
+ if (anistats.valid) {
+ survey.cycle_count = anistats.cyclecnt_diff;
+ survey.chan_busy = anistats.rxclr_cnt;
+ survey.ext_chan_busy = anistats.extrxclr_cnt;
+ survey.tx_busy = anistats.txframecnt_diff;
+ survey.rx_busy = anistats.rxframecnt_diff;
+ ath_hal_survey_add_sample(ah, &survey);
+ }
}
/*
@@ -335,9 +393,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;
}
@@ -465,11 +525,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);
@@ -590,8 +652,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, 0,
+ AH_PRIVATE(ah)->ah_opmode);
}
HAL_BOOL
@@ -653,6 +715,55 @@ ar9300SetMulticastFilterIndex(struct ath_hal *ah, uint32_t ix)
return (AH_TRUE);
}
+#define TU_TO_USEC(_tu) ((_tu) << 10)
+#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7)
+
+/*
+ * Initializes all of the hardware registers used to
+ * send beacons. Note that for station operation the
+ * driver calls ar9300_set_sta_beacon_timers instead.
+ */
+static void
+ar9300_beacon_set_beacon_timers(struct ath_hal *ah,
+ const HAL_BEACON_TIMERS *bt)
+{
+ uint32_t bperiod;
+
+#if 0
+ HALASSERT(opmode == HAL_M_IBSS || opmode == HAL_M_HOSTAP);
+ if (opmode == HAL_M_IBSS) {
+ OS_REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+ }
+#endif
+
+ /* XXX TODO: should migrate the HAL code to always use ONE_EIGHTH_TU */
+ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bt->bt_nexttbtt));
+ OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba));
+ OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba));
+ OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER, TU_TO_USEC(bt->bt_nextatim));
+
+ bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);
+ /* XXX TODO! */
+// ahp->ah_beaconInterval = bt->bt_intval & HAL_BEACON_PERIOD;
+ OS_REG_WRITE(ah, AR_BEACON_PERIOD, bperiod);
+ OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bperiod);
+ OS_REG_WRITE(ah, AR_SWBA_PERIOD, bperiod);
+ OS_REG_WRITE(ah, AR_NDP_PERIOD, bperiod);
+
+ /*
+ * Reset TSF if required.
+ */
+ if (bt->bt_intval & HAL_BEACON_RESET_TSF)
+ ar9300_reset_tsf(ah);
+
+ /* enable timers */
+ /* NB: flags == 0 handled specially for backwards compatibility */
+ OS_REG_SET_BIT(ah, AR_TIMER_MODE,
+ bt->bt_flags != 0 ? bt->bt_flags :
+ AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN);
+}
+
+
/*
* RF attach stubs
*/
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h
index c07c32f..524c3f3 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.h
@@ -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);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
index a159c2c..1af621b 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
@@ -35,6 +35,7 @@
#define ATH_SUPPORT_PAPRD 1
#define ATH_SUPPORT_TxBF 0
#define AH_PRIVATE_DIAG 1
+#define ATH_SUPPORT_KEYPLUMB_WAR 0
/* XXX need to reverify these; they came in with qcamain */
#define ATH_SUPPORT_FAST_CC 0
@@ -57,7 +58,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! */
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c
index 5660c1f..1dcdafe 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c
@@ -162,7 +162,6 @@ ar9300_gpio_cfg_output(
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
- (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
(gpio == AR9382_GPIO_9_INPUT_ONLY))
{
return AH_FALSE;
@@ -348,7 +347,6 @@ ar9300_gpio_cfg_input(struct ath_hal *ah, u_int32_t gpio)
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
- (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
(gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
{
return AH_FALSE;
@@ -378,7 +376,6 @@ ar9300_gpio_set(struct ath_hal *ah, u_int32_t gpio, u_int32_t val)
{
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
- (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
(gpio == AR9382_GPIO_9_INPUT_ONLY))
{
return AH_FALSE;
@@ -397,8 +394,7 @@ ar9300_gpio_get(struct ath_hal *ah, u_int32_t gpio)
{
u_int32_t gpio_in;
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
- if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
- (gpio == AR9382_GPIO_PIN_11_RESERVED))
+ if (gpio == AR9382_GPIO_PIN_8_RESERVED)
{
return 0xffffffff;
}
@@ -453,7 +449,6 @@ ar9300_gpio_set_intr(struct ath_hal *ah, u_int gpio, u_int32_t ilevel)
HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
if ((gpio == AR9382_GPIO_PIN_8_RESERVED) ||
- (gpio == AR9382_GPIO_PIN_11_RESERVED) ||
(gpio > AR9382_MAX_GPIO_INPUT_PIN_NUM))
{
return;
@@ -549,8 +544,7 @@ ar9300_gpio_get_mask(struct ath_hal *ah)
if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
mask = (1 << AR9382_MAX_GPIO_PIN_NUM) - 1;
- mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED |
- 1 << AR9382_GPIO_PIN_11_RESERVED);
+ mask &= ~(1 << AR9382_GPIO_PIN_8_RESERVED);
}
return mask;
}
@@ -562,8 +556,7 @@ ar9300_gpio_set_mask(struct ath_hal *ah, u_int32_t mask, u_int32_t pol_map)
if (AH_PRIVATE(ah)->ah_devid == AR9300_DEVID_AR9380_PCIE) {
invalid = ~((1 << AR9382_MAX_GPIO_PIN_NUM) - 1);
- invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED |
- 1 << AR9382_GPIO_PIN_11_RESERVED;
+ invalid |= 1 << AR9382_GPIO_PIN_8_RESERVED;
}
if (mask & invalid) {
ath_hal_printf(ah, "%s: invalid GPIO mask 0x%x\n", __func__, mask);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
index 51ee3cd..acc14b3 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
@@ -142,6 +142,21 @@ ar9300_get_pending_interrupts(
sync_en_def = AR9340_INTR_SYNC_DEFAULT;
}
+ /* Store away the async and sync cause registers */
+ /* XXX Do this before the filtering done below */
+#ifdef AH_INTERRUPT_DEBUGGING
+ ah->ah_intrstate[0] = OS_REG_READ(ah, AR_ISR);
+ ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0);
+ ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1);
+ ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2);
+ ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3);
+ ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4);
+ ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5);
+
+ /* XXX double reading? */
+ ah->ah_syncstate = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
+#endif
+
sync_cause =
OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &
(sync_en_def | AR_INTR_SYNC_MASK_GPIO);
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c
index 8b9a143..0f4fab9 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c
@@ -436,3 +436,156 @@ void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry)
}
#undef AH_KEY_REG_SIZE
}
+
+#if ATH_SUPPORT_KEYPLUMB_WAR
+/*
+ * Check the contents of the specified key cache entry
+ * and any associated MIC entry.
+ */
+ HAL_BOOL
+ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
+ const HAL_KEYVAL *k, int xorKey)
+{
+ const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+ u_int32_t key0, key1, key2, key3, key4;
+ u_int32_t keyType;
+ u_int32_t xorMask = xorKey ?
+ (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+
+ if (entry >= pCap->hal_key_cache_size) {
+ HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
+ "%s: entry %u out of range\n", __func__, entry);
+ return AH_FALSE;
+ }
+ switch (k->kv_type) {
+ case HAL_CIPHER_AES_OCB:
+ keyType = AR_KEYTABLE_TYPE_AES;
+ break;
+ case HAL_CIPHER_AES_CCM:
+ if (!pCap->hal_cipher_aes_ccm_support) {
+ HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
+ "mac rev 0x%x\n",
+ __func__, AH_PRIVATE(ah)->ah_macRev);
+ return AH_FALSE;
+ }
+ keyType = AR_KEYTABLE_TYPE_CCM;
+ break;
+ case HAL_CIPHER_TKIP:
+ keyType = AR_KEYTABLE_TYPE_TKIP;
+ if (IS_MIC_ENABLED(ah) && entry + 64 >= pCap->hal_key_cache_size) {
+ HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
+ "%s: entry %u inappropriate for TKIP\n",
+ __func__, entry);
+ return AH_FALSE;
+ }
+ break;
+ case HAL_CIPHER_WEP:
+ if (k->kv_len < 40 / NBBY) {
+ HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
+ __func__, k->kv_len);
+ return AH_FALSE;
+ }
+ if (k->kv_len <= 40 / NBBY) {
+ keyType = AR_KEYTABLE_TYPE_40;
+ } else if (k->kv_len <= 104 / NBBY) {
+ keyType = AR_KEYTABLE_TYPE_104;
+ } else {
+ keyType = AR_KEYTABLE_TYPE_128;
+ }
+ break;
+ case HAL_CIPHER_CLR:
+ keyType = AR_KEYTABLE_TYPE_CLR;
+ return AH_TRUE;
+ default:
+ HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
+ __func__, k->kv_type);
+ return AH_TRUE;
+ }
+
+ key0 = LE_READ_4(k->kv_val + 0) ^ xorMask;
+ key1 = (LE_READ_2(k->kv_val + 4) ^ xorMask) & 0xffff;
+ key2 = LE_READ_4(k->kv_val + 6) ^ xorMask;
+ key3 = (LE_READ_2(k->kv_val + 10) ^ xorMask) & 0xffff;
+ key4 = LE_READ_4(k->kv_val + 12) ^ xorMask;
+ if (k->kv_len <= 104 / NBBY) {
+ key4 &= 0xff;
+ }
+
+ /*
+ * Note: key cache hardware requires that each double-word
+ * pair be written in even/odd order (since the destination is
+ * a 64-bit register). Don't reorder these writes w/o
+ * considering this!
+ */
+ if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
+ u_int16_t micentry = entry + 64; /* MIC goes at slot+64 */
+
+
+ /*
+ * Invalidate the encrypt/decrypt key until the MIC
+ * key is installed so pending rx frames will fail
+ * with decrypt errors rather than a MIC error.
+ */
+ if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
+ ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE)))
+ {
+
+ /*
+ * since the AR_MISC_MODE register was written with the contents of
+ * ah_miscMode (if any) in ar9300Attach, just check ah_miscMode and
+ * save a pci read per key set.
+ */
+ if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
+ u_int32_t mic0,mic1,mic2,mic3,mic4;
+ /*
+ * both RX and TX mic values can be combined into
+ * one cache slot entry.
+ * 8*N + 800 31:0 RX Michael key 0
+ * 8*N + 804 15:0 TX Michael key 0 [31:16]
+ * 8*N + 808 31:0 RX Michael key 1
+ * 8*N + 80C 15:0 TX Michael key 0 [15:0]
+ * 8*N + 810 31:0 TX Michael key 1
+ * 8*N + 814 15:0 reserved
+ * 8*N + 818 31:0 reserved
+ * 8*N + 81C 14:0 reserved
+ * 15 key valid == 0
+ */
+ /* RX mic */
+ mic0 = LE_READ_4(k->kv_mic + 0);
+ mic2 = LE_READ_4(k->kv_mic + 4);
+ /* TX mic */
+ mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
+ mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
+ mic4 = LE_READ_4(k->kv_txmic + 4);
+ if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(micentry)) == mic0) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY1(micentry)) == mic1) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY2(micentry)) == mic2) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY3(micentry)) == mic3) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY4(micentry)) == mic4) &&
+ ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEY_TYPE) == (AR_KEYTABLE_TYPE_CLR & AR_KEY_TYPE))) {
+ return AH_TRUE;
+ }
+
+ } else {
+ return AH_TRUE;
+ }
+ }
+ } else {
+ if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
+ (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
+ ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) {
+ return AH_TRUE;
+ }
+ }
+ return AH_FALSE;
+}
+#endif
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
index a0722b7..e9caa43 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
@@ -683,6 +683,7 @@ ar9300_get_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
{
struct ath_hal_9300 *ahp = AH9300(ah);
const HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
+ struct ar9300_ani_state *ani;
switch (type) {
case HAL_CAP_CIPHER: /* cipher handled in hardware */
@@ -911,6 +912,34 @@ ar9300_get_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
return HAL_ENOTSUPP;
}
#endif
+
+ /* FreeBSD ANI */
+ case HAL_CAP_INTMIT: /* interference mitigation */
+ switch (capability) {
+ case HAL_CAP_INTMIT_PRESENT: /* hardware capability */
+ return HAL_OK;
+ case HAL_CAP_INTMIT_ENABLE:
+ return (ahp->ah_proc_phy_err & HAL_PROCESS_ANI) ?
+ HAL_OK : HAL_ENXIO;
+ case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL:
+ case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL:
+// case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR:
+ case HAL_CAP_INTMIT_FIRSTEP_LEVEL:
+ case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL:
+ ani = ar9300_ani_get_current_state(ah);
+ if (ani == AH_NULL)
+ return HAL_ENXIO;
+ switch (capability) {
+ /* XXX AR9300 HAL has OFDM/CCK noise immunity level params? */
+ case 2: *result = ani->ofdm_noise_immunity_level; break;
+ case 3: *result = !ani->ofdm_weak_sig_detect_off; break;
+ // case 4: *result = ani->cck_weak_sig_threshold; break;
+ case 5: *result = ani->firstep_level; break;
+ case 6: *result = ani->spur_immunity_level; break;
+ }
+ return HAL_OK;
+ }
+ return HAL_EINVAL;
default:
return ath_hal_getcapability(ah, type, capability, result);
}
@@ -986,6 +1015,27 @@ ar9300_set_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
return AH_TRUE;
}
return AH_FALSE;
+
+ /* FreeBSD interrupt mitigation / ANI */
+ case HAL_CAP_INTMIT: { /* interference mitigation */
+ /* This maps the public ANI commands to the internal ANI commands */
+ /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */
+ static const HAL_ANI_CMD cmds[] = {
+ HAL_ANI_PRESENT,
+ HAL_ANI_MODE,
+ HAL_ANI_NOISE_IMMUNITY_LEVEL,
+ HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ HAL_ANI_CCK_WEAK_SIGNAL_THR,
+ HAL_ANI_FIRSTEP_LEVEL,
+ HAL_ANI_SPUR_IMMUNITY_LEVEL,
+ };
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ return capability < N(cmds) ?
+ ar9300_ani_control(ah, cmds[capability], setting) :
+ AH_FALSE;
+#undef N
+ }
+
case HAL_CAP_RXBUFSIZE: /* set MAC receive buffer size */
ahp->rx_buf_size = setting & AR_DATABUF_MASK;
OS_REG_WRITE(ah, AR_DATABUF, ahp->rx_buf_size);
@@ -1129,6 +1179,7 @@ ar9300_get_diag_state(struct ath_hal *ah, int request,
void **result, u_int32_t *resultsize)
{
struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ar9300_ani_state *ani;
(void) ahp;
if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) {
@@ -1169,14 +1220,35 @@ ar9300_get_diag_state(struct ath_hal *ah, int request,
return AH_TRUE;
#endif
case HAL_DIAG_ANI_CURRENT:
+
+ ani = ar9300_ani_get_current_state(ah);
+ if (ani == AH_NULL)
+ return AH_FALSE;
+ /* Convert ar9300 HAL to FreeBSD HAL ANI state */
+ /* XXX TODO: add all of these to the HAL ANI state structure */
+ bzero(&ahp->ext_ani_state, sizeof(ahp->ext_ani_state));
+ /* XXX should this be OFDM or CCK noise immunity level? */
+ ahp->ext_ani_state.noiseImmunityLevel = ani->ofdm_noise_immunity_level;
+ ahp->ext_ani_state.spurImmunityLevel = ani->spur_immunity_level;
+ ahp->ext_ani_state.firstepLevel = ani->firstep_level;
+ ahp->ext_ani_state.ofdmWeakSigDetectOff = ani->ofdm_weak_sig_detect_off;
+ /* mrc_cck_off */
+ /* cck_noise_immunity_level */
+
+ ahp->ext_ani_state.listenTime = ani->listen_time;
+
+ *result = &ahp->ext_ani_state;
+ *resultsize = sizeof(ahp->ext_ani_state);
+#if 0
*result = ar9300_ani_get_current_state(ah);
*resultsize = (*result == AH_NULL) ?
0 : sizeof(struct ar9300_ani_state);
+#endif
return AH_TRUE;
case HAL_DIAG_ANI_STATS:
*result = ar9300_ani_get_current_stats(ah);
*resultsize = (*result == AH_NULL) ?
- 0 : sizeof(struct ar9300_stats);
+ 0 : sizeof(HAL_ANI_STATS);
return AH_TRUE;
case HAL_DIAG_ANI_CMD:
if (argsize != 2*sizeof(u_int32_t)) {
@@ -1697,10 +1769,10 @@ ar9300_get_bb_panic_info(struct ath_hal *ah, struct hal_bb_panic_info *bb_panic)
/* Suppress BB Status mesg following signature */
switch (bb_panic->status) {
- case 0x04000539:
- case 0x04008009:
- case 0x04000b09:
- case 0x1300000a:
+ case 0x04000539:
+ case 0x04008009:
+ case 0x04000b09:
+ case 0x1300000a:
return -1;
}
@@ -3718,8 +3790,6 @@ ar9300_tx99_start(struct ath_hal *ah, u_int8_t *data)
/* Disable AGC to A2 */
OS_REG_WRITE(ah, AR_PHY_TEST, (OS_REG_READ(ah, AR_PHY_TEST) | PHY_AGC_CLR));
- OS_REG_WRITE(ah, 0x9864, OS_REG_READ(ah, 0x9864) | 0x7f000);
- OS_REG_WRITE(ah, 0x9924, OS_REG_READ(ah, 0x9924) | 0x7f00fe);
OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS);
OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* set receive disable */
@@ -3763,3 +3833,47 @@ ar9300SetDfs3StreamFix(struct ath_hal *ah, u_int32_t val)
{
return AH_FALSE;
}
+
+HAL_BOOL
+ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ ar9300_eeprom_t *p_eep_data = &ahp->ah_eeprom;
+ u_int8_t *ctl_index;
+ u_int32_t offset = 0;
+
+ if (!ctl_array)
+ return AH_FALSE;
+
+ /* copy 2G ctl freqbin and power data */
+ ctl_index = p_eep_data->ctl_index_2g;
+ OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_2G, ctl_array,
+ OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G + /* ctl_freqbin_2G */
+ OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G)); /* ctl_power_data_2g */
+ offset = (OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G) +
+ ( OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G));
+
+
+ /* copy 2G ctl freqbin and power data */
+ ctl_index = p_eep_data->ctl_index_5g;
+ OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_5G, ctl_array + offset,
+ OSPREY_NUM_CTLS_5G * OSPREY_NUM_BAND_EDGES_5G + /* ctl_freqbin_5G */
+ OSPREY_NUM_CTLS_5G * sizeof(OSP_CAL_CTL_DATA_5G)); /* ctl_power_data_5g */
+
+ return AH_FALSE;
+}
+
+void
+ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ /* optional txchainmask should be subset of primary txchainmask */
+ if ((mask & ahp->ah_tx_chainmask) != mask) {
+ ahp->ah_tx_chainmaskopt = 0;
+ ath_hal_printf(ah, "Error: ah_tx_chainmask=%d, mask=%d\n", ahp->ah_tx_chainmask, mask);
+ return;
+ }
+
+ ahp->ah_tx_chainmaskopt = mask;
+}
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini
index 9814dab..fffaf7a 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini
@@ -881,7 +881,7 @@ static const u_int32_t ar9300_osprey_2p2_mac_core[][2] = {
{ 0x00008258 , 0x00000000 },
{ 0x0000825c , 0x40000000 },
{ 0x00008260 , 0x00080922 },
- { 0x00008264 , 0x9bc00010 },
+ { 0x00008264 , 0x9d400010 },
{ 0x00008268 , 0xffffffff },
{ 0x0000826c , 0x0000ffff },
{ 0x00008270 , 0x00000000 },
@@ -1171,7 +1171,7 @@ static const u_int32_t ar9300_osprey_2p2_mac_postamble[][5] = {
{ 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 },
{ 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 },
{ 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b },
- { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 },
+ { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 },
{ 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a },
{ 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 },
};
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
index 44bebe4..2a8f7f8 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
@@ -469,7 +469,7 @@ u_int32_t ar9300_wow_offload_handshake(struct ath_hal *ah, u_int32_t pattern_ena
OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_REQ);
OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_INT_EMB_CPU);
- if (!ath_hal_wait(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
+ if (!ath_hal_waitfor(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: WoW offload handshake failed", __func__);
return 0;
}
@@ -666,15 +666,19 @@ 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 " : "");
+ OS_MARK(ah, AH_MARK_CHIP_POWER, mode);
switch (mode) {
case HAL_PM_AWAKE:
+ if (set_chip)
+ ah->ah_powerMode = mode;
status = ar9300_set_power_mode_awake(ah, set_chip);
#if ATH_SUPPORT_MCI
if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
}
#endif
+ ahp->ah_chip_full_sleep = AH_FALSE;
break;
case HAL_PM_FULL_SLEEP:
#if ATH_SUPPORT_MCI
@@ -698,7 +702,10 @@ ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip)
}
#endif
ar9300_set_power_mode_sleep(ah, set_chip);
- ahp->ah_chip_full_sleep = AH_TRUE;
+ if (set_chip) {
+ ahp->ah_chip_full_sleep = AH_TRUE;
+ ah->ah_powerMode = mode;
+ }
break;
case HAL_PM_NETWORK_SLEEP:
#if ATH_SUPPORT_MCI
@@ -707,12 +714,17 @@ ar9300_set_power_mode(struct ath_hal *ah, HAL_POWER_MODE mode, int set_chip)
}
#endif
ar9300_set_power_mode_network_sleep(ah, set_chip);
+ if (set_chip) {
+ ah->ah_powerMode = mode;
+ }
break;
default:
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
"%s: unknown power mode %u\n", __func__, mode);
+ OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, -1);
return AH_FALSE;
}
+ OS_MARK(ah, AH_MARK_CHIP_POWER_DONE, status);
return status;
}
@@ -976,7 +988,7 @@ ar9300_set_power_mode_wow_sleep(struct ath_hal *ah)
OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */
- if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
+ if (!ath_hal_waitfor(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: dma failed to stop in 10ms\n"
"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__,
OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW));
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c
index e13c00b..c919d3c 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c
@@ -113,6 +113,8 @@ ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
#define AH_TIME_QUANTUM 100 /* usec */
+ OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);
+
if (timeout == 0) {
timeout = AH_RX_STOP_DMA_TIMEOUT;
}
@@ -157,6 +159,9 @@ ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
OS_REG_WRITE(ah, AR_MACMISC, org_value);
+ OS_MARK(ah, AH_MARK_RX_CTL,
+ status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);
+
return status;
#undef AH_RX_STOP_DMA_TIMEOUT
#undef AH_TIME_QUANTUM
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c
index a83099e..d4065d8 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c
@@ -68,6 +68,7 @@ ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds,
rxs->rs_status = 0;
rxs->rs_flags = 0;
+ rxs->rs_phyerr = 0;
rxs->rs_datalen = rxsp->status2 & AR_data_len;
rxs->rs_tstamp = rxsp->status3;
@@ -129,17 +130,16 @@ ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds,
* Consequently we filter them out here so we don't
* confuse and/or complicate drivers.
*/
+
if (rxsp->status11 & AR_crc_err) {
rxs->rs_status |= HAL_RXERR_CRC;
/*
- * ignore CRC flag for spectral phy reports
+ * ignore CRC flag for phy reports
*/
if (rxsp->status11 & AR_phyerr) {
u_int phyerr = MS(rxsp->status11, AR_phy_err_code);
- if (phyerr == HAL_PHYERR_SPECTRAL) {
- rxs->rs_status |= HAL_RXERR_PHY;
- rxs->rs_phyerr = phyerr;
- }
+ rxs->rs_status |= HAL_RXERR_PHY;
+ rxs->rs_phyerr = phyerr;
}
} else if (rxsp->status11 & AR_phyerr) {
u_int phyerr;
@@ -165,7 +165,9 @@ ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds,
rxs->rs_status |= HAL_RXERR_MIC;
}
}
-
+#if 0
+ rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel;
+#endif
return HAL_OK;
}
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
index 642aba1..01845b9 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
@@ -31,7 +31,6 @@
#define FIX_NOISE_FLOOR 1
-
/* Additional Time delay to wait after activiting the Base band */
#define BASE_ACTIVATE_DELAY 100 /* usec */
#define RTC_PLL_SETTLE_DELAY 100 /* usec */
@@ -325,6 +324,7 @@ int16_t ar9300_get_min_cca_pwr(struct ath_hal *ah)
int16_t nf;
// struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+
if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR9280_PHY_MINCCA_PWR);
if (nf & 0x100) {
@@ -402,6 +402,33 @@ void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf,
}
}
+/*
+ * Return the current NF value in register.
+ * If the current NF cal is not completed, return 0.
+ */
+int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time)
+{
+ int16_t nfarray[HAL_NUM_NF_READINGS] = {0};
+ int is_2g = 0;
+ HAL_CHANNEL_INTERNAL *ichan = NULL;
+
+ ichan = ath_hal_checkchannel(ah, chan);
+ if (ichan == NULL)
+ return (0);
+
+ if (wait_time <= 0) {
+ return 0;
+ }
+
+ if (!ath_hal_waitfor(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0, wait_time)) {
+ ath_hal_printf(ah, "%s: NF cal is not complete in %dus", __func__, wait_time);
+ return 0;
+ }
+ is_2g = !! (IS_CHAN_2GHZ(ichan));
+ ar9300_upload_noise_floor(ah, is_2g, nfarray);
+
+ return nfarray[0];
+}
/*
* Pick up the medium one in the noise floor buffer and update the
@@ -415,6 +442,7 @@ ar9300_get_nf_hist_mid(struct ath_hal *ah, HAL_NFCAL_HIST_FULL *h, int reading,
int16_t sort[HAL_NF_CAL_HIST_LEN_FULL]; /* upper bound for hist_len */
int i, j;
+
for (i = 0; i < hist_len; i++) {
sort[i] = h->nf_cal_buffer[i][reading];
HALDEBUG(ah, HAL_DEBUG_NFCAL,
@@ -451,7 +479,7 @@ ar9300_reset_nf_hist_buff(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
HAL_CHAN_NFCAL_HIST *h = &ichan->nf_cal_hist;
HAL_NFCAL_HIST_FULL *home = &AH_PRIVATE(ah)->nf_cal_hist;
int i;
-
+
/*
* Copy the value for the channel in question into the home-channel
* NF history buffer. The channel NF is probably a value filled in by
@@ -538,6 +566,7 @@ get_noise_floor_thresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan,
{
struct ath_hal_9300 *ahp = AH9300(ah);
+
switch (chan->channel_flags & CHANNEL_ALL_NOTURBO) {
case CHANNEL_A:
case CHANNEL_A_HT20:
@@ -1332,7 +1361,7 @@ ar9300_set_operating_mode(struct ath_hal *ah, int opmode)
}
/* XXX need the logic for Osprey */
-inline void
+void
ar9300_init_pll(struct ath_hal *ah, struct ieee80211_channel *chan)
{
u_int32_t pll;
@@ -1609,6 +1638,7 @@ ar9300_set_reset(struct ath_hal *ah, int type)
{
u_int32_t rst_flags;
u_int32_t tmp_reg;
+ struct ath_hal_9300 *ahp = AH9300(ah);
HALASSERT(type == HAL_RESET_WARM || type == HAL_RESET_COLD);
@@ -1802,6 +1832,7 @@ ar9300_set_reset(struct ath_hal *ah, int type)
ar9300_attach_hw_platform(ah);
+ ahp->ah_chip_reset_done = 1;
return AH_TRUE;
}
@@ -1987,13 +2018,25 @@ HAL_BOOL
ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan)
{
struct ath_hal_9300 *ahp = AH9300(ah);
+ int type = HAL_RESET_WARM;
OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
/*
* Warm reset is optimistic.
+ *
+ * If the TX/RX DMA engines aren't shut down (eg, they're
+ * wedged) then we're better off doing a full cold reset
+ * to try and shake that condition.
*/
- if (!ar9300_set_reset_reg(ah, HAL_RESET_WARM)) {
+ if (ahp->ah_chip_full_sleep ||
+ (ah->ah_config.ah_force_full_reset == 1) ||
+ OS_REG_READ(ah, AR_Q_TXE) ||
+ (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) {
+ type = HAL_RESET_COLD;
+ }
+
+ if (!ar9300_set_reset_reg(ah, type)) {
return AH_FALSE;
}
@@ -2300,10 +2343,22 @@ ar9300_per_calibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan,
static void
ar9300_start_nf_cal(struct ath_hal *ah)
{
+ struct ath_hal_9300 *ahp = AH9300(ah);
OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
AH9300(ah)->nf_tsf32 = ar9300_get_tsf32(ah);
+
+/*
+ * We are reading the NF values before we start the NF operation, because
+ * of that we are getting very high values like -45.
+ * This triggers the CW_INT detected and EACS module triggers the channel change
+ * chip_reset_done value is used to fix this issue.
+ * chip_reset_flag is set during the RTC reset.
+ * chip_reset_flag is cleared during the starting NF operation.
+ * if flag is set we will clear the flag and will not read the NF values.
+ */
+ ahp->ah_chip_reset_done = 0;
}
/* ar9300_calibration
@@ -2397,7 +2452,7 @@ ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t
ar9300_load_nf(ah, nf_buf);
/* start NF calibration, without updating BB NF register*/
- ar9300_start_nf_cal(ah);
+ ar9300_start_nf_cal(ah);
}
}
return AH_TRUE;
@@ -2447,12 +2502,15 @@ ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains)
u_int32_t q_coff_denom, i_coff_denom;
int32_t q_coff, i_coff;
int iq_corr_neg, i;
+ HAL_CHANNEL_INTERNAL *ichan;
static const u_int32_t offset_array[3] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
};
+ ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan);
+
for (i = 0; i < num_chains; i++) {
power_meas_i = ahp->ah_total_power_meas_i[i];
power_meas_q = ahp->ah_total_power_meas_q[i];
@@ -2525,6 +2583,19 @@ ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains)
OS_REG_RMW_FIELD(ah, offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
+ /* store the RX cal results */
+ if (ichan != NULL) {
+ ahp->ah_rx_cal_corr[i] = OS_REG_READ(ah, offset_array[i]) & 0x7fff;
+ ahp->ah_rx_cal_complete = AH_TRUE;
+ ahp->ah_rx_cal_chan = ichan->channel;
+// ahp->ah_rx_cal_chan_flag = ichan->channel_flags &~ CHANNEL_PASSIVE;
+ ahp->ah_rx_cal_chan_flag = 0; /* XXX */
+ } else {
+ /* XXX? Is this what I should do? */
+ ahp->ah_rx_cal_complete = AH_FALSE;
+
+ }
+
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
"Register offset (0x%04x) QI COFF (bitfields 0x%08x) "
"after update = 0x%x\n",
@@ -2551,6 +2622,55 @@ ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains)
}
/*
+ * When coming back from offchan, we do not perform RX IQ Cal.
+ * But the chip reset will clear all previous results
+ * We store the previous results and restore here.
+ */
+static void
+ar9300_rx_iq_cal_restore(struct ath_hal *ah)
+{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+ u_int32_t i_coff, q_coff;
+ HAL_BOOL is_restore = AH_FALSE;
+ int i;
+ static const u_int32_t offset_array[3] = {
+ AR_PHY_RX_IQCAL_CORR_B0,
+ AR_PHY_RX_IQCAL_CORR_B1,
+ AR_PHY_RX_IQCAL_CORR_B2,
+ };
+
+ for (i=0; i<AR9300_MAX_CHAINS; i++) {
+ if (ahp->ah_rx_cal_corr[i]) {
+ i_coff = (ahp->ah_rx_cal_corr[i] &
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF) >>
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S;
+ q_coff = (ahp->ah_rx_cal_corr[i] &
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF) >>
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S;
+
+ OS_REG_RMW_FIELD(ah, offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff);
+ OS_REG_RMW_FIELD(ah, offset_array[i],
+ AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
+
+ is_restore = AH_TRUE;
+ }
+ }
+
+ if (is_restore)
+ OS_REG_SET_BIT(ah,
+ AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
+
+ HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+ "%s: IQ Cal and Correction (offset 0x%04x) enabled "
+ "(bit position 0x%08x). New Value 0x%08x\n",
+ __func__,
+ (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
+ AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
+ OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
+}
+
+/*
* Set a limit on the overall output power. Used for dynamic
* transmit power control and the like.
*
@@ -3727,6 +3847,13 @@ ar9300_init_cal_internal(struct ath_hal *ah, struct ieee80211_channel *chan,
#endif
/* end - Init time calibrations */
+ /* Do not do RX cal in case of offchan, or cal data already exists on same channel*/
+ if (ahp->ah_skip_rx_iq_cal) {
+ HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+ "Skip RX IQ Cal\n");
+ return AH_TRUE;
+ }
+
/* If Cals are supported, add them to list via INIT/INSERT_CAL */
if (AH_TRUE == ar9300_is_cal_supp(ah, chan, IQ_MISMATCH_CAL)) {
INIT_CAL(&ahp->ah_iq_cal_data);
@@ -3827,6 +3954,8 @@ ar9300_set_dma(struct ath_hal *ah)
{
u_int32_t regval;
struct ath_hal_9300 *ahp = AH9300(ah);
+ struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+ HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
#if 0
/*
@@ -3886,9 +4015,14 @@ ar9300_set_dma(struct ath_hal *ah)
/*
* Enable HPQ for UAPSD
*/
- if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
- OS_REG_WRITE(ah, AR_HP_Q_CONTROL,
- AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN);
+ if (pCap->halHwUapsdTrig == AH_TRUE) {
+ /* Only enable this if HAL capabilities says it is OK */
+ if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
+ OS_REG_WRITE(ah, AR_HP_Q_CONTROL,
+ AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN);
+ }
+ } else {
+ /* use default value from ini file - which disable HPQ queue usage */
}
/*
@@ -4307,6 +4441,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
HAL_BOOL stopped, cal_ret;
HAL_BOOL apply_last_iqcorr = AH_FALSE;
+
if (OS_REG_READ(ah, AR_IER) == AR_IER_ENABLE) {
HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "** Reset called with WLAN "
"interrupt enabled %08x **\n", ar9300_get_interrupts(ah));
@@ -4335,6 +4470,11 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
ahp->ah_rx_chainmask = rxchainmask & ap->ah_caps.halRxChainMask;
ahp->ah_tx_cal_chainmask = ap->ah_caps.halTxChainMask;
ahp->ah_rx_cal_chainmask = ap->ah_caps.halRxChainMask;
+
+ /*
+ * Keep the previous optinal txchainmask value
+ */
+
HALASSERT(ar9300_check_op_mode(opmode));
OS_MARK(ah, AH_MARK_RESET, b_channel_change);
@@ -4441,7 +4581,21 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
#if 0
/* Get the value from the previous NF cal and update history buffer */
if (curchan && (ahp->ah_chip_full_sleep != AH_TRUE)) {
- ar9300_store_new_nf(ah, curchan, is_scan);
+
+ if(ahp->ah_chip_reset_done){
+ ahp->ah_chip_reset_done = 0;
+ } else {
+ /*
+ * is_scan controls updating NF for home channel or off channel.
+ * Home -> Off, update home channel
+ * Off -> Home, update off channel
+ * Home -> Home, uppdate home channel
+ */
+ if (ap->ah_curchan->channel != chan->channel)
+ ar9300_store_new_nf(ah, curchan, !is_scan);
+ else
+ ar9300_store_new_nf(ah, curchan, is_scan);
+ }
}
#endif
@@ -4452,7 +4606,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
AH9300(ah)->nfp = IS_CHAN_2GHZ(ichan) ? &ahp->nf_2GHz : &ahp->nf_5GHz;
/*
- * XXX For now, don't apply the last IQ correction.
+ * XXX FreeBSD For now, don't apply the last IQ correction.
*
* This should be done when scorpion is enabled on FreeBSD; just be
* sure to fix this channel match code so it uses net80211 flags
@@ -4489,6 +4643,34 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
}
#endif
/*
+ * In case of
+ * - offchan scan, or
+ * - same channel and RX IQ Cal already available
+ * disable RX IQ Cal.
+ */
+ if (is_scan) {
+ ahp->ah_skip_rx_iq_cal = AH_TRUE;
+ HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+ "Skip RX IQ Cal due to scanning\n");
+ } else {
+#if 0
+ /* XXX FreeBSD: always just do the RX IQ cal */
+ /* XXX I think it's just going to speed things up; I don't think it's to avoid chan bugs */
+ if (ahp->ah_rx_cal_complete &&
+ ahp->ah_rx_cal_chan == ichan->channel &&
+ ahp->ah_rx_cal_chan_flag == chan->channel_flags) {
+ ahp->ah_skip_rx_iq_cal = AH_TRUE;
+ HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+ "Skip RX IQ Cal due to same channel with completed RX IQ Cal\n");
+ } else
+#endif
+ ahp->ah_skip_rx_iq_cal = AH_FALSE;
+ }
+
+ /* FreeBSD: clear the channel survey data */
+ ath_hal_survey_clear(ah);
+
+ /*
* Fast channel change (Change synthesizer based on channel freq
* without resetting chip)
* Don't do it when
@@ -4854,6 +5036,23 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
ar9300_init_bb(ah, chan);
/* BB Step 7: Calibration */
+ /*
+ * Only kick off calibration not on offchan.
+ * If coming back from offchan, restore prevous Cal results
+ * since chip reset will clear existings.
+ */
+ if (!ahp->ah_skip_rx_iq_cal) {
+ int i;
+ /* clear existing RX cal data */
+ for (i=0; i<AR9300_MAX_CHAINS; i++)
+ ahp->ah_rx_cal_corr[i] = 0;
+
+ ahp->ah_rx_cal_complete = AH_FALSE;
+// ahp->ah_rx_cal_chan = chan->channel;
+// ahp->ah_rx_cal_chan_flag = ichan->channel_flags;
+ ahp->ah_rx_cal_chan = 0;
+ ahp->ah_rx_cal_chan_flag = 0; /* XXX FreeBSD */
+ }
ar9300_invalidate_saved_cals(ah, ichan);
cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr);
@@ -5009,6 +5208,11 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
nf_hist_buff_reset = 0;
#ifndef ATH_NF_PER_CHAN
if (First_NFCal(ah, ichan, is_scan, chan)){
+ if (ahp->ah_skip_rx_iq_cal && !is_scan) {
+ /* restore RX Cal result if existing */
+ ar9300_rx_iq_cal_restore(ah);
+ ahp->ah_skip_rx_iq_cal = AH_FALSE;
+ }
}
#endif /* ATH_NF_PER_CHAN */
}
@@ -5082,12 +5286,24 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
ar9300_set_smart_antenna(ah, ahp->ah_smartantenna_enable);
+ if (ahp->ah_skip_rx_iq_cal && !is_scan) {
+ /* restore RX Cal result if existing */
+ ar9300_rx_iq_cal_restore(ah);
+ ahp->ah_skip_rx_iq_cal = AH_FALSE;
+ }
+
return AH_TRUE;
bad:
OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
*status = ecode;
+ if (ahp->ah_skip_rx_iq_cal && !is_scan) {
+ /* restore RX Cal result if existing */
+ ar9300_rx_iq_cal_restore(ah);
+ ahp->ah_skip_rx_iq_cal = AH_FALSE;
+ }
+
return AH_FALSE;
#undef FAIL
}
@@ -6139,6 +6355,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);
@@ -6186,5 +6403,7 @@ ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, cons
} else {
return AH_TRUE;
}
+
+ /* XXX TODO: Add AR9565 support? */
}
#endif /* ATH_ANT_DIV_COMB */
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c
index 2dd9472..211e201 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c
@@ -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;
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c
index ab39284..530b29a 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c
@@ -583,6 +583,14 @@ ar9300_num_tx_pending(struct ath_hal *ah, u_int q)
HAL_BOOL
ar9300_stop_tx_dma(struct ath_hal *ah, u_int q, u_int timeout)
{
+ struct ath_hal_9300 *ahp = AH9300(ah);
+
+ /*
+ * If we call abort txdma instead, no need to stop RX.
+ * Otherwise, the RX logic might not be restarted properly.
+ */
+ ahp->ah_abort_txdma_norx = AH_FALSE;
+
/*
* Directly call abort. It is better, hardware-wise, to stop all
* queues at once than individual ones.
@@ -798,10 +806,40 @@ ar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout)
*/
#define AR9300_ABORT_LOOPS 1000
#define AR9300_ABORT_WAIT 5
+#define NEXT_TBTT_NOW 10
HAL_BOOL
ar9300_abort_tx_dma(struct ath_hal *ah)
{
+ struct ath_hal_9300 *ahp = AH9300(ah);
int i, q;
+ u_int32_t nexttbtt, nextdba, tsf_tbtt, tbtt, dba;
+ HAL_BOOL stopped;
+ HAL_BOOL status = AH_TRUE;
+
+ if (ahp->ah_abort_txdma_norx) {
+ /*
+ * First of all, make sure RX has been stopped
+ */
+ if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) {
+ /* Need to stop RX DMA before reset otherwise chip might hang */
+ stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */
+ ar9300_set_rx_filter(ah, 0);
+ stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */
+ if (!stopped) {
+ /*
+ * During the transition from full sleep to reset,
+ * recv DMA regs are not available to be read
+ */
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__);
+ //We still continue to stop TX dma
+ //return AH_FALSE;
+ }
+ } else {
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__);
+ }
+ }
/*
* set txd on all queues
@@ -812,13 +850,27 @@ ar9300_abort_tx_dma(struct ath_hal *ah)
* set tx abort bits (also disable rx)
*/
OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
- OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
- AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR));
+ /* Add a new receipe from K31 code */
+ OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
+ AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+ /* beacon Q flush */
+ nexttbtt = OS_REG_READ(ah, AR_NEXT_TBTT_TIMER);
+ nextdba = OS_REG_READ(ah, AR_NEXT_DMA_BEACON_ALERT);
+ //printk("%s[%d]:dba: %d, nt: %d \n", __func__, __LINE__, nextdba, nexttbtt);
+ tsf_tbtt = OS_REG_READ(ah, AR_TSF_L32);
+ tbtt = tsf_tbtt + NEXT_TBTT_NOW;
+ dba = tsf_tbtt;
+ OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, dba);
+ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, tbtt);
OS_REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
- /* Let TXE (all queues) clear before waiting on any pending frames */
- for (i = 0; i < AR9300_ABORT_LOOPS; i++) {
- if (OS_REG_READ(ah, AR_Q_TXE) == 0) {
+ /*
+ * Let TXE (all queues) clear before waiting for any pending frames
+ * This is needed before starting the RF_BUS GRANT sequence other wise causes kernel
+ * panic
+ */
+ for(i = 0; i < AR9300_ABORT_LOOPS; i++) {
+ if(OS_REG_READ(ah, AR_Q_TXE) == 0) {
break;
}
OS_DELAY(AR9300_ABORT_WAIT);
@@ -830,28 +882,38 @@ ar9300_abort_tx_dma(struct ath_hal *ah)
/*
* wait on all tx queues
+ * This need to be checked in the last to gain extra 50 usec. on avg.
+ * Currently checked first since we dont have a previous channel information currently.
+ * Which is needed to revert the rf changes.
*/
- for (q = 0; q < AR_NUM_QCU; q++) {
+ for (q = AR_NUM_QCU - 1; q >= 0; q--) {
for (i = 0; i < AR9300_ABORT_LOOPS; i++) {
- if (!ar9300_num_tx_pending(ah, q)) {
+ if (!(ar9300_num_tx_pending(ah, q))) {
break;
}
OS_DELAY(AR9300_ABORT_WAIT);
}
if (i == AR9300_ABORT_LOOPS) {
- HALDEBUG(ah, HAL_DEBUG_TX,
- "%s[%d] reached max wait on pending tx, q %d\n",
- __func__, __LINE__, q);
- return AH_FALSE;
+ status = AH_FALSE;
+ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
+ "ABORT LOOP finsihsed for Q: %d, num_pending: %d \n",
+ q, ar9300_num_tx_pending(ah, q));
+ goto exit;
}
}
+ /* Updating the beacon alert register with correct value */
+ OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, nextdba);
+ OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, nexttbtt);
+
+exit:
/*
* clear tx abort bits
*/
OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
- OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
- AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR));
+ /* Added a new receipe from K31 code */
+ OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS |
+ AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
OS_REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
/*
@@ -859,7 +921,9 @@ ar9300_abort_tx_dma(struct ath_hal *ah)
*/
OS_REG_WRITE(ah, AR_Q_TXD, 0);
- return AH_TRUE;
+ ahp->ah_abort_txdma_norx = AH_TRUE;
+
+ return status;
}
/*
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
index 596f6dc..72ed110 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c
@@ -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;
}
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h
index 9054db0..5dbf927 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300desc.h
@@ -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)|\
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini
index 81894de..ef7dbca 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini
@@ -1078,7 +1078,7 @@ static const u_int32_t ar9340_wasp_1p0_mac_postamble[][5] = {
{ 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b },
- { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 },
+ { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 },
{ 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a },
@@ -1212,7 +1212,7 @@ static const u_int32_t ar9340_wasp_1p0_baseband_postamble[][5] = {
{ 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
- { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c },
+ { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c },
{ 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce },
@@ -1586,10 +1586,14 @@ static const u_int32_t ar9340_wasp_1p0_baseband_postamble_dfs_channel[][3] = {
{ 0x00009824 , 0x5ac668d0 , 0x5ac668d0 },
+ { 0x00009828 , 0x06903080 , 0x06903080 },
+
{ 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 },
{ 0x00009e14 , 0x37b9625e , 0x37b9625e },
+ { 0x00009814 , 0x3400c00f , 0x3400c00f },
+
};
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini
index 32124db..52b92ff 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini
@@ -34,8 +34,10 @@
static const u_int32_t ar9300_ar9580_1p0_baseband_postamble_dfs_channel[][3] = {
/* Addr 5G_HT20 5G_HT40 */
{ 0x00009824 , 0x5ac668d0 , 0x5ac668d0 },
+ { 0x00009828 , 0x06903080 , 0x06903080 },
{ 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 },
{ 0x00009e14 , 0x37b9625e , 0x37b9625e },
+ { 0x00009814 , 0x3400c00f , 0x3400c00f },
};
static const u_int32_t ar9300Modes_fast_clock_ar9580_1p0[][3] = {
@@ -257,7 +259,7 @@ static const u_int32_t ar9300_ar9580_1p0_mac_postamble[][5] = {
{ 0x000010b0 , 0x00000e60 , 0x00001cc0 , 0x00007c70 , 0x00003e38 },
{ 0x00008014 , 0x03e803e8 , 0x07d007d0 , 0x10801600 , 0x08400b00 },
{ 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b },
- { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 },
+ { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 },
{ 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a },
{ 0x00008318 , 0x00003e80 , 0x00007d00 , 0x00006880 , 0x00003440 },
};
@@ -1091,7 +1093,7 @@ static const u_int32_t ar9300_ar9580_1p0_mac_core[][2] = {
{ 0x00008258 , 0x00000000 },
{ 0x0000825c , 0x40000000 },
{ 0x00008260 , 0x00080922 },
- { 0x00008264 , 0x9bc00010 },
+ { 0x00008264 , 0x9d400010 },
{ 0x00008268 , 0xffffffff },
{ 0x0000826c , 0x0000ffff },
{ 0x00008270 , 0x00000000 },
@@ -2155,7 +2157,7 @@ static const u_int32_t ar9300_ar9580_1p0_baseband_postamble[][5] = {
{ 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec84d2e , 0x7ec84d2e },
{ 0x00009e14 , 0x37b95d5e , 0x37b9605e , 0x3379605e , 0x33795d5e },
{ 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 },
- { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c },
+ { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c },
{ 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce },
{ 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 },
{ 0x00009e3c , 0xcf946220 , 0xcf946220 , 0xcf946222 , 0xcf946222 },
diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c
index 043ebed..5c29e26 100644
--- a/sys/dev/ath/ah_osdep.c
+++ b/sys/dev/ath/ah_osdep.c
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ah_osdep.c 267992 2014-06-28 03:56:17Z hselasky $
*/
#include "opt_ah.h"
@@ -96,9 +96,8 @@ static SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0,
#ifdef AH_DEBUG
int ath_hal_debug = 0;
-SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug,
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RWTUN, &ath_hal_debug,
0, "Atheros HAL debugging printfs");
-TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug);
#endif /* AH_DEBUG */
static MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
@@ -138,6 +137,24 @@ ath_hal_ether_sprintf(const u_int8_t *mac)
#ifdef AH_DEBUG
+/*
+ * XXX This is highly relevant only for the AR5416 and later
+ * PCI/PCIe NICs. It'll need adjustment for other hardware
+ * variations.
+ */
+static int
+ath_hal_reg_whilst_asleep(struct ath_hal *ah, uint32_t reg)
+{
+
+ if (reg >= 0x4000 && reg < 0x5000)
+ return (1);
+ if (reg >= 0x6000 && reg < 0x7000)
+ return (1);
+ if (reg >= 0x7000 && reg < 0x8000)
+ return (1);
+ return (0);
+}
+
void
DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
{
@@ -253,6 +270,13 @@ ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
bus_space_tag_t tag = BUSTAG(ah);
bus_space_handle_t h = ah->ah_sh;
+ /* Debug - complain if we haven't fully waken things up */
+ if (! ath_hal_reg_whilst_asleep(ah, reg) &&
+ ah->ah_powerMode != HAL_PM_AWAKE) {
+ ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
+ __func__, reg, val, ah->ah_powerMode);
+ }
+
if (ath_hal_alq) {
struct ale *ale = ath_hal_alq_get(ah);
if (ale) {
@@ -278,6 +302,13 @@ ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
bus_space_handle_t h = ah->ah_sh;
u_int32_t val;
+ /* Debug - complain if we haven't fully waken things up */
+ if (! ath_hal_reg_whilst_asleep(ah, reg) &&
+ ah->ah_powerMode != HAL_PM_AWAKE) {
+ ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
+ __func__, reg, ah->ah_powerMode);
+ }
+
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
val = bus_space_read_4(tag, h, reg);
@@ -330,6 +361,13 @@ ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
bus_space_tag_t tag = BUSTAG(ah);
bus_space_handle_t h = ah->ah_sh;
+ /* Debug - complain if we haven't fully waken things up */
+ if (! ath_hal_reg_whilst_asleep(ah, reg) &&
+ ah->ah_powerMode != HAL_PM_AWAKE) {
+ ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n",
+ __func__, reg, val, ah->ah_powerMode);
+ }
+
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
bus_space_write_4(tag, h, reg, val);
@@ -344,6 +382,13 @@ ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
bus_space_handle_t h = ah->ah_sh;
u_int32_t val;
+ /* Debug - complain if we haven't fully waken things up */
+ if (! ath_hal_reg_whilst_asleep(ah, reg) &&
+ ah->ah_powerMode != HAL_PM_AWAKE) {
+ ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n",
+ __func__, reg, ah->ah_powerMode);
+ }
+
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
val = bus_space_read_4(tag, h, reg);
diff --git a/sys/dev/ath/ah_osdep.h b/sys/dev/ath/ah_osdep.h
index 50778f2..3c31327 100644
--- a/sys/dev/ath/ah_osdep.h
+++ b/sys/dev/ath/ah_osdep.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ah_osdep.h 239051 2012-08-05 10:12:27Z adrian $
*/
#ifndef _ATH_AH_OSDEP_H_
#define _ATH_AH_OSDEP_H_
diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c
index 36b2042..94a391d 100644
--- a/sys/dev/ath/ath_dfs/null/dfs_null.c
+++ b/sys/dev/ath/ath_dfs/null/dfs_null.c
@@ -26,10 +26,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_dfs/null/dfs_null.c 257176 2013-10-26 17:58:36Z glebius $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/ath_dfs/null/dfs_null.c 257176 2013-10-26 17:58:36Z glebius $");
/*
* This implements an empty DFS module.
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -53,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
index 7187d57..0fab78b 100644
--- a/sys/dev/ath/ath_hal/ah.c
+++ b/sys/dev/ath/ath_hal/ah.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah.c 280828 2015-03-29 21:50:21Z adrian $
*/
#include "opt_ah.h"
@@ -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;
@@ -786,6 +789,8 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
return HAL_OK;
case HAL_CAP_RX_LNA_MIXING: /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
+ case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */
+ return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
default:
return HAL_EINVAL;
}
@@ -848,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);
@@ -875,6 +881,7 @@ ath_hal_getdiagstate(struct ath_hal *ah, int request,
const void *args, uint32_t argsize,
void **result, uint32_t *resultsize)
{
+
switch (request) {
case HAL_DIAG_REVS:
*result = &AH_PRIVATE(ah)->ah_devid;
@@ -932,6 +939,10 @@ ath_hal_getdiagstate(struct ath_hal *ah, int request,
} else
return AH_FALSE;
return AH_TRUE;
+ case HAL_DIAG_CHANSURVEY:
+ *result = &AH_PRIVATE(ah)->ah_chansurvey;
+ *resultsize = sizeof(HAL_CHANNEL_SURVEY);
+ return AH_TRUE;
}
return AH_FALSE;
}
@@ -1427,3 +1438,32 @@ ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
else
return 15 + ((ichan->channel - 2512) / 20);
}
+
+/*
+ * Clear the current survey data.
+ *
+ * This should be done during a channel change.
+ */
+void
+ath_hal_survey_clear(struct ath_hal *ah)
+{
+
+ OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey,
+ sizeof(AH_PRIVATE(ah)->ah_chansurvey));
+}
+
+/*
+ * Add a sample to the channel survey.
+ */
+void
+ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs)
+{
+ HAL_CHANNEL_SURVEY *cs;
+
+ cs = &AH_PRIVATE(ah)->ah_chansurvey;
+
+ OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs));
+ cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
+ cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
+ cs->cur_seq++;
+}
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index 2480803..a17d74e 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah.h 280940 2015-04-01 03:42:46Z adrian $
*/
#ifndef _ATH_AH_H_
@@ -199,6 +199,7 @@ typedef enum {
HAL_CAP_SERIALISE_WAR = 245, /* serialise register access on PCI */
HAL_CAP_ENFORCE_TXOP = 246, /* Enforce TXOP if supported */
HAL_CAP_RX_LNA_MIXING = 247, /* RX hardware uses LNA mixing */
+ HAL_CAP_DO_MYBEACON = 248, /* Supports HAL_RX_FILTER_MYBEACON */
} HAL_CAPABILITY_TYPE;
/*
@@ -404,6 +405,7 @@ typedef enum {
HAL_RX_FILTER_PROM = 0x00000020, /* Promiscuous mode */
HAL_RX_FILTER_PROBEREQ = 0x00000080, /* Allow probe request frames */
HAL_RX_FILTER_PHYERR = 0x00000100, /* Allow phy errors */
+ HAL_RX_FILTER_MYBEACON = 0x00000200, /* Filter beacons other than mine */
HAL_RX_FILTER_COMPBAR = 0x00000400, /* Allow compressed BAR */
HAL_RX_FILTER_COMP_BA = 0x00000800, /* Allow compressed blockack */
HAL_RX_FILTER_PHYRADAR = 0x00002000, /* Allow phy radar errors */
@@ -538,6 +540,7 @@ typedef enum {
typedef struct {
u_int32_t cyclecnt_diff; /* delta cycle count */
u_int32_t rxclr_cnt; /* rx clear count */
+ u_int32_t extrxclr_cnt; /* ext chan rx clear count */
u_int32_t txframecnt_diff; /* delta tx frame count */
u_int32_t rxframecnt_diff; /* delta rx frame count */
u_int32_t listen_time; /* listen time in msec - time for which ch is free */
@@ -847,6 +850,48 @@ typedef struct {
#define HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */
+/*
+ * This is the ANI state and MIB stats.
+ *
+ * It's used by the HAL modules to keep state /and/ by the debug ioctl
+ * to fetch ANI information.
+ */
+typedef struct {
+ uint32_t ast_ani_niup; /* ANI increased noise immunity */
+ uint32_t ast_ani_nidown; /* ANI decreased noise immunity */
+ uint32_t ast_ani_spurup; /* ANI increased spur immunity */
+ uint32_t ast_ani_spurdown;/* ANI descreased spur immunity */
+ uint32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */
+ uint32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */
+ uint32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */
+ uint32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */
+ uint32_t ast_ani_stepup; /* ANI increased first step level */
+ uint32_t ast_ani_stepdown;/* ANI decreased first step level */
+ uint32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */
+ uint32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */
+ uint32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */
+ uint32_t ast_ani_lzero; /* ANI listen time forced to zero */
+ uint32_t ast_ani_lneg; /* ANI listen time calculated < 0 */
+ HAL_MIB_STATS ast_mibstats; /* MIB counter stats */
+ HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */
+} HAL_ANI_STATS;
+
+typedef struct {
+ uint8_t noiseImmunityLevel;
+ uint8_t spurImmunityLevel;
+ uint8_t firstepLevel;
+ uint8_t ofdmWeakSigDetectOff;
+ uint8_t cckWeakSigThreshold;
+ uint32_t listenTime;
+
+ /* NB: intentionally ordered so data exported to user space is first */
+ uint32_t txFrameCount; /* Last txFrameCount */
+ uint32_t rxFrameCount; /* Last rx Frame count */
+ uint32_t cycleCount; /* Last cycleCount
+ (to detect wrap-around) */
+ uint32_t ofdmPhyErrCount;/* OFDM err count since last reset */
+ uint32_t cckPhyErrCount; /* CCK err count since last reset */
+} HAL_ANI_STATE;
struct ath_desc;
struct ath_tx_status;
@@ -1262,6 +1307,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;
@@ -1297,6 +1343,9 @@ struct ath_hal {
uint32_t ah_intrstate[8]; /* last int state */
uint32_t ah_syncstate; /* last sync intr state */
+ /* Current powerstate from HAL calls */
+ HAL_POWER_MODE ah_powerMode;
+
HAL_OPS_CONFIG ah_config;
const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *,
u_int mode);
@@ -1583,6 +1632,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);
+ uint32_t __ahdecl(*ah_btMciGetInterrupt)(struct ath_hal *,
+ uint32_t *, uint32_t *);
+ uint32_t __ahdecl(*ah_btMciGetState)(struct ath_hal *,
+ uint32_t, uint32_t *);
+ void __ahdecl(*ah_btMciDetach)(struct ath_hal *);
+
/* LNA diversity configuration */
void __ahdecl(*ah_divLnaConfGet)(struct ath_hal *,
HAL_ANT_COMB_CONFIG *);
@@ -1611,7 +1672,8 @@ extern const char *__ahdecl ath_hal_probe(uint16_t vendorid, uint16_t devid);
* be returned if the status parameter is non-zero.
*/
extern struct ath_hal * __ahdecl ath_hal_attach(uint16_t devid, HAL_SOFTC,
- HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata, HAL_STATUS* status);
+ HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config, HAL_STATUS* status);
extern const char *ath_hal_mac_name(struct ath_hal *);
extern const char *ath_hal_rf_name(struct ath_hal *);
diff --git a/sys/dev/ath/ath_hal/ah_debug.h b/sys/dev/ath/ath_hal/ah_debug.h
index 933811f..a10226b 100644
--- a/sys/dev/ath/ath_hal/ah_debug.h
+++ b/sys/dev/ath/ath_hal/ah_debug.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_debug.h 249131 2013-04-05 07:41:47Z adrian $
*/
#ifndef _ATH_AH_DEBUG_H_
#define _ATH_AH_DEBUG_H_
diff --git a/sys/dev/ath/ath_hal/ah_decode.h b/sys/dev/ath/ath_hal/ah_decode.h
index 07c4ac7..7c2ff5b 100644
--- a/sys/dev/ath/ath_hal/ah_decode.h
+++ b/sys/dev/ath/ath_hal/ah_decode.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_decode.h 269749 2014-08-09 09:13:10Z adrian $
*/
#ifndef _ATH_AH_DECODE_H_
#define _ATH_AH_DECODE_H_
@@ -53,6 +53,8 @@ enum {
AH_MARK_ANI_POLL, /* ar*AniReset, listen time */
AH_MARK_ANI_CONTROL, /* ar*AniReset, cmd */
AH_MARK_RX_CTL, /* RX DMA control */
+ AH_MARK_CHIP_POWER, /* chip power control, mode */
+ AH_MARK_CHIP_POWER_DONE, /* chip power control done, status */
};
enum {
@@ -61,6 +63,7 @@ enum {
AH_MARK_RX_CTL_DMA_START,
AH_MARK_RX_CTL_DMA_STOP,
AH_MARK_RX_CTL_DMA_STOP_ERR,
+ AH_MARK_RX_CTL_DMA_STOP_OK,
};
#endif /* _ATH_AH_DECODE_H_ */
diff --git a/sys/dev/ath/ath_hal/ah_desc.h b/sys/dev/ath/ath_hal/ah_desc.h
index 9f58dce..badc73f 100644
--- a/sys/dev/ath/ath_hal/ah_desc.h
+++ b/sys/dev/ath/ath_hal/ah_desc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_desc.h 251399 2013-06-05 00:39:20Z adrian $
*/
#ifndef _DEV_ATH_DESC_H
diff --git a/sys/dev/ath/ath_hal/ah_devid.h b/sys/dev/ath/ath_hal/ah_devid.h
index 43d994d..4f0bb50 100644
--- a/sys/dev/ath/ath_hal/ah_devid.h
+++ b/sys/dev/ath/ath_hal/ah_devid.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_devid.h 265348 2014-05-05 07:58:05Z adrian $
*/
#ifndef _DEV_ATH_DEVID_H_
@@ -92,6 +92,7 @@
#define AR9300_DEVID_AR946X_PCIE 0x0034
#define AR9300_DEVID_AR9330 0x0035
#define AR9300_DEVID_QCA9565 0x0036
+#define AR9300_DEVID_AR1111_PCIE 0x0037
#define AR9300_DEVID_QCA955X 0x0039
#define AR_SUBVENDOR_ID_NOG 0x0e11 /* No 11G subvendor ID */
diff --git a/sys/dev/ath/ath_hal/ah_diagcodes.h b/sys/dev/ath/ath_hal/ah_diagcodes.h
index df23242..efad838 100644
--- a/sys/dev/ath/ath_hal/ah_diagcodes.h
+++ b/sys/dev/ath/ath_hal/ah_diagcodes.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_diagcodes.h 239629 2012-08-24 00:17:39Z adrian $
*/
#ifndef _ATH_AH_DIAGCODES_H_
#define _ATH_AH_DIAGCODES_H_
diff --git a/sys/dev/ath/ath_hal/ah_eeprom.h b/sys/dev/ath/ath_hal/ah_eeprom.h
index 3e9330b..247b9e8 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom.h 239637 2012-08-24 01:14:00Z adrian $
*/
#ifndef _ATH_AH_EEPROM_H_
#define _ATH_AH_EEPROM_H_
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.c b/sys/dev/ath/ath_hal/ah_eeprom_9287.c
index abdbce0..4e5d895 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_9287.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_9287.c 239704 2012-08-26 04:26:49Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.h b/sys/dev/ath/ath_hal/ah_eeprom_9287.h
index ff8080a..d6e1a24 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_9287.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_9287.h 223615 2011-06-28 00:01:55Z adrian $
*/
#ifndef __AH_EEPROM_9287_H__
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v1.c b/sys/dev/ath/ath_hal/ah_eeprom_v1.c
index 8b4664f..9925b8d 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v1.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v1.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v1.c 221896 2011-05-14 15:12:02Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v1.h b/sys/dev/ath/ath_hal/ah_eeprom_v1.h
index 22fce8a..3f34ab5 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v1.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v1.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v1.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _ATH_AH_EEPROM_V1_H_
#define _ATH_AH_EEPROM_V1_H_
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.c b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
index 37e973c..71597e1 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v14.c 224519 2011-07-30 13:45:12Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.h b/sys/dev/ath/ath_hal/ah_eeprom_v14.h
index 7b2c898..ba8c581 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v14.h 224519 2011-07-30 13:45:12Z adrian $
*/
#ifndef _AH_EEPROM_V14_H_
#define _AH_EEPROM_V14_H_
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
index 3a7b0cc..df69550 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v3.c 221896 2011-05-14 15:12:02Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.h b/sys/dev/ath/ath_hal/ah_eeprom_v3.h
index cde9a10..33e8241 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v3.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v3.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _ATH_AH_EEPROM_V3_H_
#define _ATH_AH_EEPROM_V3_H_
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
index 12cb67e..66f4f4c 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v4k.c 234508 2012-04-20 21:56:13Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v4k.h b/sys/dev/ath/ath_hal/ah_eeprom_v4k.h
index 3487de4..b9af2bc 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v4k.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v4k.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_eeprom_v4k.h 220946 2011-04-22 10:57:46Z adrian $
*/
#ifndef _AH_EEPROM_V4K_H_
#define _AH_EEPROM_V4K_H_
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index 908f33e..d229b94 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_internal.h 280828 2015-03-29 21:50:21Z adrian $
*/
#ifndef _ATH_AH_INTERAL_H_
#define _ATH_AH_INTERAL_H_
@@ -50,8 +50,8 @@
#endif
typedef struct {
- uint16_t start; /* first register */
- uint16_t end; /* ending register or zero */
+ uint32_t start; /* first register */
+ uint32_t end; /* ending register or zero */
} HAL_REGRANGE;
typedef struct {
@@ -91,6 +91,7 @@ struct ath_hal_chip {
const char *(*probe)(uint16_t vendorid, uint16_t devid);
struct ath_hal *(*attach)(uint16_t devid, HAL_SOFTC,
HAL_BUS_TAG, HAL_BUS_HANDLE, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah,
HAL_STATUS *error);
};
#ifndef AH_CHIP
@@ -280,7 +281,9 @@ typedef struct {
halAntDivCombSupportOrg : 1,
halRadioRetentionSupport : 1,
halSpectralScanSupport : 1,
- halRxUsingLnaMixing : 1;
+ halRxUsingLnaMixing : 1,
+ halRxDoMyBeacon : 1,
+ halHwUapsdTrig : 1;
uint32_t halWirelessModes;
uint16_t halTotalQueues;
@@ -419,9 +422,13 @@ struct ath_hal_private {
uint32_t ah_fatalState[6]; /* AR_ISR+shadow regs */
int ah_rxornIsFatal; /* how to treat HAL_INT_RXORN */
-#ifndef ATH_NF_PER_CHAN
+ /* Only used if ATH_NF_PER_CHAN is defined */
HAL_NFCAL_HIST_FULL nf_cal_hist;
-#endif /* ! ATH_NF_PER_CHAN */
+
+ /*
+ * Channel survey history - current channel only.
+ */
+ HAL_CHANNEL_SURVEY ah_chansurvey; /* channel survey */
};
#define AH_PRIVATE(_ah) ((struct ath_hal_private *)(_ah))
@@ -1026,4 +1033,15 @@ ath_hal_getantennaallowed(struct ath_hal *ah,
*/
extern int ath_hal_mhz2ieee_2ghz(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
+/*
+ * Clear the channel survey data.
+ */
+extern void ath_hal_survey_clear(struct ath_hal *ah);
+
+/*
+ * Add a sample to the channel survey data.
+ */
+extern void ath_hal_survey_add_sample(struct ath_hal *ah,
+ HAL_SURVEY_SAMPLE *hs);
+
#endif /* _ATH_AH_INTERAL_H_ */
diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c
index 807db44..1148c59 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain.c
+++ b/sys/dev/ath/ath_hal/ah_regdomain.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain.c 262375 2014-02-23 18:07:17Z hiren $
*/
#include "opt_ah.h"
@@ -169,6 +169,11 @@ isEepromValid(struct ath_hal *ah)
if (regDomainPairs[i].regDmnEnum == rd)
return AH_TRUE;
}
+
+ if (rd == FCC_UBNT) {
+ return AH_TRUE;
+ }
+
HALDEBUG(ah, HAL_DEBUG_REGDOMAIN,
"%s: invalid regulatory domain/country code 0x%x\n", __func__, rd);
return AH_FALSE;
diff --git a/sys/dev/ath/ath_hal/ah_regdomain.h b/sys/dev/ath/ath_hal/ah_regdomain.h
index e17e79a..e950370 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain.h 219442 2011-03-10 03:13:56Z adrian $
*/
#ifndef __AH_REGDOMAIN_H__
#define __AH_REGDOMAIN_H__
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
index af4824c..5a086ae 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h 224226 2011-07-20 12:46:58Z adrian $
*/
#ifndef __AH_REGDOMAIN_CTRY_H__
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h
index 04a6ccd..0be44c0 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_domains.h 248677 2013-03-24 04:42:56Z adrian $
*/
#ifndef __AH_REGDOMAIN_DOMAINS_H__
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h
index 79d418f..e8c6d78 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_freqbands.h 219442 2011-03-10 03:13:56Z adrian $
*/
#ifndef __AH_REGDOMAIN_FREQBANDS_H__
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
index bc569cb..8f6b3e5 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h 262375 2014-02-23 18:07:17Z hiren $
*/
#ifndef __AH_REGDOMAIN_REGENUM_H__
@@ -51,6 +51,7 @@ enum {
FCC2_FCCA = 0x20, /* Canada */
FCC2_WORLD = 0x21, /* Australia & HK */
FCC2_ETSIC = 0x22,
+ FCC_UBNT = 0x2A, /* Ubiquity PicoStation M2HP */
FRANCE_RES = 0x31, /* Legacy France for OEM */
FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */
FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h
index f77be22..b7d8450 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regmap.h 248677 2013-03-24 04:42:56Z adrian $
*/
#ifndef __AH_REGDOMAIN_REGMAP_H__
diff --git a/sys/dev/ath/ath_hal/ah_soc.h b/sys/dev/ath/ath_hal/ah_soc.h
index ca75ae9..021e35b 100644
--- a/sys/dev/ath/ath_hal/ah_soc.h
+++ b/sys/dev/ath/ath_hal/ah_soc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ah_soc.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _ATH_AH_SOC_H_
#define _ATH_AH_SOC_H_
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h
index 48ccc20..f70eeae 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210.h
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210.h 264899 2014-04-24 23:11:18Z adrian $
*/
#ifndef _ATH_AR5210_H_
#define _ATH_AR5210_H_
@@ -108,7 +108,6 @@ struct ath_hal_5210 {
uint32_t ah_txDescInterruptMask;
uint32_t ah_txEolInterruptMask;
uint32_t ah_txUrnInterruptMask;
- HAL_POWER_MODE ah_powerMode;
uint8_t ah_bssid[IEEE80211_ADDR_LEN];
HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES]; /* beacon+cab+data */
/*
@@ -121,6 +120,8 @@ struct ath_hal_5210 {
u_int ah_slottime; /* user-specified slot time */
u_int ah_acktimeout; /* user-specified ack timeout */
u_int ah_ctstimeout; /* user-specified cts timeout */
+
+ uint16_t ah_associd; /* association id */
};
#define AH5210(ah) ((struct ath_hal_5210 *)(ah))
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
index 3c0ed71..fab58f6 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -183,7 +183,7 @@ static HAL_BOOL ar5210FillCapabilityInfo(struct ath_hal *ah);
*/
static struct ath_hal *
ar5210Attach(uint16_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)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
struct ath_hal_5210 *ahp;
@@ -219,7 +219,7 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
AH_PRIVATE(ah)->ah_powerLimit = AR5210_MAX_RATE_POWER;
AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */
- ahp->ah_powerMode = HAL_PM_UNDEFINED;
+ ah->ah_powerMode = HAL_PM_UNDEFINED;
ahp->ah_staId1Defaults = 0;
ahp->ah_rssiThr = INIT_RSSI_THR;
ahp->ah_sifstime = (u_int) -1;
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
index e12b039..162ef88 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c 225444 2011-09-08 01:23:05Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c b/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c
index 96b1a2c..5f755d3 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_interrupts.c 192397 2009-05-19 17:35:15Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c b/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c
index 87fb067..a9e0eb8 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_keycache.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c
index 8170880..cfaa58b 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c 264899 2014-04-24 23:11:18Z adrian $
*/
#include "opt_ah.h"
@@ -315,6 +315,7 @@ ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId)
/* XXX save bssid for possible re-use on reset */
OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN);
+ ahp->ah_associd = assocId;
OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) |
((assocId & 0x3fff)<<AR_BSS_ID1_AID_S));
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c b/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c
index 0455d65..62fe89c 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_phy.c 191022 2009-04-13 21:01:08Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_power.c b/sys/dev/ath/ath_hal/ar5210/ar5210_power.c
index 1c6909b..12faade 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_power.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_power.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_power.c 265112 2014-04-30 02:03:13Z adrian $
*/
#include "opt_ah.h"
@@ -93,7 +93,6 @@ ar5210SetPowerModeSleep(struct ath_hal *ah, int setChip)
HAL_BOOL
ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
{
- struct ath_hal_5210 *ahp = AH5210(ah);
#ifdef AH_DEBUG
static const char* modes[] = {
"AWAKE",
@@ -105,25 +104,30 @@ ar5210SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
int status = AH_TRUE;
HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode],
+ modes[ah->ah_powerMode], modes[mode],
setChip ? "set chip " : "");
switch (mode) {
case HAL_PM_AWAKE:
+ if (setChip)
+ ah->ah_powerMode = mode;
status = ar5210SetPowerModeAwake(ah, setChip);
break;
case HAL_PM_FULL_SLEEP:
ar5210SetPowerModeSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
case HAL_PM_NETWORK_SLEEP:
ar5210SetPowerModeAuto(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
default:
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
__func__, mode);
return AH_FALSE;
}
- ahp->ah_powerMode = mode;
- return status;
+ return status;
}
HAL_POWER_MODE
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c
index b43d807..7e187ec 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_recv.c 243317 2012-11-19 23:42:46Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c
index 1d50f99..34d7db4 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_reset.c 264899 2014-04-24 23:11:18Z adrian $
*/
#include "opt_ah.h"
@@ -152,8 +152,12 @@ ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode,
/* Restore previous led state */
OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
+#if 0
OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
+#endif
+ /* BSSID, association id, ps-poll */
+ ar5210WriteAssocid(ah, ahp->ah_bssid, ahp->ah_associd);
OS_REG_WRITE(ah, AR_TXDP0, 0);
OS_REG_WRITE(ah, AR_TXDP1, 0);
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c b/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c
index d376996..ac2c03d 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210_xmit.c 243174 2012-11-17 02:39:37Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210desc.h b/sys/dev/ath/ath_hal/ar5210/ar5210desc.h
index da5c51f..18fe231 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210desc.h
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210desc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210desc.h 243173 2012-11-17 02:39:09Z adrian $
*/
#ifndef _DEV_ATH_AR5210DESC_H
#define _DEV_ATH_AR5210DESC_H
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210phy.h b/sys/dev/ath/ath_hal/ar5210/ar5210phy.h
index 4ab3025..1235a90 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210phy.h
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210phy.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210phy.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _DEV_ATH_AR5210PHY_H
#define _DEV_ATH_AR5210PHY_H
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210reg.h b/sys/dev/ath/ath_hal/ar5210/ar5210reg.h
index 16cd74e..139fc62 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210reg.h
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5210reg.h 243317 2012-11-19 23:42:46Z adrian $
*/
#ifndef _DEV_ATH_AR5210REG_H
#define _DEV_ATH_AR5210REG_H
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini b/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini
index b536483..71295b0 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini
+++ b/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5210/ar5k_0007.ini 204644 2010-03-03 17:32:32Z rpaulo $
*/
/* crete register init */
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h
index c50531e..2be9306 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211.h
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211.h 262969 2014-03-10 06:03:35Z adrian $
*/
#ifndef _ATH_AR5211_H_
#define _ATH_AR5211_H_
@@ -119,7 +119,6 @@ struct ath_hal_5211 {
uint32_t ah_txEolInterruptMask;
uint32_t ah_txUrnInterruptMask;
HAL_TX_QUEUE_INFO ah_txq[HAL_NUM_TX_QUEUES];
- HAL_POWER_MODE ah_powerMode;
HAL_ANT_SETTING ah_diversityControl; /* antenna setting */
uint32_t ah_calibrationTime;
HAL_BOOL ah_bIQCalibration;
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
index 4549295..791f14d 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -203,7 +203,7 @@ ar5211GetRadioRev(struct ath_hal *ah)
static struct ath_hal *
ar5211Attach(uint16_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)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
struct ath_hal_5211 *ahp;
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
index b2775d0..6d59405 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c 225444 2011-09-08 01:23:05Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c b/sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c
index 4c20ca1b..f08fa2c 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_interrupts.c 192397 2009-05-19 17:35:15Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c b/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c
index 3e0f922..dce99d2 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_keycache.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c
index a1a5967..f23e770 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c 247286 2013-02-25 22:42:43Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c b/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c
index d224732..c531caf 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_phy.c 191022 2009-04-13 21:01:08Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_power.c b/sys/dev/ath/ath_hal/ar5211/ar5211_power.c
index 776cfb3..3fb1990 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_power.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_power.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_power.c 265112 2014-04-30 02:03:13Z adrian $
*/
#include "opt_ah.h"
@@ -95,7 +95,6 @@ ar5211SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
HAL_BOOL
ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
{
- struct ath_hal_5211 *ahp = AH5211(ah);
#ifdef AH_DEBUG
static const char* modes[] = {
"AWAKE",
@@ -107,25 +106,30 @@ ar5211SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
int status = AH_TRUE;
HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode],
+ modes[ah->ah_powerMode], modes[mode],
setChip ? "set chip " : "");
switch (mode) {
case HAL_PM_AWAKE:
+ if (setChip)
+ ah->ah_powerMode = mode;
status = ar5211SetPowerModeAwake(ah, setChip);
break;
case HAL_PM_FULL_SLEEP:
ar5211SetPowerModeSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
case HAL_PM_NETWORK_SLEEP:
ar5211SetPowerModeNetworkSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
default:
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
__func__, mode);
return AH_FALSE;
}
- ahp->ah_powerMode = mode;
- return status;
+ return status;
}
HAL_POWER_MODE
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c
index 27c4835..632652b 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_recv.c 238278 2012-07-09 07:19:11Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c b/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c
index 01e3967..0624689 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c 234450 2012-04-19 03:26:21Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c
index dc0ad3f..05e8696 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c 239051 2012-08-05 10:12:27Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211desc.h b/sys/dev/ath/ath_hal/ar5211/ar5211desc.h
index 8702e91..45c8bd7 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211desc.h
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211desc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211desc.h 243249 2012-11-18 20:41:46Z adrian $
*/
#ifndef _DEV_ATH_AR5211DESC_H
#define _DEV_ATH_AR5211DESC_H
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211phy.h b/sys/dev/ath/ath_hal/ar5211/ar5211phy.h
index bf5b67e..db24339 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211phy.h
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211phy.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211phy.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _DEV_ATH_AR5211PHY_H
#define _DEV_ATH_AR5211PHY_H
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211reg.h b/sys/dev/ath/ath_hal/ar5211/ar5211reg.h
index 93d4fc5..b315f36 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211reg.h
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/ar5211reg.h 228980 2011-12-30 02:58:37Z dim $
*/
#ifndef _DEV_ATH_AR5211REG_H
#define _DEV_ATH_AR5211REG_H
diff --git a/sys/dev/ath/ath_hal/ar5211/boss.ini b/sys/dev/ath/ath_hal/ar5211/boss.ini
index e054436..ce3397d 100644
--- a/sys/dev/ath/ath_hal/ar5211/boss.ini
+++ b/sys/dev/ath/ath_hal/ar5211/boss.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5211/boss.ini 245952 2013-01-26 22:08:21Z pfg $
*/
/* Auto Generated PCI Register Writes. Created: 09/12/02 */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar2316.c b/sys/dev/ath/ath_hal/ar5212/ar2316.c
index 9bfc482..9217cb5 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar2316.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar2316.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar2316.c 187831 2009-01-28 18:00:22Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar2317.c b/sys/dev/ath/ath_hal/ar5212/ar2317.c
index fdf88e3..6ac7529 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar2317.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar2317.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar2317.c 187831 2009-01-28 18:00:22Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar2413.c b/sys/dev/ath/ath_hal/ar5212/ar2413.c
index e069444..082b99e 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar2413.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar2413.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar2413.c 187831 2009-01-28 18:00:22Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar2425.c b/sys/dev/ath/ath_hal/ar5212/ar2425.c
index e487489..883d706 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar2425.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar2425.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar2425.c 188979 2009-02-24 01:07:06Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5111.c b/sys/dev/ath/ath_hal/ar5212/ar5111.c
index f9fd3f3..23367c6 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5111.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5111.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5111.c 187831 2009-01-28 18:00:22Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5112.c b/sys/dev/ath/ath_hal/ar5212/ar5112.c
index c1920b9..82deb87 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5112.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5112.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5112.c 225883 2011-09-30 05:17:57Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h
index 6d38d65..166170e 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212.h 281128 2015-04-06 01:12:53Z adrian $
*/
#ifndef _ATH_AR5212_H_
#define _ATH_AR5212_H_
@@ -200,6 +200,7 @@ struct ar5212AniState {
#define HAL_ANI_ENA 0x00000001 /* ANI operation enabled */
#define HAL_RSSI_ANI_ENA 0x00000002 /* rssi-based processing ena'd*/
+#if 0
struct ar5212Stats {
uint32_t ast_ani_niup; /* ANI increased noise immunity */
uint32_t ast_ani_nidown; /* ANI decreased noise immunity */
@@ -219,6 +220,7 @@ struct ar5212Stats {
HAL_MIB_STATS ast_mibstats; /* MIB counter stats */
HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */
};
+#endif
/*
* NF Cal history buffer
@@ -258,7 +260,7 @@ struct ath_hal_5212 {
* Runtime state.
*/
uint32_t ah_maskReg; /* copy of AR_IMR */
- struct ar5212Stats ah_stats; /* various statistics */
+ HAL_ANI_STATS ah_stats; /* various statistics */
RF_HAL_FUNCS *ah_rfHal;
uint32_t ah_txDescMask; /* mask for TXDESC */
uint32_t ah_txOkInterruptMask;
@@ -270,7 +272,6 @@ struct ath_hal_5212 {
uint32_t ah_intrTxqs; /* tx q interrupt state */
/* decomp mask array */
uint8_t ah_decompMask[HAL_DECOMP_MASK_SIZE];
- HAL_POWER_MODE ah_powerMode;
HAL_ANT_SETTING ah_antControl; /* antenna setting */
HAL_BOOL ah_diversity; /* fast diversity setting */
enum {
@@ -320,7 +321,6 @@ struct ath_hal_5212 {
struct ar5212AniParams ah_aniParams5; /* 5GHz parameters */
struct ar5212AniState *ah_curani; /* cached last reference */
struct ar5212AniState ah_ani[AH_MAXCHAN]; /* per-channel state */
- HAL_CHANNEL_SURVEY ah_chansurvey; /* channel survey */
/* AR5416 uses some of the AR5212 ANI code; these are the ANI methods */
HAL_BOOL (*ah_aniControl) (struct ath_hal *, HAL_ANI_CMD cmd, int param);
@@ -345,6 +345,9 @@ struct ath_hal_5212 {
uint32_t ah_txBusy;
uint32_t ah_rx_chainmask;
uint32_t ah_tx_chainmask;
+
+ /* Used to return ANI statistics to the diagnostic API */
+ HAL_ANI_STATS ext_ani_stats;
};
#define AH5212(_ah) ((struct ath_hal_5212 *)(_ah))
@@ -627,7 +630,7 @@ extern void ar5212AniAttach(struct ath_hal *, const struct ar5212AniParams *,
const struct ar5212AniParams *, HAL_BOOL ena);
extern void ar5212AniDetach(struct ath_hal *);
extern struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *);
-extern struct ar5212Stats *ar5212AniGetCurrentStats(struct ath_hal *);
+extern HAL_ANI_STATS *ar5212AniGetCurrentStats(struct ath_hal *);
extern HAL_BOOL ar5212AniControl(struct ath_hal *, HAL_ANI_CMD cmd, int param);
extern HAL_BOOL ar5212AniSetParams(struct ath_hal *,
const struct ar5212AniParams *, const struct ar5212AniParams *);
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.ini b/sys/dev/ath/ath_hal/ar5212/ar5212.ini
index 608f91f..37e2d96 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212.ini
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212.ini 204644 2010-03-03 17:32:32Z rpaulo $
*/
/* Auto Generated PCI Register Writes. Created: 09/01/04 */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
index 8e87a2f..5674ec1 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c 280940 2015-04-01 03:42:46Z adrian $
*/
#include "opt_ah.h"
@@ -110,7 +110,7 @@ ar5212AniGetCurrentState(struct ath_hal *ah)
/*
* Return the current statistics.
*/
-struct ar5212Stats *
+HAL_ANI_STATS *
ar5212AniGetCurrentStats(struct ath_hal *ah)
{
struct ath_hal_5212 *ahp = AH5212(ah);
@@ -869,7 +869,6 @@ ar5212AniGetListenTime(struct ath_hal *ah)
int32_t listenTime = 0;
int good;
HAL_SURVEY_SAMPLE hs;
- HAL_CHANNEL_SURVEY *cs = AH_NULL;
/*
* We shouldn't see ah_curchan be NULL, but just in case..
@@ -879,21 +878,13 @@ ar5212AniGetListenTime(struct ath_hal *ah)
return (0);
}
- cs = &ahp->ah_chansurvey;
-
/*
* Fetch the current statistics, squirrel away the current
* sample, bump the sequence/sample counter.
*/
OS_MEMZERO(&hs, sizeof(hs));
good = ar5212GetMibCycleCounts(ah, &hs);
- if (cs != AH_NULL) {
- OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs));
- cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
- cs->cur_sample =
- (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
- cs->cur_seq++;
- }
+ ath_hal_survey_add_sample(ah, &hs);
if (ANI_ENA(ah))
aniState = ahp->ah_curani;
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
index e0af27c..ee18ce7 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -317,7 +317,7 @@ ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)
static struct ath_hal *
ar5212Attach(uint16_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)
{
#define AH_EEPROM_PROTECT(ah) \
(AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
index b52077f..e84bab3 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c 243588 2012-11-27 02:18:41Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c b/sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c
index f4b6771..3e897e4 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_eeprom.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c b/sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c
index b2363af..be57458 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_gpio.c 188974 2009-02-24 00:12:16Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c b/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c
index 47f9e74..a3ec20d 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c 201758 2010-01-07 21:01:37Z mbr $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c b/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c
index bf7db49..6364bf5 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c 218483 2011-02-09 15:23:16Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
index 71ee845..1e1f10b 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c 281128 2015-04-06 01:12:53Z adrian $
*/
#include "opt_ah.h"
@@ -1052,6 +1052,7 @@ ar5212GetDiagState(struct ath_hal *ah, int request,
void **result, uint32_t *resultsize)
{
struct ath_hal_5212 *ahp = AH5212(ah);
+ HAL_ANI_STATS *astats;
(void) ahp;
if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
@@ -1083,9 +1084,16 @@ ar5212GetDiagState(struct ath_hal *ah, int request,
0 : sizeof(struct ar5212AniState);
return AH_TRUE;
case HAL_DIAG_ANI_STATS:
- *result = ar5212AniGetCurrentStats(ah);
- *resultsize = (*result == AH_NULL) ?
- 0 : sizeof(struct ar5212Stats);
+ OS_MEMZERO(&ahp->ext_ani_stats, sizeof(ahp->ext_ani_stats));
+ astats = ar5212AniGetCurrentStats(ah);
+ if (astats == NULL) {
+ *result = NULL;
+ *resultsize = 0;
+ } else {
+ OS_MEMCPY(&ahp->ext_ani_stats, astats, sizeof(HAL_ANI_STATS));
+ *result = &ahp->ext_ani_stats;
+ *resultsize = sizeof(ahp->ext_ani_stats);
+ }
return AH_TRUE;
case HAL_DIAG_ANI_CMD:
if (argsize != 2*sizeof(uint32_t))
@@ -1113,10 +1121,6 @@ ar5212GetDiagState(struct ath_hal *ah, int request,
return ar5212AniSetParams(ah, args, args);
}
break;
- case HAL_DIAG_CHANSURVEY:
- *result = &ahp->ah_chansurvey;
- *resultsize = sizeof(HAL_CHANNEL_SURVEY);
- return AH_TRUE;
}
return AH_FALSE;
}
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c b/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c
index ac55be6..e92a52e 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_phy.c 191022 2009-04-13 21:01:08Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_power.c b/sys/dev/ath/ath_hal/ar5212/ar5212_power.c
index 3f755bd..435c975 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_power.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_power.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_power.c 265112 2014-04-30 02:03:13Z adrian $
*/
#include "opt_ah.h"
@@ -119,7 +119,6 @@ ar5212SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
HAL_BOOL
ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
{
- struct ath_hal_5212 *ahp = AH5212(ah);
#ifdef AH_DEBUG
static const char* modes[] = {
"AWAKE",
@@ -131,24 +130,29 @@ ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
int status = AH_TRUE;
HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode],
+ modes[ah->ah_powerMode], modes[mode],
setChip ? "set chip " : "");
switch (mode) {
case HAL_PM_AWAKE:
+ if (setChip)
+ ah->ah_powerMode = mode;
status = ar5212SetPowerModeAwake(ah, setChip);
break;
case HAL_PM_FULL_SLEEP:
ar5212SetPowerModeSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
case HAL_PM_NETWORK_SLEEP:
ar5212SetPowerModeNetworkSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
default:
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode %u\n",
__func__, mode);
return AH_FALSE;
}
- ahp->ah_powerMode = mode;
return status;
}
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c
index 958a954..82d2f67 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_recv.c 243169 2012-11-17 02:02:36Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
index eca2e1f..2851268 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c 280828 2015-03-29 21:50:21Z adrian $
*/
#include "opt_ah.h"
@@ -197,7 +197,8 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode,
saveFrameSeqCount = 0; /* NB: silence compiler */
/* Blank the channel survey statistics */
- OS_MEMZERO(&ahp->ah_chansurvey, sizeof(ahp->ah_chansurvey));
+ ath_hal_survey_clear(ah);
+
#if 0
/*
* XXX disable for now; this appears to sometimes cause OFDM
@@ -2605,6 +2606,12 @@ ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan,
powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54);
}
+static uint32_t
+udiff(uint32_t u, uint32_t v)
+{
+ return (u >= v ? u - v : v - u);
+}
+
/*
* Search a list for a specified value v that is within
* EEP_DELTA of the search values. Return the closest
@@ -2639,7 +2646,7 @@ ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize,
* If value is close to the current value of the list
* then target is not between values, it is one of the values
*/
- if (abs(lp[0] * EEP_SCALE - target) < EEP_DELTA) {
+ if (udiff(lp[0] * EEP_SCALE, target) < EEP_DELTA) {
*vlo = *vhi = lp[0];
return;
}
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c b/sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c
index f9fbc9c..6236142 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_rfgain.c 188197 2009-02-05 21:13:31Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c
index 5aeefed..665af67 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c 243169 2012-11-17 02:02:36Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212desc.h b/sys/dev/ath/ath_hal/ar5212/ar5212desc.h
index ce01dd2..6c66920 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212desc.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212desc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212desc.h 243168 2012-11-17 02:00:33Z adrian $
*/
#ifndef _ATH_AR5212_DESC_H_
#define _ATH_AR5212_DESC_H_
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212phy.h b/sys/dev/ath/ath_hal/ar5212/ar5212phy.h
index 9e9bbbf..d5dd261 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212phy.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212phy.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212phy.h 239801 2012-08-29 03:58:13Z adrian $
*/
#ifndef _DEV_ATH_AR5212PHY_H_
#define _DEV_ATH_AR5212PHY_H_
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212reg.h b/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
index 96dfa9d..0cdd1b5 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5212reg.h 226489 2011-10-18 03:17:06Z adrian $
*/
#ifndef _DEV_ATH_AR5212REG_H_
#define _DEV_ATH_AR5212REG_H_
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5311reg.h b/sys/dev/ath/ath_hal/ar5212/ar5311reg.h
index b79370e..220723c 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5311reg.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5311reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5311reg.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _DEV_ATH_AR5311REG_H_
#define _DEV_ATH_AR5311REG_H_
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5413.c b/sys/dev/ath/ath_hal/ar5212/ar5413.c
index ab6cc65..6b1af69 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5413.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5413.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5212/ar5413.c 188979 2009-02-24 01:07:06Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312.h b/sys/dev/ath/ath_hal/ar5312/ar5312.h
index 0fb9b75..da8860f 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312.h
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312.h 188974 2009-02-24 00:12:16Z sam $
*/
#ifndef _ATH_AR5312_H_
#define _ATH_AR5312_H_
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
index 4ca1a4d..66447fa 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -62,7 +62,7 @@ ar5312AniSetup(struct ath_hal *ah)
static struct ath_hal *
ar5312Attach(uint16_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)
{
struct ath_hal_5212 *ahp = AH_NULL;
struct ath_hal *ah;
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c b/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c
index 7a84232..2f89dcc 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_eeprom.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c b/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c
index 20a575d..7d2e7e3 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_gpio.c 188974 2009-02-24 00:12:16Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c b/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c
index 0a1545c..1360875 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_interrupts.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c b/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c
index 3d85ece..318ff24 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c 204644 2010-03-03 17:32:32Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_power.c b/sys/dev/ath/ath_hal/ar5312/ar5312_power.c
index 94a0f1c..0aa52460 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_power.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_power.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_power.c 262969 2014-03-10 06:03:35Z adrian $
*/
#include "opt_ah.h"
@@ -71,7 +71,6 @@ ar5312SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
HAL_BOOL
ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
{
- struct ath_hal_5212 *ahp = AH5212(ah);
#ifdef AH_DEBUG
static const char* modes[] = {
"AWAKE",
@@ -83,7 +82,7 @@ ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
int status = AH_TRUE;
HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode],
+ modes[ah->ah_powerMode], modes[mode],
setChip ? "set chip " : "");
switch (mode) {
case HAL_PM_AWAKE:
@@ -100,7 +99,7 @@ ar5312SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
__func__, mode);
return AH_FALSE;
}
- ahp->ah_powerMode = mode;
+ ah->ah_powerMode = mode;
return status;
}
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c b/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c
index fdba35d..1b03f10 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312_reset.c 234450 2012-04-19 03:26:21Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312phy.h b/sys/dev/ath/ath_hal/ar5312/ar5312phy.h
index fcb8564..513014d 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312phy.h
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312phy.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312phy.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _DEV_ATH_AR5312PHY_H_
#define _DEV_ATH_AR5312PHY_H_
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312reg.h b/sys/dev/ath/ath_hal/ar5312/ar5312reg.h
index bdfeffa..4210950 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312reg.h
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5312reg.h 204644 2010-03-03 17:32:32Z rpaulo $
*/
#ifndef _DEV_ATH_AR5312REG_H_
#define _DEV_ATH_AR5312REG_H_
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c b/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c
index 4c04c86..45666bb 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5312/ar5315_gpio.c 188974 2009-02-24 00:12:16Z sam $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar2133.c b/sys/dev/ath/ath_hal/ar5416/ar2133.c
index 457a7c3..c2f9534 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar2133.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar2133.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar2133.c 241195 2012-10-04 15:42:45Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index a631aad..d1d6d26 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416.h 249580 2013-04-17 07:31:53Z adrian $
*/
#ifndef _ATH_AR5416_H_
#define _ATH_AR5416_H_
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.ini b/sys/dev/ath/ath_hal/ar5416/ar5416.ini
index 7f8c793..229b7de 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.ini
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416.ini 225420 2011-09-06 10:49:05Z adrian $
*/
/* Auto Generated PCI Register Writes. Created: 09/20/06 */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
index 3f9bc69..fb13241 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c 280828 2015-03-29 21:50:21Z adrian $
*/
#include "opt_ah.h"
@@ -818,7 +818,6 @@ ar5416AniGetListenTime(struct ath_hal *ah)
int32_t listenTime = 0;
int good;
HAL_SURVEY_SAMPLE hs;
- HAL_CHANNEL_SURVEY *cs = AH_NULL;
/*
* We shouldn't see ah_curchan be NULL, but just in case..
@@ -828,21 +827,13 @@ ar5416AniGetListenTime(struct ath_hal *ah)
return (0);
}
- cs = &ahp->ah_chansurvey;
-
/*
* Fetch the current statistics, squirrel away the current
- * sample, bump the sequence/sample counter.
+ * sample.
*/
OS_MEMZERO(&hs, sizeof(hs));
good = ar5416GetMibCycleCounts(ah, &hs);
- if (cs != AH_NULL) {
- OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs));
- cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
- cs->cur_sample =
- (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
- cs->cur_seq++;
- }
+ ath_hal_survey_add_sample(ah, &hs);
if (ANI_ENA(ah))
aniState = ahp->ah_curani;
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index 99bab06..2b6d93a 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -297,7 +297,7 @@ ar5416GetRadioRev(struct ath_hal *ah)
static struct ath_hal *
ar5416Attach(uint16_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)
{
struct ath_hal_5416 *ahp5416;
struct ath_hal_5212 *ahp;
@@ -1059,6 +1059,11 @@ ar5416FillCapabilityInfo(struct ath_hal *ah)
if (! AH_PRIVATE(ah)->ah_ispcie)
pCap->halSerialiseRegWar = 1;
+ /*
+ * AR5416 and later NICs support MYBEACON filtering.
+ */
+ pCap->halRxDoMyBeacon = AH_TRUE;
+
return AH_TRUE;
}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
index e2bf6c7..2f2997e 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c 265031 2014-04-27 23:35:05Z adrian $
*/
#include "opt_ah.h"
@@ -197,6 +197,25 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
* beacon jitter; cab timeout is max time to wait for cab
* after seeing the last DTIM or MORE CAB bit
*/
+
+/*
+ * I've bumped these to 30TU for now.
+ *
+ * Some APs (AR933x/AR934x?) in 2GHz especially seem to not always
+ * transmit beacon frames at exactly the right times and with it set
+ * to 10TU, the NIC starts not waking up at the right times to hear
+ * these slightly-larger-jitering beacons. It also never recovers
+ * from that (it doesn't resync? I'm not sure.)
+ *
+ * So for now bump this to 30TU. Ideally we'd cap this based on
+ * the beacon interval so the sum of CAB+BEACON timeouts never
+ * exceeded the beacon interval.
+ *
+ * Now, since we're doing all the math in the ath(4) driver in TU
+ * rather than TSF, we may be seeing the result of dumb rounding
+ * errors causing the jitter to actually be a much bigger problem.
+ * I'll have to investigate that with a fine tooth comb.
+ */
#define CAB_TIMEOUT_VAL 10 /* in TU */
#define BEACON_TIMEOUT_VAL 10 /* in TU */
#define SLEEP_SLOP 3 /* in TU */
@@ -248,6 +267,13 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
OS_REG_SET_BIT(ah, AR_TIMER_MODE,
AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM);
+
+#define HAL_TSFOOR_THRESHOLD 0x00004240 /* TSF OOR threshold (16k us) */
+
+ /* TSF out of range threshold */
+// OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
+ OS_REG_WRITE(ah, AR_TSFOOR_THRESHOLD, HAL_TSFOOR_THRESHOLD);
+
HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
__func__, bs->bs_nextdtim);
HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next beacon %d\n",
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c b/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c
index c73b0ee..4f15e4f 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c 251483 2013-06-07 05:17:58Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h b/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h
index 0d3e316..7d5f359 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.h 237621 2012-06-27 03:00:29Z adrian $
*/
#ifndef __ATH_AR5416_BTCOEX_H__
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
index d51417f4..8bbfdcd 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c 277290 2015-01-17 07:33:02Z adrian $
*/
#include "opt_ah.h"
@@ -663,7 +663,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
* by the median we just loaded. This will be initial (and max) value
* of next noise floor calibration the baseband does.
*/
- for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
+ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) {
/* Don't write to EXT radio CCA registers unless in HT/40 mode */
/* XXX this check should really be cleaner! */
@@ -676,6 +676,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
val |= (((uint32_t)(-50) << 1) & 0x1ff);
OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
}
+ }
}
/*
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h
index a4f19e5..342b9b3c 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_cal.h 219480 2011-03-11 11:35:36Z adrian $
*/
#ifndef _ATH_AR5416_CAL_H_
#define _ATH_AR5416_CAL_H_
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c
index 9083d3a..ee912ed 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c 203158 2010-01-29 10:07:17Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c
index 4af1ca4..590f23a 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c 203158 2010-01-29 10:07:17Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c
index 939ba12..75f71f9 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_cal_iq.c 211306 2010-08-14 15:28:15Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c b/sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c
index 2947726..d3cdfc6 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_eeprom.c 203158 2010-01-29 10:07:17Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c b/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c
index 3c493b4..75139a0 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c 237611 2012-06-26 22:16:53Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c
index 631ca2f..56312ab 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c 265029 2014-04-27 23:31:42Z adrian $
*/
#include "opt_ah.h"
@@ -337,6 +337,9 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints)
/* Write the new IMR and store off our SW copy. */
HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
OS_REG_WRITE(ah, AR_IMR, mask);
+ /* Flush write */
+ (void) OS_REG_READ(ah, AR_IMR);
+
mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
AR_IMR_S2_DTIM |
AR_IMR_S2_DTIMSYNC |
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c b/sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c
index 533fe03..c687152 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_keycache.c 203158 2010-01-29 10:07:17Z rpaulo $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
index dd76843..3c0b775 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 250856 2013-05-21 14:28:05Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_phy.c b/sys/dev/ath/ath_hal/ar5416/ar5416_phy.c
index 1cfd964..1b704b8 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_phy.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_phy.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_phy.c 218908 2011-02-21 05:10:34Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c
index 43a9241..8e471a9 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_power.c 265112 2014-04-30 02:03:13Z adrian $
*/
#include "opt_ah.h"
@@ -124,7 +124,6 @@ ar5416SetPowerModeNetworkSleep(struct ath_hal *ah, int setChip)
HAL_BOOL
ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
{
- struct ath_hal_5212 *ahp = AH5212(ah);
#ifdef AH_DEBUG
static const char* modes[] = {
"AWAKE",
@@ -134,27 +133,35 @@ ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip)
};
#endif
int status = AH_TRUE;
+
+#if 0
if (!setChip)
return AH_TRUE;
+#endif
HALDEBUG(ah, HAL_DEBUG_POWER, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode], setChip ? "set chip " : "");
+ modes[ah->ah_powerMode], modes[mode], setChip ? "set chip " : "");
switch (mode) {
case HAL_PM_AWAKE:
+ if (setChip)
+ ah->ah_powerMode = mode;
status = ar5416SetPowerModeAwake(ah, setChip);
break;
case HAL_PM_FULL_SLEEP:
ar5416SetPowerModeSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
case HAL_PM_NETWORK_SLEEP:
ar5416SetPowerModeNetworkSleep(ah, setChip);
+ if (setChip)
+ ah->ah_powerMode = mode;
break;
default:
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown power mode 0x%x\n",
__func__, mode);
return AH_FALSE;
}
- ahp->ah_powerMode = mode;
return status;
}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_radar.c b/sys/dev/ath/ath_hal/ar5416/ar5416_radar.c
index edac235..563e187 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_radar.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_radar.c
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_radar.c 239638 2012-08-24 01:29:46Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
index df096f9..0852ad9 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c 250346 2013-05-08 01:11:25Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
index eb31f08..21e2a87 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c 280828 2015-03-29 21:50:21Z adrian $
*/
#include "opt_ah.h"
@@ -120,9 +120,10 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
/* Blank the channel survey statistics */
- OS_MEMZERO(&ahp->ah_chansurvey, sizeof(ahp->ah_chansurvey));
+ ath_hal_survey_clear(ah);
/* XXX Turn on fast channel change for 5416 */
+
/*
* Preserve the bmiss rssi threshold and count threshold
* across resets
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c
index 6bdd722..f19c47d 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c 244950 2013-01-02 03:56:20Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
index 47e8c35..c792f07 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c 249580 2013-04-17 07:31:53Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416desc.h b/sys/dev/ath/ath_hal/ar5416/ar5416desc.h
index 2730394..a4a8d06 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416desc.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416desc.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416desc.h 250346 2013-05-08 01:11:25Z adrian $
*/
#ifndef _ATH_AR5416_DESC_H_
#define _ATH_AR5416_DESC_H_
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
index 4884dac..f6707db 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416phy.h 244943 2013-01-02 00:38:01Z adrian $
*/
#ifndef _DEV_ATH_AR5416PHY_H_
#define _DEV_ATH_AR5416PHY_H_
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
index 435599c..c3acb67 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416reg.h 265030 2014-04-27 23:33:37Z adrian $
*/
#ifndef _DEV_ATH_AR5416REG_H
#define _DEV_ATH_AR5416REG_H
@@ -476,10 +476,10 @@
/* Sleep control */
#define AR5416_SLEEP1_ASSUME_DTIM 0x00080000
#define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */
-#define AR5416_SLEEP1_CAB_TIMEOUT_S 22
+#define AR5416_SLEEP1_CAB_TIMEOUT_S 21
#define AR5416_SLEEP2_BEACON_TIMEOUT 0xFFE00000 /* Beacon timeout (TU)*/
-#define AR5416_SLEEP2_BEACON_TIMEOUT_S 22
+#define AR5416_SLEEP2_BEACON_TIMEOUT_S 21
/* Sleep Registers */
#define AR_SLP32_HALFCLK_LATENCY 0x000FFFFF /* rising <-> falling edge */
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130.ini b/sys/dev/ath/ath_hal/ar9001/ar9130.ini
index 0bd9f8e..fa207c1 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130.ini
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130.ini
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130.ini 221163 2011-04-28 12:47:40Z adrian $
*/
static const uint32_t ar5416Modes_9100[][6] = {
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
index 4f478c0..22669d9 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -69,7 +69,9 @@ static HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah);
*/
static struct ath_hal *
ar9130Attach(uint16_t devid, HAL_SOFTC sc,
- HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, HAL_STATUS *status)
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config,
+ HAL_STATUS *status)
{
struct ath_hal_5416 *ahp5416;
struct ath_hal_5212 *ahp;
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c b/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c
index 81bd0fe..212be72 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c
@@ -14,5 +14,5 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.c 230147 2012-01-15 19:22:34Z adrian $
*/
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h b/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h
index 5d1013b..08dab1f 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_eeprom.h 230147 2012-01-15 19:22:34Z adrian $
*/
#ifndef __AR9130_EEPROM_H__
#define __AR9130_EEPROM_H__
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_phy.c b/sys/dev/ath/ath_hal/ar9001/ar9130_phy.c
index a71fdfa..11c4e0c 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_phy.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_phy.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_phy.c 242412 2012-10-31 21:14:25Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_phy.h b/sys/dev/ath/ath_hal/ar9001/ar9130_phy.h
index 516df92..cddc0d5 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_phy.h
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_phy.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_phy.h 221163 2011-04-28 12:47:40Z adrian $
*/
#ifndef __AR9130_PHY_H__
#define __AR9130_PHY_H__
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130reg.h b/sys/dev/ath/ath_hal/ar9001/ar9130reg.h
index c289c32..64a6848 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130reg.h
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130reg.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130reg.h 221163 2011-04-28 12:47:40Z adrian $
*/
#ifndef __AR9130REG_H__
#define __AR9130REG_H__
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160.ini b/sys/dev/ath/ath_hal/ar9001/ar9160.ini
index 963b000..45a0855 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9160.ini
+++ b/sys/dev/ath/ath_hal/ar9001/ar9160.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9160.ini 220293 2011-04-03 11:59:52Z adrian $
*/
/* Auto Generated PCI Register Writes. Created: 05/22/08 */
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
index 979ba1a..f073a1e 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -114,6 +114,7 @@ ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
static struct ath_hal *
ar9160Attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config,
HAL_STATUS *status)
{
struct ath_hal_5416 *ahp5416;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9002phy.h b/sys/dev/ath/ath_hal/ar9002/ar9002phy.h
index 3d837cf..0d10d8c 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9002phy.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9002phy.h
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9002phy.h 220590 2011-04-13 04:40:59Z adrian $
*/
#ifndef __ATH_AR9002PHY_H__
#define __ATH_AR9002PHY_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280.c b/sys/dev/ath/ath_hal/ar9002/ar9280.c
index c9aabf0..68e7069 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280.c 241195 2012-10-04 15:42:45Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280.h b/sys/dev/ath/ath_hal/ar9002/ar9280.h
index e383918..6e33e51 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280.h 224243 2011-07-21 08:35:10Z adrian $
*/
#ifndef _ATH_AR9280_H_
#define _ATH_AR9280_H_
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
index 2a67fe5..643b82f 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -148,6 +148,7 @@ ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
static struct ath_hal *
ar9280Attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config,
HAL_STATUS *status)
{
struct ath_hal_9280 *ahp9280;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c
index 361930b..3cf3bfc 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_olc.c 221837 2011-05-13 14:33:45Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.h b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.h
index e08639c..8ca2b50 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_olc.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_olc.h
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_olc.h 219393 2011-03-08 06:59:59Z adrian $
*/
#ifndef __ATH_AR9280_OLC_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280v1.ini b/sys/dev/ath/ath_hal/ar9002/ar9280v1.ini
index 96e0f44..310c450 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280v1.ini
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280v1.ini
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280v1.ini 217631 2011-01-20 09:03:40Z adrian $
*/
/* Auto Generated PCI Register Writes. Created: 10/12/07 */
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280v2.ini b/sys/dev/ath/ath_hal/ar9002/ar9280v2.ini
index 60286ec0..a227c11 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280v2.ini
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280v2.ini
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280v2.ini 217751 2011-01-23 14:30:35Z adrian $
*/
static const uint32_t ar9280Modes_v2[][6] = {
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.c b/sys/dev/ath/ath_hal/ar9002/ar9285.c
index 9e9f95c..1724ebe 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285.c 228517 2011-12-15 00:59:11Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.h b/sys/dev/ath/ath_hal/ar9002/ar9285.h
index b37b297..257bb3f 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285.h 251655 2013-06-12 14:52:57Z adrian $
*/
#ifndef _ATH_AR9285_H_
#define _ATH_AR9285_H_
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.ini b/sys/dev/ath/ath_hal/ar9002/ar9285.ini
index ef0ff2d..4a24808 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285.ini
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285.ini
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285.ini 217631 2011-01-20 09:03:40Z adrian $
*/
/* AR9285 Revsion 10 */
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
index edb6f26..dc16e69 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -133,6 +133,7 @@ ar9285_eeprom_print_diversity_settings(struct ath_hal *ah)
static struct ath_hal *
ar9285Attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config,
HAL_STATUS *status)
{
struct ath_hal_9285 *ahp9285;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c b/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c
index 4d79a4f..b49c8ab 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c 251483 2013-06-07 05:17:58Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c
index a743e21..5bcfb15 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c 221806 2011-05-12 10:11:24Z adrian $
*/
#include "opt_ah.h"
#include "ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.h b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.h
index c6ecc41..497cd57 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_cal.h 219481 2011-03-11 11:58:54Z adrian $
*/
#ifndef __AR9285_CAL_H__
#define __AR9285_CAL_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c
index 5fd01b7..ca594bf 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c 251655 2013-06-12 14:52:57Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h
index 59d53b6..fae4799 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.h 251655 2013-06-12 14:52:57Z adrian $
*/
#ifndef __AR9285_DIVERSITY_H__
#define __AR9285_DIVERSITY_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_phy.c b/sys/dev/ath/ath_hal/ar9002/ar9285_phy.c
index c91048a..d0370c6 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_phy.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_phy.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_phy.c 251656 2013-06-12 15:18:10Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_phy.h b/sys/dev/ath/ath_hal/ar9002/ar9285_phy.h
index 0255e17..3d4efc6 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_phy.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_phy.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_phy.h 251643 2013-06-12 06:01:53Z adrian $
*/
#ifndef __AR9285_PHY_H__
#define __AR9285_PHY_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c
index cb5940f..715d715 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c 251655 2013-06-12 14:52:57Z adrian $
*/
/*
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285an.h b/sys/dev/ath/ath_hal/ar9002/ar9285an.h
index 3b80938..ffe4cc7 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285an.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285an.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285an.h 221806 2011-05-12 10:11:24Z adrian $
*/
#ifndef __AR9285_AN_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285phy.h b/sys/dev/ath/ath_hal/ar9002/ar9285phy.h
index f823053..f526789 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285phy.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285phy.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285phy.h 219481 2011-03-11 11:58:54Z adrian $
*/
#ifndef __ATH_AR9285PHY_H__
#define __ATH_AR9285PHY_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285v2.ini b/sys/dev/ath/ath_hal/ar9002/ar9285v2.ini
index 9126dc4..c22ee7f 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285v2.ini
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285v2.ini
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285v2.ini 217811 2011-01-25 05:36:29Z adrian $
*/
static const u_int32_t ar9285Modes_v2[][6] = {
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287.c b/sys/dev/ath/ath_hal/ar9002/ar9287.c
index 724fb7c..7fed99a 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287.c 228517 2011-12-15 00:59:11Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287.h b/sys/dev/ath/ath_hal/ar9002/ar9287.h
index 3122ea4..5aed2cd 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287.h 228833 2011-12-23 04:05:39Z adrian $
*/
#ifndef _ATH_AR9287_H_
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287.ini b/sys/dev/ath/ath_hal/ar9002/ar9287.ini
index 7f4ca05..7d1bfaf 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287.ini
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287.ini
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287.ini 222301 2011-05-26 09:15:33Z adrian $
*/
static const uint32_t ar9287Modes_9287_1_1[][6] = {
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
index 010e2c3..fa0da6f 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include "opt_ah.h"
@@ -111,6 +111,7 @@ ar9287AniSetup(struct ath_hal *ah)
static struct ath_hal *
ar9287Attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
+ HAL_OPS_CONFIG *ah_config,
HAL_STATUS *status)
{
struct ath_hal_9287 *ahp9287;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c
index d5024b0..cbb9473 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_cal.c 222301 2011-05-26 09:15:33Z adrian $
*/
#include "opt_ah.h"
#include "ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.h b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.h
index 1a7cda2..dcb55dd 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_cal.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_cal.h
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_cal.h 222301 2011-05-26 09:15:33Z adrian $
*/
#ifndef __AR9287_CAL_H__
#define __AR9287_CAL_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c b/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c
index cbbe017..0342cb0 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c 222314 2011-05-26 16:52:37Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h b/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h
index ff21ce6..fdb4468 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h 222308 2011-05-26 14:29:05Z adrian $
*/
#ifndef __AR9287_OLC_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
index 5ed4af2..5db38496 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c 249580 2013-04-17 07:31:53Z adrian $
*/
#include "opt_ah.h"
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.h b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.h
index 679fb8c..f5e1687 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_reset.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_reset.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.h 222301 2011-05-26 09:15:33Z adrian $
*/
#ifndef __AR9287_RESET_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287an.h b/sys/dev/ath/ath_hal/ar9002/ar9287an.h
index ba7a92c..f6570c8 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287an.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287an.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287an.h 222301 2011-05-26 09:15:33Z adrian $
*/
#ifndef __AR9287AN_H__
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287phy.h b/sys/dev/ath/ath_hal/ar9002/ar9287phy.h
index 8f28194..d4c377c 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287phy.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287phy.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9287phy.h 222301 2011-05-26 09:15:33Z adrian $
*/
#ifndef __AR9287PHY_H__
diff --git a/sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h b/sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h
index 583636e..94a79b3 100644
--- a/sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h
+++ b/sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h
@@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9003/ar9300_btcoex.h 237611 2012-06-26 22:16:53Z adrian $
*/
#ifndef __ATH_AR9300_BTCOEX_H__
diff --git a/sys/dev/ath/ath_hal/ar9003/ar9300_devid.h b/sys/dev/ath/ath_hal/ar9003/ar9300_devid.h
index 8d0a39a..188969b 100644
--- a/sys/dev/ath/ath_hal/ar9003/ar9300_devid.h
+++ b/sys/dev/ath/ath_hal/ar9003/ar9300_devid.h
@@ -32,7 +32,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_hal/ar9003/ar9300_devid.h 250166 2013-05-02 00:59:39Z adrian $
*
*/
#ifndef __AR9300_DEVID_H__
diff --git a/sys/dev/ath/ath_rate/amrr/amrr.c b/sys/dev/ath/ath_rate/amrr/amrr.c
index c252009..bfaadec 100644
--- a/sys/dev/ath/ath_rate/amrr/amrr.c
+++ b/sys/dev/ath/ath_rate/amrr/amrr.c
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/amrr/amrr.c 238633 2012-07-20 01:36:02Z adrian $");
/*
* AMRR rate control. See:
diff --git a/sys/dev/ath/ath_rate/amrr/amrr.h b/sys/dev/ath/ath_rate/amrr/amrr.h
index c97a007..a66a214 100644
--- a/sys/dev/ath/ath_rate/amrr/amrr.h
+++ b/sys/dev/ath/ath_rate/amrr/amrr.h
@@ -34,7 +34,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_rate/amrr/amrr.h 178354 2008-04-20 20:35:46Z sam $
*/
#ifndef _DEV_ATH_RATE_AMRR_H
diff --git a/sys/dev/ath/ath_rate/onoe/onoe.c b/sys/dev/ath/ath_rate/onoe/onoe.c
index 7c73926..baf5dd1 100644
--- a/sys/dev/ath/ath_rate/onoe/onoe.c
+++ b/sys/dev/ath/ath_rate/onoe/onoe.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/onoe/onoe.c 238633 2012-07-20 01:36:02Z adrian $");
/*
* Atsushi Onoe's rate control algorithm.
diff --git a/sys/dev/ath/ath_rate/onoe/onoe.h b/sys/dev/ath/ath_rate/onoe/onoe.h
index 27bbe94..b15932d 100644
--- a/sys/dev/ath/ath_rate/onoe/onoe.h
+++ b/sys/dev/ath/ath_rate/onoe/onoe.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_rate/onoe/onoe.h 178354 2008-04-20 20:35:46Z sam $
*/
/*
diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c
index b3f82fa..2fdd40e 100644
--- a/sys/dev/ath/ath_rate/sample/sample.c
+++ b/sys/dev/ath/ath_rate/sample/sample.c
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 277822 2015-01-28 04:42:40Z adrian $");
/*
* John Bicket's SampleRate control algorithm.
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -61,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
@@ -889,8 +891,8 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
if (!mrr || ts->ts_finaltsi == 0) {
if (!IS_RATE_DEFINED(sn, final_rix)) {
- device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d\n",
- __func__, ts->ts_rate, ts->ts_finaltsi);
+ device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
+ __func__, ts->ts_rate, ts->ts_finaltsi, final_rix);
badrate(ifp, 0, ts->ts_rate, long_tries, status);
return;
}
diff --git a/sys/dev/ath/ath_rate/sample/sample.h b/sys/dev/ath/ath_rate/sample/sample.h
index 7438a3d..e1bcbf8 100644
--- a/sys/dev/ath/ath_rate/sample/sample.h
+++ b/sys/dev/ath/ath_rate/sample/sample.h
@@ -33,7 +33,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.h 277823 2015-01-28 04:44:42Z adrian $
*/
/*
@@ -113,7 +113,7 @@ struct sample_node {
#ifdef _KERNEL
#define ATH_NODE_SAMPLE(an) ((struct sample_node *)&(an)[1])
-#define IS_RATE_DEFINED(sn, rix) (((sn)->ratemask & (1<<(rix))) != 0)
+#define IS_RATE_DEFINED(sn, rix) (((uint64_t) (sn)->ratemask & (1ULL<<((uint64_t) rix))) != 0)
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
diff --git a/sys/dev/ath/ath_rate/sample/tx_schedules.h b/sys/dev/ath/ath_rate/sample/tx_schedules.h
index f749e57..832d45e 100644
--- a/sys/dev/ath/ath_rate/sample/tx_schedules.h
+++ b/sys/dev/ath/ath_rate/sample/tx_schedules.h
@@ -38,7 +38,7 @@
#define __ATH_RATE_SAMPLE_TXSCHEDULES_H__
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/sample/tx_schedules.h 239286 2012-08-15 07:50:42Z adrian $");
#define A(_r) \
(((_r) == 6) ? 0 : (((_r) == 9) ? 1 : (((_r) == 12) ? 2 : \
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 6e58896..6a84643 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath.c 280825 2015-03-29 21:41:05Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -164,6 +165,7 @@ 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 *);
@@ -238,17 +240,14 @@ 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);
int ath_bstuck_threshold = 4; /* max missed beacons */
SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold,
@@ -278,6 +277,293 @@ ath_legacy_attach_comp_func(struct ath_softc *sc)
}
}
+/*
+ * Set the target power mode.
+ *
+ * If this is called during a point in time where
+ * the hardware is being programmed elsewhere, it will
+ * simply store it away and update it when all current
+ * uses of the hardware are completed.
+ */
+void
+_ath_power_setpower(struct ath_softc *sc, int power_state, const char *file, int line)
+{
+ ATH_LOCK_ASSERT(sc);
+
+ sc->sc_target_powerstate = power_state;
+
+ DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n",
+ __func__,
+ file,
+ line,
+ power_state,
+ sc->sc_powersave_refcnt);
+
+ if (sc->sc_powersave_refcnt == 0 &&
+ power_state != sc->sc_cur_powerstate) {
+ sc->sc_cur_powerstate = power_state;
+ ath_hal_setpower(sc->sc_ah, power_state);
+
+ /*
+ * If the NIC is force-awake, then set the
+ * self-gen frame state appropriately.
+ *
+ * If the nic is in network sleep or full-sleep,
+ * we let the above call leave the self-gen
+ * state as "sleep".
+ */
+ if (sc->sc_cur_powerstate == HAL_PM_AWAKE &&
+ sc->sc_target_selfgen_state != HAL_PM_AWAKE) {
+ ath_hal_setselfgenpower(sc->sc_ah,
+ sc->sc_target_selfgen_state);
+ }
+ }
+}
+
+/*
+ * Set the current self-generated frames state.
+ *
+ * This is separate from the target power mode. The chip may be
+ * awake but the desired state is "sleep", so frames sent to the
+ * destination has PWRMGT=1 in the 802.11 header. The NIC also
+ * needs to know to set PWRMGT=1 in self-generated frames.
+ */
+void
+_ath_power_set_selfgen(struct ath_softc *sc, int power_state, const char *file, int line)
+{
+
+ ATH_LOCK_ASSERT(sc);
+
+ DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n",
+ __func__,
+ file,
+ line,
+ power_state,
+ sc->sc_target_selfgen_state);
+
+ sc->sc_target_selfgen_state = power_state;
+
+ /*
+ * If the NIC is force-awake, then set the power state.
+ * Network-state and full-sleep will already transition it to
+ * mark self-gen frames as sleeping - and we can't
+ * guarantee the NIC is awake to program the self-gen frame
+ * setting anyway.
+ */
+ if (sc->sc_cur_powerstate == HAL_PM_AWAKE) {
+ ath_hal_setselfgenpower(sc->sc_ah, power_state);
+ }
+}
+
+/*
+ * Set the hardware power mode and take a reference.
+ *
+ * This doesn't update the target power mode in the driver;
+ * it just updates the hardware power state.
+ *
+ * XXX it should only ever force the hardware awake; it should
+ * never be called to set it asleep.
+ */
+void
+_ath_power_set_power_state(struct ath_softc *sc, int power_state, const char *file, int line)
+{
+ ATH_LOCK_ASSERT(sc);
+
+ DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n",
+ __func__,
+ file,
+ line,
+ power_state,
+ sc->sc_powersave_refcnt);
+
+ sc->sc_powersave_refcnt++;
+
+ if (power_state != sc->sc_cur_powerstate) {
+ ath_hal_setpower(sc->sc_ah, power_state);
+ sc->sc_cur_powerstate = power_state;
+
+ /*
+ * Adjust the self-gen powerstate if appropriate.
+ */
+ if (sc->sc_cur_powerstate == HAL_PM_AWAKE &&
+ sc->sc_target_selfgen_state != HAL_PM_AWAKE) {
+ ath_hal_setselfgenpower(sc->sc_ah,
+ sc->sc_target_selfgen_state);
+ }
+
+ }
+}
+
+/*
+ * Restore the power save mode to what it once was.
+ *
+ * This will decrement the reference counter and once it hits
+ * zero, it'll restore the powersave state.
+ */
+void
+_ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line)
+{
+
+ ATH_LOCK_ASSERT(sc);
+
+ DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) refcnt=%d, target state=%d\n",
+ __func__,
+ file,
+ line,
+ sc->sc_powersave_refcnt,
+ sc->sc_target_powerstate);
+
+ if (sc->sc_powersave_refcnt == 0)
+ device_printf(sc->sc_dev, "%s: refcnt=0?\n", __func__);
+ else
+ sc->sc_powersave_refcnt--;
+
+ if (sc->sc_powersave_refcnt == 0 &&
+ sc->sc_target_powerstate != sc->sc_cur_powerstate) {
+ sc->sc_cur_powerstate = sc->sc_target_powerstate;
+ ath_hal_setpower(sc->sc_ah, sc->sc_target_powerstate);
+ }
+
+ /*
+ * Adjust the self-gen powerstate if appropriate.
+ */
+ if (sc->sc_cur_powerstate == HAL_PM_AWAKE &&
+ sc->sc_target_selfgen_state != HAL_PM_AWAKE) {
+ ath_hal_setselfgenpower(sc->sc_ah,
+ sc->sc_target_selfgen_state);
+ }
+
+}
+
+/*
+ * 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
+
+}
+
+/*
+ * Attempt to fetch the MAC address from the kernel environment.
+ *
+ * Returns 0, macaddr in macaddr if successful; -1 otherwise.
+ */
+static int
+ath_fetch_mac_kenv(struct ath_softc *sc, uint8_t *macaddr)
+{
+ char devid_str[32];
+ int local_mac = 0;
+ char *local_macstr;
+
+ /*
+ * Fetch from the kenv rather than using hints.
+ *
+ * Hints would be nice but the transition to dynamic
+ * hints/kenv doesn't happen early enough for this
+ * to work reliably (eg on anything embedded.)
+ */
+ snprintf(devid_str, 32, "hint.%s.%d.macaddr",
+ device_get_name(sc->sc_dev),
+ device_get_unit(sc->sc_dev));
+
+ if ((local_macstr = getenv(devid_str)) != NULL) {
+ uint32_t tmpmac[ETHER_ADDR_LEN];
+ int count;
+ int i;
+
+ /* Have a MAC address; should use it */
+ device_printf(sc->sc_dev,
+ "Overriding MAC address from environment: '%s'\n",
+ local_macstr);
+
+ /* Extract out the MAC address */
+ count = sscanf(local_macstr, "%x%*c%x%*c%x%*c%x%*c%x%*c%x",
+ &tmpmac[0], &tmpmac[1],
+ &tmpmac[2], &tmpmac[3],
+ &tmpmac[4], &tmpmac[5]);
+ if (count == 6) {
+ /* Valid! */
+ local_mac = 1;
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ macaddr[i] = tmpmac[i];
+ }
+ /* Done! */
+ freeenv(local_macstr);
+ local_macstr = NULL;
+ }
+
+ if (local_mac)
+ return (0);
+ return (-1);
+}
+
#define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20)
#define HAL_MODE_HT40 \
(HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \
@@ -293,6 +579,7 @@ 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);
@@ -311,8 +598,17 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
device_get_unit(sc->sc_dev));
CURVNET_RESTORE();
+ /*
+ * 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);
@@ -340,6 +636,10 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ath_xmit_setup_legacy(sc);
}
+ if (ath_hal_hasmybeacon(sc->sc_ah)) {
+ sc->sc_do_mybeacon = 1;
+ }
+
/*
* Check if the MAC has multi-rate retry support.
* We do this by trying to setup a fake extended
@@ -604,6 +904,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
#ifdef ATH_ENABLE_DFS
| IEEE80211_C_DFS /* Enable radar detection */
#endif
+ | IEEE80211_C_PMGT /* Station side power mgmt */
+ | IEEE80211_C_SWSLEEP
;
/*
* Query the hal to figure out h/w crypto support.
@@ -901,8 +1203,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
sc->sc_hasveol = ath_hal_hasveol(ah);
- /* get mac address from hardware */
- ath_hal_getmac(ah, macaddr);
+ /* get mac address from kenv first, then hardware */
+ if (ath_fetch_mac_kenv(sc, macaddr) == 0) {
+ /* Tell the HAL now about the new MAC */
+ ath_hal_setmac(ah, macaddr);
+ } else {
+ ath_hal_getmac(ah, macaddr);
+ }
+
if (sc->sc_hasbmask)
ath_hal_getbssidmask(ah, sc->sc_hwbssidmask);
@@ -993,6 +1301,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
if (bootverbose)
ieee80211_announce(ic);
ath_announce(sc);
+
+ /*
+ * Put it to sleep for now.
+ */
+ ATH_LOCK(sc);
+ ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
+ ATH_UNLOCK(sc);
+
return 0;
bad2:
ath_tx_cleanup(sc);
@@ -1038,7 +1354,22 @@ ath_detach(struct ath_softc *sc)
* it last
* Other than that, it's straightforward...
*/
+
+ /*
+ * XXX Wake the hardware up first. ath_stop() will still
+ * 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);
+
ieee80211_ifdetach(ifp->if_l2com);
taskqueue_free(sc->sc_tq);
#ifdef ATH_TX99_DIAG
@@ -1401,6 +1732,10 @@ 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_drv_flags & IFF_DRV_RUNNING) {
/*
@@ -1409,11 +1744,13 @@ 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. */
+
ieee80211_vap_detach(vap);
/*
@@ -1501,6 +1838,9 @@ ath_vap_delete(struct ieee80211vap *vap)
}
ath_hal_intrset(ah, sc->sc_imask);
}
+
+ /* Ok, let the hardware asleep. */
+ ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
}
@@ -1520,12 +1860,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(&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 */
@@ -1546,8 +1899,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);
}
@@ -1599,11 +1956,24 @@ ath_resume(struct ath_softc *sc)
sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan);
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
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);
+
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);
@@ -1631,6 +2001,10 @@ 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 ? */
}
@@ -1688,6 +2062,10 @@ 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_drv_flags & IFF_DRV_RUNNING) == 0) {
HAL_INT status;
@@ -1697,6 +2075,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;
}
@@ -1736,6 +2118,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;
}
@@ -1791,44 +2178,46 @@ ath_intr(void *arg)
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.
- */
- if (! sc->sc_kickpcu)
- 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);
}
@@ -1902,10 +2291,18 @@ ath_intr(void *arg)
ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXORN");
sc->sc_stats.ast_rxorn++;
}
+ if (status & HAL_INT_TSFOOR) {
+ device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__);
+ sc->sc_syncbeacon = 1;
+ }
}
ATH_PCU_LOCK(sc);
sc->sc_intr_cnt--;
ATH_PCU_UNLOCK(sc);
+
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
}
static void
@@ -1936,6 +2333,8 @@ ath_fatal_proc(void *arg, int pending)
static void
ath_bmiss_vap(struct ieee80211vap *vap)
{
+ struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+
/*
* Workaround phantom bmiss interrupts by sanity-checking
* the time of our last rx'd frame. If it is within the
@@ -1944,6 +2343,16 @@ ath_bmiss_vap(struct ieee80211vap *vap)
* be dispatched up for processing. Note this applies only
* for h/w beacon miss events.
*/
+
+ /*
+ * XXX TODO: Just read the TSF during the interrupt path;
+ * 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;
@@ -1961,12 +2370,32 @@ 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;
}
}
+
+ /*
+ * 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.
+ */
+ sc->sc_syncbeacon = 1;
+
ATH_VAP(vap)->av_bmiss(vap);
}
+/* XXX this needs a force wakeup! */
int
ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs)
{
@@ -1989,6 +2418,12 @@ 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.
*
@@ -2002,6 +2437,13 @@ ath_bmiss_proc(void *arg, int pending)
ath_reset(ifp, ATH_RESET_NOLOSS);
ieee80211_beacon_miss(ifp->if_l2com);
}
+
+ /* Force a beacon resync, in case they've drifted */
+ sc->sc_syncbeacon = 1;
+
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
}
/*
@@ -2041,6 +2483,13 @@ ath_init(void *arg)
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.
*/
@@ -2057,12 +2506,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);
+
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 */
@@ -2090,11 +2546,11 @@ ath_init(void *arg)
* state cached in the driver.
*/
sc->sc_diversity = ath_hal_getdiversity(ah);
- sc->sc_lastlongcal = 0;
+ sc->sc_lastlongcal = ticks;
sc->sc_resetcal = 1;
sc->sc_lastcalreset = 0;
- sc->sc_lastani = 0;
- sc->sc_lastshortcal = 0;
+ sc->sc_lastani = ticks;
+ sc->sc_lastshortcal = ticks;
sc->sc_doresetcal = AH_FALSE;
/*
* Beacon timers were cleared here; give ath_newstate()
@@ -2112,6 +2568,7 @@ ath_init(void *arg)
*/
if (ath_startrecv(sc) != 0) {
if_printf(ifp, "unable to start recv logic\n");
+ ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
return;
}
@@ -2120,8 +2577,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;
/*
@@ -2132,12 +2588,29 @@ ath_init(void *arg)
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.
*/
if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
sc->sc_imask |= HAL_INT_MIB;
+ /*
+ * XXX add capability for this.
+ *
+ * If we're in STA mode (and maybe IBSS?) then register for
+ * TSFOOR interrupts.
+ */
+ if (ic->ic_opmode == IEEE80211_M_STA)
+ sc->sc_imask |= HAL_INT_TSFOOR;
+
/* Enable global TX timeout and carrier sense timeout if available */
if (ath_hal_gtxto_supported(ah))
sc->sc_imask |= HAL_INT_GTT;
@@ -2149,6 +2622,7 @@ ath_init(void *arg)
callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
ath_hal_intrset(ah, sc->sc_imask);
+ ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
#ifdef ATH_TX99_DIAG
@@ -2169,6 +2643,12 @@ ath_stop_locked(struct ifnet *ifp)
__func__, sc->sc_invalid, ifp->if_flags);
ATH_LOCK_ASSERT(sc);
+
+ /*
+ * Wake the hardware up before fiddling with it.
+ */
+ ath_power_set_power_state(sc, HAL_PM_AWAKE);
+
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/*
* Shutdown the hardware and driver:
@@ -2201,17 +2681,29 @@ ath_stop_locked(struct ifnet *ifp)
}
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 */
}
+
+ /* And now, restore the current power state */
+ ath_power_restore_power_state(sc);
}
-#define MAX_TXRX_ITERATIONS 1000
+/*
+ * Wait until all pending TX/RX has completed.
+ *
+ * This waits until all existing transmit, receive and interrupts
+ * have completed. It's assumed that the caller has first
+ * grabbed the reset lock so it doesn't try to do overlapping
+ * chip resets.
+ */
+#define MAX_TXRX_ITERATIONS 100
static void
ath_txrx_stop_locked(struct ath_softc *sc)
{
@@ -2230,7 +2722,8 @@ ath_txrx_stop_locked(struct ath_softc *sc)
sc->sc_txstart_cnt || sc->sc_intr_cnt) {
if (i <= 0)
break;
- msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", 1);
+ msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop",
+ msecs_to_ticks(10));
i--;
}
@@ -2277,7 +2770,7 @@ ath_txrx_start(struct ath_softc *sc)
* Another, cleaner way should be found to serialise all of
* these operations.
*/
-#define MAX_RESET_ITERATIONS 10
+#define MAX_RESET_ITERATIONS 25
static int
ath_reset_grablock(struct ath_softc *sc, int dowait)
{
@@ -2295,7 +2788,11 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
break;
}
ATH_PCU_UNLOCK(sc);
- pause("ath_reset_grablock", 1);
+ /*
+ * 1 tick is likely not enough time for long calibrations
+ * to complete. So we should wait quite a while.
+ */
+ pause("ath_reset_grablock", msecs_to_ticks(100));
i--;
ATH_PCU_LOCK(sc);
} while (i > 0);
@@ -2360,6 +2857,13 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
/* Try to (stop any further TX/RX from occuring */
taskqueue_block(sc->sc_tq);
+ /*
+ * Wake the hardware up.
+ */
+ ATH_LOCK(sc);
+ ath_power_set_power_state(sc, HAL_PM_AWAKE);
+ ATH_UNLOCK(sc);
+
ATH_PCU_LOCK(sc);
/*
@@ -2385,13 +2889,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.
* That way frames aren't dropped which shouldn't be.
@@ -2399,6 +2896,13 @@ 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);
@@ -2409,6 +2913,11 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
__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);
@@ -2454,9 +2963,13 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
* reset counter - this way ath_intr() doesn't end up
* disabling interrupts without a corresponding enable
* in the rest or channel change path.
+ *
+ * Grab the TX reference in case we need to transmit.
+ * That way a parallel transmit doesn't.
*/
ATH_PCU_LOCK(sc);
sc->sc_inreset_cnt--;
+ sc->sc_txstart_cnt++;
/* XXX only do this if sc_inreset_cnt == 0? */
ath_hal_intrset(ah, sc->sc_imask);
ATH_PCU_UNLOCK(sc);
@@ -2473,6 +2986,8 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
/* 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++) {
@@ -2497,6 +3012,14 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
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--;
+ ATH_PCU_UNLOCK(sc);
+
/* Handle any frames in the TX queue */
/*
* XXX should this be done by the caller, rather than
@@ -2637,6 +3160,7 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_status = bf->bf_status;
tbf->bf_m = bf->bf_m;
tbf->bf_node = bf->bf_node;
+ KASSERT((bf->bf_node != NULL), ("%s: bf_node=NULL!", __func__));
/* will be setup by the chain/setup function */
tbf->bf_lastds = NULL;
/* for now, last == self */
@@ -2738,6 +3262,11 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
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");
/*
* Grab the TX lock - it's ok to do this here; we haven't
@@ -2971,6 +3500,11 @@ finish:
sc->sc_txstart_cnt--;
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");
return (retval);
@@ -2998,7 +3532,6 @@ ath_key_update_begin(struct ieee80211vap *vap)
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_block(sc->sc_tq);
- IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */
}
static void
@@ -3008,7 +3541,6 @@ ath_key_update_end(struct ieee80211vap *vap)
struct ath_softc *sc = ifp->if_softc;
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
- IF_UNLOCK(&ifp->if_snd);
taskqueue_unblock(sc->sc_tq);
}
@@ -3019,16 +3551,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 */
@@ -3056,11 +3597,33 @@ ath_update_mcast(struct ifnet *ifp)
if_maddr_runlock(ifp);
} else
mfilt[0] = mfilt[1] = ~0;
+
ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
+
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)
{
@@ -3086,7 +3649,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);
}
/*
@@ -3118,8 +3681,13 @@ ath_setslottime(struct ath_softc *sc)
__func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags,
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);
}
/*
@@ -3136,6 +3704,8 @@ ath_updateslot(struct ifnet *ifp)
* When not coordinating the BSS, change the hardware
* immediately. For other operation we defer the change
* until beacon updates have propagated to the stations.
+ *
+ * XXX sc_updateslot isn't changed behind a lock?
*/
if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
ic->ic_opmode == IEEE80211_M_MBSS)
@@ -4041,14 +4611,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);
}
@@ -4257,6 +4825,10 @@ ath_tx_proc_q0(void *arg, int npending)
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);
@@ -4277,6 +4849,10 @@ 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);
}
@@ -4298,6 +4874,10 @@ ath_tx_proc_q0123(void *arg, int npending)
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);
@@ -4330,6 +4910,10 @@ 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);
}
@@ -4350,6 +4934,10 @@ ath_tx_proc(void *arg, int npending)
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);
/*
@@ -4375,6 +4963,10 @@ 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);
}
#undef TXQACTIVE
@@ -4401,6 +4993,10 @@ ath_txq_sched_tasklet(void *arg, int npending)
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++) {
if (ATH_TXQ_SETUP(sc, i)) {
@@ -4409,6 +5005,10 @@ 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);
@@ -4916,14 +5516,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);
@@ -4967,6 +5568,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);
@@ -5056,6 +5662,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);
+
+ /* 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);
@@ -5085,6 +5702,7 @@ 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);
+ ath_power_restore_power_state(sc);
return;
}
/*
@@ -5156,6 +5774,10 @@ restart:
__func__);
/* NB: don't rearm timer */
}
+ /*
+ * Restore power state now that we're done.
+ */
+ ath_power_restore_power_state(sc);
}
static void
@@ -5241,6 +5863,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
@@ -5251,6 +5877,7 @@ ath_set_channel(struct ieee80211com *ic)
ATH_LOCK(sc);
if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan)
sc->sc_syncbeacon = 1;
+ ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
}
@@ -5283,6 +5910,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int i, error, stamode;
u_int32_t rfilt;
int csa_run_transition = 0;
+ enum ieee80211_state ostate = vap->iv_state;
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
@@ -5296,7 +5924,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
};
DPRINTF(sc, ATH_DEBUG_STATE, "%s: %s -> %s\n", __func__,
- ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[ostate],
ieee80211_state_name[nstate]);
/*
@@ -5308,10 +5936,34 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
*/
IEEE80211_LOCK_ASSERT(ic);
- if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
+ /* 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
+ * set for PWRMGT=0. Otherwise we may end up with
+ * strange situations.
+ *
+ * XXX TODO: is this actually the case? :-)
+ */
+ if (nstate != IEEE80211_S_SLEEP)
+ ath_power_setselfgen(sc, HAL_PM_AWAKE);
+
+ /*
+ * Now, wake the thing up.
+ */
+ ath_power_set_power_state(sc, HAL_PM_AWAKE);
+
+ /*
+ * And stop the calibration callout whilst we have
+ * ATH_LOCK held.
+ */
+ callout_stop(&sc->sc_cal_ch);
+ ATH_UNLOCK(sc);
+
+ if (ostate == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
csa_run_transition = 1;
- callout_drain(&sc->sc_cal_ch);
ath_hal_setledstate(ah, leds[nstate]); /* set LED */
if (nstate == IEEE80211_S_SCAN) {
@@ -5321,6 +5973,13 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* [re]setup beacons. Unblock the task q thread so
* deferred interrupt processing is done.
*/
+
+ /* 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));
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
@@ -5333,6 +5992,11 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
stamode = (vap->iv_opmode == IEEE80211_M_STA ||
vap->iv_opmode == IEEE80211_M_AHDEMO ||
vap->iv_opmode == IEEE80211_M_IBSS);
+
+ /*
+ * XXX Dont need to do this (and others) if we've transitioned
+ * from SLEEP->RUN.
+ */
if (stamode && nstate == IEEE80211_S_RUN) {
sc->sc_curaid = ni->ni_associd;
IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid);
@@ -5435,11 +6099,14 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* beacon to update the beacon timer and thus we
* won't get notified of the missing beacons.
*/
- sc->sc_syncbeacon = 1;
-#if 0
- if (csa_run_transition)
-#endif
- ath_beacon_config(sc, vap);
+ if (ostate != IEEE80211_S_RUN &&
+ ostate != IEEE80211_S_SLEEP) {
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: STA; syncbeacon=1\n", __func__);
+ sc->sc_syncbeacon = 1;
+
+ if (csa_run_transition)
+ ath_beacon_config(sc, vap);
/*
* PR: kern/175227
@@ -5453,7 +6120,8 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* timer fires (too often), leading to a STA
* disassociation.
*/
- sc->sc_beacons = 1;
+ sc->sc_beacons = 1;
+ }
break;
case IEEE80211_M_MONITOR:
/*
@@ -5479,6 +6147,14 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
+
+ /*
+ * Force awake for RUN mode.
+ */
+ ATH_LOCK(sc);
+ ath_power_setselfgen(sc, HAL_PM_AWAKE);
+ ath_power_setpower(sc, HAL_PM_AWAKE);
+
/*
* Finally, start any timers and the task q thread
* (in case we didn't go through SCAN state).
@@ -5490,6 +6166,8 @@ 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) {
/*
@@ -5509,9 +6187,43 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
#ifdef IEEE80211_SUPPORT_TDMA
ath_hal_setcca(ah, AH_TRUE);
#endif
+ } else if (nstate == IEEE80211_S_SLEEP) {
+ /* We're going to sleep, so transition appropriately */
+ /* 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);
+ ATH_LOCK(sc);
+ /*
+ * Always at least set the self-generated
+ * frame config to set PWRMGT=1.
+ */
+ ath_power_setselfgen(sc, HAL_PM_NETWORK_SLEEP);
+
+ /*
+ * If we're not syncing beacons, transition
+ * to NETWORK_SLEEP.
+ *
+ * We stay awake if syncbeacon > 0 in case
+ * we need to listen for some beacons otherwise
+ * our beacon timer config may be wrong.
+ */
+ if (sc->sc_syncbeacon == 0) {
+ ath_power_setpower(sc, HAL_PM_NETWORK_SLEEP);
+ }
+ ATH_UNLOCK(sc);
+ }
}
bad:
ieee80211_free_node(ni);
+
+ /*
+ * 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;
}
@@ -5566,7 +6278,16 @@ 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: %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);
+ ATH_NODE_UNLOCK(an);
if (isnew &&
(vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
@@ -5806,10 +6527,14 @@ ath_watchdog(void *arg)
struct ath_softc *sc = arg;
int do_reset = 0;
+ ATH_LOCK_ASSERT(sc);
+
if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) {
struct ifnet *ifp = sc->sc_ifp;
uint32_t hangs;
+ ath_power_set_power_state(sc, HAL_PM_AWAKE);
+
if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) &&
hangs != 0) {
if_printf(ifp, "%s hang detected (0x%x)\n",
@@ -5819,6 +6544,8 @@ ath_watchdog(void *arg)
do_reset = 1;
ifp->if_oerrors++;
sc->sc_stats.ast_watchdog++;
+
+ ath_power_restore_power_state(sc);
}
/*
@@ -5916,6 +6643,13 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
goto bad;
}
}
+
+
+ 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)
ad->ad_out_size = outsize;
@@ -5925,6 +6659,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)
free(indata, M_TEMP);
@@ -5947,14 +6687,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
@@ -5968,14 +6711,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);
-#ifdef notyet
- /* XXX must wakeup in places like ath_vap_delete */
if (!sc->sc_invalid)
- ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
-#endif
+ ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
+ ATH_UNLOCK(sc);
}
- ATH_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@@ -6341,7 +7082,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 &&
@@ -6511,6 +7252,6 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
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
diff --git a/sys/dev/ath/if_ath_ahb.c b/sys/dev/ath/if_ath_ahb.c
index 59593b6..c400d93 100644
--- a/sys/dev/ath/if_ath_ahb.c
+++ b/sys/dev/ath/if_ath_ahb.c
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_ahb.c 279512 2015-03-02 02:14:44Z adrian $");
/*
* AHB bus front-end for the Atheros Wireless LAN controller driver.
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_arp.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
@@ -151,19 +153,30 @@ ath_ahb_attach(device_t dev)
eepromsize = ATH_EEPROM_DATA_SIZE * 2;
}
-
rid = 0;
device_printf(sc->sc_dev, "eeprom @ %p (%d bytes)\n",
(void *) eepromaddr, eepromsize);
- psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr,
- (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE);
+ /*
+ * XXX this assumes that the parent device is the nexus
+ * and will just pass through requests for all of memory.
+ *
+ * Later on, when this has to attach off of the actual
+ * AHB, this won't work.
+ *
+ * Ideally this would be done in machdep code in mips/atheros/
+ * and it'd expose the EEPROM via the firmware interface,
+ * so the ath/ath_ahb drivers can be loaded as modules
+ * after boot-time.
+ */
+ psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &rid, (uintptr_t) eepromaddr,
+ (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE);
if (psc->sc_eeprom == NULL) {
device_printf(dev, "cannot map eeprom space\n");
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)
@@ -348,6 +361,7 @@ static driver_t ath_ahb_driver = {
};
static devclass_t ath_devclass;
DRIVER_MODULE(ath, nexus, ath_ahb_driver, ath_devclass, 0, 0);
+DRIVER_MODULE(ath, apb, 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 */
diff --git a/sys/dev/ath/if_ath_alq.c b/sys/dev/ath/if_ath_alq.c
index 8ca53ae..79ad48c 100644
--- a/sys/dev/ath/if_ath_alq.c
+++ b/sys/dev/ath/if_ath_alq.c
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_alq.c 250618 2013-05-13 21:17:27Z adrian $
*/
#include "opt_ah.h"
#include "opt_ath.h"
diff --git a/sys/dev/ath/if_ath_alq.h b/sys/dev/ath/if_ath_alq.h
index 9f6ceac..b8b0c0d 100644
--- a/sys/dev/ath/if_ath_alq.h
+++ b/sys/dev/ath/if_ath_alq.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_alq.h 250619 2013-05-13 21:18:00Z adrian $
*/
#ifndef __IF_ATH_ALQ_H__
#define __IF_ATH_ALQ_H__
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index 11b0426..758ad6f 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_beacon.c 270430 2014-08-23 18:55:51Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -381,7 +382,7 @@ ath_beacon_update(struct ieee80211vap *vap, int item)
/*
* Handle a beacon miss.
*/
-static void
+void
ath_beacon_miss(struct ath_softc *sc)
{
HAL_SURVEY_SAMPLE hs;
@@ -748,6 +749,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);
}
}
@@ -915,7 +921,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
struct ieee80211_node *ni;
u_int32_t nexttbtt, intval, tsftu;
u_int32_t nexttbtt_u8, intval_u8;
- u_int64_t tsf;
+ u_int64_t tsf, tsf_beacon;
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
@@ -931,9 +937,17 @@ 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),
LE_READ_4(ni->ni_tstamp.data));
+
+ tsf_beacon = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32;
+ tsf_beacon |= LE_READ_4(ni->ni_tstamp.data);
+
if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
ic->ic_opmode == IEEE80211_M_MBSS) {
/*
@@ -979,14 +993,63 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
*/
tsf = ath_hal_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
- do {
- nexttbtt += intval;
- if (--dtimcount < 0) {
- dtimcount = dtimperiod - 1;
- if (--cfpcount < 0)
- cfpcount = cfpperiod - 1;
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: beacon tsf=%llu, hw tsf=%llu, nexttbtt=%u, tsftu=%u\n",
+ __func__,
+ (unsigned long long) tsf_beacon,
+ (unsigned long long) tsf,
+ nexttbtt,
+ tsftu);
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: beacon tsf=%llu, hw tsf=%llu, tsf delta=%lld\n",
+ __func__,
+ (unsigned long long) tsf_beacon,
+ (unsigned long long) tsf,
+ (long long) tsf -
+ (long long) tsf_beacon);
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: nexttbtt=%llu, beacon tsf delta=%lld\n",
+ __func__,
+ (unsigned long long) nexttbtt,
+ (long long) ((long long) nexttbtt * 1024LL) - (long long) tsf_beacon);
+
+ /* XXX cfpcount? */
+
+ if (nexttbtt > tsftu) {
+ uint32_t countdiff, oldtbtt, remainder;
+
+ oldtbtt = nexttbtt;
+ remainder = (nexttbtt - tsftu) % intval;
+ nexttbtt = tsftu + remainder;
+
+ countdiff = (oldtbtt - nexttbtt) / intval % dtimperiod;
+ if (dtimcount > countdiff) {
+ dtimcount -= countdiff;
+ } else {
+ dtimcount += dtimperiod - countdiff;
+ }
+ } else { //nexttbtt <= tsftu
+ uint32_t countdiff, oldtbtt, remainder;
+
+ oldtbtt = nexttbtt;
+ remainder = (tsftu - nexttbtt) % intval;
+ nexttbtt = tsftu - remainder + intval;
+ countdiff = (nexttbtt - oldtbtt) / intval % dtimperiod;
+ if (dtimcount > countdiff) {
+ dtimcount -= countdiff;
+ } else {
+ dtimcount += dtimperiod - countdiff;
}
- } while (nexttbtt < tsftu);
+ }
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: adj nexttbtt=%llu, rx tsf delta=%lld\n",
+ __func__,
+ (unsigned long long) nexttbtt,
+ (long long) ((long long)nexttbtt * 1024LL) - (long long)tsf);
+
memset(&bs, 0, sizeof(bs));
bs.bs_intval = intval;
bs.bs_nexttbtt = nexttbtt;
@@ -1033,9 +1096,12 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
DPRINTF(sc, ATH_DEBUG_BEACON,
- "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n"
+ "%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u "
+ "nextdtim %u bmiss %u sleep %u cfp:period %u "
+ "maxdur %u next %u timoffset %u\n"
, __func__
- , tsf, tsftu
+ , tsf
+ , tsftu
, bs.bs_intval
, bs.bs_nexttbtt
, bs.bs_dtimperiod
@@ -1112,8 +1178,11 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
ath_beacon_start_adhoc(sc, vap);
}
- sc->sc_syncbeacon = 0;
ieee80211_free_node(ni);
+
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
#undef FUDGE
#undef TSF_TO_TU
}
diff --git a/sys/dev/ath/if_ath_beacon.h b/sys/dev/ath/if_ath_beacon.h
index f3f73d7..b8a4a5d 100644
--- a/sys/dev/ath/if_ath_beacon.h
+++ b/sys/dev/ath/if_ath_beacon.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_beacon.h 265115 2014-04-30 02:19:41Z adrian $
*/
#ifndef __IF_ATH_BEACON_H__
#define __IF_ATH_BEACON_H__
@@ -48,5 +48,7 @@ extern int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni);
extern void ath_beacon_return(struct ath_softc *sc, struct ath_buf *bf);
extern void ath_beacon_free(struct ath_softc *sc);
extern void ath_beacon_proc(void *arg, int pending);
+extern void ath_beacon_miss(struct ath_softc *sc);
#endif
+
diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c
index fff6f3b..f3f44a6 100644
--- a/sys/dev/ath/if_ath_btcoex.c
+++ b/sys/dev/ath/if_ath_btcoex.c
@@ -26,10 +26,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_btcoex.c 277277 2015-01-17 00:02:18Z adrian $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_btcoex.c 277277 2015-01-17 00:02:18Z adrian $");
/*
* This implements some very basic bluetooth coexistence methods for
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
@@ -186,6 +188,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
/*
@@ -241,6 +309,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 {
diff --git a/sys/dev/ath/if_ath_btcoex.h b/sys/dev/ath/if_ath_btcoex.h
index 8b175d2..7faf418 100644
--- a/sys/dev/ath/if_ath_btcoex.h
+++ b/sys/dev/ath/if_ath_btcoex.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_btcoex.h 251487 2013-06-07 09:02:02Z adrian $
*/
#ifndef __IF_ATH_BTCOEX_H__
#define __IF_ATH_BTCOEX_H__
diff --git a/sys/dev/ath/if_ath_debug.c b/sys/dev/ath/if_ath_debug.c
index e3c73f5..6b5cc16 100644
--- a/sys/dev/ath/if_ath_debug.c
+++ b/sys/dev/ath/if_ath_debug.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_debug.c 267992 2014-06-28 03:56:17Z hselasky $");
#include "opt_inet.h"
#include "opt_ath.h"
@@ -92,9 +92,8 @@ __FBSDID("$FreeBSD$");
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,
diff --git a/sys/dev/ath/if_ath_debug.h b/sys/dev/ath/if_ath_debug.h
index 83597af..80d81a9 100644
--- a/sys/dev/ath/if_ath_debug.h
+++ b/sys/dev/ath/if_ath_debug.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_debug.h 265115 2014-04-30 02:19:41Z adrian $
*/
#ifndef __IF_ATH_DEBUG_H__
#define __IF_ATH_DEBUG_H__
@@ -68,6 +68,7 @@ enum {
ATH_DEBUG_SW_TX_FILT = 0x400000000ULL, /* SW TX FF */
ATH_DEBUG_NODE_PWRSAVE = 0x800000000ULL, /* node powersave */
ATH_DEBUG_DIVERSITY = 0x1000000000ULL, /* Diversity logic */
+ ATH_DEBUG_PWRSAVE = 0x2000000000ULL,
ATH_DEBUG_ANY = 0xffffffffffffffffULL
};
diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c
index 6c2749f..cfeb895 100644
--- a/sys/dev/ath/if_ath_keycache.c
+++ b/sys/dev/ath/if_ath_keycache.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_keycache.c 265115 2014-04-30 02:19:41Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -77,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_debug.h>
#include <dev/ath/if_ath_keycache.h>
+#include <dev/ath/if_ath_misc.h>
#ifdef ATH_DEBUG
static void
@@ -197,6 +199,7 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap,
u_int8_t gmac[IEEE80211_ADDR_LEN];
const u_int8_t *mac;
HAL_KEYVAL hk;
+ int ret;
memset(&hk, 0, sizeof(hk));
/*
@@ -250,13 +253,19 @@ 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) {
- return ath_keyset_tkip(sc, k, &hk, mac);
+ ret = ath_keyset_tkip(sc, k, &hk, mac);
} else {
KEYPRINTF(sc, k->wk_keyix, &hk, mac);
- return ath_hal_keyset(ah, k->wk_keyix, &hk, mac);
+ ret = ath_hal_keyset(ah, k->wk_keyix, &hk, mac);
}
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
+
+ return (ret);
#undef N
}
@@ -491,6 +500,8 @@ 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);
/*
* Handle split tx/rx keying required for TKIP with h/w MIC.
@@ -514,6 +525,8 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
}
}
}
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
return 1;
}
diff --git a/sys/dev/ath/if_ath_keycache.h b/sys/dev/ath/if_ath_keycache.h
index 0b79e6f..1e5c6f3 100644
--- a/sys/dev/ath/if_ath_keycache.h
+++ b/sys/dev/ath/if_ath_keycache.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_keycache.h 227357 2011-11-08 19:25:52Z adrian $
*/
#ifndef __IF_ATH_CRYPTO_H__
diff --git a/sys/dev/ath/if_ath_led.c b/sys/dev/ath/if_ath_led.c
index 33cc512..2e11df0 100644
--- a/sys/dev/ath/if_ath_led.c
+++ b/sys/dev/ath/if_ath_led.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_led.c 265115 2014-04-30 02:19:41Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -122,6 +122,11 @@ __FBSDID("$FreeBSD$");
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) {
ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin,
@@ -144,6 +149,10 @@ ath_led_config(struct ath_softc *sc)
ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_led_net_pin,
HAL_GPIO_OUTPUT_MUX_MAC_NETWORK_LED);
}
+
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
}
static void
diff --git a/sys/dev/ath/if_ath_led.h b/sys/dev/ath/if_ath_led.h
index 54de4c4..52a5602 100644
--- a/sys/dev/ath/if_ath_led.h
+++ b/sys/dev/ath/if_ath_led.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_led.h 228888 2011-12-26 05:46:22Z adrian $
*/
#ifndef __IF_ATH_LED_H__
#define __IF_ATH_LED_H__
diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c
index 4ae81a3..373dc10 100644
--- a/sys/dev/ath/if_ath_lna_div.c
+++ b/sys/dev/ath/if_ath_lna_div.c
@@ -26,10 +26,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_lna_div.c 272292 2014-09-30 03:19:29Z adrian $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_lna_div.c 272292 2014-09-30 03:19:29Z adrian $");
/*
* This module handles LNA diversity for those chips which implement LNA
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
@@ -207,6 +209,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)
diff --git a/sys/dev/ath/if_ath_lna_div.h b/sys/dev/ath/if_ath_lna_div.h
index 997466a..d988269 100644
--- a/sys/dev/ath/if_ath_lna_div.h
+++ b/sys/dev/ath/if_ath_lna_div.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_lna_div.h 251730 2013-06-14 03:42:10Z adrian $
*/
#ifndef __IF_ATH_LNA_DIV_H__
#define __IF_ATH_LNA_DIV_H__
diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h
index 0c99bc7..1e14a9f 100644
--- a/sys/dev/ath/if_ath_misc.h
+++ b/sys/dev/ath/if_ath_misc.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_misc.h 265205 2014-05-02 00:48:09Z adrian $
*/
#ifndef __IF_ATH_MISC_H__
#define __IF_ATH_MISC_H__
@@ -128,6 +128,19 @@ extern void ath_start_task(void *arg, int npending);
extern void ath_tx_dump(struct ath_softc *sc, struct ath_txq *txq);
/*
+ * Power state tracking.
+ */
+extern void _ath_power_setpower(struct ath_softc *sc, int power_state, const char *file, int line);
+extern void _ath_power_set_selfgen(struct ath_softc *sc, int power_state, const char *file, int line);
+extern void _ath_power_set_power_state(struct ath_softc *sc, int power_state, const char *file, int line);
+extern void _ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line);
+
+#define ath_power_setpower(sc, ps) _ath_power_setpower(sc, ps, __FILE__, __LINE__)
+#define ath_power_setselfgen(sc, ps) _ath_power_set_selfgen(sc, ps, __FILE__, __LINE__)
+#define ath_power_set_power_state(sc, ps) _ath_power_set_power_state(sc, ps, __FILE__, __LINE__)
+#define ath_power_restore_power_state(sc) _ath_power_restore_power_state(sc, __FILE__, __LINE__)
+
+/*
* Kick the frame TX task.
*/
static inline void
diff --git a/sys/dev/ath/if_ath_pci.c b/sys/dev/ath/if_ath_pci.c
index 91cb425..8cc0d00 100644
--- a/sys/dev/ath/if_ath_pci.c
+++ b/sys/dev/ath/if_ath_pci.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_pci.c 278765 2015-02-14 18:14:45Z adrian $");
/*
* PCI/Cardbus front-end for the Atheros Wireless LAN controller driver.
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -53,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_arp.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
@@ -78,6 +80,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
@@ -148,9 +242,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.
*/
@@ -171,8 +271,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)
@@ -180,6 +279,13 @@ ath_pci_attach(device_t dev)
*/
sc->sc_invalid = 1;
+ ATH_LOCK_INIT(sc);
+ ATH_PCU_LOCK_INIT(sc);
+ ATH_RX_LOCK_INIT(sc);
+ ATH_TX_LOCK_INIT(sc);
+ ATH_TX_IC_LOCK_INIT(sc);
+ ATH_TXSTATUS_LOCK_INIT(sc);
+
/*
* Arrange interrupt line.
*/
@@ -230,7 +336,7 @@ ath_pci_attach(device_t dev)
if (fw == NULL) {
device_printf(dev, "%s: couldn't find firmware\n",
__func__);
- goto bad3;
+ goto bad4;
}
device_printf(dev, "%s: EEPROM firmware @ %p\n",
@@ -240,30 +346,20 @@ ath_pci_attach(device_t dev)
if (! sc->sc_eepromdata) {
device_printf(dev, "%s: can't malloc eepromdata\n",
__func__);
- goto bad3;
+ goto bad4;
}
memcpy(sc->sc_eepromdata, fw->data, fw->datasize);
firmware_put(fw, 0);
}
#endif /* ATH_EEPROM_FIRMWARE */
- ATH_LOCK_INIT(sc);
- ATH_PCU_LOCK_INIT(sc);
- ATH_RX_LOCK_INIT(sc);
- ATH_TX_LOCK_INIT(sc);
- ATH_TX_IC_LOCK_INIT(sc);
- ATH_TXSTATUS_LOCK_INIT(sc);
-
error = ath_attach(pci_get_device(dev), sc);
if (error == 0) /* success */
return 0;
- ATH_TXSTATUS_LOCK_DESTROY(sc);
- ATH_PCU_LOCK_DESTROY(sc);
- ATH_RX_LOCK_DESTROY(sc);
- ATH_TX_IC_LOCK_DESTROY(sc);
- ATH_TX_LOCK_DESTROY(sc);
- ATH_LOCK_DESTROY(sc);
+#ifdef ATH_EEPROM_FIRMWARE
+bad4:
+#endif
bus_dma_tag_destroy(sc->sc_dmat);
bad3:
bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
@@ -271,6 +367,14 @@ bad2:
bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
bad1:
bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr);
+
+ ATH_TXSTATUS_LOCK_DESTROY(sc);
+ ATH_PCU_LOCK_DESTROY(sc);
+ ATH_RX_LOCK_DESTROY(sc);
+ ATH_TX_IC_LOCK_DESTROY(sc);
+ ATH_TX_LOCK_DESTROY(sc);
+ ATH_LOCK_DESTROY(sc);
+
bad:
return (error);
}
diff --git a/sys/dev/ath/if_ath_pci_devlist.h b/sys/dev/ath/if_ath_pci_devlist.h
new file mode 100644
index 0000000..c699f04
--- /dev/null
+++ b/sys/dev/ath/if_ath_pci_devlist.h
@@ -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: head/sys/dev/ath/if_ath_pci_devlist.h 272295 2014-09-30 05:50:34Z adrian $
+ */
+
+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 }
+};
+
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index d9e212b..2799ffd 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_rx.c 271823 2014-09-18 20:47:39Z glebius $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -165,10 +166,22 @@ ath_calcrxfilter(struct ath_softc *sc)
/* XXX ic->ic_monvaps != 0? */
if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
rfilt |= HAL_RX_FILTER_PROM;
+
+ /*
+ * Only listen to all beacons if we're scanning.
+ *
+ * Otherwise we only really need to hear beacons from
+ * our own BSSID.
+ */
if (ic->ic_opmode == IEEE80211_M_STA ||
- ic->ic_opmode == IEEE80211_M_IBSS ||
- sc->sc_swbmiss || sc->sc_scanning)
- rfilt |= HAL_RX_FILTER_BEACON;
+ ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss) {
+ if (sc->sc_do_mybeacon && ! sc->sc_scanning) {
+ rfilt |= HAL_RX_FILTER_MYBEACON;
+ } else { /* scanning, non-mybeacon chips */
+ rfilt |= HAL_RX_FILTER_BEACON;
+ }
+ }
+
/*
* NB: We don't recalculate the rx filter when
* ic_protmode changes; otherwise we could do
@@ -232,6 +245,8 @@ ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
struct mbuf *m;
struct ath_desc *ds;
+ /* XXX TODO: ATH_RX_LOCK_ASSERT(sc); */
+
m = bf->bf_m;
if (m == NULL) {
/*
@@ -316,6 +331,23 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
{
struct ieee80211vap *vap = ni->ni_vap;
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ uint64_t tsf_beacon_old, tsf_beacon;
+ uint64_t nexttbtt;
+ int64_t tsf_delta;
+ int32_t tsf_delta_bmiss;
+ int32_t tsf_remainder;
+ uint64_t tsf_beacon_target;
+ int tsf_intval;
+
+ tsf_beacon_old = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32;
+ tsf_beacon_old |= LE_READ_4(ni->ni_tstamp.data);
+
+#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10)
+ tsf_intval = 1;
+ if (ni->ni_intval > 0) {
+ tsf_intval = TU_TO_TSF(ni->ni_intval);
+ }
+#undef TU_TO_TSF
/*
* Call up first so subsequent work can use information
@@ -327,14 +359,79 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
/* update rssi statistics for use by the hal */
/* XXX unlocked check against vap->iv_bss? */
ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi);
+
+ tsf_beacon = ((uint64_t) LE_READ_4(ni->ni_tstamp.data + 4)) << 32;
+ tsf_beacon |= LE_READ_4(ni->ni_tstamp.data);
+
+ nexttbtt = ath_hal_getnexttbtt(sc->sc_ah);
+
+ /*
+ * Let's calculate the delta and remainder, so we can see
+ * if the beacon timer from the AP is varying by more than
+ * a few TU. (Which would be a huge, huge problem.)
+ */
+ tsf_delta = (long long) tsf_beacon - (long long) tsf_beacon_old;
+
+ tsf_delta_bmiss = tsf_delta / tsf_intval;
+
+ /*
+ * If our delta is greater than half the beacon interval,
+ * let's round the bmiss value up to the next beacon
+ * interval. Ie, we're running really, really early
+ * on the next beacon.
+ */
+ if (tsf_delta % tsf_intval > (tsf_intval / 2))
+ tsf_delta_bmiss ++;
+
+ tsf_beacon_target = tsf_beacon_old +
+ (((unsigned long long) tsf_delta_bmiss) * (long long) tsf_intval);
+
+ /*
+ * The remainder using '%' is between 0 .. intval-1.
+ * If we're actually running too fast, then the remainder
+ * will be some large number just under intval-1.
+ * So we need to look at whether we're running
+ * before or after the target beacon interval
+ * and if we are, modify how we do the remainder
+ * calculation.
+ */
+ if (tsf_beacon < tsf_beacon_target) {
+ tsf_remainder =
+ -(tsf_intval - ((tsf_beacon - tsf_beacon_old) % tsf_intval));
+ } else {
+ tsf_remainder = (tsf_beacon - tsf_beacon_old) % tsf_intval;
+ }
+
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: old_tsf=%llu, new_tsf=%llu, target_tsf=%llu, delta=%lld, bmiss=%d, remainder=%d\n",
+ __func__,
+ (unsigned long long) tsf_beacon_old,
+ (unsigned long long) tsf_beacon,
+ (unsigned long long) tsf_beacon_target,
+ (long long) tsf_delta,
+ tsf_delta_bmiss,
+ tsf_remainder);
+
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: tsf=%llu, nexttbtt=%llu, delta=%d\n",
+ __func__,
+ (unsigned long long) tsf_beacon,
+ (unsigned long long) nexttbtt,
+ (int32_t) tsf_beacon - (int32_t) nexttbtt + tsf_intval);
+
if (sc->sc_syncbeacon &&
- ni == vap->iv_bss && vap->iv_state == IEEE80211_S_RUN) {
+ ni == vap->iv_bss &&
+ (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) {
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: syncbeacon=1; syncing\n",
+ __func__);
/*
* Resync beacon timers using the tsf of the beacon
* frame we just received.
*/
ath_beacon_config(sc, vap);
+ sc->sc_syncbeacon = 0;
}
+
+
/* fall thru... */
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
if (vap->iv_opmode == IEEE80211_M_IBSS &&
@@ -879,6 +976,14 @@ rx_next:
#define ATH_RX_MAX 128
+/*
+ * XXX TODO: break out the "get buffers" from "call ath_rx_pkt()" like
+ * the EDMA code does.
+ *
+ * XXX TODO: then, do all of the RX list management stuff inside
+ * ATH_RX_LOCK() so we don't end up potentially racing. The EDMA
+ * code is doing it right.
+ */
static void
ath_rx_proc(struct ath_softc *sc, int resched)
{
@@ -900,6 +1005,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
u_int64_t tsf;
int npkts = 0;
int kickpcu = 0;
+ int ret;
/* XXX we must not hold the ATH_LOCK here */
ATH_UNLOCK_ASSERT(sc);
@@ -910,6 +1016,10 @@ 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;
nf = ath_hal_getchannoise(ah, sc->sc_curchan);
@@ -995,8 +1105,26 @@ ath_rx_proc(struct ath_softc *sc, int resched)
if (ath_rx_pkt(sc, rs, status, tsf, nf, HAL_RX_QUEUE_HP, bf, m))
ngood++;
rx_proc_next:
- TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
- } while (ath_rxbuf_init(sc, bf) == 0);
+ /*
+ * If there's a holding buffer, insert that onto
+ * the RX list; the hardware is now definitely not pointing
+ * to it now.
+ */
+ ret = 0;
+ if (sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf != NULL) {
+ TAILQ_INSERT_TAIL(&sc->sc_rxbuf,
+ sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf,
+ bf_list);
+ ret = ath_rxbuf_init(sc,
+ sc->sc_rxedma[HAL_RX_QUEUE_HP].m_holdbf);
+ }
+ /*
+ * Next, throw our buffer into the holding entry. The hardware
+ * may use the descriptor to read the link pointer before
+ * DMAing the next descriptor in to write out a packet.
+ */
+ 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);
@@ -1028,6 +1156,13 @@ rx_proc_next:
* constantly write over the same frame, leading
* the RX driver code here to get heavily confused.
*/
+ /*
+ * XXX Has RX DMA stopped enough here to just call
+ * ath_startrecv()?
+ * XXX Do we need to use the holding buffer to restart
+ * RX DMA by appending entries to the final
+ * descriptor? Quite likely.
+ */
#if 1
ath_startrecv(sc);
#else
@@ -1065,6 +1200,13 @@ rx_proc_next:
#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,
* reschedule for another immediate pass. This gives
* the TX and TX completion routines time to run, which
@@ -1111,6 +1253,58 @@ ath_legacy_flushrecv(struct ath_softc *sc)
ath_rx_proc(sc, 0);
}
+static void
+ath_legacy_flush_rxpending(struct ath_softc *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;
+ }
+}
+
+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);
+}
+
/*
* Disable the receive h/w in preparation for a reset.
*/
@@ -1122,6 +1316,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 */
@@ -1155,22 +1351,23 @@ ath_legacy_stoprecv(struct ath_softc *sc, int dodelay)
}
}
#endif
- /*
- * Free both high/low RX pending, just in case.
- */
- 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;
- }
+
+ (void) ath_legacy_flush_rxpending(sc);
+ (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.
*/
static int
@@ -1179,9 +1376,18 @@ 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;
- sc->sc_rxedma[HAL_RX_QUEUE_LP].m_rxpending = NULL;
- sc->sc_rxedma[HAL_RX_QUEUE_HP].m_rxpending = NULL;
+ (void) ath_legacy_flush_rxpending(sc);
+ (void) ath_legacy_flush_rxholdbf(sc);
+
+ /*
+ * Re-chain all of the buffers in the RX buffer list.
+ */
TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
int error = ath_rxbuf_init(sc, bf);
if (error != 0) {
@@ -1197,6 +1403,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;
}
diff --git a/sys/dev/ath/if_ath_rx.h b/sys/dev/ath/if_ath_rx.h
index f831148..9a33df7 100644
--- a/sys/dev/ath/if_ath_rx.h
+++ b/sys/dev/ath/if_ath_rx.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_rx.h 249085 2013-04-04 08:21:56Z adrian $
*/
#ifndef __IF_ATH_RX_H__
#define __IF_ATH_RX_H__
diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c
index 2be8627..33bf31a 100644
--- a/sys/dev/ath/if_ath_rx_edma.c
+++ b/sys/dev/ath/if_ath_rx_edma.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_rx_edma.c 271887 2014-09-20 01:22:17Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -159,10 +160,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 */
@@ -217,10 +228,6 @@ ath_edma_reinit_fifo(struct ath_softc *sc, HAL_RX_QUEUE qtype)
/*
* 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)
@@ -229,35 +236,31 @@ 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);
/*
- * Entries should only be written out if the
- * FIFO is empty.
- *
- * XXX This isn't correct. I should be looking
- * at the value of AR_RXDP_SIZE (0x0070) to determine
- * how many entries are in here.
- *
- * A warm reset will clear the registers but not the FIFO.
- *
- * And I believe this is actually the address of the last
- * handled buffer rather than the current FIFO pointer.
- * So if no frames have been (yet) seen, we'll reinit the
- * FIFO.
- *
- * I'll chase that up at some point.
+ * In theory the hardware has been initialised, right?
*/
- if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_HP) == 0) {
+ 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);
- }
- if (ath_hal_getrxbuf(sc->sc_ah, HAL_RX_QUEUE_LP) == 0) {
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 */
@@ -265,6 +268,9 @@ ath_edma_startrecv(struct ath_softc *sc)
* 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);
@@ -275,6 +281,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);
@@ -285,7 +296,16 @@ 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);
+ 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);
}
@@ -293,8 +313,17 @@ static void
ath_edma_recv_sched(struct ath_softc *sc, int dosched)
{
+ ATH_LOCK(sc);
+ ath_power_set_power_state(sc, HAL_PM_AWAKE);
+ 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);
}
@@ -308,6 +337,10 @@ 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
*/
@@ -317,9 +350,18 @@ ath_edma_recv_flush(struct ath_softc *sc)
/*
* Process what's in the deferred queue
*/
+ /*
+ * 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_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--;
ATH_PCU_UNLOCK(sc);
@@ -348,6 +390,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! */
@@ -419,24 +476,6 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
"ath edma rx proc: npkts=%d\n",
npkts);
- /* Handle resched and kickpcu appropriately */
- ATH_PCU_LOCK(sc);
- if (dosched && sc->sc_kickpcu) {
- ATH_KTR(sc, ATH_KTR_ERROR, 0,
- "ath_edma_recv_proc_queue(): kickpcu");
- if (npkts > 0)
- device_printf(sc->sc_dev,
- "%s: handled npkts %d\n",
- __func__, npkts);
-
- /*
- * XXX TODO: what should occur here? Just re-poke and
- * re-enable the RX FIFO?
- */
- sc->sc_kickpcu = 0;
- }
- ATH_PCU_UNLOCK(sc);
-
return;
}
@@ -449,18 +488,20 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
static void
ath_edma_flush_deferred_queue(struct ath_softc *sc)
{
- struct ath_buf *bf, *next;
+ struct ath_buf *bf;
ATH_RX_LOCK_ASSERT(sc);
/* Free in one set, inside the lock */
- TAILQ_FOREACH_SAFE(bf,
- &sc->sc_rx_rxlist[HAL_RX_QUEUE_LP], bf_list, next) {
+ 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);
}
- TAILQ_FOREACH_SAFE(bf,
- &sc->sc_rx_rxlist[HAL_RX_QUEUE_HP], bf_list, next) {
+ 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);
}
@@ -494,6 +535,10 @@ ath_edma_recv_proc_deferred_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
ATH_RX_UNLOCK(sc);
/* Handle the completed descriptors */
+ /*
+ * 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
@@ -519,7 +564,9 @@ 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);
- TAILQ_FOREACH_SAFE(bf, &rxlist, bf_list, next) {
+ while (! TAILQ_EMPTY(&rxlist)) {
+ bf = TAILQ_FIRST(&rxlist);
+ TAILQ_REMOVE(&rxlist, bf, bf_list);
/* Free the buffer/mbuf */
ath_edma_rxbuf_free(sc, bf);
}
@@ -551,12 +598,25 @@ ath_edma_recv_tasklet(void *arg, int npending)
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_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);
+ /*
+ * 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 ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
@@ -835,10 +895,13 @@ 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 = malloc(sizeof(struct ath_buf *) * re->m_fifolen,
@@ -929,10 +992,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;
diff --git a/sys/dev/ath/if_ath_rx_edma.h b/sys/dev/ath/if_ath_rx_edma.h
index e786daa..6635abc 100644
--- a/sys/dev/ath/if_ath_rx_edma.h
+++ b/sys/dev/ath/if_ath_rx_edma.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_rx_edma.h 238055 2012-07-03 06:59:12Z adrian $
*/
#ifndef __IF_ATH_RX_EDMA_H__
#define __IF_ATH_RX_EDMA_H__
diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c
index 5cfb1a9..2a2013f 100644
--- a/sys/dev/ath/if_ath_spectral.c
+++ b/sys/dev/ath/if_ath_spectral.c
@@ -26,10 +26,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_spectral.c 257176 2013-10-26 17:58:36Z glebius $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_spectral.c 257176 2013-10-26 17:58:36Z glebius $");
/*
* Implement some basic spectral scan control logic.
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/errno.h>
@@ -53,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
diff --git a/sys/dev/ath/if_ath_spectral.h b/sys/dev/ath/if_ath_spectral.h
index 3e069db..4d21395 100644
--- a/sys/dev/ath/if_ath_spectral.h
+++ b/sys/dev/ath/if_ath_spectral.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_spectral.h 244951 2013-01-02 03:59:02Z adrian $
*/
#ifndef __IF_ATH_SPECTRAL_H__
#define __IF_ATH_SPECTRAL_H__
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index 0a5719a..15593ca 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_sysctl.c 276150 2014-12-23 18:48:45Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -107,13 +108,26 @@ static int
ath_sysctl_slottime(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
- u_int slottime = ath_hal_getslottime(sc->sc_ah);
+ u_int slottime;
int error;
+ 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 || !req->newptr)
- return error;
- return !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
+ goto finish;
+
+ error = !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
+
+finish:
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
+
+ return error;
}
static int
@@ -399,12 +413,14 @@ ath_sysctl_txagg(SYSCTL_HANDLER_ARGS)
ATH_RX_LOCK(sc);
for (i = 0; i < 2; i++) {
- printf("%d: fifolen: %d/%d; head=%d; tail=%d\n",
+ printf("%d: fifolen: %d/%d; head=%d; tail=%d; m_pending=%p, m_holdbf=%p\n",
i,
sc->sc_rxedma[i].m_fifo_depth,
sc->sc_rxedma[i].m_fifolen,
sc->sc_rxedma[i].m_fifo_head,
- sc->sc_rxedma[i].m_fifo_tail);
+ sc->sc_rxedma[i].m_fifo_tail,
+ sc->sc_rxedma[i].m_rxpending,
+ sc->sc_rxedma[i].m_holdbf);
}
i = 0;
TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
@@ -430,7 +446,15 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
return error;
if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent))
return EINVAL;
- sc->sc_rfsilentpin = rfsilent & 0x1c;
+ /*
+ * 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;
return 0;
}
diff --git a/sys/dev/ath/if_ath_sysctl.h b/sys/dev/ath/if_ath_sysctl.h
index 1fef2be..9a53488 100644
--- a/sys/dev/ath/if_ath_sysctl.h
+++ b/sys/dev/ath/if_ath_sysctl.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_sysctl.h 223459 2011-06-23 02:38:36Z adrian $
*/
#ifndef __IF_ATH_SYSCTL_H__
diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c
index c075d01..fbf936d 100644
--- a/sys/dev/ath/if_ath_tdma.c
+++ b/sys/dev/ath/if_ath_tdma.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tdma.c 265588 2014-05-07 19:07:45Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -476,16 +477,19 @@ ath_tdma_update(struct ieee80211_node *ni,
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
"rs->rstamp %llu rstamp %llu tsf %llu txtime %d, nextslot %llu, "
"nextslottu %d, nextslottume %d\n",
- (unsigned long long) rs->rs_tstamp, rstamp, tsf, txtime,
- 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: %llu (0x%016llx)\n",
- le64toh(ni->ni_tstamp.tsf),
- le64toh(ni->ni_tstamp.tsf));
+ (unsigned long long) le64toh(ni->ni_tstamp.tsf),
+ (unsigned long long) le64toh(ni->ni_tstamp.tsf));
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
"nexttbtt %llu (0x%08llx) tsfdelta %d avg +%d/-%d\n",
- nexttbtt,
+ (unsigned long long) nexttbtt,
(long long) nexttbtt,
tsfdelta,
TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam));
@@ -579,7 +583,7 @@ ath_tdma_update(struct ieee80211_node *ni,
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
"%s: calling ath_hal_adjusttsf: TSF=%llu, tsfdelta=%d\n",
__func__,
- tsf,
+ (unsigned long long) tsf,
tsfdelta);
#ifdef ATH_DEBUG_ALQ
diff --git a/sys/dev/ath/if_ath_tdma.h b/sys/dev/ath/if_ath_tdma.h
index 1e90a5f..010ed11 100644
--- a/sys/dev/ath/if_ath_tdma.h
+++ b/sys/dev/ath/if_ath_tdma.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_tdma.h 235679 2012-05-20 02:49:42Z adrian $
*/
#ifndef __IF_ATH_TDMA_H__
#define __IF_ATH_TDMA_H__
diff --git a/sys/dev/ath/if_ath_tsf.h b/sys/dev/ath/if_ath_tsf.h
index cce089f..f6ab268 100644
--- a/sys/dev/ath/if_ath_tsf.h
+++ b/sys/dev/ath/if_ath_tsf.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_tsf.h 235676 2012-05-20 02:05:10Z adrian $
*/
#ifndef __IF_ATH_TSF_H__
#define __IF_ATH_TSF_H__
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 8bacd92..2ae4862 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 271823 2014-09-18 20:47:39Z glebius $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -59,10 +59,12 @@ __FBSDID("$FreeBSD$");
#include <sys/kthread.h>
#include <sys/taskqueue.h>
#include <sys/priv.h>
+#include <sys/ktr.h>
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -759,37 +761,21 @@ ath_tx_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
("ath_tx_handoff_hw called for mcast queue"));
/*
- * XXX racy, should hold the PCU lock when checking this,
- * and also should ensure that the TX counter is >0!
+ * XXX We should instead just verify that sc_txstart_cnt
+ * or ath_txproc_cnt > 0. That would mean that
+ * the reset is going to be waiting for us to complete.
*/
- KASSERT((sc->sc_inreset_cnt == 0),
- ("%s: TX during reset?\n", __func__));
+ if (sc->sc_txproc_cnt == 0 && sc->sc_txstart_cnt == 0) {
+ device_printf(sc->sc_dev,
+ "%s: TX dispatch without holding txcount/txstart refcnt!\n",
+ __func__);
+ }
-#if 0
/*
- * This causes a LOR. Find out where the PCU lock is being
- * held whilst the TXQ lock is grabbed - that shouldn't
- * be occuring.
+ * XXX .. this is going to cause the hardware to get upset;
+ * so we really should find some way to drop or queue
+ * things.
*/
- ATH_PCU_LOCK(sc);
- if (sc->sc_inreset_cnt) {
- ATH_PCU_UNLOCK(sc);
- DPRINTF(sc, ATH_DEBUG_RESET,
- "%s: called with sc_in_reset != 0\n",
- __func__);
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: queued: TXDP[%u] = %p (%p) depth %d\n",
- __func__, txq->axq_qnum,
- (caddr_t)bf->bf_daddr, bf->bf_desc,
- txq->axq_depth);
- /* XXX axq_link needs to be set and updated! */
- ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
- if (bf->bf_state.bfs_aggr)
- txq->axq_aggr_depth++;
- return;
- }
- ATH_PCU_UNLOCK(sc);
-#endif
ATH_TXQ_LOCK(txq);
@@ -1613,6 +1599,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
error = ath_tx_dmasetup(sc, bf, m0);
if (error != 0)
return error;
+ KASSERT((ni != NULL), ("%s: ni=NULL!", __func__));
bf->bf_node = ni; /* NB: held reference */
m0 = bf->bf_m; /* NB: may have changed */
wh = mtod(m0, struct ieee80211_frame *);
@@ -2104,6 +2091,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
int do_override;
uint8_t type, subtype;
int queue_to_head;
+ struct ath_node *an = ATH_NODE(ni);
ATH_TX_LOCK_ASSERT(sc);
@@ -2163,6 +2151,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
return error;
m0 = bf->bf_m; /* NB: may have changed */
wh = mtod(m0, struct ieee80211_frame *);
+ KASSERT((ni != NULL), ("%s: ni=NULL!", __func__));
bf->bf_node = ni; /* NB: held reference */
/* Always enable CLRDMASK for raw frames for now.. */
@@ -2181,12 +2170,24 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
rt = sc->sc_currates;
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+
+ /* Fetch first rate information */
rix = ath_tx_findrix(sc, params->ibp_rate0);
+ try0 = params->ibp_try0;
+
+ /*
+ * Override EAPOL rate as appropriate.
+ */
+ if (m0->m_flags & M_EAPOL) {
+ /* XXX? maybe always use long preamble? */
+ rix = an->an_mgmtrix;
+ try0 = ATH_TXMAXTRY; /* XXX?too many? */
+ }
+
txrate = rt->info[rix].rateCode;
if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
txrate |= rt->info[rix].shortPreamble;
sc->sc_txrix = rix;
- try0 = params->ibp_try0;
ismrr = (params->ibp_try1 != 0);
txantenna = params->ibp_pri >> 2;
if (txantenna == 0) /* XXX? */
@@ -2259,8 +2260,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
/* Blank the legacy rate array */
bzero(&bf->bf_state.bfs_rc, sizeof(bf->bf_state.bfs_rc));
- bf->bf_state.bfs_rc[0].rix =
- ath_tx_findrix(sc, params->ibp_rate0);
+ bf->bf_state.bfs_rc[0].rix = rix;
bf->bf_state.bfs_rc[0].tries = try0;
bf->bf_state.bfs_rc[0].ratecode = txrate;
@@ -2352,11 +2352,16 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
"%s: sc_inreset_cnt > 0; bailing\n", __func__);
error = EIO;
ATH_PCU_UNLOCK(sc);
- goto bad0;
+ goto badbad;
}
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_TX_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
@@ -2435,7 +2440,14 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
sc->sc_txstart_cnt--;
ATH_PCU_UNLOCK(sc);
+
+ /* Put the hardware back to sleep if required */
+ ATH_LOCK(sc);
+ ath_power_restore_power_state(sc);
+ ATH_UNLOCK(sc);
+
return 0;
+
bad2:
ATH_KTR(sc, ATH_KTR_TX, 3, "ath_raw_xmit: bad2: m=%p, params=%p, "
"bf=%p",
@@ -2445,14 +2457,20 @@ bad2:
ATH_TXBUF_LOCK(sc);
ath_returnbuf_head(sc, bf);
ATH_TXBUF_UNLOCK(sc);
-bad:
+bad:
ATH_TX_UNLOCK(sc);
ATH_PCU_LOCK(sc);
sc->sc_txstart_cnt--;
ATH_PCU_UNLOCK(sc);
-bad0:
+
+ /* 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++;
@@ -2748,8 +2766,8 @@ ath_tx_update_baw(struct ath_softc *sc, struct ath_node *an,
INCR(tid->baw_head, ATH_TID_MAX_BUFS);
}
DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
- "%s: baw is now %d:%d, baw head=%d\n",
- __func__, tap->txa_start, tap->txa_wnd, tid->baw_head);
+ "%s: tid=%d: baw is now %d:%d, baw head=%d\n",
+ __func__, tid->tid, tap->txa_start, tap->txa_wnd, tid->baw_head);
}
static void
@@ -3242,8 +3260,11 @@ 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: paused = %d\n",
- __func__, tid->paused);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: [%6D]: tid=%d, paused = %d\n",
+ __func__,
+ tid->an->an_node.ni_macaddr, ":",
+ tid->tid,
+ tid->paused);
}
/*
@@ -3260,15 +3281,21 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
* until it's actually resolved.
*/
if (tid->paused == 0) {
- DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
- "%s: %6D: paused=0?\n", __func__,
- tid->an->an_node.ni_macaddr, ":");
+ device_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: unpaused = %d\n",
- __func__, tid->paused);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: [%6D]: tid=%d, unpaused = %d\n",
+ __func__,
+ tid->an->an_node.ni_macaddr, ":",
+ tid->tid,
+ tid->paused);
if (tid->paused)
return;
@@ -3334,8 +3361,8 @@ ath_tx_tid_filt_comp_buf(struct ath_softc *sc, struct ath_tid *tid,
ATH_TX_LOCK_ASSERT(sc);
if (! tid->isfiltered) {
- DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: filter transition\n",
- __func__);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: tid=%d; filter transition\n",
+ __func__, tid->tid);
tid->isfiltered = 1;
ath_tx_tid_pause(sc, tid);
}
@@ -3355,15 +3382,20 @@ static void
ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid)
{
struct ath_buf *bf;
+ int do_resume = 0;
ATH_TX_LOCK_ASSERT(sc);
if (tid->hwq_depth != 0)
return;
- DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
- __func__);
- tid->isfiltered = 0;
+ DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: tid=%d, hwq=0, transition back\n",
+ __func__, tid->tid);
+ if (tid->isfiltered == 1) {
+ tid->isfiltered = 0;
+ do_resume = 1;
+ }
+
/* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */
ath_tx_set_clrdmask(sc, tid->an);
@@ -3373,16 +3405,21 @@ ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid)
ATH_TID_INSERT_HEAD(tid, bf, bf_list);
}
- ath_tx_tid_resume(sc, tid);
+ /* And only resume if we had paused before */
+ if (do_resume)
+ ath_tx_tid_resume(sc, tid);
}
/*
* Called when a single (aggregate or otherwise) frame is completed.
*
- * Returns 1 if the buffer could be added to the filtered list
- * (cloned or otherwise), 0 if the buffer couldn't be added to the
+ * Returns 0 if the buffer could be added to the filtered list
+ * (cloned or otherwise), 1 if the buffer couldn't be added to the
* filtered list (failed clone; expired retry) and the caller should
* free it and handle it like a failure (eg by sending a BAR.)
+ *
+ * since the buffer may be cloned, bf must be not touched after this
+ * if the return value is 0.
*/
static int
ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid,
@@ -3402,8 +3439,9 @@ ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid,
"%s: bf=%p, seqno=%d, exceeded retries\n",
__func__,
bf,
- bf->bf_state.bfs_seqno);
- return (0);
+ SEQNO(bf->bf_state.bfs_seqno));
+ retval = 1; /* error */
+ goto finish;
}
/*
@@ -3423,11 +3461,12 @@ ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid,
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
"%s: busy buffer couldn't be cloned (%p)!\n",
__func__, bf);
- retval = 1;
+ retval = 1; /* error */
} else {
ath_tx_tid_filt_comp_buf(sc, tid, nbf);
- retval = 0;
+ retval = 0; /* ok */
}
+finish:
ath_tx_tid_filt_comp_complete(sc, tid);
return (retval);
@@ -3452,10 +3491,11 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid,
if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
sc->sc_stats.ast_tx_swretrymax++;
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
- "%s: bf=%p, seqno=%d, exceeded retries\n",
+ "%s: tid=%d, bf=%p, seqno=%d, exceeded retries\n",
__func__,
+ tid->tid,
bf,
- bf->bf_state.bfs_seqno);
+ SEQNO(bf->bf_state.bfs_seqno));
TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
goto next;
}
@@ -3463,8 +3503,8 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid,
if (bf->bf_flags & ATH_BUF_BUSY) {
nbf = ath_tx_retry_clone(sc, tid->an, tid, bf);
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
- "%s: busy buffer cloned: %p -> %p",
- __func__, bf, nbf);
+ "%s: tid=%d, busy buffer cloned: %p -> %p, seqno=%d\n",
+ __func__, tid->tid, bf, nbf, SEQNO(bf->bf_state.bfs_seqno));
} else {
nbf = bf;
}
@@ -3475,8 +3515,8 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid,
*/
if (nbf == NULL) {
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
- "%s: buffer couldn't be cloned! (%p)\n",
- __func__, bf);
+ "%s: tid=%d, buffer couldn't be cloned! (%p) seqno=%d\n",
+ __func__, tid->tid, bf, SEQNO(bf->bf_state.bfs_seqno));
TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
} else {
ath_tx_tid_filt_comp_buf(sc, tid, nbf);
@@ -3717,7 +3757,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
txq = sc->sc_ac2q[tid->ac];
tap = ath_tx_get_tx_tid(an, tid->tid);
- DPRINTF(sc, ATH_DEBUG_SW_TX,
+ DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
"%s: %s: %6D: bf=%p: addbaw=%d, dobaw=%d, "
"seqno=%d, retry=%d\n",
__func__,
@@ -3729,7 +3769,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
bf->bf_state.bfs_dobaw,
SEQNO(bf->bf_state.bfs_seqno),
bf->bf_state.bfs_retries);
- DPRINTF(sc, ATH_DEBUG_SW_TX,
+ DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
"%s: %s: %6D: bf=%p: txq[%d] axq_depth=%d, axq_aggr_depth=%d\n",
__func__,
pfx,
@@ -3739,7 +3779,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
txq->axq_qnum,
txq->axq_depth,
txq->axq_aggr_depth);
- DPRINTF(sc, ATH_DEBUG_SW_TX,
+ DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
"%s: %s: %6D: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, "
"isfiltered=%d\n",
__func__,
@@ -3751,7 +3791,7 @@ ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
tid->hwq_depth,
tid->bar_wait,
tid->isfiltered);
- DPRINTF(sc, ATH_DEBUG_SW_TX,
+ DPRINTF(sc, ATH_DEBUG_SW_TX | ATH_DEBUG_RESET,
"%s: %s: %6D: tid %d: "
"sched=%d, paused=%d, "
"incomp=%d, baw_head=%d, "
@@ -3811,7 +3851,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
if (t == 0) {
ath_tx_tid_drain_print(sc, an, "norm", tid, bf);
- t = 1;
+// t = 1;
}
ATH_TID_REMOVE(tid, bf, bf_list);
@@ -3827,7 +3867,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
if (t == 0) {
ath_tx_tid_drain_print(sc, an, "filt", tid, bf);
- t = 1;
+// t = 1;
}
ATH_TID_FILT_REMOVE(tid, bf, bf_list);
@@ -4084,6 +4124,19 @@ ath_tx_normal_comp(struct ath_softc *sc, struct ath_buf *bf, int fail)
DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: hwq_depth < 0: %d\n",
__func__, atid->hwq_depth);
+ /* If the TID is being cleaned up, track things */
+ /* XXX refactor! */
+ if (atid->cleanup_inprogress) {
+ atid->incomp--;
+ if (atid->incomp == 0) {
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: TID %d: cleaned up! resume!\n",
+ __func__, tid);
+ atid->cleanup_inprogress = 0;
+ ath_tx_tid_resume(sc, atid);
+ }
+ }
+
/*
* If the queue is filtered, potentially mark it as complete
* and reschedule it as needed.
@@ -4131,6 +4184,16 @@ ath_tx_comp_cleanup_unaggr(struct ath_softc *sc, struct ath_buf *bf)
ATH_TX_LOCK(sc);
atid->incomp--;
+
+ /* XXX refactor! */
+ if (bf->bf_state.bfs_dobaw) {
+ ath_tx_update_baw(sc, an, atid, bf);
+ if (!bf->bf_state.bfs_addedbaw)
+ DPRINTF(sc, ATH_DEBUG_SW_TX,
+ "%s: wasn't added: seqno %d\n",
+ __func__, SEQNO(bf->bf_state.bfs_seqno));
+ }
+
if (atid->incomp == 0) {
DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
"%s: TID %d: cleaned up! resume!\n",
@@ -4143,14 +4206,72 @@ ath_tx_comp_cleanup_unaggr(struct ath_softc *sc, struct ath_buf *bf)
ath_tx_default_comp(sc, bf, 0);
}
+
+/*
+ * This as it currently stands is a bit dumb. Ideally we'd just
+ * fail the frame the normal way and have it permanently fail
+ * via the normal aggregate completion path.
+ */
+static void
+ath_tx_tid_cleanup_frame(struct ath_softc *sc, struct ath_node *an,
+ int tid, struct ath_buf *bf_head, ath_bufhead *bf_cq)
+{
+ struct ath_tid *atid = &an->an_tid[tid];
+ struct ath_buf *bf, *bf_next;
+
+ ATH_TX_LOCK_ASSERT(sc);
+
+ /*
+ * Remove this frame from the queue.
+ */
+ ATH_TID_REMOVE(atid, bf_head, bf_list);
+
+ /*
+ * Loop over all the frames in the aggregate.
+ */
+ bf = bf_head;
+ while (bf != NULL) {
+ bf_next = bf->bf_next; /* next aggregate frame, or NULL */
+
+ /*
+ * If it's been added to the BAW we need to kick
+ * it out of the BAW before we continue.
+ *
+ * XXX if it's an aggregate, assert that it's in the
+ * BAW - we shouldn't have it be in an aggregate
+ * otherwise!
+ */
+ if (bf->bf_state.bfs_addedbaw) {
+ ath_tx_update_baw(sc, an, atid, bf);
+ bf->bf_state.bfs_dobaw = 0;
+ }
+
+ /*
+ * Give it the default completion handler.
+ */
+ bf->bf_comp = ath_tx_normal_comp;
+ bf->bf_next = NULL;
+
+ /*
+ * Add it to the list to free.
+ */
+ TAILQ_INSERT_TAIL(bf_cq, bf, bf_list);
+
+ /*
+ * Now advance to the next frame in the aggregate.
+ */
+ bf = bf_next;
+ }
+}
+
/*
* Performs transmit side cleanup when TID changes from aggregated to
- * unaggregated.
+ * unaggregated and during reassociation.
*
- * - Discard all retry frames from the s/w queue.
- * - Fix the tx completion function for all buffers in s/w queue.
- * - Count the number of unacked frames, and let transmit completion
- * handle it later.
+ * For now, this just tosses everything from the TID software queue
+ * whether or not it has been retried and marks the TID as
+ * pending completion if there's anything for this TID queued to
+ * the hardware.
*
* The caller is responsible for pausing the TID and unpausing the
* TID if no cleanup was required. Otherwise the cleanup path will
@@ -4161,18 +4282,19 @@ ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an, int tid,
ath_bufhead *bf_cq)
{
struct ath_tid *atid = &an->an_tid[tid];
- struct ieee80211_tx_ampdu *tap;
struct ath_buf *bf, *bf_next;
ATH_TX_LOCK_ASSERT(sc);
DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
- "%s: TID %d: called\n", __func__, tid);
+ "%s: TID %d: called; inprogress=%d\n", __func__, tid,
+ atid->cleanup_inprogress);
/*
* Move the filtered frames to the TX queue, before
* we run off and discard/process things.
*/
+
/* XXX this is really quite inefficient */
while ((bf = ATH_TID_FILT_LAST(atid, ath_bufhead_s)) != NULL) {
ATH_TID_FILT_REMOVE(atid, bf, bf_list);
@@ -4187,47 +4309,35 @@ ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an, int tid,
*/
bf = ATH_TID_FIRST(atid);
while (bf) {
- if (bf->bf_state.bfs_isretried) {
- bf_next = TAILQ_NEXT(bf, bf_list);
- ATH_TID_REMOVE(atid, bf, bf_list);
- if (bf->bf_state.bfs_dobaw) {
- ath_tx_update_baw(sc, an, atid, bf);
- if (!bf->bf_state.bfs_addedbaw)
- DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
- "%s: wasn't added: seqno %d\n",
- __func__,
- SEQNO(bf->bf_state.bfs_seqno));
- }
- bf->bf_state.bfs_dobaw = 0;
- /*
- * Call the default completion handler with "fail" just
- * so upper levels are suitably notified about this.
- */
- TAILQ_INSERT_TAIL(bf_cq, bf, bf_list);
- bf = bf_next;
- continue;
- }
- /* Give these the default completion handler */
- bf->bf_comp = ath_tx_normal_comp;
- bf = TAILQ_NEXT(bf, bf_list);
+ /*
+ * Grab the next frame in the list, we may
+ * be fiddling with the list.
+ */
+ bf_next = TAILQ_NEXT(bf, bf_list);
+
+ /*
+ * Free the frame and all subframes.
+ */
+ ath_tx_tid_cleanup_frame(sc, an, tid, bf, bf_cq);
+
+ /*
+ * Next frame!
+ */
+ bf = bf_next;
}
/*
- * Calculate what hardware-queued frames exist based
- * on the current BAW size. Ie, what frames have been
- * added to the TX hardware queue for this TID but
- * not yet ACKed.
+ * If there's anything in the hardware queue we wait
+ * for the TID HWQ to empty.
*/
- tap = ath_tx_get_tx_tid(an, tid);
- /* Need the lock - fiddling with BAW */
- while (atid->baw_head != atid->baw_tail) {
- if (atid->tx_buf[atid->baw_head]) {
- atid->incomp++;
- atid->cleanup_inprogress = 1;
- atid->tx_buf[atid->baw_head] = NULL;
- }
- INCR(atid->baw_head, ATH_TID_MAX_BUFS);
- INCR(tap->txa_start, IEEE80211_SEQ_RANGE);
+ if (atid->hwq_depth > 0) {
+ /*
+ * XXX how about we kill atid->incomp, and instead
+ * replace it with a macro that checks that atid->hwq_depth
+ * is 0?
+ */
+ atid->incomp = atid->hwq_depth;
+ atid->cleanup_inprogress = 1;
}
if (atid->cleanup_inprogress)
@@ -4560,9 +4670,19 @@ ath_tx_comp_cleanup_aggr(struct ath_softc *sc, struct ath_buf *bf_first)
ATH_TX_LOCK(sc);
/* update incomp */
+ atid->incomp--;
+
+ /* Update the BAW */
bf = bf_first;
while (bf) {
- atid->incomp--;
+ /* XXX refactor! */
+ if (bf->bf_state.bfs_dobaw) {
+ ath_tx_update_baw(sc, an, atid, bf);
+ if (!bf->bf_state.bfs_addedbaw)
+ DPRINTF(sc, ATH_DEBUG_SW_TX,
+ "%s: wasn't added: seqno %d\n",
+ __func__, SEQNO(bf->bf_state.bfs_seqno));
+ }
bf = bf->bf_next;
}
@@ -4585,10 +4705,11 @@ ath_tx_comp_cleanup_aggr(struct ath_softc *sc, struct ath_buf *bf_first)
ATH_TX_UNLOCK(sc);
- /* Handle frame completion */
+ /* Handle frame completion as individual frames */
bf = bf_first;
while (bf) {
bf_next = bf->bf_next;
+ bf->bf_next = NULL;
ath_tx_default_comp(sc, bf, 1);
bf = bf_next;
}
@@ -5030,6 +5151,10 @@ ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail)
"%s: isfiltered=1, fail=%d\n",
__func__, fail);
freeframe = ath_tx_tid_filt_comp_single(sc, atid, bf);
+ /*
+ * If freeframe=0 then bf is no longer ours; don't
+ * touch it.
+ */
if (freeframe) {
/* Remove from BAW */
if (bf->bf_state.bfs_addedbaw)
@@ -5065,7 +5190,6 @@ ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail)
if (freeframe)
ath_tx_default_comp(sc, bf, fail);
-
return;
}
/*
@@ -5495,7 +5619,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)) {
- continue;
+ goto loop_done;
}
if (ath_tx_ampdu_running(sc, tid->an, tid->tid))
ath_tx_tid_hw_queue_aggr(sc, tid->an, tid);
@@ -5518,7 +5642,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
@@ -5771,12 +5895,26 @@ ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
*/
TAILQ_INIT(&bf_cq);
ATH_TX_LOCK(sc);
- ath_tx_tid_cleanup(sc, an, tid, &bf_cq);
+
/*
- * Unpause the TID if no cleanup is required.
+ * In case there's a followup call to this, only call it
+ * if we don't have a cleanup in progress.
+ *
+ * Since we've paused the queue above, we need to make
+ * sure we unpause if there's already a cleanup in
+ * progress - it means something else is also doing
+ * this stuff, so we don't need to also keep it paused.
*/
- if (! atid->cleanup_inprogress)
+ if (atid->cleanup_inprogress) {
ath_tx_tid_resume(sc, atid);
+ } else {
+ ath_tx_tid_cleanup(sc, an, tid, &bf_cq);
+ /*
+ * Unpause the TID if no cleanup is required.
+ */
+ if (! atid->cleanup_inprogress)
+ ath_tx_tid_resume(sc, atid);
+ }
ATH_TX_UNLOCK(sc);
/* Handle completing frames and fail them */
@@ -5810,19 +5948,25 @@ ath_tx_node_reassoc(struct ath_softc *sc, struct ath_node *an)
tid = &an->an_tid[i];
if (tid->hwq_depth == 0)
continue;
- ath_tx_tid_pause(sc, tid);
DPRINTF(sc, ATH_DEBUG_NODE,
"%s: %6D: TID %d: cleaning up TID\n",
__func__,
an->an_node.ni_macaddr,
":",
i);
- ath_tx_tid_cleanup(sc, an, i, &bf_cq);
/*
- * Unpause the TID if no cleanup is required.
+ * In case there's a followup call to this, only call it
+ * if we don't have a cleanup in progress.
*/
- if (! tid->cleanup_inprogress)
- ath_tx_tid_resume(sc, tid);
+ if (! tid->cleanup_inprogress) {
+ ath_tx_tid_pause(sc, tid);
+ ath_tx_tid_cleanup(sc, an, i, &bf_cq);
+ /*
+ * Unpause the TID if no cleanup is required.
+ */
+ if (! tid->cleanup_inprogress)
+ ath_tx_tid_resume(sc, tid);
+ }
}
ATH_TX_UNLOCK(sc);
@@ -5852,19 +5996,43 @@ ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
int attempts = tap->txa_attempts;
+ int old_txa_start;
DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,
- "%s: %6D: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d\n",
+ "%s: %6D: called; txa_tid=%d, atid->tid=%d, status=%d, attempts=%d, txa_start=%d, txa_seqpending=%d\n",
__func__,
ni->ni_macaddr,
":",
tap->txa_tid,
atid->tid,
status,
- attempts);
+ attempts,
+ tap->txa_start,
+ tap->txa_seqpending);
/* Note: This may update the BAW details */
+ /*
+ * XXX What if this does slide the BAW along? We need to somehow
+ * XXX either fix things when it does happen, or prevent the
+ * XXX seqpending value to be anything other than exactly what
+ * XXX the hell we want!
+ *
+ * XXX So for now, how I do this inside the TX lock for now
+ * 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);
+ }
+ tap->txa_start = old_txa_start;
+ ATH_TX_UNLOCK(sc);
/* Unpause the TID */
/*
diff --git a/sys/dev/ath/if_ath_tx.h b/sys/dev/ath/if_ath_tx.h
index 281dbcb..490f955 100644
--- a/sys/dev/ath/if_ath_tx.h
+++ b/sys/dev/ath/if_ath_tx.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_tx.h 250866 2013-05-21 18:13:57Z adrian $
*/
#ifndef __IF_ATH_TX_H__
#define __IF_ATH_TX_H__
diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c
index 5498dd5..0b507f7 100644
--- a/sys/dev/ath/if_ath_tx_edma.c
+++ b/sys/dev/ath/if_ath_tx_edma.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_edma.c 265349 2014-05-05 08:00:50Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -865,12 +866,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;
diff --git a/sys/dev/ath/if_ath_tx_edma.h b/sys/dev/ath/if_ath_tx_edma.h
index d4975a6..f2e0aed 100644
--- a/sys/dev/ath/if_ath_tx_edma.h
+++ b/sys/dev/ath/if_ath_tx_edma.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_tx_edma.h 238710 2012-07-23 03:52:18Z adrian $
*/
#ifndef __IF_ATH_TX_EDMA_H__
#define __IF_ATH_TX_EDMA_H__
diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
index 36c3dff..8b13496 100644
--- a/sys/dev/ath/if_ath_tx_ht.c
+++ b/sys/dev/ath/if_ath_tx_ht.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_ht.c 250665 2013-05-15 18:33:05Z adrian $");
#include "opt_inet.h"
#include "opt_ath.h"
diff --git a/sys/dev/ath/if_ath_tx_ht.h b/sys/dev/ath/if_ath_tx_ht.h
index 38885ef..6af7848 100644
--- a/sys/dev/ath/if_ath_tx_ht.h
+++ b/sys/dev/ath/if_ath_tx_ht.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_ath_tx_ht.h 250665 2013-05-15 18:33:05Z adrian $
*/
#ifndef __IF_ATH_TX_HT_H__
#define __IF_ATH_TX_HT_H__
diff --git a/sys/dev/ath/if_athdfs.h b/sys/dev/ath/if_athdfs.h
index cc4db15..1dd7174 100644
--- a/sys/dev/ath/if_athdfs.h
+++ b/sys/dev/ath/if_athdfs.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_athdfs.h 244946 2013-01-02 01:36:10Z adrian $
*/
#ifndef __IF_ATHDFS_H__
#define __IF_ATHDFS_H__
diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h
index e9ce887..818838a 100644
--- a/sys/dev/ath/if_athioctl.h
+++ b/sys/dev/ath/if_athioctl.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_athioctl.h 250665 2013-05-15 18:33:05Z adrian $
*/
/*
diff --git a/sys/dev/ath/if_athrate.h b/sys/dev/ath/if_athrate.h
index a97d686..0fec625 100644
--- a/sys/dev/ath/if_athrate.h
+++ b/sys/dev/ath/if_athrate.h
@@ -27,7 +27,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_athrate.h 249578 2013-04-17 07:21:30Z adrian $
*/
#ifndef _ATH_RATECTRL_H_
#define _ATH_RATECTRL_H_
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 6b074d6..3824948 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -26,7 +26,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/ath/if_athvar.h 272292 2014-09-30 03:19:29Z adrian $
*/
/*
@@ -82,6 +82,25 @@
#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.
* We also setup a mapping table between key cache slot indices
@@ -510,6 +529,7 @@ struct ath_rx_edma {
int m_fifo_tail;
int m_fifo_depth;
struct mbuf *m_rxpending;
+ struct ath_buf *m_holdbf;
};
struct ath_tx_edma_fifo {
@@ -565,6 +585,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 *);
@@ -621,7 +643,8 @@ struct ath_softc {
sc_resetcal : 1,/* reset cal state next trip */
sc_rxslink : 1,/* do self-linked final descriptor */
sc_rxtsf32 : 1,/* RX dec TSF is 32 bits */
- sc_isedma : 1;/* supports EDMA */
+ sc_isedma : 1,/* supports EDMA */
+ sc_do_mybeacon : 1; /* supports mybeacon */
/*
* Second set of flags.
@@ -864,6 +887,25 @@ struct ath_softc {
void (*sc_bar_response)(struct ieee80211_node *ni,
struct ieee80211_tx_ampdu *tap,
int status);
+
+ /*
+ * Powersave state tracking.
+ *
+ * target/cur powerstate is the chip power state.
+ * target selfgen state is the self-generated frames
+ * state. The chip can be awake but transmitted frames
+ * can have the PWRMGT bit set to 1 so the destination
+ * thinks the node is asleep.
+ */
+ HAL_POWER_MODE sc_target_powerstate;
+ HAL_POWER_MODE sc_target_selfgen_state;
+
+ HAL_POWER_MODE sc_cur_powerstate;
+
+ int sc_powersave_refcnt;
+
+ /* ATH_PCI_* flags */
+ uint32_t sc_pci_devinfo;
};
#define ATH_LOCK_INIT(_sc) \
@@ -1038,6 +1080,8 @@ void ath_intr(void *);
((*(_ah)->ah_updateTxTrigLevel)((_ah), (_inc)))
#define ath_hal_setpower(_ah, _mode) \
((*(_ah)->ah_setPowerMode)((_ah), (_mode), AH_TRUE))
+#define ath_hal_setselfgenpower(_ah, _mode) \
+ ((*(_ah)->ah_setPowerMode)((_ah), (_mode), AH_FALSE))
#define ath_hal_keycachesize(_ah) \
((*(_ah)->ah_getKeyCacheSize)((_ah)))
#define ath_hal_keyreset(_ah, _ix) \
@@ -1266,6 +1310,8 @@ void ath_intr(void *);
#define ath_hal_setintmit(_ah, _v) \
ath_hal_setcapability(_ah, HAL_CAP_INTMIT, \
HAL_CAP_INTMIT_ENABLE, _v, NULL)
+#define ath_hal_hasmybeacon(_ah) \
+ (ath_hal_getcapability(_ah, HAL_CAP_DO_MYBEACON, 1, NULL) == HAL_OK)
#define ath_hal_hasenforcetxop(_ah) \
(ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 0, NULL) == HAL_OK)
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 609a703..226fe46 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -1,11 +1,10 @@
/*-
- * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
- * Copyright (c) 2011 Intel Corporation
- * Copyright (c) 2007-2009
- * Damien Bergamini <damien.bergamini@free.fr>
- * Copyright (c) 2008
- * Benjamin Close <benjsc@FreeBSD.org>
+ * Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008 Benjamin Close <benjsc@FreeBSD.org>
* Copyright (c) 2008 Sam Leffler, Errno Consulting
+ * Copyright (c) 2011 Intel Corporation
+ * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
+ * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -57,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
@@ -77,6 +77,9 @@ __FBSDID("$FreeBSD$");
#include <dev/iwn/if_iwnreg.h>
#include <dev/iwn/if_iwnvar.h>
#include <dev/iwn/if_iwn_devid.h>
+#include <dev/iwn/if_iwn_chip_cfg.h>
+#include <dev/iwn/if_iwn_debug.h>
+#include <dev/iwn/if_iwn_ioctl.h>
struct iwn_ident {
uint16_t vendor;
@@ -97,12 +100,19 @@ static const struct iwn_ident iwn_ident_table[] = {
{ 0x8086, IWN_DID_x030_4, "Intel Centrino Advanced-N 6230" },
{ 0x8086, IWN_DID_6150_1, "Intel Centrino Wireless-N + WiMAX 6150" },
{ 0x8086, IWN_DID_6150_2, "Intel Centrino Wireless-N + WiMAX 6150" },
+ { 0x8086, IWN_DID_2x00_1, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
+ { 0x8086, IWN_DID_2x00_2, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
+ /* XXX 2200D is IWN_SDID_2x00_4; there's no way to express this here! */
{ 0x8086, IWN_DID_2x30_1, "Intel Centrino Wireless-N 2230" },
{ 0x8086, IWN_DID_2x30_2, "Intel Centrino Wireless-N 2230" },
{ 0x8086, IWN_DID_130_1, "Intel Centrino Wireless-N 130" },
{ 0x8086, IWN_DID_130_2, "Intel Centrino Wireless-N 130" },
{ 0x8086, IWN_DID_100_1, "Intel Centrino Wireless-N 100" },
{ 0x8086, IWN_DID_100_2, "Intel Centrino Wireless-N 100" },
+ { 0x8086, IWN_DID_105_1, "Intel Centrino Wireless-N 105" },
+ { 0x8086, IWN_DID_105_2, "Intel Centrino Wireless-N 105" },
+ { 0x8086, IWN_DID_135_1, "Intel Centrino Wireless-N 135" },
+ { 0x8086, IWN_DID_135_2, "Intel Centrino Wireless-N 135" },
{ 0x8086, IWN_DID_4965_1, "Intel Wireless WiFi Link 4965" },
{ 0x8086, IWN_DID_6x00_1, "Intel Centrino Ultimate-N 6300" },
{ 0x8086, IWN_DID_6x00_2, "Intel Centrino Advanced-N 6200" },
@@ -119,6 +129,8 @@ static const struct iwn_ident iwn_ident_table[] = {
{ 0x8086, IWN_DID_5x50_2, "Intel WiMAX/WiFi Link 5350" },
{ 0x8086, IWN_DID_5x50_3, "Intel WiMAX/WiFi Link 5150" },
{ 0x8086, IWN_DID_5x50_4, "Intel WiMAX/WiFi Link 5150" },
+ { 0x8086, IWN_DID_6035_1, "Intel Centrino Advanced 6235" },
+ { 0x8086, IWN_DID_6035_2, "Intel Centrino Advanced 6235" },
{ 0, 0, NULL }
};
@@ -126,6 +138,7 @@ static int iwn_probe(device_t);
static int iwn_attach(device_t);
static int iwn4965_attach(struct iwn_softc *, uint16_t);
static int iwn5000_attach(struct iwn_softc *, uint16_t);
+static int iwn_config_specific(struct iwn_softc *, uint16_t);
static void iwn_radiotap_attach(struct iwn_softc *);
static void iwn_sysctlattach(struct iwn_softc *);
static struct ieee80211vap *iwn_vap_create(struct ieee80211com *,
@@ -200,7 +213,7 @@ static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
struct iwn_rx_data *);
static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int,
uint8_t);
-static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, void *);
+static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *);
static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *);
static void iwn_notif_intr(struct iwn_softc *);
static void iwn_wakeup_intr(struct iwn_softc *);
@@ -257,14 +270,17 @@ static int iwn4965_set_gains(struct iwn_softc *);
static int iwn5000_set_gains(struct iwn_softc *);
static void iwn_tune_sensitivity(struct iwn_softc *,
const struct iwn_rx_stats *);
+static void iwn_save_stats_counters(struct iwn_softc *,
+ const struct iwn_stats *);
static int iwn_send_sensitivity(struct iwn_softc *);
+static void iwn_check_rx_recovery(struct iwn_softc *, struct iwn_stats *);
static int iwn_set_pslevel(struct iwn_softc *, int, int, int);
static int iwn_send_btcoex(struct iwn_softc *);
static int iwn_send_advanced_btcoex(struct iwn_softc *);
static int iwn5000_runtime_calib(struct iwn_softc *);
static int iwn_config(struct iwn_softc *);
-static uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
-static int iwn_scan(struct iwn_softc *);
+static int iwn_scan(struct iwn_softc *, struct ieee80211vap *,
+ struct ieee80211_scan_state *, struct ieee80211_channel *);
static int iwn_auth(struct iwn_softc *, struct ieee80211vap *vap);
static int iwn_run(struct iwn_softc *, struct ieee80211vap *vap);
static int iwn_ampdu_rx_start(struct ieee80211_node *,
@@ -292,6 +308,7 @@ static int iwn5000_send_calibration(struct iwn_softc *);
static int iwn5000_send_wimax_coex(struct iwn_softc *);
static int iwn5000_crystal_calib(struct iwn_softc *);
static int iwn5000_temp_offset_calib(struct iwn_softc *);
+static int iwn5000_temp_offset_calibv2(struct iwn_softc *);
static int iwn4965_post_alive(struct iwn_softc *);
static int iwn5000_post_alive(struct iwn_softc *);
static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
@@ -316,6 +333,7 @@ static int iwn_hw_init(struct iwn_softc *);
static void iwn_hw_stop(struct iwn_softc *);
static void iwn_radio_on(void *, int);
static void iwn_radio_off(void *, int);
+static void iwn_panicked(void *, int);
static void iwn_init_locked(struct iwn_softc *);
static void iwn_init(void *);
static void iwn_stop_locked(struct iwn_softc *);
@@ -331,80 +349,6 @@ static char *iwn_get_csr_string(int);
static void iwn_debug_register(struct iwn_softc *);
#endif
-#ifdef IWN_DEBUG
-enum {
- IWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
- IWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
- IWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
- IWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
- IWN_DEBUG_RESET = 0x00000010, /* reset processing */
- IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */
- IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
- IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
- IWN_DEBUG_INTR = 0x00000100, /* ISR */
- IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
- IWN_DEBUG_NODE = 0x00000400, /* node management */
- IWN_DEBUG_LED = 0x00000800, /* led management */
- IWN_DEBUG_CMD = 0x00001000, /* cmd submission */
- IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
- IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
- IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */
- IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
- IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
- IWN_DEBUG_ANY = 0xffffffff
-};
-
-#define DPRINTF(sc, m, fmt, ...) do { \
- if (sc->sc_debug & (m)) \
- printf(fmt, __VA_ARGS__); \
-} while (0)
-
-static const char *
-iwn_intr_str(uint8_t cmd)
-{
- switch (cmd) {
- /* Notifications */
- case IWN_UC_READY: return "UC_READY";
- case IWN_ADD_NODE_DONE: return "ADD_NODE_DONE";
- case IWN_TX_DONE: return "TX_DONE";
- case IWN_START_SCAN: return "START_SCAN";
- case IWN_STOP_SCAN: return "STOP_SCAN";
- case IWN_RX_STATISTICS: return "RX_STATS";
- case IWN_BEACON_STATISTICS: return "BEACON_STATS";
- case IWN_STATE_CHANGED: return "STATE_CHANGED";
- case IWN_BEACON_MISSED: return "BEACON_MISSED";
- case IWN_RX_PHY: return "RX_PHY";
- case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE";
- case IWN_RX_DONE: return "RX_DONE";
-
- /* Command Notifications */
- case IWN_CMD_RXON: return "IWN_CMD_RXON";
- case IWN_CMD_RXON_ASSOC: return "IWN_CMD_RXON_ASSOC";
- case IWN_CMD_EDCA_PARAMS: return "IWN_CMD_EDCA_PARAMS";
- case IWN_CMD_TIMING: return "IWN_CMD_TIMING";
- case IWN_CMD_LINK_QUALITY: return "IWN_CMD_LINK_QUALITY";
- case IWN_CMD_SET_LED: return "IWN_CMD_SET_LED";
- case IWN5000_CMD_WIMAX_COEX: return "IWN5000_CMD_WIMAX_COEX";
- case IWN5000_CMD_CALIB_CONFIG: return "IWN5000_CMD_CALIB_CONFIG";
- case IWN5000_CMD_CALIB_RESULT: return "IWN5000_CMD_CALIB_RESULT";
- case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE";
- case IWN_CMD_SET_POWER_MODE: return "IWN_CMD_SET_POWER_MODE";
- case IWN_CMD_SCAN: return "IWN_CMD_SCAN";
- case IWN_CMD_SCAN_RESULTS: return "IWN_CMD_SCAN_RESULTS";
- case IWN_CMD_TXPOWER: return "IWN_CMD_TXPOWER";
- case IWN_CMD_TXPOWER_DBM: return "IWN_CMD_TXPOWER_DBM";
- case IWN5000_CMD_TX_ANT_CONFIG: return "IWN5000_CMD_TX_ANT_CONFIG";
- case IWN_CMD_BT_COEX: return "IWN_CMD_BT_COEX";
- case IWN_CMD_SET_CRITICAL_TEMP: return "IWN_CMD_SET_CRITICAL_TEMP";
- case IWN_CMD_SET_SENSITIVITY: return "IWN_CMD_SET_SENSITIVITY";
- case IWN_CMD_PHY_CALIB: return "IWN_CMD_PHY_CALIB";
- }
- return "UNKNOWN INTR NOTIF/CMD";
-}
-#else
-#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
-#endif
-
static device_method_t iwn_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, iwn_probe),
@@ -448,6 +392,15 @@ iwn_probe(device_t dev)
}
static int
+iwn_is_3stream_device(struct iwn_softc *sc)
+{
+ /* XXX for now only 5300, until the 5350 can be tested */
+ if (sc->hw_type == IWN_HW_REV_TYPE_5300)
+ return (1);
+ return (0);
+}
+
+static int
iwn_attach(device_t dev)
{
struct iwn_softc *sc = (struct iwn_softc *)device_get_softc(dev);
@@ -515,6 +468,11 @@ iwn_attach(device_t dev)
sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
& IWN_HW_REV_TYPE_MASK;
sc->subdevice_id = pci_get_subdevice(dev);
+
+ /*
+ * 4965 versus 5000 and later have different methods.
+ * Let's set those up first.
+ */
if (sc->hw_type == IWN_HW_REV_TYPE_4965)
error = iwn4965_attach(sc, pci_get_device(dev));
else
@@ -525,6 +483,16 @@ iwn_attach(device_t dev)
goto fail;
}
+ /*
+ * Next, let's setup the various parameters of each NIC.
+ */
+ error = iwn_config_specific(sc, pci_get_device(dev));
+ if (error != 0) {
+ device_printf(dev, "could not attach device, error %d\n",
+ error);
+ goto fail;
+ }
+
if ((error = iwn_hw_prepare(sc)) != 0) {
device_printf(dev, "hardware not ready, error %d\n", error);
goto fail;
@@ -634,17 +602,16 @@ iwn_attach(device_t dev)
ic->ic_txstream = sc->ntxchains;
/*
- * The NICs we currently support cap out at 2x2 support
- * separate from the chains being used.
- *
- * This is a total hack to work around that until some
- * per-device method is implemented to return the
- * actual stream support.
+ * Some of the 3 antenna devices (ie, the 4965) only supports
+ * 2x2 operation. So correct the number of streams if
+ * it's not a 3-stream device.
*/
- if (ic->ic_rxstream > 2)
- ic->ic_rxstream = 2;
- if (ic->ic_txstream > 2)
- ic->ic_txstream = 2;
+ if (! iwn_is_3stream_device(sc)) {
+ if (ic->ic_rxstream > 2)
+ ic->ic_rxstream = 2;
+ if (ic->ic_txstream > 2)
+ ic->ic_txstream = 2;
+ }
ic->ic_htcaps =
IEEE80211_HTCAP_SMPS_OFF /* SMPS mode disabled */
@@ -710,6 +677,15 @@ iwn_attach(device_t dev)
TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc);
TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc);
TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc);
+ TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc);
+
+ sc->sc_tq = taskqueue_create("iwn_taskq", M_WAITOK,
+ taskqueue_thread_enqueue, &sc->sc_tq);
+ error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwn_taskq");
+ if (error != 0) {
+ device_printf(dev, "can't start threads, error %d\n", error);
+ goto fail;
+ }
iwn_sysctlattach(sc);
@@ -724,6 +700,13 @@ iwn_attach(device_t dev)
goto fail;
}
+#if 0
+ device_printf(sc->sc_dev, "%s: rx_stats=%d, rx_stats_bt=%d\n",
+ __func__,
+ sizeof(struct iwn_stats),
+ sizeof(struct iwn_stats_bt));
+#endif
+
if (bootverbose)
ieee80211_announce(ic);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@@ -734,6 +717,488 @@ fail:
return error;
}
+/*
+ * Define specific configuration based on device id and subdevice id
+ * pid : PCI device id
+ */
+static int
+iwn_config_specific(struct iwn_softc *sc, uint16_t pid)
+{
+
+ switch (pid) {
+/* 4965 series */
+ case IWN_DID_4965_1:
+ case IWN_DID_4965_2:
+ case IWN_DID_4965_3:
+ case IWN_DID_4965_4:
+ sc->base_params = &iwn4965_base_params;
+ sc->limits = &iwn4965_sensitivity_limits;
+ sc->fwname = "iwn4965fw";
+ /* Override chains masks, ROM is known to be broken. */
+ sc->txchainmask = IWN_ANT_AB;
+ sc->rxchainmask = IWN_ANT_ABC;
+ /* Enable normal btcoex */
+ sc->sc_flags |= IWN_FLAG_BTCOEX;
+ break;
+/* 1000 Series */
+ case IWN_DID_1000_1:
+ case IWN_DID_1000_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_1000_1:
+ case IWN_SDID_1000_2:
+ case IWN_SDID_1000_3:
+ case IWN_SDID_1000_4:
+ case IWN_SDID_1000_5:
+ case IWN_SDID_1000_6:
+ case IWN_SDID_1000_7:
+ case IWN_SDID_1000_8:
+ case IWN_SDID_1000_9:
+ case IWN_SDID_1000_10:
+ case IWN_SDID_1000_11:
+ case IWN_SDID_1000_12:
+ sc->limits = &iwn1000_sensitivity_limits;
+ sc->base_params = &iwn1000_base_params;
+ sc->fwname = "iwn1000fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x00 Series */
+ case IWN_DID_6x00_2:
+ case IWN_DID_6x00_4:
+ case IWN_DID_6x00_1:
+ case IWN_DID_6x00_3:
+ sc->fwname = "iwn6000fw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6x00_1:
+ case IWN_SDID_6x00_2:
+ case IWN_SDID_6x00_8:
+ //iwl6000_3agn_cfg
+ sc->base_params = &iwn_6000_base_params;
+ break;
+ case IWN_SDID_6x00_3:
+ case IWN_SDID_6x00_6:
+ case IWN_SDID_6x00_9:
+ ////iwl6000i_2agn
+ case IWN_SDID_6x00_4:
+ case IWN_SDID_6x00_7:
+ case IWN_SDID_6x00_10:
+ //iwl6000i_2abg_cfg
+ case IWN_SDID_6x00_5:
+ //iwl6000i_2bg_cfg
+ sc->base_params = &iwn_6000i_base_params;
+ sc->sc_flags |= IWN_FLAG_INTERNAL_PA;
+ sc->txchainmask = IWN_ANT_BC;
+ sc->rxchainmask = IWN_ANT_BC;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x05 Series */
+ case IWN_DID_6x05_1:
+ case IWN_DID_6x05_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6x05_1:
+ case IWN_SDID_6x05_4:
+ case IWN_SDID_6x05_6:
+ //iwl6005_2agn_cfg
+ case IWN_SDID_6x05_2:
+ case IWN_SDID_6x05_5:
+ case IWN_SDID_6x05_7:
+ //iwl6005_2abg_cfg
+ case IWN_SDID_6x05_3:
+ //iwl6005_2bg_cfg
+ case IWN_SDID_6x05_8:
+ case IWN_SDID_6x05_9:
+ //iwl6005_2agn_sff_cfg
+ case IWN_SDID_6x05_10:
+ //iwl6005_2agn_d_cfg
+ case IWN_SDID_6x05_11:
+ //iwl6005_2agn_mow1_cfg
+ case IWN_SDID_6x05_12:
+ //iwl6005_2agn_mow2_cfg
+ sc->fwname = "iwn6000g2afw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x35 Series */
+ case IWN_DID_6035_1:
+ case IWN_DID_6035_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6035_1:
+ case IWN_SDID_6035_2:
+ case IWN_SDID_6035_3:
+ case IWN_SDID_6035_4:
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6235_sensitivity_limits;
+ sc->base_params = &iwn_6235_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6x50 WiFi/WiMax Series */
+ case IWN_DID_6050_1:
+ case IWN_DID_6050_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6050_1:
+ case IWN_SDID_6050_3:
+ case IWN_SDID_6050_5:
+ //iwl6050_2agn_cfg
+ case IWN_SDID_6050_2:
+ case IWN_SDID_6050_4:
+ case IWN_SDID_6050_6:
+ //iwl6050_2abg_cfg
+ sc->fwname = "iwn6050fw";
+ sc->txchainmask = IWN_ANT_AB;
+ sc->rxchainmask = IWN_ANT_AB;
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6050_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6150 WiFi/WiMax Series */
+ case IWN_DID_6150_1:
+ case IWN_DID_6150_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_6150_1:
+ case IWN_SDID_6150_3:
+ case IWN_SDID_6150_5:
+ // iwl6150_bgn_cfg
+ case IWN_SDID_6150_2:
+ case IWN_SDID_6150_4:
+ case IWN_SDID_6150_6:
+ //iwl6150_bg_cfg
+ sc->fwname = "iwn6050fw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6150_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 6030 Series and 1030 Series */
+ case IWN_DID_x030_1:
+ case IWN_DID_x030_2:
+ case IWN_DID_x030_3:
+ case IWN_DID_x030_4:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_x030_1:
+ case IWN_SDID_x030_3:
+ case IWN_SDID_x030_5:
+ // iwl1030_bgn_cfg
+ case IWN_SDID_x030_2:
+ case IWN_SDID_x030_4:
+ case IWN_SDID_x030_6:
+ //iwl1030_bg_cfg
+ case IWN_SDID_x030_7:
+ case IWN_SDID_x030_10:
+ case IWN_SDID_x030_14:
+ //iwl6030_2agn_cfg
+ case IWN_SDID_x030_8:
+ case IWN_SDID_x030_11:
+ case IWN_SDID_x030_15:
+ // iwl6030_2bgn_cfg
+ case IWN_SDID_x030_9:
+ case IWN_SDID_x030_12:
+ case IWN_SDID_x030_16:
+ // iwl6030_2abg_cfg
+ case IWN_SDID_x030_13:
+ //iwl6030_2bg_cfg
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2b_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 130 Series WiFi */
+/* XXX: This series will need adjustment for rate.
+ * see rx_with_siso_diversity in linux kernel
+ */
+ case IWN_DID_130_1:
+ case IWN_DID_130_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_130_1:
+ case IWN_SDID_130_3:
+ case IWN_SDID_130_5:
+ //iwl130_bgn_cfg
+ case IWN_SDID_130_2:
+ case IWN_SDID_130_4:
+ case IWN_SDID_130_6:
+ //iwl130_bg_cfg
+ sc->fwname = "iwn6000g2bfw";
+ sc->limits = &iwn6000_sensitivity_limits;
+ sc->base_params = &iwn_6000g2b_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 100 Series WiFi */
+ case IWN_DID_100_1:
+ case IWN_DID_100_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_100_1:
+ case IWN_SDID_100_2:
+ case IWN_SDID_100_3:
+ case IWN_SDID_100_4:
+ case IWN_SDID_100_5:
+ case IWN_SDID_100_6:
+ sc->limits = &iwn1000_sensitivity_limits;
+ sc->base_params = &iwn1000_base_params;
+ sc->fwname = "iwn100fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+
+/* 105 Series */
+/* XXX: This series will need adjustment for rate.
+ * see rx_with_siso_diversity in linux kernel
+ */
+ case IWN_DID_105_1:
+ case IWN_DID_105_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_105_1:
+ case IWN_SDID_105_2:
+ case IWN_SDID_105_3:
+ //iwl105_bgn_cfg
+ case IWN_SDID_105_4:
+ //iwl105_bgn_d_cfg
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2000_base_params;
+ sc->fwname = "iwn105fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+
+/* 135 Series */
+/* XXX: This series will need adjustment for rate.
+ * see rx_with_siso_diversity in linux kernel
+ */
+ case IWN_DID_135_1:
+ case IWN_DID_135_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_135_1:
+ case IWN_SDID_135_2:
+ case IWN_SDID_135_3:
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2030_base_params;
+ sc->fwname = "iwn135fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+
+/* 2x00 Series */
+ case IWN_DID_2x00_1:
+ case IWN_DID_2x00_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_2x00_1:
+ case IWN_SDID_2x00_2:
+ case IWN_SDID_2x00_3:
+ //iwl2000_2bgn_cfg
+ case IWN_SDID_2x00_4:
+ //iwl2000_2bgn_d_cfg
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2000_base_params;
+ sc->fwname = "iwn2000fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice) \n",
+ pid, sc->subdevice_id, sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 2x30 Series */
+ case IWN_DID_2x30_1:
+ case IWN_DID_2x30_2:
+ switch(sc->subdevice_id) {
+ case IWN_SDID_2x30_1:
+ case IWN_SDID_2x30_3:
+ case IWN_SDID_2x30_5:
+ //iwl100_bgn_cfg
+ case IWN_SDID_2x30_2:
+ case IWN_SDID_2x30_4:
+ case IWN_SDID_2x30_6:
+ //iwl100_bg_cfg
+ sc->limits = &iwn2030_sensitivity_limits;
+ sc->base_params = &iwn2030_base_params;
+ sc->fwname = "iwn2030fw";
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 5x00 Series */
+ case IWN_DID_5x00_1:
+ case IWN_DID_5x00_2:
+ case IWN_DID_5x00_3:
+ case IWN_DID_5x00_4:
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn5000_base_params;
+ sc->fwname = "iwn5000fw";
+ switch(sc->subdevice_id) {
+ case IWN_SDID_5x00_1:
+ case IWN_SDID_5x00_2:
+ case IWN_SDID_5x00_3:
+ case IWN_SDID_5x00_4:
+ case IWN_SDID_5x00_9:
+ case IWN_SDID_5x00_10:
+ case IWN_SDID_5x00_11:
+ case IWN_SDID_5x00_12:
+ case IWN_SDID_5x00_17:
+ case IWN_SDID_5x00_18:
+ case IWN_SDID_5x00_19:
+ case IWN_SDID_5x00_20:
+ //iwl5100_agn_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+ case IWN_SDID_5x00_5:
+ case IWN_SDID_5x00_6:
+ case IWN_SDID_5x00_13:
+ case IWN_SDID_5x00_14:
+ case IWN_SDID_5x00_21:
+ case IWN_SDID_5x00_22:
+ //iwl5100_bgn_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+ case IWN_SDID_5x00_7:
+ case IWN_SDID_5x00_8:
+ case IWN_SDID_5x00_15:
+ case IWN_SDID_5x00_16:
+ case IWN_SDID_5x00_23:
+ case IWN_SDID_5x00_24:
+ //iwl5100_abg_cfg
+ sc->txchainmask = IWN_ANT_B;
+ sc->rxchainmask = IWN_ANT_AB;
+ break;
+ case IWN_SDID_5x00_25:
+ case IWN_SDID_5x00_26:
+ case IWN_SDID_5x00_27:
+ case IWN_SDID_5x00_28:
+ case IWN_SDID_5x00_29:
+ case IWN_SDID_5x00_30:
+ case IWN_SDID_5x00_31:
+ case IWN_SDID_5x00_32:
+ case IWN_SDID_5x00_33:
+ case IWN_SDID_5x00_34:
+ case IWN_SDID_5x00_35:
+ case IWN_SDID_5x00_36:
+ //iwl5300_agn_cfg
+ sc->txchainmask = IWN_ANT_ABC;
+ sc->rxchainmask = IWN_ANT_ABC;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+/* 5x50 Series */
+ case IWN_DID_5x50_1:
+ case IWN_DID_5x50_2:
+ case IWN_DID_5x50_3:
+ case IWN_DID_5x50_4:
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn5000_base_params;
+ sc->fwname = "iwn5000fw";
+ switch(sc->subdevice_id) {
+ case IWN_SDID_5x50_1:
+ case IWN_SDID_5x50_2:
+ case IWN_SDID_5x50_3:
+ //iwl5350_agn_cfg
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->base_params = &iwn5000_base_params;
+ sc->fwname = "iwn5000fw";
+ break;
+ case IWN_SDID_5x50_4:
+ case IWN_SDID_5x50_5:
+ case IWN_SDID_5x50_8:
+ case IWN_SDID_5x50_9:
+ case IWN_SDID_5x50_10:
+ case IWN_SDID_5x50_11:
+ //iwl5150_agn_cfg
+ case IWN_SDID_5x50_6:
+ case IWN_SDID_5x50_7:
+ case IWN_SDID_5x50_12:
+ case IWN_SDID_5x50_13:
+ //iwl5150_abg_cfg
+ sc->limits = &iwn5000_sensitivity_limits;
+ sc->fwname = "iwn5150fw";
+ sc->base_params = &iwn_5x50_base_params;
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
+ "0x%04x rev %d not supported (subdevice)\n", pid,
+ sc->subdevice_id,sc->hw_type);
+ return ENOTSUP;
+ }
+ break;
+ default:
+ device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x"
+ "rev 0x%08x not supported (device)\n", pid, sc->subdevice_id,
+ sc->hw_type);
+ return ENOTSUP;
+ }
+ return 0;
+}
+
static int
iwn4965_attach(struct iwn_softc *sc, uint16_t pid)
{
@@ -769,6 +1234,8 @@ iwn4965_attach(struct iwn_softc *sc, uint16_t pid)
/* Override chains masks, ROM is known to be broken. */
sc->txchainmask = IWN_ANT_AB;
sc->rxchainmask = IWN_ANT_ABC;
+ /* Enable normal btcoex */
+ sc->sc_flags |= IWN_FLAG_BTCOEX;
DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__);
@@ -809,58 +1276,6 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;
sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN;
- switch (sc->hw_type) {
- case IWN_HW_REV_TYPE_5100:
- sc->limits = &iwn5000_sensitivity_limits;
- sc->fwname = "iwn5000fw";
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_B;
- sc->rxchainmask = IWN_ANT_AB;
- break;
- case IWN_HW_REV_TYPE_5150:
- sc->limits = &iwn5150_sensitivity_limits;
- sc->fwname = "iwn5150fw";
- break;
- case IWN_HW_REV_TYPE_5300:
- case IWN_HW_REV_TYPE_5350:
- sc->limits = &iwn5000_sensitivity_limits;
- sc->fwname = "iwn5000fw";
- break;
- case IWN_HW_REV_TYPE_1000:
- sc->limits = &iwn1000_sensitivity_limits;
- sc->fwname = "iwn1000fw";
- break;
- case IWN_HW_REV_TYPE_6000:
- sc->limits = &iwn6000_sensitivity_limits;
- sc->fwname = "iwn6000fw";
- if (pid == 0x422c || pid == 0x4239) {
- sc->sc_flags |= IWN_FLAG_INTERNAL_PA;
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_BC;
- sc->rxchainmask = IWN_ANT_BC;
- }
- break;
- case IWN_HW_REV_TYPE_6050:
- sc->limits = &iwn6000_sensitivity_limits;
- sc->fwname = "iwn6050fw";
- /* Override chains masks, ROM is known to be broken. */
- sc->txchainmask = IWN_ANT_AB;
- sc->rxchainmask = IWN_ANT_AB;
- break;
- case IWN_HW_REV_TYPE_6005:
- sc->limits = &iwn6000_sensitivity_limits;
- if (pid != 0x0082 && pid != 0x0085) {
- sc->fwname = "iwn6000g2bfw";
- sc->sc_flags |= IWN_FLAG_ADV_BTCOEX;
- } else
- sc->fwname = "iwn6000g2afw";
- break;
- default:
- device_printf(sc->sc_dev, "adapter type %d not supported\n",
- sc->hw_type);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
- return ENOTSUP;
- }
return 0;
}
@@ -959,6 +1374,10 @@ iwn_detach(device_t dev)
ieee80211_draintask(ic, &sc->sc_radiooff_task);
iwn_stop(sc);
+
+ taskqueue_drain_all(sc->sc_tq);
+ taskqueue_free(sc->sc_tq);
+
callout_drain(&sc->watchdog_to);
callout_drain(&sc->calib_to);
ieee80211_ifdetach(ic);
@@ -1184,7 +1603,7 @@ iwn_init_otprom(struct iwn_softc *sc)
iwn_nic_unlock(sc);
/* Set auto clock gate disable bit for HW with OTP shadow RAM. */
- if (sc->hw_type != IWN_HW_REV_TYPE_1000) {
+ if (sc->base_params->shadow_ram_support) {
IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT,
IWN_RESET_LINK_PWR_MGMT_DIS);
}
@@ -1197,11 +1616,12 @@ iwn_init_otprom(struct iwn_softc *sc)
* Find the block before last block (contains the EEPROM image)
* for HW without OTP shadow RAM.
*/
- if (sc->hw_type == IWN_HW_REV_TYPE_1000) {
+ if (! sc->base_params->shadow_ram_support) {
/* Switch to absolute addressing mode. */
IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS);
base = prev = 0;
- for (count = 0; count < IWN1000_OTP_NBLOCKS; count++) {
+ for (count = 0; count < sc->base_params->max_ll_items;
+ count++) {
error = iwn_read_prom_data(sc, base, &next, 2);
if (error != 0)
return error;
@@ -1210,7 +1630,7 @@ iwn_init_otprom(struct iwn_softc *sc)
prev = base;
base = le16toh(next);
}
- if (count == 0 || count == IWN1000_OTP_NBLOCKS)
+ if (count == 0 || count == sc->base_params->max_ll_items)
return EIO;
/* Skip "next" word. */
sc->prom_base = prev + 1;
@@ -1316,16 +1736,12 @@ fail: iwn_dma_contig_free(dma);
static void
iwn_dma_contig_free(struct iwn_dma_info *dma)
{
- if (dma->map != NULL) {
- if (dma->vaddr != NULL) {
- bus_dmamap_sync(dma->tag, dma->map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(dma->tag, dma->map);
- bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
- dma->vaddr = NULL;
- }
- bus_dmamap_destroy(dma->tag, dma->map);
- dma->map = NULL;
+ if (dma->vaddr != NULL) {
+ bus_dmamap_sync(dma->tag, dma->map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(dma->tag, dma->map);
+ bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
+ dma->vaddr = NULL;
}
if (dma->tag != NULL) {
bus_dma_tag_destroy(dma->tag);
@@ -1768,7 +2184,7 @@ iwn4965_read_eeprom(struct iwn_softc *sc)
iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4);
/* Read the list of authorized channels (20MHz ones only). */
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < IWN_NBANDS - 1; i++) {
addr = iwn4965_regulatory_bands[i];
iwn_read_eeprom_channels(sc, i, addr);
}
@@ -1798,7 +2214,7 @@ iwn4965_read_eeprom(struct iwn_softc *sc)
#ifdef IWN_DEBUG
/* Print samples. */
if (sc->sc_debug & IWN_DEBUG_ANY) {
- for (i = 0; i < IWN_NBANDS; i++)
+ for (i = 0; i < IWN_NBANDS - 1; i++)
iwn4965_print_power_group(sc, i);
}
#endif
@@ -1859,16 +2275,13 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
sc->eeprom_domain, 4);
/* Read the list of authorized channels (20MHz ones only). */
- for (i = 0; i < 7; i++) {
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
- addr = base + iwn6000_regulatory_bands[i];
- else
- addr = base + iwn5000_regulatory_bands[i];
+ for (i = 0; i < IWN_NBANDS - 1; i++) {
+ addr = base + sc->base_params->regulatory_bands[i];
iwn_read_eeprom_channels(sc, i, addr);
}
/* Read enhanced TX power information for 6000 Series. */
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
+ if (sc->base_params->enhanced_TX_power)
iwn_read_eeprom_enhinfo(sc);
iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2);
@@ -1879,6 +2292,14 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
hdr.version, hdr.pa_type, le16toh(hdr.volt));
sc->calib_ver = hdr.version;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) {
+ sc->eeprom_voltage = le16toh(hdr.volt);
+ iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
+ sc->eeprom_temp_high=le16toh(val);
+ iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
+ sc->eeprom_temp = le16toh(val);
+ }
+
if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
/* Compute temperature offset. */
iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
@@ -2215,6 +2636,52 @@ rate2plcp(int rate)
return 0;
}
+static int
+iwn_get_1stream_tx_antmask(struct iwn_softc *sc)
+{
+
+ return IWN_LSB(sc->txchainmask);
+}
+
+static int
+iwn_get_2stream_tx_antmask(struct iwn_softc *sc)
+{
+ int tx;
+
+ /*
+ * The '2 stream' setup is a bit .. odd.
+ *
+ * For NICs that support only 1 antenna, default to IWN_ANT_AB or
+ * the firmware panics (eg Intel 5100.)
+ *
+ * For NICs that support two antennas, we use ANT_AB.
+ *
+ * For NICs that support three antennas, we use the two that
+ * wasn't the default one.
+ *
+ * XXX TODO: if bluetooth (full concurrent) is enabled, restrict
+ * this to only one antenna.
+ */
+
+ /* Default - transmit on the other antennas */
+ tx = (sc->txchainmask & ~IWN_LSB(sc->txchainmask));
+
+ /* Now, if it's zero, set it to IWN_ANT_AB, so to not panic firmware */
+ if (tx == 0)
+ tx = IWN_ANT_AB;
+
+ /*
+ * If the NIC is a two-stream TX NIC, configure the TX mask to
+ * the default chainmask
+ */
+ else if (sc->ntxchains == 2)
+ tx = sc->txchainmask;
+
+ return (tx);
+}
+
+
+
/*
* Calculate the required PLCP value from the given rate,
* to the given node.
@@ -2228,19 +2695,14 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni,
{
#define RV(v) ((v) & IEEE80211_RATE_VAL)
struct ieee80211com *ic = ni->ni_ic;
- uint8_t txant1, txant2;
uint32_t plcp = 0;
int ridx;
- /* Use the first valid TX antenna. */
- txant1 = IWN_LSB(sc->txchainmask);
- txant2 = IWN_LSB(sc->txchainmask & ~txant1);
-
/*
* If it's an MCS rate, let's set the plcp correctly
* and set the relevant flags based on the node config.
*/
- if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
+ if (rate & IEEE80211_RATE_MCS) {
/*
* Set the initial PLCP value to be between 0->31 for
* MCS 0 -> MCS 31, then set the "I'm an MCS rate!"
@@ -2267,15 +2729,15 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni,
}
/*
- * If it's a two stream rate, enable TX on both
- * antennas.
- *
- * XXX three stream rates?
+ * Ensure the selected rate matches the link quality
+ * table entries being used.
*/
- if (rate > 0x87)
- plcp |= IWN_RFLAG_ANT(txant1 | txant2);
+ if (rate > 0x8f)
+ plcp |= IWN_RFLAG_ANT(sc->txchainmask);
+ else if (rate > 0x87)
+ plcp |= IWN_RFLAG_ANT(iwn_get_2stream_tx_antmask(sc));
else
- plcp |= IWN_RFLAG_ANT(txant1);
+ plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc));
} else {
/*
* Set the initial PLCP - fine for both
@@ -2297,7 +2759,8 @@ iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni,
plcp |= IWN_RFLAG_CCK;
/* Set antenna configuration */
- plcp |= IWN_RFLAG_ANT(txant1);
+ /* XXX TODO: is this the right antenna to use for legacy? */
+ plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc));
}
DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n",
@@ -2629,8 +3092,9 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
uint16_t ssn;
uint8_t tid;
int ackfailcnt = 0, i, lastidx, qid, *res, shift;
+ int tx_ok = 0, tx_err = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
@@ -2660,6 +3124,7 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
KASSERT(ni != NULL, ("no node"));
KASSERT(m != NULL, ("no mbuf"));
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m);
ieee80211_tx_complete(ni, m, 1);
txq->queued--;
@@ -2685,22 +3150,32 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (wn->agg[tid].nframes > (64 - shift))
return;
+ /*
+ * Walk the bitmap and calculate how many successful and failed
+ * attempts are made.
+ *
+ * Yes, the rate control code doesn't know these are A-MPDU
+ * subframes and that it's okay to fail some of these.
+ */
ni = tap->txa_ni;
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
for (i = 0; bitmap; i++) {
if ((bitmap & 1) == 0) {
ifp->if_oerrors++;
+ tx_err ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
} else {
ifp->if_opackets++;
+ tx_ok ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
}
bitmap >>= 1;
}
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT,
+ "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err);
}
@@ -2728,25 +3203,24 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
switch (calib->code) {
case IWN5000_PHY_CALIB_DC:
- if ((sc->sc_flags & IWN_FLAG_INTERNAL_PA) == 0 &&
- (sc->hw_type == IWN_HW_REV_TYPE_5150 ||
- sc->hw_type >= IWN_HW_REV_TYPE_6000) &&
- sc->hw_type != IWN_HW_REV_TYPE_6050)
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_DC)
idx = 0;
break;
case IWN5000_PHY_CALIB_LO:
- idx = 1;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_LO)
+ idx = 1;
break;
case IWN5000_PHY_CALIB_TX_IQ:
- idx = 2;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ)
+ idx = 2;
break;
case IWN5000_PHY_CALIB_TX_IQ_PERIODIC:
- if (sc->hw_type < IWN_HW_REV_TYPE_6000 &&
- sc->hw_type != IWN_HW_REV_TYPE_5150)
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC)
idx = 3;
break;
case IWN5000_PHY_CALIB_BASE_BAND:
- idx = 4;
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_BASE_BAND)
+ idx = 4;
break;
}
if (idx == -1) /* Ignore other results. */
@@ -2763,11 +3237,72 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
return;
}
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
- "saving calibration result code=%d len=%d\n", calib->code, len);
+ "saving calibration result idx=%d, code=%d len=%d\n", idx, calib->code, len);
sc->calibcmd[idx].len = len;
memcpy(sc->calibcmd[idx].buf, calib, len);
}
+static void
+iwn_stats_update(struct iwn_softc *sc, struct iwn_calib_state *calib,
+ struct iwn_stats *stats, int len)
+{
+ struct iwn_stats_bt *stats_bt;
+ struct iwn_stats *lstats;
+
+ /*
+ * First - check whether the length is the bluetooth or normal.
+ *
+ * If it's normal - just copy it and bump out.
+ * Otherwise we have to convert things.
+ */
+
+ if (len == sizeof(struct iwn_stats) + 4) {
+ memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats));
+ sc->last_stat_valid = 1;
+ return;
+ }
+
+ /*
+ * If it's not the bluetooth size - log, then just copy.
+ */
+ if (len != sizeof(struct iwn_stats_bt) + 4) {
+ DPRINTF(sc, IWN_DEBUG_STATS,
+ "%s: size of rx statistics (%d) not an expected size!\n",
+ __func__,
+ len);
+ memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats));
+ sc->last_stat_valid = 1;
+ return;
+ }
+
+ /*
+ * Ok. Time to copy.
+ */
+ stats_bt = (struct iwn_stats_bt *) stats;
+ lstats = &sc->last_stat;
+
+ /* flags */
+ lstats->flags = stats_bt->flags;
+ /* rx_bt */
+ memcpy(&lstats->rx.ofdm, &stats_bt->rx_bt.ofdm,
+ sizeof(struct iwn_rx_phy_stats));
+ memcpy(&lstats->rx.cck, &stats_bt->rx_bt.cck,
+ sizeof(struct iwn_rx_phy_stats));
+ memcpy(&lstats->rx.general, &stats_bt->rx_bt.general_bt.common,
+ sizeof(struct iwn_rx_general_stats));
+ memcpy(&lstats->rx.ht, &stats_bt->rx_bt.ht,
+ sizeof(struct iwn_rx_ht_phy_stats));
+ /* tx */
+ memcpy(&lstats->tx, &stats_bt->tx,
+ sizeof(struct iwn_tx_stats));
+ /* general */
+ memcpy(&lstats->general, &stats_bt->general,
+ sizeof(struct iwn_general_stats));
+
+ /* XXX TODO: Squirrel away the extra bluetooth stats somewhere */
+ sc->last_stat_valid = 1;
+}
+
/*
* Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.
* The latter is sent by the firmware after each received beacon.
@@ -2782,6 +3317,7 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwn_calib_state *calib = &sc->calib;
struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
+ struct iwn_stats *lstats;
int temp;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
@@ -2796,12 +3332,26 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
- DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: received statistics, cmd %d\n",
- __func__, desc->type);
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_STATS,
+ "%s: received statistics, cmd %d, len %d\n",
+ __func__, desc->type, le16toh(desc->len));
sc->calib_cnt = 0; /* Reset TX power calibration timeout. */
+ /*
+ * Collect/track general statistics for reporting.
+ *
+ * This takes care of ensuring that the bluetooth sized message
+ * will be correctly converted to the legacy sized message.
+ */
+ iwn_stats_update(sc, calib, stats, le16toh(desc->len));
+
+ /*
+ * And now, let's take a reference of it to use!
+ */
+ lstats = &sc->last_stat;
+
/* Test if temperature has changed. */
- if (stats->general.temp != sc->rawtemp) {
+ if (lstats->general.temp != sc->rawtemp) {
/* Convert "raw" temperature to degC. */
sc->rawtemp = stats->general.temp;
temp = ops->get_temperature(sc);
@@ -2816,25 +3366,51 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (desc->type != IWN_BEACON_STATISTICS)
return; /* Reply to a statistics request. */
- sc->noise = iwn_get_noise(&stats->rx.general);
+ sc->noise = iwn_get_noise(&lstats->rx.general);
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: noise %d\n", __func__, sc->noise);
/* Test that RSSI and noise are present in stats report. */
- if (le32toh(stats->rx.general.flags) != 1) {
+ if (le32toh(lstats->rx.general.flags) != 1) {
DPRINTF(sc, IWN_DEBUG_ANY, "%s\n",
"received statistics without RSSI");
return;
}
if (calib->state == IWN_CALIB_STATE_ASSOC)
- iwn_collect_noise(sc, &stats->rx.general);
- else if (calib->state == IWN_CALIB_STATE_RUN)
- iwn_tune_sensitivity(sc, &stats->rx);
+ iwn_collect_noise(sc, &lstats->rx.general);
+ else if (calib->state == IWN_CALIB_STATE_RUN) {
+ iwn_tune_sensitivity(sc, &lstats->rx);
+ /*
+ * XXX TODO: Only run the RX recovery if we're associated!
+ */
+ iwn_check_rx_recovery(sc, lstats);
+ iwn_save_stats_counters(sc, lstats);
+ }
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
}
/*
+ * Save the relevant statistic counters for the next calibration
+ * pass.
+ */
+static void
+iwn_save_stats_counters(struct iwn_softc *sc, const struct iwn_stats *rs)
+{
+ struct iwn_calib_state *calib = &sc->calib;
+
+ /* Save counters values for next call. */
+ calib->bad_plcp_cck = le32toh(rs->rx.cck.bad_plcp);
+ calib->fa_cck = le32toh(rs->rx.cck.fa);
+ calib->bad_plcp_ht = le32toh(rs->rx.ht.bad_plcp);
+ calib->bad_plcp_ofdm = le32toh(rs->rx.ofdm.bad_plcp);
+ calib->fa_ofdm = le32toh(rs->rx.ofdm.fa);
+
+ /* Last time we received these tick values */
+ sc->last_calib_ticks = ticks;
+}
+
+/*
* Process a TX_DONE firmware notification. Unfortunately, the 4965AGN
* and 5000 adapters have different incompatible TX status formats.
*/
@@ -2850,15 +3426,18 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
ring = &sc->txq[qid];
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: "
- "qid %d idx %d retries %d nkill %d rate %x duration %d status %x\n",
- __func__, desc->qid, desc->idx, stat->ackfailcnt,
- stat->btkillcnt, stat->rate, le16toh(stat->duration),
+ "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n",
+ __func__, desc->qid, desc->idx,
+ stat->rtsfailcnt,
+ stat->ackfailcnt,
+ stat->btkillcnt,
+ stat->rate, le16toh(stat->duration),
le32toh(stat->status));
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
if (qid >= sc->firstaggqueue) {
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes,
- &stat->status);
+ stat->ackfailcnt, &stat->status);
} else {
iwn_tx_done(sc, desc, stat->ackfailcnt,
le32toh(stat->status) & 0xff);
@@ -2877,9 +3456,12 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
ring = &sc->txq[qid];
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: "
- "qid %d idx %d retries %d nkill %d rate %x duration %d status %x\n",
- __func__, desc->qid, desc->idx, stat->ackfailcnt,
- stat->btkillcnt, stat->rate, le16toh(stat->duration),
+ "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n",
+ __func__, desc->qid, desc->idx,
+ stat->rtsfailcnt,
+ stat->ackfailcnt,
+ stat->btkillcnt,
+ stat->rate, le16toh(stat->duration),
le32toh(stat->status));
#ifdef notyet
@@ -2890,7 +3472,7 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
if (qid >= sc->firstaggqueue) {
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes,
- &stat->status);
+ stat->ackfailcnt, &stat->status);
} else {
iwn_tx_done(sc, desc, stat->ackfailcnt,
le16toh(stat->status) & 0xff);
@@ -2977,12 +3559,19 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
static void
iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
{
- struct iwn_tx_ring *ring = &sc->txq[4];
+ struct iwn_tx_ring *ring;
struct iwn_tx_data *data;
+ int cmd_queue_num;
+
+ if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ cmd_queue_num = IWN_PAN_CMD_QUEUE;
+ else
+ cmd_queue_num = IWN_CMD_QUEUE_NUM;
- if ((desc->qid & 0xf) != 4)
+ if ((desc->qid & IWN_RX_DESC_QID_MSK) != cmd_queue_num)
return; /* Not a command ack. */
+ ring = &sc->txq[cmd_queue_num];
data = &ring->data[desc->idx];
/* If the command was mapped in an mbuf, free it. */
@@ -2998,7 +3587,7 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
static void
iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
- void *stat)
+ int ackfailcnt, void *stat)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
@@ -3015,14 +3604,60 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
uint8_t tid;
int bit, i, lastidx, *res, seqno, shift, start;
+ /* XXX TODO: status is le16 field! Grr */
+
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: nframes=%d, status=0x%08x\n",
+ __func__,
+ nframes,
+ *status);
+
+ tap = sc->qid2tap[qid];
+ tid = tap->txa_tid;
+ wn = (void *)tap->txa_ni;
+ ni = tap->txa_ni;
+
+ /*
+ * XXX TODO: ACK and RTS failures would be nice here!
+ */
-#ifdef NOT_YET
+ /*
+ * A-MPDU single frame status - if we failed to transmit it
+ * in A-MPDU, then it may be a permanent failure.
+ *
+ * XXX TODO: check what the Linux iwlwifi driver does here;
+ * there's some permanent and temporary failures that may be
+ * handled differently.
+ */
if (nframes == 1) {
- if ((*status & 0xff) != 1 && (*status & 0xff) != 2)
+ if ((*status & 0xff) != 1 && (*status & 0xff) != 2) {
+#ifdef NOT_YET
printf("ieee80211_send_bar()\n");
- }
#endif
+ /*
+ * If we completely fail a transmit, make sure a
+ * notification is pushed up to the rate control
+ * layer.
+ */
+ ieee80211_ratectl_tx_complete(ni->ni_vap,
+ ni,
+ IEEE80211_RATECTL_TX_FAILURE,
+ &ackfailcnt,
+ NULL);
+ } else {
+ /*
+ * If nframes=1, then we won't be getting a BA for
+ * this frame. Ensure that we correctly update the
+ * rate control code with how many retries were
+ * needed to send it.
+ */
+ ieee80211_ratectl_tx_complete(ni->ni_vap,
+ ni,
+ IEEE80211_RATECTL_TX_SUCCESS,
+ &ackfailcnt,
+ NULL);
+ }
+ }
bitmap = 0;
start = idx;
@@ -3061,6 +3696,7 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
ssn = tap->txa_start & 0xfff;
}
+ /* This is going nframes DWORDS into the descriptor? */
seqno = le32toh(*(status + nframes)) & 0xfff;
for (lastidx = (seqno & 0xff); ring->read != lastidx;) {
data = &ring->data[ring->read];
@@ -3074,7 +3710,7 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
KASSERT(ni != NULL, ("no node"));
KASSERT(m != NULL, ("no mbuf"));
-
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m);
ieee80211_tx_complete(ni, m, 1);
ring->queued--;
@@ -3129,12 +3765,12 @@ iwn_notif_intr(struct iwn_softc *sc)
desc = mtod(data->m, struct iwn_rx_desc *);
DPRINTF(sc, IWN_DEBUG_RECV,
- "%s: qid %x idx %d flags %x type %d(%s) len %d\n",
- __func__, desc->qid & 0xf, desc->idx, desc->flags,
+ "%s: cur=%d; qid %x idx %d flags %x type %d(%s) len %d\n",
+ __func__, sc->rxq.cur, desc->qid & 0xf, desc->idx, desc->flags,
desc->type, iwn_intr_str(desc->type),
le16toh(desc->len));
- if (!(desc->qid & 0x80)) /* Reply to a command. */
+ if (!(desc->qid & IWN_UNSOLICITED_RX_NOTIF)) /* Reply to a command. */
iwn_cmd_done(sc, desc);
switch (desc->type) {
@@ -3229,7 +3865,8 @@ iwn_notif_intr(struct iwn_softc *sc)
BUS_DMASYNC_POSTREAD);
#ifdef IWN_DEBUG
uint32_t *status = (uint32_t *)(desc + 1);
- DPRINTF(sc, IWN_DEBUG_INTR, "state changed to %x\n",
+ DPRINTF(sc, IWN_DEBUG_INTR | IWN_DEBUG_STATE,
+ "state changed to %x\n",
le32toh(*status));
#endif
break;
@@ -3254,11 +3891,11 @@ iwn_notif_intr(struct iwn_softc *sc)
#ifdef IWN_DEBUG
struct iwn_stop_scan *scan =
(struct iwn_stop_scan *)(desc + 1);
- DPRINTF(sc, IWN_DEBUG_STATE,
+ DPRINTF(sc, IWN_DEBUG_STATE | IWN_DEBUG_SCAN,
"scan finished nchan=%d status=%d chan=%d\n",
scan->nchan, scan->status, scan->chan);
#endif
-
+ sc->sc_is_scanning = 0;
IWN_UNLOCK(sc);
ieee80211_scan_next(vap);
IWN_LOCK(sc);
@@ -3442,8 +4079,8 @@ iwn_intr(void *arg)
#endif
/* Dump firmware error log and stop. */
iwn_fatal_intr(sc);
- ifp->if_flags &= ~IFF_UP;
- iwn_stop_locked(sc);
+
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_panic_task);
goto done;
}
if ((r1 & (IWN_INT_FH_RX | IWN_INT_SW_RX | IWN_INT_RX_PERIODIC)) ||
@@ -3541,6 +4178,115 @@ iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)
}
#endif
+/*
+ * Check whether OFDM 11g protection will be enabled for the given rate.
+ *
+ * The original driver code only enabled protection for OFDM rates.
+ * It didn't check to see whether it was operating in 11a or 11bg mode.
+ */
+static int
+iwn_check_rate_needs_protection(struct iwn_softc *sc,
+ struct ieee80211vap *vap, uint8_t rate)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /*
+ * Not in 2GHz mode? Then there's no need to enable OFDM
+ * 11bg protection.
+ */
+ if (! IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
+ return (0);
+ }
+
+ /*
+ * 11bg protection not enabled? Then don't use it.
+ */
+ if ((ic->ic_flags & IEEE80211_F_USEPROT) == 0)
+ return (0);
+
+ /*
+ * If it's an 11n rate - no protection.
+ * We'll do it via a specific 11n check.
+ */
+ if (rate & IEEE80211_RATE_MCS) {
+ return (0);
+ }
+
+ /*
+ * Do a rate table lookup. If the PHY is CCK,
+ * don't do protection.
+ */
+ if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_CCK)
+ return (0);
+
+ /*
+ * Yup, enable protection.
+ */
+ return (1);
+}
+
+/*
+ * return a value between 0 and IWN_MAX_TX_RETRIES-1 as an index into
+ * the link quality table that reflects this particular entry.
+ */
+static int
+iwn_tx_rate_to_linkq_offset(struct iwn_softc *sc, struct ieee80211_node *ni,
+ uint8_t rate)
+{
+ struct ieee80211_rateset *rs;
+ int is_11n;
+ int nr;
+ int i;
+ uint8_t cmp_rate;
+
+ /*
+ * Figure out if we're using 11n or not here.
+ */
+ if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates > 0)
+ is_11n = 1;
+ else
+ is_11n = 0;
+
+ /*
+ * Use the correct rate table.
+ */
+ if (is_11n) {
+ rs = (struct ieee80211_rateset *) &ni->ni_htrates;
+ nr = ni->ni_htrates.rs_nrates;
+ } else {
+ rs = &ni->ni_rates;
+ nr = rs->rs_nrates;
+ }
+
+ /*
+ * Find the relevant link quality entry in the table.
+ */
+ for (i = 0; i < nr && i < IWN_MAX_TX_RETRIES - 1 ; i++) {
+ /*
+ * The link quality table index starts at 0 == highest
+ * rate, so we walk the rate table backwards.
+ */
+ cmp_rate = rs->rs_rates[(nr - 1) - i];
+ if (rate & IEEE80211_RATE_MCS)
+ cmp_rate |= IEEE80211_RATE_MCS;
+
+#if 0
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: idx %d: nr=%d, rate=0x%02x, rateentry=0x%02x\n",
+ __func__,
+ i,
+ nr,
+ rate,
+ cmp_rate);
+#endif
+
+ if (cmp_rate == rate)
+ return (i);
+ }
+
+ /* Failed? Start at the end */
+ return (IWN_MAX_TX_RETRIES - 1);
+}
+
static int
iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
@@ -3561,7 +4307,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
uint16_t qos;
u_int hdrlen;
bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
- uint8_t tid, ridx, txant, type;
+ uint8_t tid, type;
int ac, i, totlen, error, pad, nsegs = 0, rate;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
@@ -3582,6 +4328,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
}
ac = M_WME_GETAC(m);
if (m->m_flags & M_AMPDU_MPDU) {
+ uint16_t seqno;
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
if (!IEEE80211_AMPDU_RUNNING(tap)) {
@@ -3589,9 +4336,27 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
return EINVAL;
}
+ /*
+ * Queue this frame to the hardware ring that we've
+ * negotiated AMPDU TX on.
+ *
+ * Note that the sequence number must match the TX slot
+ * being used!
+ */
ac = *(int *)tap->txa_private;
+ seqno = ni->ni_txseqs[tid];
*(uint16_t *)wh->i_seq =
- htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
+ htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ ring = &sc->txq[ac];
+ if ((seqno % 256) != ring->cur) {
+ device_printf(sc->sc_dev,
+ "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n",
+ __func__,
+ m,
+ seqno,
+ seqno % 256,
+ ring->cur);
+ }
ni->ni_txseqs[tid]++;
}
ring = &sc->txq[ac];
@@ -3606,13 +4371,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
rate = tp->mcastrate;
else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
rate = tp->ucastrate;
+ else if (m->m_flags & M_EAPOL)
+ rate = tp->mgmtrate;
else {
/* XXX pass pktlen */
(void) ieee80211_ratectl_rate(ni, NULL, 0);
rate = ni->ni_txrate;
}
- ridx = ieee80211_legacy_rate_lookup(ic->ic_rt,
- rate & IEEE80211_RATE_VAL);
/* Encrypt the frame if need be. */
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
@@ -3669,13 +4434,18 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
/* NB: Group frames are sent using CCK in 802.11b/g. */
if (totlen + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) {
flags |= IWN_TX_NEED_RTS;
- } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
- ridx >= IWN_RIDX_OFDM6) {
+ } else if (iwn_check_rate_needs_protection(sc, vap, rate)) {
if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
flags |= IWN_TX_NEED_CTS;
else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
flags |= IWN_TX_NEED_RTS;
+ } else if ((rate & IEEE80211_RATE_MCS) &&
+ (ic->ic_htprotmode == IEEE80211_PROT_RTSCTS)) {
+ flags |= IWN_TX_NEED_RTS;
}
+
+ /* XXX HT protection? */
+
if (flags & (IWN_TX_NEED_RTS | IWN_TX_NEED_CTS)) {
if (sc->hw_type != IWN_HW_REV_TYPE_4965) {
/* 5000 autoselects RTS/CTS or CTS-to-self. */
@@ -3722,13 +4492,11 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
if (tx->id == sc->broadcast_id) {
/* Group or management frame. */
tx->linkq = 0;
- /* XXX Alternate between antenna A and B? */
- txant = IWN_LSB(sc->txchainmask);
- tx->rate |= htole32(IWN_RFLAG_ANT(txant));
} else {
- tx->linkq = ni->ni_rates.rs_nrates - ridx - 1;
+ tx->linkq = iwn_tx_rate_to_linkq_offset(sc, ni, rate);
flags |= IWN_TX_LINKQ; /* enable MRR */
}
+
/* Set physical address of "scratch area". */
tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
tx->hiaddr = IWN_HIADDR(data->scratch_paddr);
@@ -3773,8 +4541,16 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
data->m = m;
data->ni = ni;
- DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n",
- __func__, ring->qid, ring->cur, m->m_pkthdr.len, nsegs);
+ DPRINTF(sc, IWN_DEBUG_XMIT,
+ "%s: qid %d idx %d len %d nsegs %d flags 0x%08x rate 0x%04x plcp 0x%08x\n",
+ __func__,
+ ring->qid,
+ ring->cur,
+ m->m_pkthdr.len,
+ nsegs,
+ flags,
+ rate,
+ tx->rate);
/* Fill TX descriptor. */
desc->nsegs = 1;
@@ -3821,9 +4597,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
+// struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211com *ic = ifp->if_l2com;
+// struct ieee80211com *ic = ifp->if_l2com;
struct iwn_tx_cmd *cmd;
struct iwn_cmd_data *tx;
struct ieee80211_frame *wh;
@@ -3835,7 +4611,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
uint32_t flags;
u_int hdrlen;
int ac, totlen, error, pad, nsegs = 0, i, rate;
- uint8_t ridx, type, txant;
+ uint8_t type;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
@@ -3851,16 +4627,8 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
- /* Choose a TX rate index. */
+ /* Choose a TX rate. */
rate = params->ibp_rate0;
- ridx = ieee80211_legacy_rate_lookup(ic->ic_rt,
- rate & IEEE80211_RATE_VAL);
- if (ridx == (uint8_t)-1) {
- /* XXX fall back to mcast/mgmt rate? */
- m_freem(m);
- return EINVAL;
- }
-
totlen = m->m_pkthdr.len;
/* Prepare TX firmware command. */
@@ -3930,17 +4698,10 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
tx->rts_ntries = params->ibp_try1;
tx->data_ntries = params->ibp_try0;
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
-
- /* XXX should just use iwn_rate_to_plcp() */
- tx->rate = htole32(rate2plcp(rate));
- if (ridx < IWN_RIDX_OFDM6 &&
- IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
- tx->rate |= htole32(IWN_RFLAG_CCK);
+ tx->rate = iwn_rate_to_plcp(sc, ni, rate);
/* Group or management frame. */
tx->linkq = 0;
- txant = IWN_LSB(sc->txchainmask);
- tx->rate |= htole32(IWN_RFLAG_ANT(txant));
/* Set physical address of "scratch area". */
tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
@@ -4038,7 +4799,7 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
struct iwn_softc *sc = ifp->if_softc;
int error = 0;
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
ieee80211_free_node(ni);
@@ -4069,7 +4830,7 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
IWN_UNLOCK(sc);
- DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
+ DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s: end\n",__func__);
return error;
}
@@ -4093,6 +4854,8 @@ iwn_start_locked(struct ifnet *ifp)
IWN_LOCK_ASSERT(sc);
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__);
+
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ifp->if_drv_flags & IFF_DRV_OACTIVE))
return;
@@ -4113,6 +4876,8 @@ iwn_start_locked(struct ifnet *ifp)
}
sc->sc_tx_timer = 5;
}
+
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__);
}
static void
@@ -4174,6 +4939,19 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
+ case SIOCGIWNSTATS:
+ IWN_LOCK(sc);
+ /* XXX validate permissions/memory/etc? */
+ error = copyout(&sc->last_stat, ifr->ifr_data,
+ sizeof(struct iwn_stats));
+ IWN_UNLOCK(sc);
+ break;
+ case SIOCZIWNSTATS:
+ IWN_LOCK(sc);
+ memset(&sc->last_stat, 0, sizeof(struct iwn_stats));
+ IWN_UNLOCK(sc);
+ error = 0;
+ break;
default:
error = EINVAL;
break;
@@ -4187,19 +4965,26 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static int
iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
{
- struct iwn_tx_ring *ring = &sc->txq[4];
+ struct iwn_tx_ring *ring;
struct iwn_tx_desc *desc;
struct iwn_tx_data *data;
struct iwn_tx_cmd *cmd;
struct mbuf *m;
bus_addr_t paddr;
int totlen, error;
+ int cmd_queue_num;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
if (async == 0)
IWN_LOCK_ASSERT(sc);
+ if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ cmd_queue_num = IWN_PAN_CMD_QUEUE;
+ else
+ cmd_queue_num = IWN_CMD_QUEUE_NUM;
+
+ ring = &sc->txq[cmd_queue_num];
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
totlen = 4 + size;
@@ -4293,42 +5078,87 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
{
#define RV(v) ((v) & IEEE80211_RATE_VAL)
struct iwn_node *wn = (void *)ni;
- struct ieee80211_rateset *rs = &ni->ni_rates;
+ struct ieee80211_rateset *rs;
struct iwn_cmd_link_quality linkq;
- uint8_t txant;
int i, rate, txrate;
+ int is_11n;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
- /* Use the first valid TX antenna. */
- txant = IWN_LSB(sc->txchainmask);
-
memset(&linkq, 0, sizeof linkq);
linkq.id = wn->id;
- linkq.antmsk_1stream = txant;
- linkq.antmsk_2stream = IWN_ANT_AB;
- linkq.ampdu_max = 64;
+ linkq.antmsk_1stream = iwn_get_1stream_tx_antmask(sc);
+ linkq.antmsk_2stream = iwn_get_2stream_tx_antmask(sc);
+
+ linkq.ampdu_max = 32; /* XXX negotiated? */
linkq.ampdu_threshold = 3;
linkq.ampdu_limit = htole16(4000); /* 4ms */
+ DPRINTF(sc, IWN_DEBUG_XMIT,
+ "%s: 1stream antenna=0x%02x, 2stream antenna=0x%02x, ntxstreams=%d\n",
+ __func__,
+ linkq.antmsk_1stream,
+ linkq.antmsk_2stream,
+ sc->ntxchains);
+
+ /*
+ * Are we using 11n rates? Ensure the channel is
+ * 11n _and_ we have some 11n rates, or don't
+ * try.
+ */
+ if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates > 0) {
+ rs = (struct ieee80211_rateset *) &ni->ni_htrates;
+ is_11n = 1;
+ } else {
+ rs = &ni->ni_rates;
+ is_11n = 0;
+ }
+
/* Start at highest available bit-rate. */
- if (IEEE80211_IS_CHAN_HT(ni->ni_chan))
+ /*
+ * XXX this is all very dirty!
+ */
+ if (is_11n)
txrate = ni->ni_htrates.rs_nrates - 1;
else
txrate = rs->rs_nrates - 1;
for (i = 0; i < IWN_MAX_TX_RETRIES; i++) {
uint32_t plcp;
- if (IEEE80211_IS_CHAN_HT(ni->ni_chan))
- rate = IEEE80211_RATE_MCS | txrate;
+ /*
+ * XXX TODO: ensure the last two slots are the two lowest
+ * rate entries, just for now.
+ */
+ if (i == 14 || i == 15)
+ txrate = 0;
+
+ if (is_11n)
+ rate = IEEE80211_RATE_MCS | rs->rs_rates[txrate];
else
rate = RV(rs->rs_rates[txrate]);
/* Do rate -> PLCP config mapping */
plcp = iwn_rate_to_plcp(sc, ni, rate);
linkq.retry[i] = plcp;
+ DPRINTF(sc, IWN_DEBUG_XMIT,
+ "%s: i=%d, txrate=%d, rate=0x%02x, plcp=0x%08x\n",
+ __func__,
+ i,
+ txrate,
+ rate,
+ le32toh(plcp));
- /* Special case for dual-stream rates? */
+ /*
+ * The mimo field is an index into the table which
+ * indicates the first index where it and subsequent entries
+ * will not be using MIMO.
+ *
+ * Since we're filling linkq from 0..15 and we're filling
+ * from the higest MCS rates to the lowest rates, if we
+ * _are_ doing a dual-stream rate, set mimo to idx+1 (ie,
+ * the next entry.) That way if the next entry is a non-MIMO
+ * entry, we're already pointing at it.
+ */
if ((le32toh(plcp) & IWN_RFLAG_MCS) &&
RV(le32toh(plcp)) > 7)
linkq.mimo = i + 1;
@@ -4337,6 +5167,15 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
if (txrate > 0)
txrate--;
}
+ /*
+ * If we reached the end of the list and indeed we hit
+ * all MIMO rates (eg 5300 doing MCS23-15) then yes,
+ * set mimo to 15. Setting it to 16 panics the firmware.
+ */
+ if (linkq.mimo > 15)
+ linkq.mimo = 15;
+
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: mimo = %d\n", __func__, linkq.mimo);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@@ -4374,13 +5213,14 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async)
memset(&linkq, 0, sizeof linkq);
linkq.id = sc->broadcast_id;
- linkq.antmsk_1stream = txant;
- linkq.antmsk_2stream = IWN_ANT_AB;
+ linkq.antmsk_1stream = iwn_get_1stream_tx_antmask(sc);
+ linkq.antmsk_2stream = iwn_get_2stream_tx_antmask(sc);
linkq.ampdu_max = 64;
linkq.ampdu_threshold = 3;
linkq.ampdu_limit = htole16(4000); /* 4ms */
/* Use lowest mandatory bit-rate. */
+ /* XXX rate table lookup? */
if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
linkq.retry[0] = htole32(0xd);
else
@@ -4442,6 +5282,12 @@ iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
+#if 0
+ /* XXX don't set LEDs during scan? */
+ if (sc->sc_is_scanning)
+ return;
+#endif
+
/* Clear microcode LED ownership. */
IWN_CLRBITS(sc, IWN_LED, IWN_LED_BSM_CTRL);
@@ -4681,6 +5527,7 @@ iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch,
int async)
{
struct iwn5000_cmd_txpower cmd;
+ int cmdid;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -4692,8 +5539,15 @@ iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch,
cmd.global_limit = 2 * IWN5000_TXPOWER_MAX_DBM; /* 16 dBm */
cmd.flags = IWN5000_TXPOWER_NO_CLOSED;
cmd.srv_limit = IWN5000_TXPOWER_AUTO;
- DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: setting TX power\n", __func__);
- return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM, &cmd, sizeof cmd, async);
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT,
+ "%s: setting TX power; rev=%d\n",
+ __func__,
+ IWN_UCODE_API(sc->ucode_rev));
+ if (IWN_UCODE_API(sc->ucode_rev) == 1)
+ cmdid = IWN_CMD_TXPOWER_DBM_V1;
+ else
+ cmdid = IWN_CMD_TXPOWER_DBM;
+ return iwn_cmd(sc, cmdid, &cmd, sizeof cmd, async);
}
/*
@@ -4893,7 +5747,7 @@ iwn_collect_noise(struct iwn_softc *sc,
for (i = 0; i < 3; i++)
if (val - calib->rssi[i] > 15 * 20)
sc->chainmask &= ~(1 << i);
- DPRINTF(sc, IWN_DEBUG_CALIBRATE,
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT,
"%s: RX chains mask: theoretical=0x%x, actual=0x%x\n",
__func__, sc->rxchainmask, sc->chainmask);
@@ -4907,6 +5761,10 @@ iwn_collect_noise(struct iwn_softc *sc,
#ifdef notyet
/* XXX Disable RX chains with no antennas connected. */
sc->rxon->rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask));
+ if (sc->sc_is_scanning)
+ device_printf(sc->sc_dev,
+ "%s: is_scanning set, before RXON\n",
+ __func__);
(void)iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
#endif
@@ -5014,7 +5872,7 @@ iwn5000_set_gains(struct iwn_softc *sc)
cmd.gain[i - 1] |= 1 << 2; /* sign bit */
}
}
- DPRINTF(sc, IWN_DEBUG_CALIBRATE,
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_XMIT,
"setting differential gains Ant B/C: %x/%x (%x)\n",
cmd.gain[0], cmd.gain[1], sc->chainmask);
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);
@@ -5064,10 +5922,6 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
fa += le32toh(stats->ofdm.fa) - calib->fa_ofdm;
fa *= 200 * IEEE80211_DUR_TU; /* 200TU */
- /* Save counters values for next call. */
- calib->bad_plcp_ofdm = le32toh(stats->ofdm.bad_plcp);
- calib->fa_ofdm = le32toh(stats->ofdm.fa);
-
if (fa > 50 * rxena) {
/* High false alarm count, decrease sensitivity. */
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
@@ -5121,10 +5975,6 @@ iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
fa += le32toh(stats->cck.fa) - calib->fa_cck;
fa *= 200 * IEEE80211_DUR_TU; /* 200TU */
- /* Save counters values for next call. */
- calib->bad_plcp_cck = le32toh(stats->cck.bad_plcp);
- calib->fa_cck = le32toh(stats->cck.fa);
-
if (fa > 50 * rxena) {
/* High false alarm count, decrease sensitivity. */
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
@@ -5205,7 +6055,7 @@ iwn_send_sensitivity(struct iwn_softc *sc)
cmd.energy_cck = htole16(calib->energy_cck);
/* Barker modulation: use default values. */
cmd.corr_barker = htole16(190);
- cmd.corr_barker_mrc = htole16(390);
+ cmd.corr_barker_mrc = htole16(sc->limits->barker_mrc);
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
"%s: set sensitivity %d/%d/%d/%d/%d/%d/%d\n", __func__,
@@ -5230,6 +6080,86 @@ send:
}
/*
+ * Look at the increase of PLCP errors over time; if it exceeds
+ * a programmed threshold then trigger an RF retune.
+ */
+static void
+iwn_check_rx_recovery(struct iwn_softc *sc, struct iwn_stats *rs)
+{
+ int32_t delta_ofdm, delta_ht, delta_cck;
+ struct iwn_calib_state *calib = &sc->calib;
+ int delta_ticks, cur_ticks;
+ int delta_msec;
+ int thresh;
+
+ /*
+ * Calculate the difference between the current and
+ * previous statistics.
+ */
+ delta_cck = le32toh(rs->rx.cck.bad_plcp) - calib->bad_plcp_cck;
+ delta_ofdm = le32toh(rs->rx.ofdm.bad_plcp) - calib->bad_plcp_ofdm;
+ delta_ht = le32toh(rs->rx.ht.bad_plcp) - calib->bad_plcp_ht;
+
+ /*
+ * Calculate the delta in time between successive statistics
+ * messages. Yes, it can roll over; so we make sure that
+ * this doesn't happen.
+ *
+ * XXX go figure out what to do about rollover
+ * XXX go figure out what to do if ticks rolls over to -ve instead!
+ * XXX go stab signed integer overflow undefined-ness in the face.
+ */
+ cur_ticks = ticks;
+ delta_ticks = cur_ticks - sc->last_calib_ticks;
+
+ /*
+ * If any are negative, then the firmware likely reset; so just
+ * bail. We'll pick this up next time.
+ */
+ if (delta_cck < 0 || delta_ofdm < 0 || delta_ht < 0 || delta_ticks < 0)
+ return;
+
+ /*
+ * delta_ticks is in ticks; we need to convert it up to milliseconds
+ * so we can do some useful math with it.
+ */
+ delta_msec = ticks_to_msecs(delta_ticks);
+
+ /*
+ * Calculate what our threshold is given the current delta_msec.
+ */
+ thresh = sc->base_params->plcp_err_threshold * delta_msec;
+
+ DPRINTF(sc, IWN_DEBUG_STATE,
+ "%s: time delta: %d; cck=%d, ofdm=%d, ht=%d, total=%d, thresh=%d\n",
+ __func__,
+ delta_msec,
+ delta_cck,
+ delta_ofdm,
+ delta_ht,
+ (delta_msec + delta_cck + delta_ofdm + delta_ht),
+ thresh);
+
+ /*
+ * If we need a retune, then schedule a single channel scan
+ * to a channel that isn't the currently active one!
+ *
+ * The math from linux iwlwifi:
+ *
+ * if ((delta * 100 / msecs) > threshold)
+ */
+ if (thresh > 0 && (delta_cck + delta_ofdm + delta_ht) * 100 > thresh) {
+ DPRINTF(sc, IWN_DEBUG_ANY,
+ "%s: PLCP error threshold raw (%d) comparison (%d) "
+ "over limit (%d); retune!\n",
+ __func__,
+ (delta_cck + delta_ofdm + delta_ht),
+ (delta_cck + delta_ofdm + delta_ht) * 100,
+ thresh);
+ }
+}
+
+/*
* Set STA mode power saving level (between 0 and 5).
* Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.
*/
@@ -5314,25 +6244,73 @@ iwn_send_advanced_btcoex(struct iwn_softc *sc)
0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
};
struct iwn6000_btcoex_config btconfig;
+ struct iwn2000_btcoex_config btconfig2k;
struct iwn_btcoex_priotable btprio;
struct iwn_btcoex_prot btprot;
int error, i;
+ uint8_t flags;
memset(&btconfig, 0, sizeof btconfig);
- btconfig.flags = 145;
- btconfig.max_kill = 5;
- btconfig.bt3_t7_timer = 1;
- btconfig.kill_ack = htole32(0xffff0000);
- btconfig.kill_cts = htole32(0xffff0000);
- btconfig.sample_time = 2;
- btconfig.bt3_t2_timer = 0xc;
- for (i = 0; i < 12; i++)
- btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
- btconfig.valid = htole16(0xff);
- btconfig.prio_boost = 0xf0;
- DPRINTF(sc, IWN_DEBUG_RESET,
- "%s: configuring advanced bluetooth coexistence\n", __func__);
- error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+ memset(&btconfig2k, 0, sizeof btconfig2k);
+
+ flags = IWN_BT_FLAG_COEX6000_MODE_3W <<
+ IWN_BT_FLAG_COEX6000_MODE_SHIFT; // Done as is in linux kernel 3.2
+
+ if (sc->base_params->bt_sco_disable)
+ flags &= ~IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+ else
+ flags |= IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+
+ flags |= IWN_BT_FLAG_COEX6000_CHAN_INHIBITION;
+
+ /* Default flags result is 145 as old value */
+
+ /*
+ * Flags value has to be review. Values must change if we
+ * which to disable it
+ */
+ if (sc->base_params->bt_session_2) {
+ btconfig2k.flags = flags;
+ btconfig2k.max_kill = 5;
+ btconfig2k.bt3_t7_timer = 1;
+ btconfig2k.kill_ack = htole32(0xffff0000);
+ btconfig2k.kill_cts = htole32(0xffff0000);
+ btconfig2k.sample_time = 2;
+ btconfig2k.bt3_t2_timer = 0xc;
+
+ for (i = 0; i < 12; i++)
+ btconfig2k.lookup_table[i] = htole32(btcoex_3wire[i]);
+ btconfig2k.valid = htole16(0xff);
+ btconfig2k.prio_boost = htole32(0xf0);
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "%s: configuring advanced bluetooth coexistence"
+ " session 2, flags : 0x%x\n",
+ __func__,
+ flags);
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig2k,
+ sizeof(btconfig2k), 1);
+ } else {
+ btconfig.flags = flags;
+ btconfig.max_kill = 5;
+ btconfig.bt3_t7_timer = 1;
+ btconfig.kill_ack = htole32(0xffff0000);
+ btconfig.kill_cts = htole32(0xffff0000);
+ btconfig.sample_time = 2;
+ btconfig.bt3_t2_timer = 0xc;
+
+ for (i = 0; i < 12; i++)
+ btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
+ btconfig.valid = htole16(0xff);
+ btconfig.prio_boost = 0xf0;
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "%s: configuring advanced bluetooth coexistence,"
+ " flags : 0x%x\n",
+ __func__,
+ flags);
+ error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig,
+ sizeof(btconfig), 1);
+ }
+
if (error != 0)
return error;
@@ -5387,13 +6365,32 @@ iwn_config(struct iwn_softc *sc)
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
- if (sc->hw_type == IWN_HW_REV_TYPE_6005) {
- /* Set radio temperature sensor offset. */
+ if ((sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET)
+ && (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2)) {
+ device_printf(sc->sc_dev,"%s: temp_offset and temp_offsetv2 are"
+ " exclusive each together. Review NIC config file. Conf"
+ " : 0x%08x Flags : 0x%08x \n", __func__,
+ sc->base_params->calib_need,
+ (IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET |
+ IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2));
+ return (EINVAL);
+ }
+
+ /* Compute temperature calib if needed. Will be send by send calib */
+ if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET) {
error = iwn5000_temp_offset_calib(sc);
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not set temperature offset\n", __func__);
- return error;
+ return (error);
+ }
+ } else if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) {
+ error = iwn5000_temp_offset_calibv2(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not compute temperature offset v2\n",
+ __func__);
+ return (error);
}
}
@@ -5409,9 +6406,10 @@ iwn_config(struct iwn_softc *sc)
}
/* Configure valid TX chains for >=5000 Series. */
- if (sc->hw_type != IWN_HW_REV_TYPE_4965) {
+ if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
+ IWN_UCODE_API(sc->ucode_rev) > 1) {
txmask = htole32(sc->txchainmask);
- DPRINTF(sc, IWN_DEBUG_RESET,
+ DPRINTF(sc, IWN_DEBUG_RESET | IWN_DEBUG_XMIT,
"%s: configuring valid TX chains 0x%x\n", __func__, txmask);
error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG, &txmask,
sizeof txmask, 0);
@@ -5424,10 +6422,14 @@ iwn_config(struct iwn_softc *sc)
}
/* Configure bluetooth coexistence. */
- if (sc->sc_flags & IWN_FLAG_ADV_BTCOEX)
+ error = 0;
+
+ /* Configure bluetooth coexistence if needed. */
+ if (sc->base_params->bt_mode == IWN_BT_ADVANCED)
error = iwn_send_advanced_btcoex(sc);
- else
+ if (sc->base_params->bt_mode == IWN_BT_SIMPLE)
error = iwn_send_btcoex(sc);
+
if (error != 0) {
device_printf(sc->sc_dev,
"%s: could not configure bluetooth coexistence, error %d\n",
@@ -5463,12 +6465,29 @@ iwn_config(struct iwn_softc *sc)
sc->rxon->ht_single_mask = 0xff;
sc->rxon->ht_dual_mask = 0xff;
sc->rxon->ht_triple_mask = 0xff;
+ /*
+ * In active association mode, ensure that
+ * all the receive chains are enabled.
+ *
+ * Since we're not yet doing SMPS, don't allow the
+ * number of idle RX chains to be less than the active
+ * number.
+ */
rxchain =
IWN_RXCHAIN_VALID(sc->rxchainmask) |
- IWN_RXCHAIN_MIMO_COUNT(2) |
- IWN_RXCHAIN_IDLE_COUNT(2);
+ IWN_RXCHAIN_MIMO_COUNT(sc->nrxchains) |
+ IWN_RXCHAIN_IDLE_COUNT(sc->nrxchains);
sc->rxon->rxchain = htole16(rxchain);
+ DPRINTF(sc, IWN_DEBUG_RESET | IWN_DEBUG_XMIT,
+ "%s: rxchainmask=0x%x, nrxchains=%d\n",
+ __func__,
+ sc->rxchainmask,
+ sc->nrxchains);
DPRINTF(sc, IWN_DEBUG_RESET, "%s: setting configuration\n", __func__);
+ if (sc->sc_is_scanning)
+ device_printf(sc->sc_dev,
+ "%s: is_scanning set, before RXON\n",
+ __func__);
error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 0);
if (error != 0) {
device_printf(sc->sc_dev, "%s: RXON command failed\n",
@@ -5507,39 +6526,109 @@ iwn_config(struct iwn_softc *sc)
return 0;
}
+static uint16_t
+iwn_get_active_dwell_time(struct iwn_softc *sc,
+ struct ieee80211_channel *c, uint8_t n_probes)
+{
+ /* No channel? Default to 2GHz settings */
+ if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) {
+ return (IWN_ACTIVE_DWELL_TIME_2GHZ +
+ IWN_ACTIVE_DWELL_FACTOR_2GHZ * (n_probes + 1));
+ }
+
+ /* 5GHz dwell time */
+ return (IWN_ACTIVE_DWELL_TIME_5GHZ +
+ IWN_ACTIVE_DWELL_FACTOR_5GHZ * (n_probes + 1));
+}
+
/*
- * Add an ssid element to a frame.
+ * Limit the total dwell time to 85% of the beacon interval.
+ *
+ * Returns the dwell time in milliseconds.
*/
-static uint8_t *
-ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len)
+static uint16_t
+iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
{
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = len;
- memcpy(frm, ssid, len);
- return frm + len;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211vap *vap = NULL;
+ int bintval = 0;
+
+ /* bintval is in TU (1.024mS) */
+ if (! TAILQ_EMPTY(&ic->ic_vaps)) {
+ vap = TAILQ_FIRST(&ic->ic_vaps);
+ bintval = vap->iv_bss->ni_intval;
+ }
+
+ /*
+ * If it's non-zero, we should calculate the minimum of
+ * it and the DWELL_BASE.
+ *
+ * XXX Yes, the math should take into account that bintval
+ * is 1.024mS, not 1mS..
+ */
+ if (bintval > 0) {
+ DPRINTF(sc, IWN_DEBUG_SCAN,
+ "%s: bintval=%d\n",
+ __func__,
+ bintval);
+ return (MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100)));
+ }
+
+ /* No association context? Default */
+ return (IWN_PASSIVE_DWELL_BASE);
+}
+
+static uint16_t
+iwn_get_passive_dwell_time(struct iwn_softc *sc, struct ieee80211_channel *c)
+{
+ uint16_t passive;
+
+ if (c == NULL || IEEE80211_IS_CHAN_2GHZ(c)) {
+ passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_2GHZ;
+ } else {
+ passive = IWN_PASSIVE_DWELL_BASE + IWN_PASSIVE_DWELL_TIME_5GHZ;
+ }
+
+ /* Clamp to the beacon interval if we're associated */
+ return (iwn_limit_dwell(sc, passive));
}
static int
-iwn_scan(struct iwn_softc *sc)
+iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
+ struct ieee80211_scan_state *ss, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211_scan_state *ss = ic->ic_scan; /*XXX*/
- struct ieee80211_node *ni = ss->ss_vap->iv_bss;
+ struct ieee80211_node *ni = vap->iv_bss;
struct iwn_scan_hdr *hdr;
struct iwn_cmd_data *tx;
struct iwn_scan_essid *essid;
struct iwn_scan_chan *chan;
struct ieee80211_frame *wh;
struct ieee80211_rateset *rs;
- struct ieee80211_channel *c;
uint8_t *buf, *frm;
uint16_t rxchain;
uint8_t txant;
int buflen, error;
+ int is_active;
+ uint16_t dwell_active, dwell_passive;
+ uint32_t extra, scan_service_time;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ /*
+ * We are absolutely not allowed to send a scan command when another
+ * scan command is pending.
+ */
+ if (sc->sc_is_scanning) {
+ device_printf(sc->sc_dev, "%s: called whilst scanning!\n",
+ __func__);
+ return (EAGAIN);
+ }
+
+ /* Assign the scan channel */
+ c = ic->ic_curchan;
+
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
buf = malloc(IWN_SCAN_MAXSZ, M_DEVBUF, M_NOWAIT | M_ZERO);
if (buf == NULL) {
@@ -5555,13 +6644,29 @@ iwn_scan(struct iwn_softc *sc)
*/
hdr->quiet_time = htole16(10); /* timeout in milliseconds */
hdr->quiet_threshold = htole16(1); /* min # of packets */
+ /*
+ * Max needs to be greater than active and passive and quiet!
+ * It's also in microseconds!
+ */
+ hdr->max_svc = htole32(250 * 1024);
+
+ /*
+ * Reset scan: interval=100
+ * Normal scan: interval=becaon interval
+ * suspend_time: 100 (TU)
+ *
+ */
+ extra = (100 /* suspend_time */ / 100 /* beacon interval */) << 22;
+ //scan_service_time = extra | ((100 /* susp */ % 100 /* int */) * 1024);
+ scan_service_time = (4 << 22) | (100 * 1024); /* Hardcode for now! */
+ hdr->pause_svc = htole32(scan_service_time);
/* Select antennas for scanning. */
rxchain =
IWN_RXCHAIN_VALID(sc->rxchainmask) |
IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask) |
IWN_RXCHAIN_DRIVER_FORCE;
- if (IEEE80211_IS_CHAN_A(ic->ic_curchan) &&
+ if (IEEE80211_IS_CHAN_A(c) &&
sc->hw_type == IWN_HW_REV_TYPE_4965) {
/* Ant A must be avoided in 5GHz because of an HW bug. */
rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B);
@@ -5575,7 +6680,7 @@ iwn_scan(struct iwn_softc *sc)
tx->id = sc->broadcast_id;
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
- if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) {
+ if (IEEE80211_IS_CHAN_5GHZ(c)) {
/* Send probe requests at 6Mbps. */
tx->rate = htole32(0xd);
rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
@@ -5594,12 +6699,35 @@ iwn_scan(struct iwn_softc *sc)
txant = IWN_LSB(sc->txchainmask);
tx->rate |= htole32(IWN_RFLAG_ANT(txant));
+ /*
+ * Only do active scanning if we're announcing a probe request
+ * for a given SSID (or more, if we ever add it to the driver.)
+ */
+ is_active = 0;
+
+ /*
+ * If we're scanning for a specific SSID, add it to the command.
+ *
+ * XXX maybe look at adding support for scanning multiple SSIDs?
+ */
essid = (struct iwn_scan_essid *)(tx + 1);
- if (ss->ss_ssid[0].len != 0) {
- essid[0].id = IEEE80211_ELEMID_SSID;
- essid[0].len = ss->ss_ssid[0].len;
- memcpy(essid[0].data, ss->ss_ssid[0].ssid, ss->ss_ssid[0].len);
+ if (ss != NULL) {
+ if (ss->ss_ssid[0].len != 0) {
+ essid[0].id = IEEE80211_ELEMID_SSID;
+ essid[0].len = ss->ss_ssid[0].len;
+ memcpy(essid[0].data, ss->ss_ssid[0].ssid, ss->ss_ssid[0].len);
+ }
+
+ DPRINTF(sc, IWN_DEBUG_SCAN, "%s: ssid_len=%d, ssid=%*s\n",
+ __func__,
+ ss->ss_ssid[0].len,
+ ss->ss_ssid[0].len,
+ ss->ss_ssid[0].ssid);
+
+ if (ss->ss_nssid > 0)
+ is_active = 1;
}
+
/*
* Build a probe request frame. Most of the following code is a
* copy & paste of what is done in net80211.
@@ -5625,53 +6753,102 @@ iwn_scan(struct iwn_softc *sc)
/* Set length of probe request. */
tx->len = htole16(frm - (uint8_t *)wh);
- c = ic->ic_curchan;
+ /*
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+ * here instead of IWL_GOOD_CRC_TH_DISABLED.
+ *
+ * This was fixed in later versions along with some other
+ * scan changes, and the threshold behaves as a flag in those
+ * versions.
+ */
+
+ /*
+ * If we're doing active scanning, set the crc_threshold
+ * to a suitable value. This is different to active veruss
+ * passive scanning depending upon the channel flags; the
+ * firmware will obey that particular check for us.
+ */
+ if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN)
+ hdr->crc_threshold = is_active ?
+ IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_DISABLED;
+ else
+ hdr->crc_threshold = is_active ?
+ IWN_GOOD_CRC_TH_DEFAULT : IWN_GOOD_CRC_TH_NEVER;
+
chan = (struct iwn_scan_chan *)frm;
chan->chan = htole16(ieee80211_chan2ieee(ic, c));
chan->flags = 0;
if (ss->ss_nssid > 0)
chan->flags |= htole32(IWN_CHAN_NPBREQS(1));
chan->dsp_gain = 0x6e;
+
+ /*
+ * Set the passive/active flag depending upon the channel mode.
+ * XXX TODO: take the is_active flag into account as well?
+ */
+ if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
+ chan->flags |= htole32(IWN_CHAN_PASSIVE);
+ else
+ chan->flags |= htole32(IWN_CHAN_ACTIVE);
+
+ /*
+ * Calculate the active/passive dwell times.
+ */
+
+ dwell_active = iwn_get_active_dwell_time(sc, c, ss->ss_nssid);
+ dwell_passive = iwn_get_passive_dwell_time(sc, c);
+
+ /* Make sure they're valid */
+ if (dwell_passive <= dwell_active)
+ dwell_passive = dwell_active + 1;
+
+ chan->active = htole16(dwell_active);
+ chan->passive = htole16(dwell_passive);
+
if (IEEE80211_IS_CHAN_5GHZ(c) &&
!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
chan->rf_gain = 0x3b;
- chan->active = htole16(24);
- chan->passive = htole16(110);
- chan->flags |= htole32(IWN_CHAN_ACTIVE);
} else if (IEEE80211_IS_CHAN_5GHZ(c)) {
chan->rf_gain = 0x3b;
- chan->active = htole16(24);
- if (sc->rxon->associd)
- chan->passive = htole16(78);
- else
- chan->passive = htole16(110);
- hdr->crc_threshold = 0xffff;
} else if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
chan->rf_gain = 0x28;
- chan->active = htole16(36);
- chan->passive = htole16(120);
- chan->flags |= htole32(IWN_CHAN_ACTIVE);
} else {
chan->rf_gain = 0x28;
- chan->active = htole16(36);
- if (sc->rxon->associd)
- chan->passive = htole16(88);
- else
- chan->passive = htole16(120);
- hdr->crc_threshold = 0xffff;
}
DPRINTF(sc, IWN_DEBUG_STATE,
"%s: chan %u flags 0x%x rf_gain 0x%x "
- "dsp_gain 0x%x active 0x%x passive 0x%x\n", __func__,
+ "dsp_gain 0x%x active %d passive %d scan_svc_time %d crc 0x%x "
+ "isactive=%d numssid=%d\n", __func__,
chan->chan, chan->flags, chan->rf_gain, chan->dsp_gain,
- chan->active, chan->passive);
+ dwell_active, dwell_passive, scan_service_time,
+ hdr->crc_threshold, is_active, ss->ss_nssid);
hdr->nchan++;
chan++;
buflen = (uint8_t *)chan - buf;
hdr->len = htole16(buflen);
+ if (sc->sc_is_scanning) {
+ device_printf(sc->sc_dev,
+ "%s: called with is_scanning set!\n",
+ __func__);
+ }
+ sc->sc_is_scanning = 1;
+
DPRINTF(sc, IWN_DEBUG_STATE, "sending scan command nchan=%d\n",
hdr->nchan);
error = iwn_cmd(sc, IWN_CMD_SCAN, buf, buflen, 1);
@@ -5712,12 +6889,16 @@ iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap)
sc->rxon->ofdm_mask = 0;
} else {
/* Assume 802.11b/g. */
- sc->rxon->cck_mask = 0x0f;
+ sc->rxon->cck_mask = 0x03;
sc->rxon->ofdm_mask = 0x15;
}
DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n",
sc->rxon->chan, sc->rxon->flags, sc->rxon->cck_mask,
sc->rxon->ofdm_mask);
+ if (sc->sc_is_scanning)
+ device_printf(sc->sc_dev,
+ "%s: is_scanning set, before RXON\n",
+ __func__);
error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
if (error != 0) {
device_printf(sc->sc_dev, "%s: RXON command failed, error %d\n",
@@ -5813,6 +6994,10 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
sc->rxon->filter |= htole32(IWN_FILTER_BSS);
DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x\n",
sc->rxon->chan, sc->rxon->flags);
+ if (sc->sc_is_scanning)
+ device_printf(sc->sc_dev,
+ "%s: is_scanning set, before RXON\n",
+ __func__);
error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1);
if (error != 0) {
device_printf(sc->sc_dev,
@@ -6211,10 +7396,10 @@ iwn5000_query_calibration(struct iwn_softc *sc)
int error;
memset(&cmd, 0, sizeof cmd);
- cmd.ucode.once.enable = 0xffffffff;
- cmd.ucode.once.start = 0xffffffff;
- cmd.ucode.once.send = 0xffffffff;
- cmd.ucode.flags = 0xffffffff;
+ cmd.ucode.once.enable = htole32(0xffffffff);
+ cmd.ucode.once.start = htole32(0xffffffff);
+ cmd.ucode.once.send = htole32(0xffffffff);
+ cmd.ucode.flags = htole32(0xffffffff);
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending calibration query\n",
__func__);
error = iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof cmd, 0);
@@ -6236,9 +7421,20 @@ iwn5000_send_calibration(struct iwn_softc *sc)
{
int idx, error;
- for (idx = 0; idx < 5; idx++) {
- if (sc->calibcmd[idx].buf == NULL)
- continue; /* No results available. */
+ for (idx = 0; idx < IWN5000_PHY_CALIB_MAX_RESULT; idx++) {
+ if (!(sc->base_params->calib_need & (1<<idx))) {
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE,
+ "No need of calib %d\n",
+ idx);
+ continue; /* no need for this calib */
+ }
+ if (sc->calibcmd[idx].buf == NULL) {
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE,
+ "Need calib idx : %d but no available data\n",
+ idx);
+ continue;
+ }
+
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
"send calibration result idx=%d len=%d\n", idx,
sc->calibcmd[idx].len);
@@ -6259,7 +7455,7 @@ iwn5000_send_wimax_coex(struct iwn_softc *sc)
{
struct iwn5000_wimax_coex wimax;
-#ifdef notyet
+#if 0
if (sc->hw_type == IWN_HW_REV_TYPE_6050) {
/* Enable WiMAX coexistence for combo adapters. */
wimax.flags =
@@ -6315,6 +7511,33 @@ iwn5000_temp_offset_calib(struct iwn_softc *sc)
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
}
+static int
+iwn5000_temp_offset_calibv2(struct iwn_softc *sc)
+{
+ struct iwn5000_phy_calib_temp_offsetv2 cmd;
+
+ memset(&cmd, 0, sizeof cmd);
+ cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET;
+ cmd.ngroups = 1;
+ cmd.isvalid = 1;
+ if (sc->eeprom_temp != 0) {
+ cmd.offset_low = htole16(sc->eeprom_temp);
+ cmd.offset_high = htole16(sc->eeprom_temp_high);
+ } else {
+ cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);
+ cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);
+ }
+ cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage);
+
+ DPRINTF(sc, IWN_DEBUG_CALIBRATE,
+ "setting radio sensor low offset to %d, high offset to %d, voltage to %d\n",
+ le16toh(cmd.offset_low),
+ le16toh(cmd.offset_high),
+ le16toh(cmd.burnt_voltage_ref));
+
+ return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+}
+
/*
* This function is called after the runtime firmware notifies us of its
* readiness (called in a process context).
@@ -6400,7 +7623,10 @@ iwn5000_post_alive(struct iwn_softc *sc)
IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY);
/* Enable chain mode for all queues, except command queue. */
- iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef);
+ if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT)
+ iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffdf);
+ else
+ iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL, 0xfffef);
iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL, 0);
for (qid = 0; qid < IWN5000_NTXQUEUES; qid++) {
@@ -6421,10 +7647,20 @@ iwn5000_post_alive(struct iwn_softc *sc)
iwn_prph_write(sc, IWN5000_SCHED_TXFACT, 0xff);
/* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
- for (qid = 0; qid < 7; qid++) {
- static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
- iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
- IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ if (sc->sc_flags & IWN_FLAG_PAN_SUPPORT) {
+ /* Mark TX rings as active. */
+ for (qid = 0; qid < 11; qid++) {
+ static uint8_t qid2fifo[] = { 3, 2, 1, 0, 0, 4, 2, 5, 4, 7, 5 };
+ iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
+ IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ }
+ } else {
+ /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
+ for (qid = 0; qid < 7; qid++) {
+ static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
+ iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid),
+ IWN5000_TXQ_STATUS_ACTIVE | qid2fifo[qid]);
+ }
}
iwn_nic_unlock(sc);
@@ -6669,6 +7905,8 @@ iwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw)
ptr = (const uint32_t *)fw->data;
rev = le32toh(*ptr++);
+ sc->ucode_rev = rev;
+
/* Check firmware API version. */
if (IWN_FW_API(rev) <= 1) {
device_printf(sc->sc_dev,
@@ -6734,6 +7972,7 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
}
DPRINTF(sc, IWN_DEBUG_RESET, "FW: \"%.64s\", build 0x%x\n", hdr->descr,
le32toh(hdr->build));
+ sc->ucode_rev = le32toh(hdr->rev);
/*
* Select the closest supported alternative that is less than
@@ -6789,7 +8028,7 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
sc->sc_flags |= IWN_FLAG_ENH_SENS;
break;
case IWN_FW_TLV_PHY_CALIB:
- tmp = htole32(*ptr);
+ tmp = le32toh(*ptr);
if (tmp < 253) {
sc->reset_noise_gain = tmp;
sc->noise_gain = tmp + 1;
@@ -6800,8 +8039,16 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
DPRINTF(sc, IWN_DEBUG_RESET,
"PAN Support found: %d\n", 1);
break;
- case IWN_FW_TLV_FLAGS :
- sc->tlv_feature_flags = htole32(*ptr);
+ case IWN_FW_TLV_FLAGS:
+ if (len < sizeof(uint32_t))
+ break;
+ if (len % sizeof(uint32_t))
+ break;
+ sc->tlv_feature_flags = le32toh(*ptr);
+ DPRINTF(sc, IWN_DEBUG_RESET,
+ "%s: feature: 0x%08x\n",
+ __func__,
+ sc->tlv_feature_flags);
break;
case IWN_FW_TLV_PBREQ_MAXLEN:
case IWN_FW_TLV_RUNT_EVTLOG_PTR:
@@ -6873,6 +8120,8 @@ iwn_read_firmware(struct iwn_softc *sc)
return error;
}
+ device_printf(sc->sc_dev, "%s: ucode rev=0x%08x\n", __func__, sc->ucode_rev);
+
/* Make sure text and data sections fit in hardware memory. */
if (fw->main.textsz > sc->fw_text_maxsz ||
fw->main.datasz > sc->fw_data_maxsz ||
@@ -6937,9 +8186,8 @@ iwn_apm_init(struct iwn_softc *sc)
else
IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
- if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
- sc->hw_type <= IWN_HW_REV_TYPE_1000)
- IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT);
+ if (sc->base_params->pll_cfg_val)
+ IWN_SETBITS(sc, IWN_ANA_PLL, sc->base_params->pll_cfg_val);
/* Wait for clock stabilization before accessing prph. */
if ((error = iwn_clock_wait(sc)) != 0)
@@ -7051,13 +8299,13 @@ iwn5000_nic_config(struct iwn_softc *sc)
/* Use internal power amplifier only. */
IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);
}
- if ((sc->hw_type == IWN_HW_REV_TYPE_6050 ||
- sc->hw_type == IWN_HW_REV_TYPE_6005) && sc->calib_ver >= 6) {
+ if (sc->base_params->additional_nic_config && sc->calib_ver >= 6) {
/* Indicate that ROM calibration version is >=6. */
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);
}
- if (sc->hw_type == IWN_HW_REV_TYPE_6005)
- IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);
+ if (sc->base_params->additional_gp_drv_bit)
+ IWN_SETBITS(sc, IWN_GP_DRIVER,
+ sc->base_params->additional_gp_drv_bit);
return 0;
}
@@ -7192,7 +8440,7 @@ iwn_hw_init(struct iwn_softc *sc)
IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL);
/* Enable shadow registers. */
- if (sc->hw_type >= IWN_HW_REV_TYPE_6000)
+ if (sc->base_params->shadow_reg_enable)
IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff);
if ((error = ops->load_firmware(sc)) != 0) {
@@ -7305,6 +8553,44 @@ iwn_radio_off(void *arg0, int pending)
}
static void
+iwn_panicked(void *arg0, int pending)
+{
+ struct iwn_softc *sc = arg0;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ int error;
+
+ if (vap == NULL) {
+ printf("%s: null vap\n", __func__);
+ return;
+ }
+
+ device_printf(sc->sc_dev, "%s: controller panicked, iv_state = %d; "
+ "resetting...\n", __func__, vap->iv_state);
+
+ IWN_LOCK(sc);
+
+ iwn_stop_locked(sc);
+ iwn_init_locked(sc);
+ if (vap->iv_state >= IEEE80211_S_AUTH &&
+ (error = iwn_auth(sc, vap)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to auth state\n", __func__);
+ }
+ if (vap->iv_state >= IEEE80211_S_RUN &&
+ (error = iwn_run(sc, vap)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to run state\n", __func__);
+ }
+
+ /* Only run start once the NIC is in a useful state, like associated */
+ iwn_start_locked(sc->sc_ifp);
+
+ IWN_UNLOCK(sc);
+}
+
+static void
iwn_init_locked(struct iwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
@@ -7396,6 +8682,7 @@ iwn_stop_locked(struct iwn_softc *sc)
IWN_LOCK_ASSERT(sc);
+ sc->sc_is_scanning = 0;
sc->sc_tx_timer = 0;
callout_stop(&sc->watchdog_to);
callout_stop(&sc->calib_to);
@@ -7486,10 +8773,11 @@ iwn_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
struct iwn_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ieee80211com *ic = vap->iv_ic;
int error;
IWN_LOCK(sc);
- error = iwn_scan(sc);
+ error = iwn_scan(sc, vap, ss, ic->ic_curchan);
IWN_UNLOCK(sc);
if (error != 0)
ieee80211_cancel_scan(vap);
diff --git a/sys/dev/iwn/if_iwn_chip_cfg.h b/sys/dev/iwn/if_iwn_chip_cfg.h
new file mode 100644
index 0000000..ea6f3e1
--- /dev/null
+++ b/sys/dev/iwn/if_iwn_chip_cfg.h
@@ -0,0 +1,413 @@
+/*-
+ * Copyright (c) 2013 Cedric GROSS <cg@cgross.info>
+ * Copyright (c) 2011 Intel Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IF_IWN_CHIP_CFG_H__
+#define __IF_IWN_CHIP_CFG_H__
+
+/* ==========================================================================
+ * NIC PARAMETERS
+ *
+ * ==========================================================================
+ */
+
+/*
+ * Flags for managing calibration result. See calib_need
+ * in iwn_base_params struct
+ *
+ * These are bitmasks that determine which indexes in the calibcmd
+ * array are pushed up.
+ */
+#define IWN_FLG_NEED_PHY_CALIB_DC (1<<0)
+#define IWN_FLG_NEED_PHY_CALIB_LO (1<<1)
+#define IWN_FLG_NEED_PHY_CALIB_TX_IQ (1<<2)
+#define IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC (1<<3)
+#define IWN_FLG_NEED_PHY_CALIB_BASE_BAND (1<<4)
+/*
+ * These aren't (yet) included in the calibcmd array, but
+ * are used as flags for which calibrations to use.
+ *
+ * XXX I think they should be named differently and
+ * stuffed in a different member in the config struct!
+ */
+#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET (1<<5)
+#define IWN_FLG_NEED_PHY_CALIB_CRYSTAL (1<<6)
+#define IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 (1<<7)
+
+/*
+ * Each chip has a different threshold for PLCP errors that should trigger a
+ * retune.
+ */
+#define IWN_PLCP_ERR_DEFAULT_THRESHOLD 50
+#define IWN_PLCP_ERR_LONG_THRESHOLD 100
+#define IWN_PLCP_ERR_EXT_LONG_THRESHOLD 200
+
+/*
+ * Define some parameters for managing different NIC.
+ * Refer to linux specific file like iwl-xxxx.c to determine correct value
+ * for NIC.
+ *
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
+ * @shadow_reg_enable: HW shadhow register bit
+ * @no_idle_support: do not support idle mode
+ * @advanced_bt_coexist : Advanced BT management
+ * @bt_session_2 : NIC need a new struct for configure BT coexistence. Needed
+ * only if advanced_bt_coexist is true
+ * @bt_sco_disable :
+ * @additional_nic_config: For 6005 series
+ * @iq_invert : ? But need it for N 2000 series
+ * @regulatory_bands : XXX
+ * @enhanced_TX_power : EEPROM Has advanced TX power options. Set 'True'
+ * if update_enhanced_txpower = iwl_eeprom_enhanced_txpower.
+ * See iwl-agn-devices.c file to determine that(enhanced_txpower)
+ * @need_temp_offset_calib : Need to compute some temp offset for calibration.
+ * @calib_need : Use IWN_FLG_NEED_PHY_CALIB_* flags to specify which
+ * calibration data ucode need. See calib_init_cfg in iwl-xxxx.c
+ * linux kernel file
+ * @support_hostap: Define IEEE80211_C_HOSTAP for ic_caps
+ * @no_multi_vaps: See iwn_vap_create
+ * @additional_gp_drv_bit : Specific bit to defined during nic_config
+ * @bt_mode: BT configuration mode
+ */
+enum bt_mode_enum {
+ IWN_BT_NONE,
+ IWN_BT_SIMPLE,
+ IWN_BT_ADVANCED
+};
+
+struct iwn_base_params {
+ uint32_t pll_cfg_val;
+ const uint16_t max_ll_items;
+#define IWN_OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
+#define IWN_OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
+#define IWN_OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
+#define IWN_OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */
+ const bool shadow_ram_support;
+ const bool shadow_reg_enable;
+ const bool bt_session_2;
+ const bool bt_sco_disable;
+ const bool additional_nic_config;
+ const uint32_t *regulatory_bands;
+ const bool enhanced_TX_power;
+ const uint16_t calib_need;
+ const bool support_hostap;
+ const bool no_multi_vaps;
+ uint8_t additional_gp_drv_bit;
+ enum bt_mode_enum bt_mode;
+ uint32_t plcp_err_threshold;
+};
+
+static const struct iwn_base_params iwn5000_base_params = {
+ .pll_cfg_val = IWN_ANA_PLL_INIT, /* pll_cfg_val; */
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, /* max_ll_items */
+ .shadow_ram_support = false, /* shadow_ram_support */
+ .shadow_reg_enable = false, /* shadow_reg_enable */
+ .bt_session_2 = false, /* bt_session_2 */
+ .bt_sco_disable = true, /* bt_sco_disable */
+ .additional_nic_config = false, /* additional_nic_config */
+ .regulatory_bands = iwn5000_regulatory_bands, /* regulatory_bands */
+ .enhanced_TX_power = false, /* enhanced_TX_power */
+ .calib_need =
+ ( IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false, /* support_hostap */
+ .no_multi_vaps = true, /* no_multi_vaps */
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, /* additional_gp_drv_bit */
+ .bt_mode = IWN_BT_NONE, /* bt_mode */
+ .plcp_err_threshold = IWN_PLCP_ERR_LONG_THRESHOLD,
+};
+
+/*
+ * 4965 support
+ */
+static const struct iwn_base_params iwn4965_base_params = {
+ .pll_cfg_val = 0, /* pll_cfg_val; */
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00, /* max_ll_items - ignored for 4965 */
+ .shadow_ram_support = true, /* shadow_ram_support */
+ .shadow_reg_enable = false, /* shadow_reg_enable */
+ .bt_session_2 = false, /* bt_session_2 XXX unknown? */
+ .bt_sco_disable = true, /* bt_sco_disable XXX unknown? */
+ .additional_nic_config = false, /* additional_nic_config - not for 4965 */
+ .regulatory_bands = iwn5000_regulatory_bands, /* regulatory_bands */
+ .enhanced_TX_power = false, /* enhanced_TX_power - not for 4965 */
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false, /* support_hostap - XXX should work on fixing! */
+ .no_multi_vaps = true, /* no_multi_vaps - XXX should work on fixing! */
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE, /* additional_gp_drv_bit */
+ .bt_mode = IWN_BT_SIMPLE, /* bt_mode */
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+
+static const struct iwn_base_params iwn2000_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_2x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = false,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn2030_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ),
+ .support_hostap = true,
+ .no_multi_vaps = false,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT,
+ .bt_mode = IWN_BT_NONE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+static const struct iwn_base_params iwn2030_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_2x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = false, /* XXX check? */
+ .bt_session_2 = true,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn2030_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2 ),
+ .support_hostap = true,
+ .no_multi_vaps = false,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT,
+ .bt_mode = IWN_BT_ADVANCED,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+static const struct iwn_base_params iwn1000_base_params = {
+ .pll_cfg_val = IWN_ANA_PLL_INIT,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_1000,
+ .shadow_ram_support = false,
+ .shadow_reg_enable = false, /* XXX check? */
+ .bt_session_2 = false,
+ .bt_sco_disable = false,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn5000_regulatory_bands,
+ .enhanced_TX_power = false,
+ .calib_need =
+ ( IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ /* XXX 1000 - no BT */
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_EXT_LONG_THRESHOLD,
+};
+static const struct iwn_base_params iwn_6000_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = false,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+static const struct iwn_base_params iwn_6000i_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+static const struct iwn_base_params iwn_6000g2_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = 0,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+static const struct iwn_base_params iwn_6050_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x50,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = true,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+static const struct iwn_base_params iwn_6150_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x50,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = true,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_6050_1X2,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+/* IWL_DEVICE_6035 & IWL_DEVICE_6030 */
+static const struct iwn_base_params iwn_6000g2b_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ .bt_mode = IWN_BT_ADVANCED,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+/*
+ * 6235 series NICs.
+ */
+static const struct iwn_base_params iwn_6235_base_params = {
+ .pll_cfg_val = 0,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = true,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = true,
+ .regulatory_bands = iwn6000_regulatory_bands,
+ .enhanced_TX_power = true,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND
+ | IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSET ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ /* XXX 1x2? This NIC is 2x2, right? */
+ .additional_gp_drv_bit = IWN_GP_DRIVER_6050_1X2,
+ .bt_mode = IWN_BT_ADVANCED,
+ .plcp_err_threshold = IWN_PLCP_ERR_DEFAULT_THRESHOLD,
+};
+
+static const struct iwn_base_params iwn_5x50_base_params = {
+ .pll_cfg_val = IWN_ANA_PLL_INIT,
+ .max_ll_items = IWN_OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
+ .shadow_reg_enable = false,
+ .bt_session_2 = false,
+ .bt_sco_disable = true,
+ .additional_nic_config = false,
+ .regulatory_bands = iwn5000_regulatory_bands,
+ .enhanced_TX_power =false,
+ .calib_need =
+ (IWN_FLG_NEED_PHY_CALIB_DC
+ | IWN_FLG_NEED_PHY_CALIB_LO
+ | IWN_FLG_NEED_PHY_CALIB_TX_IQ
+ | IWN_FLG_NEED_PHY_CALIB_BASE_BAND ),
+ .support_hostap = false,
+ .no_multi_vaps = true,
+ .additional_gp_drv_bit = IWN_GP_DRIVER_NONE,
+ .bt_mode = IWN_BT_SIMPLE,
+ .plcp_err_threshold = IWN_PLCP_ERR_LONG_THRESHOLD,
+};
+
+#endif /* __IF_IWN_CHIP_CFG_H__ */
diff --git a/sys/dev/iwn/if_iwn_debug.h b/sys/dev/iwn/if_iwn_debug.h
new file mode 100644
index 0000000..2932c7e
--- /dev/null
+++ b/sys/dev/iwn/if_iwn_debug.h
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
+ * Copyright (c) 2011 Intel Corporation
+ * Copyright (c) 2007-2009
+ * Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008
+ * Benjamin Close <benjsc@FreeBSD.org>
+ * Copyright (c) 2008 Sam Leffler, Errno Consulting
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __IF_IWN_DEBUG_H__
+#define __IF_IWN_DEBUG_H__
+
+#ifdef IWN_DEBUG
+enum {
+ IWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
+ IWN_DEBUG_RECV = 0x00000002, /* basic recv operation */
+ IWN_DEBUG_STATE = 0x00000004, /* 802.11 state transitions */
+ IWN_DEBUG_TXPOW = 0x00000008, /* tx power processing */
+ IWN_DEBUG_RESET = 0x00000010, /* reset processing */
+ IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */
+ IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */
+ IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */
+ IWN_DEBUG_INTR = 0x00000100, /* ISR */
+ IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */
+ IWN_DEBUG_NODE = 0x00000400, /* node management */
+ IWN_DEBUG_LED = 0x00000800, /* led management */
+ IWN_DEBUG_CMD = 0x00001000, /* cmd submission */
+ IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
+ IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
+ IWN_DEBUG_SCAN = 0x00008000, /* Scan related operations */
+ IWN_DEBUG_STATS = 0x00010000, /* Statistics updates */
+ IWN_DEBUG_REGISTER = 0x20000000, /* print chipset register */
+ IWN_DEBUG_TRACE = 0x40000000, /* Print begin and start driver function */
+ IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */
+ IWN_DEBUG_ANY = 0xffffffff
+};
+
+#define DPRINTF(sc, m, fmt, ...) do { \
+ if (sc->sc_debug & (m)) \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+
+static const char *
+iwn_intr_str(uint8_t cmd)
+{
+ switch (cmd) {
+ /* Notifications */
+ case IWN_UC_READY: return "UC_READY";
+ case IWN_ADD_NODE_DONE: return "ADD_NODE_DONE";
+ case IWN_TX_DONE: return "TX_DONE";
+ case IWN_START_SCAN: return "START_SCAN";
+ case IWN_STOP_SCAN: return "STOP_SCAN";
+ case IWN_RX_STATISTICS: return "RX_STATS";
+ case IWN_BEACON_STATISTICS: return "BEACON_STATS";
+ case IWN_STATE_CHANGED: return "STATE_CHANGED";
+ case IWN_BEACON_MISSED: return "BEACON_MISSED";
+ case IWN_RX_PHY: return "RX_PHY";
+ case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE";
+ case IWN_RX_DONE: return "RX_DONE";
+
+ /* Command Notifications */
+ case IWN_CMD_RXON: return "IWN_CMD_RXON";
+ case IWN_CMD_RXON_ASSOC: return "IWN_CMD_RXON_ASSOC";
+ case IWN_CMD_EDCA_PARAMS: return "IWN_CMD_EDCA_PARAMS";
+ case IWN_CMD_TIMING: return "IWN_CMD_TIMING";
+ case IWN_CMD_LINK_QUALITY: return "IWN_CMD_LINK_QUALITY";
+ case IWN_CMD_SET_LED: return "IWN_CMD_SET_LED";
+ case IWN5000_CMD_WIMAX_COEX: return "IWN5000_CMD_WIMAX_COEX";
+ case IWN5000_CMD_CALIB_CONFIG: return "IWN5000_CMD_CALIB_CONFIG";
+ case IWN5000_CMD_CALIB_RESULT: return "IWN5000_CMD_CALIB_RESULT";
+ case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE";
+ case IWN_CMD_SET_POWER_MODE: return "IWN_CMD_SET_POWER_MODE";
+ case IWN_CMD_SCAN: return "IWN_CMD_SCAN";
+ case IWN_CMD_SCAN_RESULTS: return "IWN_CMD_SCAN_RESULTS";
+ case IWN_CMD_TXPOWER: return "IWN_CMD_TXPOWER";
+ case IWN_CMD_TXPOWER_DBM: return "IWN_CMD_TXPOWER_DBM";
+ case IWN5000_CMD_TX_ANT_CONFIG: return "IWN5000_CMD_TX_ANT_CONFIG";
+ case IWN_CMD_BT_COEX: return "IWN_CMD_BT_COEX";
+ case IWN_CMD_SET_CRITICAL_TEMP: return "IWN_CMD_SET_CRITICAL_TEMP";
+ case IWN_CMD_SET_SENSITIVITY: return "IWN_CMD_SET_SENSITIVITY";
+ case IWN_CMD_PHY_CALIB: return "IWN_CMD_PHY_CALIB";
+
+ /* Bluetooth commands */
+ case IWN_CMD_BT_COEX_PRIOTABLE: return "IWN_CMD_BT_COEX_PRIOTABLE";
+ case IWN_CMD_BT_COEX_PROT: return "IWN_CMD_BT_COEX_PROT";
+ case IWN_CMD_BT_COEX_NOTIF: return "IWN_CMD_BT_COEX_NOTIF";
+
+ /* PAN commands */
+ case IWN_CMD_WIPAN_PARAMS: return "IWN_CMD_WIPAN_PARAMS";
+ case IWN_CMD_WIPAN_RXON: return "IWN_CMD_WIPAN_RXON";
+ case IWN_CMD_WIPAN_RXON_TIMING: return "IWN_CMD_WIPAN_RXON_TIMING";
+ case IWN_CMD_WIPAN_RXON_ASSOC: return "IWN_CMD_WIPAN_RXON_ASSOC";
+ case IWN_CMD_WIPAN_QOS_PARAM: return "IWN_CMD_WIPAN_QOS_PARAM";
+ case IWN_CMD_WIPAN_WEPKEY: return "IWN_CMD_WIPAN_WEPKEY";
+ case IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH:
+ return "IWN_CMD_WIPAN_P2P_CHANNEL_SWITCH";
+ case IWN_CMD_WIPAN_NOA_NOTIFICATION:
+ return "IWN_CMD_WIPAN_NOA_NOTIFICATION";
+ case IWN_CMD_WIPAN_DEACTIVATION_COMPLETE:
+ return "IWN_CMD_WIPAN_DEACTIVATION_COMPLETE";
+ }
+ return "UNKNOWN INTR NOTIF/CMD";
+}
+#else
+#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
+#endif
+
+#endif /* __IF_IWN_DEBUG_H__ */
diff --git a/sys/dev/iwn/if_iwn_devid.h b/sys/dev/iwn/if_iwn_devid.h
index 23fd0a1..dd08737 100644
--- a/sys/dev/iwn/if_iwn_devid.h
+++ b/sys/dev/iwn/if_iwn_devid.h
@@ -41,6 +41,20 @@
* DEVICE ID BLOCK
* ==========================================================================
*/
+
+/*
+ * --------------------------------------------------------------------------
+ * Device ID for 2x00 series
+ * --------------------------------------------------------------------------
+ */
+#define IWN_DID_2x00_1 0x0890
+#define IWN_DID_2x00_2 0x0891
+/* SubDevice ID */
+#define IWN_SDID_2x00_1 0x4022
+#define IWN_SDID_2x00_2 0x4222
+#define IWN_SDID_2x00_3 0x4422
+#define IWN_SDID_2x00_4 0x4822
+
/*
* --------------------------------------------------------------------------
* Device ID for 2x30 series
@@ -214,6 +228,31 @@
/*
* --------------------------------------------------------------------------
+ * Device ID for 105 Series
+ * --------------------------------------------------------------------------
+ */
+#define IWN_DID_105_1 0x0894
+#define IWN_DID_105_2 0x0895
+/* SubDevice ID */
+#define IWN_SDID_105_1 0x0022
+#define IWN_SDID_105_2 0x0222
+#define IWN_SDID_105_3 0x0422
+#define IWN_SDID_105_4 0x0822
+
+/*
+ * --------------------------------------------------------------------------
+ * Device ID for 135 Series
+ * --------------------------------------------------------------------------
+ */
+#define IWN_DID_135_1 0x0892
+#define IWN_DID_135_2 0x0893
+/* SubDevice ID */
+#define IWN_SDID_135_1 0x0062
+#define IWN_SDID_135_2 0x0262
+#define IWN_SDID_135_3 0x0462
+
+/*
+ * --------------------------------------------------------------------------
* Device ID for 5x00 Series
* --------------------------------------------------------------------------
*/
diff --git a/sys/dev/iwn/if_iwn_ioctl.h b/sys/dev/iwn/if_iwn_ioctl.h
new file mode 100644
index 0000000..1acf464
--- /dev/null
+++ b/sys/dev/iwn/if_iwn_ioctl.h
@@ -0,0 +1,25 @@
+/*-
+ * Copyright (c) 2014 Adrian Chadd <adrian@FreeBSD.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+#ifndef __IF_IWN_IOCTL_H__
+#define __IF_IWN_IOCTL_H__
+
+/* XXX how should I pick appropriate ioctl numbers? */
+#define SIOCGIWNSTATS _IOWR('i', 145, struct ifreq)
+#define SIOCZIWNSTATS _IOWR('i', 146, struct ifreq)
+
+#endif /* __IF_IWN_IOCTL_H__ */
diff --git a/sys/dev/iwn/if_iwnreg.h b/sys/dev/iwn/if_iwnreg.h
index e61d0fd..ed65c0b 100644
--- a/sys/dev/iwn/if_iwnreg.h
+++ b/sys/dev/iwn/if_iwnreg.h
@@ -17,6 +17,8 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifndef __IF_IWNREG_H__
+#define __IF_IWNREG_H__
#define IWN_CT_KILL_THRESHOLD 114 /* in Celsius */
#define IWN_CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */
@@ -222,6 +224,7 @@
#define IWN_GP_DRIVER_CALIB_VER6 (1 << 2)
#define IWN_GP_DRIVER_6050_1X2 (1 << 3)
#define IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT (1 << 7)
+#define IWN_GP_DRIVER_NONE 0
/* Possible flags for register IWN_UCODE_GP1_CLR. */
#define IWN_UCODE_GP1_RFKILL (1 << 1)
@@ -486,6 +489,7 @@ struct iwn_tx_cmd {
#define IWN_CMD_TXPOWER_DBM 149
#define IWN_CMD_TXPOWER 151
#define IWN5000_CMD_TX_ANT_CONFIG 152
+#define IWN_CMD_TXPOWER_DBM_V1 152
#define IWN_CMD_BT_COEX 155
#define IWN_CMD_GET_STATISTICS 156
#define IWN_CMD_SET_CRITICAL_TEMP 164
@@ -882,7 +886,7 @@ struct iwn_scan_essid {
struct iwn_scan_hdr {
uint16_t len;
- uint8_t reserved1;
+ uint8_t scan_flags;
uint8_t nchan;
uint16_t quiet_time;
uint16_t quiet_threshold;
@@ -919,17 +923,53 @@ struct iwn_scan_chan {
/* Maximum size of a scan command. */
#define IWN_SCAN_MAXSZ (MCLBYTES - 4)
-#define IWN_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */
-#define IWN_ACTIVE_DWELL_TIME_52 (20)
-#define IWN_ACTIVE_DWELL_FACTOR_24 (3)
-#define IWN_ACTIVE_DWELL_FACTOR_52 (2)
+/*
+ * For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
+ * sending probe req. This should be set long enough to hear probe responses
+ * from more than one AP.
+ */
+#define IWN_ACTIVE_DWELL_TIME_2GHZ (30) /* all times in msec */
+#define IWN_ACTIVE_DWELL_TIME_5GHZ (20)
+#define IWN_ACTIVE_DWELL_FACTOR_2GHZ (3)
+#define IWN_ACTIVE_DWELL_FACTOR_5GHZ (2)
-#define IWN_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */
-#define IWN_PASSIVE_DWELL_TIME_52 (10)
+/*
+ * For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
+ * Must be set longer than active dwell time.
+ * For the most reliable scan, set > AP beacon interval (typically 100msec).
+ */
+#define IWN_PASSIVE_DWELL_TIME_2GHZ (20) /* all times in msec */
+#define IWN_PASSIVE_DWELL_TIME_5GHZ (10)
#define IWN_PASSIVE_DWELL_BASE (100)
#define IWN_CHANNEL_TUNE_TIME (5)
#define IWN_SCAN_CHAN_TIMEOUT 2
+#define IWN_MAX_SCAN_CHANNEL 50
+
+/*
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+ * here instead of IWL_GOOD_CRC_TH_DISABLED.
+ *
+ * This was fixed in later versions along with some other
+ * scan changes, and the threshold behaves as a flag in those
+ * versions.
+ */
+#define IWN_GOOD_CRC_TH_DISABLED 0
+#define IWN_GOOD_CRC_TH_DEFAULT htole16(1)
+#define IWN_GOOD_CRC_TH_NEVER htole16(0xffff)
/* Structure for command IWN_CMD_TXPOWER (4965AGN only.) */
#define IWN_RIDX_MAX 32
@@ -1102,6 +1142,12 @@ struct iwn_enhanced_sensitivity_cmd {
uint16_t reserved;
} __packed;
+/*
+ * Define maximal number of calib result send to runtime firmware
+ * PS: TEMP_OFFSET count for 2 (std and v2)
+ */
+#define IWN5000_PHY_CALIB_MAX_RESULT 8
+
/* Structures for command IWN_CMD_PHY_CALIB. */
struct iwn_phy_calib {
uint8_t code;
@@ -1221,17 +1267,91 @@ struct iwn_ucode_info {
} __packed;
/* Structures for IWN_TX_DONE notification. */
-#define IWN_TX_STATUS_MSK 0xff
-#define TX_STATUS_SUCCESS 0x01
-#define TX_STATUS_DIRECT_DONE 0x02
-
-#define IWN_TX_SUCCESS 0x00
-#define IWN_TX_FAIL 0x80 /* all failures have 0x80 set */
-#define IWN_TX_FAIL_SHORT_LIMIT 0x82 /* too many RTS retries */
-#define IWN_TX_FAIL_LONG_LIMIT 0x83 /* too many retries */
-#define IWN_TX_FAIL_FIFO_UNDERRRUN 0x84 /* tx fifo not kept running */
-#define IWN_TX_FAIL_DEST_IN_PS 0x88 /* sta found in power save */
-#define IWN_TX_FAIL_TX_LOCKED 0x90 /* waiting to see traffic */
+
+/*
+ * TX command response is sent after *agn* transmission attempts.
+ *
+ * both postpone and abort status are expected behavior from uCode. there is
+ * no special operation required from driver; except for RFKILL_FLUSH,
+ * which required tx flush host command to flush all the tx frames in queues
+ */
+#define IWN_TX_STATUS_MSK 0x000000ff
+#define IWN_TX_STATUS_DELAY_MSK 0x00000040
+#define IWN_TX_STATUS_ABORT_MSK 0x00000080
+#define IWN_TX_PACKET_MODE_MSK 0x0000ff00
+#define IWN_TX_FIFO_NUMBER_MSK 0x00070000
+#define IWN_TX_RESERVED 0x00780000
+#define IWN_TX_POWER_PA_DETECT_MSK 0x7f800000
+#define IWN_TX_ABORT_REQUIRED_MSK 0x80000000
+
+/* Success status */
+#define IWN_TX_STATUS_SUCCESS 0x01
+#define IWN_TX_STATUS_DIRECT_DONE 0x02
+
+/* postpone TX */
+#define IWN_TX_STATUS_POSTPONE_DELAY 0x40
+#define IWN_TX_STATUS_POSTPONE_FEW_BYTES 0x41
+#define IWN_TX_STATUS_POSTPONE_BT_PRIO 0x42
+#define IWN_TX_STATUS_POSTPONE_QUIET_PERIOD 0x43
+#define IWN_TX_STATUS_POSTPONE_CALC_TTAK 0x44
+
+/* Failures */
+#define IWN_TX_FAIL 0x80 /* all failures have 0x80 set */
+#define IWN_TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY 0x81
+#define IWN_TX_FAIL_SHORT_LIMIT 0x82 /* too many RTS retries */
+#define IWN_TX_FAIL_LONG_LIMIT 0x83 /* too many retries */
+#define IWN_TX_FAIL_FIFO_UNDERRRUN 0x84 /* tx fifo not kept running */
+#define IWN_TX_STATUS_FAIL_DRAIN_FLOW 0x85
+#define IWN_TX_STATUS_FAIL_RFKILL_FLUSH 0x86
+#define IWN_TX_STATUS_FAIL_LIFE_EXPIRE 0x87
+#define IWN_TX_FAIL_DEST_IN_PS 0x88 /* sta found in power save */
+#define IWN_TX_STATUS_FAIL_HOST_ABORTED 0x89
+#define IWN_TX_STATUS_FAIL_BT_RETRY 0x8a
+#define IWN_TX_FAIL_STA_INVALID 0x8b /* XXX STA invalid (???) */
+#define IWN_TX_STATUS_FAIL_FRAG_DROPPED 0x8c
+#define IWN_TX_STATUS_FAIL_TID_DISABLE 0x8d
+#define IWN_TX_STATUS_FAIL_FIFO_FLUSHED 0x8e
+#define IWN_TX_STATUS_FAIL_INSUFFICIENT_CF_POLL 0x8f
+#define IWN_TX_FAIL_TX_LOCKED 0x90 /* waiting to see traffic */
+#define IWN_TX_STATUS_FAIL_NO_BEACON_ON_RADAR 0x91
+
+/*
+ * TX command response for A-MPDU packet responses.
+ *
+ * The status response is different to the non A-MPDU responses.
+ * In addition, the sequence number is treated as the sequence
+ * number of the TX command, NOT the 802.11 sequence number!
+ */
+#define IWN_AGG_TX_STATE_TRANSMITTED 0x00
+#define IWN_AGG_TX_STATE_UNDERRUN_MSK 0x01
+#define IWN_AGG_TX_STATE_FEW_BYTES_MSK 0x04
+#define IWN_AGG_TX_STATE_ABORT_MSK 0x08
+
+#define IWN_AGG_TX_STATE_LAST_SENT_TTL_MSK 0x10
+#define IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK 0x20
+
+#define IWN_AGG_TX_STATE_SCD_QUERY_MSK 0x80
+
+#define IWN_AGG_TX_STATE_TEST_BAD_CRC32_MSK 0x100
+
+#define IWN_AGG_TX_STATE_RESPONSE_MSK 0x1ff
+#define IWN_AGG_TX_STATE_DUMP_TX_MSK 0x200
+#define IWN_AGG_TX_STATE_DELAY_TX_MSK 0x400
+
+#define IWN_AGG_TX_STATUS_MSK 0x00000fff
+#define IWN_AGG_TX_TRY_MSK 0x0000f000
+
+#define IWN_AGG_TX_STATE_LAST_SENT_MSK \
+ (IWN_AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+ IWN_AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK)
+
+/* # tx attempts for first frame in aggregation */
+#define IWN_AGG_TX_STATE_TRY_CNT_POS 12
+#define IWN_AGG_TX_STATE_TRY_CNT_MSK 0xf000
+
+/* Command ID and sequence number of Tx command for this frame */
+#define IWN_AGG_TX_STATE_SEQ_NUM_POS 16
+#define IWN_AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
struct iwn4965_tx_stat {
uint8_t nframes;
@@ -1358,6 +1478,12 @@ struct iwn_compressed_ba {
uint64_t bitmap;
uint16_t qid;
uint16_t ssn;
+ /* extra fields starting with iwn5000 */
+#if 0
+ uint8_t txed; /* number of frames sent */
+ uint8_t txed_2_done; /* number of frames acked */
+ uint16_t reserved1;
+#endif
} __packed;
/* Structure for IWN_START_SCAN notification. */
@@ -1463,7 +1589,7 @@ struct iwn_rx_ht_phy_stats {
uint32_t good_ampdu_crc32;
uint32_t ampdu;
uint32_t fragment;
- uint32_t reserved;
+ uint32_t unsupport_mcs;
} __packed;
struct iwn_rx_stats {
@@ -1473,6 +1599,20 @@ struct iwn_rx_stats {
struct iwn_rx_ht_phy_stats ht;
} __packed;
+struct iwn_rx_general_stats_bt {
+ struct iwn_rx_general_stats common;
+ /* additional stats for bt */
+ uint32_t num_bt_kills;
+ uint32_t reserved[2];
+} __packed;
+
+struct iwn_rx_stats_bt {
+ struct iwn_rx_phy_stats ofdm;
+ struct iwn_rx_phy_stats cck;
+ struct iwn_rx_general_stats_bt general_bt;
+ struct iwn_rx_ht_phy_stats ht;
+} __packed;
+
struct iwn_tx_stats {
uint32_t preamble;
uint32_t rx_detected;
@@ -1484,7 +1624,7 @@ struct iwn_tx_stats {
uint32_t exp_ack;
uint32_t ack;
uint32_t msdu;
- uint32_t busrt_err1;
+ uint32_t burst_err1;
uint32_t burst_err2;
uint32_t cts_collision;
uint32_t ack_collision;
@@ -1498,15 +1638,21 @@ struct iwn_tx_stats {
uint32_t underrun;
uint32_t bt_ht_kill;
uint32_t rx_ba_resp;
- uint32_t reserved[2];
+ /*
+ * 6000 series only - LSB=ant A, ant B, ant C, MSB=reserved
+ * TX power on chain in 1/2 dBm.
+ */
+ uint32_t tx_power;
+ uint32_t reserved[1];
} __packed;
struct iwn_general_stats {
- uint32_t temp;
- uint32_t temp_m;
+ uint32_t temp; /* radio temperature */
+ uint32_t temp_m; /* radio voltage */
uint32_t burst_check;
uint32_t burst;
- uint32_t reserved1[4];
+ uint32_t wait_for_silence_timeout_cnt;
+ uint32_t reserved1[3];
uint32_t sleep;
uint32_t slot_out;
uint32_t slot_idle;
@@ -1517,7 +1663,11 @@ struct iwn_general_stats {
uint32_t probe;
uint32_t reserved2[2];
uint32_t rx_enabled;
- uint32_t reserved3[3];
+ /*
+ * This is the number of times we have to re-tune
+ * in order to get out of bad PHY status.
+ */
+ uint32_t num_of_sos_states;
} __packed;
struct iwn_stats {
@@ -1525,8 +1675,30 @@ struct iwn_stats {
struct iwn_rx_stats rx;
struct iwn_tx_stats tx;
struct iwn_general_stats general;
+ uint32_t reserved1[2];
} __packed;
+struct iwn_bt_activity_stats {
+ /* Tx statistics */
+ uint32_t hi_priority_tx_req_cnt;
+ uint32_t hi_priority_tx_denied_cnt;
+ uint32_t lo_priority_tx_req_cnt;
+ uint32_t lo_priority_tx_denied_cnt;
+ /* Rx statistics */
+ uint32_t hi_priority_rx_req_cnt;
+ uint32_t hi_priority_rx_denied_cnt;
+ uint32_t lo_priority_rx_req_cnt;
+ uint32_t lo_priority_rx_denied_cnt;
+} __packed;
+
+struct iwn_stats_bt {
+ uint32_t flags;
+ struct iwn_rx_stats_bt rx_bt;
+ struct iwn_tx_stats tx;
+ struct iwn_general_stats general;
+ struct iwn_bt_activity_stats activity;
+ uint32_t reserved1[2];
+};
/* Firmware error dump. */
struct iwn_fw_dump {
@@ -1564,7 +1736,7 @@ struct iwn_fw_tlv {
#define IWN_FW_TLV_INIT_DATA 4
#define IWN_FW_TLV_BOOT_TEXT 5
#define IWN_FW_TLV_PBREQ_MAXLEN 6
-#define IWN_FW_TLV_PAN 7
+#define IWN_FW_TLV_PAN 7
#define IWN_FW_TLV_RUNT_EVTLOG_PTR 8
#define IWN_FW_TLV_RUNT_EVTLOG_SIZE 9
#define IWN_FW_TLV_RUNT_ERRLOG_PTR 10
@@ -1575,7 +1747,7 @@ struct iwn_fw_tlv {
#define IWN_FW_TLV_PHY_CALIB 15
#define IWN_FW_TLV_WOWLAN_INST 16
#define IWN_FW_TLV_WOWLAN_DATA 17
-#define IWN_FW_TLV_FLAGS 18
+#define IWN_FW_TLV_FLAGS 18
uint16_t alt;
uint32_t len;
@@ -1590,6 +1762,60 @@ struct iwn_fw_tlv {
#define IWN5000_FWSZ IWN5000_FW_TEXT_MAXSZ
/*
+ * Microcode flags TLV (18.)
+ */
+
+/**
+ * enum iwn_ucode_tlv_flag - ucode API flags
+ * @IWN_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
+ * was a separate TLV but moved here to save space.
+ * @IWN_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ * treats good CRC threshold as a boolean
+ * @IWN_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWN_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ * @IWN_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
+ * @IWN_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
+ * @IWN_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
+ * offload profile config command.
+ * @IWN_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
+ * @IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
+ * @IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
+ * (rather than two) IPv6 addresses
+ * @IWN_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
+ * @IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
+ * from the probe request template.
+ * @IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping
+ * connection when going back to D0
+ * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
+ * @IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
+ * @IWN_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.
+ * @IWN_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
+ * @IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
+ * containing CAM (Continuous Active Mode) indication.
+ */
+enum iwn_ucode_tlv_flag {
+ IWN_UCODE_TLV_FLAGS_PAN = (1 << 0),
+ IWN_UCODE_TLV_FLAGS_NEWSCAN = (1 << 1),
+ IWN_UCODE_TLV_FLAGS_MFP = (1 << 2),
+ IWN_UCODE_TLV_FLAGS_P2P = (1 << 3),
+ IWN_UCODE_TLV_FLAGS_DW_BC_TABLE = (1 << 4),
+ IWN_UCODE_TLV_FLAGS_NEWBT_COEX = (1 << 5),
+ IWN_UCODE_TLV_FLAGS_UAPSD = (1 << 6),
+ IWN_UCODE_TLV_FLAGS_SHORT_BL = (1 << 7),
+ IWN_UCODE_TLV_FLAGS_RX_ENERGY_API = (1 << 8),
+ IWN_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = (1 << 9),
+ IWN_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = (1 << 10),
+ IWN_UCODE_TLV_FLAGS_BF_UPDATED = (1 << 11),
+ IWN_UCODE_TLV_FLAGS_NO_BASIC_SSID = (1 << 12),
+ IWN_UCODE_TLV_FLAGS_D3_CONTINUITY_API = (1 << 14),
+ IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = (1 << 15),
+ IWN_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = (1 << 16),
+ IWN_UCODE_TLV_FLAGS_SCHED_SCAN = (1 << 17),
+ IWN_UCODE_TLV_FLAGS_STA_KEY_CMD = (1 << 19),
+ IWN_UCODE_TLV_FLAGS_DEVICE_PS_CMD = (1 << 20),
+};
+
+/*
* Offsets into EEPROM.
*/
#define IWN_EEPROM_MAC 0x015
@@ -1731,6 +1957,16 @@ static const uint32_t iwn1000_regulatory_bands[IWN_NBANDS] = {
IWN5000_EEPROM_NO_HT40,
};
+static const uint32_t iwn2030_regulatory_bands[IWN_NBANDS] = {
+ IWN5000_EEPROM_BAND1,
+ IWN5000_EEPROM_BAND2,
+ IWN5000_EEPROM_BAND3,
+ IWN5000_EEPROM_BAND4,
+ IWN5000_EEPROM_BAND5,
+ IWN6000_EEPROM_BAND6,
+ IWN5000_EEPROM_BAND7
+};
+
#define IWN_CHAN_BANDS_COUNT 7
#define IWN_MAX_CHAN_PER_BAND 14
static const struct iwn_chan_band {
@@ -1757,8 +1993,8 @@ static const uint8_t iwn_bss_ac_to_queue[] = {
static const uint8_t iwn_pan_ac_to_queue[] = {
5, 4, 6, 7,
};
-#define IWN1000_OTP_NBLOCKS 3
-#define IWN6000_OTP_NBLOCKS 4
+#define IWN1000_OTP_NBLOCKS 3
+#define IWN6000_OTP_NBLOCKS 4
#define IWN6050_OTP_NBLOCKS 7
/* HW rate indices. */
@@ -1891,6 +2127,7 @@ struct iwn_sensitivity_limits {
uint32_t min_energy_cck;
uint32_t energy_cck;
uint32_t energy_ofdm;
+ uint32_t barker_mrc;
};
/*
@@ -1905,7 +2142,8 @@ static const struct iwn_sensitivity_limits iwn4965_sensitivity_limits = {
200, 400,
97,
100,
- 100
+ 100,
+ 390
};
static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {
@@ -1917,7 +2155,8 @@ static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {
170, 400,
95,
95,
- 95
+ 95,
+ 390
};
static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {
@@ -1929,7 +2168,8 @@ static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {
170, 400,
95,
95,
- 95
+ 95,
+ 390,
};
static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {
@@ -1941,7 +2181,8 @@ static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {
170, 400,
95,
95,
- 95
+ 95,
+ 390,
};
static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
@@ -1953,9 +2194,24 @@ static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
160, 310,
97,
97,
- 100
+ 100,
+ 390
+};
+
+static const struct iwn_sensitivity_limits iwn6235_sensitivity_limits = {
+ 105, 110,
+ 192, 232,
+ 80, 145,
+ 128, 232,
+ 125, 175,
+ 160, 310,
+ 100,
+ 110,
+ 110,
+ 336
};
+
/* Get value from linux kernel 3.2.+ in Drivers/net/wireless/iwlwifi/iwl-2000.c*/
static const struct iwn_sensitivity_limits iwn2030_sensitivity_limits = {
105,110,
@@ -2052,3 +2308,5 @@ static const char * const iwn_fw_errmsg[] = {
#define IWN_BARRIER_READ_WRITE(sc) \
bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, (sc)->sc_sz, \
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+
+#endif /* __IF_IWNREG_H__ */
diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h
index 11a233d..b14158b 100644
--- a/sys/dev/iwn/if_iwnvar.h
+++ b/sys/dev/iwn/if_iwnvar.h
@@ -163,6 +163,7 @@ struct iwn_calib_state {
uint32_t bad_plcp_cck;
uint32_t fa_cck;
uint32_t low_fa;
+ uint32_t bad_plcp_ht;
uint8_t cck_state;
#define IWN_CCK_STATE_INIT 0
#define IWN_CCK_STATE_LOFA 1
@@ -249,6 +250,7 @@ struct iwn_softc {
#define IWN_FLAG_ENH_SENS (1 << 7)
#define IWN_FLAG_ADV_BTCOEX (1 << 8)
#define IWN_FLAG_PAN_SUPPORT (1 << 9)
+#define IWN_FLAG_BTCOEX (1 << 10)
uint8_t hw_type;
/* subdevice_id used to adjust configuration */
@@ -306,14 +308,20 @@ struct iwn_softc {
struct task sc_reinit_task;
struct task sc_radioon_task;
struct task sc_radiooff_task;
+ struct task sc_panic_task;
+ /* Taskqueue */
+ struct taskqueue *sc_tq;
+
+ /* Calibration information */
struct callout calib_to;
int calib_cnt;
struct iwn_calib_state calib;
+ int last_calib_ticks;
struct callout watchdog_to;
struct callout ct_kill_exit_to;
struct iwn_fw_info fw;
- struct iwn_calib_info calibcmd[5];
+ struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT];
uint32_t errptr;
struct iwn_rx_stat last_rx_stat;
@@ -324,6 +332,22 @@ struct iwn_softc {
int ctx;
struct ieee80211vap *ivap[IWN_NUM_RXON_CTX];
+ /* General statistics */
+ /*
+ * The statistics are reset after each channel
+ * change. So it may be zeroed after things like
+ * a background scan.
+ *
+ * So for now, this is just a cheap hack to
+ * expose the last received statistics dump
+ * via an ioctl(). Later versions of this
+ * could expose the last 'n' messages, or just
+ * provide a pipeline for the firmware responses
+ * via something like BPF.
+ */
+ struct iwn_stats last_stat;
+ int last_stat_valid;
+
uint8_t uc_scan_progress;
uint32_t rawtemp;
int temp;
@@ -358,6 +382,9 @@ struct iwn_softc {
int sc_tx_timer;
int sc_scan_timer;
+ /* Are we doing a scan? */
+ int sc_is_scanning;
+
struct ieee80211_tx_ampdu *qid2tap[IWN5000_NTXQUEUES];
int (*sc_ampdu_rx_start)(struct ieee80211_node *,
@@ -385,8 +412,11 @@ struct iwn_softc {
*/
int current_pwrsave_level;
- /* For specifique params */
- struct iwn_base_params *base_params;
+ /* For specific params */
+ const struct iwn_base_params *base_params;
+
+#define IWN_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
+ uint32_t ucode_rev;
};
#define IWN_LOCK_INIT(_sc) \
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index db505ab..409ac72 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -569,15 +570,9 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
ifp->if_baudrate = IF_Mbps(maxrate);
ether_ifattach(ifp, vap->iv_myaddr);
- if (vap->iv_opmode == IEEE80211_M_MONITOR) {
- /* NB: disallow transmit */
- ifp->if_transmit = null_transmit;
- ifp->if_output = null_output;
- } else {
- /* hook output method setup by ether_ifattach */
- vap->iv_output = ifp->if_output;
- ifp->if_output = ieee80211_output;
- }
+ /* hook output method setup by ether_ifattach */
+ vap->iv_output = ifp->if_output;
+ ifp->if_output = ieee80211_output;
/* NB: if_mtu set by ether_ifattach to ETHERMTU */
IEEE80211_LOCK(ic);
@@ -1407,7 +1402,8 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
* rate only when running; otherwise we may have a mismatch
* in which case the rate will not be convertible.
*/
- if (vap->iv_state == IEEE80211_S_RUN) {
+ if (vap->iv_state == IEEE80211_S_RUN ||
+ vap->iv_state == IEEE80211_S_SLEEP) {
imr->ifm_status |= IFM_ACTIVE;
mode = ieee80211_chan2mode(ic->ic_curchan);
} else
@@ -1751,3 +1747,23 @@ ieee80211_mac_hash(const struct ieee80211com *ic,
return c;
}
#undef mix
+
+char
+ieee80211_channel_type_char(const struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_ST(c))
+ return 'S';
+ if (IEEE80211_IS_CHAN_108A(c))
+ return 'T';
+ if (IEEE80211_IS_CHAN_108G(c))
+ return 'G';
+ if (IEEE80211_IS_CHAN_HT(c))
+ return 'n';
+ if (IEEE80211_IS_CHAN_A(c))
+ return 'a';
+ if (IEEE80211_IS_CHAN_ANYG(c))
+ return 'g';
+ if (IEEE80211_IS_CHAN_B(c))
+ return 'b';
+ return 'f';
+}
diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c
index a36df7c..e37863e 100644
--- a/sys/net80211/ieee80211_action.c
+++ b/sys/net80211/ieee80211_action.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index e9e0d30..181b922 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_ageq.c b/sys/net80211/ieee80211_ageq.c
index 018ddc2..b650136 100644
--- a/sys/net80211/ieee80211_ageq.c
+++ b/sys/net80211/ieee80211_ageq.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_alq.c b/sys/net80211/ieee80211_alq.c
index e651574..a52103a 100644
--- a/sys/net80211/ieee80211_alq.c
+++ b/sys/net80211/ieee80211_alq.c
@@ -53,10 +53,8 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
-#include <net/if_dl.h>
-#include <net/if_clone.h>
#include <net/if_media.h>
-#include <net/if_types.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_freebsd.h>
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
index 003b4bc..b1d92c8 100644
--- a/sys/net80211/ieee80211_amrr.c
+++ b/sys/net80211/ieee80211_amrr.c
@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#ifdef INET
#include <netinet/in.h>
@@ -129,6 +131,12 @@ amrr_deinit(struct ieee80211vap *vap)
free(vap->iv_rs, M_80211_RATECTL);
}
+/*
+ * Return whether 11n rates are possible.
+ *
+ * Some 11n devices may return HT information but no HT rates.
+ * Thus, we shouldn't treat them as an 11n node.
+ */
static int
amrr_node_is_11n(struct ieee80211_node *ni)
{
@@ -137,6 +145,8 @@ amrr_node_is_11n(struct ieee80211_node *ni)
return (0);
if (ni->ni_chan == IEEE80211_CHAN_ANYC)
return (0);
+ if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates == 0)
+ return (0);
return (IEEE80211_IS_CHAN_HT(ni->ni_chan));
}
@@ -185,17 +195,18 @@ amrr_node_init(struct ieee80211_node *ni)
rate &= IEEE80211_RATE_VAL;
/* pick initial rate from the rateset - HT or otherwise */
+ /* Pick something low that's likely to succeed */
for (amn->amn_rix = rs->rs_nrates - 1; amn->amn_rix > 0;
amn->amn_rix--) {
/* legacy - anything < 36mbit, stop searching */
- /* 11n - stop at MCS4 / MCS12 / MCS28 */
- if (amrr_node_is_11n(ni) &&
- (rs->rs_rates[amn->amn_rix] & 0x7) < 4)
- break;
- else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72)
+ /* 11n - stop at MCS4 */
+ if (amrr_node_is_11n(ni)) {
+ if ((rs->rs_rates[amn->amn_rix] & 0x1f) < 4)
+ break;
+ } else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72)
break;
- rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
}
+ rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
/* if the rate is an 11n rate, ensure the MCS bit is set */
if (amrr_node_is_11n(ni))
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index 6f7dabf..74e82e5 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c
index 82e525d..5fa9ba4 100644
--- a/sys/net80211/ieee80211_dfs.c
+++ b/sys/net80211/ieee80211_dfs.c
@@ -48,7 +48,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 8c97f1e..ab5b26e 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_clone.h>
#include <net/if_media.h>
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 832a8b0..8cb97b0 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 7f41b27..5fe2e80 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
@@ -154,7 +155,7 @@ SYSCTL_PROC(_net_wlan, OID_AUTO, addba_backoff, CTLTYPE_INT | CTLFLAG_RW,
&ieee80211_addba_backoff, 0, ieee80211_sysctl_msecs_ticks, "I",
"ADDBA request backoff (ms)");
static int ieee80211_addba_maxtries = 3;/* max ADDBA requests before backoff */
-SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLFLAG_RW,
&ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff");
static int ieee80211_bar_timeout = -1; /* timeout waiting for BAR response */
@@ -1046,6 +1047,7 @@ ieee80211_ht_node_init(struct ieee80211_node *ni)
tap = &ni->ni_tx_ampdu[tid];
tap->txa_tid = tid;
tap->txa_ni = ni;
+ tap->txa_lastsample = ticks;
/* NB: further initialization deferred */
}
ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
@@ -1215,6 +1217,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni)
for (tid = 0; tid < WME_NUM_TID; tid++) {
tap = &ni->ni_tx_ampdu[tid];
tap->txa_tid = tid;
+ tap->txa_lastsample = ticks;
}
/* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */
ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
@@ -1690,6 +1693,7 @@ ampdu_tx_setup(struct ieee80211_tx_ampdu *tap)
{
callout_init(&tap->txa_timer, CALLOUT_MPSAFE);
tap->txa_flags |= IEEE80211_AGGR_SETUP;
+ tap->txa_lastsample = ticks;
}
static void
@@ -1717,8 +1721,12 @@ ampdu_tx_stop(struct ieee80211_tx_ampdu *tap)
*/
bar_stop_timer(tap);
- tap->txa_lastsample = 0;
+ /*
+ * Reset packet estimate.
+ */
+ tap->txa_lastsample = ticks;
tap->txa_avgpps = 0;
+
/* NB: clearing NAK means we may re-send ADDBA */
tap->txa_flags &= ~(IEEE80211_AGGR_SETUP | IEEE80211_AGGR_NAK);
}
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 751f1e7..8d57302 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -168,7 +168,7 @@ struct ieee80211_hwmp_state {
static SYSCTL_NODE(_net_wlan, OID_AUTO, hwmp, CTLFLAG_RD, 0,
"IEEE 802.11s HWMP parameters");
static int ieee80211_hwmp_targetonly = 0;
-SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, targetonly, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, targetonly, CTLFLAG_RW,
&ieee80211_hwmp_targetonly, 0, "Set TO bit on generated PREQs");
static int ieee80211_hwmp_pathtimeout = -1;
SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, pathlifetime, CTLTYPE_INT | CTLFLAG_RW,
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 5e95646..6ea4f9b 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_llc.h>
#include <net/if_media.h>
#include <net/if_vlan_var.h>
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 6b668cb..2798d80 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
*/
#include "opt_inet.h"
-#include "opt_ipx.h"
#include "opt_wlan.h"
#include <sys/endian.h>
@@ -44,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/ethernet.h>
@@ -53,11 +53,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/if_ether.h>
#endif
-#ifdef IPX
-#include <netipx/ipx.h>
-#include <netipx/ipx_if.h>
-#endif
-
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_ioctl.h>
#include <net80211/ieee80211_regdomain.h>
@@ -607,7 +602,7 @@ ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
* in use. When in RUN state report the vap-specific channel.
* Otherwise return curchan.
*/
- if (vap->iv_state == IEEE80211_S_RUN)
+ if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
c = vap->iv_bss->ni_chan;
else
c = ic->ic_curchan;
@@ -925,7 +920,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
case IEEE80211_IOC_BSSID:
if (ireq->i_len != IEEE80211_ADDR_LEN)
return EINVAL;
- if (vap->iv_state == IEEE80211_S_RUN) {
+ if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) {
error = copyout(vap->iv_opmode == IEEE80211_M_WDS ?
vap->iv_bss->ni_macaddr : vap->iv_bss->ni_bssid,
ireq->i_data, ireq->i_len);
@@ -1031,7 +1026,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
case IEEE80211_IOC_AMPDU_LIMIT:
if (vap->iv_opmode == IEEE80211_M_HOSTAP)
ireq->i_val = vap->iv_ampdu_rxmax;
- else if (vap->iv_state == IEEE80211_S_RUN)
+ else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
ireq->i_val = MS(vap->iv_bss->ni_htparam,
IEEE80211_HTCAP_MAXRXAMPDU);
else
@@ -1039,7 +1034,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
break;
case IEEE80211_IOC_AMPDU_DENSITY:
if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN)
+ (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
ireq->i_val = MS(vap->iv_bss->ni_htparam,
IEEE80211_HTCAP_MPDUDENSITY);
else
@@ -1113,7 +1108,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
break;
case IEEE80211_IOC_SMPS:
if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN) {
+ (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) {
if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS)
ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC;
else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS)
@@ -1125,7 +1120,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
break;
case IEEE80211_IOC_RIFS:
if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN)
+ (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
ireq->i_val =
(vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0;
else
@@ -1954,7 +1949,7 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
if (IEEE80211_IS_CHAN_NOADHOC(c))
return EINVAL;
}
- if (vap->iv_state == IEEE80211_S_RUN &&
+ if ((vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) &&
vap->iv_bss->ni_chan == c)
return 0; /* NB: nothing to do */
}
@@ -3419,24 +3414,6 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
arp_ifinit(ifp, ifa);
break;
#endif
-#ifdef IPX
- /*
- * XXX - This code is probably wrong,
- * but has been copied many times.
- */
- case AF_IPX: {
- struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
-
- if (ipx_nullhost(*ina))
- ina->x_host = *(union ipx_host *)
- IF_LLADDR(ifp);
- else
- bcopy((caddr_t) ina->x_host.c_host,
- (caddr_t) IF_LLADDR(ifp),
- ETHER_ADDR_LEN);
- /* fall thru... */
- }
-#endif
default:
if ((ifp->if_flags & IFF_UP) == 0) {
ifp->if_flags |= IFF_UP;
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index 5cb80c3..89c024d 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/ethernet.h>
@@ -127,11 +128,11 @@ SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, backofftimeout, CTLTYPE_INT | CTLFLAG_RW,
"Backoff timeout (msec). This is to throutles peering forever when "
"not receving answer or is rejected by a neighbor");
static int ieee80211_mesh_maxretries = 2;
-SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLFLAG_RW,
&ieee80211_mesh_maxretries, 0,
"Maximum retries during peer link establishment");
static int ieee80211_mesh_maxholding = 2;
-SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxholding, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxholding, CTLFLAG_RW,
&ieee80211_mesh_maxholding, 0,
"Maximum times we are allowed to transition to HOLDING state before "
"backinoff during peer link establishment");
@@ -2692,7 +2693,7 @@ mesh_send_action(struct ieee80211_node *ni,
return EIO; /* XXX */
}
- M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
+ M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT);
if (m == NULL) {
ieee80211_free_node(ni);
return ENOMEM;
@@ -3333,7 +3334,7 @@ mesh_airtime_calc(struct ieee80211_node *ni)
/* Error rate in percentage */
/* XXX assuming small failures are ok */
errrate = (((ifp->if_oerrors +
- ifp->if_ierrors) / 100) << M_BITS) / 100;
+ ifp->if_ierrors) / 100) << M_BITS) / 100;
res = (overhead + (nbits / rate)) *
((1 << S_FACTOR) / ((1 << M_BITS) - errrate));
diff --git a/sys/net80211/ieee80211_monitor.c b/sys/net80211/ieee80211_monitor.c
index e324081..f52b0fb 100644
--- a/sys/net80211/ieee80211_monitor.c
+++ b/sys/net80211/ieee80211_monitor.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 4169255..9fc4cd4 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index a1f9965..d828a35 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_llc.h>
#include <net/if_media.h>
#include <net/if_vlan_var.h>
@@ -389,6 +390,19 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m)
/*
* We've resolved the sender, so attempt to transmit it.
*/
+
+ if (vap->iv_state == IEEE80211_S_SLEEP) {
+ /*
+ * In power save; queue frame and then wakeup device
+ * for transmit.
+ */
+ ic->ic_lastdata = ticks;
+ (void) ieee80211_pwrsave(ni, m);
+ ieee80211_free_node(ni);
+ ieee80211_new_state(vap, IEEE80211_S_RUN, 0);
+ return (0);
+ }
+
if (ieee80211_vap_pkt_send_dest(vap, m, ni) != 0)
return (ENOBUFS);
return (0);
@@ -419,24 +433,19 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m)
m_freem(m);
return (EINVAL);
}
- if (vap->iv_state == IEEE80211_S_SLEEP) {
- /*
- * In power save, wakeup device for transmit.
- */
- ieee80211_new_state(vap, IEEE80211_S_RUN, 0);
- m_freem(m);
- return (0);
- }
+
/*
* No data frames go out unless we're running.
* Note in particular this covers CAC and CSA
* states (though maybe we should check muting
* for CSA).
*/
- if (vap->iv_state != IEEE80211_S_RUN) {
+ if (vap->iv_state != IEEE80211_S_RUN &&
+ vap->iv_state != IEEE80211_S_SLEEP) {
IEEE80211_LOCK(ic);
/* re-check under the com lock to avoid races */
- if (vap->iv_state != IEEE80211_S_RUN) {
+ if (vap->iv_state != IEEE80211_S_RUN &&
+ vap->iv_state != IEEE80211_S_SLEEP) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
"%s: ignore queue, in %s state\n",
__func__, ieee80211_state_name[vap->iv_state]);
@@ -476,6 +485,13 @@ ieee80211_vap_qflush(struct ifnet *ifp)
/*
* 802.11 raw output routine.
+ *
+ * XXX TODO: this (and other send routines) should correctly
+ * XXX keep the pwr mgmt bit set if it decides to call into the
+ * XXX driver to send a frame whilst the state is SLEEP.
+ *
+ * Otherwise the peer may decide that we're awake and flood us
+ * with traffic we are still too asleep to receive!
*/
int
ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
@@ -1686,7 +1702,7 @@ ieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs)
/*
* Add an ssid element to a frame.
*/
-static uint8_t *
+uint8_t *
ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len)
{
*frm++ = IEEE80211_ELEMID_SSID;
@@ -2306,18 +2322,33 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
ic->ic_curchan);
frm = ieee80211_add_supportedchannels(frm, ic);
}
+
+ /*
+ * Check the channel - we may be using an 11n NIC with an
+ * 11n capable station, but we're configured to be an 11b
+ * channel.
+ */
if ((vap->iv_flags_ht & IEEE80211_FHT_HT) &&
+ IEEE80211_IS_CHAN_HT(ni->ni_chan) &&
ni->ni_ies.htcap_ie != NULL &&
- ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_HTCAP)
+ ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_HTCAP) {
frm = ieee80211_add_htcap(frm, ni);
+ }
frm = ieee80211_add_wpa(frm, vap);
if ((ic->ic_flags & IEEE80211_F_WME) &&
ni->ni_ies.wme_ie != NULL)
frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
+
+ /*
+ * Same deal - only send HT info if we're on an 11n
+ * capable channel.
+ */
if ((vap->iv_flags_ht & IEEE80211_FHT_HT) &&
+ IEEE80211_IS_CHAN_HT(ni->ni_chan) &&
ni->ni_ies.htcap_ie != NULL &&
- ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_VENDOR)
+ ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_VENDOR) {
frm = ieee80211_add_htcap_vendor(frm, ni);
+ }
#ifdef IEEE80211_SUPPORT_SUPERG
if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS)) {
frm = ieee80211_add_ath(frm,
diff --git a/sys/net80211/ieee80211_phy.c b/sys/net80211/ieee80211_phy.c
index 923266c..4242ac0 100644
--- a/sys/net80211/ieee80211_phy.c
+++ b/sys/net80211/ieee80211_phy.c
@@ -35,12 +35,16 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
+#include <net/route.h>
+
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_phy.h>
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 4542ec5..812cd70 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
@@ -554,3 +555,108 @@ ieee80211_sta_pwrsave(struct ieee80211vap *vap, int enable)
ieee80211_send_nulldata(ieee80211_ref_node(ni));
}
}
+
+/*
+ * Handle being notified that we have data available for us in a TIM/ATIM.
+ *
+ * This may schedule a transition from _SLEEP -> _RUN if it's appropriate.
+ *
+ * In STA mode, we may have put to sleep during scan and need to be dragged
+ * back out of powersave mode.
+ */
+void
+ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /*
+ * Schedule the driver state change. It'll happen at some point soon.
+ * Since the hardware shouldn't know that we're running just yet
+ * (and thus tell the peer that we're awake before we actually wake
+ * up said hardware), we leave the actual node state transition
+ * up to the transition to RUN.
+ *
+ * XXX TODO: verify that the transition to RUN will wake up the
+ * BSS node!
+ */
+ IEEE80211_LOCK(vap->iv_ic);
+ if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) {
+ ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0);
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: TIM=%d; wakeup\n", __func__, set);
+ } else if ((set == 1) && (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)) {
+ /*
+ * XXX only do this if we're in RUN state?
+ */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: wake up from bgscan vap sleep\n",
+ __func__);
+ /*
+ * We may be in BGSCAN mode - this means the VAP is is in STA
+ * mode powersave. If it is, we need to wake it up so we
+ * can process outbound traffic.
+ */
+ vap->iv_sta_ps(vap, 0);
+ }
+ IEEE80211_UNLOCK(vap->iv_ic);
+}
+
+/*
+ * Timer check on whether the VAP has had any transmit activity.
+ *
+ * This may schedule a transition from _RUN -> _SLEEP if it's appropriate.
+ */
+void
+ieee80211_sta_ps_timer_check(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /* XXX lock assert */
+
+ /* For no, only do this in STA mode */
+ if (! (vap->iv_caps & IEEE80211_C_SWSLEEP))
+ goto out;
+
+ if (vap->iv_opmode != IEEE80211_M_STA)
+ goto out;
+
+ /* If we're not at run state, bail */
+ if (vap->iv_state != IEEE80211_S_RUN)
+ goto out;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: lastdata=%llu, ticks=%llu\n",
+ __func__, (unsigned long long) ic->ic_lastdata,
+ (unsigned long long) ticks);
+
+ /* If powersave is disabled on the VAP, don't bother */
+ if (! (vap->iv_flags & IEEE80211_F_PMGTON))
+ goto out;
+
+ /* If we've done any data within our idle interval, bail */
+ /* XXX hard-coded to one second for now, ew! */
+ if (time_after(ic->ic_lastdata + 500, ticks))
+ goto out;
+
+ /*
+ * Signify we're going into power save and transition the
+ * node to powersave.
+ */
+ if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0)
+ vap->iv_sta_ps(vap, 1);
+
+ /*
+ * XXX The driver has to handle the fact that we're going
+ * to sleep but frames may still be transmitted;
+ * hopefully it and/or us will do the right thing and mark any
+ * transmitted frames with PWRMGT set to 1.
+ */
+ ieee80211_new_state_locked(vap, IEEE80211_S_SLEEP, 0);
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: time delta=%d msec\n", __func__,
+ (int) ticks_to_msecs(ticks - ic->ic_lastdata));
+
+out:
+ return;
+}
diff --git a/sys/net80211/ieee80211_power.h b/sys/net80211/ieee80211_power.h
index 55270d2..d9bbaa5 100644
--- a/sys/net80211/ieee80211_power.h
+++ b/sys/net80211/ieee80211_power.h
@@ -79,6 +79,9 @@ int ieee80211_node_psq_age(struct ieee80211_node *);
int ieee80211_pwrsave(struct ieee80211_node *, struct mbuf *);
void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
void ieee80211_sta_pwrsave(struct ieee80211vap *, int enable);
+void ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set);
+void ieee80211_sta_ps_timer_check(struct ieee80211vap *vap);
+/* XXX what's this? */
void ieee80211_power_poll(struct ieee80211com *);
#endif /* _NET80211_IEEE80211_POWER_H_ */
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 6f75130..2f84769 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h> /* XXX for ether_sprintf */
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index 8df5116..3b46ac4 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -149,6 +149,7 @@ struct mbuf *ieee80211_alloc_cts(struct ieee80211com *,
uint8_t *ieee80211_add_rates(uint8_t *, const struct ieee80211_rateset *);
uint8_t *ieee80211_add_xrates(uint8_t *, const struct ieee80211_rateset *);
+uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
uint8_t *ieee80211_add_wpa(uint8_t *, const struct ieee80211vap *);
uint8_t *ieee80211_add_rsn(uint8_t *, const struct ieee80211vap *);
uint8_t *ieee80211_add_qos(uint8_t *, const struct ieee80211_node *);
diff --git a/sys/net80211/ieee80211_radiotap.c b/sys/net80211/ieee80211_radiotap.c
index f06f7e0..5638f52 100644
--- a/sys/net80211/ieee80211_radiotap.c
+++ b/sys/net80211/ieee80211_radiotap.c
@@ -42,8 +42,10 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_llc.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c
index 0ad46bd3..3eff898 100644
--- a/sys/net80211/ieee80211_ratectl.c
+++ b/sys/net80211/ieee80211_ratectl.c
@@ -30,9 +30,12 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/socket.h>
+#include <sys/malloc.h>
#include <net/if.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
+#include <net/route.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_ratectl.h>
diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h
index be81781..5603509 100644
--- a/sys/net80211/ieee80211_ratectl.h
+++ b/sys/net80211/ieee80211_ratectl.h
@@ -62,13 +62,13 @@ void ieee80211_ratectl_set(struct ieee80211vap *, int);
MALLOC_DECLARE(M_80211_RATECTL);
-static void __inline
+static __inline void
ieee80211_ratectl_deinit(struct ieee80211vap *vap)
{
vap->iv_rate->ir_deinit(vap);
}
-static void __inline
+static __inline void
ieee80211_ratectl_node_init(struct ieee80211_node *ni)
{
const struct ieee80211vap *vap = ni->ni_vap;
@@ -76,7 +76,7 @@ ieee80211_ratectl_node_init(struct ieee80211_node *ni)
vap->iv_rate->ir_node_init(ni);
}
-static void __inline
+static __inline void
ieee80211_ratectl_node_deinit(struct ieee80211_node *ni)
{
const struct ieee80211vap *vap = ni->ni_vap;
@@ -92,14 +92,14 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg)
return vap->iv_rate->ir_rate(ni, arg, iarg);
}
-static void __inline
+static __inline void
ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
{
vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2);
}
-static void __inline
+static __inline void
ieee80211_ratectl_tx_update(const struct ieee80211vap *vap,
const struct ieee80211_node *ni, void *arg1, void *arg2, void *arg3)
{
@@ -108,7 +108,7 @@ ieee80211_ratectl_tx_update(const struct ieee80211vap *vap,
vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3);
}
-static void __inline
+static __inline void
ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs)
{
if (vap->iv_rate->ir_setinterval == NULL)
diff --git a/sys/net80211/ieee80211_ratectl_none.c b/sys/net80211/ieee80211_ratectl_none.c
index 0edec44..a0056f3 100644
--- a/sys/net80211/ieee80211_ratectl_none.c
+++ b/sys/net80211/ieee80211_ratectl_none.c
@@ -29,13 +29,16 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#ifdef INET
#include <netinet/in.h>
diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c
index 6bc5e0d..ed7f422 100644
--- a/sys/net80211/ieee80211_regdomain.c
+++ b/sys/net80211/ieee80211_regdomain.c
@@ -34,11 +34,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
diff --git a/sys/net80211/ieee80211_rssadapt.c b/sys/net80211/ieee80211_rssadapt.c
index aaf4057..f230f60 100644
--- a/sys/net80211/ieee80211_rssadapt.c
+++ b/sys/net80211/ieee80211_rssadapt.c
@@ -33,13 +33,17 @@
#include "opt_wlan.h"
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_rssadapt.h>
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index 3a8c24d..f42ddc0 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -40,40 +40,16 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
-#include <net/bpf.h>
-
-struct scan_state {
- struct ieee80211_scan_state base; /* public state */
-
- u_int ss_iflags; /* flags used internally */
-#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */
-#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */
-#define ISCAN_CANCEL 0x0004 /* cancel current scan */
-#define ISCAN_ABORT 0x0008 /* end the scan immediately */
- unsigned long ss_chanmindwell; /* min dwell on curchan */
- unsigned long ss_scanend; /* time scan must stop */
- u_int ss_duration; /* duration for next scan */
- struct task ss_scan_task; /* scan execution */
- struct cv ss_scan_cv; /* scan signal */
- struct callout ss_scan_timer; /* scan timer */
-};
-#define SCAN_PRIVATE(ss) ((struct scan_state *) ss)
+/* XXX until it's implemented as attach ops */
+#include <net80211/ieee80211_scan_sw.h>
-/*
- * Amount of time to go off-channel during a background
- * scan. This value should be large enough to catch most
- * ap's but short enough that we can return on-channel
- * before our listen interval expires.
- *
- * XXX tunable
- * XXX check against configured listen interval
- */
-#define IEEE80211_SCAN_OFFCHANNEL msecs_to_ticks(150)
+#include <net/bpf.h>
/*
* Roaming-related defaults. RSSI thresholds are as returned by the
@@ -92,55 +68,32 @@ struct scan_state {
#define ROAM_RATE_QUARTER_DEFAULT 2*3 /* quarter-width 11a/g bss */
#define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */
-static void scan_curchan(struct ieee80211_scan_state *, unsigned long);
-static void scan_mindwell(struct ieee80211_scan_state *);
-static void scan_signal(void *);
-static void scan_task(void *, int);
-
-MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
-
void
ieee80211_scan_attach(struct ieee80211com *ic)
{
- struct scan_state *ss;
- ss = (struct scan_state *) malloc(sizeof(struct scan_state),
- M_80211_SCAN, M_NOWAIT | M_ZERO);
- if (ss == NULL) {
- ic->ic_scan = NULL;
- return;
- }
- callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0);
- cv_init(&ss->ss_scan_cv, "scan");
- TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss);
- ic->ic_scan = &ss->base;
- ss->base.ss_ic = ic;
-
- ic->ic_scan_curchan = scan_curchan;
- ic->ic_scan_mindwell = scan_mindwell;
+ /*
+ * For now, the swscan module does both the
+ * allocation (so it can pad it) and sets up the net80211
+ * bits.
+ *
+ * I'll split this stuff later.
+ */
+ ieee80211_swscan_attach(ic);
}
void
ieee80211_scan_detach(struct ieee80211com *ic)
{
- struct ieee80211_scan_state *ss = ic->ic_scan;
- if (ss != NULL) {
- IEEE80211_LOCK(ic);
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
- scan_signal(ss);
- IEEE80211_UNLOCK(ic);
- ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
- callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
- KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
- ("scan still running"));
- if (ss->ss_ops != NULL) {
- ss->ss_ops->scan_detach(ss);
- ss->ss_ops = NULL;
- }
- ic->ic_scan = NULL;
- free(SCAN_PRIVATE(ss), M_80211_SCAN);
- }
+ /*
+ * Ideally we'd do the ss_ops detach call here;
+ * but then ieee80211_swscan_detach would need
+ * to be split in two.
+ *
+ * I'll do that later.
+ */
+ ieee80211_swscan_detach(ic);
}
static const struct ieee80211_roamparam defroam[IEEE80211_MODE_MAX] = {
@@ -175,6 +128,8 @@ ieee80211_scan_vattach(struct ieee80211vap *vap)
vap->iv_roaming = IEEE80211_ROAMING_AUTO;
memcpy(vap->iv_roamparms, defroam, sizeof(defroam));
+
+ ieee80211_swscan_vattach(vap);
}
void
@@ -185,11 +140,10 @@ ieee80211_scan_vdetach(struct ieee80211vap *vap)
IEEE80211_LOCK(ic);
ss = ic->ic_scan;
+
+ ieee80211_swscan_vdetach(vap);
+
if (ss != NULL && ss->ss_vap == vap) {
- if (ic->ic_flags & IEEE80211_F_SCAN) {
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
- scan_signal(ss);
- }
if (ss->ss_ops != NULL) {
ss->ss_ops->scan_detach(ss);
ss->ss_ops = NULL;
@@ -260,8 +214,8 @@ ieee80211_scanner_unregister_all(const struct ieee80211_scanner *scan)
* ensure later callbacks find ss_ops set to properly
* reflect current operating mode.
*/
-static void
-scan_update_locked(struct ieee80211vap *vap,
+void
+ieee80211_scan_update_locked(struct ieee80211vap *vap,
const struct ieee80211_scanner *scan)
{
struct ieee80211com *ic = vap->iv_ic;
@@ -306,26 +260,6 @@ scan_update_locked(struct ieee80211vap *vap,
}
}
-static char
-channel_type(const struct ieee80211_channel *c)
-{
- if (IEEE80211_IS_CHAN_ST(c))
- return 'S';
- if (IEEE80211_IS_CHAN_108A(c))
- return 'T';
- if (IEEE80211_IS_CHAN_108G(c))
- return 'G';
- if (IEEE80211_IS_CHAN_HT(c))
- return 'n';
- if (IEEE80211_IS_CHAN_A(c))
- return 'a';
- if (IEEE80211_IS_CHAN_ANYG(c))
- return 'g';
- if (IEEE80211_IS_CHAN_B(c))
- return 'b';
- return 'f';
-}
-
void
ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss)
{
@@ -338,14 +272,14 @@ ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss)
const struct ieee80211_channel *c = ss->ss_chans[i];
printf("%s%u%c", sep, ieee80211_chan2ieee(ic, c),
- channel_type(c));
+ ieee80211_channel_type_char(c));
sep = ", ";
}
}
#ifdef IEEE80211_DEBUG
-static void
-scan_dump(struct ieee80211_scan_state *ss)
+void
+ieee80211_scan_dump(struct ieee80211_scan_state *ss)
{
struct ieee80211vap *vap = ss->ss_vap;
@@ -356,8 +290,8 @@ scan_dump(struct ieee80211_scan_state *ss)
}
#endif /* IEEE80211_DEBUG */
-static void
-copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
+void
+ieee80211_scan_copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
int nssid, const struct ieee80211_scan_ssid ssids[])
{
if (nssid > IEEE80211_SCAN_MAX_SSID) {
@@ -374,8 +308,8 @@ copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
/*
* Start a scan unless one is already going.
*/
-static int
-start_scan_locked(const struct ieee80211_scanner *scan,
+int
+ieee80211_start_scan_locked(const struct ieee80211_scanner *scan,
struct ieee80211vap *vap, int flags, u_int duration,
u_int mindwell, u_int maxdwell,
u_int nssid, const struct ieee80211_scan_ssid ssids[])
@@ -403,10 +337,10 @@ start_scan_locked(const struct ieee80211_scanner *scan,
, flags & IEEE80211_SCAN_ONCE ? ", once" : ""
);
- scan_update_locked(vap, scan);
+ ieee80211_scan_update_locked(vap, scan);
if (ss->ss_ops != NULL) {
if ((flags & IEEE80211_SCAN_NOSSID) == 0)
- copy_ssid(vap, ss, nssid, ssids);
+ ieee80211_scan_copy_ssid(vap, ss, nssid, ssids);
/* NB: top 4 bits for internal use */
ss->ss_flags = flags & 0xfff;
@@ -419,9 +353,9 @@ start_scan_locked(const struct ieee80211_scanner *scan,
if (flags & IEEE80211_SCAN_BGSCAN)
ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
- /* NB: flush frames rx'd before 1st channel change */
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
- SCAN_PRIVATE(ss)->ss_duration = duration;
+ /* Set duration for this particular scan */
+ ieee80211_swscan_set_scan_duration(vap, duration);
+
ss->ss_next = 0;
ss->ss_mindwell = mindwell;
ss->ss_maxdwell = maxdwell;
@@ -429,10 +363,12 @@ start_scan_locked(const struct ieee80211_scanner *scan,
ss->ss_ops->scan_start(ss, vap);
#ifdef IEEE80211_DEBUG
if (ieee80211_msg_scan(vap))
- scan_dump(ss);
+ ieee80211_scan_dump(ss);
#endif /* IEEE80211_DEBUG */
ic->ic_flags |= IEEE80211_F_SCAN;
- ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+
+ /* Start scan task */
+ ieee80211_swscan_run_scan_task(vap);
}
return 1;
} else {
@@ -451,9 +387,7 @@ ieee80211_start_scan(struct ieee80211vap *vap, int flags,
u_int duration, u_int mindwell, u_int maxdwell,
u_int nssid, const struct ieee80211_scan_ssid ssids[])
{
- struct ieee80211com *ic = vap->iv_ic;
const struct ieee80211_scanner *scan;
- int result;
scan = ieee80211_scanner_get(vap->iv_opmode);
if (scan == NULL) {
@@ -464,12 +398,9 @@ ieee80211_start_scan(struct ieee80211vap *vap, int flags,
return 0;
}
- IEEE80211_LOCK(ic);
- result = start_scan_locked(scan, vap, flags, duration,
+ /* XXX ops */
+ return ieee80211_swscan_start_scan(scan, vap, flags, duration,
mindwell, maxdwell, nssid, ssids);
- IEEE80211_UNLOCK(ic);
-
- return result;
}
/*
@@ -516,49 +447,19 @@ ieee80211_check_scan(struct ieee80211vap *vap, int flags,
/* XXX re-use cache contents? e.g. adhoc<->sta */
flags |= IEEE80211_SCAN_FLUSH;
}
- scan_update_locked(vap, scan);
- if (ss->ss_ops != NULL) {
- /* XXX verify ss_ops matches vap->iv_opmode */
- if ((flags & IEEE80211_SCAN_NOSSID) == 0) {
- /*
- * Update the ssid list and mark flags so if
- * we call start_scan it doesn't duplicate work.
- */
- copy_ssid(vap, ss, nssid, ssids);
- flags |= IEEE80211_SCAN_NOSSID;
- }
- if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
- (flags & IEEE80211_SCAN_FLUSH) == 0 &&
- time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
- /*
- * We're not currently scanning and the cache is
- * deemed hot enough to consult. Lock out others
- * by marking IEEE80211_F_SCAN while we decide if
- * something is already in the scan cache we can
- * use. Also discard any frames that might come
- * in while temporarily marked as scanning.
- */
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
- ic->ic_flags |= IEEE80211_F_SCAN;
- /* NB: need to use supplied flags in check */
- ss->ss_flags = flags & 0xff;
- result = ss->ss_ops->scan_end(ss, vap);
+ /*
+ * XXX TODO: separate things out a bit better.
+ * XXX TODO: ops
+ */
+ ieee80211_scan_update_locked(vap, scan);
- ic->ic_flags &= ~IEEE80211_F_SCAN;
- SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD;
- if (result) {
- ieee80211_notify_scan_done(vap);
- IEEE80211_UNLOCK(ic);
- return 1;
- }
- }
- }
- result = start_scan_locked(scan, vap, flags, duration,
+ result = ieee80211_swscan_check_scan(scan, vap, flags, duration,
mindwell, maxdwell, nssid, ssids);
+
IEEE80211_UNLOCK(ic);
- return result;
+ return (result);
}
/*
@@ -581,10 +482,10 @@ ieee80211_check_scan_current(struct ieee80211vap *vap)
int
ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
const struct ieee80211_scanner *scan;
+ // IEEE80211_UNLOCK_ASSERT(sc);
+
scan = ieee80211_scanner_get(vap->iv_opmode);
if (scan == NULL) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
@@ -594,84 +495,14 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
return 0;
}
- IEEE80211_LOCK(ic);
- if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
- u_int duration;
- /*
- * Go off-channel for a fixed interval that is large
- * enough to catch most ap's but short enough that
- * we can return on-channel before our listen interval
- * expires.
- */
- duration = IEEE80211_SCAN_OFFCHANNEL;
-
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: %s scan, ticks %u duration %lu\n", __func__,
- ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",
- ticks, duration);
-
- scan_update_locked(vap, scan);
- if (ss->ss_ops != NULL) {
- ss->ss_vap = vap;
- /*
- * A background scan does not select a new sta; it
- * just refreshes the scan cache. Also, indicate
- * the scan logic should follow the beacon schedule:
- * we go off-channel and scan for a while, then
- * return to the bss channel to receive a beacon,
- * then go off-channel again. All during this time
- * we notify the ap we're in power save mode. When
- * the scan is complete we leave power save mode.
- * If any beacon indicates there are frames pending
- * for us then we drop out of power save mode
- * (and background scan) automatically by way of the
- * usual sta power save logic.
- */
- ss->ss_flags |= IEEE80211_SCAN_NOPICK
- | IEEE80211_SCAN_BGSCAN
- | flags
- ;
- /* if previous scan completed, restart */
- if (ss->ss_next >= ss->ss_last) {
- if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
- vap->iv_stats.is_scan_active++;
- else
- vap->iv_stats.is_scan_passive++;
- /*
- * NB: beware of the scan cache being flushed;
- * if the channel list is empty use the
- * scan_start method to populate it.
- */
- ss->ss_next = 0;
- if (ss->ss_last != 0)
- ss->ss_ops->scan_restart(ss, vap);
- else {
- ss->ss_ops->scan_start(ss, vap);
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(vap))
- scan_dump(ss);
-#endif /* IEEE80211_DEBUG */
- }
- }
- /* NB: flush frames rx'd before 1st channel change */
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
- SCAN_PRIVATE(ss)->ss_duration = duration;
- ss->ss_maxdwell = duration;
- ic->ic_flags |= IEEE80211_F_SCAN;
- ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
- ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
- } else {
- /* XXX msg+stat */
- }
- } else {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: %s scan already in progress\n", __func__,
- ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");
- }
- IEEE80211_UNLOCK(ic);
-
- /* NB: racey, does it matter? */
- return (ic->ic_flags & IEEE80211_F_SCAN);
+ /*
+ * XXX TODO: pull apart the bgscan logic into whatever
+ * belongs here and whatever belongs in the software
+ * scanner.
+ *
+ * XXX TODO: ops
+ */
+ return (ieee80211_swscan_bg_scan(scan, vap, flags));
}
/*
@@ -680,25 +511,9 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
void
ieee80211_cancel_scan(struct ieee80211vap *vap)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
- IEEE80211_LOCK(ic);
- if ((ic->ic_flags & IEEE80211_F_SCAN) &&
- ss->ss_vap == vap &&
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: cancel %s scan\n", __func__,
- ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
- "active" : "passive");
-
- /* clear bg scan NOPICK and mark cancel request */
- ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
- /* wake up the scan task */
- scan_signal(ss);
- }
- IEEE80211_UNLOCK(ic);
+ /* XXX TODO: ops */
+ ieee80211_swscan_cancel_scan(vap);
}
/*
@@ -707,24 +522,9 @@ ieee80211_cancel_scan(struct ieee80211vap *vap)
void
ieee80211_cancel_anyscan(struct ieee80211vap *vap)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
- IEEE80211_LOCK(ic);
- if ((ic->ic_flags & IEEE80211_F_SCAN) &&
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: cancel %s scan\n", __func__,
- ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
- "active" : "passive");
-
- /* clear bg scan NOPICK and mark cancel request */
- ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
- /* wake up the scan task */
- scan_signal(ss);
- }
- IEEE80211_UNLOCK(ic);
+ /* XXX TODO: ops */
+ ieee80211_swscan_cancel_anyscan(vap);
}
/*
@@ -734,13 +534,9 @@ ieee80211_cancel_anyscan(struct ieee80211vap *vap)
void
ieee80211_scan_next(struct ieee80211vap *vap)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
- /* wake up the scan task */
- IEEE80211_LOCK(ic);
- scan_signal(ss);
- IEEE80211_UNLOCK(ic);
+ /* XXX TODO: ops */
+ ieee80211_swscan_scan_next(vap);
}
/*
@@ -753,10 +549,15 @@ ieee80211_scan_done(struct ieee80211vap *vap)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_state *ss;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
IEEE80211_LOCK(ic);
ss = ic->ic_scan;
ss->ss_next = ss->ss_last; /* all channels are complete */
- scan_signal(ss);
+
+ /* XXX TODO: ops */
+ ieee80211_swscan_scan_done(vap);
+
IEEE80211_UNLOCK(ic);
}
@@ -771,293 +572,14 @@ void
ieee80211_probe_curchan(struct ieee80211vap *vap, int force)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
- struct ifnet *ifp = vap->iv_ifp;
- int i;
if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) && !force) {
ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN;
return;
}
- /*
- * Send directed probe requests followed by any
- * broadcast probe request.
- * XXX remove dependence on ic/vap->iv_bss
- */
- for (i = 0; i < ss->ss_nssid; i++)
- ieee80211_send_probereq(vap->iv_bss,
- vap->iv_myaddr, ifp->if_broadcastaddr,
- ifp->if_broadcastaddr,
- ss->ss_ssid[i].ssid, ss->ss_ssid[i].len);
- if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0)
- ieee80211_send_probereq(vap->iv_bss,
- vap->iv_myaddr, ifp->if_broadcastaddr,
- ifp->if_broadcastaddr,
- "", 0);
-}
-/*
- * Scan curchan. If this is an active scan and the channel
- * is not marked passive then send probe request frame(s).
- * Arrange for the channel change after maxdwell ticks.
- */
-static void
-scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
-{
- struct ieee80211vap *vap = ss->ss_vap;
-
- IEEE80211_LOCK(vap->iv_ic);
- if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
- ieee80211_probe_curchan(vap, 0);
- callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
- maxdwell, scan_signal, ss);
- IEEE80211_UNLOCK(vap->iv_ic);
-}
-
-static void
-scan_signal(void *arg)
-{
- struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
-
- IEEE80211_LOCK_ASSERT(ss->ss_ic);
-
- cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv);
-}
-
-/*
- * Handle mindwell requirements completed; initiate a channel
- * change to the next channel asap.
- */
-static void
-scan_mindwell(struct ieee80211_scan_state *ss)
-{
- struct ieee80211com *ic = ss->ss_ic;
-
- IEEE80211_LOCK(ic);
- scan_signal(ss);
- IEEE80211_UNLOCK(ic);
-}
-
-static void
-scan_task(void *arg, int pending)
-{
-#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD)
- struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
- struct ieee80211vap *vap = ss->ss_vap;
- struct ieee80211com *ic = ss->ss_ic;
- struct ieee80211_channel *chan;
- unsigned long maxdwell, scanend;
- int scandone = 0;
-
- IEEE80211_LOCK(ic);
- if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) {
- /* Cancelled before we started */
- goto done;
- }
-
- if (ss->ss_next == ss->ss_last) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: no channels to scan\n", __func__);
- scandone = 1;
- goto done;
- }
-
- if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN) {
- if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
- /* Enable station power save mode */
- vap->iv_sta_ps(vap, 1);
- /*
- * Use an 1ms delay so the null data frame has a chance
- * to go out.
- * XXX Should use M_TXCB mechanism to eliminate this.
- */
- cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv,
- IEEE80211_LOCK_OBJ(ic), hz / 1000);
- if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
- goto done;
- }
- }
-
- scanend = ticks + SCAN_PRIVATE(ss)->ss_duration;
- IEEE80211_UNLOCK(ic);
- ic->ic_scan_start(ic); /* notify driver */
- IEEE80211_LOCK(ic);
-
- for (;;) {
- scandone = (ss->ss_next >= ss->ss_last) ||
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
- if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
- time_after(ticks + ss->ss_mindwell, scanend))
- break;
-
- chan = ss->ss_chans[ss->ss_next++];
-
- /*
- * Watch for truncation due to the scan end time.
- */
- if (time_after(ticks + ss->ss_maxdwell, scanend))
- maxdwell = scanend - ticks;
- else
- maxdwell = ss->ss_maxdwell;
-
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
- __func__,
- ieee80211_chan2ieee(ic, ic->ic_curchan),
- channel_type(ic->ic_curchan),
- ieee80211_chan2ieee(ic, chan), channel_type(chan),
- (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
- (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
- "active" : "passive",
- ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
-
- /*
- * Potentially change channel and phy mode.
- */
- ic->ic_curchan = chan;
- ic->ic_rt = ieee80211_get_ratetable(chan);
- IEEE80211_UNLOCK(ic);
- /*
- * Perform the channel change and scan unlocked so the driver
- * may sleep. Once set_channel returns the hardware has
- * completed the channel change.
- */
- ic->ic_set_channel(ic);
- ieee80211_radiotap_chan_change(ic);
-
- /*
- * Scan curchan. Drivers for "intelligent hardware"
- * override ic_scan_curchan to tell the device to do
- * the work. Otherwise we manage the work outselves;
- * sending a probe request (as needed), and arming the
- * timeout to switch channels after maxdwell ticks.
- *
- * scan_curchan should only pause for the time required to
- * prepare/initiate the hardware for the scan (if at all), the
- * below condvar is used to sleep for the channels dwell time
- * and allows it to be signalled for abort.
- */
- ic->ic_scan_curchan(ss, maxdwell);
- IEEE80211_LOCK(ic);
-
- SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
- /* clear mindwell lock and initial channel change flush */
- SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
-
- if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
- continue;
-
- /* Wait to be signalled to scan the next channel */
- cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
- }
- if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
- goto done;
-
- IEEE80211_UNLOCK(ic);
- ic->ic_scan_end(ic); /* notify driver */
- IEEE80211_LOCK(ic);
-
- /*
- * Since a cancellation may have occured during one of the
- * driver calls (whilst unlocked), update scandone.
- */
- if (scandone == 0 &&
- ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
- /* XXX printf? */
- if_printf(vap->iv_ifp,
- "%s: OOPS! scan cancelled during driver call!\n",
- __func__);
- }
- scandone |= ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0);
-
- /*
- * Record scan complete time. Note that we also do
- * this when canceled so any background scan will
- * not be restarted for a while.
- */
- if (scandone)
- ic->ic_lastscan = ticks;
- /* return to the bss channel */
- if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
- ic->ic_curchan != ic->ic_bsschan) {
- ieee80211_setupcurchan(ic, ic->ic_bsschan);
- IEEE80211_UNLOCK(ic);
- ic->ic_set_channel(ic);
- ieee80211_radiotap_chan_change(ic);
- IEEE80211_LOCK(ic);
- }
- /* clear internal flags and any indication of a pick */
- SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
- ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
-
- /*
- * If not canceled and scan completed, do post-processing.
- * If the callback function returns 0, then it wants to
- * continue/restart scanning. Unfortunately we needed to
- * notify the driver to end the scan above to avoid having
- * rx frames alter the scan candidate list.
- */
- if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 &&
- !ss->ss_ops->scan_end(ss, vap) &&
- (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
- time_before(ticks + ss->ss_mindwell, scanend)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: done, restart "
- "[ticks %u, dwell min %lu scanend %lu]\n",
- __func__,
- ticks, ss->ss_mindwell, scanend);
- ss->ss_next = 0; /* reset to begining */
- if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
- vap->iv_stats.is_scan_active++;
- else
- vap->iv_stats.is_scan_passive++;
-
- ss->ss_ops->scan_restart(ss, vap); /* XXX? */
- ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
- IEEE80211_UNLOCK(ic);
- return;
- }
-
- /* past here, scandone is ``true'' if not in bg mode */
- if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
- scandone = 1;
-
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n",
- __func__, scandone ? "done" : "stopped",
- ticks, ss->ss_mindwell, scanend);
-
- /*
- * Clear the SCAN bit first in case frames are
- * pending on the station power save queue. If
- * we defer this then the dispatch of the frames
- * may generate a request to cancel scanning.
- */
-done:
- ic->ic_flags &= ~IEEE80211_F_SCAN;
- /*
- * Drop out of power save mode when a scan has
- * completed. If this scan was prematurely terminated
- * because it is a background scan then don't notify
- * the ap; we'll either return to scanning after we
- * receive the beacon frame or we'll drop out of power
- * save mode because the beacon indicates we have frames
- * waiting for us.
- */
- if (scandone) {
- vap->iv_sta_ps(vap, 0);
- if (ss->ss_next >= ss->ss_last) {
- ieee80211_notify_scan_done(vap);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
- }
- }
- SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
- ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
- IEEE80211_UNLOCK(ic);
-#undef ISCAN_REP
+ /* XXX TODO: ops */
+ ieee80211_swscan_probe_curchan(vap, force);
}
#ifdef IEEE80211_DEBUG
@@ -1086,8 +608,8 @@ dump_country(const uint8_t *ie)
printf("]");
}
-static void
-dump_probe_beacon(uint8_t subtype, int isnew,
+void
+ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew,
const uint8_t mac[IEEE80211_ADDR_LEN],
const struct ieee80211_scanparams *sp, int rssi)
{
@@ -1118,45 +640,8 @@ ieee80211_add_scan(struct ieee80211vap *vap,
const struct ieee80211_frame *wh,
int subtype, int rssi, int noise)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = ic->ic_scan;
- /* XXX locking */
- /*
- * Frames received during startup are discarded to avoid
- * using scan state setup on the initial entry to the timer
- * callback. This can occur because the device may enable
- * rx prior to our doing the initial channel change in the
- * timer routine.
- */
- if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD)
- return;
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN))
- dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi);
-#endif
- if (ss->ss_ops != NULL &&
- ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise)) {
- /*
- * If we've reached the min dwell time terminate
- * the timer so we'll switch to the next channel.
- */
- if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
- time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: chan %3d%c min dwell met (%u > %lu)\n",
- __func__,
- ieee80211_chan2ieee(ic, ic->ic_curchan),
- channel_type(ic->ic_curchan),
- ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
- SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL;
- /*
- * NB: trigger at next clock tick or wait for the
- * hardware.
- */
- ic->ic_scan_mindwell(ss);
- }
- }
+ return (ieee80211_swscan_add_scan(vap, sp, wh, subtype, rssi, noise));
}
/*
diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h
index 3f13e17..9c2575a 100644
--- a/sys/net80211/ieee80211_scan.h
+++ b/sys/net80211/ieee80211_scan.h
@@ -299,4 +299,18 @@ void ieee80211_scanner_unregister(enum ieee80211_opmode,
const struct ieee80211_scanner *);
void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
const struct ieee80211_scanner *ieee80211_scanner_get(enum ieee80211_opmode);
+void ieee80211_scan_update_locked(struct ieee80211vap *vap,
+ const struct ieee80211_scanner *scan);
+void ieee80211_scan_copy_ssid(struct ieee80211vap *vap,
+ struct ieee80211_scan_state *ss,
+ int nssid, const struct ieee80211_scan_ssid ssids[]);
+void ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew,
+ const uint8_t mac[IEEE80211_ADDR_LEN],
+ const struct ieee80211_scanparams *sp, int rssi);
+int ieee80211_start_scan_locked(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags, u_int duration,
+ u_int mindwell, u_int maxdwell,
+ u_int nssid, const struct ieee80211_scan_ssid ssids[]);
+void ieee80211_scan_dump(struct ieee80211_scan_state *ss);
+
#endif /* _NET80211_IEEE80211_SCAN_H_ */
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index c791ea1..1e87e35 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ethernet.h>
@@ -599,10 +600,12 @@ makescanlist(struct ieee80211_scan_state *ss, struct ieee80211vap *vap,
* so if the desired mode is 11g, then use
* the 11b channel list but upgrade the mode.
*/
- if (vap->iv_des_mode != IEEE80211_MODE_11G ||
- mode != IEEE80211_MODE_11B)
- continue;
- mode = IEEE80211_MODE_11G; /* upgrade */
+ if (vap->iv_des_mode == IEEE80211_MODE_11G) {
+ if (mode == IEEE80211_MODE_11G) /* Skip the G check */
+ continue;
+ else if (mode == IEEE80211_MODE_11B)
+ mode = IEEE80211_MODE_11G; /* upgrade */
+ }
}
} else {
/*
@@ -732,7 +735,7 @@ sta_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
return 0;
}
-/* unalligned little endian access */
+/* unaligned little endian access */
#define LE_READ_2(p) \
((uint16_t) \
((((const uint8_t *)(p))[0] ) | \
diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c
new file mode 100644
index 0000000..bce92a4
--- /dev/null
+++ b/sys/net80211/ieee80211_scan_sw.c
@@ -0,0 +1,872 @@
+/*-
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, 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 DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * IEEE 802.11 scanning support.
+ */
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/condvar.h>
+
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_media.h>
+#include <net/ethernet.h>
+
+#include <net80211/ieee80211_var.h>
+
+#include <net80211/ieee80211_scan_sw.h>
+
+#include <net/bpf.h>
+
+struct scan_state {
+ struct ieee80211_scan_state base; /* public state */
+
+ u_int ss_iflags; /* flags used internally */
+#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */
+#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */
+#define ISCAN_CANCEL 0x0004 /* cancel current scan */
+#define ISCAN_ABORT 0x0008 /* end the scan immediately */
+ unsigned long ss_chanmindwell; /* min dwell on curchan */
+ unsigned long ss_scanend; /* time scan must stop */
+ u_int ss_duration; /* duration for next scan */
+ struct task ss_scan_task; /* scan execution */
+ struct cv ss_scan_cv; /* scan signal */
+ struct callout ss_scan_timer; /* scan timer */
+};
+#define SCAN_PRIVATE(ss) ((struct scan_state *) ss)
+
+/*
+ * Amount of time to go off-channel during a background
+ * scan. This value should be large enough to catch most
+ * ap's but short enough that we can return on-channel
+ * before our listen interval expires.
+ *
+ * XXX tunable
+ * XXX check against configured listen interval
+ */
+#define IEEE80211_SCAN_OFFCHANNEL msecs_to_ticks(150)
+
+/*
+ * Roaming-related defaults. RSSI thresholds are as returned by the
+ * driver (.5dBm). Transmit rate thresholds are IEEE rate codes (i.e
+ * .5M units) or MCS.
+ */
+/* rssi thresholds */
+#define ROAM_RSSI_11A_DEFAULT 14 /* 11a bss */
+#define ROAM_RSSI_11B_DEFAULT 14 /* 11b bss */
+#define ROAM_RSSI_11BONLY_DEFAULT 14 /* 11b-only bss */
+/* transmit rate thresholds */
+#define ROAM_RATE_11A_DEFAULT 2*12 /* 11a bss */
+#define ROAM_RATE_11B_DEFAULT 2*5 /* 11b bss */
+#define ROAM_RATE_11BONLY_DEFAULT 2*1 /* 11b-only bss */
+#define ROAM_RATE_HALF_DEFAULT 2*6 /* half-width 11a/g bss */
+#define ROAM_RATE_QUARTER_DEFAULT 2*3 /* quarter-width 11a/g bss */
+#define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */
+
+static void scan_curchan(struct ieee80211_scan_state *, unsigned long);
+static void scan_mindwell(struct ieee80211_scan_state *);
+static void scan_signal(void *);
+static void scan_task(void *, int);
+
+MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
+
+void
+ieee80211_swscan_attach(struct ieee80211com *ic)
+{
+ struct scan_state *ss;
+
+ ss = (struct scan_state *) malloc(sizeof(struct scan_state),
+ M_80211_SCAN, M_NOWAIT | M_ZERO);
+ if (ss == NULL) {
+ ic->ic_scan = NULL;
+ return;
+ }
+ callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0);
+ cv_init(&ss->ss_scan_cv, "scan");
+ TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss);
+
+ ic->ic_scan = &ss->base;
+ ss->base.ss_ic = ic;
+
+ ic->ic_scan_curchan = scan_curchan;
+ ic->ic_scan_mindwell = scan_mindwell;
+
+ /*
+ * TODO: all of the non-vap scan calls should be methods!
+ */
+}
+
+void
+ieee80211_swscan_detach(struct ieee80211com *ic)
+{
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ if (ss != NULL) {
+ IEEE80211_LOCK(ic);
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
+ ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+ callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
+ KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
+ ("scan still running"));
+
+ /*
+ * For now, do the ss_ops detach here rather
+ * than ieee80211_scan_detach().
+ *
+ * I'll figure out how to cleanly split things up
+ * at a later date.
+ */
+ if (ss->ss_ops != NULL) {
+ ss->ss_ops->scan_detach(ss);
+ ss->ss_ops = NULL;
+ }
+ ic->ic_scan = NULL;
+ free(SCAN_PRIVATE(ss), M_80211_SCAN);
+ }
+}
+
+void
+ieee80211_swscan_vattach(struct ieee80211vap *vap)
+{
+ /* nothing to do for now */
+ /*
+ * TODO: all of the vap scan calls should be methods!
+ */
+
+}
+
+void
+ieee80211_swscan_vdetach(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss;
+
+ IEEE80211_LOCK_ASSERT(ic);
+ ss = ic->ic_scan;
+ if (ss != NULL && ss->ss_vap == vap) {
+ if (ic->ic_flags & IEEE80211_F_SCAN) {
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
+ scan_signal(ss);
+ }
+ }
+}
+
+void
+ieee80211_swscan_set_scan_duration(struct ieee80211vap *vap, u_int duration)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ /* NB: flush frames rx'd before 1st channel change */
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
+ SCAN_PRIVATE(ss)->ss_duration = duration;
+}
+
+void
+ieee80211_swscan_run_scan_task(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+}
+
+/*
+ * Start a scan unless one is already going.
+ *
+ * Called without the comlock held; grab the comlock as appropriate.
+ */
+int
+ieee80211_swscan_start_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags,
+ u_int duration, u_int mindwell, u_int maxdwell,
+ u_int nssid, const struct ieee80211_scan_ssid ssids[])
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ int result;
+
+ IEEE80211_UNLOCK_ASSERT(ic);
+
+ IEEE80211_LOCK(ic);
+ result = ieee80211_start_scan_locked(scan, vap, flags, duration,
+ mindwell, maxdwell, nssid, ssids);
+ IEEE80211_UNLOCK(ic);
+
+ return result;
+}
+
+/*
+ * Check the scan cache for an ap/channel to use; if that
+ * fails then kick off a new scan.
+ *
+ * Called with the comlock held.
+ *
+ * XXX TODO: split out!
+ */
+int
+ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags,
+ u_int duration, u_int mindwell, u_int maxdwell,
+ u_int nssid, const struct ieee80211_scan_ssid ssids[])
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ int result;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ if (ss->ss_ops != NULL) {
+ /* XXX verify ss_ops matches vap->iv_opmode */
+ if ((flags & IEEE80211_SCAN_NOSSID) == 0) {
+ /*
+ * Update the ssid list and mark flags so if
+ * we call start_scan it doesn't duplicate work.
+ */
+ ieee80211_scan_copy_ssid(vap, ss, nssid, ssids);
+ flags |= IEEE80211_SCAN_NOSSID;
+ }
+ if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
+ (flags & IEEE80211_SCAN_FLUSH) == 0 &&
+ time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
+ /*
+ * We're not currently scanning and the cache is
+ * deemed hot enough to consult. Lock out others
+ * by marking IEEE80211_F_SCAN while we decide if
+ * something is already in the scan cache we can
+ * use. Also discard any frames that might come
+ * in while temporarily marked as scanning.
+ */
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
+ ic->ic_flags |= IEEE80211_F_SCAN;
+
+ /* NB: need to use supplied flags in check */
+ ss->ss_flags = flags & 0xff;
+ result = ss->ss_ops->scan_end(ss, vap);
+
+ ic->ic_flags &= ~IEEE80211_F_SCAN;
+ SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD;
+ if (result) {
+ ieee80211_notify_scan_done(vap);
+ return 1;
+ }
+ }
+ }
+ result = ieee80211_start_scan_locked(scan, vap, flags, duration,
+ mindwell, maxdwell, nssid, ssids);
+
+ return result;
+}
+
+/*
+ * Restart a previous scan. If the previous scan completed
+ * then we start again using the existing channel list.
+ */
+int
+ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ /* XXX assert unlocked? */
+ // IEEE80211_UNLOCK_ASSERT(ic);
+
+ IEEE80211_LOCK(ic);
+ if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+ u_int duration;
+ /*
+ * Go off-channel for a fixed interval that is large
+ * enough to catch most ap's but short enough that
+ * we can return on-channel before our listen interval
+ * expires.
+ */
+ duration = IEEE80211_SCAN_OFFCHANNEL;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: %s scan, ticks %u duration %lu\n", __func__,
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",
+ ticks, duration);
+
+ ieee80211_scan_update_locked(vap, scan);
+ if (ss->ss_ops != NULL) {
+ ss->ss_vap = vap;
+ /*
+ * A background scan does not select a new sta; it
+ * just refreshes the scan cache. Also, indicate
+ * the scan logic should follow the beacon schedule:
+ * we go off-channel and scan for a while, then
+ * return to the bss channel to receive a beacon,
+ * then go off-channel again. All during this time
+ * we notify the ap we're in power save mode. When
+ * the scan is complete we leave power save mode.
+ * If any beacon indicates there are frames pending
+ * for us then we drop out of power save mode
+ * (and background scan) automatically by way of the
+ * usual sta power save logic.
+ */
+ ss->ss_flags |= IEEE80211_SCAN_NOPICK
+ | IEEE80211_SCAN_BGSCAN
+ | flags
+ ;
+ /* if previous scan completed, restart */
+ if (ss->ss_next >= ss->ss_last) {
+ if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
+ vap->iv_stats.is_scan_active++;
+ else
+ vap->iv_stats.is_scan_passive++;
+ /*
+ * NB: beware of the scan cache being flushed;
+ * if the channel list is empty use the
+ * scan_start method to populate it.
+ */
+ ss->ss_next = 0;
+ if (ss->ss_last != 0)
+ ss->ss_ops->scan_restart(ss, vap);
+ else {
+ ss->ss_ops->scan_start(ss, vap);
+#ifdef IEEE80211_DEBUG
+ if (ieee80211_msg_scan(vap))
+ ieee80211_scan_dump(ss);
+#endif /* IEEE80211_DEBUG */
+ }
+ }
+ ieee80211_swscan_set_scan_duration(vap, duration);
+ ss->ss_maxdwell = duration;
+ ic->ic_flags |= IEEE80211_F_SCAN;
+ ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+ } else {
+ /* XXX msg+stat */
+ }
+ } else {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: %s scan already in progress\n", __func__,
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");
+ }
+ IEEE80211_UNLOCK(ic);
+
+ /* NB: racey, does it matter? */
+ return (ic->ic_flags & IEEE80211_F_SCAN);
+}
+
+/*
+ * Cancel any scan currently going on for the specified vap.
+ */
+void
+ieee80211_swscan_cancel_scan(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ IEEE80211_LOCK(ic);
+ if ((ic->ic_flags & IEEE80211_F_SCAN) &&
+ ss->ss_vap == vap &&
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: cancel %s scan\n", __func__,
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
+ "active" : "passive");
+
+ /* clear bg scan NOPICK and mark cancel request */
+ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
+ /* wake up the scan task */
+ scan_signal(ss);
+ } else {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
+ __func__,
+ !! (ic->ic_flags & IEEE80211_F_SCAN),
+ (ss->ss_vap == vap ? "match" : "nomatch"),
+ !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
+ }
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Cancel any scan currently going on.
+ */
+void
+ieee80211_swscan_cancel_anyscan(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ IEEE80211_LOCK(ic);
+ if ((ic->ic_flags & IEEE80211_F_SCAN) &&
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: cancel %s scan\n", __func__,
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
+ "active" : "passive");
+
+ /* clear bg scan NOPICK and mark cancel request */
+ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
+ /* wake up the scan task */
+ scan_signal(ss);
+ } else {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
+ __func__,
+ !! (ic->ic_flags & IEEE80211_F_SCAN),
+ (ss->ss_vap == vap ? "match" : "nomatch"),
+ !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
+ }
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Public access to scan_next for drivers that manage
+ * scanning themselves (e.g. for firmware-based devices).
+ */
+void
+ieee80211_swscan_scan_next(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
+ /* wake up the scan task */
+ IEEE80211_LOCK(ic);
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Public access to scan_next for drivers that are not able to scan single
+ * channels (e.g. for firmware-based devices).
+ */
+void
+ieee80211_swscan_scan_done(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss;
+
+ IEEE80211_LOCK_ASSERT(ic);
+
+ ss = ic->ic_scan;
+ scan_signal(ss);
+}
+
+/*
+ * Probe the curent channel, if allowed, while scanning.
+ * If the channel is not marked passive-only then send
+ * a probe request immediately. Otherwise mark state and
+ * listen for beacons on the channel; if we receive something
+ * then we'll transmit a probe request.
+ */
+void
+ieee80211_swscan_probe_curchan(struct ieee80211vap *vap, int force)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+ struct ifnet *ifp = vap->iv_ifp;
+ int i;
+
+ /*
+ * Send directed probe requests followed by any
+ * broadcast probe request.
+ * XXX remove dependence on ic/vap->iv_bss
+ */
+ for (i = 0; i < ss->ss_nssid; i++)
+ ieee80211_send_probereq(vap->iv_bss,
+ vap->iv_myaddr, ifp->if_broadcastaddr,
+ ifp->if_broadcastaddr,
+ ss->ss_ssid[i].ssid, ss->ss_ssid[i].len);
+ if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0)
+ ieee80211_send_probereq(vap->iv_bss,
+ vap->iv_myaddr, ifp->if_broadcastaddr,
+ ifp->if_broadcastaddr,
+ "", 0);
+}
+
+/*
+ * Scan curchan. If this is an active scan and the channel
+ * is not marked passive then send probe request frame(s).
+ * Arrange for the channel change after maxdwell ticks.
+ */
+static void
+scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
+{
+ struct ieee80211vap *vap = ss->ss_vap;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: calling; maxdwell=%lu\n",
+ __func__,
+ maxdwell);
+ IEEE80211_LOCK(vap->iv_ic);
+ if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
+ ieee80211_probe_curchan(vap, 0);
+ callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
+ maxdwell, scan_signal, ss);
+ IEEE80211_UNLOCK(vap->iv_ic);
+}
+
+static void
+scan_signal(void *arg)
+{
+ struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
+
+ IEEE80211_LOCK_ASSERT(ss->ss_ic);
+ cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv);
+}
+
+/*
+ * Handle mindwell requirements completed; initiate a channel
+ * change to the next channel asap.
+ */
+static void
+scan_mindwell(struct ieee80211_scan_state *ss)
+{
+ struct ieee80211com *ic = ss->ss_ic;
+
+ IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
+ IEEE80211_LOCK(ic);
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
+}
+
+static void
+scan_task(void *arg, int pending)
+{
+#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD)
+ struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
+ struct ieee80211vap *vap = ss->ss_vap;
+ struct ieee80211com *ic = ss->ss_ic;
+ struct ieee80211_channel *chan;
+ unsigned long maxdwell, scanend;
+ int scandone = 0;
+
+ IEEE80211_LOCK(ic);
+ if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) {
+ /* Cancelled before we started */
+ goto done;
+ }
+
+ if (ss->ss_next == ss->ss_last) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: no channels to scan\n", __func__);
+ scandone = 1;
+ goto done;
+ }
+
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_state == IEEE80211_S_RUN) {
+ if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
+ /* Enable station power save mode */
+ vap->iv_sta_ps(vap, 1);
+ /*
+ * Use an 1ms delay so the null data frame has a chance
+ * to go out.
+ * XXX Should use M_TXCB mechanism to eliminate this.
+ */
+ cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv,
+ IEEE80211_LOCK_OBJ(ic), hz / 1000);
+ if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
+ goto done;
+ }
+ }
+
+ scanend = ticks + SCAN_PRIVATE(ss)->ss_duration;
+
+ /* XXX scan state can change! Re-validate scan state! */
+
+ IEEE80211_UNLOCK(ic);
+ ic->ic_scan_start(ic); /* notify driver */
+ IEEE80211_LOCK(ic);
+
+ for (;;) {
+
+ scandone = (ss->ss_next >= ss->ss_last) ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: loop start; scandone=%d\n",
+ __func__,
+ scandone);
+
+ if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
+ time_after(ticks + ss->ss_mindwell, scanend))
+ break;
+
+ chan = ss->ss_chans[ss->ss_next++];
+
+ /*
+ * Watch for truncation due to the scan end time.
+ */
+ if (time_after(ticks + ss->ss_maxdwell, scanend))
+ maxdwell = scanend - ticks;
+ else
+ maxdwell = ss->ss_maxdwell;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
+ __func__,
+ ieee80211_chan2ieee(ic, ic->ic_curchan),
+ ieee80211_channel_type_char(ic->ic_curchan),
+ ieee80211_chan2ieee(ic, chan),
+ ieee80211_channel_type_char(chan),
+ (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
+ (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
+ "active" : "passive",
+ ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
+
+ /*
+ * Potentially change channel and phy mode.
+ */
+ ic->ic_curchan = chan;
+ ic->ic_rt = ieee80211_get_ratetable(chan);
+ IEEE80211_UNLOCK(ic);
+ /*
+ * Perform the channel change and scan unlocked so the driver
+ * may sleep. Once set_channel returns the hardware has
+ * completed the channel change.
+ */
+ ic->ic_set_channel(ic);
+ ieee80211_radiotap_chan_change(ic);
+
+ /*
+ * Scan curchan. Drivers for "intelligent hardware"
+ * override ic_scan_curchan to tell the device to do
+ * the work. Otherwise we manage the work outselves;
+ * sending a probe request (as needed), and arming the
+ * timeout to switch channels after maxdwell ticks.
+ *
+ * scan_curchan should only pause for the time required to
+ * prepare/initiate the hardware for the scan (if at all), the
+ * below condvar is used to sleep for the channels dwell time
+ * and allows it to be signalled for abort.
+ */
+ ic->ic_scan_curchan(ss, maxdwell);
+ IEEE80211_LOCK(ic);
+
+ /* XXX scan state can change! Re-validate scan state! */
+
+ SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
+ /* clear mindwell lock and initial channel change flush */
+ SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
+
+ if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
+ continue;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__);
+ /* Wait to be signalled to scan the next channel */
+ cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
+ }
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__);
+
+ if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
+ goto done;
+
+ IEEE80211_UNLOCK(ic);
+ ic->ic_scan_end(ic); /* notify driver */
+ IEEE80211_LOCK(ic);
+ /* XXX scan state can change! Re-validate scan state! */
+
+ /*
+ * Since a cancellation may have occured during one of the
+ * driver calls (whilst unlocked), update scandone.
+ */
+ if (scandone == 0 &&
+ ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
+ /* XXX printf? */
+ if_printf(vap->iv_ifp,
+ "%s: OOPS! scan cancelled during driver call (1)!\n",
+ __func__);
+ scandone = 1;
+ }
+
+ /*
+ * Record scan complete time. Note that we also do
+ * this when canceled so any background scan will
+ * not be restarted for a while.
+ */
+ if (scandone)
+ ic->ic_lastscan = ticks;
+ /* return to the bss channel */
+ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
+ ic->ic_curchan != ic->ic_bsschan) {
+ ieee80211_setupcurchan(ic, ic->ic_bsschan);
+ IEEE80211_UNLOCK(ic);
+ ic->ic_set_channel(ic);
+ ieee80211_radiotap_chan_change(ic);
+ IEEE80211_LOCK(ic);
+ }
+ /* clear internal flags and any indication of a pick */
+ SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
+ ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
+
+ /*
+ * If not canceled and scan completed, do post-processing.
+ * If the callback function returns 0, then it wants to
+ * continue/restart scanning. Unfortunately we needed to
+ * notify the driver to end the scan above to avoid having
+ * rx frames alter the scan candidate list.
+ */
+ if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 &&
+ !ss->ss_ops->scan_end(ss, vap) &&
+ (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
+ time_before(ticks + ss->ss_mindwell, scanend)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: done, restart "
+ "[ticks %u, dwell min %lu scanend %lu]\n",
+ __func__,
+ ticks, ss->ss_mindwell, scanend);
+ ss->ss_next = 0; /* reset to begining */
+ if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
+ vap->iv_stats.is_scan_active++;
+ else
+ vap->iv_stats.is_scan_passive++;
+
+ ss->ss_ops->scan_restart(ss, vap); /* XXX? */
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+ IEEE80211_UNLOCK(ic);
+ return;
+ }
+
+ /* past here, scandone is ``true'' if not in bg mode */
+ if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
+ scandone = 1;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n",
+ __func__, scandone ? "done" : "stopped",
+ ticks, ss->ss_mindwell, scanend);
+
+ /*
+ * Since a cancellation may have occured during one of the
+ * driver calls (whilst unlocked), update scandone.
+ */
+ if (scandone == 0 &&
+ ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
+ /* XXX printf? */
+ if_printf(vap->iv_ifp,
+ "%s: OOPS! scan cancelled during driver call (2)!\n",
+ __func__);
+ scandone = 1;
+ }
+
+ /*
+ * Clear the SCAN bit first in case frames are
+ * pending on the station power save queue. If
+ * we defer this then the dispatch of the frames
+ * may generate a request to cancel scanning.
+ */
+done:
+ ic->ic_flags &= ~IEEE80211_F_SCAN;
+ /*
+ * Drop out of power save mode when a scan has
+ * completed. If this scan was prematurely terminated
+ * because it is a background scan then don't notify
+ * the ap; we'll either return to scanning after we
+ * receive the beacon frame or we'll drop out of power
+ * save mode because the beacon indicates we have frames
+ * waiting for us.
+ */
+ if (scandone) {
+ vap->iv_sta_ps(vap, 0);
+ if (ss->ss_next >= ss->ss_last) {
+ ieee80211_notify_scan_done(vap);
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
+ }
+ }
+ SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
+ ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
+ IEEE80211_UNLOCK(ic);
+#undef ISCAN_REP
+}
+
+/*
+ * Process a beacon or probe response frame.
+ */
+void
+ieee80211_swscan_add_scan(struct ieee80211vap *vap,
+ const struct ieee80211_scanparams *sp,
+ const struct ieee80211_frame *wh,
+ int subtype, int rssi, int noise)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
+
+ /* XXX locking */
+ /*
+ * Frames received during startup are discarded to avoid
+ * using scan state setup on the initial entry to the timer
+ * callback. This can occur because the device may enable
+ * rx prior to our doing the initial channel change in the
+ * timer routine.
+ */
+ if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD)
+ return;
+#ifdef IEEE80211_DEBUG
+ if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN))
+ ieee80211_scan_dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi);
+#endif
+ if (ss->ss_ops != NULL &&
+ ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise)) {
+ /*
+ * If we've reached the min dwell time terminate
+ * the timer so we'll switch to the next channel.
+ */
+ if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
+ time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: chan %3d%c min dwell met (%u > %lu)\n",
+ __func__,
+ ieee80211_chan2ieee(ic, ic->ic_curchan),
+ ieee80211_channel_type_char(ic->ic_curchan),
+ ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL;
+ /*
+ * NB: trigger at next clock tick or wait for the
+ * hardware.
+ */
+ ic->ic_scan_mindwell(ss);
+ }
+ }
+}
+
diff --git a/sys/net80211/ieee80211_scan_sw.h b/sys/net80211/ieee80211_scan_sw.h
new file mode 100644
index 0000000..95fe482
--- /dev/null
+++ b/sys/net80211/ieee80211_scan_sw.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, 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 DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef __NET80211_IEEE80211_SCAN_SW_H__
+#define __NET80211_IEEE80211_SCAN_SW_H__
+
+extern void ieee80211_swscan_attach(struct ieee80211com *ic);
+extern void ieee80211_swscan_detach(struct ieee80211com *ic);
+
+extern void ieee80211_swscan_vattach(struct ieee80211vap *vap);
+extern void ieee80211_swscan_vdetach(struct ieee80211vap *vap);
+
+extern int ieee80211_swscan_start_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags,
+ u_int duration, u_int mindwell, u_int maxdwell,
+ u_int nssid, const struct ieee80211_scan_ssid ssids[]);
+extern void ieee80211_swscan_set_scan_duration(struct ieee80211vap *vap,
+ u_int duration);
+extern void ieee80211_swscan_run_scan_task(struct ieee80211vap *vap);
+extern int ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags,
+ u_int duration, u_int mindwell, u_int maxdwell,
+ u_int nssid, const struct ieee80211_scan_ssid ssids[]);
+extern int ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan,
+ struct ieee80211vap *vap, int flags);
+extern void ieee80211_swscan_cancel_scan(struct ieee80211vap *vap);
+extern void ieee80211_swscan_cancel_anyscan(struct ieee80211vap *vap);
+extern void ieee80211_swscan_scan_next(struct ieee80211vap *vap);
+extern void ieee80211_swscan_scan_done(struct ieee80211vap *vap);
+extern void ieee80211_swscan_probe_curchan(struct ieee80211vap *vap,
+ int force);
+extern void ieee80211_swscan_add_scan(struct ieee80211vap *vap,
+ const struct ieee80211_scanparams *sp,
+ const struct ieee80211_frame *wh,
+ int subtype, int rssi, int noise);
+
+#endif /* __NET80211_IEEE80211_SCAN_SW_H__ */
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 8685e4b..0a7298d 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -234,6 +234,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
switch (ostate) {
case IEEE80211_S_SLEEP:
/* XXX wakeup */
+ /* XXX driver hook to wakeup the hardware? */
case IEEE80211_S_RUN:
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_DISASSOC,
@@ -299,12 +300,18 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
if (vap->iv_roaming == IEEE80211_ROAMING_AUTO)
ieee80211_check_scan_current(vap);
break;
+ case IEEE80211_S_SLEEP: /* beacon miss */
+ /*
+ * XXX if in sleep we need to wakeup the hardware.
+ */
+ /* FALLTHROUGH */
case IEEE80211_S_RUN: /* beacon miss */
/*
* Beacon miss. Notify user space and if not
* under control of a user application (roaming
* manual) kick off a scan to re-connect.
*/
+
ieee80211_sta_leave(ni);
if (vap->iv_roaming == IEEE80211_ROAMING_AUTO)
ieee80211_check_scan_current(vap);
@@ -403,6 +410,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
break;
case IEEE80211_S_SLEEP:
+ /* Wake up from sleep */
vap->iv_sta_ps(vap, 0);
break;
default:
@@ -430,9 +438,11 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_node_authorize(ni);
/*
* Fake association when joining an existing bss.
+ *
+ * Don't do this if we're doing SLEEP->RUN.
*/
- if (ic->ic_newassoc != NULL)
- ic->ic_newassoc(vap->iv_bss, ostate != IEEE80211_S_RUN);
+ if (ic->ic_newassoc != NULL && ostate != IEEE80211_S_SLEEP)
+ ic->ic_newassoc(vap->iv_bss, (ostate != IEEE80211_S_RUN));
break;
case IEEE80211_S_CSA:
if (ostate != IEEE80211_S_RUN)
@@ -1312,6 +1322,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
vap->iv_stats.is_beacon_bad++;
return;
}
+
/*
* Count frame now that we know it's to be processed.
*/
@@ -1381,25 +1392,66 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
}
if (scan.quiet)
ic->ic_set_quiet(ni, scan.quiet);
+
if (scan.tim != NULL) {
struct ieee80211_tim_ie *tim =
(struct ieee80211_tim_ie *) scan.tim;
-#if 0
+ /*
+ * XXX Check/debug this code; see if it's about
+ * the right time to force the VAP awake if we
+ * receive a frame destined for us?
+ */
int aid = IEEE80211_AID(ni->ni_associd);
int ix = aid / NBBY;
int min = tim->tim_bitctl &~ 1;
int max = tim->tim_len + min - 4;
- if ((tim->tim_bitctl&1) ||
- (min <= ix && ix <= max &&
- isset(tim->tim_bitmap - min, aid))) {
- /*
- * XXX Do not let bg scan kick off
- * we are expecting data.
+ int tim_ucast = 0, tim_mcast = 0;
+
+ /*
+ * Only do this for unicast traffic in the TIM
+ * The multicast traffic notification for
+ * the scan notification stuff should occur
+ * differently.
+ */
+ if (min <= ix && ix <= max &&
+ isset(tim->tim_bitmap - min, aid)) {
+ tim_ucast = 1;
+ }
+
+ /*
+ * Do a separate notification
+ * for the multicast bit being set.
+ */
+ if (tim->tim_bitctl & 1) {
+ tim_mcast = 1;
+ }
+
+ /*
+ * If the TIM indicates there's traffic for
+ * us then get us out of STA mode powersave.
+ */
+ if (tim_ucast == 1) {
+
+ /*
+ * Wake us out of SLEEP state if we're
+ * in it; and if we're doing bgscan
+ * then wake us out of STA powersave.
+ */
+ ieee80211_sta_tim_notify(vap, 1);
+
+ /*
+ * This is preventing us from
+ * continuing a bgscan; because it
+ * tricks the contbgscan()
+ * routine to think there's always
+ * traffic for us.
+ *
+ * I think we need both an RX and
+ * TX ic_lastdata field.
*/
ic->ic_lastdata = ticks;
- vap->iv_sta_ps(vap, 0);
}
-#endif
+
ni->ni_dtim_count = tim->tim_count;
ni->ni_dtim_period = tim->tim_period;
}
@@ -1446,6 +1498,14 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
}
/*
+ * Put the station to sleep if we haven't seen
+ * traffic in a while.
+ */
+ IEEE80211_LOCK(ic);
+ ieee80211_sta_ps_timer_check(vap);
+ IEEE80211_UNLOCK(ic);
+
+ /*
* If we've had a channel width change (eg HT20<->HT40)
* then schedule a delayed driver notification.
*/
diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c
index 21f3b99..60e1283 100644
--- a/sys/net80211/ieee80211_superg.c
+++ b/sys/net80211/ieee80211_superg.c
@@ -38,11 +38,12 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
-#include <net/bpf.h>
-#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_llc.h>
#include <net/if_media.h>
+#include <net/bpf.h>
+#include <net/ethernet.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_input.h>
@@ -86,7 +87,7 @@ __FBSDID("$FreeBSD$");
memcpy(dst, src, sizeof(struct ether_header))
static int ieee80211_ffppsmin = 2; /* pps threshold for ff aggregation */
-SYSCTL_INT(_net_wlan, OID_AUTO, ffppsmin, CTLTYPE_INT | CTLFLAG_RW,
+SYSCTL_INT(_net_wlan, OID_AUTO, ffppsmin, CTLFLAG_RW,
&ieee80211_ffppsmin, 0, "min packet rate before fast-frame staging");
static int ieee80211_ffagemax = -1; /* max time frames held on stage q */
SYSCTL_PROC(_net_wlan, OID_AUTO, ffagemax, CTLTYPE_INT | CTLFLAG_RW,
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 174fabc..4710697 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -629,6 +629,7 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */
#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/
#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */
+#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */
/* 0x7c0000 available */
#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */
#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */
@@ -710,6 +711,7 @@ int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
uint32_t ieee80211_mac_hash(const struct ieee80211com *,
const uint8_t addr[IEEE80211_ADDR_LEN]);
+char ieee80211_channel_type_char(const struct ieee80211_channel *c);
void ieee80211_radiotap_attach(struct ieee80211com *,
struct ieee80211_radiotap_header *th, int tlen,
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index 8b9b3b3..fdeaf25 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/ethernet.h>
OpenPOWER on IntegriCloud